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 */
bin_search_in_dir_item(struct reiserfs_dir_entry * de,loff_t off)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 */
set_de_item_location(struct reiserfs_dir_entry * de,struct treepath * path)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 */
set_de_name_and_namelen(struct reiserfs_dir_entry * de)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 */
set_de_object_key(struct reiserfs_dir_entry * de)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
store_de_entry_key(struct reiserfs_dir_entry * de)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! */
search_by_entry_key(struct super_block * sb,const struct cpu_key * key,struct treepath * path,struct reiserfs_dir_entry * de)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)--;
135c3754da3SGustavo A. R. Silva break;
1361da177e4SLinus Torvalds
1371da177e4SLinus Torvalds case ITEM_FOUND:
1381da177e4SLinus Torvalds break;
1391da177e4SLinus Torvalds
1401da177e4SLinus Torvalds case IO_ERROR:
1411da177e4SLinus Torvalds return retval;
1421da177e4SLinus Torvalds
1431da177e4SLinus Torvalds default:
1441da177e4SLinus Torvalds pathrelse(path);
1450030b645SJeff Mahoney reiserfs_error(sb, "vs-7002", "no path to here");
1461da177e4SLinus Torvalds return IO_ERROR;
1471da177e4SLinus Torvalds }
1481da177e4SLinus Torvalds
1491da177e4SLinus Torvalds set_de_item_location(de, path);
1501da177e4SLinus Torvalds
1511da177e4SLinus Torvalds #ifdef CONFIG_REISERFS_CHECK
1521da177e4SLinus Torvalds if (!is_direntry_le_ih(de->de_ih) ||
153a228bf8fSJeff Mahoney COMP_SHORT_KEYS(&de->de_ih->ih_key, key)) {
1541da177e4SLinus Torvalds print_block(de->de_bh, 0, -1, -1);
155c3a9c210SJeff Mahoney reiserfs_panic(sb, "vs-7005", "found item %h is not directory "
156c3a9c210SJeff Mahoney "item or does not belong to the same directory "
157c3a9c210SJeff Mahoney "as key %K", de->de_ih, key);
1581da177e4SLinus Torvalds }
1591da177e4SLinus Torvalds #endif /* CONFIG_REISERFS_CHECK */
1601da177e4SLinus Torvalds
161098297b2SJeff Mahoney /*
162098297b2SJeff Mahoney * binary search in directory item by third component of the
163098297b2SJeff Mahoney * key. sets de->de_entry_num of de
164098297b2SJeff Mahoney */
1651da177e4SLinus Torvalds retval = bin_search_in_dir_item(de, cpu_key_k_offset(key));
1661da177e4SLinus Torvalds path->pos_in_item = de->de_entry_num;
1671da177e4SLinus Torvalds if (retval != NAME_NOT_FOUND) {
168098297b2SJeff Mahoney /*
169098297b2SJeff Mahoney * ugly, but rename needs de_bh, de_deh, de_name,
170098297b2SJeff Mahoney * de_namelen, de_objectid set
171098297b2SJeff Mahoney */
1721da177e4SLinus Torvalds set_de_name_and_namelen(de);
1731da177e4SLinus Torvalds set_de_object_key(de);
1741da177e4SLinus Torvalds }
1751da177e4SLinus Torvalds return retval;
1761da177e4SLinus Torvalds }
1771da177e4SLinus Torvalds
1781da177e4SLinus Torvalds /* Keyed 32-bit hash function using TEA in a Davis-Meyer function */
1791da177e4SLinus Torvalds
180098297b2SJeff Mahoney /*
181098297b2SJeff Mahoney * The third component is hashed, and you can choose from more than
182098297b2SJeff Mahoney * one hash function. Per directory hashes are not yet implemented
183098297b2SJeff Mahoney * but are thought about. This function should be moved to hashes.c
184098297b2SJeff Mahoney * Jedi, please do so. -Hans
185098297b2SJeff Mahoney */
get_third_component(struct super_block * s,const char * name,int len)1861da177e4SLinus Torvalds static __u32 get_third_component(struct super_block *s,
1871da177e4SLinus Torvalds const char *name, int len)
1881da177e4SLinus Torvalds {
1891da177e4SLinus Torvalds __u32 res;
1901da177e4SLinus Torvalds
1911da177e4SLinus Torvalds if (!len || (len == 1 && name[0] == '.'))
1921da177e4SLinus Torvalds return DOT_OFFSET;
1931da177e4SLinus Torvalds if (len == 2 && name[0] == '.' && name[1] == '.')
1941da177e4SLinus Torvalds return DOT_DOT_OFFSET;
1951da177e4SLinus Torvalds
1961da177e4SLinus Torvalds res = REISERFS_SB(s)->s_hash_function(name, len);
1971da177e4SLinus Torvalds
198098297b2SJeff Mahoney /* take bits from 7-th to 30-th including both bounds */
1991da177e4SLinus Torvalds res = GET_HASH_VALUE(res);
2001da177e4SLinus Torvalds if (res == 0)
201098297b2SJeff Mahoney /*
202098297b2SJeff Mahoney * needed to have no names before "." and ".." those have hash
203098297b2SJeff Mahoney * value == 0 and generation conters 1 and 2 accordingly
204098297b2SJeff Mahoney */
2051da177e4SLinus Torvalds res = 128;
2061da177e4SLinus Torvalds return res + MAX_GENERATION_NUMBER;
2071da177e4SLinus Torvalds }
2081da177e4SLinus Torvalds
reiserfs_match(struct reiserfs_dir_entry * de,const char * name,int namelen)2091da177e4SLinus Torvalds static int reiserfs_match(struct reiserfs_dir_entry *de,
2101da177e4SLinus Torvalds const char *name, int namelen)
2111da177e4SLinus Torvalds {
2121da177e4SLinus Torvalds int retval = NAME_NOT_FOUND;
2131da177e4SLinus Torvalds
2141da177e4SLinus Torvalds if ((namelen == de->de_namelen) &&
2151da177e4SLinus Torvalds !memcmp(de->de_name, name, de->de_namelen))
216bd4c625cSLinus Torvalds retval =
217bd4c625cSLinus Torvalds (de_visible(de->de_deh + de->de_entry_num) ? NAME_FOUND :
218bd4c625cSLinus Torvalds NAME_FOUND_INVISIBLE);
2191da177e4SLinus Torvalds
2201da177e4SLinus Torvalds return retval;
2211da177e4SLinus Torvalds }
2221da177e4SLinus Torvalds
2231da177e4SLinus Torvalds /* de's de_bh, de_ih, de_deh, de_item_num, de_entry_num are set already */
2241da177e4SLinus Torvalds
2251da177e4SLinus Torvalds /* used when hash collisions exist */
2261da177e4SLinus Torvalds
linear_search_in_dir_item(struct cpu_key * key,struct reiserfs_dir_entry * de,const char * name,int namelen)227bd4c625cSLinus Torvalds static int linear_search_in_dir_item(struct cpu_key *key,
228bd4c625cSLinus Torvalds struct reiserfs_dir_entry *de,
2291da177e4SLinus Torvalds const char *name, int namelen)
2301da177e4SLinus Torvalds {
2311da177e4SLinus Torvalds struct reiserfs_de_head *deh = de->de_deh;
2321da177e4SLinus Torvalds int retval;
2331da177e4SLinus Torvalds int i;
2341da177e4SLinus Torvalds
2351da177e4SLinus Torvalds i = de->de_entry_num;
2361da177e4SLinus Torvalds
2374cf5f7adSJeff Mahoney if (i == ih_entry_count(de->de_ih) ||
238bd4c625cSLinus Torvalds GET_HASH_VALUE(deh_offset(deh + i)) !=
239bd4c625cSLinus Torvalds GET_HASH_VALUE(cpu_key_k_offset(key))) {
2401da177e4SLinus Torvalds i--;
2411da177e4SLinus Torvalds }
2421da177e4SLinus Torvalds
2431da177e4SLinus Torvalds RFALSE(de->de_deh != B_I_DEH(de->de_bh, de->de_ih),
2441da177e4SLinus Torvalds "vs-7010: array of entry headers not found");
2451da177e4SLinus Torvalds
2461da177e4SLinus Torvalds deh += i;
2471da177e4SLinus Torvalds
2481da177e4SLinus Torvalds for (; i >= 0; i--, deh--) {
249098297b2SJeff Mahoney /* hash value does not match, no need to check whole name */
2501da177e4SLinus Torvalds if (GET_HASH_VALUE(deh_offset(deh)) !=
2511da177e4SLinus Torvalds GET_HASH_VALUE(cpu_key_k_offset(key))) {
2521da177e4SLinus Torvalds return NAME_NOT_FOUND;
2531da177e4SLinus Torvalds }
2541da177e4SLinus Torvalds
255098297b2SJeff Mahoney /* mark that this generation number is used */
2561da177e4SLinus Torvalds if (de->de_gen_number_bit_string)
257bd4c625cSLinus Torvalds set_bit(GET_GENERATION_NUMBER(deh_offset(deh)),
2583af1efe8SJeff Mahoney de->de_gen_number_bit_string);
2591da177e4SLinus Torvalds
260098297b2SJeff Mahoney /* calculate pointer to name and namelen */
2611da177e4SLinus Torvalds de->de_entry_num = i;
2621da177e4SLinus Torvalds set_de_name_and_namelen(de);
2631da177e4SLinus Torvalds
264098297b2SJeff Mahoney /*
265098297b2SJeff Mahoney * de's de_name, de_namelen, de_recordlen are set.
266098297b2SJeff Mahoney * Fill the rest.
267098297b2SJeff Mahoney */
268bd4c625cSLinus Torvalds if ((retval =
269bd4c625cSLinus Torvalds reiserfs_match(de, name, namelen)) != NAME_NOT_FOUND) {
2701da177e4SLinus Torvalds
271098297b2SJeff Mahoney /* key of pointed object */
2721da177e4SLinus Torvalds set_de_object_key(de);
2731da177e4SLinus Torvalds
2741da177e4SLinus Torvalds store_de_entry_key(de);
2751da177e4SLinus Torvalds
276098297b2SJeff Mahoney /* retval can be NAME_FOUND or NAME_FOUND_INVISIBLE */
2771da177e4SLinus Torvalds return retval;
2781da177e4SLinus Torvalds }
2791da177e4SLinus Torvalds }
2801da177e4SLinus Torvalds
2811da177e4SLinus Torvalds if (GET_GENERATION_NUMBER(le_ih_k_offset(de->de_ih)) == 0)
282098297b2SJeff Mahoney /*
283098297b2SJeff Mahoney * we have reached left most entry in the node. In common we
284098297b2SJeff Mahoney * have to go to the left neighbor, but if generation counter
285098297b2SJeff Mahoney * is 0 already, we know for sure, that there is no name with
286098297b2SJeff Mahoney * the same hash value
287098297b2SJeff Mahoney */
288098297b2SJeff Mahoney /*
289098297b2SJeff Mahoney * FIXME: this work correctly only because hash value can not
290098297b2SJeff Mahoney * be 0. Btw, in case of Yura's hash it is probably possible,
291098297b2SJeff Mahoney * so, this is a bug
292098297b2SJeff Mahoney */
2931da177e4SLinus Torvalds return NAME_NOT_FOUND;
2941da177e4SLinus Torvalds
2951da177e4SLinus Torvalds RFALSE(de->de_item_num,
2961da177e4SLinus Torvalds "vs-7015: two diritems of the same directory in one node?");
2971da177e4SLinus Torvalds
2981da177e4SLinus Torvalds return GOTO_PREVIOUS_ITEM;
2991da177e4SLinus Torvalds }
3001da177e4SLinus Torvalds
301098297b2SJeff Mahoney /*
302098297b2SJeff Mahoney * may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND
303098297b2SJeff Mahoney * FIXME: should add something like IOERROR
304098297b2SJeff Mahoney */
reiserfs_find_entry(struct inode * dir,const char * name,int namelen,struct treepath * path_to_entry,struct reiserfs_dir_entry * de)3051da177e4SLinus Torvalds static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen,
306fec6d055SJosef "Jeff" Sipek struct treepath *path_to_entry,
307bd4c625cSLinus Torvalds struct reiserfs_dir_entry *de)
3081da177e4SLinus Torvalds {
3091da177e4SLinus Torvalds struct cpu_key key_to_search;
3101da177e4SLinus Torvalds int retval;
3111da177e4SLinus Torvalds
3121da177e4SLinus Torvalds if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize))
3131da177e4SLinus Torvalds return NAME_NOT_FOUND;
3141da177e4SLinus Torvalds
3151da177e4SLinus Torvalds /* we will search for this key in the tree */
3161da177e4SLinus Torvalds make_cpu_key(&key_to_search, dir,
317bd4c625cSLinus Torvalds get_third_component(dir->i_sb, name, namelen),
318bd4c625cSLinus Torvalds TYPE_DIRENTRY, 3);
3191da177e4SLinus Torvalds
3201da177e4SLinus Torvalds while (1) {
321bd4c625cSLinus Torvalds retval =
322bd4c625cSLinus Torvalds search_by_entry_key(dir->i_sb, &key_to_search,
323bd4c625cSLinus Torvalds path_to_entry, de);
3241da177e4SLinus Torvalds if (retval == IO_ERROR) {
3250030b645SJeff Mahoney reiserfs_error(dir->i_sb, "zam-7001", "io error");
3261da177e4SLinus Torvalds return IO_ERROR;
3271da177e4SLinus Torvalds }
3281da177e4SLinus Torvalds
3291da177e4SLinus Torvalds /* compare names for all entries having given hash value */
330bd4c625cSLinus Torvalds retval =
331bd4c625cSLinus Torvalds linear_search_in_dir_item(&key_to_search, de, name,
332bd4c625cSLinus Torvalds namelen);
333098297b2SJeff Mahoney /*
334098297b2SJeff Mahoney * there is no need to scan directory anymore.
335098297b2SJeff Mahoney * Given entry found or does not exist
336098297b2SJeff Mahoney */
3371da177e4SLinus Torvalds if (retval != GOTO_PREVIOUS_ITEM) {
3381da177e4SLinus Torvalds path_to_entry->pos_in_item = de->de_entry_num;
3391da177e4SLinus Torvalds return retval;
3401da177e4SLinus Torvalds }
3411da177e4SLinus Torvalds
342098297b2SJeff Mahoney /*
343098297b2SJeff Mahoney * there is left neighboring item of this directory
344098297b2SJeff Mahoney * and given entry can be there
345098297b2SJeff Mahoney */
346bd4c625cSLinus Torvalds set_cpu_key_k_offset(&key_to_search,
347bd4c625cSLinus Torvalds le_ih_k_offset(de->de_ih) - 1);
3481da177e4SLinus Torvalds pathrelse(path_to_entry);
3491da177e4SLinus Torvalds
3501da177e4SLinus Torvalds } /* while (1) */
3511da177e4SLinus Torvalds }
3521da177e4SLinus Torvalds
reiserfs_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)353bd4c625cSLinus Torvalds static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
35400cd8dd3SAl Viro unsigned int flags)
3551da177e4SLinus Torvalds {
3561da177e4SLinus Torvalds int retval;
3571da177e4SLinus Torvalds struct inode *inode = NULL;
3581da177e4SLinus Torvalds struct reiserfs_dir_entry de;
3591da177e4SLinus Torvalds INITIALIZE_PATH(path_to_entry);
3601da177e4SLinus Torvalds
3611da177e4SLinus Torvalds if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len)
3621da177e4SLinus Torvalds return ERR_PTR(-ENAMETOOLONG);
3631da177e4SLinus Torvalds
364278f6679SJeff Mahoney reiserfs_write_lock(dir->i_sb);
365b1c839bbSFrederic Weisbecker
3661da177e4SLinus Torvalds de.de_gen_number_bit_string = NULL;
367bd4c625cSLinus Torvalds retval =
368bd4c625cSLinus Torvalds reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
369bd4c625cSLinus Torvalds &path_to_entry, &de);
3701da177e4SLinus Torvalds pathrelse(&path_to_entry);
3711da177e4SLinus Torvalds if (retval == NAME_FOUND) {
372677c9b2eSJeff Mahoney inode = reiserfs_iget(dir->i_sb,
373a228bf8fSJeff Mahoney (struct cpu_key *)&de.de_dir_id);
3741da177e4SLinus Torvalds if (!inode || IS_ERR(inode)) {
375278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb);
3761da177e4SLinus Torvalds return ERR_PTR(-EACCES);
3771da177e4SLinus Torvalds }
3781da177e4SLinus Torvalds
379098297b2SJeff Mahoney /*
380098297b2SJeff Mahoney * Propagate the private flag so we know we're
381d9f892b9SChristian Brauner * in the priv tree. Also clear xattr support
38260e4cf67SJeff Mahoney * since we don't have xattrs on xattr files.
383098297b2SJeff Mahoney */
384d9f892b9SChristian Brauner if (IS_PRIVATE(dir))
385d9f892b9SChristian Brauner reiserfs_init_priv_inode(inode);
3861da177e4SLinus Torvalds }
387278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb);
3881da177e4SLinus Torvalds if (retval == IO_ERROR) {
3891da177e4SLinus Torvalds return ERR_PTR(-EIO);
3901da177e4SLinus Torvalds }
3911da177e4SLinus Torvalds
3921da177e4SLinus Torvalds return d_splice_alias(inode, dentry);
3931da177e4SLinus Torvalds }
3941da177e4SLinus Torvalds
3951da177e4SLinus Torvalds /*
396098297b2SJeff Mahoney * looks up the dentry of the parent directory for child.
397098297b2SJeff Mahoney * taken from ext2_get_parent
3981da177e4SLinus Torvalds */
reiserfs_get_parent(struct dentry * child)3991da177e4SLinus Torvalds struct dentry *reiserfs_get_parent(struct dentry *child)
4001da177e4SLinus Torvalds {
4011da177e4SLinus Torvalds int retval;
4021da177e4SLinus Torvalds struct inode *inode = NULL;
4031da177e4SLinus Torvalds struct reiserfs_dir_entry de;
4041da177e4SLinus Torvalds INITIALIZE_PATH(path_to_entry);
4052b0143b5SDavid Howells struct inode *dir = d_inode(child);
4061da177e4SLinus Torvalds
4071da177e4SLinus Torvalds if (dir->i_nlink == 0) {
4081da177e4SLinus Torvalds return ERR_PTR(-ENOENT);
4091da177e4SLinus Torvalds }
4101da177e4SLinus Torvalds de.de_gen_number_bit_string = NULL;
4111da177e4SLinus Torvalds
4121da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb);
4131da177e4SLinus Torvalds retval = reiserfs_find_entry(dir, "..", 2, &path_to_entry, &de);
4141da177e4SLinus Torvalds pathrelse(&path_to_entry);
4151da177e4SLinus Torvalds if (retval != NAME_FOUND) {
4161da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb);
4171da177e4SLinus Torvalds return ERR_PTR(-ENOENT);
4181da177e4SLinus Torvalds }
419a228bf8fSJeff Mahoney inode = reiserfs_iget(dir->i_sb, (struct cpu_key *)&de.de_dir_id);
4201da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb);
4211da177e4SLinus Torvalds
42244003728SChristoph Hellwig return d_obtain_alias(inode);
4231da177e4SLinus Torvalds }
4241da177e4SLinus Torvalds
4251da177e4SLinus Torvalds /* add entry to the directory (entry can be hidden).
4261da177e4SLinus Torvalds
4271da177e4SLinus Torvalds insert definition of when hidden directories are used here -Hans
4281da177e4SLinus Torvalds
4291da177e4SLinus Torvalds Does not mark dir inode dirty, do it after successesfull call to it */
4301da177e4SLinus Torvalds
reiserfs_add_entry(struct reiserfs_transaction_handle * th,struct inode * dir,const char * name,int namelen,struct inode * inode,int visible)431bd4c625cSLinus Torvalds static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
432bd4c625cSLinus Torvalds struct inode *dir, const char *name, int namelen,
433bd4c625cSLinus Torvalds struct inode *inode, int visible)
4341da177e4SLinus Torvalds {
4351da177e4SLinus Torvalds struct cpu_key entry_key;
4361da177e4SLinus Torvalds struct reiserfs_de_head *deh;
4371da177e4SLinus Torvalds INITIALIZE_PATH(path);
4381da177e4SLinus Torvalds struct reiserfs_dir_entry de;
4393af1efe8SJeff Mahoney DECLARE_BITMAP(bit_string, MAX_GENERATION_NUMBER + 1);
4401da177e4SLinus Torvalds int gen_number;
441098297b2SJeff Mahoney
442098297b2SJeff Mahoney /*
443098297b2SJeff Mahoney * 48 bytes now and we avoid kmalloc if we
444098297b2SJeff Mahoney * create file with short name
445098297b2SJeff Mahoney */
446098297b2SJeff Mahoney char small_buf[32 + DEH_SIZE];
447098297b2SJeff Mahoney
4481da177e4SLinus Torvalds char *buffer;
4491da177e4SLinus Torvalds int buflen, paste_size;
4501da177e4SLinus Torvalds int retval;
4511da177e4SLinus Torvalds
4521da177e4SLinus Torvalds BUG_ON(!th->t_trans_id);
4531da177e4SLinus Torvalds
4541da177e4SLinus Torvalds /* cannot allow items to be added into a busy deleted directory */
4551da177e4SLinus Torvalds if (!namelen)
4561da177e4SLinus Torvalds return -EINVAL;
4571da177e4SLinus Torvalds
4581da177e4SLinus Torvalds if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize))
4591da177e4SLinus Torvalds return -ENAMETOOLONG;
4601da177e4SLinus Torvalds
4611da177e4SLinus Torvalds /* each entry has unique key. compose it */
4621da177e4SLinus Torvalds make_cpu_key(&entry_key, dir,
463bd4c625cSLinus Torvalds get_third_component(dir->i_sb, name, namelen),
464bd4c625cSLinus Torvalds TYPE_DIRENTRY, 3);
4651da177e4SLinus Torvalds
4661da177e4SLinus Torvalds /* get memory for composing the entry */
4671da177e4SLinus Torvalds buflen = DEH_SIZE + ROUND_UP(namelen);
4681da177e4SLinus Torvalds if (buflen > sizeof(small_buf)) {
469d739b42bSPekka Enberg buffer = kmalloc(buflen, GFP_NOFS);
4709dce07f1SAl Viro if (!buffer)
4711da177e4SLinus Torvalds return -ENOMEM;
4721da177e4SLinus Torvalds } else
4731da177e4SLinus Torvalds buffer = small_buf;
4741da177e4SLinus Torvalds
475bd4c625cSLinus Torvalds paste_size =
476bd4c625cSLinus Torvalds (get_inode_sd_version(dir) ==
477bd4c625cSLinus Torvalds STAT_DATA_V1) ? (DEH_SIZE + namelen) : buflen;
4781da177e4SLinus Torvalds
479098297b2SJeff Mahoney /*
480098297b2SJeff Mahoney * fill buffer : directory entry head, name[, dir objectid | ,
481098297b2SJeff Mahoney * stat data | ,stat data, dir objectid ]
482098297b2SJeff Mahoney */
4831da177e4SLinus Torvalds deh = (struct reiserfs_de_head *)buffer;
4841da177e4SLinus Torvalds deh->deh_location = 0; /* JDM Endian safe if 0 */
4851da177e4SLinus Torvalds put_deh_offset(deh, cpu_key_k_offset(&entry_key));
4861da177e4SLinus Torvalds deh->deh_state = 0; /* JDM Endian safe if 0 */
4871da177e4SLinus Torvalds /* put key (ino analog) to de */
488098297b2SJeff Mahoney
489098297b2SJeff Mahoney /* safe: k_dir_id is le */
490098297b2SJeff Mahoney deh->deh_dir_id = INODE_PKEY(inode)->k_dir_id;
491098297b2SJeff Mahoney /* safe: k_objectid is le */
492098297b2SJeff Mahoney deh->deh_objectid = INODE_PKEY(inode)->k_objectid;
4931da177e4SLinus Torvalds
4941da177e4SLinus Torvalds /* copy name */
4951da177e4SLinus Torvalds memcpy((char *)(deh + 1), name, namelen);
4961da177e4SLinus Torvalds /* padd by 0s to the 4 byte boundary */
4971da177e4SLinus Torvalds padd_item((char *)(deh + 1), ROUND_UP(namelen), namelen);
4981da177e4SLinus Torvalds
499098297b2SJeff Mahoney /*
500098297b2SJeff Mahoney * entry is ready to be pasted into tree, set 'visibility'
501098297b2SJeff Mahoney * and 'stat data in entry' attributes
502098297b2SJeff Mahoney */
5031da177e4SLinus Torvalds mark_de_without_sd(deh);
5041da177e4SLinus Torvalds visible ? mark_de_visible(deh) : mark_de_hidden(deh);
5051da177e4SLinus Torvalds
5061da177e4SLinus Torvalds /* find the proper place for the new entry */
5071da177e4SLinus Torvalds memset(bit_string, 0, sizeof(bit_string));
5083af1efe8SJeff Mahoney de.de_gen_number_bit_string = bit_string;
5091da177e4SLinus Torvalds retval = reiserfs_find_entry(dir, name, namelen, &path, &de);
5101da177e4SLinus Torvalds if (retval != NAME_NOT_FOUND) {
5111da177e4SLinus Torvalds if (buffer != small_buf)
512d739b42bSPekka Enberg kfree(buffer);
5131da177e4SLinus Torvalds pathrelse(&path);
5141da177e4SLinus Torvalds
5151da177e4SLinus Torvalds if (retval == IO_ERROR) {
5161da177e4SLinus Torvalds return -EIO;
5171da177e4SLinus Torvalds }
5181da177e4SLinus Torvalds
5191da177e4SLinus Torvalds if (retval != NAME_FOUND) {
5200030b645SJeff Mahoney reiserfs_error(dir->i_sb, "zam-7002",
52145b03d5eSJeff Mahoney "reiserfs_find_entry() returned "
52245b03d5eSJeff Mahoney "unexpected value (%d)", retval);
5231da177e4SLinus Torvalds }
5241da177e4SLinus Torvalds
5251da177e4SLinus Torvalds return -EEXIST;
5261da177e4SLinus Torvalds }
5271da177e4SLinus Torvalds
528bd4c625cSLinus Torvalds gen_number =
5293af1efe8SJeff Mahoney find_first_zero_bit(bit_string,
530bd4c625cSLinus Torvalds MAX_GENERATION_NUMBER + 1);
5311da177e4SLinus Torvalds if (gen_number > MAX_GENERATION_NUMBER) {
5321da177e4SLinus Torvalds /* there is no free generation number */
53345b03d5eSJeff Mahoney reiserfs_warning(dir->i_sb, "reiserfs-7010",
53445b03d5eSJeff Mahoney "Congratulations! we have got hash function "
53545b03d5eSJeff Mahoney "screwed up");
5361da177e4SLinus Torvalds if (buffer != small_buf)
537d739b42bSPekka Enberg kfree(buffer);
5381da177e4SLinus Torvalds pathrelse(&path);
5391da177e4SLinus Torvalds return -EBUSY;
5401da177e4SLinus Torvalds }
5411da177e4SLinus Torvalds /* adjust offset of directory enrty */
5421da177e4SLinus Torvalds put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number));
5431da177e4SLinus Torvalds set_cpu_key_k_offset(&entry_key, deh_offset(deh));
5441da177e4SLinus Torvalds
5451da177e4SLinus Torvalds /* update max-hash-collisions counter in reiserfs_sb_info */
5461da177e4SLinus Torvalds PROC_INFO_MAX(th->t_super, max_hash_collisions, gen_number);
5471da177e4SLinus Torvalds
548098297b2SJeff Mahoney /* we need to re-search for the insertion point */
549098297b2SJeff Mahoney if (gen_number != 0) {
550bd4c625cSLinus Torvalds if (search_by_entry_key(dir->i_sb, &entry_key, &path, &de) !=
551bd4c625cSLinus Torvalds NAME_NOT_FOUND) {
55245b03d5eSJeff Mahoney reiserfs_warning(dir->i_sb, "vs-7032",
55345b03d5eSJeff Mahoney "entry with this key (%K) already "
55445b03d5eSJeff Mahoney "exists", &entry_key);
5551da177e4SLinus Torvalds
5561da177e4SLinus Torvalds if (buffer != small_buf)
557d739b42bSPekka Enberg kfree(buffer);
5581da177e4SLinus Torvalds pathrelse(&path);
5591da177e4SLinus Torvalds return -EBUSY;
5601da177e4SLinus Torvalds }
5611da177e4SLinus Torvalds }
5621da177e4SLinus Torvalds
5631da177e4SLinus Torvalds /* perform the insertion of the entry that we have prepared */
564bd4c625cSLinus Torvalds retval =
565bd4c625cSLinus Torvalds reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer,
566bd4c625cSLinus Torvalds paste_size);
5671da177e4SLinus Torvalds if (buffer != small_buf)
568d739b42bSPekka Enberg kfree(buffer);
5691da177e4SLinus Torvalds if (retval) {
5701da177e4SLinus Torvalds reiserfs_check_path(&path);
5711da177e4SLinus Torvalds return retval;
5721da177e4SLinus Torvalds }
5731da177e4SLinus Torvalds
5741da177e4SLinus Torvalds dir->i_size += paste_size;
575ae834901SJeff Layton dir->i_mtime = inode_set_ctime_current(dir);
5761da177e4SLinus Torvalds if (!S_ISDIR(inode->i_mode) && visible)
577098297b2SJeff Mahoney /* reiserfs_mkdir or reiserfs_rename will do that by itself */
5781da177e4SLinus Torvalds reiserfs_update_sd(th, dir);
5791da177e4SLinus Torvalds
5801da177e4SLinus Torvalds reiserfs_check_path(&path);
5811da177e4SLinus Torvalds return 0;
5821da177e4SLinus Torvalds }
5831da177e4SLinus Torvalds
584098297b2SJeff Mahoney /*
585098297b2SJeff Mahoney * quota utility function, call if you've had to abort after calling
586098297b2SJeff Mahoney * new_inode_init, and have not called reiserfs_new_inode yet.
587098297b2SJeff Mahoney * This should only be called on inodes that do not have stat data
588098297b2SJeff Mahoney * inserted into the tree yet.
5891da177e4SLinus Torvalds */
drop_new_inode(struct inode * inode)590bd4c625cSLinus Torvalds static int drop_new_inode(struct inode *inode)
591bd4c625cSLinus Torvalds {
5929f754758SChristoph Hellwig dquot_drop(inode);
5931da177e4SLinus Torvalds make_bad_inode(inode);
5941da177e4SLinus Torvalds inode->i_flags |= S_NOQUOTA;
5951da177e4SLinus Torvalds iput(inode);
5961da177e4SLinus Torvalds return 0;
5971da177e4SLinus Torvalds }
5981da177e4SLinus Torvalds
599098297b2SJeff Mahoney /*
600098297b2SJeff Mahoney * utility function that does setup for reiserfs_new_inode.
601098297b2SJeff Mahoney * dquot_initialize needs lots of credits so it's better to have it
602098297b2SJeff Mahoney * outside of a transaction, so we had to pull some bits of
603098297b2SJeff Mahoney * reiserfs_new_inode out into this func.
6041da177e4SLinus Torvalds */
new_inode_init(struct inode * inode,struct inode * dir,umode_t mode)6058e071892SAl Viro static int new_inode_init(struct inode *inode, struct inode *dir, umode_t mode)
606bd4c625cSLinus Torvalds {
607098297b2SJeff Mahoney /*
608098297b2SJeff Mahoney * Make inode invalid - just in case we are going to drop it before
609098297b2SJeff Mahoney * the initialization happens
610098297b2SJeff Mahoney */
6111b0a74d1SJan Kara INODE_PKEY(inode)->k_objectid = 0;
612098297b2SJeff Mahoney
613098297b2SJeff Mahoney /*
614098297b2SJeff Mahoney * the quota init calls have to know who to charge the quota to, so
615098297b2SJeff Mahoney * we have to set uid and gid here
61604b7ed0dSDmitry Monakhov */
617f2d40141SChristian Brauner inode_init_owner(&nop_mnt_idmap, inode, dir, mode);
6182e6c97eaSJan Kara return dquot_initialize(inode);
6191da177e4SLinus Torvalds }
6201da177e4SLinus Torvalds
reiserfs_create(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,bool excl)6216c960e68SChristian Brauner static int reiserfs_create(struct mnt_idmap *idmap, struct inode *dir,
622549c7297SChristian Brauner struct dentry *dentry, umode_t mode, bool excl)
6231da177e4SLinus Torvalds {
6241da177e4SLinus Torvalds int retval;
6251da177e4SLinus Torvalds struct inode *inode;
626098297b2SJeff Mahoney /*
627098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas
628098297b2SJeff Mahoney * for new inode + update of quota for directory owner)
629098297b2SJeff Mahoney */
630bd4c625cSLinus Torvalds int jbegin_count =
631bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 2 +
632bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
633bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
6341da177e4SLinus Torvalds struct reiserfs_transaction_handle th;
63557fe60dfSJeff Mahoney struct reiserfs_security_handle security;
6361da177e4SLinus Torvalds
6372e6c97eaSJan Kara retval = dquot_initialize(dir);
6382e6c97eaSJan Kara if (retval)
6392e6c97eaSJan Kara return retval;
640907f4554SChristoph Hellwig
6411da177e4SLinus Torvalds if (!(inode = new_inode(dir->i_sb))) {
6421da177e4SLinus Torvalds return -ENOMEM;
6431da177e4SLinus Torvalds }
6442e6c97eaSJan Kara retval = new_inode_init(inode, dir, mode);
6452e6c97eaSJan Kara if (retval) {
6462e6c97eaSJan Kara drop_new_inode(inode);
6472e6c97eaSJan Kara return retval;
6482e6c97eaSJan Kara }
6491da177e4SLinus Torvalds
6500ab2621eSJeff Mahoney jbegin_count += reiserfs_cache_default_acl(dir);
6512a7dba39SEric Paris retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
65257fe60dfSJeff Mahoney if (retval < 0) {
65357fe60dfSJeff Mahoney drop_new_inode(inode);
65457fe60dfSJeff Mahoney return retval;
65557fe60dfSJeff Mahoney }
65657fe60dfSJeff Mahoney jbegin_count += retval;
6571da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb);
6581da177e4SLinus Torvalds
6591da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count);
6601da177e4SLinus Torvalds if (retval) {
6611da177e4SLinus Torvalds drop_new_inode(inode);
6621da177e4SLinus Torvalds goto out_failed;
6631da177e4SLinus Torvalds }
6641da177e4SLinus Torvalds
665bd4c625cSLinus Torvalds retval =
666bd4c625cSLinus Torvalds reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
66757fe60dfSJeff Mahoney inode, &security);
6681da177e4SLinus Torvalds if (retval)
6691da177e4SLinus Torvalds goto out_failed;
6701da177e4SLinus Torvalds
6711da177e4SLinus Torvalds inode->i_op = &reiserfs_file_inode_operations;
6721da177e4SLinus Torvalds inode->i_fop = &reiserfs_file_operations;
6731da177e4SLinus Torvalds inode->i_mapping->a_ops = &reiserfs_address_space_operations;
6741da177e4SLinus Torvalds
675bd4c625cSLinus Torvalds retval =
676bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name,
677bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ );
6781da177e4SLinus Torvalds if (retval) {
6791da177e4SLinus Torvalds int err;
6806d6b77f1SMiklos Szeredi drop_nlink(inode);
6811da177e4SLinus Torvalds reiserfs_update_sd(&th, inode);
68258d85426SJeff Mahoney err = journal_end(&th);
6831da177e4SLinus Torvalds if (err)
6841da177e4SLinus Torvalds retval = err;
685c1eaa26bSAl Viro unlock_new_inode(inode);
6861da177e4SLinus Torvalds iput(inode);
6871da177e4SLinus Torvalds goto out_failed;
6881da177e4SLinus Torvalds }
6891da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode);
6901da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir);
6911da177e4SLinus Torvalds
6921e2e547aSAl Viro d_instantiate_new(dentry, inode);
69358d85426SJeff Mahoney retval = journal_end(&th);
6941da177e4SLinus Torvalds
6951da177e4SLinus Torvalds out_failed:
6961da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb);
697572302afSRoberto Sassu reiserfs_security_free(&security);
6981da177e4SLinus Torvalds return retval;
6991da177e4SLinus Torvalds }
7001da177e4SLinus Torvalds
reiserfs_mknod(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,dev_t rdev)7015ebb29beSChristian Brauner static int reiserfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
702549c7297SChristian Brauner struct dentry *dentry, umode_t mode, dev_t rdev)
7031da177e4SLinus Torvalds {
7041da177e4SLinus Torvalds int retval;
7051da177e4SLinus Torvalds struct inode *inode;
7061da177e4SLinus Torvalds struct reiserfs_transaction_handle th;
70757fe60dfSJeff Mahoney struct reiserfs_security_handle security;
708098297b2SJeff Mahoney /*
709098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas
710098297b2SJeff Mahoney * for new inode + update of quota for directory owner)
711098297b2SJeff Mahoney */
712bd4c625cSLinus Torvalds int jbegin_count =
713bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 +
714bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
715bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
7161da177e4SLinus Torvalds
7172e6c97eaSJan Kara retval = dquot_initialize(dir);
7182e6c97eaSJan Kara if (retval)
7192e6c97eaSJan Kara return retval;
720907f4554SChristoph Hellwig
7211da177e4SLinus Torvalds if (!(inode = new_inode(dir->i_sb))) {
7221da177e4SLinus Torvalds return -ENOMEM;
7231da177e4SLinus Torvalds }
7242e6c97eaSJan Kara retval = new_inode_init(inode, dir, mode);
7252e6c97eaSJan Kara if (retval) {
7262e6c97eaSJan Kara drop_new_inode(inode);
7272e6c97eaSJan Kara return retval;
7282e6c97eaSJan Kara }
7291da177e4SLinus Torvalds
7300ab2621eSJeff Mahoney jbegin_count += reiserfs_cache_default_acl(dir);
7312a7dba39SEric Paris retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
73257fe60dfSJeff Mahoney if (retval < 0) {
73357fe60dfSJeff Mahoney drop_new_inode(inode);
73457fe60dfSJeff Mahoney return retval;
73557fe60dfSJeff Mahoney }
73657fe60dfSJeff Mahoney jbegin_count += retval;
7371da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb);
7381da177e4SLinus Torvalds
7391da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count);
7401da177e4SLinus Torvalds if (retval) {
7411da177e4SLinus Torvalds drop_new_inode(inode);
7421da177e4SLinus Torvalds goto out_failed;
7431da177e4SLinus Torvalds }
7441da177e4SLinus Torvalds
745bd4c625cSLinus Torvalds retval =
746bd4c625cSLinus Torvalds reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
74757fe60dfSJeff Mahoney inode, &security);
7481da177e4SLinus Torvalds if (retval) {
7491da177e4SLinus Torvalds goto out_failed;
7501da177e4SLinus Torvalds }
7511da177e4SLinus Torvalds
7521da177e4SLinus Torvalds inode->i_op = &reiserfs_special_inode_operations;
7531da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, rdev);
7541da177e4SLinus Torvalds
755098297b2SJeff Mahoney /* FIXME: needed for block and char devices only */
7561da177e4SLinus Torvalds reiserfs_update_sd(&th, inode);
7571da177e4SLinus Torvalds
7581da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode);
7591da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir);
7601da177e4SLinus Torvalds
761bd4c625cSLinus Torvalds retval =
762bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name,
763bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ );
7641da177e4SLinus Torvalds if (retval) {
7651da177e4SLinus Torvalds int err;
7666d6b77f1SMiklos Szeredi drop_nlink(inode);
7671da177e4SLinus Torvalds reiserfs_update_sd(&th, inode);
76858d85426SJeff Mahoney err = journal_end(&th);
7691da177e4SLinus Torvalds if (err)
7701da177e4SLinus Torvalds retval = err;
771c1eaa26bSAl Viro unlock_new_inode(inode);
7721da177e4SLinus Torvalds iput(inode);
7731da177e4SLinus Torvalds goto out_failed;
7741da177e4SLinus Torvalds }
7751da177e4SLinus Torvalds
7761e2e547aSAl Viro d_instantiate_new(dentry, inode);
77758d85426SJeff Mahoney retval = journal_end(&th);
7781da177e4SLinus Torvalds
7791da177e4SLinus Torvalds out_failed:
7801da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb);
781572302afSRoberto Sassu reiserfs_security_free(&security);
7821da177e4SLinus Torvalds return retval;
7831da177e4SLinus Torvalds }
7841da177e4SLinus Torvalds
reiserfs_mkdir(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode)785c54bd91eSChristian Brauner static int reiserfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
786549c7297SChristian Brauner struct dentry *dentry, umode_t mode)
7871da177e4SLinus Torvalds {
7881da177e4SLinus Torvalds int retval;
7891da177e4SLinus Torvalds struct inode *inode;
7901da177e4SLinus Torvalds struct reiserfs_transaction_handle th;
79157fe60dfSJeff Mahoney struct reiserfs_security_handle security;
792098297b2SJeff Mahoney /*
793098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas
794098297b2SJeff Mahoney * for new inode + update of quota for directory owner)
795098297b2SJeff Mahoney */
796bd4c625cSLinus Torvalds int jbegin_count =
797bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 +
798bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
799bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
8001da177e4SLinus Torvalds
8012e6c97eaSJan Kara retval = dquot_initialize(dir);
8022e6c97eaSJan Kara if (retval)
8032e6c97eaSJan Kara return retval;
804907f4554SChristoph Hellwig
8051da177e4SLinus Torvalds #ifdef DISPLACE_NEW_PACKING_LOCALITIES
806098297b2SJeff Mahoney /*
807098297b2SJeff Mahoney * set flag that new packing locality created and new blocks
808098297b2SJeff Mahoney * for the content of that directory are not displaced yet
809098297b2SJeff Mahoney */
8101da177e4SLinus Torvalds REISERFS_I(dir)->new_packing_locality = 1;
8111da177e4SLinus Torvalds #endif
8121da177e4SLinus Torvalds mode = S_IFDIR | mode;
8131da177e4SLinus Torvalds if (!(inode = new_inode(dir->i_sb))) {
8141da177e4SLinus Torvalds return -ENOMEM;
8151da177e4SLinus Torvalds }
8162e6c97eaSJan Kara retval = new_inode_init(inode, dir, mode);
8172e6c97eaSJan Kara if (retval) {
8182e6c97eaSJan Kara drop_new_inode(inode);
8192e6c97eaSJan Kara return retval;
8202e6c97eaSJan Kara }
8211da177e4SLinus Torvalds
8220ab2621eSJeff Mahoney jbegin_count += reiserfs_cache_default_acl(dir);
8232a7dba39SEric Paris retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
82457fe60dfSJeff Mahoney if (retval < 0) {
82557fe60dfSJeff Mahoney drop_new_inode(inode);
82657fe60dfSJeff Mahoney return retval;
82757fe60dfSJeff Mahoney }
82857fe60dfSJeff Mahoney jbegin_count += retval;
829278f6679SJeff Mahoney reiserfs_write_lock(dir->i_sb);
8301da177e4SLinus Torvalds
8311da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count);
8321da177e4SLinus Torvalds if (retval) {
8331da177e4SLinus Torvalds drop_new_inode(inode);
8341da177e4SLinus Torvalds goto out_failed;
8351da177e4SLinus Torvalds }
8361da177e4SLinus Torvalds
837098297b2SJeff Mahoney /*
838098297b2SJeff Mahoney * inc the link count now, so another writer doesn't overflow
839098297b2SJeff Mahoney * it while we sleep later on.
8401da177e4SLinus Torvalds */
8411da177e4SLinus Torvalds INC_DIR_INODE_NLINK(dir)
8421da177e4SLinus Torvalds
8431da177e4SLinus Torvalds retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */,
8441da177e4SLinus Torvalds old_format_only(dir->i_sb) ?
8451da177e4SLinus Torvalds EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
84657fe60dfSJeff Mahoney dentry, inode, &security);
8471da177e4SLinus Torvalds if (retval) {
84899890a3bSAl Viro DEC_DIR_INODE_NLINK(dir)
8491da177e4SLinus Torvalds goto out_failed;
8501da177e4SLinus Torvalds }
8511da177e4SLinus Torvalds
8521da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode);
8531da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir);
8541da177e4SLinus Torvalds
8551da177e4SLinus Torvalds inode->i_op = &reiserfs_dir_inode_operations;
8561da177e4SLinus Torvalds inode->i_fop = &reiserfs_dir_operations;
8571da177e4SLinus Torvalds
858098297b2SJeff Mahoney /* note, _this_ add_entry will not update dir's stat data */
859bd4c625cSLinus Torvalds retval =
860bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name,
861bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ );
8621da177e4SLinus Torvalds if (retval) {
8631da177e4SLinus Torvalds int err;
8646d6b77f1SMiklos Szeredi clear_nlink(inode);
8651da177e4SLinus Torvalds DEC_DIR_INODE_NLINK(dir);
8661da177e4SLinus Torvalds reiserfs_update_sd(&th, inode);
86758d85426SJeff Mahoney err = journal_end(&th);
8681da177e4SLinus Torvalds if (err)
8691da177e4SLinus Torvalds retval = err;
870c1eaa26bSAl Viro unlock_new_inode(inode);
8711da177e4SLinus Torvalds iput(inode);
8721da177e4SLinus Torvalds goto out_failed;
8731da177e4SLinus Torvalds }
874098297b2SJeff Mahoney /* the above add_entry did not update dir's stat data */
8751da177e4SLinus Torvalds reiserfs_update_sd(&th, dir);
8761da177e4SLinus Torvalds
8771e2e547aSAl Viro d_instantiate_new(dentry, inode);
87858d85426SJeff Mahoney retval = journal_end(&th);
8791da177e4SLinus Torvalds out_failed:
880278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb);
881572302afSRoberto Sassu reiserfs_security_free(&security);
8821da177e4SLinus Torvalds return retval;
8831da177e4SLinus Torvalds }
8841da177e4SLinus Torvalds
reiserfs_empty_dir(struct inode * inode)885bd4c625cSLinus Torvalds static inline int reiserfs_empty_dir(struct inode *inode)
886bd4c625cSLinus Torvalds {
887098297b2SJeff Mahoney /*
888098297b2SJeff Mahoney * we can cheat because an old format dir cannot have
889098297b2SJeff Mahoney * EMPTY_DIR_SIZE, and a new format dir cannot have
890098297b2SJeff Mahoney * EMPTY_DIR_SIZE_V1. So, if the inode is either size,
891098297b2SJeff Mahoney * regardless of disk format version, the directory is empty.
8921da177e4SLinus Torvalds */
8931da177e4SLinus Torvalds if (inode->i_size != EMPTY_DIR_SIZE &&
8941da177e4SLinus Torvalds inode->i_size != EMPTY_DIR_SIZE_V1) {
8951da177e4SLinus Torvalds return 0;
8961da177e4SLinus Torvalds }
8971da177e4SLinus Torvalds return 1;
8981da177e4SLinus Torvalds }
8991da177e4SLinus Torvalds
reiserfs_rmdir(struct inode * dir,struct dentry * dentry)9001da177e4SLinus Torvalds static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
9011da177e4SLinus Torvalds {
9021da177e4SLinus Torvalds int retval, err;
9031da177e4SLinus Torvalds struct inode *inode;
9041da177e4SLinus Torvalds struct reiserfs_transaction_handle th;
9051da177e4SLinus Torvalds int jbegin_count;
9061da177e4SLinus Torvalds INITIALIZE_PATH(path);
9071da177e4SLinus Torvalds struct reiserfs_dir_entry de;
9081da177e4SLinus Torvalds
909098297b2SJeff Mahoney /*
910098297b2SJeff Mahoney * we will be doing 2 balancings and update 2 stat data, we
911098297b2SJeff Mahoney * change quotas of the owner of the directory and of the owner
912098297b2SJeff Mahoney * of the parent directory. The quota structure is possibly
913098297b2SJeff Mahoney * deleted only on last iput => outside of this transaction
914098297b2SJeff Mahoney */
915bd4c625cSLinus Torvalds jbegin_count =
916bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 2 + 2 +
917bd4c625cSLinus Torvalds 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
9181da177e4SLinus Torvalds
9192e6c97eaSJan Kara retval = dquot_initialize(dir);
9202e6c97eaSJan Kara if (retval)
9212e6c97eaSJan Kara return retval;
922907f4554SChristoph Hellwig
9231da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb);
9241da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count);
9251da177e4SLinus Torvalds if (retval)
9261da177e4SLinus Torvalds goto out_rmdir;
9271da177e4SLinus Torvalds
9281da177e4SLinus Torvalds de.de_gen_number_bit_string = NULL;
929bd4c625cSLinus Torvalds if ((retval =
930bd4c625cSLinus Torvalds reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
931bd4c625cSLinus Torvalds &path, &de)) == NAME_NOT_FOUND) {
9321da177e4SLinus Torvalds retval = -ENOENT;
9331da177e4SLinus Torvalds goto end_rmdir;
9341da177e4SLinus Torvalds } else if (retval == IO_ERROR) {
9351da177e4SLinus Torvalds retval = -EIO;
9361da177e4SLinus Torvalds goto end_rmdir;
9371da177e4SLinus Torvalds }
9381da177e4SLinus Torvalds
9392b0143b5SDavid Howells inode = d_inode(dentry);
9401da177e4SLinus Torvalds
9411da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode);
9421da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir);
9431da177e4SLinus Torvalds
9441da177e4SLinus Torvalds if (de.de_objectid != inode->i_ino) {
945098297b2SJeff Mahoney /*
946098297b2SJeff Mahoney * FIXME: compare key of an object and a key found in the entry
947098297b2SJeff Mahoney */
9481da177e4SLinus Torvalds retval = -EIO;
9491da177e4SLinus Torvalds goto end_rmdir;
9501da177e4SLinus Torvalds }
9511da177e4SLinus Torvalds if (!reiserfs_empty_dir(inode)) {
9521da177e4SLinus Torvalds retval = -ENOTEMPTY;
9531da177e4SLinus Torvalds goto end_rmdir;
9541da177e4SLinus Torvalds }
9551da177e4SLinus Torvalds
9561da177e4SLinus Torvalds /* cut entry from dir directory */
957a228bf8fSJeff Mahoney retval = reiserfs_cut_from_item(&th, &path, &de.de_entry_key,
958a228bf8fSJeff Mahoney dir, NULL, /* page */
9591da177e4SLinus Torvalds 0 /*new file size - not used here */ );
9601da177e4SLinus Torvalds if (retval < 0)
9611da177e4SLinus Torvalds goto end_rmdir;
9621da177e4SLinus Torvalds
9631da177e4SLinus Torvalds if (inode->i_nlink != 2 && inode->i_nlink != 1)
9640030b645SJeff Mahoney reiserfs_error(inode->i_sb, "reiserfs-7040",
96545b03d5eSJeff Mahoney "empty directory has nlink != 2 (%d)",
96645b03d5eSJeff Mahoney inode->i_nlink);
9671da177e4SLinus Torvalds
968ce71ec36SDave Hansen clear_nlink(inode);
969ae834901SJeff Layton dir->i_mtime = inode_set_ctime_to_ts(dir,
970ae834901SJeff Layton inode_set_ctime_current(inode));
9711da177e4SLinus Torvalds reiserfs_update_sd(&th, inode);
9721da177e4SLinus Torvalds
9731da177e4SLinus Torvalds DEC_DIR_INODE_NLINK(dir)
9741da177e4SLinus Torvalds dir->i_size -= (DEH_SIZE + de.de_entrylen);
9751da177e4SLinus Torvalds reiserfs_update_sd(&th, dir);
9761da177e4SLinus Torvalds
9771da177e4SLinus Torvalds /* prevent empty directory from getting lost */
9781da177e4SLinus Torvalds add_save_link(&th, inode, 0 /* not truncate */ );
9791da177e4SLinus Torvalds
98058d85426SJeff Mahoney retval = journal_end(&th);
9811da177e4SLinus Torvalds reiserfs_check_path(&path);
9821da177e4SLinus Torvalds out_rmdir:
9831da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb);
9841da177e4SLinus Torvalds return retval;
9851da177e4SLinus Torvalds
9861da177e4SLinus Torvalds end_rmdir:
987098297b2SJeff Mahoney /*
988098297b2SJeff Mahoney * we must release path, because we did not call
989098297b2SJeff Mahoney * reiserfs_cut_from_item, or reiserfs_cut_from_item does not
990098297b2SJeff Mahoney * release path if operation was not complete
991098297b2SJeff Mahoney */
9921da177e4SLinus Torvalds pathrelse(&path);
99358d85426SJeff Mahoney err = journal_end(&th);
9941da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb);
9951da177e4SLinus Torvalds return err ? err : retval;
9961da177e4SLinus Torvalds }
9971da177e4SLinus Torvalds
reiserfs_unlink(struct inode * dir,struct dentry * dentry)9981da177e4SLinus Torvalds static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
9991da177e4SLinus Torvalds {
10001da177e4SLinus Torvalds int retval, err;
10011da177e4SLinus Torvalds struct inode *inode;
10021da177e4SLinus Torvalds struct reiserfs_dir_entry de;
10031da177e4SLinus Torvalds INITIALIZE_PATH(path);
10041da177e4SLinus Torvalds struct reiserfs_transaction_handle th;
10051da177e4SLinus Torvalds int jbegin_count;
10061da177e4SLinus Torvalds unsigned long savelink;
10071da177e4SLinus Torvalds
10082e6c97eaSJan Kara retval = dquot_initialize(dir);
10092e6c97eaSJan Kara if (retval)
10102e6c97eaSJan Kara return retval;
1011907f4554SChristoph Hellwig
10122b0143b5SDavid Howells inode = d_inode(dentry);
10131da177e4SLinus Torvalds
1014098297b2SJeff Mahoney /*
1015098297b2SJeff Mahoney * in this transaction we can be doing at max two balancings and
1016098297b2SJeff Mahoney * update two stat datas, we change quotas of the owner of the
1017098297b2SJeff Mahoney * directory and of the owner of the parent directory. The quota
1018098297b2SJeff Mahoney * structure is possibly deleted only on iput => outside of
1019098297b2SJeff Mahoney * this transaction
1020098297b2SJeff Mahoney */
1021bd4c625cSLinus Torvalds jbegin_count =
1022bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 2 + 2 +
1023bd4c625cSLinus Torvalds 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
10241da177e4SLinus Torvalds
1025278f6679SJeff Mahoney reiserfs_write_lock(dir->i_sb);
10261da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count);
10271da177e4SLinus Torvalds if (retval)
10281da177e4SLinus Torvalds goto out_unlink;
10291da177e4SLinus Torvalds
10301da177e4SLinus Torvalds de.de_gen_number_bit_string = NULL;
1031bd4c625cSLinus Torvalds if ((retval =
1032bd4c625cSLinus Torvalds reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
1033bd4c625cSLinus Torvalds &path, &de)) == NAME_NOT_FOUND) {
10341da177e4SLinus Torvalds retval = -ENOENT;
10351da177e4SLinus Torvalds goto end_unlink;
10361da177e4SLinus Torvalds } else if (retval == IO_ERROR) {
10371da177e4SLinus Torvalds retval = -EIO;
10381da177e4SLinus Torvalds goto end_unlink;
10391da177e4SLinus Torvalds }
10401da177e4SLinus Torvalds
10411da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode);
10421da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir);
10431da177e4SLinus Torvalds
10441da177e4SLinus Torvalds if (de.de_objectid != inode->i_ino) {
1045098297b2SJeff Mahoney /*
1046098297b2SJeff Mahoney * FIXME: compare key of an object and a key found in the entry
1047098297b2SJeff Mahoney */
10481da177e4SLinus Torvalds retval = -EIO;
10491da177e4SLinus Torvalds goto end_unlink;
10501da177e4SLinus Torvalds }
10511da177e4SLinus Torvalds
10521da177e4SLinus Torvalds if (!inode->i_nlink) {
105345b03d5eSJeff Mahoney reiserfs_warning(inode->i_sb, "reiserfs-7042",
105445b03d5eSJeff Mahoney "deleting nonexistent file (%lu), %d",
105545b03d5eSJeff Mahoney inode->i_ino, inode->i_nlink);
1056bfe86848SMiklos Szeredi set_nlink(inode, 1);
10571da177e4SLinus Torvalds }
10581da177e4SLinus Torvalds
10599a53c3a7SDave Hansen drop_nlink(inode);
10601da177e4SLinus Torvalds
10611da177e4SLinus Torvalds /*
10621da177e4SLinus Torvalds * we schedule before doing the add_save_link call, save the link
10631da177e4SLinus Torvalds * count so we don't race
10641da177e4SLinus Torvalds */
10651da177e4SLinus Torvalds savelink = inode->i_nlink;
10661da177e4SLinus Torvalds
1067bd4c625cSLinus Torvalds retval =
1068a228bf8fSJeff Mahoney reiserfs_cut_from_item(&th, &path, &de.de_entry_key, dir, NULL,
1069bd4c625cSLinus Torvalds 0);
10701da177e4SLinus Torvalds if (retval < 0) {
1071d8c76e6fSDave Hansen inc_nlink(inode);
10721da177e4SLinus Torvalds goto end_unlink;
10731da177e4SLinus Torvalds }
1074ae834901SJeff Layton inode_set_ctime_current(inode);
10751da177e4SLinus Torvalds reiserfs_update_sd(&th, inode);
10761da177e4SLinus Torvalds
10771da177e4SLinus Torvalds dir->i_size -= (de.de_entrylen + DEH_SIZE);
1078ae834901SJeff Layton dir->i_mtime = inode_set_ctime_current(dir);
10791da177e4SLinus Torvalds reiserfs_update_sd(&th, dir);
10801da177e4SLinus Torvalds
10811da177e4SLinus Torvalds if (!savelink)
10821da177e4SLinus Torvalds /* prevent file from getting lost */
10831da177e4SLinus Torvalds add_save_link(&th, inode, 0 /* not truncate */ );
10841da177e4SLinus Torvalds
108558d85426SJeff Mahoney retval = journal_end(&th);
10861da177e4SLinus Torvalds reiserfs_check_path(&path);
1087278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb);
10881da177e4SLinus Torvalds return retval;
10891da177e4SLinus Torvalds
10901da177e4SLinus Torvalds end_unlink:
10911da177e4SLinus Torvalds pathrelse(&path);
109258d85426SJeff Mahoney err = journal_end(&th);
10931da177e4SLinus Torvalds reiserfs_check_path(&path);
10941da177e4SLinus Torvalds if (err)
10951da177e4SLinus Torvalds retval = err;
10961da177e4SLinus Torvalds out_unlink:
1097278f6679SJeff Mahoney reiserfs_write_unlock(dir->i_sb);
10981da177e4SLinus Torvalds return retval;
10991da177e4SLinus Torvalds }
11001da177e4SLinus Torvalds
reiserfs_symlink(struct mnt_idmap * idmap,struct inode * parent_dir,struct dentry * dentry,const char * symname)11017a77db95SChristian Brauner static int reiserfs_symlink(struct mnt_idmap *idmap,
1102549c7297SChristian Brauner struct inode *parent_dir, struct dentry *dentry,
1103549c7297SChristian Brauner const char *symname)
11041da177e4SLinus Torvalds {
11051da177e4SLinus Torvalds int retval;
11061da177e4SLinus Torvalds struct inode *inode;
11071da177e4SLinus Torvalds char *name;
11081da177e4SLinus Torvalds int item_len;
11091da177e4SLinus Torvalds struct reiserfs_transaction_handle th;
111057fe60dfSJeff Mahoney struct reiserfs_security_handle security;
11111da177e4SLinus Torvalds int mode = S_IFLNK | S_IRWXUGO;
1112098297b2SJeff Mahoney /*
1113098297b2SJeff Mahoney * We need blocks for transaction + (user+group)*(quotas for
1114098297b2SJeff Mahoney * new inode + update of quota for directory owner)
1115098297b2SJeff Mahoney */
1116bd4c625cSLinus Torvalds int jbegin_count =
1117bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 +
1118bd4c625cSLinus Torvalds 2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb) +
1119bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb));
11201da177e4SLinus Torvalds
11212e6c97eaSJan Kara retval = dquot_initialize(parent_dir);
11222e6c97eaSJan Kara if (retval)
11232e6c97eaSJan Kara return retval;
1124907f4554SChristoph Hellwig
11251da177e4SLinus Torvalds if (!(inode = new_inode(parent_dir->i_sb))) {
11261da177e4SLinus Torvalds return -ENOMEM;
11271da177e4SLinus Torvalds }
11282e6c97eaSJan Kara retval = new_inode_init(inode, parent_dir, mode);
11292e6c97eaSJan Kara if (retval) {
11302e6c97eaSJan Kara drop_new_inode(inode);
11312e6c97eaSJan Kara return retval;
11322e6c97eaSJan Kara }
11331da177e4SLinus Torvalds
11342a7dba39SEric Paris retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name,
11352a7dba39SEric Paris &security);
113657fe60dfSJeff Mahoney if (retval < 0) {
113757fe60dfSJeff Mahoney drop_new_inode(inode);
113857fe60dfSJeff Mahoney return retval;
113957fe60dfSJeff Mahoney }
114057fe60dfSJeff Mahoney jbegin_count += retval;
114157fe60dfSJeff Mahoney
11421da177e4SLinus Torvalds reiserfs_write_lock(parent_dir->i_sb);
11431da177e4SLinus Torvalds item_len = ROUND_UP(strlen(symname));
11441da177e4SLinus Torvalds if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) {
11451da177e4SLinus Torvalds retval = -ENAMETOOLONG;
11461da177e4SLinus Torvalds drop_new_inode(inode);
11471da177e4SLinus Torvalds goto out_failed;
11481da177e4SLinus Torvalds }
11491da177e4SLinus Torvalds
1150d739b42bSPekka Enberg name = kmalloc(item_len, GFP_NOFS);
11511da177e4SLinus Torvalds if (!name) {
11521da177e4SLinus Torvalds drop_new_inode(inode);
11531da177e4SLinus Torvalds retval = -ENOMEM;
11541da177e4SLinus Torvalds goto out_failed;
11551da177e4SLinus Torvalds }
11561da177e4SLinus Torvalds memcpy(name, symname, strlen(symname));
11571da177e4SLinus Torvalds padd_item(name, item_len, strlen(symname));
11581da177e4SLinus Torvalds
11591da177e4SLinus Torvalds retval = journal_begin(&th, parent_dir->i_sb, jbegin_count);
11601da177e4SLinus Torvalds if (retval) {
11611da177e4SLinus Torvalds drop_new_inode(inode);
1162d739b42bSPekka Enberg kfree(name);
11631da177e4SLinus Torvalds goto out_failed;
11641da177e4SLinus Torvalds }
11651da177e4SLinus Torvalds
1166bd4c625cSLinus Torvalds retval =
1167bd4c625cSLinus Torvalds reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname),
116857fe60dfSJeff Mahoney dentry, inode, &security);
1169d739b42bSPekka Enberg kfree(name);
11701da177e4SLinus Torvalds if (retval) { /* reiserfs_new_inode iputs for us */
11711da177e4SLinus Torvalds goto out_failed;
11721da177e4SLinus Torvalds }
11731da177e4SLinus Torvalds
11741da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode);
11751da177e4SLinus Torvalds reiserfs_update_inode_transaction(parent_dir);
11761da177e4SLinus Torvalds
11771da177e4SLinus Torvalds inode->i_op = &reiserfs_symlink_inode_operations;
117821fc61c7SAl Viro inode_nohighmem(inode);
11791da177e4SLinus Torvalds inode->i_mapping->a_ops = &reiserfs_address_space_operations;
11801da177e4SLinus Torvalds
11811da177e4SLinus Torvalds retval = reiserfs_add_entry(&th, parent_dir, dentry->d_name.name,
11821da177e4SLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ );
11831da177e4SLinus Torvalds if (retval) {
11841da177e4SLinus Torvalds int err;
11856d6b77f1SMiklos Szeredi drop_nlink(inode);
11861da177e4SLinus Torvalds reiserfs_update_sd(&th, inode);
118758d85426SJeff Mahoney err = journal_end(&th);
11881da177e4SLinus Torvalds if (err)
11891da177e4SLinus Torvalds retval = err;
1190c1eaa26bSAl Viro unlock_new_inode(inode);
11911da177e4SLinus Torvalds iput(inode);
11921da177e4SLinus Torvalds goto out_failed;
11931da177e4SLinus Torvalds }
11941da177e4SLinus Torvalds
11951e2e547aSAl Viro d_instantiate_new(dentry, inode);
119658d85426SJeff Mahoney retval = journal_end(&th);
11971da177e4SLinus Torvalds out_failed:
11981da177e4SLinus Torvalds reiserfs_write_unlock(parent_dir->i_sb);
1199572302afSRoberto Sassu reiserfs_security_free(&security);
12001da177e4SLinus Torvalds return retval;
12011da177e4SLinus Torvalds }
12021da177e4SLinus Torvalds
reiserfs_link(struct dentry * old_dentry,struct inode * dir,struct dentry * dentry)1203bd4c625cSLinus Torvalds static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
1204bd4c625cSLinus Torvalds struct dentry *dentry)
12051da177e4SLinus Torvalds {
12061da177e4SLinus Torvalds int retval;
12072b0143b5SDavid Howells struct inode *inode = d_inode(old_dentry);
12081da177e4SLinus Torvalds struct reiserfs_transaction_handle th;
1209098297b2SJeff Mahoney /*
1210098297b2SJeff Mahoney * We need blocks for transaction + update of quotas for
1211098297b2SJeff Mahoney * the owners of the directory
1212098297b2SJeff Mahoney */
1213bd4c625cSLinus Torvalds int jbegin_count =
1214bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 +
1215bd4c625cSLinus Torvalds 2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
12161da177e4SLinus Torvalds
12172e6c97eaSJan Kara retval = dquot_initialize(dir);
12182e6c97eaSJan Kara if (retval)
12192e6c97eaSJan Kara return retval;
1220907f4554SChristoph Hellwig
12211da177e4SLinus Torvalds reiserfs_write_lock(dir->i_sb);
12221da177e4SLinus Torvalds if (inode->i_nlink >= REISERFS_LINK_MAX) {
1223098297b2SJeff Mahoney /* FIXME: sd_nlink is 32 bit for new files */
12241da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb);
12251da177e4SLinus Torvalds return -EMLINK;
12261da177e4SLinus Torvalds }
12271da177e4SLinus Torvalds
12281da177e4SLinus Torvalds /* inc before scheduling so reiserfs_unlink knows we are here */
1229d8c76e6fSDave Hansen inc_nlink(inode);
12301da177e4SLinus Torvalds
12311da177e4SLinus Torvalds retval = journal_begin(&th, dir->i_sb, jbegin_count);
12321da177e4SLinus Torvalds if (retval) {
12336d6b77f1SMiklos Szeredi drop_nlink(inode);
12341da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb);
12351da177e4SLinus Torvalds return retval;
12361da177e4SLinus Torvalds }
12371da177e4SLinus Torvalds
12381da177e4SLinus Torvalds /* create new entry */
1239bd4c625cSLinus Torvalds retval =
1240bd4c625cSLinus Torvalds reiserfs_add_entry(&th, dir, dentry->d_name.name,
1241bd4c625cSLinus Torvalds dentry->d_name.len, inode, 1 /*visible */ );
12421da177e4SLinus Torvalds
12431da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode);
12441da177e4SLinus Torvalds reiserfs_update_inode_transaction(dir);
12451da177e4SLinus Torvalds
12461da177e4SLinus Torvalds if (retval) {
12471da177e4SLinus Torvalds int err;
12486d6b77f1SMiklos Szeredi drop_nlink(inode);
124958d85426SJeff Mahoney err = journal_end(&th);
12501da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb);
12511da177e4SLinus Torvalds return err ? err : retval;
12521da177e4SLinus Torvalds }
12531da177e4SLinus Torvalds
1254ae834901SJeff Layton inode_set_ctime_current(inode);
12551da177e4SLinus Torvalds reiserfs_update_sd(&th, inode);
12561da177e4SLinus Torvalds
12577de9c6eeSAl Viro ihold(inode);
12581da177e4SLinus Torvalds d_instantiate(dentry, inode);
125958d85426SJeff Mahoney retval = journal_end(&th);
12601da177e4SLinus Torvalds reiserfs_write_unlock(dir->i_sb);
12611da177e4SLinus Torvalds return retval;
12621da177e4SLinus Torvalds }
12631da177e4SLinus Torvalds
12640222e657SJeff Mahoney /* de contains information pointing to an entry which */
de_still_valid(const char * name,int len,struct reiserfs_dir_entry * de)1265bd4c625cSLinus Torvalds static int de_still_valid(const char *name, int len,
1266bd4c625cSLinus Torvalds struct reiserfs_dir_entry *de)
12671da177e4SLinus Torvalds {
12681da177e4SLinus Torvalds struct reiserfs_dir_entry tmp = *de;
12691da177e4SLinus Torvalds
1270098297b2SJeff Mahoney /* recalculate pointer to name and name length */
12711da177e4SLinus Torvalds set_de_name_and_namelen(&tmp);
1272098297b2SJeff Mahoney /* FIXME: could check more */
12731da177e4SLinus Torvalds if (tmp.de_namelen != len || memcmp(name, de->de_name, len))
12741da177e4SLinus Torvalds return 0;
12751da177e4SLinus Torvalds return 1;
12761da177e4SLinus Torvalds }
12771da177e4SLinus Torvalds
entry_points_to_object(const char * name,int len,struct reiserfs_dir_entry * de,struct inode * inode)1278bd4c625cSLinus Torvalds static int entry_points_to_object(const char *name, int len,
1279bd4c625cSLinus Torvalds struct reiserfs_dir_entry *de,
1280bd4c625cSLinus Torvalds struct inode *inode)
12811da177e4SLinus Torvalds {
12821da177e4SLinus Torvalds if (!de_still_valid(name, len, de))
12831da177e4SLinus Torvalds return 0;
12841da177e4SLinus Torvalds
12851da177e4SLinus Torvalds if (inode) {
12861da177e4SLinus Torvalds if (!de_visible(de->de_deh + de->de_entry_num))
1287c3a9c210SJeff Mahoney reiserfs_panic(inode->i_sb, "vs-7042",
1288c3a9c210SJeff Mahoney "entry must be visible");
12891da177e4SLinus Torvalds return (de->de_objectid == inode->i_ino) ? 1 : 0;
12901da177e4SLinus Torvalds }
12911da177e4SLinus Torvalds
12921da177e4SLinus Torvalds /* this must be added hidden entry */
12931da177e4SLinus Torvalds if (de_visible(de->de_deh + de->de_entry_num))
1294c3a9c210SJeff Mahoney reiserfs_panic(NULL, "vs-7043", "entry must be visible");
12951da177e4SLinus Torvalds
12961da177e4SLinus Torvalds return 1;
12971da177e4SLinus Torvalds }
12981da177e4SLinus Torvalds
12991da177e4SLinus Torvalds /* sets key of objectid the entry has to point to */
set_ino_in_dir_entry(struct reiserfs_dir_entry * de,struct reiserfs_key * key)1300bd4c625cSLinus Torvalds static void set_ino_in_dir_entry(struct reiserfs_dir_entry *de,
1301bd4c625cSLinus Torvalds struct reiserfs_key *key)
13021da177e4SLinus Torvalds {
13031da177e4SLinus Torvalds /* JDM These operations are endian safe - both are le */
13041da177e4SLinus Torvalds de->de_deh[de->de_entry_num].deh_dir_id = key->k_dir_id;
13051da177e4SLinus Torvalds de->de_deh[de->de_entry_num].deh_objectid = key->k_objectid;
13061da177e4SLinus Torvalds }
13071da177e4SLinus Torvalds
13081da177e4SLinus Torvalds /*
13091da177e4SLinus Torvalds * process, that is going to call fix_nodes/do_balance must hold only
13101da177e4SLinus Torvalds * one path. If it holds 2 or more, it can get into endless waiting in
13111da177e4SLinus Torvalds * get_empty_nodes or its clones
13121da177e4SLinus Torvalds */
reiserfs_rename(struct mnt_idmap * idmap,struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)1313e18275aeSChristian Brauner static int reiserfs_rename(struct mnt_idmap *idmap,
1314549c7297SChristian Brauner struct inode *old_dir, struct dentry *old_dentry,
1315f03b8ad8SMiklos Szeredi struct inode *new_dir, struct dentry *new_dentry,
1316f03b8ad8SMiklos Szeredi unsigned int flags)
13171da177e4SLinus Torvalds {
13181da177e4SLinus Torvalds int retval;
13191da177e4SLinus Torvalds INITIALIZE_PATH(old_entry_path);
13201da177e4SLinus Torvalds INITIALIZE_PATH(new_entry_path);
13211da177e4SLinus Torvalds INITIALIZE_PATH(dot_dot_entry_path);
13221da177e4SLinus Torvalds struct item_head new_entry_ih, old_entry_ih, dot_dot_ih;
13231da177e4SLinus Torvalds struct reiserfs_dir_entry old_de, new_de, dot_dot_de;
13241da177e4SLinus Torvalds struct inode *old_inode, *new_dentry_inode;
13251da177e4SLinus Torvalds struct reiserfs_transaction_handle th;
13261da177e4SLinus Torvalds int jbegin_count;
13271da177e4SLinus Torvalds unsigned long savelink = 1;
1328*17e1361cSJan Kara bool update_dir_parent = false;
13291da177e4SLinus Torvalds
1330f03b8ad8SMiklos Szeredi if (flags & ~RENAME_NOREPLACE)
1331f03b8ad8SMiklos Szeredi return -EINVAL;
1332f03b8ad8SMiklos Szeredi
1333098297b2SJeff Mahoney /*
1334098297b2SJeff Mahoney * three balancings: (1) old name removal, (2) new name insertion
1335098297b2SJeff Mahoney * and (3) maybe "save" link insertion
1336098297b2SJeff Mahoney * stat data updates: (1) old directory,
1337098297b2SJeff Mahoney * (2) new directory and (3) maybe old object stat data (when it is
1338098297b2SJeff Mahoney * directory) and (4) maybe stat data of object to which new entry
1339098297b2SJeff Mahoney * pointed initially and (5) maybe block containing ".." of
1340098297b2SJeff Mahoney * renamed directory
1341098297b2SJeff Mahoney * quota updates: two parent directories
1342098297b2SJeff Mahoney */
1343bd4c625cSLinus Torvalds jbegin_count =
1344bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 5 +
1345bd4c625cSLinus Torvalds 4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);
13461da177e4SLinus Torvalds
13472e6c97eaSJan Kara retval = dquot_initialize(old_dir);
13482e6c97eaSJan Kara if (retval)
13492e6c97eaSJan Kara return retval;
13502e6c97eaSJan Kara retval = dquot_initialize(new_dir);
13512e6c97eaSJan Kara if (retval)
13522e6c97eaSJan Kara return retval;
1353907f4554SChristoph Hellwig
13542b0143b5SDavid Howells old_inode = d_inode(old_dentry);
13552b0143b5SDavid Howells new_dentry_inode = d_inode(new_dentry);
13561da177e4SLinus Torvalds
1357098297b2SJeff Mahoney /*
1358098297b2SJeff Mahoney * make sure that oldname still exists and points to an object we
1359098297b2SJeff Mahoney * are going to rename
1360098297b2SJeff Mahoney */
13611da177e4SLinus Torvalds old_de.de_gen_number_bit_string = NULL;
13621da177e4SLinus Torvalds reiserfs_write_lock(old_dir->i_sb);
1363bd4c625cSLinus Torvalds retval =
1364bd4c625cSLinus Torvalds reiserfs_find_entry(old_dir, old_dentry->d_name.name,
1365bd4c625cSLinus Torvalds old_dentry->d_name.len, &old_entry_path,
1366bd4c625cSLinus Torvalds &old_de);
13671da177e4SLinus Torvalds pathrelse(&old_entry_path);
13681da177e4SLinus Torvalds if (retval == IO_ERROR) {
13691da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
13701da177e4SLinus Torvalds return -EIO;
13711da177e4SLinus Torvalds }
13721da177e4SLinus Torvalds
13731da177e4SLinus Torvalds if (retval != NAME_FOUND || old_de.de_objectid != old_inode->i_ino) {
13741da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
13751da177e4SLinus Torvalds return -ENOENT;
13761da177e4SLinus Torvalds }
13771da177e4SLinus Torvalds
1378*17e1361cSJan Kara if (S_ISDIR(old_inode->i_mode)) {
1379098297b2SJeff Mahoney /*
1380098297b2SJeff Mahoney * make sure that directory being renamed has correct ".."
1381098297b2SJeff Mahoney * and that its new parent directory has not too many links
1382098297b2SJeff Mahoney * already
1383098297b2SJeff Mahoney */
13841da177e4SLinus Torvalds if (new_dentry_inode) {
13851da177e4SLinus Torvalds if (!reiserfs_empty_dir(new_dentry_inode)) {
13861da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
13871da177e4SLinus Torvalds return -ENOTEMPTY;
13881da177e4SLinus Torvalds }
13891da177e4SLinus Torvalds }
13901da177e4SLinus Torvalds
1391*17e1361cSJan Kara if (old_dir != new_dir) {
1392098297b2SJeff Mahoney /*
1393*17e1361cSJan Kara * directory is renamed, its parent directory will be
1394*17e1361cSJan Kara * changed, so find ".." entry
13951da177e4SLinus Torvalds */
13961da177e4SLinus Torvalds dot_dot_de.de_gen_number_bit_string = NULL;
1397bd4c625cSLinus Torvalds retval =
1398*17e1361cSJan Kara reiserfs_find_entry(old_inode, "..", 2,
1399*17e1361cSJan Kara &dot_dot_entry_path,
1400bd4c625cSLinus Torvalds &dot_dot_de);
14011da177e4SLinus Torvalds pathrelse(&dot_dot_entry_path);
14021da177e4SLinus Torvalds if (retval != NAME_FOUND) {
14031da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
14041da177e4SLinus Torvalds return -EIO;
14051da177e4SLinus Torvalds }
14061da177e4SLinus Torvalds
14071da177e4SLinus Torvalds /* inode number of .. must equal old_dir->i_ino */
14081da177e4SLinus Torvalds if (dot_dot_de.de_objectid != old_dir->i_ino) {
14091da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
14101da177e4SLinus Torvalds return -EIO;
14111da177e4SLinus Torvalds }
1412*17e1361cSJan Kara update_dir_parent = true;
1413*17e1361cSJan Kara }
14141da177e4SLinus Torvalds }
14151da177e4SLinus Torvalds
14161da177e4SLinus Torvalds retval = journal_begin(&th, old_dir->i_sb, jbegin_count);
14171da177e4SLinus Torvalds if (retval) {
14181da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
14191da177e4SLinus Torvalds return retval;
14201da177e4SLinus Torvalds }
14211da177e4SLinus Torvalds
14221da177e4SLinus Torvalds /* add new entry (or find the existing one) */
1423bd4c625cSLinus Torvalds retval =
1424bd4c625cSLinus Torvalds reiserfs_add_entry(&th, new_dir, new_dentry->d_name.name,
1425bd4c625cSLinus Torvalds new_dentry->d_name.len, old_inode, 0);
14261da177e4SLinus Torvalds if (retval == -EEXIST) {
14271da177e4SLinus Torvalds if (!new_dentry_inode) {
1428c3a9c210SJeff Mahoney reiserfs_panic(old_dir->i_sb, "vs-7050",
1429c3a9c210SJeff Mahoney "new entry is found, new inode == 0");
14301da177e4SLinus Torvalds }
14311da177e4SLinus Torvalds } else if (retval) {
143258d85426SJeff Mahoney int err = journal_end(&th);
14331da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
14341da177e4SLinus Torvalds return err ? err : retval;
14351da177e4SLinus Torvalds }
14361da177e4SLinus Torvalds
14371da177e4SLinus Torvalds reiserfs_update_inode_transaction(old_dir);
14381da177e4SLinus Torvalds reiserfs_update_inode_transaction(new_dir);
14391da177e4SLinus Torvalds
1440098297b2SJeff Mahoney /*
1441098297b2SJeff Mahoney * this makes it so an fsync on an open fd for the old name will
1442098297b2SJeff Mahoney * commit the rename operation
14431da177e4SLinus Torvalds */
14441da177e4SLinus Torvalds reiserfs_update_inode_transaction(old_inode);
14451da177e4SLinus Torvalds
14461da177e4SLinus Torvalds if (new_dentry_inode)
14471da177e4SLinus Torvalds reiserfs_update_inode_transaction(new_dentry_inode);
14481da177e4SLinus Torvalds
14491da177e4SLinus Torvalds while (1) {
1450098297b2SJeff Mahoney /*
1451098297b2SJeff Mahoney * look for old name using corresponding entry key
1452098297b2SJeff Mahoney * (found by reiserfs_find_entry)
1453098297b2SJeff Mahoney */
1454bd4c625cSLinus Torvalds if ((retval =
1455bd4c625cSLinus Torvalds search_by_entry_key(new_dir->i_sb, &old_de.de_entry_key,
1456bd4c625cSLinus Torvalds &old_entry_path,
1457bd4c625cSLinus Torvalds &old_de)) != NAME_FOUND) {
14581da177e4SLinus Torvalds pathrelse(&old_entry_path);
145958d85426SJeff Mahoney journal_end(&th);
14601da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
14611da177e4SLinus Torvalds return -EIO;
14621da177e4SLinus Torvalds }
14631da177e4SLinus Torvalds
14644cf5f7adSJeff Mahoney copy_item_head(&old_entry_ih, tp_item_head(&old_entry_path));
14651da177e4SLinus Torvalds
14661da177e4SLinus Torvalds reiserfs_prepare_for_journal(old_inode->i_sb, old_de.de_bh, 1);
14671da177e4SLinus Torvalds
1468098297b2SJeff Mahoney /* look for new name by reiserfs_find_entry */
14691da177e4SLinus Torvalds new_de.de_gen_number_bit_string = NULL;
1470bd4c625cSLinus Torvalds retval =
1471bd4c625cSLinus Torvalds reiserfs_find_entry(new_dir, new_dentry->d_name.name,
1472bd4c625cSLinus Torvalds new_dentry->d_name.len, &new_entry_path,
1473bd4c625cSLinus Torvalds &new_de);
1474098297b2SJeff Mahoney /*
1475098297b2SJeff Mahoney * reiserfs_add_entry should not return IO_ERROR,
1476098297b2SJeff Mahoney * because it is called with essentially same parameters from
1477098297b2SJeff Mahoney * reiserfs_add_entry above, and we'll catch any i/o errors
1478098297b2SJeff Mahoney * before we get here.
1479098297b2SJeff Mahoney */
14801da177e4SLinus Torvalds if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) {
14811da177e4SLinus Torvalds pathrelse(&new_entry_path);
14821da177e4SLinus Torvalds pathrelse(&old_entry_path);
148358d85426SJeff Mahoney journal_end(&th);
14841da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
14851da177e4SLinus Torvalds return -EIO;
14861da177e4SLinus Torvalds }
14871da177e4SLinus Torvalds
14884cf5f7adSJeff Mahoney copy_item_head(&new_entry_ih, tp_item_head(&new_entry_path));
14891da177e4SLinus Torvalds
14901da177e4SLinus Torvalds reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1);
14911da177e4SLinus Torvalds
1492*17e1361cSJan Kara if (update_dir_parent) {
1493bd4c625cSLinus Torvalds if ((retval =
1494bd4c625cSLinus Torvalds search_by_entry_key(new_dir->i_sb,
1495bd4c625cSLinus Torvalds &dot_dot_de.de_entry_key,
1496bd4c625cSLinus Torvalds &dot_dot_entry_path,
1497bd4c625cSLinus Torvalds &dot_dot_de)) != NAME_FOUND) {
14981da177e4SLinus Torvalds pathrelse(&dot_dot_entry_path);
14991da177e4SLinus Torvalds pathrelse(&new_entry_path);
15001da177e4SLinus Torvalds pathrelse(&old_entry_path);
150158d85426SJeff Mahoney journal_end(&th);
15021da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
15031da177e4SLinus Torvalds return -EIO;
15041da177e4SLinus Torvalds }
1505bd4c625cSLinus Torvalds copy_item_head(&dot_dot_ih,
15064cf5f7adSJeff Mahoney tp_item_head(&dot_dot_entry_path));
1507098297b2SJeff Mahoney /* node containing ".." gets into transaction */
1508bd4c625cSLinus Torvalds reiserfs_prepare_for_journal(old_inode->i_sb,
1509bd4c625cSLinus Torvalds dot_dot_de.de_bh, 1);
15101da177e4SLinus Torvalds }
1511098297b2SJeff Mahoney /*
1512098297b2SJeff Mahoney * we should check seals here, not do
1513098297b2SJeff Mahoney * this stuff, yes? Then, having
1514098297b2SJeff Mahoney * gathered everything into RAM we
1515098297b2SJeff Mahoney * should lock the buffers, yes? -Hans
15161da177e4SLinus Torvalds */
1517098297b2SJeff Mahoney /*
1518098297b2SJeff Mahoney * probably. our rename needs to hold more
1519098297b2SJeff Mahoney * than one path at once. The seals would
1520098297b2SJeff Mahoney * have to be written to deal with multi-path
1521098297b2SJeff Mahoney * issues -chris
1522098297b2SJeff Mahoney */
1523098297b2SJeff Mahoney /*
1524098297b2SJeff Mahoney * sanity checking before doing the rename - avoid races many
1525098297b2SJeff Mahoney * of the above checks could have scheduled. We have to be
1526098297b2SJeff Mahoney * sure our items haven't been shifted by another process.
15271da177e4SLinus Torvalds */
15281da177e4SLinus Torvalds if (item_moved(&new_entry_ih, &new_entry_path) ||
15291da177e4SLinus Torvalds !entry_points_to_object(new_dentry->d_name.name,
15301da177e4SLinus Torvalds new_dentry->d_name.len,
15311da177e4SLinus Torvalds &new_de, new_dentry_inode) ||
15321da177e4SLinus Torvalds item_moved(&old_entry_ih, &old_entry_path) ||
15331da177e4SLinus Torvalds !entry_points_to_object(old_dentry->d_name.name,
15341da177e4SLinus Torvalds old_dentry->d_name.len,
15351da177e4SLinus Torvalds &old_de, old_inode)) {
1536bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode->i_sb,
1537bd4c625cSLinus Torvalds new_de.de_bh);
1538bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode->i_sb,
1539bd4c625cSLinus Torvalds old_de.de_bh);
1540*17e1361cSJan Kara if (update_dir_parent)
1541bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode->
1542bd4c625cSLinus Torvalds i_sb,
1543bd4c625cSLinus Torvalds dot_dot_de.
1544bd4c625cSLinus Torvalds de_bh);
15451da177e4SLinus Torvalds continue;
15461da177e4SLinus Torvalds }
1547*17e1361cSJan Kara if (update_dir_parent) {
15481da177e4SLinus Torvalds if (item_moved(&dot_dot_ih, &dot_dot_entry_path) ||
1549bd4c625cSLinus Torvalds !entry_points_to_object("..", 2, &dot_dot_de,
1550bd4c625cSLinus Torvalds old_dir)) {
1551bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode->
1552bd4c625cSLinus Torvalds i_sb,
1553bd4c625cSLinus Torvalds old_de.de_bh);
1554bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode->
1555bd4c625cSLinus Torvalds i_sb,
1556bd4c625cSLinus Torvalds new_de.de_bh);
1557bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(old_inode->
1558bd4c625cSLinus Torvalds i_sb,
1559bd4c625cSLinus Torvalds dot_dot_de.
1560bd4c625cSLinus Torvalds de_bh);
15611da177e4SLinus Torvalds continue;
15621da177e4SLinus Torvalds }
15631da177e4SLinus Torvalds }
15641da177e4SLinus Torvalds
1565*17e1361cSJan Kara RFALSE(update_dir_parent &&
15661da177e4SLinus Torvalds !buffer_journal_prepared(dot_dot_de.de_bh), "");
15671da177e4SLinus Torvalds
15681da177e4SLinus Torvalds break;
15691da177e4SLinus Torvalds }
15701da177e4SLinus Torvalds
1571098297b2SJeff Mahoney /*
1572098297b2SJeff Mahoney * ok, all the changes can be done in one fell swoop when we
1573098297b2SJeff Mahoney * have claimed all the buffers needed.
1574098297b2SJeff Mahoney */
15751da177e4SLinus Torvalds
15761da177e4SLinus Torvalds mark_de_visible(new_de.de_deh + new_de.de_entry_num);
15771da177e4SLinus Torvalds set_ino_in_dir_entry(&new_de, INODE_PKEY(old_inode));
157809f1b80bSJeff Mahoney journal_mark_dirty(&th, new_de.de_bh);
15791da177e4SLinus Torvalds
15801da177e4SLinus Torvalds mark_de_hidden(old_de.de_deh + old_de.de_entry_num);
158109f1b80bSJeff Mahoney journal_mark_dirty(&th, old_de.de_bh);
1582098297b2SJeff Mahoney /*
1583098297b2SJeff Mahoney * thanks to Alex Adriaanse <alex_a@caltech.edu> for patch
1584098297b2SJeff Mahoney * which adds ctime update of renamed object
1585098297b2SJeff Mahoney */
1586298d35efSJeff Layton simple_rename_timestamp(old_dir, old_dentry, new_dir, new_dentry);
15871da177e4SLinus Torvalds
15881da177e4SLinus Torvalds if (new_dentry_inode) {
1589098297b2SJeff Mahoney /* adjust link number of the victim */
15901da177e4SLinus Torvalds if (S_ISDIR(new_dentry_inode->i_mode)) {
1591ce71ec36SDave Hansen clear_nlink(new_dentry_inode);
15921da177e4SLinus Torvalds } else {
15939a53c3a7SDave Hansen drop_nlink(new_dentry_inode);
15941da177e4SLinus Torvalds }
15951da177e4SLinus Torvalds savelink = new_dentry_inode->i_nlink;
15961da177e4SLinus Torvalds }
15971da177e4SLinus Torvalds
1598*17e1361cSJan Kara if (update_dir_parent) {
15990222e657SJeff Mahoney /* adjust ".." of renamed directory */
16001da177e4SLinus Torvalds set_ino_in_dir_entry(&dot_dot_de, INODE_PKEY(new_dir));
160109f1b80bSJeff Mahoney journal_mark_dirty(&th, dot_dot_de.de_bh);
1602*17e1361cSJan Kara }
1603*17e1361cSJan Kara if (S_ISDIR(old_inode->i_mode)) {
1604098297b2SJeff Mahoney /*
1605098297b2SJeff Mahoney * there (in new_dir) was no directory, so it got new link
1606098297b2SJeff Mahoney * (".." of renamed directory)
1607098297b2SJeff Mahoney */
16081da177e4SLinus Torvalds if (!new_dentry_inode)
16091da177e4SLinus Torvalds INC_DIR_INODE_NLINK(new_dir);
16101da177e4SLinus Torvalds
16111da177e4SLinus Torvalds /* old directory lost one link - ".. " of renamed directory */
16121da177e4SLinus Torvalds DEC_DIR_INODE_NLINK(old_dir);
16131da177e4SLinus Torvalds }
1614098297b2SJeff Mahoney /*
1615098297b2SJeff Mahoney * looks like in 2.3.99pre3 brelse is atomic.
1616098297b2SJeff Mahoney * so we can use pathrelse
1617098297b2SJeff Mahoney */
16181da177e4SLinus Torvalds pathrelse(&new_entry_path);
16191da177e4SLinus Torvalds pathrelse(&dot_dot_entry_path);
16201da177e4SLinus Torvalds
1621098297b2SJeff Mahoney /*
1622098297b2SJeff Mahoney * FIXME: this reiserfs_cut_from_item's return value may screw up
1623098297b2SJeff Mahoney * anybody, but it will panic if will not be able to find the
1624098297b2SJeff Mahoney * entry. This needs one more clean up
1625098297b2SJeff Mahoney */
1626bd4c625cSLinus Torvalds if (reiserfs_cut_from_item
1627a228bf8fSJeff Mahoney (&th, &old_entry_path, &old_de.de_entry_key, old_dir, NULL,
1628bd4c625cSLinus Torvalds 0) < 0)
16290030b645SJeff Mahoney reiserfs_error(old_dir->i_sb, "vs-7060",
163045b03d5eSJeff Mahoney "couldn't not cut old name. Fsck later?");
16311da177e4SLinus Torvalds
16321da177e4SLinus Torvalds old_dir->i_size -= DEH_SIZE + old_de.de_entrylen;
16331da177e4SLinus Torvalds
16341da177e4SLinus Torvalds reiserfs_update_sd(&th, old_dir);
16351da177e4SLinus Torvalds reiserfs_update_sd(&th, new_dir);
16361da177e4SLinus Torvalds reiserfs_update_sd(&th, old_inode);
16371da177e4SLinus Torvalds
16381da177e4SLinus Torvalds if (new_dentry_inode) {
16391da177e4SLinus Torvalds if (savelink == 0)
1640bd4c625cSLinus Torvalds add_save_link(&th, new_dentry_inode,
1641bd4c625cSLinus Torvalds 0 /* not truncate */ );
16421da177e4SLinus Torvalds reiserfs_update_sd(&th, new_dentry_inode);
16431da177e4SLinus Torvalds }
16441da177e4SLinus Torvalds
164558d85426SJeff Mahoney retval = journal_end(&th);
16461da177e4SLinus Torvalds reiserfs_write_unlock(old_dir->i_sb);
16471da177e4SLinus Torvalds return retval;
16481da177e4SLinus Torvalds }
16491da177e4SLinus Torvalds
1650d9f892b9SChristian Brauner static const struct inode_operations reiserfs_priv_dir_inode_operations = {
1651d9f892b9SChristian Brauner .create = reiserfs_create,
1652d9f892b9SChristian Brauner .lookup = reiserfs_lookup,
1653d9f892b9SChristian Brauner .link = reiserfs_link,
1654d9f892b9SChristian Brauner .unlink = reiserfs_unlink,
1655d9f892b9SChristian Brauner .symlink = reiserfs_symlink,
1656d9f892b9SChristian Brauner .mkdir = reiserfs_mkdir,
1657d9f892b9SChristian Brauner .rmdir = reiserfs_rmdir,
1658d9f892b9SChristian Brauner .mknod = reiserfs_mknod,
1659d9f892b9SChristian Brauner .rename = reiserfs_rename,
1660d9f892b9SChristian Brauner .setattr = reiserfs_setattr,
1661d9f892b9SChristian Brauner .permission = reiserfs_permission,
1662d9f892b9SChristian Brauner .fileattr_get = reiserfs_fileattr_get,
1663d9f892b9SChristian Brauner .fileattr_set = reiserfs_fileattr_set,
1664d9f892b9SChristian Brauner };
1665d9f892b9SChristian Brauner
1666d9f892b9SChristian Brauner static const struct inode_operations reiserfs_priv_symlink_inode_operations = {
1667d9f892b9SChristian Brauner .get_link = page_get_link,
1668d9f892b9SChristian Brauner .setattr = reiserfs_setattr,
1669d9f892b9SChristian Brauner .permission = reiserfs_permission,
1670d9f892b9SChristian Brauner };
1671d9f892b9SChristian Brauner
1672d9f892b9SChristian Brauner static const struct inode_operations reiserfs_priv_special_inode_operations = {
1673d9f892b9SChristian Brauner .setattr = reiserfs_setattr,
1674d9f892b9SChristian Brauner .permission = reiserfs_permission,
1675d9f892b9SChristian Brauner };
1676d9f892b9SChristian Brauner
reiserfs_init_priv_inode(struct inode * inode)1677d9f892b9SChristian Brauner void reiserfs_init_priv_inode(struct inode *inode)
1678d9f892b9SChristian Brauner {
1679d9f892b9SChristian Brauner inode->i_flags |= S_PRIVATE;
1680d9f892b9SChristian Brauner inode->i_opflags &= ~IOP_XATTR;
1681d9f892b9SChristian Brauner
1682d9f892b9SChristian Brauner if (S_ISREG(inode->i_mode))
1683d9f892b9SChristian Brauner inode->i_op = &reiserfs_priv_file_inode_operations;
1684d9f892b9SChristian Brauner else if (S_ISDIR(inode->i_mode))
1685d9f892b9SChristian Brauner inode->i_op = &reiserfs_priv_dir_inode_operations;
1686d9f892b9SChristian Brauner else if (S_ISLNK(inode->i_mode))
1687d9f892b9SChristian Brauner inode->i_op = &reiserfs_priv_symlink_inode_operations;
1688d9f892b9SChristian Brauner else
1689d9f892b9SChristian Brauner inode->i_op = &reiserfs_priv_special_inode_operations;
1690d9f892b9SChristian Brauner }
1691d9f892b9SChristian Brauner
1692098297b2SJeff Mahoney /* directories can handle most operations... */
1693c5ef1c42SArjan van de Ven const struct inode_operations reiserfs_dir_inode_operations = {
16941da177e4SLinus Torvalds .create = reiserfs_create,
16951da177e4SLinus Torvalds .lookup = reiserfs_lookup,
16961da177e4SLinus Torvalds .link = reiserfs_link,
16971da177e4SLinus Torvalds .unlink = reiserfs_unlink,
16981da177e4SLinus Torvalds .symlink = reiserfs_symlink,
16991da177e4SLinus Torvalds .mkdir = reiserfs_mkdir,
17001da177e4SLinus Torvalds .rmdir = reiserfs_rmdir,
17011da177e4SLinus Torvalds .mknod = reiserfs_mknod,
17021da177e4SLinus Torvalds .rename = reiserfs_rename,
17031da177e4SLinus Torvalds .setattr = reiserfs_setattr,
17041da177e4SLinus Torvalds .listxattr = reiserfs_listxattr,
17051da177e4SLinus Torvalds .permission = reiserfs_permission,
1706cac2f8b8SChristian Brauner .get_inode_acl = reiserfs_get_acl,
170747f70d08SChristoph Hellwig .set_acl = reiserfs_set_acl,
170803eb6066SMiklos Szeredi .fileattr_get = reiserfs_fileattr_get,
170903eb6066SMiklos Szeredi .fileattr_set = reiserfs_fileattr_set,
17101da177e4SLinus Torvalds };
17111da177e4SLinus Torvalds
17121da177e4SLinus Torvalds /*
17131da177e4SLinus Torvalds * symlink operations.. same as page_symlink_inode_operations, with xattr
17141da177e4SLinus Torvalds * stuff added
17151da177e4SLinus Torvalds */
1716c5ef1c42SArjan van de Ven const struct inode_operations reiserfs_symlink_inode_operations = {
17176b255391SAl Viro .get_link = page_get_link,
17181da177e4SLinus Torvalds .setattr = reiserfs_setattr,
17191da177e4SLinus Torvalds .listxattr = reiserfs_listxattr,
17201da177e4SLinus Torvalds .permission = reiserfs_permission,
17211da177e4SLinus Torvalds };
17221da177e4SLinus Torvalds
17231da177e4SLinus Torvalds /*
17241da177e4SLinus Torvalds * special file operations.. just xattr/acl stuff
17251da177e4SLinus Torvalds */
1726c5ef1c42SArjan van de Ven const struct inode_operations reiserfs_special_inode_operations = {
17271da177e4SLinus Torvalds .setattr = reiserfs_setattr,
17281da177e4SLinus Torvalds .listxattr = reiserfs_listxattr,
17291da177e4SLinus Torvalds .permission = reiserfs_permission,
1730cac2f8b8SChristian Brauner .get_inode_acl = reiserfs_get_acl,
173147f70d08SChristoph Hellwig .set_acl = reiserfs_set_acl,
17321da177e4SLinus Torvalds };
1733