11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Trivial changes by Alan Cox to remove EHASHCOLLISION for compatibility 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Trivial Changes: 71da177e4SLinus Torvalds * Rights granted to Hans Reiser to redistribute under other terms providing 81da177e4SLinus Torvalds * he accepts all liability including but not limited to patent, fitness 91da177e4SLinus Torvalds * for purpose, and direct or indirect claims arising from failure to perform. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * NO WARRANTY 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds #include <linux/time.h> 151da177e4SLinus Torvalds #include <linux/bitops.h> 165a0e3ad6STejun Heo #include <linux/slab.h> 17f466c6fdSAl Viro #include "reiserfs.h" 18a3063ab8SAl Viro #include "acl.h" 19c45ac888SAl Viro #include "xattr.h" 201da177e4SLinus Torvalds #include <linux/quotaops.h> 211da177e4SLinus Torvalds 22bfe86848SMiklos Szeredi #define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { inc_nlink(i); if (i->i_nlink >= REISERFS_LINK_MAX) set_nlink(i, 1); } 239a53c3a7SDave Hansen #define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) drop_nlink(i); 241da177e4SLinus Torvalds 25098297b2SJeff Mahoney /* 26098297b2SJeff Mahoney * directory item contains array of entry headers. This performs 27098297b2SJeff Mahoney * binary search through that array 28098297b2SJeff Mahoney */ 291da177e4SLinus Torvalds static int bin_search_in_dir_item(struct reiserfs_dir_entry *de, loff_t off) 301da177e4SLinus Torvalds { 311da177e4SLinus Torvalds struct item_head *ih = de->de_ih; 321da177e4SLinus Torvalds struct reiserfs_de_head *deh = de->de_deh; 331da177e4SLinus Torvalds int rbound, lbound, j; 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds lbound = 0; 364cf5f7adSJeff Mahoney rbound = ih_entry_count(ih) - 1; 371da177e4SLinus Torvalds 38bd4c625cSLinus Torvalds for (j = (rbound + lbound) / 2; lbound <= rbound; 39bd4c625cSLinus Torvalds j = (rbound + lbound) / 2) { 401da177e4SLinus Torvalds if (off < deh_offset(deh + j)) { 411da177e4SLinus Torvalds rbound = j - 1; 421da177e4SLinus Torvalds continue; 431da177e4SLinus Torvalds } 441da177e4SLinus Torvalds if (off > deh_offset(deh + j)) { 451da177e4SLinus Torvalds lbound = j + 1; 461da177e4SLinus Torvalds continue; 471da177e4SLinus Torvalds } 48098297b2SJeff Mahoney /* this is not name found, but matched third key component */ 491da177e4SLinus Torvalds de->de_entry_num = j; 501da177e4SLinus Torvalds return NAME_FOUND; 511da177e4SLinus Torvalds } 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds de->de_entry_num = lbound; 541da177e4SLinus Torvalds return NAME_NOT_FOUND; 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds 57098297b2SJeff Mahoney /* 58098297b2SJeff Mahoney * comment? maybe something like set de to point to what the path points to? 59098297b2SJeff Mahoney */ 60bd4c625cSLinus Torvalds static inline void set_de_item_location(struct reiserfs_dir_entry *de, 61fec6d055SJosef "Jeff" Sipek struct treepath *path) 621da177e4SLinus Torvalds { 631da177e4SLinus Torvalds de->de_bh = get_last_bh(path); 644cf5f7adSJeff Mahoney de->de_ih = tp_item_head(path); 651da177e4SLinus Torvalds de->de_deh = B_I_DEH(de->de_bh, de->de_ih); 661da177e4SLinus Torvalds de->de_item_num = PATH_LAST_POSITION(path); 671da177e4SLinus Torvalds } 681da177e4SLinus Torvalds 69098297b2SJeff Mahoney /* 70098297b2SJeff Mahoney * de_bh, de_ih, de_deh (points to first element of array), de_item_num is set 71098297b2SJeff Mahoney */ 721da177e4SLinus Torvalds inline void set_de_name_and_namelen(struct reiserfs_dir_entry *de) 731da177e4SLinus Torvalds { 741da177e4SLinus Torvalds struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num; 751da177e4SLinus Torvalds 7614a61442SEric Sesterhenn BUG_ON(de->de_entry_num >= ih_entry_count(de->de_ih)); 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds de->de_entrylen = entry_length(de->de_bh, de->de_ih, de->de_entry_num); 791da177e4SLinus Torvalds de->de_namelen = de->de_entrylen - (de_with_sd(deh) ? SD_SIZE : 0); 804cf5f7adSJeff Mahoney de->de_name = ih_item_body(de->de_bh, de->de_ih) + deh_location(deh); 811da177e4SLinus Torvalds if (de->de_name[de->de_namelen - 1] == 0) 821da177e4SLinus Torvalds de->de_namelen = strlen(de->de_name); 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds 85098297b2SJeff Mahoney /* what entry points to */ 861da177e4SLinus Torvalds static inline void set_de_object_key(struct reiserfs_dir_entry *de) 871da177e4SLinus Torvalds { 8814a61442SEric Sesterhenn BUG_ON(de->de_entry_num >= ih_entry_count(de->de_ih)); 89a228bf8fSJeff Mahoney de->de_dir_id = deh_dir_id(&de->de_deh[de->de_entry_num]); 90a228bf8fSJeff Mahoney de->de_objectid = deh_objectid(&de->de_deh[de->de_entry_num]); 911da177e4SLinus Torvalds } 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds static inline void store_de_entry_key(struct reiserfs_dir_entry *de) 941da177e4SLinus Torvalds { 951da177e4SLinus Torvalds struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num; 961da177e4SLinus Torvalds 9714a61442SEric Sesterhenn BUG_ON(de->de_entry_num >= ih_entry_count(de->de_ih)); 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds /* store key of the found entry */ 1001da177e4SLinus Torvalds de->de_entry_key.version = KEY_FORMAT_3_5; 101bd4c625cSLinus Torvalds de->de_entry_key.on_disk_key.k_dir_id = 102bd4c625cSLinus Torvalds le32_to_cpu(de->de_ih->ih_key.k_dir_id); 103bd4c625cSLinus Torvalds de->de_entry_key.on_disk_key.k_objectid = 104bd4c625cSLinus Torvalds le32_to_cpu(de->de_ih->ih_key.k_objectid); 105a228bf8fSJeff Mahoney set_cpu_key_k_offset(&de->de_entry_key, deh_offset(deh)); 106a228bf8fSJeff Mahoney set_cpu_key_k_type(&de->de_entry_key, TYPE_DIRENTRY); 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 109098297b2SJeff Mahoney /* 110098297b2SJeff Mahoney * We assign a key to each directory item, and place multiple entries in a 111098297b2SJeff Mahoney * single directory item. A directory item has a key equal to the key of 112098297b2SJeff Mahoney * the first directory entry in it. 1131da177e4SLinus Torvalds 114098297b2SJeff Mahoney * This function first calls search_by_key, then, if item whose first entry 115098297b2SJeff Mahoney * matches is not found it looks for the entry inside directory item found 116098297b2SJeff Mahoney * by search_by_key. Fills the path to the entry, and to the entry position 117098297b2SJeff Mahoney * in the item 1181da177e4SLinus Torvalds */ 1191da177e4SLinus Torvalds /* The function is NOT SCHEDULE-SAFE! */ 1201da177e4SLinus Torvalds int search_by_entry_key(struct super_block *sb, const struct cpu_key *key, 121fec6d055SJosef "Jeff" Sipek struct treepath *path, struct reiserfs_dir_entry *de) 1221da177e4SLinus Torvalds { 1231da177e4SLinus Torvalds int retval; 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds retval = search_item(sb, key, path); 1261da177e4SLinus Torvalds switch (retval) { 1271da177e4SLinus Torvalds case ITEM_NOT_FOUND: 1281da177e4SLinus Torvalds if (!PATH_LAST_POSITION(path)) { 1290030b645SJeff Mahoney reiserfs_error(sb, "vs-7000", "search_by_key " 13045b03d5eSJeff Mahoney "returned item position == 0"); 1311da177e4SLinus Torvalds pathrelse(path); 1321da177e4SLinus Torvalds return IO_ERROR; 1331da177e4SLinus Torvalds } 1341da177e4SLinus Torvalds PATH_LAST_POSITION(path)--; 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds case ITEM_FOUND: 1371da177e4SLinus Torvalds break; 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds case IO_ERROR: 1401da177e4SLinus Torvalds return retval; 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds default: 1431da177e4SLinus Torvalds pathrelse(path); 1440030b645SJeff Mahoney reiserfs_error(sb, "vs-7002", "no path to here"); 1451da177e4SLinus Torvalds return IO_ERROR; 1461da177e4SLinus Torvalds } 1471da177e4SLinus Torvalds 1481da177e4SLinus Torvalds set_de_item_location(de, path); 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds #ifdef CONFIG_REISERFS_CHECK 1511da177e4SLinus Torvalds if (!is_direntry_le_ih(de->de_ih) || 152a228bf8fSJeff Mahoney COMP_SHORT_KEYS(&de->de_ih->ih_key, key)) { 1531da177e4SLinus Torvalds print_block(de->de_bh, 0, -1, -1); 154c3a9c210SJeff Mahoney reiserfs_panic(sb, "vs-7005", "found item %h is not directory " 155c3a9c210SJeff Mahoney "item or does not belong to the same directory " 156c3a9c210SJeff Mahoney "as key %K", de->de_ih, key); 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds #endif /* CONFIG_REISERFS_CHECK */ 1591da177e4SLinus Torvalds 160098297b2SJeff Mahoney /* 161098297b2SJeff Mahoney * binary search in directory item by third component of the 162098297b2SJeff Mahoney * key. sets de->de_entry_num of de 163098297b2SJeff Mahoney */ 1641da177e4SLinus Torvalds retval = bin_search_in_dir_item(de, cpu_key_k_offset(key)); 1651da177e4SLinus Torvalds path->pos_in_item = de->de_entry_num; 1661da177e4SLinus Torvalds if (retval != NAME_NOT_FOUND) { 167098297b2SJeff Mahoney /* 168098297b2SJeff Mahoney * ugly, but rename needs de_bh, de_deh, de_name, 169098297b2SJeff Mahoney * de_namelen, de_objectid set 170098297b2SJeff Mahoney */ 1711da177e4SLinus Torvalds set_de_name_and_namelen(de); 1721da177e4SLinus Torvalds set_de_object_key(de); 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds return retval; 1751da177e4SLinus Torvalds } 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds /* Keyed 32-bit hash function using TEA in a Davis-Meyer function */ 1781da177e4SLinus Torvalds 179098297b2SJeff Mahoney /* 180098297b2SJeff Mahoney * The third component is hashed, and you can choose from more than 181098297b2SJeff Mahoney * one hash function. Per directory hashes are not yet implemented 182098297b2SJeff Mahoney * but are thought about. This function should be moved to hashes.c 183098297b2SJeff Mahoney * Jedi, please do so. -Hans 184098297b2SJeff Mahoney */ 1851da177e4SLinus Torvalds static __u32 get_third_component(struct super_block *s, 1861da177e4SLinus Torvalds const char *name, int len) 1871da177e4SLinus Torvalds { 1881da177e4SLinus Torvalds __u32 res; 1891da177e4SLinus Torvalds 1901da177e4SLinus Torvalds if (!len || (len == 1 && name[0] == '.')) 1911da177e4SLinus Torvalds return DOT_OFFSET; 1921da177e4SLinus Torvalds if (len == 2 && name[0] == '.' && name[1] == '.') 1931da177e4SLinus Torvalds return DOT_DOT_OFFSET; 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds res = REISERFS_SB(s)->s_hash_function(name, len); 1961da177e4SLinus Torvalds 197098297b2SJeff Mahoney /* take bits from 7-th to 30-th including both bounds */ 1981da177e4SLinus Torvalds res = GET_HASH_VALUE(res); 1991da177e4SLinus Torvalds if (res == 0) 200098297b2SJeff Mahoney /* 201098297b2SJeff Mahoney * needed to have no names before "." and ".." those have hash 202098297b2SJeff Mahoney * value == 0 and generation conters 1 and 2 accordingly 203098297b2SJeff Mahoney */ 2041da177e4SLinus Torvalds res = 128; 2051da177e4SLinus Torvalds return res + MAX_GENERATION_NUMBER; 2061da177e4SLinus Torvalds } 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds static int reiserfs_match(struct reiserfs_dir_entry *de, 2091da177e4SLinus Torvalds const char *name, int namelen) 2101da177e4SLinus Torvalds { 2111da177e4SLinus Torvalds int retval = NAME_NOT_FOUND; 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds if ((namelen == de->de_namelen) && 2141da177e4SLinus Torvalds !memcmp(de->de_name, name, de->de_namelen)) 215bd4c625cSLinus Torvalds retval = 216bd4c625cSLinus Torvalds (de_visible(de->de_deh + de->de_entry_num) ? NAME_FOUND : 217bd4c625cSLinus Torvalds NAME_FOUND_INVISIBLE); 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds return retval; 2201da177e4SLinus Torvalds } 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds /* de's de_bh, de_ih, de_deh, de_item_num, de_entry_num are set already */ 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds /* used when hash collisions exist */ 2251da177e4SLinus Torvalds 226bd4c625cSLinus Torvalds static int linear_search_in_dir_item(struct cpu_key *key, 227bd4c625cSLinus Torvalds struct reiserfs_dir_entry *de, 2281da177e4SLinus Torvalds const char *name, int namelen) 2291da177e4SLinus Torvalds { 2301da177e4SLinus Torvalds struct reiserfs_de_head *deh = de->de_deh; 2311da177e4SLinus Torvalds int retval; 2321da177e4SLinus Torvalds int i; 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds i = de->de_entry_num; 2351da177e4SLinus Torvalds 2364cf5f7adSJeff Mahoney if (i == ih_entry_count(de->de_ih) || 237bd4c625cSLinus Torvalds GET_HASH_VALUE(deh_offset(deh + i)) != 238bd4c625cSLinus Torvalds GET_HASH_VALUE(cpu_key_k_offset(key))) { 2391da177e4SLinus Torvalds i--; 2401da177e4SLinus Torvalds } 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds RFALSE(de->de_deh != B_I_DEH(de->de_bh, de->de_ih), 2431da177e4SLinus Torvalds "vs-7010: array of entry headers not found"); 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds deh += i; 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds for (; i >= 0; i--, deh--) { 248098297b2SJeff Mahoney /* hash value does not match, no need to check whole name */ 2491da177e4SLinus Torvalds if (GET_HASH_VALUE(deh_offset(deh)) != 2501da177e4SLinus Torvalds GET_HASH_VALUE(cpu_key_k_offset(key))) { 2511da177e4SLinus Torvalds return NAME_NOT_FOUND; 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds 254098297b2SJeff Mahoney /* mark that this generation number is used */ 2551da177e4SLinus Torvalds if (de->de_gen_number_bit_string) 256bd4c625cSLinus Torvalds set_bit(GET_GENERATION_NUMBER(deh_offset(deh)), 2573af1efe8SJeff Mahoney de->de_gen_number_bit_string); 2581da177e4SLinus Torvalds 259098297b2SJeff Mahoney /* calculate pointer to name and namelen */ 2601da177e4SLinus Torvalds de->de_entry_num = i; 2611da177e4SLinus Torvalds set_de_name_and_namelen(de); 2621da177e4SLinus Torvalds 263098297b2SJeff Mahoney /* 264098297b2SJeff Mahoney * de's de_name, de_namelen, de_recordlen are set. 265098297b2SJeff Mahoney * Fill the rest. 266098297b2SJeff Mahoney */ 267bd4c625cSLinus Torvalds if ((retval = 268bd4c625cSLinus Torvalds reiserfs_match(de, name, namelen)) != NAME_NOT_FOUND) { 2691da177e4SLinus Torvalds 270098297b2SJeff Mahoney /* key of pointed object */ 2711da177e4SLinus Torvalds set_de_object_key(de); 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds store_de_entry_key(de); 2741da177e4SLinus Torvalds 275098297b2SJeff Mahoney /* retval can be NAME_FOUND or NAME_FOUND_INVISIBLE */ 2761da177e4SLinus Torvalds return retval; 2771da177e4SLinus Torvalds } 2781da177e4SLinus Torvalds } 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds if (GET_GENERATION_NUMBER(le_ih_k_offset(de->de_ih)) == 0) 281098297b2SJeff Mahoney /* 282098297b2SJeff Mahoney * we have reached left most entry in the node. In common we 283098297b2SJeff Mahoney * have to go to the left neighbor, but if generation counter 284098297b2SJeff Mahoney * is 0 already, we know for sure, that there is no name with 285098297b2SJeff Mahoney * the same hash value 286098297b2SJeff Mahoney */ 287098297b2SJeff Mahoney /* 288098297b2SJeff Mahoney * FIXME: this work correctly only because hash value can not 289098297b2SJeff Mahoney * be 0. Btw, in case of Yura's hash it is probably possible, 290098297b2SJeff Mahoney * so, this is a bug 291098297b2SJeff Mahoney */ 2921da177e4SLinus Torvalds return NAME_NOT_FOUND; 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds RFALSE(de->de_item_num, 2951da177e4SLinus Torvalds "vs-7015: two diritems of the same directory in one node?"); 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvalds return GOTO_PREVIOUS_ITEM; 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds 300098297b2SJeff Mahoney /* 301098297b2SJeff Mahoney * may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND 302098297b2SJeff Mahoney * FIXME: should add something like IOERROR 303098297b2SJeff Mahoney */ 3041da177e4SLinus Torvalds static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen, 305fec6d055SJosef "Jeff" Sipek struct treepath *path_to_entry, 306bd4c625cSLinus Torvalds struct reiserfs_dir_entry *de) 3071da177e4SLinus Torvalds { 3081da177e4SLinus Torvalds struct cpu_key key_to_search; 3091da177e4SLinus Torvalds int retval; 3101da177e4SLinus Torvalds 3111da177e4SLinus Torvalds if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize)) 3121da177e4SLinus Torvalds return NAME_NOT_FOUND; 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds /* we will search for this key in the tree */ 3151da177e4SLinus Torvalds make_cpu_key(&key_to_search, dir, 316bd4c625cSLinus Torvalds get_third_component(dir->i_sb, name, namelen), 317bd4c625cSLinus Torvalds TYPE_DIRENTRY, 3); 3181da177e4SLinus Torvalds 3191da177e4SLinus Torvalds while (1) { 320bd4c625cSLinus Torvalds retval = 321bd4c625cSLinus Torvalds search_by_entry_key(dir->i_sb, &key_to_search, 322bd4c625cSLinus Torvalds path_to_entry, de); 3231da177e4SLinus Torvalds if (retval == IO_ERROR) { 3240030b645SJeff Mahoney reiserfs_error(dir->i_sb, "zam-7001", "io error"); 3251da177e4SLinus Torvalds return IO_ERROR; 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds /* compare names for all entries having given hash value */ 329bd4c625cSLinus Torvalds retval = 330bd4c625cSLinus Torvalds linear_search_in_dir_item(&key_to_search, de, name, 331bd4c625cSLinus Torvalds namelen); 332098297b2SJeff Mahoney /* 333098297b2SJeff Mahoney * there is no need to scan directory anymore. 334098297b2SJeff Mahoney * Given entry found or does not exist 335098297b2SJeff Mahoney */ 3361da177e4SLinus Torvalds if (retval != GOTO_PREVIOUS_ITEM) { 3371da177e4SLinus Torvalds path_to_entry->pos_in_item = de->de_entry_num; 3381da177e4SLinus Torvalds return retval; 3391da177e4SLinus Torvalds } 3401da177e4SLinus Torvalds 341098297b2SJeff Mahoney /* 342098297b2SJeff Mahoney * there is left neighboring item of this directory 343098297b2SJeff Mahoney * and given entry can be there 344098297b2SJeff Mahoney */ 345bd4c625cSLinus Torvalds set_cpu_key_k_offset(&key_to_search, 346bd4c625cSLinus Torvalds le_ih_k_offset(de->de_ih) - 1); 3471da177e4SLinus Torvalds pathrelse(path_to_entry); 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds } /* while (1) */ 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds 352bd4c625cSLinus Torvalds static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, 35300cd8dd3SAl Viro unsigned int flags) 3541da177e4SLinus Torvalds { 3551da177e4SLinus Torvalds int retval; 3561da177e4SLinus Torvalds struct inode *inode = NULL; 3571da177e4SLinus Torvalds struct reiserfs_dir_entry de; 3581da177e4SLinus Torvalds INITIALIZE_PATH(path_to_entry); 3591da177e4SLinus Torvalds 3601da177e4SLinus Torvalds if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len) 3611da177e4SLinus Torvalds return ERR_PTR(-ENAMETOOLONG); 3621da177e4SLinus Torvalds 363278f6679SJeff Mahoney reiserfs_write_lock(dir->i_sb); 364b1c839bbSFrederic Weisbecker 3651da177e4SLinus Torvalds de.de_gen_number_bit_string = NULL; 366bd4c625cSLinus Torvalds retval = 367bd4c625cSLinus Torvalds reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, 368bd4c625cSLinus Torvalds &path_to_entry, &de); 3691da177e4SLinus Torvalds pathrelse(&path_to_entry); 3701da177e4SLinus Torvalds if (retval == NAME_FOUND) { 371677c9b2eSJeff Mahoney inode = reiserfs_iget(dir->i_sb, 372a228bf8fSJeff Mahoney (struct cpu_key *)&de.de_dir_id); 3731da177e4SLinus Torvalds if (!inode || IS_ERR(inode)) { 374278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb); 3751da177e4SLinus Torvalds return ERR_PTR(-EACCES); 3761da177e4SLinus Torvalds } 3771da177e4SLinus Torvalds 378098297b2SJeff Mahoney /* 379098297b2SJeff Mahoney * Propagate the private flag so we know we're 380098297b2SJeff Mahoney * in the priv tree 381098297b2SJeff Mahoney */ 3826dfede69SJeff Mahoney if (IS_PRIVATE(dir)) 3836dfede69SJeff Mahoney inode->i_flags |= S_PRIVATE; 3841da177e4SLinus Torvalds } 385278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb); 3861da177e4SLinus Torvalds if (retval == IO_ERROR) { 3871da177e4SLinus Torvalds return ERR_PTR(-EIO); 3881da177e4SLinus Torvalds } 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds return d_splice_alias(inode, dentry); 3911da177e4SLinus Torvalds } 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds /* 394098297b2SJeff Mahoney * looks up the dentry of the parent directory for child. 395098297b2SJeff Mahoney * taken from ext2_get_parent 3961da177e4SLinus Torvalds */ 3971da177e4SLinus Torvalds struct dentry *reiserfs_get_parent(struct dentry *child) 3981da177e4SLinus Torvalds { 3991da177e4SLinus Torvalds int retval; 4001da177e4SLinus Torvalds struct inode *inode = NULL; 4011da177e4SLinus Torvalds struct reiserfs_dir_entry de; 4021da177e4SLinus Torvalds INITIALIZE_PATH(path_to_entry); 4032b0143b5SDavid Howells struct inode *dir = d_inode(child); 4041da177e4SLinus Torvalds 4051da177e4SLinus Torvalds if (dir->i_nlink == 0) { 4061da177e4SLinus Torvalds return ERR_PTR(-ENOENT); 4071da177e4SLinus Torvalds } 4081da177e4SLinus Torvalds de.de_gen_number_bit_string = NULL; 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb); 4111da177e4SLinus Torvalds retval = reiserfs_find_entry(dir, "..", 2, &path_to_entry, &de); 4121da177e4SLinus Torvalds pathrelse(&path_to_entry); 4131da177e4SLinus Torvalds if (retval != NAME_FOUND) { 4141da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 4151da177e4SLinus Torvalds return ERR_PTR(-ENOENT); 4161da177e4SLinus Torvalds } 417a228bf8fSJeff Mahoney inode = reiserfs_iget(dir->i_sb, (struct cpu_key *)&de.de_dir_id); 4181da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 4191da177e4SLinus Torvalds 42044003728SChristoph Hellwig return d_obtain_alias(inode); 4211da177e4SLinus Torvalds } 4221da177e4SLinus Torvalds 4231da177e4SLinus Torvalds /* add entry to the directory (entry can be hidden). 4241da177e4SLinus Torvalds 4251da177e4SLinus Torvalds insert definition of when hidden directories are used here -Hans 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds Does not mark dir inode dirty, do it after successesfull call to it */ 4281da177e4SLinus Torvalds 429bd4c625cSLinus Torvalds static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, 430bd4c625cSLinus Torvalds struct inode *dir, const char *name, int namelen, 431bd4c625cSLinus Torvalds struct inode *inode, int visible) 4321da177e4SLinus Torvalds { 4331da177e4SLinus Torvalds struct cpu_key entry_key; 4341da177e4SLinus Torvalds struct reiserfs_de_head *deh; 4351da177e4SLinus Torvalds INITIALIZE_PATH(path); 4361da177e4SLinus Torvalds struct reiserfs_dir_entry de; 4373af1efe8SJeff Mahoney DECLARE_BITMAP(bit_string, MAX_GENERATION_NUMBER + 1); 4381da177e4SLinus Torvalds int gen_number; 439098297b2SJeff Mahoney 440098297b2SJeff Mahoney /* 441098297b2SJeff Mahoney * 48 bytes now and we avoid kmalloc if we 442098297b2SJeff Mahoney * create file with short name 443098297b2SJeff Mahoney */ 444098297b2SJeff Mahoney char small_buf[32 + DEH_SIZE]; 445098297b2SJeff Mahoney 4461da177e4SLinus Torvalds char *buffer; 4471da177e4SLinus Torvalds int buflen, paste_size; 4481da177e4SLinus Torvalds int retval; 4491da177e4SLinus Torvalds 4501da177e4SLinus Torvalds BUG_ON(!th->t_trans_id); 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds /* cannot allow items to be added into a busy deleted directory */ 4531da177e4SLinus Torvalds if (!namelen) 4541da177e4SLinus Torvalds return -EINVAL; 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize)) 4571da177e4SLinus Torvalds return -ENAMETOOLONG; 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds /* each entry has unique key. compose it */ 4601da177e4SLinus Torvalds make_cpu_key(&entry_key, dir, 461bd4c625cSLinus Torvalds get_third_component(dir->i_sb, name, namelen), 462bd4c625cSLinus Torvalds TYPE_DIRENTRY, 3); 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds /* get memory for composing the entry */ 4651da177e4SLinus Torvalds buflen = DEH_SIZE + ROUND_UP(namelen); 4661da177e4SLinus Torvalds if (buflen > sizeof(small_buf)) { 467d739b42bSPekka Enberg buffer = kmalloc(buflen, GFP_NOFS); 4689dce07f1SAl Viro if (!buffer) 4691da177e4SLinus Torvalds return -ENOMEM; 4701da177e4SLinus Torvalds } else 4711da177e4SLinus Torvalds buffer = small_buf; 4721da177e4SLinus Torvalds 473bd4c625cSLinus Torvalds paste_size = 474bd4c625cSLinus Torvalds (get_inode_sd_version(dir) == 475bd4c625cSLinus Torvalds STAT_DATA_V1) ? (DEH_SIZE + namelen) : buflen; 4761da177e4SLinus Torvalds 477098297b2SJeff Mahoney /* 478098297b2SJeff Mahoney * fill buffer : directory entry head, name[, dir objectid | , 479098297b2SJeff Mahoney * stat data | ,stat data, dir objectid ] 480098297b2SJeff Mahoney */ 4811da177e4SLinus Torvalds deh = (struct reiserfs_de_head *)buffer; 4821da177e4SLinus Torvalds deh->deh_location = 0; /* JDM Endian safe if 0 */ 4831da177e4SLinus Torvalds put_deh_offset(deh, cpu_key_k_offset(&entry_key)); 4841da177e4SLinus Torvalds deh->deh_state = 0; /* JDM Endian safe if 0 */ 4851da177e4SLinus Torvalds /* put key (ino analog) to de */ 486098297b2SJeff Mahoney 487098297b2SJeff Mahoney /* safe: k_dir_id is le */ 488098297b2SJeff Mahoney deh->deh_dir_id = INODE_PKEY(inode)->k_dir_id; 489098297b2SJeff Mahoney /* safe: k_objectid is le */ 490098297b2SJeff Mahoney deh->deh_objectid = INODE_PKEY(inode)->k_objectid; 4911da177e4SLinus Torvalds 4921da177e4SLinus Torvalds /* copy name */ 4931da177e4SLinus Torvalds memcpy((char *)(deh + 1), name, namelen); 4941da177e4SLinus Torvalds /* padd by 0s to the 4 byte boundary */ 4951da177e4SLinus Torvalds padd_item((char *)(deh + 1), ROUND_UP(namelen), namelen); 4961da177e4SLinus Torvalds 497098297b2SJeff Mahoney /* 498098297b2SJeff Mahoney * entry is ready to be pasted into tree, set 'visibility' 499098297b2SJeff Mahoney * and 'stat data in entry' attributes 500098297b2SJeff Mahoney */ 5011da177e4SLinus Torvalds mark_de_without_sd(deh); 5021da177e4SLinus Torvalds visible ? mark_de_visible(deh) : mark_de_hidden(deh); 5031da177e4SLinus Torvalds 5041da177e4SLinus Torvalds /* find the proper place for the new entry */ 5051da177e4SLinus Torvalds memset(bit_string, 0, sizeof(bit_string)); 5063af1efe8SJeff Mahoney de.de_gen_number_bit_string = bit_string; 5071da177e4SLinus Torvalds retval = reiserfs_find_entry(dir, name, namelen, &path, &de); 5081da177e4SLinus Torvalds if (retval != NAME_NOT_FOUND) { 5091da177e4SLinus Torvalds if (buffer != small_buf) 510d739b42bSPekka Enberg kfree(buffer); 5111da177e4SLinus Torvalds pathrelse(&path); 5121da177e4SLinus Torvalds 5131da177e4SLinus Torvalds if (retval == IO_ERROR) { 5141da177e4SLinus Torvalds return -EIO; 5151da177e4SLinus Torvalds } 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds if (retval != NAME_FOUND) { 5180030b645SJeff Mahoney reiserfs_error(dir->i_sb, "zam-7002", 51945b03d5eSJeff Mahoney "reiserfs_find_entry() returned " 52045b03d5eSJeff Mahoney "unexpected value (%d)", retval); 5211da177e4SLinus Torvalds } 5221da177e4SLinus Torvalds 5231da177e4SLinus Torvalds return -EEXIST; 5241da177e4SLinus Torvalds } 5251da177e4SLinus Torvalds 526bd4c625cSLinus Torvalds gen_number = 5273af1efe8SJeff Mahoney find_first_zero_bit(bit_string, 528bd4c625cSLinus Torvalds MAX_GENERATION_NUMBER + 1); 5291da177e4SLinus Torvalds if (gen_number > MAX_GENERATION_NUMBER) { 5301da177e4SLinus Torvalds /* there is no free generation number */ 53145b03d5eSJeff Mahoney reiserfs_warning(dir->i_sb, "reiserfs-7010", 53245b03d5eSJeff Mahoney "Congratulations! we have got hash function " 53345b03d5eSJeff Mahoney "screwed up"); 5341da177e4SLinus Torvalds if (buffer != small_buf) 535d739b42bSPekka Enberg kfree(buffer); 5361da177e4SLinus Torvalds pathrelse(&path); 5371da177e4SLinus Torvalds return -EBUSY; 5381da177e4SLinus Torvalds } 5391da177e4SLinus Torvalds /* adjust offset of directory enrty */ 5401da177e4SLinus Torvalds put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number)); 5411da177e4SLinus Torvalds set_cpu_key_k_offset(&entry_key, deh_offset(deh)); 5421da177e4SLinus Torvalds 5431da177e4SLinus Torvalds /* update max-hash-collisions counter in reiserfs_sb_info */ 5441da177e4SLinus Torvalds PROC_INFO_MAX(th->t_super, max_hash_collisions, gen_number); 5451da177e4SLinus Torvalds 546098297b2SJeff Mahoney /* we need to re-search for the insertion point */ 547098297b2SJeff Mahoney if (gen_number != 0) { 548bd4c625cSLinus Torvalds if (search_by_entry_key(dir->i_sb, &entry_key, &path, &de) != 549bd4c625cSLinus Torvalds NAME_NOT_FOUND) { 55045b03d5eSJeff Mahoney reiserfs_warning(dir->i_sb, "vs-7032", 55145b03d5eSJeff Mahoney "entry with this key (%K) already " 55245b03d5eSJeff Mahoney "exists", &entry_key); 5531da177e4SLinus Torvalds 5541da177e4SLinus Torvalds if (buffer != small_buf) 555d739b42bSPekka Enberg kfree(buffer); 5561da177e4SLinus Torvalds pathrelse(&path); 5571da177e4SLinus Torvalds return -EBUSY; 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds } 5601da177e4SLinus Torvalds 5611da177e4SLinus Torvalds /* perform the insertion of the entry that we have prepared */ 562bd4c625cSLinus Torvalds retval = 563bd4c625cSLinus Torvalds reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer, 564bd4c625cSLinus Torvalds paste_size); 5651da177e4SLinus Torvalds if (buffer != small_buf) 566d739b42bSPekka Enberg kfree(buffer); 5671da177e4SLinus Torvalds if (retval) { 5681da177e4SLinus Torvalds reiserfs_check_path(&path); 5691da177e4SLinus Torvalds return retval; 5701da177e4SLinus Torvalds } 5711da177e4SLinus Torvalds 5721da177e4SLinus Torvalds dir->i_size += paste_size; 5731da177e4SLinus Torvalds dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; 5741da177e4SLinus Torvalds if (!S_ISDIR(inode->i_mode) && visible) 575098297b2SJeff Mahoney /* reiserfs_mkdir or reiserfs_rename will do that by itself */ 5761da177e4SLinus Torvalds reiserfs_update_sd(th, dir); 5771da177e4SLinus Torvalds 5781da177e4SLinus Torvalds reiserfs_check_path(&path); 5791da177e4SLinus Torvalds return 0; 5801da177e4SLinus Torvalds } 5811da177e4SLinus Torvalds 582098297b2SJeff Mahoney /* 583098297b2SJeff Mahoney * quota utility function, call if you've had to abort after calling 584098297b2SJeff Mahoney * new_inode_init, and have not called reiserfs_new_inode yet. 585098297b2SJeff Mahoney * This should only be called on inodes that do not have stat data 586098297b2SJeff Mahoney * inserted into the tree yet. 5871da177e4SLinus Torvalds */ 588bd4c625cSLinus Torvalds static int drop_new_inode(struct inode *inode) 589bd4c625cSLinus Torvalds { 5909f754758SChristoph Hellwig dquot_drop(inode); 5911da177e4SLinus Torvalds make_bad_inode(inode); 5921da177e4SLinus Torvalds inode->i_flags |= S_NOQUOTA; 5931da177e4SLinus Torvalds iput(inode); 5941da177e4SLinus Torvalds return 0; 5951da177e4SLinus Torvalds } 5961da177e4SLinus Torvalds 597098297b2SJeff Mahoney /* 598098297b2SJeff Mahoney * utility function that does setup for reiserfs_new_inode. 599098297b2SJeff Mahoney * dquot_initialize needs lots of credits so it's better to have it 600098297b2SJeff Mahoney * outside of a transaction, so we had to pull some bits of 601098297b2SJeff Mahoney * reiserfs_new_inode out into this func. 6021da177e4SLinus Torvalds */ 6038e071892SAl Viro static int new_inode_init(struct inode *inode, struct inode *dir, umode_t mode) 604bd4c625cSLinus Torvalds { 605098297b2SJeff Mahoney /* 606098297b2SJeff Mahoney * Make inode invalid - just in case we are going to drop it before 607098297b2SJeff Mahoney * the initialization happens 608098297b2SJeff Mahoney */ 6091b0a74d1SJan Kara INODE_PKEY(inode)->k_objectid = 0; 610098297b2SJeff Mahoney 611098297b2SJeff Mahoney /* 612098297b2SJeff Mahoney * the quota init calls have to know who to charge the quota to, so 613098297b2SJeff Mahoney * we have to set uid and gid here 61404b7ed0dSDmitry Monakhov */ 61504b7ed0dSDmitry Monakhov inode_init_owner(inode, dir, mode); 6162e6c97eaSJan Kara return dquot_initialize(inode); 6171da177e4SLinus Torvalds } 6181da177e4SLinus Torvalds 6194acdaf27SAl Viro static int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, 620ebfc3b49SAl Viro bool excl) 6211da177e4SLinus Torvalds { 6221da177e4SLinus Torvalds int retval; 6231da177e4SLinus Torvalds struct inode *inode; 624098297b2SJeff Mahoney /* 625098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas 626098297b2SJeff Mahoney * for new inode + update of quota for directory owner) 627098297b2SJeff Mahoney */ 628bd4c625cSLinus Torvalds int jbegin_count = 629bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 2 + 630bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + 631bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); 6321da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 63357fe60dfSJeff Mahoney struct reiserfs_security_handle security; 6341da177e4SLinus Torvalds 6352e6c97eaSJan Kara retval = dquot_initialize(dir); 6362e6c97eaSJan Kara if (retval) 6372e6c97eaSJan Kara return retval; 638907f4554SChristoph Hellwig 6391da177e4SLinus Torvalds if (!(inode = new_inode(dir->i_sb))) { 6401da177e4SLinus Torvalds return -ENOMEM; 6411da177e4SLinus Torvalds } 6422e6c97eaSJan Kara retval = new_inode_init(inode, dir, mode); 6432e6c97eaSJan Kara if (retval) { 6442e6c97eaSJan Kara drop_new_inode(inode); 6452e6c97eaSJan Kara return retval; 6462e6c97eaSJan Kara } 6471da177e4SLinus Torvalds 6480ab2621eSJeff Mahoney jbegin_count += reiserfs_cache_default_acl(dir); 6492a7dba39SEric Paris retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); 65057fe60dfSJeff Mahoney if (retval < 0) { 65157fe60dfSJeff Mahoney drop_new_inode(inode); 65257fe60dfSJeff Mahoney return retval; 65357fe60dfSJeff Mahoney } 65457fe60dfSJeff Mahoney jbegin_count += retval; 6551da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb); 6561da177e4SLinus Torvalds 6571da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 6581da177e4SLinus Torvalds if (retval) { 6591da177e4SLinus Torvalds drop_new_inode(inode); 6601da177e4SLinus Torvalds goto out_failed; 6611da177e4SLinus Torvalds } 6621da177e4SLinus Torvalds 663bd4c625cSLinus Torvalds retval = 664bd4c625cSLinus Torvalds reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, 66557fe60dfSJeff Mahoney inode, &security); 6661da177e4SLinus Torvalds if (retval) 6671da177e4SLinus Torvalds goto out_failed; 6681da177e4SLinus Torvalds 6691da177e4SLinus Torvalds inode->i_op = &reiserfs_file_inode_operations; 6701da177e4SLinus Torvalds inode->i_fop = &reiserfs_file_operations; 6711da177e4SLinus Torvalds inode->i_mapping->a_ops = &reiserfs_address_space_operations; 6721da177e4SLinus Torvalds 673bd4c625cSLinus Torvalds retval = 674bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name, 675bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ ); 6761da177e4SLinus Torvalds if (retval) { 6771da177e4SLinus Torvalds int err; 6786d6b77f1SMiklos Szeredi drop_nlink(inode); 6791da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 68058d85426SJeff Mahoney err = journal_end(&th); 6811da177e4SLinus Torvalds if (err) 6821da177e4SLinus Torvalds retval = err; 683c1eaa26bSAl Viro unlock_new_inode(inode); 6841da177e4SLinus Torvalds iput(inode); 6851da177e4SLinus Torvalds goto out_failed; 6861da177e4SLinus Torvalds } 6871da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 6881da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 6891da177e4SLinus Torvalds 690c1eaa26bSAl Viro unlock_new_inode(inode); 6918fc37ec5SAl Viro d_instantiate(dentry, inode); 69258d85426SJeff Mahoney retval = journal_end(&th); 6931da177e4SLinus Torvalds 6941da177e4SLinus Torvalds out_failed: 6951da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 6961da177e4SLinus Torvalds return retval; 6971da177e4SLinus Torvalds } 6981da177e4SLinus Torvalds 6991a67aafbSAl Viro static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, 700bd4c625cSLinus Torvalds dev_t rdev) 7011da177e4SLinus Torvalds { 7021da177e4SLinus Torvalds int retval; 7031da177e4SLinus Torvalds struct inode *inode; 7041da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 70557fe60dfSJeff Mahoney struct reiserfs_security_handle security; 706098297b2SJeff Mahoney /* 707098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas 708098297b2SJeff Mahoney * for new inode + update of quota for directory owner) 709098297b2SJeff Mahoney */ 710bd4c625cSLinus Torvalds int jbegin_count = 711bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 712bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + 713bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); 7141da177e4SLinus Torvalds 7152e6c97eaSJan Kara retval = dquot_initialize(dir); 7162e6c97eaSJan Kara if (retval) 7172e6c97eaSJan Kara return retval; 718907f4554SChristoph Hellwig 7191da177e4SLinus Torvalds if (!(inode = new_inode(dir->i_sb))) { 7201da177e4SLinus Torvalds return -ENOMEM; 7211da177e4SLinus Torvalds } 7222e6c97eaSJan Kara retval = new_inode_init(inode, dir, mode); 7232e6c97eaSJan Kara if (retval) { 7242e6c97eaSJan Kara drop_new_inode(inode); 7252e6c97eaSJan Kara return retval; 7262e6c97eaSJan Kara } 7271da177e4SLinus Torvalds 7280ab2621eSJeff Mahoney jbegin_count += reiserfs_cache_default_acl(dir); 7292a7dba39SEric Paris retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); 73057fe60dfSJeff Mahoney if (retval < 0) { 73157fe60dfSJeff Mahoney drop_new_inode(inode); 73257fe60dfSJeff Mahoney return retval; 73357fe60dfSJeff Mahoney } 73457fe60dfSJeff Mahoney jbegin_count += retval; 7351da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb); 7361da177e4SLinus Torvalds 7371da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 7381da177e4SLinus Torvalds if (retval) { 7391da177e4SLinus Torvalds drop_new_inode(inode); 7401da177e4SLinus Torvalds goto out_failed; 7411da177e4SLinus Torvalds } 7421da177e4SLinus Torvalds 743bd4c625cSLinus Torvalds retval = 744bd4c625cSLinus Torvalds reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, 74557fe60dfSJeff Mahoney inode, &security); 7461da177e4SLinus Torvalds if (retval) { 7471da177e4SLinus Torvalds goto out_failed; 7481da177e4SLinus Torvalds } 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds inode->i_op = &reiserfs_special_inode_operations; 7511da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, rdev); 7521da177e4SLinus Torvalds 753098297b2SJeff Mahoney /* FIXME: needed for block and char devices only */ 7541da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 7551da177e4SLinus Torvalds 7561da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 7571da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 7581da177e4SLinus Torvalds 759bd4c625cSLinus Torvalds retval = 760bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name, 761bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ ); 7621da177e4SLinus Torvalds if (retval) { 7631da177e4SLinus Torvalds int err; 7646d6b77f1SMiklos Szeredi drop_nlink(inode); 7651da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 76658d85426SJeff Mahoney err = journal_end(&th); 7671da177e4SLinus Torvalds if (err) 7681da177e4SLinus Torvalds retval = err; 769c1eaa26bSAl Viro unlock_new_inode(inode); 7701da177e4SLinus Torvalds iput(inode); 7711da177e4SLinus Torvalds goto out_failed; 7721da177e4SLinus Torvalds } 7731da177e4SLinus Torvalds 774c1eaa26bSAl Viro unlock_new_inode(inode); 7758fc37ec5SAl Viro d_instantiate(dentry, inode); 77658d85426SJeff Mahoney retval = journal_end(&th); 7771da177e4SLinus Torvalds 7781da177e4SLinus Torvalds out_failed: 7791da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 7801da177e4SLinus Torvalds return retval; 7811da177e4SLinus Torvalds } 7821da177e4SLinus Torvalds 78318bb1db3SAl Viro static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 7841da177e4SLinus Torvalds { 7851da177e4SLinus Torvalds int retval; 7861da177e4SLinus Torvalds struct inode *inode; 7871da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 78857fe60dfSJeff Mahoney struct reiserfs_security_handle security; 789098297b2SJeff Mahoney /* 790098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas 791098297b2SJeff Mahoney * for new inode + update of quota for directory owner) 792098297b2SJeff Mahoney */ 793bd4c625cSLinus Torvalds int jbegin_count = 794bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 795bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + 796bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); 7971da177e4SLinus Torvalds 7982e6c97eaSJan Kara retval = dquot_initialize(dir); 7992e6c97eaSJan Kara if (retval) 8002e6c97eaSJan Kara return retval; 801907f4554SChristoph Hellwig 8021da177e4SLinus Torvalds #ifdef DISPLACE_NEW_PACKING_LOCALITIES 803098297b2SJeff Mahoney /* 804098297b2SJeff Mahoney * set flag that new packing locality created and new blocks 805098297b2SJeff Mahoney * for the content of that directory are not displaced yet 806098297b2SJeff Mahoney */ 8071da177e4SLinus Torvalds REISERFS_I(dir)->new_packing_locality = 1; 8081da177e4SLinus Torvalds #endif 8091da177e4SLinus Torvalds mode = S_IFDIR | mode; 8101da177e4SLinus Torvalds if (!(inode = new_inode(dir->i_sb))) { 8111da177e4SLinus Torvalds return -ENOMEM; 8121da177e4SLinus Torvalds } 8132e6c97eaSJan Kara retval = new_inode_init(inode, dir, mode); 8142e6c97eaSJan Kara if (retval) { 8152e6c97eaSJan Kara drop_new_inode(inode); 8162e6c97eaSJan Kara return retval; 8172e6c97eaSJan Kara } 8181da177e4SLinus Torvalds 8190ab2621eSJeff Mahoney jbegin_count += reiserfs_cache_default_acl(dir); 8202a7dba39SEric Paris retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); 82157fe60dfSJeff Mahoney if (retval < 0) { 82257fe60dfSJeff Mahoney drop_new_inode(inode); 82357fe60dfSJeff Mahoney return retval; 82457fe60dfSJeff Mahoney } 82557fe60dfSJeff Mahoney jbegin_count += retval; 826278f6679SJeff Mahoney reiserfs_write_lock(dir->i_sb); 8271da177e4SLinus Torvalds 8281da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 8291da177e4SLinus Torvalds if (retval) { 8301da177e4SLinus Torvalds drop_new_inode(inode); 8311da177e4SLinus Torvalds goto out_failed; 8321da177e4SLinus Torvalds } 8331da177e4SLinus Torvalds 834098297b2SJeff Mahoney /* 835098297b2SJeff Mahoney * inc the link count now, so another writer doesn't overflow 836098297b2SJeff Mahoney * it while we sleep later on. 8371da177e4SLinus Torvalds */ 8381da177e4SLinus Torvalds INC_DIR_INODE_NLINK(dir) 8391da177e4SLinus Torvalds 8401da177e4SLinus Torvalds retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ , 8411da177e4SLinus Torvalds old_format_only(dir->i_sb) ? 8421da177e4SLinus Torvalds EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, 84357fe60dfSJeff Mahoney dentry, inode, &security); 8441da177e4SLinus Torvalds if (retval) { 84599890a3bSAl Viro DEC_DIR_INODE_NLINK(dir) 8461da177e4SLinus Torvalds goto out_failed; 8471da177e4SLinus Torvalds } 8481da177e4SLinus Torvalds 8491da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 8501da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 8511da177e4SLinus Torvalds 8521da177e4SLinus Torvalds inode->i_op = &reiserfs_dir_inode_operations; 8531da177e4SLinus Torvalds inode->i_fop = &reiserfs_dir_operations; 8541da177e4SLinus Torvalds 855098297b2SJeff Mahoney /* note, _this_ add_entry will not update dir's stat data */ 856bd4c625cSLinus Torvalds retval = 857bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name, 858bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ ); 8591da177e4SLinus Torvalds if (retval) { 8601da177e4SLinus Torvalds int err; 8616d6b77f1SMiklos Szeredi clear_nlink(inode); 8621da177e4SLinus Torvalds DEC_DIR_INODE_NLINK(dir); 8631da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 86458d85426SJeff Mahoney err = journal_end(&th); 8651da177e4SLinus Torvalds if (err) 8661da177e4SLinus Torvalds retval = err; 867c1eaa26bSAl Viro unlock_new_inode(inode); 8681da177e4SLinus Torvalds iput(inode); 8691da177e4SLinus Torvalds goto out_failed; 8701da177e4SLinus Torvalds } 871098297b2SJeff Mahoney /* the above add_entry did not update dir's stat data */ 8721da177e4SLinus Torvalds reiserfs_update_sd(&th, dir); 8731da177e4SLinus Torvalds 874c1eaa26bSAl Viro unlock_new_inode(inode); 8758fc37ec5SAl Viro d_instantiate(dentry, inode); 87658d85426SJeff Mahoney retval = journal_end(&th); 8771da177e4SLinus Torvalds out_failed: 878278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb); 8791da177e4SLinus Torvalds return retval; 8801da177e4SLinus Torvalds } 8811da177e4SLinus Torvalds 882bd4c625cSLinus Torvalds static inline int reiserfs_empty_dir(struct inode *inode) 883bd4c625cSLinus Torvalds { 884098297b2SJeff Mahoney /* 885098297b2SJeff Mahoney * we can cheat because an old format dir cannot have 886098297b2SJeff Mahoney * EMPTY_DIR_SIZE, and a new format dir cannot have 887098297b2SJeff Mahoney * EMPTY_DIR_SIZE_V1. So, if the inode is either size, 888098297b2SJeff Mahoney * regardless of disk format version, the directory is empty. 8891da177e4SLinus Torvalds */ 8901da177e4SLinus Torvalds if (inode->i_size != EMPTY_DIR_SIZE && 8911da177e4SLinus Torvalds inode->i_size != EMPTY_DIR_SIZE_V1) { 8921da177e4SLinus Torvalds return 0; 8931da177e4SLinus Torvalds } 8941da177e4SLinus Torvalds return 1; 8951da177e4SLinus Torvalds } 8961da177e4SLinus Torvalds 8971da177e4SLinus Torvalds static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry) 8981da177e4SLinus Torvalds { 8991da177e4SLinus Torvalds int retval, err; 9001da177e4SLinus Torvalds struct inode *inode; 9011da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 9021da177e4SLinus Torvalds int jbegin_count; 9031da177e4SLinus Torvalds INITIALIZE_PATH(path); 9041da177e4SLinus Torvalds struct reiserfs_dir_entry de; 9051da177e4SLinus Torvalds 906098297b2SJeff Mahoney /* 907098297b2SJeff Mahoney * we will be doing 2 balancings and update 2 stat data, we 908098297b2SJeff Mahoney * change quotas of the owner of the directory and of the owner 909098297b2SJeff Mahoney * of the parent directory. The quota structure is possibly 910098297b2SJeff Mahoney * deleted only on last iput => outside of this transaction 911098297b2SJeff Mahoney */ 912bd4c625cSLinus Torvalds jbegin_count = 913bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 2 + 2 + 914bd4c625cSLinus Torvalds 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); 9151da177e4SLinus Torvalds 9162e6c97eaSJan Kara retval = dquot_initialize(dir); 9172e6c97eaSJan Kara if (retval) 9182e6c97eaSJan Kara return retval; 919907f4554SChristoph Hellwig 9201da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb); 9211da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 9221da177e4SLinus Torvalds if (retval) 9231da177e4SLinus Torvalds goto out_rmdir; 9241da177e4SLinus Torvalds 9251da177e4SLinus Torvalds de.de_gen_number_bit_string = NULL; 926bd4c625cSLinus Torvalds if ((retval = 927bd4c625cSLinus Torvalds reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, 928bd4c625cSLinus Torvalds &path, &de)) == NAME_NOT_FOUND) { 9291da177e4SLinus Torvalds retval = -ENOENT; 9301da177e4SLinus Torvalds goto end_rmdir; 9311da177e4SLinus Torvalds } else if (retval == IO_ERROR) { 9321da177e4SLinus Torvalds retval = -EIO; 9331da177e4SLinus Torvalds goto end_rmdir; 9341da177e4SLinus Torvalds } 9351da177e4SLinus Torvalds 9362b0143b5SDavid Howells inode = d_inode(dentry); 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 9391da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 9401da177e4SLinus Torvalds 9411da177e4SLinus Torvalds if (de.de_objectid != inode->i_ino) { 942098297b2SJeff Mahoney /* 943098297b2SJeff Mahoney * FIXME: compare key of an object and a key found in the entry 944098297b2SJeff Mahoney */ 9451da177e4SLinus Torvalds retval = -EIO; 9461da177e4SLinus Torvalds goto end_rmdir; 9471da177e4SLinus Torvalds } 9481da177e4SLinus Torvalds if (!reiserfs_empty_dir(inode)) { 9491da177e4SLinus Torvalds retval = -ENOTEMPTY; 9501da177e4SLinus Torvalds goto end_rmdir; 9511da177e4SLinus Torvalds } 9521da177e4SLinus Torvalds 9531da177e4SLinus Torvalds /* cut entry from dir directory */ 954a228bf8fSJeff Mahoney retval = reiserfs_cut_from_item(&th, &path, &de.de_entry_key, 955a228bf8fSJeff Mahoney dir, NULL, /* page */ 9561da177e4SLinus Torvalds 0 /*new file size - not used here */ ); 9571da177e4SLinus Torvalds if (retval < 0) 9581da177e4SLinus Torvalds goto end_rmdir; 9591da177e4SLinus Torvalds 9601da177e4SLinus Torvalds if (inode->i_nlink != 2 && inode->i_nlink != 1) 9610030b645SJeff Mahoney reiserfs_error(inode->i_sb, "reiserfs-7040", 96245b03d5eSJeff Mahoney "empty directory has nlink != 2 (%d)", 96345b03d5eSJeff Mahoney inode->i_nlink); 9641da177e4SLinus Torvalds 965ce71ec36SDave Hansen clear_nlink(inode); 9661da177e4SLinus Torvalds inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; 9671da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 9681da177e4SLinus Torvalds 9691da177e4SLinus Torvalds DEC_DIR_INODE_NLINK(dir) 9701da177e4SLinus Torvalds dir->i_size -= (DEH_SIZE + de.de_entrylen); 9711da177e4SLinus Torvalds reiserfs_update_sd(&th, dir); 9721da177e4SLinus Torvalds 9731da177e4SLinus Torvalds /* prevent empty directory from getting lost */ 9741da177e4SLinus Torvalds add_save_link(&th, inode, 0 /* not truncate */ ); 9751da177e4SLinus Torvalds 97658d85426SJeff Mahoney retval = journal_end(&th); 9771da177e4SLinus Torvalds reiserfs_check_path(&path); 9781da177e4SLinus Torvalds out_rmdir: 9791da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 9801da177e4SLinus Torvalds return retval; 9811da177e4SLinus Torvalds 9821da177e4SLinus Torvalds end_rmdir: 983098297b2SJeff Mahoney /* 984098297b2SJeff Mahoney * we must release path, because we did not call 985098297b2SJeff Mahoney * reiserfs_cut_from_item, or reiserfs_cut_from_item does not 986098297b2SJeff Mahoney * release path if operation was not complete 987098297b2SJeff Mahoney */ 9881da177e4SLinus Torvalds pathrelse(&path); 98958d85426SJeff Mahoney err = journal_end(&th); 9901da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 9911da177e4SLinus Torvalds return err ? err : retval; 9921da177e4SLinus Torvalds } 9931da177e4SLinus Torvalds 9941da177e4SLinus Torvalds static int reiserfs_unlink(struct inode *dir, struct dentry *dentry) 9951da177e4SLinus Torvalds { 9961da177e4SLinus Torvalds int retval, err; 9971da177e4SLinus Torvalds struct inode *inode; 9981da177e4SLinus Torvalds struct reiserfs_dir_entry de; 9991da177e4SLinus Torvalds INITIALIZE_PATH(path); 10001da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 10011da177e4SLinus Torvalds int jbegin_count; 10021da177e4SLinus Torvalds unsigned long savelink; 10031da177e4SLinus Torvalds 10042e6c97eaSJan Kara retval = dquot_initialize(dir); 10052e6c97eaSJan Kara if (retval) 10062e6c97eaSJan Kara return retval; 1007907f4554SChristoph Hellwig 10082b0143b5SDavid Howells inode = d_inode(dentry); 10091da177e4SLinus Torvalds 1010098297b2SJeff Mahoney /* 1011098297b2SJeff Mahoney * in this transaction we can be doing at max two balancings and 1012098297b2SJeff Mahoney * update two stat datas, we change quotas of the owner of the 1013098297b2SJeff Mahoney * directory and of the owner of the parent directory. The quota 1014098297b2SJeff Mahoney * structure is possibly deleted only on iput => outside of 1015098297b2SJeff Mahoney * this transaction 1016098297b2SJeff Mahoney */ 1017bd4c625cSLinus Torvalds jbegin_count = 1018bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 2 + 2 + 1019bd4c625cSLinus Torvalds 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); 10201da177e4SLinus Torvalds 1021278f6679SJeff Mahoney reiserfs_write_lock(dir->i_sb); 10221da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 10231da177e4SLinus Torvalds if (retval) 10241da177e4SLinus Torvalds goto out_unlink; 10251da177e4SLinus Torvalds 10261da177e4SLinus Torvalds de.de_gen_number_bit_string = NULL; 1027bd4c625cSLinus Torvalds if ((retval = 1028bd4c625cSLinus Torvalds reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, 1029bd4c625cSLinus Torvalds &path, &de)) == NAME_NOT_FOUND) { 10301da177e4SLinus Torvalds retval = -ENOENT; 10311da177e4SLinus Torvalds goto end_unlink; 10321da177e4SLinus Torvalds } else if (retval == IO_ERROR) { 10331da177e4SLinus Torvalds retval = -EIO; 10341da177e4SLinus Torvalds goto end_unlink; 10351da177e4SLinus Torvalds } 10361da177e4SLinus Torvalds 10371da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 10381da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 10391da177e4SLinus Torvalds 10401da177e4SLinus Torvalds if (de.de_objectid != inode->i_ino) { 1041098297b2SJeff Mahoney /* 1042098297b2SJeff Mahoney * FIXME: compare key of an object and a key found in the entry 1043098297b2SJeff Mahoney */ 10441da177e4SLinus Torvalds retval = -EIO; 10451da177e4SLinus Torvalds goto end_unlink; 10461da177e4SLinus Torvalds } 10471da177e4SLinus Torvalds 10481da177e4SLinus Torvalds if (!inode->i_nlink) { 104945b03d5eSJeff Mahoney reiserfs_warning(inode->i_sb, "reiserfs-7042", 105045b03d5eSJeff Mahoney "deleting nonexistent file (%lu), %d", 105145b03d5eSJeff Mahoney inode->i_ino, inode->i_nlink); 1052bfe86848SMiklos Szeredi set_nlink(inode, 1); 10531da177e4SLinus Torvalds } 10541da177e4SLinus Torvalds 10559a53c3a7SDave Hansen drop_nlink(inode); 10561da177e4SLinus Torvalds 10571da177e4SLinus Torvalds /* 10581da177e4SLinus Torvalds * we schedule before doing the add_save_link call, save the link 10591da177e4SLinus Torvalds * count so we don't race 10601da177e4SLinus Torvalds */ 10611da177e4SLinus Torvalds savelink = inode->i_nlink; 10621da177e4SLinus Torvalds 1063bd4c625cSLinus Torvalds retval = 1064a228bf8fSJeff Mahoney reiserfs_cut_from_item(&th, &path, &de.de_entry_key, dir, NULL, 1065bd4c625cSLinus Torvalds 0); 10661da177e4SLinus Torvalds if (retval < 0) { 1067d8c76e6fSDave Hansen inc_nlink(inode); 10681da177e4SLinus Torvalds goto end_unlink; 10691da177e4SLinus Torvalds } 10701da177e4SLinus Torvalds inode->i_ctime = CURRENT_TIME_SEC; 10711da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 10721da177e4SLinus Torvalds 10731da177e4SLinus Torvalds dir->i_size -= (de.de_entrylen + DEH_SIZE); 10741da177e4SLinus Torvalds dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; 10751da177e4SLinus Torvalds reiserfs_update_sd(&th, dir); 10761da177e4SLinus Torvalds 10771da177e4SLinus Torvalds if (!savelink) 10781da177e4SLinus Torvalds /* prevent file from getting lost */ 10791da177e4SLinus Torvalds add_save_link(&th, inode, 0 /* not truncate */ ); 10801da177e4SLinus Torvalds 108158d85426SJeff Mahoney retval = journal_end(&th); 10821da177e4SLinus Torvalds reiserfs_check_path(&path); 1083278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb); 10841da177e4SLinus Torvalds return retval; 10851da177e4SLinus Torvalds 10861da177e4SLinus Torvalds end_unlink: 10871da177e4SLinus Torvalds pathrelse(&path); 108858d85426SJeff Mahoney err = journal_end(&th); 10891da177e4SLinus Torvalds reiserfs_check_path(&path); 10901da177e4SLinus Torvalds if (err) 10911da177e4SLinus Torvalds retval = err; 10921da177e4SLinus Torvalds out_unlink: 1093278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb); 10941da177e4SLinus Torvalds return retval; 10951da177e4SLinus Torvalds } 10961da177e4SLinus Torvalds 10971da177e4SLinus Torvalds static int reiserfs_symlink(struct inode *parent_dir, 10981da177e4SLinus Torvalds struct dentry *dentry, const char *symname) 10991da177e4SLinus Torvalds { 11001da177e4SLinus Torvalds int retval; 11011da177e4SLinus Torvalds struct inode *inode; 11021da177e4SLinus Torvalds char *name; 11031da177e4SLinus Torvalds int item_len; 11041da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 110557fe60dfSJeff Mahoney struct reiserfs_security_handle security; 11061da177e4SLinus Torvalds int mode = S_IFLNK | S_IRWXUGO; 1107098297b2SJeff Mahoney /* 1108098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas for 1109098297b2SJeff Mahoney * new inode + update of quota for directory owner) 1110098297b2SJeff Mahoney */ 1111bd4c625cSLinus Torvalds int jbegin_count = 1112bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 1113bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb) + 1114bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb)); 11151da177e4SLinus Torvalds 11162e6c97eaSJan Kara retval = dquot_initialize(parent_dir); 11172e6c97eaSJan Kara if (retval) 11182e6c97eaSJan Kara return retval; 1119907f4554SChristoph Hellwig 11201da177e4SLinus Torvalds if (!(inode = new_inode(parent_dir->i_sb))) { 11211da177e4SLinus Torvalds return -ENOMEM; 11221da177e4SLinus Torvalds } 11232e6c97eaSJan Kara retval = new_inode_init(inode, parent_dir, mode); 11242e6c97eaSJan Kara if (retval) { 11252e6c97eaSJan Kara drop_new_inode(inode); 11262e6c97eaSJan Kara return retval; 11272e6c97eaSJan Kara } 11281da177e4SLinus Torvalds 11292a7dba39SEric Paris retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name, 11302a7dba39SEric Paris &security); 113157fe60dfSJeff Mahoney if (retval < 0) { 113257fe60dfSJeff Mahoney drop_new_inode(inode); 113357fe60dfSJeff Mahoney return retval; 113457fe60dfSJeff Mahoney } 113557fe60dfSJeff Mahoney jbegin_count += retval; 113657fe60dfSJeff Mahoney 11371da177e4SLinus Torvalds reiserfs_write_lock(parent_dir->i_sb); 11381da177e4SLinus Torvalds item_len = ROUND_UP(strlen(symname)); 11391da177e4SLinus Torvalds if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) { 11401da177e4SLinus Torvalds retval = -ENAMETOOLONG; 11411da177e4SLinus Torvalds drop_new_inode(inode); 11421da177e4SLinus Torvalds goto out_failed; 11431da177e4SLinus Torvalds } 11441da177e4SLinus Torvalds 1145d739b42bSPekka Enberg name = kmalloc(item_len, GFP_NOFS); 11461da177e4SLinus Torvalds if (!name) { 11471da177e4SLinus Torvalds drop_new_inode(inode); 11481da177e4SLinus Torvalds retval = -ENOMEM; 11491da177e4SLinus Torvalds goto out_failed; 11501da177e4SLinus Torvalds } 11511da177e4SLinus Torvalds memcpy(name, symname, strlen(symname)); 11521da177e4SLinus Torvalds padd_item(name, item_len, strlen(symname)); 11531da177e4SLinus Torvalds 11541da177e4SLinus Torvalds retval = journal_begin(&th, parent_dir->i_sb, jbegin_count); 11551da177e4SLinus Torvalds if (retval) { 11561da177e4SLinus Torvalds drop_new_inode(inode); 1157d739b42bSPekka Enberg kfree(name); 11581da177e4SLinus Torvalds goto out_failed; 11591da177e4SLinus Torvalds } 11601da177e4SLinus Torvalds 1161bd4c625cSLinus Torvalds retval = 1162bd4c625cSLinus Torvalds reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname), 116357fe60dfSJeff Mahoney dentry, inode, &security); 1164d739b42bSPekka Enberg kfree(name); 11651da177e4SLinus Torvalds if (retval) { /* reiserfs_new_inode iputs for us */ 11661da177e4SLinus Torvalds goto out_failed; 11671da177e4SLinus Torvalds } 11681da177e4SLinus Torvalds 11691da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 11701da177e4SLinus Torvalds reiserfs_update_inode_transaction(parent_dir); 11711da177e4SLinus Torvalds 11721da177e4SLinus Torvalds inode->i_op = &reiserfs_symlink_inode_operations; 117321fc61c7SAl Viro inode_nohighmem(inode); 11741da177e4SLinus Torvalds inode->i_mapping->a_ops = &reiserfs_address_space_operations; 11751da177e4SLinus Torvalds 11761da177e4SLinus Torvalds retval = reiserfs_add_entry(&th, parent_dir, dentry->d_name.name, 11771da177e4SLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ ); 11781da177e4SLinus Torvalds if (retval) { 11791da177e4SLinus Torvalds int err; 11806d6b77f1SMiklos Szeredi drop_nlink(inode); 11811da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 118258d85426SJeff Mahoney err = journal_end(&th); 11831da177e4SLinus Torvalds if (err) 11841da177e4SLinus Torvalds retval = err; 1185c1eaa26bSAl Viro unlock_new_inode(inode); 11861da177e4SLinus Torvalds iput(inode); 11871da177e4SLinus Torvalds goto out_failed; 11881da177e4SLinus Torvalds } 11891da177e4SLinus Torvalds 1190c1eaa26bSAl Viro unlock_new_inode(inode); 11918fc37ec5SAl Viro d_instantiate(dentry, inode); 119258d85426SJeff Mahoney retval = journal_end(&th); 11931da177e4SLinus Torvalds out_failed: 11941da177e4SLinus Torvalds reiserfs_write_unlock(parent_dir->i_sb); 11951da177e4SLinus Torvalds return retval; 11961da177e4SLinus Torvalds } 11971da177e4SLinus Torvalds 1198bd4c625cSLinus Torvalds static int reiserfs_link(struct dentry *old_dentry, struct inode *dir, 1199bd4c625cSLinus Torvalds struct dentry *dentry) 12001da177e4SLinus Torvalds { 12011da177e4SLinus Torvalds int retval; 12022b0143b5SDavid Howells struct inode *inode = d_inode(old_dentry); 12031da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 1204098297b2SJeff Mahoney /* 1205098297b2SJeff Mahoney * We need blocks for transaction + update of quotas for 1206098297b2SJeff Mahoney * the owners of the directory 1207098297b2SJeff Mahoney */ 1208bd4c625cSLinus Torvalds int jbegin_count = 1209bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 1210bd4c625cSLinus Torvalds 2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); 12111da177e4SLinus Torvalds 12122e6c97eaSJan Kara retval = dquot_initialize(dir); 12132e6c97eaSJan Kara if (retval) 12142e6c97eaSJan Kara return retval; 1215907f4554SChristoph Hellwig 12161da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb); 12171da177e4SLinus Torvalds if (inode->i_nlink >= REISERFS_LINK_MAX) { 1218098297b2SJeff Mahoney /* FIXME: sd_nlink is 32 bit for new files */ 12191da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 12201da177e4SLinus Torvalds return -EMLINK; 12211da177e4SLinus Torvalds } 12221da177e4SLinus Torvalds 12231da177e4SLinus Torvalds /* inc before scheduling so reiserfs_unlink knows we are here */ 1224d8c76e6fSDave Hansen inc_nlink(inode); 12251da177e4SLinus Torvalds 12261da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 12271da177e4SLinus Torvalds if (retval) { 12286d6b77f1SMiklos Szeredi drop_nlink(inode); 12291da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 12301da177e4SLinus Torvalds return retval; 12311da177e4SLinus Torvalds } 12321da177e4SLinus Torvalds 12331da177e4SLinus Torvalds /* create new entry */ 1234bd4c625cSLinus Torvalds retval = 1235bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name, 1236bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ ); 12371da177e4SLinus Torvalds 12381da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 12391da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 12401da177e4SLinus Torvalds 12411da177e4SLinus Torvalds if (retval) { 12421da177e4SLinus Torvalds int err; 12436d6b77f1SMiklos Szeredi drop_nlink(inode); 124458d85426SJeff Mahoney err = journal_end(&th); 12451da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 12461da177e4SLinus Torvalds return err ? err : retval; 12471da177e4SLinus Torvalds } 12481da177e4SLinus Torvalds 12491da177e4SLinus Torvalds inode->i_ctime = CURRENT_TIME_SEC; 12501da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 12511da177e4SLinus Torvalds 12527de9c6eeSAl Viro ihold(inode); 12531da177e4SLinus Torvalds d_instantiate(dentry, inode); 125458d85426SJeff Mahoney retval = journal_end(&th); 12551da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 12561da177e4SLinus Torvalds return retval; 12571da177e4SLinus Torvalds } 12581da177e4SLinus Torvalds 12590222e657SJeff Mahoney /* de contains information pointing to an entry which */ 1260bd4c625cSLinus Torvalds static int de_still_valid(const char *name, int len, 1261bd4c625cSLinus Torvalds struct reiserfs_dir_entry *de) 12621da177e4SLinus Torvalds { 12631da177e4SLinus Torvalds struct reiserfs_dir_entry tmp = *de; 12641da177e4SLinus Torvalds 1265098297b2SJeff Mahoney /* recalculate pointer to name and name length */ 12661da177e4SLinus Torvalds set_de_name_and_namelen(&tmp); 1267098297b2SJeff Mahoney /* FIXME: could check more */ 12681da177e4SLinus Torvalds if (tmp.de_namelen != len || memcmp(name, de->de_name, len)) 12691da177e4SLinus Torvalds return 0; 12701da177e4SLinus Torvalds return 1; 12711da177e4SLinus Torvalds } 12721da177e4SLinus Torvalds 1273bd4c625cSLinus Torvalds static int entry_points_to_object(const char *name, int len, 1274bd4c625cSLinus Torvalds struct reiserfs_dir_entry *de, 1275bd4c625cSLinus Torvalds struct inode *inode) 12761da177e4SLinus Torvalds { 12771da177e4SLinus Torvalds if (!de_still_valid(name, len, de)) 12781da177e4SLinus Torvalds return 0; 12791da177e4SLinus Torvalds 12801da177e4SLinus Torvalds if (inode) { 12811da177e4SLinus Torvalds if (!de_visible(de->de_deh + de->de_entry_num)) 1282c3a9c210SJeff Mahoney reiserfs_panic(inode->i_sb, "vs-7042", 1283c3a9c210SJeff Mahoney "entry must be visible"); 12841da177e4SLinus Torvalds return (de->de_objectid == inode->i_ino) ? 1 : 0; 12851da177e4SLinus Torvalds } 12861da177e4SLinus Torvalds 12871da177e4SLinus Torvalds /* this must be added hidden entry */ 12881da177e4SLinus Torvalds if (de_visible(de->de_deh + de->de_entry_num)) 1289c3a9c210SJeff Mahoney reiserfs_panic(NULL, "vs-7043", "entry must be visible"); 12901da177e4SLinus Torvalds 12911da177e4SLinus Torvalds return 1; 12921da177e4SLinus Torvalds } 12931da177e4SLinus Torvalds 12941da177e4SLinus Torvalds /* sets key of objectid the entry has to point to */ 1295bd4c625cSLinus Torvalds static void set_ino_in_dir_entry(struct reiserfs_dir_entry *de, 1296bd4c625cSLinus Torvalds struct reiserfs_key *key) 12971da177e4SLinus Torvalds { 12981da177e4SLinus Torvalds /* JDM These operations are endian safe - both are le */ 12991da177e4SLinus Torvalds de->de_deh[de->de_entry_num].deh_dir_id = key->k_dir_id; 13001da177e4SLinus Torvalds de->de_deh[de->de_entry_num].deh_objectid = key->k_objectid; 13011da177e4SLinus Torvalds } 13021da177e4SLinus Torvalds 13031da177e4SLinus Torvalds /* 13041da177e4SLinus Torvalds * process, that is going to call fix_nodes/do_balance must hold only 13051da177e4SLinus Torvalds * one path. If it holds 2 or more, it can get into endless waiting in 13061da177e4SLinus Torvalds * get_empty_nodes or its clones 13071da177e4SLinus Torvalds */ 13081da177e4SLinus Torvalds static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry, 13091da177e4SLinus Torvalds struct inode *new_dir, struct dentry *new_dentry) 13101da177e4SLinus Torvalds { 13111da177e4SLinus Torvalds int retval; 13121da177e4SLinus Torvalds INITIALIZE_PATH(old_entry_path); 13131da177e4SLinus Torvalds INITIALIZE_PATH(new_entry_path); 13141da177e4SLinus Torvalds INITIALIZE_PATH(dot_dot_entry_path); 13151da177e4SLinus Torvalds struct item_head new_entry_ih, old_entry_ih, dot_dot_ih; 13161da177e4SLinus Torvalds struct reiserfs_dir_entry old_de, new_de, dot_dot_de; 13171da177e4SLinus Torvalds struct inode *old_inode, *new_dentry_inode; 13181da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 13191da177e4SLinus Torvalds int jbegin_count; 13201da177e4SLinus Torvalds umode_t old_inode_mode; 13211da177e4SLinus Torvalds unsigned long savelink = 1; 13221da177e4SLinus Torvalds struct timespec ctime; 13231da177e4SLinus Torvalds 1324098297b2SJeff Mahoney /* 1325098297b2SJeff Mahoney * three balancings: (1) old name removal, (2) new name insertion 1326098297b2SJeff Mahoney * and (3) maybe "save" link insertion 1327098297b2SJeff Mahoney * stat data updates: (1) old directory, 1328098297b2SJeff Mahoney * (2) new directory and (3) maybe old object stat data (when it is 1329098297b2SJeff Mahoney * directory) and (4) maybe stat data of object to which new entry 1330098297b2SJeff Mahoney * pointed initially and (5) maybe block containing ".." of 1331098297b2SJeff Mahoney * renamed directory 1332098297b2SJeff Mahoney * quota updates: two parent directories 1333098297b2SJeff Mahoney */ 1334bd4c625cSLinus Torvalds jbegin_count = 1335bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 5 + 1336bd4c625cSLinus Torvalds 4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb); 13371da177e4SLinus Torvalds 13382e6c97eaSJan Kara retval = dquot_initialize(old_dir); 13392e6c97eaSJan Kara if (retval) 13402e6c97eaSJan Kara return retval; 13412e6c97eaSJan Kara retval = dquot_initialize(new_dir); 13422e6c97eaSJan Kara if (retval) 13432e6c97eaSJan Kara return retval; 1344907f4554SChristoph Hellwig 13452b0143b5SDavid Howells old_inode = d_inode(old_dentry); 13462b0143b5SDavid Howells new_dentry_inode = d_inode(new_dentry); 13471da177e4SLinus Torvalds 1348098297b2SJeff Mahoney /* 1349098297b2SJeff Mahoney * make sure that oldname still exists and points to an object we 1350098297b2SJeff Mahoney * are going to rename 1351098297b2SJeff Mahoney */ 13521da177e4SLinus Torvalds old_de.de_gen_number_bit_string = NULL; 13531da177e4SLinus Torvalds reiserfs_write_lock(old_dir->i_sb); 1354bd4c625cSLinus Torvalds retval = 1355bd4c625cSLinus Torvalds reiserfs_find_entry(old_dir, old_dentry->d_name.name, 1356bd4c625cSLinus Torvalds old_dentry->d_name.len, &old_entry_path, 1357bd4c625cSLinus Torvalds &old_de); 13581da177e4SLinus Torvalds pathrelse(&old_entry_path); 13591da177e4SLinus Torvalds if (retval == IO_ERROR) { 13601da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 13611da177e4SLinus Torvalds return -EIO; 13621da177e4SLinus Torvalds } 13631da177e4SLinus Torvalds 13641da177e4SLinus Torvalds if (retval != NAME_FOUND || old_de.de_objectid != old_inode->i_ino) { 13651da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 13661da177e4SLinus Torvalds return -ENOENT; 13671da177e4SLinus Torvalds } 13681da177e4SLinus Torvalds 13691da177e4SLinus Torvalds old_inode_mode = old_inode->i_mode; 13701da177e4SLinus Torvalds if (S_ISDIR(old_inode_mode)) { 1371098297b2SJeff Mahoney /* 1372098297b2SJeff Mahoney * make sure that directory being renamed has correct ".." 1373098297b2SJeff Mahoney * and that its new parent directory has not too many links 1374098297b2SJeff Mahoney * already 1375098297b2SJeff Mahoney */ 13761da177e4SLinus Torvalds if (new_dentry_inode) { 13771da177e4SLinus Torvalds if (!reiserfs_empty_dir(new_dentry_inode)) { 13781da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 13791da177e4SLinus Torvalds return -ENOTEMPTY; 13801da177e4SLinus Torvalds } 13811da177e4SLinus Torvalds } 13821da177e4SLinus Torvalds 1383098297b2SJeff Mahoney /* 1384098297b2SJeff Mahoney * directory is renamed, its parent directory will be changed, 1385098297b2SJeff Mahoney * so find ".." entry 13861da177e4SLinus Torvalds */ 13871da177e4SLinus Torvalds dot_dot_de.de_gen_number_bit_string = NULL; 1388bd4c625cSLinus Torvalds retval = 1389bd4c625cSLinus Torvalds reiserfs_find_entry(old_inode, "..", 2, &dot_dot_entry_path, 1390bd4c625cSLinus Torvalds &dot_dot_de); 13911da177e4SLinus Torvalds pathrelse(&dot_dot_entry_path); 13921da177e4SLinus Torvalds if (retval != NAME_FOUND) { 13931da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 13941da177e4SLinus Torvalds return -EIO; 13951da177e4SLinus Torvalds } 13961da177e4SLinus Torvalds 13971da177e4SLinus Torvalds /* inode number of .. must equal old_dir->i_ino */ 13981da177e4SLinus Torvalds if (dot_dot_de.de_objectid != old_dir->i_ino) { 13991da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 14001da177e4SLinus Torvalds return -EIO; 14011da177e4SLinus Torvalds } 14021da177e4SLinus Torvalds } 14031da177e4SLinus Torvalds 14041da177e4SLinus Torvalds retval = journal_begin(&th, old_dir->i_sb, jbegin_count); 14051da177e4SLinus Torvalds if (retval) { 14061da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 14071da177e4SLinus Torvalds return retval; 14081da177e4SLinus Torvalds } 14091da177e4SLinus Torvalds 14101da177e4SLinus Torvalds /* add new entry (or find the existing one) */ 1411bd4c625cSLinus Torvalds retval = 1412bd4c625cSLinus Torvalds reiserfs_add_entry(&th, new_dir, new_dentry->d_name.name, 1413bd4c625cSLinus Torvalds new_dentry->d_name.len, old_inode, 0); 14141da177e4SLinus Torvalds if (retval == -EEXIST) { 14151da177e4SLinus Torvalds if (!new_dentry_inode) { 1416c3a9c210SJeff Mahoney reiserfs_panic(old_dir->i_sb, "vs-7050", 1417c3a9c210SJeff Mahoney "new entry is found, new inode == 0"); 14181da177e4SLinus Torvalds } 14191da177e4SLinus Torvalds } else if (retval) { 142058d85426SJeff Mahoney int err = journal_end(&th); 14211da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 14221da177e4SLinus Torvalds return err ? err : retval; 14231da177e4SLinus Torvalds } 14241da177e4SLinus Torvalds 14251da177e4SLinus Torvalds reiserfs_update_inode_transaction(old_dir); 14261da177e4SLinus Torvalds reiserfs_update_inode_transaction(new_dir); 14271da177e4SLinus Torvalds 1428098297b2SJeff Mahoney /* 1429098297b2SJeff Mahoney * this makes it so an fsync on an open fd for the old name will 1430098297b2SJeff Mahoney * commit the rename operation 14311da177e4SLinus Torvalds */ 14321da177e4SLinus Torvalds reiserfs_update_inode_transaction(old_inode); 14331da177e4SLinus Torvalds 14341da177e4SLinus Torvalds if (new_dentry_inode) 14351da177e4SLinus Torvalds reiserfs_update_inode_transaction(new_dentry_inode); 14361da177e4SLinus Torvalds 14371da177e4SLinus Torvalds while (1) { 1438098297b2SJeff Mahoney /* 1439098297b2SJeff Mahoney * look for old name using corresponding entry key 1440098297b2SJeff Mahoney * (found by reiserfs_find_entry) 1441098297b2SJeff Mahoney */ 1442bd4c625cSLinus Torvalds if ((retval = 1443bd4c625cSLinus Torvalds search_by_entry_key(new_dir->i_sb, &old_de.de_entry_key, 1444bd4c625cSLinus Torvalds &old_entry_path, 1445bd4c625cSLinus Torvalds &old_de)) != NAME_FOUND) { 14461da177e4SLinus Torvalds pathrelse(&old_entry_path); 144758d85426SJeff Mahoney journal_end(&th); 14481da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 14491da177e4SLinus Torvalds return -EIO; 14501da177e4SLinus Torvalds } 14511da177e4SLinus Torvalds 14524cf5f7adSJeff Mahoney copy_item_head(&old_entry_ih, tp_item_head(&old_entry_path)); 14531da177e4SLinus Torvalds 14541da177e4SLinus Torvalds reiserfs_prepare_for_journal(old_inode->i_sb, old_de.de_bh, 1); 14551da177e4SLinus Torvalds 1456098297b2SJeff Mahoney /* look for new name by reiserfs_find_entry */ 14571da177e4SLinus Torvalds new_de.de_gen_number_bit_string = NULL; 1458bd4c625cSLinus Torvalds retval = 1459bd4c625cSLinus Torvalds reiserfs_find_entry(new_dir, new_dentry->d_name.name, 1460bd4c625cSLinus Torvalds new_dentry->d_name.len, &new_entry_path, 1461bd4c625cSLinus Torvalds &new_de); 1462098297b2SJeff Mahoney /* 1463098297b2SJeff Mahoney * reiserfs_add_entry should not return IO_ERROR, 1464098297b2SJeff Mahoney * because it is called with essentially same parameters from 1465098297b2SJeff Mahoney * reiserfs_add_entry above, and we'll catch any i/o errors 1466098297b2SJeff Mahoney * before we get here. 1467098297b2SJeff Mahoney */ 14681da177e4SLinus Torvalds if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) { 14691da177e4SLinus Torvalds pathrelse(&new_entry_path); 14701da177e4SLinus Torvalds pathrelse(&old_entry_path); 147158d85426SJeff Mahoney journal_end(&th); 14721da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 14731da177e4SLinus Torvalds return -EIO; 14741da177e4SLinus Torvalds } 14751da177e4SLinus Torvalds 14764cf5f7adSJeff Mahoney copy_item_head(&new_entry_ih, tp_item_head(&new_entry_path)); 14771da177e4SLinus Torvalds 14781da177e4SLinus Torvalds reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1); 14791da177e4SLinus Torvalds 14801da177e4SLinus Torvalds if (S_ISDIR(old_inode->i_mode)) { 1481bd4c625cSLinus Torvalds if ((retval = 1482bd4c625cSLinus Torvalds search_by_entry_key(new_dir->i_sb, 1483bd4c625cSLinus Torvalds &dot_dot_de.de_entry_key, 1484bd4c625cSLinus Torvalds &dot_dot_entry_path, 1485bd4c625cSLinus Torvalds &dot_dot_de)) != NAME_FOUND) { 14861da177e4SLinus Torvalds pathrelse(&dot_dot_entry_path); 14871da177e4SLinus Torvalds pathrelse(&new_entry_path); 14881da177e4SLinus Torvalds pathrelse(&old_entry_path); 148958d85426SJeff Mahoney journal_end(&th); 14901da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 14911da177e4SLinus Torvalds return -EIO; 14921da177e4SLinus Torvalds } 1493bd4c625cSLinus Torvalds copy_item_head(&dot_dot_ih, 14944cf5f7adSJeff Mahoney tp_item_head(&dot_dot_entry_path)); 1495098297b2SJeff Mahoney /* node containing ".." gets into transaction */ 1496bd4c625cSLinus Torvalds reiserfs_prepare_for_journal(old_inode->i_sb, 1497bd4c625cSLinus Torvalds dot_dot_de.de_bh, 1); 14981da177e4SLinus Torvalds } 1499098297b2SJeff Mahoney /* 1500098297b2SJeff Mahoney * we should check seals here, not do 1501098297b2SJeff Mahoney * this stuff, yes? Then, having 1502098297b2SJeff Mahoney * gathered everything into RAM we 1503098297b2SJeff Mahoney * should lock the buffers, yes? -Hans 15041da177e4SLinus Torvalds */ 1505098297b2SJeff Mahoney /* 1506098297b2SJeff Mahoney * probably. our rename needs to hold more 1507098297b2SJeff Mahoney * than one path at once. The seals would 1508098297b2SJeff Mahoney * have to be written to deal with multi-path 1509098297b2SJeff Mahoney * issues -chris 1510098297b2SJeff Mahoney */ 1511098297b2SJeff Mahoney /* 1512098297b2SJeff Mahoney * sanity checking before doing the rename - avoid races many 1513098297b2SJeff Mahoney * of the above checks could have scheduled. We have to be 1514098297b2SJeff Mahoney * sure our items haven't been shifted by another process. 15151da177e4SLinus Torvalds */ 15161da177e4SLinus Torvalds if (item_moved(&new_entry_ih, &new_entry_path) || 15171da177e4SLinus Torvalds !entry_points_to_object(new_dentry->d_name.name, 15181da177e4SLinus Torvalds new_dentry->d_name.len, 15191da177e4SLinus Torvalds &new_de, new_dentry_inode) || 15201da177e4SLinus Torvalds item_moved(&old_entry_ih, &old_entry_path) || 15211da177e4SLinus Torvalds !entry_points_to_object(old_dentry->d_name.name, 15221da177e4SLinus Torvalds old_dentry->d_name.len, 15231da177e4SLinus Torvalds &old_de, old_inode)) { 1524bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode->i_sb, 1525bd4c625cSLinus Torvalds new_de.de_bh); 1526bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode->i_sb, 1527bd4c625cSLinus Torvalds old_de.de_bh); 15281da177e4SLinus Torvalds if (S_ISDIR(old_inode_mode)) 1529bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode-> 1530bd4c625cSLinus Torvalds i_sb, 1531bd4c625cSLinus Torvalds dot_dot_de. 1532bd4c625cSLinus Torvalds de_bh); 15331da177e4SLinus Torvalds continue; 15341da177e4SLinus Torvalds } 15351da177e4SLinus Torvalds if (S_ISDIR(old_inode_mode)) { 15361da177e4SLinus Torvalds if (item_moved(&dot_dot_ih, &dot_dot_entry_path) || 1537bd4c625cSLinus Torvalds !entry_points_to_object("..", 2, &dot_dot_de, 1538bd4c625cSLinus Torvalds old_dir)) { 1539bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode-> 1540bd4c625cSLinus Torvalds i_sb, 1541bd4c625cSLinus Torvalds old_de.de_bh); 1542bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode-> 1543bd4c625cSLinus Torvalds i_sb, 1544bd4c625cSLinus Torvalds new_de.de_bh); 1545bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode-> 1546bd4c625cSLinus Torvalds i_sb, 1547bd4c625cSLinus Torvalds dot_dot_de. 1548bd4c625cSLinus Torvalds de_bh); 15491da177e4SLinus Torvalds continue; 15501da177e4SLinus Torvalds } 15511da177e4SLinus Torvalds } 15521da177e4SLinus Torvalds 15531da177e4SLinus Torvalds RFALSE(S_ISDIR(old_inode_mode) && 15541da177e4SLinus Torvalds !buffer_journal_prepared(dot_dot_de.de_bh), ""); 15551da177e4SLinus Torvalds 15561da177e4SLinus Torvalds break; 15571da177e4SLinus Torvalds } 15581da177e4SLinus Torvalds 1559098297b2SJeff Mahoney /* 1560098297b2SJeff Mahoney * ok, all the changes can be done in one fell swoop when we 1561098297b2SJeff Mahoney * have claimed all the buffers needed. 1562098297b2SJeff Mahoney */ 15631da177e4SLinus Torvalds 15641da177e4SLinus Torvalds mark_de_visible(new_de.de_deh + new_de.de_entry_num); 15651da177e4SLinus Torvalds set_ino_in_dir_entry(&new_de, INODE_PKEY(old_inode)); 156609f1b80bSJeff Mahoney journal_mark_dirty(&th, new_de.de_bh); 15671da177e4SLinus Torvalds 15681da177e4SLinus Torvalds mark_de_hidden(old_de.de_deh + old_de.de_entry_num); 156909f1b80bSJeff Mahoney journal_mark_dirty(&th, old_de.de_bh); 15701da177e4SLinus Torvalds ctime = CURRENT_TIME_SEC; 15711da177e4SLinus Torvalds old_dir->i_ctime = old_dir->i_mtime = ctime; 15721da177e4SLinus Torvalds new_dir->i_ctime = new_dir->i_mtime = ctime; 1573098297b2SJeff Mahoney /* 1574098297b2SJeff Mahoney * thanks to Alex Adriaanse <alex_a@caltech.edu> for patch 1575098297b2SJeff Mahoney * which adds ctime update of renamed object 1576098297b2SJeff Mahoney */ 15771da177e4SLinus Torvalds old_inode->i_ctime = ctime; 15781da177e4SLinus Torvalds 15791da177e4SLinus Torvalds if (new_dentry_inode) { 1580098297b2SJeff Mahoney /* adjust link number of the victim */ 15811da177e4SLinus Torvalds if (S_ISDIR(new_dentry_inode->i_mode)) { 1582ce71ec36SDave Hansen clear_nlink(new_dentry_inode); 15831da177e4SLinus Torvalds } else { 15849a53c3a7SDave Hansen drop_nlink(new_dentry_inode); 15851da177e4SLinus Torvalds } 15861da177e4SLinus Torvalds new_dentry_inode->i_ctime = ctime; 15871da177e4SLinus Torvalds savelink = new_dentry_inode->i_nlink; 15881da177e4SLinus Torvalds } 15891da177e4SLinus Torvalds 15901da177e4SLinus Torvalds if (S_ISDIR(old_inode_mode)) { 15910222e657SJeff Mahoney /* adjust ".." of renamed directory */ 15921da177e4SLinus Torvalds set_ino_in_dir_entry(&dot_dot_de, INODE_PKEY(new_dir)); 159309f1b80bSJeff Mahoney journal_mark_dirty(&th, dot_dot_de.de_bh); 15941da177e4SLinus Torvalds 1595098297b2SJeff Mahoney /* 1596098297b2SJeff Mahoney * there (in new_dir) was no directory, so it got new link 1597098297b2SJeff Mahoney * (".." of renamed directory) 1598098297b2SJeff Mahoney */ 15991da177e4SLinus Torvalds if (!new_dentry_inode) 16001da177e4SLinus Torvalds INC_DIR_INODE_NLINK(new_dir); 16011da177e4SLinus Torvalds 16021da177e4SLinus Torvalds /* old directory lost one link - ".. " of renamed directory */ 16031da177e4SLinus Torvalds DEC_DIR_INODE_NLINK(old_dir); 16041da177e4SLinus Torvalds } 1605098297b2SJeff Mahoney /* 1606098297b2SJeff Mahoney * looks like in 2.3.99pre3 brelse is atomic. 1607098297b2SJeff Mahoney * so we can use pathrelse 1608098297b2SJeff Mahoney */ 16091da177e4SLinus Torvalds pathrelse(&new_entry_path); 16101da177e4SLinus Torvalds pathrelse(&dot_dot_entry_path); 16111da177e4SLinus Torvalds 1612098297b2SJeff Mahoney /* 1613098297b2SJeff Mahoney * FIXME: this reiserfs_cut_from_item's return value may screw up 1614098297b2SJeff Mahoney * anybody, but it will panic if will not be able to find the 1615098297b2SJeff Mahoney * entry. This needs one more clean up 1616098297b2SJeff Mahoney */ 1617bd4c625cSLinus Torvalds if (reiserfs_cut_from_item 1618a228bf8fSJeff Mahoney (&th, &old_entry_path, &old_de.de_entry_key, old_dir, NULL, 1619bd4c625cSLinus Torvalds 0) < 0) 16200030b645SJeff Mahoney reiserfs_error(old_dir->i_sb, "vs-7060", 162145b03d5eSJeff Mahoney "couldn't not cut old name. Fsck later?"); 16221da177e4SLinus Torvalds 16231da177e4SLinus Torvalds old_dir->i_size -= DEH_SIZE + old_de.de_entrylen; 16241da177e4SLinus Torvalds 16251da177e4SLinus Torvalds reiserfs_update_sd(&th, old_dir); 16261da177e4SLinus Torvalds reiserfs_update_sd(&th, new_dir); 16271da177e4SLinus Torvalds reiserfs_update_sd(&th, old_inode); 16281da177e4SLinus Torvalds 16291da177e4SLinus Torvalds if (new_dentry_inode) { 16301da177e4SLinus Torvalds if (savelink == 0) 1631bd4c625cSLinus Torvalds add_save_link(&th, new_dentry_inode, 1632bd4c625cSLinus Torvalds 0 /* not truncate */ ); 16331da177e4SLinus Torvalds reiserfs_update_sd(&th, new_dentry_inode); 16341da177e4SLinus Torvalds } 16351da177e4SLinus Torvalds 163658d85426SJeff Mahoney retval = journal_end(&th); 16371da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb); 16381da177e4SLinus Torvalds return retval; 16391da177e4SLinus Torvalds } 16401da177e4SLinus Torvalds 1641098297b2SJeff Mahoney /* directories can handle most operations... */ 1642c5ef1c42SArjan van de Ven const struct inode_operations reiserfs_dir_inode_operations = { 16431da177e4SLinus Torvalds .create = reiserfs_create, 16441da177e4SLinus Torvalds .lookup = reiserfs_lookup, 16451da177e4SLinus Torvalds .link = reiserfs_link, 16461da177e4SLinus Torvalds .unlink = reiserfs_unlink, 16471da177e4SLinus Torvalds .symlink = reiserfs_symlink, 16481da177e4SLinus Torvalds .mkdir = reiserfs_mkdir, 16491da177e4SLinus Torvalds .rmdir = reiserfs_rmdir, 16501da177e4SLinus Torvalds .mknod = reiserfs_mknod, 16511da177e4SLinus Torvalds .rename = reiserfs_rename, 16521da177e4SLinus Torvalds .setattr = reiserfs_setattr, 16531da177e4SLinus Torvalds .setxattr = reiserfs_setxattr, 16541da177e4SLinus Torvalds .getxattr = reiserfs_getxattr, 16551da177e4SLinus Torvalds .listxattr = reiserfs_listxattr, 16561da177e4SLinus Torvalds .removexattr = reiserfs_removexattr, 16571da177e4SLinus Torvalds .permission = reiserfs_permission, 16584e34e719SChristoph Hellwig .get_acl = reiserfs_get_acl, 165947f70d08SChristoph Hellwig .set_acl = reiserfs_set_acl, 16601da177e4SLinus Torvalds }; 16611da177e4SLinus Torvalds 16621da177e4SLinus Torvalds /* 16631da177e4SLinus Torvalds * symlink operations.. same as page_symlink_inode_operations, with xattr 16641da177e4SLinus Torvalds * stuff added 16651da177e4SLinus Torvalds */ 1666c5ef1c42SArjan van de Ven const struct inode_operations reiserfs_symlink_inode_operations = { 16671da177e4SLinus Torvalds .readlink = generic_readlink, 1668*6b255391SAl Viro .get_link = page_get_link, 16691da177e4SLinus Torvalds .put_link = page_put_link, 16701da177e4SLinus Torvalds .setattr = reiserfs_setattr, 16711da177e4SLinus Torvalds .setxattr = reiserfs_setxattr, 16721da177e4SLinus Torvalds .getxattr = reiserfs_getxattr, 16731da177e4SLinus Torvalds .listxattr = reiserfs_listxattr, 16741da177e4SLinus Torvalds .removexattr = reiserfs_removexattr, 16751da177e4SLinus Torvalds .permission = reiserfs_permission, 16761da177e4SLinus Torvalds }; 16771da177e4SLinus Torvalds 16781da177e4SLinus Torvalds /* 16791da177e4SLinus Torvalds * special file operations.. just xattr/acl stuff 16801da177e4SLinus Torvalds */ 1681c5ef1c42SArjan van de Ven const struct inode_operations reiserfs_special_inode_operations = { 16821da177e4SLinus Torvalds .setattr = reiserfs_setattr, 16831da177e4SLinus Torvalds .setxattr = reiserfs_setxattr, 16841da177e4SLinus Torvalds .getxattr = reiserfs_getxattr, 16851da177e4SLinus Torvalds .listxattr = reiserfs_listxattr, 16861da177e4SLinus Torvalds .removexattr = reiserfs_removexattr, 16871da177e4SLinus Torvalds .permission = reiserfs_permission, 16884e34e719SChristoph Hellwig .get_acl = reiserfs_get_acl, 168947f70d08SChristoph Hellwig .set_acl = reiserfs_set_acl, 16901da177e4SLinus Torvalds }; 1691