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; 57302027d42SDeepa Dinamani dir->i_mtime = dir->i_ctime = current_time(dir); 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 690*1e2e547aSAl Viro d_instantiate_new(dentry, inode); 69158d85426SJeff Mahoney retval = journal_end(&th); 6921da177e4SLinus Torvalds 6931da177e4SLinus Torvalds out_failed: 6941da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 6951da177e4SLinus Torvalds return retval; 6961da177e4SLinus Torvalds } 6971da177e4SLinus Torvalds 6981a67aafbSAl Viro static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, 699bd4c625cSLinus Torvalds dev_t rdev) 7001da177e4SLinus Torvalds { 7011da177e4SLinus Torvalds int retval; 7021da177e4SLinus Torvalds struct inode *inode; 7031da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 70457fe60dfSJeff Mahoney struct reiserfs_security_handle security; 705098297b2SJeff Mahoney /* 706098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas 707098297b2SJeff Mahoney * for new inode + update of quota for directory owner) 708098297b2SJeff Mahoney */ 709bd4c625cSLinus Torvalds int jbegin_count = 710bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 711bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + 712bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); 7131da177e4SLinus Torvalds 7142e6c97eaSJan Kara retval = dquot_initialize(dir); 7152e6c97eaSJan Kara if (retval) 7162e6c97eaSJan Kara return retval; 717907f4554SChristoph Hellwig 7181da177e4SLinus Torvalds if (!(inode = new_inode(dir->i_sb))) { 7191da177e4SLinus Torvalds return -ENOMEM; 7201da177e4SLinus Torvalds } 7212e6c97eaSJan Kara retval = new_inode_init(inode, dir, mode); 7222e6c97eaSJan Kara if (retval) { 7232e6c97eaSJan Kara drop_new_inode(inode); 7242e6c97eaSJan Kara return retval; 7252e6c97eaSJan Kara } 7261da177e4SLinus Torvalds 7270ab2621eSJeff Mahoney jbegin_count += reiserfs_cache_default_acl(dir); 7282a7dba39SEric Paris retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); 72957fe60dfSJeff Mahoney if (retval < 0) { 73057fe60dfSJeff Mahoney drop_new_inode(inode); 73157fe60dfSJeff Mahoney return retval; 73257fe60dfSJeff Mahoney } 73357fe60dfSJeff Mahoney jbegin_count += retval; 7341da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb); 7351da177e4SLinus Torvalds 7361da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 7371da177e4SLinus Torvalds if (retval) { 7381da177e4SLinus Torvalds drop_new_inode(inode); 7391da177e4SLinus Torvalds goto out_failed; 7401da177e4SLinus Torvalds } 7411da177e4SLinus Torvalds 742bd4c625cSLinus Torvalds retval = 743bd4c625cSLinus Torvalds reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, 74457fe60dfSJeff Mahoney inode, &security); 7451da177e4SLinus Torvalds if (retval) { 7461da177e4SLinus Torvalds goto out_failed; 7471da177e4SLinus Torvalds } 7481da177e4SLinus Torvalds 7491da177e4SLinus Torvalds inode->i_op = &reiserfs_special_inode_operations; 7501da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, rdev); 7511da177e4SLinus Torvalds 752098297b2SJeff Mahoney /* FIXME: needed for block and char devices only */ 7531da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 7541da177e4SLinus Torvalds 7551da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 7561da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 7571da177e4SLinus Torvalds 758bd4c625cSLinus Torvalds retval = 759bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name, 760bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ ); 7611da177e4SLinus Torvalds if (retval) { 7621da177e4SLinus Torvalds int err; 7636d6b77f1SMiklos Szeredi drop_nlink(inode); 7641da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 76558d85426SJeff Mahoney err = journal_end(&th); 7661da177e4SLinus Torvalds if (err) 7671da177e4SLinus Torvalds retval = err; 768c1eaa26bSAl Viro unlock_new_inode(inode); 7691da177e4SLinus Torvalds iput(inode); 7701da177e4SLinus Torvalds goto out_failed; 7711da177e4SLinus Torvalds } 7721da177e4SLinus Torvalds 773*1e2e547aSAl Viro d_instantiate_new(dentry, inode); 77458d85426SJeff Mahoney retval = journal_end(&th); 7751da177e4SLinus Torvalds 7761da177e4SLinus Torvalds out_failed: 7771da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 7781da177e4SLinus Torvalds return retval; 7791da177e4SLinus Torvalds } 7801da177e4SLinus Torvalds 78118bb1db3SAl Viro static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 7821da177e4SLinus Torvalds { 7831da177e4SLinus Torvalds int retval; 7841da177e4SLinus Torvalds struct inode *inode; 7851da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 78657fe60dfSJeff Mahoney struct reiserfs_security_handle security; 787098297b2SJeff Mahoney /* 788098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas 789098297b2SJeff Mahoney * for new inode + update of quota for directory owner) 790098297b2SJeff Mahoney */ 791bd4c625cSLinus Torvalds int jbegin_count = 792bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 793bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + 794bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); 7951da177e4SLinus Torvalds 7962e6c97eaSJan Kara retval = dquot_initialize(dir); 7972e6c97eaSJan Kara if (retval) 7982e6c97eaSJan Kara return retval; 799907f4554SChristoph Hellwig 8001da177e4SLinus Torvalds #ifdef DISPLACE_NEW_PACKING_LOCALITIES 801098297b2SJeff Mahoney /* 802098297b2SJeff Mahoney * set flag that new packing locality created and new blocks 803098297b2SJeff Mahoney * for the content of that directory are not displaced yet 804098297b2SJeff Mahoney */ 8051da177e4SLinus Torvalds REISERFS_I(dir)->new_packing_locality = 1; 8061da177e4SLinus Torvalds #endif 8071da177e4SLinus Torvalds mode = S_IFDIR | mode; 8081da177e4SLinus Torvalds if (!(inode = new_inode(dir->i_sb))) { 8091da177e4SLinus Torvalds return -ENOMEM; 8101da177e4SLinus Torvalds } 8112e6c97eaSJan Kara retval = new_inode_init(inode, dir, mode); 8122e6c97eaSJan Kara if (retval) { 8132e6c97eaSJan Kara drop_new_inode(inode); 8142e6c97eaSJan Kara return retval; 8152e6c97eaSJan Kara } 8161da177e4SLinus Torvalds 8170ab2621eSJeff Mahoney jbegin_count += reiserfs_cache_default_acl(dir); 8182a7dba39SEric Paris retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); 81957fe60dfSJeff Mahoney if (retval < 0) { 82057fe60dfSJeff Mahoney drop_new_inode(inode); 82157fe60dfSJeff Mahoney return retval; 82257fe60dfSJeff Mahoney } 82357fe60dfSJeff Mahoney jbegin_count += retval; 824278f6679SJeff Mahoney reiserfs_write_lock(dir->i_sb); 8251da177e4SLinus Torvalds 8261da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 8271da177e4SLinus Torvalds if (retval) { 8281da177e4SLinus Torvalds drop_new_inode(inode); 8291da177e4SLinus Torvalds goto out_failed; 8301da177e4SLinus Torvalds } 8311da177e4SLinus Torvalds 832098297b2SJeff Mahoney /* 833098297b2SJeff Mahoney * inc the link count now, so another writer doesn't overflow 834098297b2SJeff Mahoney * it while we sleep later on. 8351da177e4SLinus Torvalds */ 8361da177e4SLinus Torvalds INC_DIR_INODE_NLINK(dir) 8371da177e4SLinus Torvalds 8381da177e4SLinus Torvalds retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ , 8391da177e4SLinus Torvalds old_format_only(dir->i_sb) ? 8401da177e4SLinus Torvalds EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, 84157fe60dfSJeff Mahoney dentry, inode, &security); 8421da177e4SLinus Torvalds if (retval) { 84399890a3bSAl Viro DEC_DIR_INODE_NLINK(dir) 8441da177e4SLinus Torvalds goto out_failed; 8451da177e4SLinus Torvalds } 8461da177e4SLinus Torvalds 8471da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 8481da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 8491da177e4SLinus Torvalds 8501da177e4SLinus Torvalds inode->i_op = &reiserfs_dir_inode_operations; 8511da177e4SLinus Torvalds inode->i_fop = &reiserfs_dir_operations; 8521da177e4SLinus Torvalds 853098297b2SJeff Mahoney /* note, _this_ add_entry will not update dir's stat data */ 854bd4c625cSLinus Torvalds retval = 855bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name, 856bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ ); 8571da177e4SLinus Torvalds if (retval) { 8581da177e4SLinus Torvalds int err; 8596d6b77f1SMiklos Szeredi clear_nlink(inode); 8601da177e4SLinus Torvalds DEC_DIR_INODE_NLINK(dir); 8611da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 86258d85426SJeff Mahoney err = journal_end(&th); 8631da177e4SLinus Torvalds if (err) 8641da177e4SLinus Torvalds retval = err; 865c1eaa26bSAl Viro unlock_new_inode(inode); 8661da177e4SLinus Torvalds iput(inode); 8671da177e4SLinus Torvalds goto out_failed; 8681da177e4SLinus Torvalds } 869098297b2SJeff Mahoney /* the above add_entry did not update dir's stat data */ 8701da177e4SLinus Torvalds reiserfs_update_sd(&th, dir); 8711da177e4SLinus Torvalds 872*1e2e547aSAl Viro d_instantiate_new(dentry, inode); 87358d85426SJeff Mahoney retval = journal_end(&th); 8741da177e4SLinus Torvalds out_failed: 875278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb); 8761da177e4SLinus Torvalds return retval; 8771da177e4SLinus Torvalds } 8781da177e4SLinus Torvalds 879bd4c625cSLinus Torvalds static inline int reiserfs_empty_dir(struct inode *inode) 880bd4c625cSLinus Torvalds { 881098297b2SJeff Mahoney /* 882098297b2SJeff Mahoney * we can cheat because an old format dir cannot have 883098297b2SJeff Mahoney * EMPTY_DIR_SIZE, and a new format dir cannot have 884098297b2SJeff Mahoney * EMPTY_DIR_SIZE_V1. So, if the inode is either size, 885098297b2SJeff Mahoney * regardless of disk format version, the directory is empty. 8861da177e4SLinus Torvalds */ 8871da177e4SLinus Torvalds if (inode->i_size != EMPTY_DIR_SIZE && 8881da177e4SLinus Torvalds inode->i_size != EMPTY_DIR_SIZE_V1) { 8891da177e4SLinus Torvalds return 0; 8901da177e4SLinus Torvalds } 8911da177e4SLinus Torvalds return 1; 8921da177e4SLinus Torvalds } 8931da177e4SLinus Torvalds 8941da177e4SLinus Torvalds static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry) 8951da177e4SLinus Torvalds { 8961da177e4SLinus Torvalds int retval, err; 8971da177e4SLinus Torvalds struct inode *inode; 8981da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 8991da177e4SLinus Torvalds int jbegin_count; 9001da177e4SLinus Torvalds INITIALIZE_PATH(path); 9011da177e4SLinus Torvalds struct reiserfs_dir_entry de; 9021da177e4SLinus Torvalds 903098297b2SJeff Mahoney /* 904098297b2SJeff Mahoney * we will be doing 2 balancings and update 2 stat data, we 905098297b2SJeff Mahoney * change quotas of the owner of the directory and of the owner 906098297b2SJeff Mahoney * of the parent directory. The quota structure is possibly 907098297b2SJeff Mahoney * deleted only on last iput => outside of this transaction 908098297b2SJeff Mahoney */ 909bd4c625cSLinus Torvalds jbegin_count = 910bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 2 + 2 + 911bd4c625cSLinus Torvalds 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); 9121da177e4SLinus Torvalds 9132e6c97eaSJan Kara retval = dquot_initialize(dir); 9142e6c97eaSJan Kara if (retval) 9152e6c97eaSJan Kara return retval; 916907f4554SChristoph Hellwig 9171da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb); 9181da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 9191da177e4SLinus Torvalds if (retval) 9201da177e4SLinus Torvalds goto out_rmdir; 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds de.de_gen_number_bit_string = NULL; 923bd4c625cSLinus Torvalds if ((retval = 924bd4c625cSLinus Torvalds reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, 925bd4c625cSLinus Torvalds &path, &de)) == NAME_NOT_FOUND) { 9261da177e4SLinus Torvalds retval = -ENOENT; 9271da177e4SLinus Torvalds goto end_rmdir; 9281da177e4SLinus Torvalds } else if (retval == IO_ERROR) { 9291da177e4SLinus Torvalds retval = -EIO; 9301da177e4SLinus Torvalds goto end_rmdir; 9311da177e4SLinus Torvalds } 9321da177e4SLinus Torvalds 9332b0143b5SDavid Howells inode = d_inode(dentry); 9341da177e4SLinus Torvalds 9351da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 9361da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds if (de.de_objectid != inode->i_ino) { 939098297b2SJeff Mahoney /* 940098297b2SJeff Mahoney * FIXME: compare key of an object and a key found in the entry 941098297b2SJeff Mahoney */ 9421da177e4SLinus Torvalds retval = -EIO; 9431da177e4SLinus Torvalds goto end_rmdir; 9441da177e4SLinus Torvalds } 9451da177e4SLinus Torvalds if (!reiserfs_empty_dir(inode)) { 9461da177e4SLinus Torvalds retval = -ENOTEMPTY; 9471da177e4SLinus Torvalds goto end_rmdir; 9481da177e4SLinus Torvalds } 9491da177e4SLinus Torvalds 9501da177e4SLinus Torvalds /* cut entry from dir directory */ 951a228bf8fSJeff Mahoney retval = reiserfs_cut_from_item(&th, &path, &de.de_entry_key, 952a228bf8fSJeff Mahoney dir, NULL, /* page */ 9531da177e4SLinus Torvalds 0 /*new file size - not used here */ ); 9541da177e4SLinus Torvalds if (retval < 0) 9551da177e4SLinus Torvalds goto end_rmdir; 9561da177e4SLinus Torvalds 9571da177e4SLinus Torvalds if (inode->i_nlink != 2 && inode->i_nlink != 1) 9580030b645SJeff Mahoney reiserfs_error(inode->i_sb, "reiserfs-7040", 95945b03d5eSJeff Mahoney "empty directory has nlink != 2 (%d)", 96045b03d5eSJeff Mahoney inode->i_nlink); 9611da177e4SLinus Torvalds 962ce71ec36SDave Hansen clear_nlink(inode); 96302027d42SDeepa Dinamani inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(dir); 9641da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 9651da177e4SLinus Torvalds 9661da177e4SLinus Torvalds DEC_DIR_INODE_NLINK(dir) 9671da177e4SLinus Torvalds dir->i_size -= (DEH_SIZE + de.de_entrylen); 9681da177e4SLinus Torvalds reiserfs_update_sd(&th, dir); 9691da177e4SLinus Torvalds 9701da177e4SLinus Torvalds /* prevent empty directory from getting lost */ 9711da177e4SLinus Torvalds add_save_link(&th, inode, 0 /* not truncate */ ); 9721da177e4SLinus Torvalds 97358d85426SJeff Mahoney retval = journal_end(&th); 9741da177e4SLinus Torvalds reiserfs_check_path(&path); 9751da177e4SLinus Torvalds out_rmdir: 9761da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 9771da177e4SLinus Torvalds return retval; 9781da177e4SLinus Torvalds 9791da177e4SLinus Torvalds end_rmdir: 980098297b2SJeff Mahoney /* 981098297b2SJeff Mahoney * we must release path, because we did not call 982098297b2SJeff Mahoney * reiserfs_cut_from_item, or reiserfs_cut_from_item does not 983098297b2SJeff Mahoney * release path if operation was not complete 984098297b2SJeff Mahoney */ 9851da177e4SLinus Torvalds pathrelse(&path); 98658d85426SJeff Mahoney err = journal_end(&th); 9871da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 9881da177e4SLinus Torvalds return err ? err : retval; 9891da177e4SLinus Torvalds } 9901da177e4SLinus Torvalds 9911da177e4SLinus Torvalds static int reiserfs_unlink(struct inode *dir, struct dentry *dentry) 9921da177e4SLinus Torvalds { 9931da177e4SLinus Torvalds int retval, err; 9941da177e4SLinus Torvalds struct inode *inode; 9951da177e4SLinus Torvalds struct reiserfs_dir_entry de; 9961da177e4SLinus Torvalds INITIALIZE_PATH(path); 9971da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 9981da177e4SLinus Torvalds int jbegin_count; 9991da177e4SLinus Torvalds unsigned long savelink; 10001da177e4SLinus Torvalds 10012e6c97eaSJan Kara retval = dquot_initialize(dir); 10022e6c97eaSJan Kara if (retval) 10032e6c97eaSJan Kara return retval; 1004907f4554SChristoph Hellwig 10052b0143b5SDavid Howells inode = d_inode(dentry); 10061da177e4SLinus Torvalds 1007098297b2SJeff Mahoney /* 1008098297b2SJeff Mahoney * in this transaction we can be doing at max two balancings and 1009098297b2SJeff Mahoney * update two stat datas, we change quotas of the owner of the 1010098297b2SJeff Mahoney * directory and of the owner of the parent directory. The quota 1011098297b2SJeff Mahoney * structure is possibly deleted only on iput => outside of 1012098297b2SJeff Mahoney * this transaction 1013098297b2SJeff Mahoney */ 1014bd4c625cSLinus Torvalds jbegin_count = 1015bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 2 + 2 + 1016bd4c625cSLinus Torvalds 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); 10171da177e4SLinus Torvalds 1018278f6679SJeff Mahoney reiserfs_write_lock(dir->i_sb); 10191da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 10201da177e4SLinus Torvalds if (retval) 10211da177e4SLinus Torvalds goto out_unlink; 10221da177e4SLinus Torvalds 10231da177e4SLinus Torvalds de.de_gen_number_bit_string = NULL; 1024bd4c625cSLinus Torvalds if ((retval = 1025bd4c625cSLinus Torvalds reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, 1026bd4c625cSLinus Torvalds &path, &de)) == NAME_NOT_FOUND) { 10271da177e4SLinus Torvalds retval = -ENOENT; 10281da177e4SLinus Torvalds goto end_unlink; 10291da177e4SLinus Torvalds } else if (retval == IO_ERROR) { 10301da177e4SLinus Torvalds retval = -EIO; 10311da177e4SLinus Torvalds goto end_unlink; 10321da177e4SLinus Torvalds } 10331da177e4SLinus Torvalds 10341da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 10351da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 10361da177e4SLinus Torvalds 10371da177e4SLinus Torvalds if (de.de_objectid != inode->i_ino) { 1038098297b2SJeff Mahoney /* 1039098297b2SJeff Mahoney * FIXME: compare key of an object and a key found in the entry 1040098297b2SJeff Mahoney */ 10411da177e4SLinus Torvalds retval = -EIO; 10421da177e4SLinus Torvalds goto end_unlink; 10431da177e4SLinus Torvalds } 10441da177e4SLinus Torvalds 10451da177e4SLinus Torvalds if (!inode->i_nlink) { 104645b03d5eSJeff Mahoney reiserfs_warning(inode->i_sb, "reiserfs-7042", 104745b03d5eSJeff Mahoney "deleting nonexistent file (%lu), %d", 104845b03d5eSJeff Mahoney inode->i_ino, inode->i_nlink); 1049bfe86848SMiklos Szeredi set_nlink(inode, 1); 10501da177e4SLinus Torvalds } 10511da177e4SLinus Torvalds 10529a53c3a7SDave Hansen drop_nlink(inode); 10531da177e4SLinus Torvalds 10541da177e4SLinus Torvalds /* 10551da177e4SLinus Torvalds * we schedule before doing the add_save_link call, save the link 10561da177e4SLinus Torvalds * count so we don't race 10571da177e4SLinus Torvalds */ 10581da177e4SLinus Torvalds savelink = inode->i_nlink; 10591da177e4SLinus Torvalds 1060bd4c625cSLinus Torvalds retval = 1061a228bf8fSJeff Mahoney reiserfs_cut_from_item(&th, &path, &de.de_entry_key, dir, NULL, 1062bd4c625cSLinus Torvalds 0); 10631da177e4SLinus Torvalds if (retval < 0) { 1064d8c76e6fSDave Hansen inc_nlink(inode); 10651da177e4SLinus Torvalds goto end_unlink; 10661da177e4SLinus Torvalds } 106702027d42SDeepa Dinamani inode->i_ctime = current_time(inode); 10681da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 10691da177e4SLinus Torvalds 10701da177e4SLinus Torvalds dir->i_size -= (de.de_entrylen + DEH_SIZE); 107102027d42SDeepa Dinamani dir->i_ctime = dir->i_mtime = current_time(dir); 10721da177e4SLinus Torvalds reiserfs_update_sd(&th, dir); 10731da177e4SLinus Torvalds 10741da177e4SLinus Torvalds if (!savelink) 10751da177e4SLinus Torvalds /* prevent file from getting lost */ 10761da177e4SLinus Torvalds add_save_link(&th, inode, 0 /* not truncate */ ); 10771da177e4SLinus Torvalds 107858d85426SJeff Mahoney retval = journal_end(&th); 10791da177e4SLinus Torvalds reiserfs_check_path(&path); 1080278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb); 10811da177e4SLinus Torvalds return retval; 10821da177e4SLinus Torvalds 10831da177e4SLinus Torvalds end_unlink: 10841da177e4SLinus Torvalds pathrelse(&path); 108558d85426SJeff Mahoney err = journal_end(&th); 10861da177e4SLinus Torvalds reiserfs_check_path(&path); 10871da177e4SLinus Torvalds if (err) 10881da177e4SLinus Torvalds retval = err; 10891da177e4SLinus Torvalds out_unlink: 1090278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb); 10911da177e4SLinus Torvalds return retval; 10921da177e4SLinus Torvalds } 10931da177e4SLinus Torvalds 10941da177e4SLinus Torvalds static int reiserfs_symlink(struct inode *parent_dir, 10951da177e4SLinus Torvalds struct dentry *dentry, const char *symname) 10961da177e4SLinus Torvalds { 10971da177e4SLinus Torvalds int retval; 10981da177e4SLinus Torvalds struct inode *inode; 10991da177e4SLinus Torvalds char *name; 11001da177e4SLinus Torvalds int item_len; 11011da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 110257fe60dfSJeff Mahoney struct reiserfs_security_handle security; 11031da177e4SLinus Torvalds int mode = S_IFLNK | S_IRWXUGO; 1104098297b2SJeff Mahoney /* 1105098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas for 1106098297b2SJeff Mahoney * new inode + update of quota for directory owner) 1107098297b2SJeff Mahoney */ 1108bd4c625cSLinus Torvalds int jbegin_count = 1109bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 1110bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb) + 1111bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb)); 11121da177e4SLinus Torvalds 11132e6c97eaSJan Kara retval = dquot_initialize(parent_dir); 11142e6c97eaSJan Kara if (retval) 11152e6c97eaSJan Kara return retval; 1116907f4554SChristoph Hellwig 11171da177e4SLinus Torvalds if (!(inode = new_inode(parent_dir->i_sb))) { 11181da177e4SLinus Torvalds return -ENOMEM; 11191da177e4SLinus Torvalds } 11202e6c97eaSJan Kara retval = new_inode_init(inode, parent_dir, mode); 11212e6c97eaSJan Kara if (retval) { 11222e6c97eaSJan Kara drop_new_inode(inode); 11232e6c97eaSJan Kara return retval; 11242e6c97eaSJan Kara } 11251da177e4SLinus Torvalds 11262a7dba39SEric Paris retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name, 11272a7dba39SEric Paris &security); 112857fe60dfSJeff Mahoney if (retval < 0) { 112957fe60dfSJeff Mahoney drop_new_inode(inode); 113057fe60dfSJeff Mahoney return retval; 113157fe60dfSJeff Mahoney } 113257fe60dfSJeff Mahoney jbegin_count += retval; 113357fe60dfSJeff Mahoney 11341da177e4SLinus Torvalds reiserfs_write_lock(parent_dir->i_sb); 11351da177e4SLinus Torvalds item_len = ROUND_UP(strlen(symname)); 11361da177e4SLinus Torvalds if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) { 11371da177e4SLinus Torvalds retval = -ENAMETOOLONG; 11381da177e4SLinus Torvalds drop_new_inode(inode); 11391da177e4SLinus Torvalds goto out_failed; 11401da177e4SLinus Torvalds } 11411da177e4SLinus Torvalds 1142d739b42bSPekka Enberg name = kmalloc(item_len, GFP_NOFS); 11431da177e4SLinus Torvalds if (!name) { 11441da177e4SLinus Torvalds drop_new_inode(inode); 11451da177e4SLinus Torvalds retval = -ENOMEM; 11461da177e4SLinus Torvalds goto out_failed; 11471da177e4SLinus Torvalds } 11481da177e4SLinus Torvalds memcpy(name, symname, strlen(symname)); 11491da177e4SLinus Torvalds padd_item(name, item_len, strlen(symname)); 11501da177e4SLinus Torvalds 11511da177e4SLinus Torvalds retval = journal_begin(&th, parent_dir->i_sb, jbegin_count); 11521da177e4SLinus Torvalds if (retval) { 11531da177e4SLinus Torvalds drop_new_inode(inode); 1154d739b42bSPekka Enberg kfree(name); 11551da177e4SLinus Torvalds goto out_failed; 11561da177e4SLinus Torvalds } 11571da177e4SLinus Torvalds 1158bd4c625cSLinus Torvalds retval = 1159bd4c625cSLinus Torvalds reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname), 116057fe60dfSJeff Mahoney dentry, inode, &security); 1161d739b42bSPekka Enberg kfree(name); 11621da177e4SLinus Torvalds if (retval) { /* reiserfs_new_inode iputs for us */ 11631da177e4SLinus Torvalds goto out_failed; 11641da177e4SLinus Torvalds } 11651da177e4SLinus Torvalds 11661da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 11671da177e4SLinus Torvalds reiserfs_update_inode_transaction(parent_dir); 11681da177e4SLinus Torvalds 11691da177e4SLinus Torvalds inode->i_op = &reiserfs_symlink_inode_operations; 117021fc61c7SAl Viro inode_nohighmem(inode); 11711da177e4SLinus Torvalds inode->i_mapping->a_ops = &reiserfs_address_space_operations; 11721da177e4SLinus Torvalds 11731da177e4SLinus Torvalds retval = reiserfs_add_entry(&th, parent_dir, dentry->d_name.name, 11741da177e4SLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ ); 11751da177e4SLinus Torvalds if (retval) { 11761da177e4SLinus Torvalds int err; 11776d6b77f1SMiklos Szeredi drop_nlink(inode); 11781da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 117958d85426SJeff Mahoney err = journal_end(&th); 11801da177e4SLinus Torvalds if (err) 11811da177e4SLinus Torvalds retval = err; 1182c1eaa26bSAl Viro unlock_new_inode(inode); 11831da177e4SLinus Torvalds iput(inode); 11841da177e4SLinus Torvalds goto out_failed; 11851da177e4SLinus Torvalds } 11861da177e4SLinus Torvalds 1187*1e2e547aSAl Viro d_instantiate_new(dentry, inode); 118858d85426SJeff Mahoney retval = journal_end(&th); 11891da177e4SLinus Torvalds out_failed: 11901da177e4SLinus Torvalds reiserfs_write_unlock(parent_dir->i_sb); 11911da177e4SLinus Torvalds return retval; 11921da177e4SLinus Torvalds } 11931da177e4SLinus Torvalds 1194bd4c625cSLinus Torvalds static int reiserfs_link(struct dentry *old_dentry, struct inode *dir, 1195bd4c625cSLinus Torvalds struct dentry *dentry) 11961da177e4SLinus Torvalds { 11971da177e4SLinus Torvalds int retval; 11982b0143b5SDavid Howells struct inode *inode = d_inode(old_dentry); 11991da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 1200098297b2SJeff Mahoney /* 1201098297b2SJeff Mahoney * We need blocks for transaction + update of quotas for 1202098297b2SJeff Mahoney * the owners of the directory 1203098297b2SJeff Mahoney */ 1204bd4c625cSLinus Torvalds int jbegin_count = 1205bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 1206bd4c625cSLinus Torvalds 2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); 12071da177e4SLinus Torvalds 12082e6c97eaSJan Kara retval = dquot_initialize(dir); 12092e6c97eaSJan Kara if (retval) 12102e6c97eaSJan Kara return retval; 1211907f4554SChristoph Hellwig 12121da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb); 12131da177e4SLinus Torvalds if (inode->i_nlink >= REISERFS_LINK_MAX) { 1214098297b2SJeff Mahoney /* FIXME: sd_nlink is 32 bit for new files */ 12151da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 12161da177e4SLinus Torvalds return -EMLINK; 12171da177e4SLinus Torvalds } 12181da177e4SLinus Torvalds 12191da177e4SLinus Torvalds /* inc before scheduling so reiserfs_unlink knows we are here */ 1220d8c76e6fSDave Hansen inc_nlink(inode); 12211da177e4SLinus Torvalds 12221da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count); 12231da177e4SLinus Torvalds if (retval) { 12246d6b77f1SMiklos Szeredi drop_nlink(inode); 12251da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 12261da177e4SLinus Torvalds return retval; 12271da177e4SLinus Torvalds } 12281da177e4SLinus Torvalds 12291da177e4SLinus Torvalds /* create new entry */ 1230bd4c625cSLinus Torvalds retval = 1231bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name, 1232bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ ); 12331da177e4SLinus Torvalds 12341da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 12351da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir); 12361da177e4SLinus Torvalds 12371da177e4SLinus Torvalds if (retval) { 12381da177e4SLinus Torvalds int err; 12396d6b77f1SMiklos Szeredi drop_nlink(inode); 124058d85426SJeff Mahoney err = journal_end(&th); 12411da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 12421da177e4SLinus Torvalds return err ? err : retval; 12431da177e4SLinus Torvalds } 12441da177e4SLinus Torvalds 124502027d42SDeepa Dinamani inode->i_ctime = current_time(inode); 12461da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 12471da177e4SLinus Torvalds 12487de9c6eeSAl Viro ihold(inode); 12491da177e4SLinus Torvalds d_instantiate(dentry, inode); 125058d85426SJeff Mahoney retval = journal_end(&th); 12511da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb); 12521da177e4SLinus Torvalds return retval; 12531da177e4SLinus Torvalds } 12541da177e4SLinus Torvalds 12550222e657SJeff Mahoney /* de contains information pointing to an entry which */ 1256bd4c625cSLinus Torvalds static int de_still_valid(const char *name, int len, 1257bd4c625cSLinus Torvalds struct reiserfs_dir_entry *de) 12581da177e4SLinus Torvalds { 12591da177e4SLinus Torvalds struct reiserfs_dir_entry tmp = *de; 12601da177e4SLinus Torvalds 1261098297b2SJeff Mahoney /* recalculate pointer to name and name length */ 12621da177e4SLinus Torvalds set_de_name_and_namelen(&tmp); 1263098297b2SJeff Mahoney /* FIXME: could check more */ 12641da177e4SLinus Torvalds if (tmp.de_namelen != len || memcmp(name, de->de_name, len)) 12651da177e4SLinus Torvalds return 0; 12661da177e4SLinus Torvalds return 1; 12671da177e4SLinus Torvalds } 12681da177e4SLinus Torvalds 1269bd4c625cSLinus Torvalds static int entry_points_to_object(const char *name, int len, 1270bd4c625cSLinus Torvalds struct reiserfs_dir_entry *de, 1271bd4c625cSLinus Torvalds struct inode *inode) 12721da177e4SLinus Torvalds { 12731da177e4SLinus Torvalds if (!de_still_valid(name, len, de)) 12741da177e4SLinus Torvalds return 0; 12751da177e4SLinus Torvalds 12761da177e4SLinus Torvalds if (inode) { 12771da177e4SLinus Torvalds if (!de_visible(de->de_deh + de->de_entry_num)) 1278c3a9c210SJeff Mahoney reiserfs_panic(inode->i_sb, "vs-7042", 1279c3a9c210SJeff Mahoney "entry must be visible"); 12801da177e4SLinus Torvalds return (de->de_objectid == inode->i_ino) ? 1 : 0; 12811da177e4SLinus Torvalds } 12821da177e4SLinus Torvalds 12831da177e4SLinus Torvalds /* this must be added hidden entry */ 12841da177e4SLinus Torvalds if (de_visible(de->de_deh + de->de_entry_num)) 1285c3a9c210SJeff Mahoney reiserfs_panic(NULL, "vs-7043", "entry must be visible"); 12861da177e4SLinus Torvalds 12871da177e4SLinus Torvalds return 1; 12881da177e4SLinus Torvalds } 12891da177e4SLinus Torvalds 12901da177e4SLinus Torvalds /* sets key of objectid the entry has to point to */ 1291bd4c625cSLinus Torvalds static void set_ino_in_dir_entry(struct reiserfs_dir_entry *de, 1292bd4c625cSLinus Torvalds struct reiserfs_key *key) 12931da177e4SLinus Torvalds { 12941da177e4SLinus Torvalds /* JDM These operations are endian safe - both are le */ 12951da177e4SLinus Torvalds de->de_deh[de->de_entry_num].deh_dir_id = key->k_dir_id; 12961da177e4SLinus Torvalds de->de_deh[de->de_entry_num].deh_objectid = key->k_objectid; 12971da177e4SLinus Torvalds } 12981da177e4SLinus Torvalds 12991da177e4SLinus Torvalds /* 13001da177e4SLinus Torvalds * process, that is going to call fix_nodes/do_balance must hold only 13011da177e4SLinus Torvalds * one path. If it holds 2 or more, it can get into endless waiting in 13021da177e4SLinus Torvalds * get_empty_nodes or its clones 13031da177e4SLinus Torvalds */ 13041da177e4SLinus Torvalds static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry, 1305f03b8ad8SMiklos Szeredi struct inode *new_dir, struct dentry *new_dentry, 1306f03b8ad8SMiklos Szeredi unsigned int flags) 13071da177e4SLinus Torvalds { 13081da177e4SLinus Torvalds int retval; 13091da177e4SLinus Torvalds INITIALIZE_PATH(old_entry_path); 13101da177e4SLinus Torvalds INITIALIZE_PATH(new_entry_path); 13111da177e4SLinus Torvalds INITIALIZE_PATH(dot_dot_entry_path); 13121da177e4SLinus Torvalds struct item_head new_entry_ih, old_entry_ih, dot_dot_ih; 13131da177e4SLinus Torvalds struct reiserfs_dir_entry old_de, new_de, dot_dot_de; 13141da177e4SLinus Torvalds struct inode *old_inode, *new_dentry_inode; 13151da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 13161da177e4SLinus Torvalds int jbegin_count; 13171da177e4SLinus Torvalds umode_t old_inode_mode; 13181da177e4SLinus Torvalds unsigned long savelink = 1; 13191da177e4SLinus Torvalds struct timespec ctime; 13201da177e4SLinus Torvalds 1321f03b8ad8SMiklos Szeredi if (flags & ~RENAME_NOREPLACE) 1322f03b8ad8SMiklos Szeredi return -EINVAL; 1323f03b8ad8SMiklos Szeredi 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); 157002027d42SDeepa Dinamani ctime = current_time(old_dir); 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 .listxattr = reiserfs_listxattr, 16541da177e4SLinus Torvalds .permission = reiserfs_permission, 16554e34e719SChristoph Hellwig .get_acl = reiserfs_get_acl, 165647f70d08SChristoph Hellwig .set_acl = reiserfs_set_acl, 16571da177e4SLinus Torvalds }; 16581da177e4SLinus Torvalds 16591da177e4SLinus Torvalds /* 16601da177e4SLinus Torvalds * symlink operations.. same as page_symlink_inode_operations, with xattr 16611da177e4SLinus Torvalds * stuff added 16621da177e4SLinus Torvalds */ 1663c5ef1c42SArjan van de Ven const struct inode_operations reiserfs_symlink_inode_operations = { 16646b255391SAl Viro .get_link = page_get_link, 16651da177e4SLinus Torvalds .setattr = reiserfs_setattr, 16661da177e4SLinus Torvalds .listxattr = reiserfs_listxattr, 16671da177e4SLinus Torvalds .permission = reiserfs_permission, 16681da177e4SLinus Torvalds }; 16691da177e4SLinus Torvalds 16701da177e4SLinus Torvalds /* 16711da177e4SLinus Torvalds * special file operations.. just xattr/acl stuff 16721da177e4SLinus Torvalds */ 1673c5ef1c42SArjan van de Ven const struct inode_operations reiserfs_special_inode_operations = { 16741da177e4SLinus Torvalds .setattr = reiserfs_setattr, 16751da177e4SLinus Torvalds .listxattr = reiserfs_listxattr, 16761da177e4SLinus Torvalds .permission = reiserfs_permission, 16774e34e719SChristoph Hellwig .get_acl = reiserfs_get_acl, 167847f70d08SChristoph Hellwig .set_acl = reiserfs_set_acl, 16791da177e4SLinus Torvalds }; 1680