Blame view

fs/reiserfs/namei.c 43.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
  /*
   * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
   *
   * Trivial changes by Alan Cox to remove EHASHCOLLISION for compatibility
   *
   * Trivial Changes:
   * Rights granted to Hans Reiser to redistribute under other terms providing
   * he accepts all liability including but not limited to patent, fitness
   * for purpose, and direct or indirect claims arising from failure to perform.
   *
   * NO WARRANTY
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
  #include <linux/time.h>
  #include <linux/bitops.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/slab.h>
f466c6fdb   Al Viro   move private bits...
16
  #include "reiserfs.h"
a3063ab88   Al Viro   move reiserfs_acl...
17
  #include "acl.h"
c45ac8887   Al Viro   take private bits...
18
  #include "xattr.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  #include <linux/quotaops.h>
bfe868486   Miklos Szeredi   filesystems: add ...
20
  #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); }
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
21
  #define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) drop_nlink(i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22

098297b27   Jeff Mahoney   reiserfs: cleanup...
23
24
25
26
  /*
   * directory item contains array of entry headers. This performs
   * binary search through that array
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
27
  static int bin_search_in_dir_item(struct reiserfs_dir_entry *de, loff_t off)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
29
30
31
32
33
  	struct item_head *ih = de->de_ih;
  	struct reiserfs_de_head *deh = de->de_deh;
  	int rbound, lbound, j;
  
  	lbound = 0;
4cf5f7add   Jeff Mahoney   reiserfs: cleanup...
34
  	rbound = ih_entry_count(ih) - 1;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
35
36
37
38
39
40
41
42
43
44
45
  
  	for (j = (rbound + lbound) / 2; lbound <= rbound;
  	     j = (rbound + lbound) / 2) {
  		if (off < deh_offset(deh + j)) {
  			rbound = j - 1;
  			continue;
  		}
  		if (off > deh_offset(deh + j)) {
  			lbound = j + 1;
  			continue;
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
46
  		/* this is not name found, but matched third key component */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
47
48
  		de->de_entry_num = j;
  		return NAME_FOUND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50

bd4c625c0   Linus Torvalds   reiserfs: run scr...
51
52
  	de->de_entry_num = lbound;
  	return NAME_NOT_FOUND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
54
55
56
  /*
   * comment?  maybe something like set de to point to what the path points to?
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
57
  static inline void set_de_item_location(struct reiserfs_dir_entry *de,
fec6d055d   Josef "Jeff" Sipek   [PATCH] struct pa...
58
  					struct treepath *path)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
60
  	de->de_bh = get_last_bh(path);
4cf5f7add   Jeff Mahoney   reiserfs: cleanup...
61
  	de->de_ih = tp_item_head(path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
62
63
64
  	de->de_deh = B_I_DEH(de->de_bh, de->de_ih);
  	de->de_item_num = PATH_LAST_POSITION(path);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65

098297b27   Jeff Mahoney   reiserfs: cleanup...
66
67
68
  /*
   * de_bh, de_ih, de_deh (points to first element of array), de_item_num is set
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
69
  inline void set_de_name_and_namelen(struct reiserfs_dir_entry *de)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
71
  	struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72

14a61442c   Eric Sesterhenn   BUG_ON conversion...
73
  	BUG_ON(de->de_entry_num >= ih_entry_count(de->de_ih));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74

bd4c625c0   Linus Torvalds   reiserfs: run scr...
75
76
  	de->de_entrylen = entry_length(de->de_bh, de->de_ih, de->de_entry_num);
  	de->de_namelen = de->de_entrylen - (de_with_sd(deh) ? SD_SIZE : 0);
4cf5f7add   Jeff Mahoney   reiserfs: cleanup...
77
  	de->de_name = ih_item_body(de->de_bh, de->de_ih) + deh_location(deh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
78
79
  	if (de->de_name[de->de_namelen - 1] == 0)
  		de->de_namelen = strlen(de->de_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
81
  /* what entry points to */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
82
  static inline void set_de_object_key(struct reiserfs_dir_entry *de)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  {
14a61442c   Eric Sesterhenn   BUG_ON conversion...
84
  	BUG_ON(de->de_entry_num >= ih_entry_count(de->de_ih));
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
85
86
  	de->de_dir_id = deh_dir_id(&de->de_deh[de->de_entry_num]);
  	de->de_objectid = deh_objectid(&de->de_deh[de->de_entry_num]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
88
  static inline void store_de_entry_key(struct reiserfs_dir_entry *de)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
90
  	struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num;
14a61442c   Eric Sesterhenn   BUG_ON conversion...
91
  	BUG_ON(de->de_entry_num >= ih_entry_count(de->de_ih));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
92
93
94
95
96
97
98
  
  	/* store key of the found entry */
  	de->de_entry_key.version = KEY_FORMAT_3_5;
  	de->de_entry_key.on_disk_key.k_dir_id =
  	    le32_to_cpu(de->de_ih->ih_key.k_dir_id);
  	de->de_entry_key.on_disk_key.k_objectid =
  	    le32_to_cpu(de->de_ih->ih_key.k_objectid);
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
99
100
  	set_cpu_key_k_offset(&de->de_entry_key, deh_offset(deh));
  	set_cpu_key_k_type(&de->de_entry_key, TYPE_DIRENTRY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
102
103
104
105
106
107
108
109
110
111
  /*
   * We assign a key to each directory item, and place multiple entries in a
   * single directory item.  A directory item has a key equal to the key of
   * the first directory entry in it.
  
   * This function first calls search_by_key, then, if item whose first entry
   * matches is not found it looks for the entry inside directory item found
   * by search_by_key. Fills the path to the entry, and to the entry position
   * in the item
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  /* The function is NOT SCHEDULE-SAFE! */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
113
  int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
fec6d055d   Josef "Jeff" Sipek   [PATCH] struct pa...
114
  			struct treepath *path, struct reiserfs_dir_entry *de)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
116
117
118
119
120
121
  	int retval;
  
  	retval = search_item(sb, key, path);
  	switch (retval) {
  	case ITEM_NOT_FOUND:
  		if (!PATH_LAST_POSITION(path)) {
0030b6457   Jeff Mahoney   reiserfs: use rei...
122
123
  			reiserfs_error(sb, "vs-7000", "search_by_key "
  				       "returned item position == 0");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
124
125
126
127
128
129
130
131
132
133
134
135
136
  			pathrelse(path);
  			return IO_ERROR;
  		}
  		PATH_LAST_POSITION(path)--;
  
  	case ITEM_FOUND:
  		break;
  
  	case IO_ERROR:
  		return retval;
  
  	default:
  		pathrelse(path);
0030b6457   Jeff Mahoney   reiserfs: use rei...
137
  		reiserfs_error(sb, "vs-7002", "no path to here");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
138
  		return IO_ERROR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140

bd4c625c0   Linus Torvalds   reiserfs: run scr...
141
  	set_de_item_location(de, path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
  
  #ifdef CONFIG_REISERFS_CHECK
bd4c625c0   Linus Torvalds   reiserfs: run scr...
144
  	if (!is_direntry_le_ih(de->de_ih) ||
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
145
  	    COMP_SHORT_KEYS(&de->de_ih->ih_key, key)) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
146
  		print_block(de->de_bh, 0, -1, -1);
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
147
148
149
  		reiserfs_panic(sb, "vs-7005", "found item %h is not directory "
  			       "item or does not belong to the same directory "
  			       "as key %K", de->de_ih, key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
150
151
  	}
  #endif				/* CONFIG_REISERFS_CHECK */
098297b27   Jeff Mahoney   reiserfs: cleanup...
152
153
154
155
  	/*
  	 * binary search in directory item by third component of the
  	 * key. sets de->de_entry_num of de
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
156
157
158
  	retval = bin_search_in_dir_item(de, cpu_key_k_offset(key));
  	path->pos_in_item = de->de_entry_num;
  	if (retval != NAME_NOT_FOUND) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
159
160
161
162
  		/*
  		 * ugly, but rename needs de_bh, de_deh, de_name,
  		 * de_namelen, de_objectid set
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
163
164
165
166
  		set_de_name_and_namelen(de);
  		set_de_object_key(de);
  	}
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
  /* Keyed 32-bit hash function using TEA in a Davis-Meyer function */
098297b27   Jeff Mahoney   reiserfs: cleanup...
169
170
171
172
173
174
  /*
   * The third component is hashed, and you can choose from more than
   * one hash function.  Per directory hashes are not yet implemented
   * but are thought about. This function should be moved to hashes.c
   * Jedi, please do so.  -Hans
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
175
176
  static __u32 get_third_component(struct super_block *s,
  				 const char *name, int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
178
179
180
181
182
183
184
185
  	__u32 res;
  
  	if (!len || (len == 1 && name[0] == '.'))
  		return DOT_OFFSET;
  	if (len == 2 && name[0] == '.' && name[1] == '.')
  		return DOT_DOT_OFFSET;
  
  	res = REISERFS_SB(s)->s_hash_function(name, len);
098297b27   Jeff Mahoney   reiserfs: cleanup...
186
  	/* take bits from 7-th to 30-th including both bounds */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
187
188
  	res = GET_HASH_VALUE(res);
  	if (res == 0)
098297b27   Jeff Mahoney   reiserfs: cleanup...
189
190
191
192
  		/*
  		 * needed to have no names before "." and ".." those have hash
  		 * value == 0 and generation conters 1 and 2 accordingly
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
193
194
  		res = 128;
  	return res + MAX_GENERATION_NUMBER;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
196
197
  static int reiserfs_match(struct reiserfs_dir_entry *de,
  			  const char *name, int namelen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
199
  	int retval = NAME_NOT_FOUND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200

bd4c625c0   Linus Torvalds   reiserfs: run scr...
201
202
203
204
205
  	if ((namelen == de->de_namelen) &&
  	    !memcmp(de->de_name, name, de->de_namelen))
  		retval =
  		    (de_visible(de->de_deh + de->de_entry_num) ? NAME_FOUND :
  		     NAME_FOUND_INVISIBLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206

bd4c625c0   Linus Torvalds   reiserfs: run scr...
207
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
  /* de's de_bh, de_ih, de_deh, de_item_num, de_entry_num are set already */
098297b27   Jeff Mahoney   reiserfs: cleanup...
210
  /* used when hash collisions exist */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211

bd4c625c0   Linus Torvalds   reiserfs: run scr...
212
213
214
  static int linear_search_in_dir_item(struct cpu_key *key,
  				     struct reiserfs_dir_entry *de,
  				     const char *name, int namelen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
216
217
218
  	struct reiserfs_de_head *deh = de->de_deh;
  	int retval;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219

bd4c625c0   Linus Torvalds   reiserfs: run scr...
220
  	i = de->de_entry_num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221

4cf5f7add   Jeff Mahoney   reiserfs: cleanup...
222
  	if (i == ih_entry_count(de->de_ih) ||
bd4c625c0   Linus Torvalds   reiserfs: run scr...
223
224
225
226
  	    GET_HASH_VALUE(deh_offset(deh + i)) !=
  	    GET_HASH_VALUE(cpu_key_k_offset(key))) {
  		i--;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227

bd4c625c0   Linus Torvalds   reiserfs: run scr...
228
229
  	RFALSE(de->de_deh != B_I_DEH(de->de_bh, de->de_ih),
  	       "vs-7010: array of entry headers not found");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230

bd4c625c0   Linus Torvalds   reiserfs: run scr...
231
  	deh += i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232

bd4c625c0   Linus Torvalds   reiserfs: run scr...
233
  	for (; i >= 0; i--, deh--) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
234
  		/* hash value does not match, no need to check whole name */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
235
236
  		if (GET_HASH_VALUE(deh_offset(deh)) !=
  		    GET_HASH_VALUE(cpu_key_k_offset(key))) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
237
238
  			return NAME_NOT_FOUND;
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
239
  		/* mark that this generation number is used */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
240
241
  		if (de->de_gen_number_bit_string)
  			set_bit(GET_GENERATION_NUMBER(deh_offset(deh)),
3af1efe8a   Jeff Mahoney   [PATCH] reiserfs:...
242
  				de->de_gen_number_bit_string);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

098297b27   Jeff Mahoney   reiserfs: cleanup...
244
  		/* calculate pointer to name and namelen */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
245
246
  		de->de_entry_num = i;
  		set_de_name_and_namelen(de);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247

098297b27   Jeff Mahoney   reiserfs: cleanup...
248
249
250
251
  		/*
  		 * de's de_name, de_namelen, de_recordlen are set.
  		 * Fill the rest.
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
252
253
  		if ((retval =
  		     reiserfs_match(de, name, namelen)) != NAME_NOT_FOUND) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254

098297b27   Jeff Mahoney   reiserfs: cleanup...
255
  			/* key of pointed object */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
256
  			set_de_object_key(de);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257

bd4c625c0   Linus Torvalds   reiserfs: run scr...
258
  			store_de_entry_key(de);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259

098297b27   Jeff Mahoney   reiserfs: cleanup...
260
  			/* retval can be NAME_FOUND or NAME_FOUND_INVISIBLE */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
261
262
  			return retval;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264

bd4c625c0   Linus Torvalds   reiserfs: run scr...
265
  	if (GET_GENERATION_NUMBER(le_ih_k_offset(de->de_ih)) == 0)
098297b27   Jeff Mahoney   reiserfs: cleanup...
266
267
268
269
270
271
272
273
274
275
276
  		/*
  		 * we have reached left most entry in the node. In common we
  		 * have to go to the left neighbor, but if generation counter
  		 * is 0 already, we know for sure, that there is no name with
  		 * the same hash value
  		 */
  		/*
  		 * FIXME: this work correctly only because hash value can not
  		 *  be 0. Btw, in case of Yura's hash it is probably possible,
  		 * so, this is a bug
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
277
  		return NAME_NOT_FOUND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

bd4c625c0   Linus Torvalds   reiserfs: run scr...
279
280
  	RFALSE(de->de_item_num,
  	       "vs-7015: two diritems of the same directory in one node?");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281

bd4c625c0   Linus Torvalds   reiserfs: run scr...
282
283
  	return GOTO_PREVIOUS_ITEM;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284

098297b27   Jeff Mahoney   reiserfs: cleanup...
285
286
287
288
  /*
   * may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND
   * FIXME: should add something like IOERROR
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
289
  static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen,
fec6d055d   Josef "Jeff" Sipek   [PATCH] struct pa...
290
  			       struct treepath *path_to_entry,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
291
  			       struct reiserfs_dir_entry *de)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  	struct cpu_key key_to_search;
  	int retval;
  
  	if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize))
  		return NAME_NOT_FOUND;
  
  	/* we will search for this key in the tree */
  	make_cpu_key(&key_to_search, dir,
  		     get_third_component(dir->i_sb, name, namelen),
  		     TYPE_DIRENTRY, 3);
  
  	while (1) {
  		retval =
  		    search_by_entry_key(dir->i_sb, &key_to_search,
  					path_to_entry, de);
  		if (retval == IO_ERROR) {
0030b6457   Jeff Mahoney   reiserfs: use rei...
309
  			reiserfs_error(dir->i_sb, "zam-7001", "io error");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
310
311
312
313
314
315
316
  			return IO_ERROR;
  		}
  
  		/* compare names for all entries having given hash value */
  		retval =
  		    linear_search_in_dir_item(&key_to_search, de, name,
  					      namelen);
098297b27   Jeff Mahoney   reiserfs: cleanup...
317
318
319
320
  		/*
  		 * there is no need to scan directory anymore.
  		 * Given entry found or does not exist
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
321
  		if (retval != GOTO_PREVIOUS_ITEM) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
322
323
324
  			path_to_entry->pos_in_item = de->de_entry_num;
  			return retval;
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
325
326
327
328
  		/*
  		 * there is left neighboring item of this directory
  		 * and given entry can be there
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
329
330
331
332
333
  		set_cpu_key_k_offset(&key_to_search,
  				     le_ih_k_offset(de->de_ih) - 1);
  		pathrelse(path_to_entry);
  
  	}			/* while (1) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
335
  static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
00cd8dd3b   Al Viro   stop passing name...
336
  				      unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
338
339
340
341
342
343
344
  	int retval;
  	struct inode *inode = NULL;
  	struct reiserfs_dir_entry de;
  	INITIALIZE_PATH(path_to_entry);
  
  	if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len)
  		return ERR_PTR(-ENAMETOOLONG);
278f6679f   Jeff Mahoney   reiserfs: locking...
345
  	reiserfs_write_lock(dir->i_sb);
b1c839bb2   Frederic Weisbecker   kill-the-bkl/reis...
346

bd4c625c0   Linus Torvalds   reiserfs: run scr...
347
348
349
350
351
352
  	de.de_gen_number_bit_string = NULL;
  	retval =
  	    reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
  				&path_to_entry, &de);
  	pathrelse(&path_to_entry);
  	if (retval == NAME_FOUND) {
677c9b2e3   Jeff Mahoney   reiserfs: remove ...
353
  		inode = reiserfs_iget(dir->i_sb,
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
354
  				      (struct cpu_key *)&de.de_dir_id);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
355
  		if (!inode || IS_ERR(inode)) {
278f6679f   Jeff Mahoney   reiserfs: locking...
356
  			reiserfs_write_unlock(dir->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
357
358
  			return ERR_PTR(-EACCES);
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
359
360
361
362
  		/*
  		 * Propagate the private flag so we know we're
  		 * in the priv tree
  		 */
6dfede696   Jeff Mahoney   reiserfs: remove ...
363
364
  		if (IS_PRIVATE(dir))
  			inode->i_flags |= S_PRIVATE;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
365
  	}
278f6679f   Jeff Mahoney   reiserfs: locking...
366
  	reiserfs_write_unlock(dir->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
367
368
  	if (retval == IO_ERROR) {
  		return ERR_PTR(-EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
  	}
d9975d6ba   Pekka Enberg   [PATCH] reiserfs:...
370
  	return d_splice_alias(inode, dentry);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
371
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372

0222e6571   Jeff Mahoney   reiserfs: strip t...
373
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
374
375
376
   * looks up the dentry of the parent directory for child.
   * taken from ext2_get_parent
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
378
  struct dentry *reiserfs_get_parent(struct dentry *child)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
379
380
381
382
  	int retval;
  	struct inode *inode = NULL;
  	struct reiserfs_dir_entry de;
  	INITIALIZE_PATH(path_to_entry);
2b0143b5c   David Howells   VFS: normal files...
383
  	struct inode *dir = d_inode(child);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
384
385
386
387
388
389
390
391
392
393
394
395
396
  
  	if (dir->i_nlink == 0) {
  		return ERR_PTR(-ENOENT);
  	}
  	de.de_gen_number_bit_string = NULL;
  
  	reiserfs_write_lock(dir->i_sb);
  	retval = reiserfs_find_entry(dir, "..", 2, &path_to_entry, &de);
  	pathrelse(&path_to_entry);
  	if (retval != NAME_FOUND) {
  		reiserfs_write_unlock(dir->i_sb);
  		return ERR_PTR(-ENOENT);
  	}
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
397
  	inode = reiserfs_iget(dir->i_sb, (struct cpu_key *)&de.de_dir_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
  	reiserfs_write_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399

440037287   Christoph Hellwig   [PATCH] switch al...
400
  	return d_obtain_alias(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
401
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402

0222e6571   Jeff Mahoney   reiserfs: strip t...
403
  /* add entry to the directory (entry can be hidden).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
406
407
  
  insert definition of when hidden directories are used here -Hans
  
   Does not mark dir   inode dirty, do it after successesfull call to it */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
408
409
410
  static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
  			      struct inode *dir, const char *name, int namelen,
  			      struct inode *inode, int visible)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
412
413
414
415
  	struct cpu_key entry_key;
  	struct reiserfs_de_head *deh;
  	INITIALIZE_PATH(path);
  	struct reiserfs_dir_entry de;
3af1efe8a   Jeff Mahoney   [PATCH] reiserfs:...
416
  	DECLARE_BITMAP(bit_string, MAX_GENERATION_NUMBER + 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
417
  	int gen_number;
098297b27   Jeff Mahoney   reiserfs: cleanup...
418
419
420
421
422
423
  
  	/*
  	 * 48 bytes now and we avoid kmalloc if we
  	 * create file with short name
  	 */
  	char small_buf[32 + DEH_SIZE];
bd4c625c0   Linus Torvalds   reiserfs: run scr...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  	char *buffer;
  	int buflen, paste_size;
  	int retval;
  
  	BUG_ON(!th->t_trans_id);
  
  	/* cannot allow items to be added into a busy deleted directory */
  	if (!namelen)
  		return -EINVAL;
  
  	if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize))
  		return -ENAMETOOLONG;
  
  	/* each entry has unique key. compose it */
  	make_cpu_key(&entry_key, dir,
  		     get_third_component(dir->i_sb, name, namelen),
  		     TYPE_DIRENTRY, 3);
  
  	/* get memory for composing the entry */
  	buflen = DEH_SIZE + ROUND_UP(namelen);
  	if (buflen > sizeof(small_buf)) {
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
445
  		buffer = kmalloc(buflen, GFP_NOFS);
9dce07f1a   Al Viro   NULL noise: fs/*,...
446
  		if (!buffer)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
447
448
449
450
451
452
453
  			return -ENOMEM;
  	} else
  		buffer = small_buf;
  
  	paste_size =
  	    (get_inode_sd_version(dir) ==
  	     STAT_DATA_V1) ? (DEH_SIZE + namelen) : buflen;
098297b27   Jeff Mahoney   reiserfs: cleanup...
454
455
456
457
  	/*
  	 * fill buffer : directory entry head, name[, dir objectid | ,
  	 * stat data | ,stat data, dir objectid ]
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
458
459
460
461
462
  	deh = (struct reiserfs_de_head *)buffer;
  	deh->deh_location = 0;	/* JDM Endian safe if 0 */
  	put_deh_offset(deh, cpu_key_k_offset(&entry_key));
  	deh->deh_state = 0;	/* JDM Endian safe if 0 */
  	/* put key (ino analog) to de */
098297b27   Jeff Mahoney   reiserfs: cleanup...
463
464
465
466
467
  
  	/* safe: k_dir_id is le */
  	deh->deh_dir_id = INODE_PKEY(inode)->k_dir_id;
  	/* safe: k_objectid is le */
  	deh->deh_objectid = INODE_PKEY(inode)->k_objectid;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
468
469
470
471
472
  
  	/* copy name */
  	memcpy((char *)(deh + 1), name, namelen);
  	/* padd by 0s to the 4 byte boundary */
  	padd_item((char *)(deh + 1), ROUND_UP(namelen), namelen);
098297b27   Jeff Mahoney   reiserfs: cleanup...
473
474
475
476
  	/*
  	 * entry is ready to be pasted into tree, set 'visibility'
  	 * and 'stat data in entry' attributes
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
477
478
479
480
481
  	mark_de_without_sd(deh);
  	visible ? mark_de_visible(deh) : mark_de_hidden(deh);
  
  	/* find the proper place for the new entry */
  	memset(bit_string, 0, sizeof(bit_string));
3af1efe8a   Jeff Mahoney   [PATCH] reiserfs:...
482
  	de.de_gen_number_bit_string = bit_string;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
483
484
485
  	retval = reiserfs_find_entry(dir, name, namelen, &path, &de);
  	if (retval != NAME_NOT_FOUND) {
  		if (buffer != small_buf)
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
486
  			kfree(buffer);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
487
488
489
490
491
492
493
  		pathrelse(&path);
  
  		if (retval == IO_ERROR) {
  			return -EIO;
  		}
  
  		if (retval != NAME_FOUND) {
0030b6457   Jeff Mahoney   reiserfs: use rei...
494
495
496
  			reiserfs_error(dir->i_sb, "zam-7002",
  				       "reiserfs_find_entry() returned "
  				       "unexpected value (%d)", retval);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
497
498
499
500
  		}
  
  		return -EEXIST;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501

bd4c625c0   Linus Torvalds   reiserfs: run scr...
502
  	gen_number =
3af1efe8a   Jeff Mahoney   [PATCH] reiserfs:...
503
  	    find_first_zero_bit(bit_string,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
504
505
506
  				MAX_GENERATION_NUMBER + 1);
  	if (gen_number > MAX_GENERATION_NUMBER) {
  		/* there is no free generation number */
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
507
508
509
  		reiserfs_warning(dir->i_sb, "reiserfs-7010",
  				 "Congratulations! we have got hash function "
  				 "screwed up");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
510
  		if (buffer != small_buf)
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
511
  			kfree(buffer);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
512
513
514
515
516
517
518
519
520
  		pathrelse(&path);
  		return -EBUSY;
  	}
  	/* adjust offset of directory enrty */
  	put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number));
  	set_cpu_key_k_offset(&entry_key, deh_offset(deh));
  
  	/* update max-hash-collisions counter in reiserfs_sb_info */
  	PROC_INFO_MAX(th->t_super, max_hash_collisions, gen_number);
098297b27   Jeff Mahoney   reiserfs: cleanup...
521
522
  	/* we need to re-search for the insertion point */
  	if (gen_number != 0) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
523
524
  		if (search_by_entry_key(dir->i_sb, &entry_key, &path, &de) !=
  		    NAME_NOT_FOUND) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
525
526
527
  			reiserfs_warning(dir->i_sb, "vs-7032",
  					 "entry with this key (%K) already "
  					 "exists", &entry_key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
528
529
  
  			if (buffer != small_buf)
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
530
  				kfree(buffer);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
531
532
533
  			pathrelse(&path);
  			return -EBUSY;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
535
536
537
538
539
  	/* perform the insertion of the entry that we have prepared */
  	retval =
  	    reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer,
  				     paste_size);
  	if (buffer != small_buf)
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
540
  		kfree(buffer);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
541
542
543
  	if (retval) {
  		reiserfs_check_path(&path);
  		return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545

bd4c625c0   Linus Torvalds   reiserfs: run scr...
546
  	dir->i_size += paste_size;
02027d42c   Deepa Dinamani   fs: Replace CURRE...
547
  	dir->i_mtime = dir->i_ctime = current_time(dir);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
548
  	if (!S_ISDIR(inode->i_mode) && visible)
098297b27   Jeff Mahoney   reiserfs: cleanup...
549
  		/* reiserfs_mkdir or reiserfs_rename will do that by itself */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
550
  		reiserfs_update_sd(th, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551

bd4c625c0   Linus Torvalds   reiserfs: run scr...
552
553
  	reiserfs_check_path(&path);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
555
556
557
558
559
560
  /*
   * quota utility function, call if you've had to abort after calling
   * new_inode_init, and have not called reiserfs_new_inode yet.
   * This should only be called on inodes that do not have stat data
   * inserted into the tree yet.
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
561
562
  static int drop_new_inode(struct inode *inode)
  {
9f7547580   Christoph Hellwig   dquot: cleanup dq...
563
  	dquot_drop(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
564
565
566
567
  	make_bad_inode(inode);
  	inode->i_flags |= S_NOQUOTA;
  	iput(inode);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
569
570
571
572
573
574
  /*
   * utility function that does setup for reiserfs_new_inode.
   * dquot_initialize needs lots of credits so it's better to have it
   * outside of a transaction, so we had to pull some bits of
   * reiserfs_new_inode out into this func.
   */
8e0718924   Al Viro   reiserfs: propaga...
575
  static int new_inode_init(struct inode *inode, struct inode *dir, umode_t mode)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
576
  {
098297b27   Jeff Mahoney   reiserfs: cleanup...
577
578
579
580
  	/*
  	 * Make inode invalid - just in case we are going to drop it before
  	 * the initialization happens
  	 */
1b0a74d1c   Jan Kara   [PATCH] Fix error...
581
  	INODE_PKEY(inode)->k_objectid = 0;
098297b27   Jeff Mahoney   reiserfs: cleanup...
582
583
584
585
  
  	/*
  	 * the quota init calls have to know who to charge the quota to, so
  	 * we have to set uid and gid here
04b7ed0d3   Dmitry Monakhov   reiserfs: replace...
586
587
  	 */
  	inode_init_owner(inode, dir, mode);
2e6c97ea4   Jan Kara   reiserfs: Handle ...
588
  	return dquot_initialize(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
  }
4acdaf27e   Al Viro   switch ->create()...
590
  static int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
ebfc3b49a   Al Viro   don't pass nameid...
591
  			   bool excl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
593
594
  	int retval;
  	struct inode *inode;
098297b27   Jeff Mahoney   reiserfs: cleanup...
595
596
597
598
  	/*
  	 * We need blocks for transaction + (user+group)*(quotas
  	 * for new inode + update of quota for directory owner)
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
599
600
601
602
603
  	int jbegin_count =
  	    JOURNAL_PER_BALANCE_CNT * 2 +
  	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
  		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
  	struct reiserfs_transaction_handle th;
57fe60df6   Jeff Mahoney   reiserfs: add ato...
604
  	struct reiserfs_security_handle security;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
605

2e6c97ea4   Jan Kara   reiserfs: Handle ...
606
607
608
  	retval = dquot_initialize(dir);
  	if (retval)
  		return retval;
907f4554e   Christoph Hellwig   dquot: move dquot...
609

bd4c625c0   Linus Torvalds   reiserfs: run scr...
610
611
612
  	if (!(inode = new_inode(dir->i_sb))) {
  		return -ENOMEM;
  	}
2e6c97ea4   Jan Kara   reiserfs: Handle ...
613
614
615
616
617
  	retval = new_inode_init(inode, dir, mode);
  	if (retval) {
  		drop_new_inode(inode);
  		return retval;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618

0ab2621eb   Jeff Mahoney   reiserfs: journal...
619
  	jbegin_count += reiserfs_cache_default_acl(dir);
2a7dba391   Eric Paris   fs/vfs/security: ...
620
  	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
57fe60df6   Jeff Mahoney   reiserfs: add ato...
621
622
623
624
625
  	if (retval < 0) {
  		drop_new_inode(inode);
  		return retval;
  	}
  	jbegin_count += retval;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
626
  	reiserfs_write_lock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627

bd4c625c0   Linus Torvalds   reiserfs: run scr...
628
629
630
631
632
633
634
635
  	retval = journal_begin(&th, dir->i_sb, jbegin_count);
  	if (retval) {
  		drop_new_inode(inode);
  		goto out_failed;
  	}
  
  	retval =
  	    reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
57fe60df6   Jeff Mahoney   reiserfs: add ato...
636
  			       inode, &security);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
637
638
  	if (retval)
  		goto out_failed;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
639
640
641
642
643
644
645
646
647
  	inode->i_op = &reiserfs_file_inode_operations;
  	inode->i_fop = &reiserfs_file_operations;
  	inode->i_mapping->a_ops = &reiserfs_address_space_operations;
  
  	retval =
  	    reiserfs_add_entry(&th, dir, dentry->d_name.name,
  			       dentry->d_name.len, inode, 1 /*visible */ );
  	if (retval) {
  		int err;
6d6b77f16   Miklos Szeredi   filesystems: add ...
648
  		drop_nlink(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
649
  		reiserfs_update_sd(&th, inode);
58d854265   Jeff Mahoney   reiserfs: cleanup...
650
  		err = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
651
652
  		if (err)
  			retval = err;
c1eaa26b6   Al Viro   nfsd race fixes: ...
653
  		unlock_new_inode(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
654
655
656
657
658
  		iput(inode);
  		goto out_failed;
  	}
  	reiserfs_update_inode_transaction(inode);
  	reiserfs_update_inode_transaction(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659

f440ea85d   Al Viro   do d_instantiate/...
660
  	d_instantiate_new(dentry, inode);
58d854265   Jeff Mahoney   reiserfs: cleanup...
661
  	retval = journal_end(&th);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662

cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
663
  out_failed:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
664
665
666
  	reiserfs_write_unlock(dir->i_sb);
  	return retval;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667

1a67aafb5   Al Viro   switch ->mknod() ...
668
  static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
669
670
671
672
673
  			  dev_t rdev)
  {
  	int retval;
  	struct inode *inode;
  	struct reiserfs_transaction_handle th;
57fe60df6   Jeff Mahoney   reiserfs: add ato...
674
  	struct reiserfs_security_handle security;
098297b27   Jeff Mahoney   reiserfs: cleanup...
675
676
677
678
  	/*
  	 * We need blocks for transaction + (user+group)*(quotas
  	 * for new inode + update of quota for directory owner)
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
679
680
681
682
  	int jbegin_count =
  	    JOURNAL_PER_BALANCE_CNT * 3 +
  	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
  		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
683

2e6c97ea4   Jan Kara   reiserfs: Handle ...
684
685
686
  	retval = dquot_initialize(dir);
  	if (retval)
  		return retval;
907f4554e   Christoph Hellwig   dquot: move dquot...
687

bd4c625c0   Linus Torvalds   reiserfs: run scr...
688
689
690
  	if (!(inode = new_inode(dir->i_sb))) {
  		return -ENOMEM;
  	}
2e6c97ea4   Jan Kara   reiserfs: Handle ...
691
692
693
694
695
  	retval = new_inode_init(inode, dir, mode);
  	if (retval) {
  		drop_new_inode(inode);
  		return retval;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696

0ab2621eb   Jeff Mahoney   reiserfs: journal...
697
  	jbegin_count += reiserfs_cache_default_acl(dir);
2a7dba391   Eric Paris   fs/vfs/security: ...
698
  	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
57fe60df6   Jeff Mahoney   reiserfs: add ato...
699
700
701
702
703
  	if (retval < 0) {
  		drop_new_inode(inode);
  		return retval;
  	}
  	jbegin_count += retval;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
704
  	reiserfs_write_lock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705

bd4c625c0   Linus Torvalds   reiserfs: run scr...
706
707
708
709
710
  	retval = journal_begin(&th, dir->i_sb, jbegin_count);
  	if (retval) {
  		drop_new_inode(inode);
  		goto out_failed;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711

bd4c625c0   Linus Torvalds   reiserfs: run scr...
712
713
  	retval =
  	    reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
57fe60df6   Jeff Mahoney   reiserfs: add ato...
714
  			       inode, &security);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
715
716
717
  	if (retval) {
  		goto out_failed;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718

bd4c625c0   Linus Torvalds   reiserfs: run scr...
719
720
  	inode->i_op = &reiserfs_special_inode_operations;
  	init_special_inode(inode, inode->i_mode, rdev);
098297b27   Jeff Mahoney   reiserfs: cleanup...
721
  	/* FIXME: needed for block and char devices only */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
722
723
724
725
726
727
728
729
730
731
  	reiserfs_update_sd(&th, inode);
  
  	reiserfs_update_inode_transaction(inode);
  	reiserfs_update_inode_transaction(dir);
  
  	retval =
  	    reiserfs_add_entry(&th, dir, dentry->d_name.name,
  			       dentry->d_name.len, inode, 1 /*visible */ );
  	if (retval) {
  		int err;
6d6b77f16   Miklos Szeredi   filesystems: add ...
732
  		drop_nlink(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
733
  		reiserfs_update_sd(&th, inode);
58d854265   Jeff Mahoney   reiserfs: cleanup...
734
  		err = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
735
736
  		if (err)
  			retval = err;
c1eaa26b6   Al Viro   nfsd race fixes: ...
737
  		unlock_new_inode(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
738
739
740
  		iput(inode);
  		goto out_failed;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741

f440ea85d   Al Viro   do d_instantiate/...
742
  	d_instantiate_new(dentry, inode);
58d854265   Jeff Mahoney   reiserfs: cleanup...
743
  	retval = journal_end(&th);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744

cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
745
  out_failed:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
746
747
  	reiserfs_write_unlock(dir->i_sb);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  }
18bb1db3e   Al Viro   switch vfs_mkdir(...
749
  static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
751
752
753
  	int retval;
  	struct inode *inode;
  	struct reiserfs_transaction_handle th;
57fe60df6   Jeff Mahoney   reiserfs: add ato...
754
  	struct reiserfs_security_handle security;
098297b27   Jeff Mahoney   reiserfs: cleanup...
755
756
757
758
  	/*
  	 * We need blocks for transaction + (user+group)*(quotas
  	 * for new inode + update of quota for directory owner)
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
759
760
761
762
  	int jbegin_count =
  	    JOURNAL_PER_BALANCE_CNT * 3 +
  	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
  		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763

2e6c97ea4   Jan Kara   reiserfs: Handle ...
764
765
766
  	retval = dquot_initialize(dir);
  	if (retval)
  		return retval;
907f4554e   Christoph Hellwig   dquot: move dquot...
767

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
  #ifdef DISPLACE_NEW_PACKING_LOCALITIES
098297b27   Jeff Mahoney   reiserfs: cleanup...
769
770
771
772
  	/*
  	 * set flag that new packing locality created and new blocks
  	 * for the content of that directory are not displaced yet
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
773
  	REISERFS_I(dir)->new_packing_locality = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
775
776
777
778
  	mode = S_IFDIR | mode;
  	if (!(inode = new_inode(dir->i_sb))) {
  		return -ENOMEM;
  	}
2e6c97ea4   Jan Kara   reiserfs: Handle ...
779
780
781
782
783
  	retval = new_inode_init(inode, dir, mode);
  	if (retval) {
  		drop_new_inode(inode);
  		return retval;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
784

0ab2621eb   Jeff Mahoney   reiserfs: journal...
785
  	jbegin_count += reiserfs_cache_default_acl(dir);
2a7dba391   Eric Paris   fs/vfs/security: ...
786
  	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
57fe60df6   Jeff Mahoney   reiserfs: add ato...
787
788
789
790
791
  	if (retval < 0) {
  		drop_new_inode(inode);
  		return retval;
  	}
  	jbegin_count += retval;
278f6679f   Jeff Mahoney   reiserfs: locking...
792
  	reiserfs_write_lock(dir->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
793
794
795
796
797
798
  
  	retval = journal_begin(&th, dir->i_sb, jbegin_count);
  	if (retval) {
  		drop_new_inode(inode);
  		goto out_failed;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799

098297b27   Jeff Mahoney   reiserfs: cleanup...
800
801
802
  	/*
  	 * inc the link count now, so another writer doesn't overflow
  	 * it while we sleep later on.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
803
804
805
806
807
808
  	 */
  	INC_DIR_INODE_NLINK(dir)
  
  	    retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ ,
  					old_format_only(dir->i_sb) ?
  					EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
57fe60df6   Jeff Mahoney   reiserfs: add ato...
809
  					dentry, inode, &security);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
810
  	if (retval) {
99890a3be   Al Viro   fix reiserfs mkdi...
811
  		DEC_DIR_INODE_NLINK(dir)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
812
813
  		goto out_failed;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
814
815
816
817
818
  	reiserfs_update_inode_transaction(inode);
  	reiserfs_update_inode_transaction(dir);
  
  	inode->i_op = &reiserfs_dir_inode_operations;
  	inode->i_fop = &reiserfs_dir_operations;
098297b27   Jeff Mahoney   reiserfs: cleanup...
819
  	/* note, _this_ add_entry will not update dir's stat data */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
820
821
822
823
824
  	retval =
  	    reiserfs_add_entry(&th, dir, dentry->d_name.name,
  			       dentry->d_name.len, inode, 1 /*visible */ );
  	if (retval) {
  		int err;
6d6b77f16   Miklos Szeredi   filesystems: add ...
825
  		clear_nlink(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
826
827
  		DEC_DIR_INODE_NLINK(dir);
  		reiserfs_update_sd(&th, inode);
58d854265   Jeff Mahoney   reiserfs: cleanup...
828
  		err = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
829
830
  		if (err)
  			retval = err;
c1eaa26b6   Al Viro   nfsd race fixes: ...
831
  		unlock_new_inode(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
832
833
834
  		iput(inode);
  		goto out_failed;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
835
  	/* the above add_entry did not update dir's stat data */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
836
  	reiserfs_update_sd(&th, dir);
f440ea85d   Al Viro   do d_instantiate/...
837
  	d_instantiate_new(dentry, inode);
58d854265   Jeff Mahoney   reiserfs: cleanup...
838
  	retval = journal_end(&th);
b10ab4c33   Frederic Weisbecker   kill-the-bkl/reis...
839
  out_failed:
278f6679f   Jeff Mahoney   reiserfs: locking...
840
  	reiserfs_write_unlock(dir->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
841
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
842
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
843
  static inline int reiserfs_empty_dir(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
  {
098297b27   Jeff Mahoney   reiserfs: cleanup...
845
846
847
848
849
  	/*
  	 * we can cheat because an old format dir cannot have
  	 * EMPTY_DIR_SIZE, and a new format dir cannot have
  	 * EMPTY_DIR_SIZE_V1.  So, if the inode is either size,
  	 * regardless of disk format version, the directory is empty.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
850
851
852
853
854
855
  	 */
  	if (inode->i_size != EMPTY_DIR_SIZE &&
  	    inode->i_size != EMPTY_DIR_SIZE_V1) {
  		return 0;
  	}
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
857
  static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
859
860
861
862
863
864
  	int retval, err;
  	struct inode *inode;
  	struct reiserfs_transaction_handle th;
  	int jbegin_count;
  	INITIALIZE_PATH(path);
  	struct reiserfs_dir_entry de;
098297b27   Jeff Mahoney   reiserfs: cleanup...
865
866
867
868
869
870
  	/*
  	 * we will be doing 2 balancings and update 2 stat data, we
  	 * change quotas of the owner of the directory and of the owner
  	 * of the parent directory.  The quota structure is possibly
  	 * deleted only on last iput => outside of this transaction
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
871
872
873
  	jbegin_count =
  	    JOURNAL_PER_BALANCE_CNT * 2 + 2 +
  	    4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
2e6c97ea4   Jan Kara   reiserfs: Handle ...
874
875
876
  	retval = dquot_initialize(dir);
  	if (retval)
  		return retval;
907f4554e   Christoph Hellwig   dquot: move dquot...
877

bd4c625c0   Linus Torvalds   reiserfs: run scr...
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
  	reiserfs_write_lock(dir->i_sb);
  	retval = journal_begin(&th, dir->i_sb, jbegin_count);
  	if (retval)
  		goto out_rmdir;
  
  	de.de_gen_number_bit_string = NULL;
  	if ((retval =
  	     reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
  				 &path, &de)) == NAME_NOT_FOUND) {
  		retval = -ENOENT;
  		goto end_rmdir;
  	} else if (retval == IO_ERROR) {
  		retval = -EIO;
  		goto end_rmdir;
  	}
2b0143b5c   David Howells   VFS: normal files...
893
  	inode = d_inode(dentry);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
894
895
896
897
898
  
  	reiserfs_update_inode_transaction(inode);
  	reiserfs_update_inode_transaction(dir);
  
  	if (de.de_objectid != inode->i_ino) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
899
900
901
  		/*
  		 * FIXME: compare key of an object and a key found in the entry
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
902
903
904
905
906
907
908
909
910
  		retval = -EIO;
  		goto end_rmdir;
  	}
  	if (!reiserfs_empty_dir(inode)) {
  		retval = -ENOTEMPTY;
  		goto end_rmdir;
  	}
  
  	/* cut entry from dir directory */
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
911
912
  	retval = reiserfs_cut_from_item(&th, &path, &de.de_entry_key,
  					dir, NULL,	/* page */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
913
914
915
916
917
  					0 /*new file size - not used here */ );
  	if (retval < 0)
  		goto end_rmdir;
  
  	if (inode->i_nlink != 2 && inode->i_nlink != 1)
0030b6457   Jeff Mahoney   reiserfs: use rei...
918
919
920
  		reiserfs_error(inode->i_sb, "reiserfs-7040",
  			       "empty directory has nlink != 2 (%d)",
  			       inode->i_nlink);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
921

ce71ec368   Dave Hansen   [PATCH] r/o bind ...
922
  	clear_nlink(inode);
02027d42c   Deepa Dinamani   fs: Replace CURRE...
923
  	inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(dir);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
924
925
926
927
928
929
930
931
  	reiserfs_update_sd(&th, inode);
  
  	DEC_DIR_INODE_NLINK(dir)
  	    dir->i_size -= (DEH_SIZE + de.de_entrylen);
  	reiserfs_update_sd(&th, dir);
  
  	/* prevent empty directory from getting lost */
  	add_save_link(&th, inode, 0 /* not truncate */ );
58d854265   Jeff Mahoney   reiserfs: cleanup...
932
  	retval = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
933
  	reiserfs_check_path(&path);
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
934
  out_rmdir:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
935
936
  	reiserfs_write_unlock(dir->i_sb);
  	return retval;
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
937
  end_rmdir:
098297b27   Jeff Mahoney   reiserfs: cleanup...
938
939
940
941
942
  	/*
  	 * we must release path, because we did not call
  	 * reiserfs_cut_from_item, or reiserfs_cut_from_item does not
  	 * release path if operation was not complete
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
943
  	pathrelse(&path);
58d854265   Jeff Mahoney   reiserfs: cleanup...
944
  	err = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
945
946
  	reiserfs_write_unlock(dir->i_sb);
  	return err ? err : retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
948
  static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
950
951
952
953
954
955
956
  	int retval, err;
  	struct inode *inode;
  	struct reiserfs_dir_entry de;
  	INITIALIZE_PATH(path);
  	struct reiserfs_transaction_handle th;
  	int jbegin_count;
  	unsigned long savelink;
2e6c97ea4   Jan Kara   reiserfs: Handle ...
957
958
959
  	retval = dquot_initialize(dir);
  	if (retval)
  		return retval;
907f4554e   Christoph Hellwig   dquot: move dquot...
960

2b0143b5c   David Howells   VFS: normal files...
961
  	inode = d_inode(dentry);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
962

098297b27   Jeff Mahoney   reiserfs: cleanup...
963
964
965
966
967
968
969
  	/*
  	 * in this transaction we can be doing at max two balancings and
  	 * update two stat datas, we change quotas of the owner of the
  	 * directory and of the owner of the parent directory. The quota
  	 * structure is possibly deleted only on iput => outside of
  	 * this transaction
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
970
971
972
  	jbegin_count =
  	    JOURNAL_PER_BALANCE_CNT * 2 + 2 +
  	    4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
278f6679f   Jeff Mahoney   reiserfs: locking...
973
  	reiserfs_write_lock(dir->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
  	retval = journal_begin(&th, dir->i_sb, jbegin_count);
  	if (retval)
  		goto out_unlink;
  
  	de.de_gen_number_bit_string = NULL;
  	if ((retval =
  	     reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
  				 &path, &de)) == NAME_NOT_FOUND) {
  		retval = -ENOENT;
  		goto end_unlink;
  	} else if (retval == IO_ERROR) {
  		retval = -EIO;
  		goto end_unlink;
  	}
  
  	reiserfs_update_inode_transaction(inode);
  	reiserfs_update_inode_transaction(dir);
  
  	if (de.de_objectid != inode->i_ino) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
993
994
995
  		/*
  		 * FIXME: compare key of an object and a key found in the entry
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
996
997
998
999
1000
  		retval = -EIO;
  		goto end_unlink;
  	}
  
  	if (!inode->i_nlink) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1001
1002
1003
  		reiserfs_warning(inode->i_sb, "reiserfs-7042",
  				 "deleting nonexistent file (%lu), %d",
  				 inode->i_ino, inode->i_nlink);
bfe868486   Miklos Szeredi   filesystems: add ...
1004
  		set_nlink(inode, 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1005
  	}
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1006
  	drop_nlink(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1007
1008
1009
1010
1011
1012
1013
1014
  
  	/*
  	 * we schedule before doing the add_save_link call, save the link
  	 * count so we don't race
  	 */
  	savelink = inode->i_nlink;
  
  	retval =
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1015
  	    reiserfs_cut_from_item(&th, &path, &de.de_entry_key, dir, NULL,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1016
1017
  				   0);
  	if (retval < 0) {
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
1018
  		inc_nlink(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1019
1020
  		goto end_unlink;
  	}
02027d42c   Deepa Dinamani   fs: Replace CURRE...
1021
  	inode->i_ctime = current_time(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1022
1023
1024
  	reiserfs_update_sd(&th, inode);
  
  	dir->i_size -= (de.de_entrylen + DEH_SIZE);
02027d42c   Deepa Dinamani   fs: Replace CURRE...
1025
  	dir->i_ctime = dir->i_mtime = current_time(dir);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1026
1027
1028
1029
1030
  	reiserfs_update_sd(&th, dir);
  
  	if (!savelink)
  		/* prevent file from getting lost */
  		add_save_link(&th, inode, 0 /* not truncate */ );
58d854265   Jeff Mahoney   reiserfs: cleanup...
1031
  	retval = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1032
  	reiserfs_check_path(&path);
278f6679f   Jeff Mahoney   reiserfs: locking...
1033
  	reiserfs_write_unlock(dir->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1034
  	return retval;
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
1035
  end_unlink:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1036
  	pathrelse(&path);
58d854265   Jeff Mahoney   reiserfs: cleanup...
1037
  	err = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1038
  	reiserfs_check_path(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
  	if (err)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1040
  		retval = err;
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
1041
  out_unlink:
278f6679f   Jeff Mahoney   reiserfs: locking...
1042
  	reiserfs_write_unlock(dir->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1043
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1044
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1045
1046
  static int reiserfs_symlink(struct inode *parent_dir,
  			    struct dentry *dentry, const char *symname)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1048
1049
1050
1051
1052
  	int retval;
  	struct inode *inode;
  	char *name;
  	int item_len;
  	struct reiserfs_transaction_handle th;
57fe60df6   Jeff Mahoney   reiserfs: add ato...
1053
  	struct reiserfs_security_handle security;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1054
  	int mode = S_IFLNK | S_IRWXUGO;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1055
1056
1057
1058
  	/*
  	 * We need blocks for transaction + (user+group)*(quotas for
  	 * new inode + update of quota for directory owner)
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1059
1060
1061
1062
  	int jbegin_count =
  	    JOURNAL_PER_BALANCE_CNT * 3 +
  	    2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb) +
  		 REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb));
2e6c97ea4   Jan Kara   reiserfs: Handle ...
1063
1064
1065
  	retval = dquot_initialize(parent_dir);
  	if (retval)
  		return retval;
907f4554e   Christoph Hellwig   dquot: move dquot...
1066

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1067
1068
1069
  	if (!(inode = new_inode(parent_dir->i_sb))) {
  		return -ENOMEM;
  	}
2e6c97ea4   Jan Kara   reiserfs: Handle ...
1070
1071
1072
1073
1074
  	retval = new_inode_init(inode, parent_dir, mode);
  	if (retval) {
  		drop_new_inode(inode);
  		return retval;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1075

2a7dba391   Eric Paris   fs/vfs/security: ...
1076
1077
  	retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name,
  					&security);
57fe60df6   Jeff Mahoney   reiserfs: add ato...
1078
1079
1080
1081
1082
  	if (retval < 0) {
  		drop_new_inode(inode);
  		return retval;
  	}
  	jbegin_count += retval;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1083
1084
1085
1086
1087
1088
1089
  	reiserfs_write_lock(parent_dir->i_sb);
  	item_len = ROUND_UP(strlen(symname));
  	if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) {
  		retval = -ENAMETOOLONG;
  		drop_new_inode(inode);
  		goto out_failed;
  	}
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
1090
  	name = kmalloc(item_len, GFP_NOFS);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1091
1092
1093
1094
1095
1096
1097
  	if (!name) {
  		drop_new_inode(inode);
  		retval = -ENOMEM;
  		goto out_failed;
  	}
  	memcpy(name, symname, strlen(symname));
  	padd_item(name, item_len, strlen(symname));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1098
1099
1100
  	retval = journal_begin(&th, parent_dir->i_sb, jbegin_count);
  	if (retval) {
  		drop_new_inode(inode);
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
1101
  		kfree(name);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1102
1103
1104
1105
1106
  		goto out_failed;
  	}
  
  	retval =
  	    reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname),
57fe60df6   Jeff Mahoney   reiserfs: add ato...
1107
  			       dentry, inode, &security);
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
1108
  	kfree(name);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1109
1110
1111
  	if (retval) {		/* reiserfs_new_inode iputs for us */
  		goto out_failed;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1113
1114
1115
1116
  	reiserfs_update_inode_transaction(inode);
  	reiserfs_update_inode_transaction(parent_dir);
  
  	inode->i_op = &reiserfs_symlink_inode_operations;
21fc61c73   Al Viro   don't put symlink...
1117
  	inode_nohighmem(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1118
  	inode->i_mapping->a_ops = &reiserfs_address_space_operations;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1119
1120
1121
1122
  	retval = reiserfs_add_entry(&th, parent_dir, dentry->d_name.name,
  				    dentry->d_name.len, inode, 1 /*visible */ );
  	if (retval) {
  		int err;
6d6b77f16   Miklos Szeredi   filesystems: add ...
1123
  		drop_nlink(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1124
  		reiserfs_update_sd(&th, inode);
58d854265   Jeff Mahoney   reiserfs: cleanup...
1125
  		err = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1126
1127
  		if (err)
  			retval = err;
c1eaa26b6   Al Viro   nfsd race fixes: ...
1128
  		unlock_new_inode(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1129
1130
1131
  		iput(inode);
  		goto out_failed;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132

f440ea85d   Al Viro   do d_instantiate/...
1133
  	d_instantiate_new(dentry, inode);
58d854265   Jeff Mahoney   reiserfs: cleanup...
1134
  	retval = journal_end(&th);
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
1135
  out_failed:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1136
1137
  	reiserfs_write_unlock(parent_dir->i_sb);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1138
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1139
1140
1141
1142
  static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
  			 struct dentry *dentry)
  {
  	int retval;
2b0143b5c   David Howells   VFS: normal files...
1143
  	struct inode *inode = d_inode(old_dentry);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1144
  	struct reiserfs_transaction_handle th;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1145
1146
1147
1148
  	/*
  	 * We need blocks for transaction + update of quotas for
  	 * the owners of the directory
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1149
1150
1151
  	int jbegin_count =
  	    JOURNAL_PER_BALANCE_CNT * 3 +
  	    2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
2e6c97ea4   Jan Kara   reiserfs: Handle ...
1152
1153
1154
  	retval = dquot_initialize(dir);
  	if (retval)
  		return retval;
907f4554e   Christoph Hellwig   dquot: move dquot...
1155

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1156
1157
  	reiserfs_write_lock(dir->i_sb);
  	if (inode->i_nlink >= REISERFS_LINK_MAX) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
1158
  		/* FIXME: sd_nlink is 32 bit for new files */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1159
1160
1161
  		reiserfs_write_unlock(dir->i_sb);
  		return -EMLINK;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1162
1163
  
  	/* inc before scheduling so reiserfs_unlink knows we are here */
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
1164
  	inc_nlink(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1165
1166
1167
  
  	retval = journal_begin(&th, dir->i_sb, jbegin_count);
  	if (retval) {
6d6b77f16   Miklos Szeredi   filesystems: add ...
1168
  		drop_nlink(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
  		reiserfs_write_unlock(dir->i_sb);
  		return retval;
  	}
  
  	/* create new entry */
  	retval =
  	    reiserfs_add_entry(&th, dir, dentry->d_name.name,
  			       dentry->d_name.len, inode, 1 /*visible */ );
  
  	reiserfs_update_inode_transaction(inode);
  	reiserfs_update_inode_transaction(dir);
  
  	if (retval) {
  		int err;
6d6b77f16   Miklos Szeredi   filesystems: add ...
1183
  		drop_nlink(inode);
58d854265   Jeff Mahoney   reiserfs: cleanup...
1184
  		err = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1185
1186
1187
  		reiserfs_write_unlock(dir->i_sb);
  		return err ? err : retval;
  	}
02027d42c   Deepa Dinamani   fs: Replace CURRE...
1188
  	inode->i_ctime = current_time(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1189
  	reiserfs_update_sd(&th, inode);
7de9c6ee3   Al Viro   new helper: ihold()
1190
  	ihold(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1191
  	d_instantiate(dentry, inode);
58d854265   Jeff Mahoney   reiserfs: cleanup...
1192
  	retval = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1193
1194
1195
  	reiserfs_write_unlock(dir->i_sb);
  	return retval;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1196

0222e6571   Jeff Mahoney   reiserfs: strip t...
1197
  /* de contains information pointing to an entry which */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1198
1199
  static int de_still_valid(const char *name, int len,
  			  struct reiserfs_dir_entry *de)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1200
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1201
  	struct reiserfs_dir_entry tmp = *de;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1202
  	/* recalculate pointer to name and name length */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1203
  	set_de_name_and_namelen(&tmp);
098297b27   Jeff Mahoney   reiserfs: cleanup...
1204
  	/* FIXME: could check more */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1205
1206
1207
  	if (tmp.de_namelen != len || memcmp(name, de->de_name, len))
  		return 0;
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1209
1210
1211
  static int entry_points_to_object(const char *name, int len,
  				  struct reiserfs_dir_entry *de,
  				  struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1212
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1213
1214
1215
1216
1217
  	if (!de_still_valid(name, len, de))
  		return 0;
  
  	if (inode) {
  		if (!de_visible(de->de_deh + de->de_entry_num))
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1218
1219
  			reiserfs_panic(inode->i_sb, "vs-7042",
  				       "entry must be visible");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1220
1221
  		return (de->de_objectid == inode->i_ino) ? 1 : 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1223
1224
  	/* this must be added hidden entry */
  	if (de_visible(de->de_deh + de->de_entry_num))
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1225
  		reiserfs_panic(NULL, "vs-7043", "entry must be visible");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1227
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1229
  /* sets key of objectid the entry has to point to */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1230
1231
  static void set_ino_in_dir_entry(struct reiserfs_dir_entry *de,
  				 struct reiserfs_key *key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1233
1234
1235
  	/* JDM These operations are endian safe - both are le */
  	de->de_deh[de->de_entry_num].deh_dir_id = key->k_dir_id;
  	de->de_deh[de->de_entry_num].deh_objectid = key->k_objectid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
  }
0222e6571   Jeff Mahoney   reiserfs: strip t...
1237
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1238
1239
   * process, that is going to call fix_nodes/do_balance must hold only
   * one path. If it holds 2 or more, it can get into endless waiting in
0222e6571   Jeff Mahoney   reiserfs: strip t...
1240
   * get_empty_nodes or its clones
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1242
  static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
f03b8ad8d   Miklos Szeredi   fs: support RENAM...
1243
1244
  			   struct inode *new_dir, struct dentry *new_dentry,
  			   unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1245
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
  	int retval;
  	INITIALIZE_PATH(old_entry_path);
  	INITIALIZE_PATH(new_entry_path);
  	INITIALIZE_PATH(dot_dot_entry_path);
  	struct item_head new_entry_ih, old_entry_ih, dot_dot_ih;
  	struct reiserfs_dir_entry old_de, new_de, dot_dot_de;
  	struct inode *old_inode, *new_dentry_inode;
  	struct reiserfs_transaction_handle th;
  	int jbegin_count;
  	umode_t old_inode_mode;
  	unsigned long savelink = 1;
  	struct timespec ctime;
f03b8ad8d   Miklos Szeredi   fs: support RENAM...
1258
1259
  	if (flags & ~RENAME_NOREPLACE)
  		return -EINVAL;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
  	/*
  	 * three balancings: (1) old name removal, (2) new name insertion
  	 * and (3) maybe "save" link insertion
  	 * stat data updates: (1) old directory,
  	 * (2) new directory and (3) maybe old object stat data (when it is
  	 * directory) and (4) maybe stat data of object to which new entry
  	 * pointed initially and (5) maybe block containing ".." of
  	 * renamed directory
  	 * quota updates: two parent directories
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1270
1271
1272
  	jbegin_count =
  	    JOURNAL_PER_BALANCE_CNT * 3 + 5 +
  	    4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);
2e6c97ea4   Jan Kara   reiserfs: Handle ...
1273
1274
1275
1276
1277
1278
  	retval = dquot_initialize(old_dir);
  	if (retval)
  		return retval;
  	retval = dquot_initialize(new_dir);
  	if (retval)
  		return retval;
907f4554e   Christoph Hellwig   dquot: move dquot...
1279

2b0143b5c   David Howells   VFS: normal files...
1280
1281
  	old_inode = d_inode(old_dentry);
  	new_dentry_inode = d_inode(new_dentry);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1282

098297b27   Jeff Mahoney   reiserfs: cleanup...
1283
1284
1285
1286
  	/*
  	 * make sure that oldname still exists and points to an object we
  	 * are going to rename
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1287
1288
1289
1290
1291
1292
1293
1294
  	old_de.de_gen_number_bit_string = NULL;
  	reiserfs_write_lock(old_dir->i_sb);
  	retval =
  	    reiserfs_find_entry(old_dir, old_dentry->d_name.name,
  				old_dentry->d_name.len, &old_entry_path,
  				&old_de);
  	pathrelse(&old_entry_path);
  	if (retval == IO_ERROR) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295
  		reiserfs_write_unlock(old_dir->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1296
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1298
1299
1300
1301
  
  	if (retval != NAME_FOUND || old_de.de_objectid != old_inode->i_ino) {
  		reiserfs_write_unlock(old_dir->i_sb);
  		return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1303
1304
  	old_inode_mode = old_inode->i_mode;
  	if (S_ISDIR(old_inode_mode)) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
1305
1306
1307
1308
1309
  		/*
  		 * make sure that directory being renamed has correct ".."
  		 * and that its new parent directory has not too many links
  		 * already
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1310
1311
1312
1313
1314
1315
  		if (new_dentry_inode) {
  			if (!reiserfs_empty_dir(new_dentry_inode)) {
  				reiserfs_write_unlock(old_dir->i_sb);
  				return -ENOTEMPTY;
  			}
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1316
1317
1318
  		/*
  		 * directory is renamed, its parent directory will be changed,
  		 * so find ".." entry
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
  		 */
  		dot_dot_de.de_gen_number_bit_string = NULL;
  		retval =
  		    reiserfs_find_entry(old_inode, "..", 2, &dot_dot_entry_path,
  					&dot_dot_de);
  		pathrelse(&dot_dot_entry_path);
  		if (retval != NAME_FOUND) {
  			reiserfs_write_unlock(old_dir->i_sb);
  			return -EIO;
  		}
  
  		/* inode number of .. must equal old_dir->i_ino */
  		if (dot_dot_de.de_objectid != old_dir->i_ino) {
  			reiserfs_write_unlock(old_dir->i_sb);
  			return -EIO;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1336
1337
1338
1339
1340
  
  	retval = journal_begin(&th, old_dir->i_sb, jbegin_count);
  	if (retval) {
  		reiserfs_write_unlock(old_dir->i_sb);
  		return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1342
1343
1344
1345
1346
1347
1348
  
  	/* add new entry (or find the existing one) */
  	retval =
  	    reiserfs_add_entry(&th, new_dir, new_dentry->d_name.name,
  			       new_dentry->d_name.len, old_inode, 0);
  	if (retval == -EEXIST) {
  		if (!new_dentry_inode) {
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1349
1350
  			reiserfs_panic(old_dir->i_sb, "vs-7050",
  				       "new entry is found, new inode == 0");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1351
1352
  		}
  	} else if (retval) {
58d854265   Jeff Mahoney   reiserfs: cleanup...
1353
  		int err = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1354
1355
  		reiserfs_write_unlock(old_dir->i_sb);
  		return err ? err : retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1357
1358
  	reiserfs_update_inode_transaction(old_dir);
  	reiserfs_update_inode_transaction(new_dir);
098297b27   Jeff Mahoney   reiserfs: cleanup...
1359
1360
1361
  	/*
  	 * this makes it so an fsync on an open fd for the old name will
  	 * commit the rename operation
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1362
1363
1364
1365
1366
1367
1368
  	 */
  	reiserfs_update_inode_transaction(old_inode);
  
  	if (new_dentry_inode)
  		reiserfs_update_inode_transaction(new_dentry_inode);
  
  	while (1) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
1369
1370
1371
1372
  		/*
  		 * look for old name using corresponding entry key
  		 * (found by reiserfs_find_entry)
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1373
1374
1375
1376
1377
  		if ((retval =
  		     search_by_entry_key(new_dir->i_sb, &old_de.de_entry_key,
  					 &old_entry_path,
  					 &old_de)) != NAME_FOUND) {
  			pathrelse(&old_entry_path);
58d854265   Jeff Mahoney   reiserfs: cleanup...
1378
  			journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1379
1380
1381
  			reiserfs_write_unlock(old_dir->i_sb);
  			return -EIO;
  		}
4cf5f7add   Jeff Mahoney   reiserfs: cleanup...
1382
  		copy_item_head(&old_entry_ih, tp_item_head(&old_entry_path));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1383
1384
  
  		reiserfs_prepare_for_journal(old_inode->i_sb, old_de.de_bh, 1);
098297b27   Jeff Mahoney   reiserfs: cleanup...
1385
  		/* look for new name by reiserfs_find_entry */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1386
1387
1388
1389
1390
  		new_de.de_gen_number_bit_string = NULL;
  		retval =
  		    reiserfs_find_entry(new_dir, new_dentry->d_name.name,
  					new_dentry->d_name.len, &new_entry_path,
  					&new_de);
098297b27   Jeff Mahoney   reiserfs: cleanup...
1391
1392
1393
1394
1395
1396
  		/*
  		 * reiserfs_add_entry should not return IO_ERROR,
  		 * because it is called with essentially same parameters from
  		 * reiserfs_add_entry above, and we'll catch any i/o errors
  		 * before we get here.
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1397
1398
1399
  		if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) {
  			pathrelse(&new_entry_path);
  			pathrelse(&old_entry_path);
58d854265   Jeff Mahoney   reiserfs: cleanup...
1400
  			journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1401
1402
1403
  			reiserfs_write_unlock(old_dir->i_sb);
  			return -EIO;
  		}
4cf5f7add   Jeff Mahoney   reiserfs: cleanup...
1404
  		copy_item_head(&new_entry_ih, tp_item_head(&new_entry_path));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
  
  		reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1);
  
  		if (S_ISDIR(old_inode->i_mode)) {
  			if ((retval =
  			     search_by_entry_key(new_dir->i_sb,
  						 &dot_dot_de.de_entry_key,
  						 &dot_dot_entry_path,
  						 &dot_dot_de)) != NAME_FOUND) {
  				pathrelse(&dot_dot_entry_path);
  				pathrelse(&new_entry_path);
  				pathrelse(&old_entry_path);
58d854265   Jeff Mahoney   reiserfs: cleanup...
1417
  				journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1418
1419
1420
1421
  				reiserfs_write_unlock(old_dir->i_sb);
  				return -EIO;
  			}
  			copy_item_head(&dot_dot_ih,
4cf5f7add   Jeff Mahoney   reiserfs: cleanup...
1422
  				       tp_item_head(&dot_dot_entry_path));
098297b27   Jeff Mahoney   reiserfs: cleanup...
1423
  			/* node containing ".." gets into transaction */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1424
1425
1426
  			reiserfs_prepare_for_journal(old_inode->i_sb,
  						     dot_dot_de.de_bh, 1);
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
  		/*
  		 * we should check seals here, not do
  		 * this stuff, yes? Then, having
  		 * gathered everything into RAM we
  		 * should lock the buffers, yes?  -Hans
  		 */
  		/*
  		 * probably.  our rename needs to hold more
  		 * than one path at once.  The seals would
  		 * have to be written to deal with multi-path
  		 * issues -chris
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1438
  		 */
098297b27   Jeff Mahoney   reiserfs: cleanup...
1439
1440
1441
1442
  		/*
  		 * sanity checking before doing the rename - avoid races many
  		 * of the above checks could have scheduled.  We have to be
  		 * sure our items haven't been shifted by another process.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
  		 */
  		if (item_moved(&new_entry_ih, &new_entry_path) ||
  		    !entry_points_to_object(new_dentry->d_name.name,
  					    new_dentry->d_name.len,
  					    &new_de, new_dentry_inode) ||
  		    item_moved(&old_entry_ih, &old_entry_path) ||
  		    !entry_points_to_object(old_dentry->d_name.name,
  					    old_dentry->d_name.len,
  					    &old_de, old_inode)) {
  			reiserfs_restore_prepared_buffer(old_inode->i_sb,
  							 new_de.de_bh);
  			reiserfs_restore_prepared_buffer(old_inode->i_sb,
  							 old_de.de_bh);
  			if (S_ISDIR(old_inode_mode))
  				reiserfs_restore_prepared_buffer(old_inode->
  								 i_sb,
  								 dot_dot_de.
  								 de_bh);
  			continue;
  		}
  		if (S_ISDIR(old_inode_mode)) {
  			if (item_moved(&dot_dot_ih, &dot_dot_entry_path) ||
  			    !entry_points_to_object("..", 2, &dot_dot_de,
  						    old_dir)) {
  				reiserfs_restore_prepared_buffer(old_inode->
  								 i_sb,
  								 old_de.de_bh);
  				reiserfs_restore_prepared_buffer(old_inode->
  								 i_sb,
  								 new_de.de_bh);
  				reiserfs_restore_prepared_buffer(old_inode->
  								 i_sb,
  								 dot_dot_de.
  								 de_bh);
  				continue;
  			}
  		}
  
  		RFALSE(S_ISDIR(old_inode_mode) &&
  		       !buffer_journal_prepared(dot_dot_de.de_bh), "");
  
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1485
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1486
1487
1488
1489
  	/*
  	 * ok, all the changes can be done in one fell swoop when we
  	 * have claimed all the buffers needed.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1490

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1491
1492
  	mark_de_visible(new_de.de_deh + new_de.de_entry_num);
  	set_ino_in_dir_entry(&new_de, INODE_PKEY(old_inode));
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
1493
  	journal_mark_dirty(&th, new_de.de_bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1494

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1495
  	mark_de_hidden(old_de.de_deh + old_de.de_entry_num);
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
1496
  	journal_mark_dirty(&th, old_de.de_bh);
02027d42c   Deepa Dinamani   fs: Replace CURRE...
1497
  	ctime = current_time(old_dir);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1498
1499
  	old_dir->i_ctime = old_dir->i_mtime = ctime;
  	new_dir->i_ctime = new_dir->i_mtime = ctime;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1500
1501
1502
1503
  	/*
  	 * thanks to Alex Adriaanse <alex_a@caltech.edu> for patch
  	 * which adds ctime update of renamed object
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1504
1505
1506
  	old_inode->i_ctime = ctime;
  
  	if (new_dentry_inode) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
1507
  		/* adjust link number of the victim */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1508
  		if (S_ISDIR(new_dentry_inode->i_mode)) {
ce71ec368   Dave Hansen   [PATCH] r/o bind ...
1509
  			clear_nlink(new_dentry_inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1510
  		} else {
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1511
  			drop_nlink(new_dentry_inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1512
1513
1514
  		}
  		new_dentry_inode->i_ctime = ctime;
  		savelink = new_dentry_inode->i_nlink;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1515
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1516

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
  	if (S_ISDIR(old_inode_mode)) {
0222e6571   Jeff Mahoney   reiserfs: strip t...
1518
  		/* adjust ".." of renamed directory */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1519
  		set_ino_in_dir_entry(&dot_dot_de, INODE_PKEY(new_dir));
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
1520
  		journal_mark_dirty(&th, dot_dot_de.de_bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1521

098297b27   Jeff Mahoney   reiserfs: cleanup...
1522
1523
1524
1525
  		/*
  		 * there (in new_dir) was no directory, so it got new link
  		 * (".."  of renamed directory)
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1526
  		if (!new_dentry_inode)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1527
1528
1529
1530
  			INC_DIR_INODE_NLINK(new_dir);
  
  		/* old directory lost one link - ".. " of renamed directory */
  		DEC_DIR_INODE_NLINK(old_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1531
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1532
1533
1534
1535
  	/*
  	 * looks like in 2.3.99pre3 brelse is atomic.
  	 * so we can use pathrelse
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1536
1537
  	pathrelse(&new_entry_path);
  	pathrelse(&dot_dot_entry_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538

098297b27   Jeff Mahoney   reiserfs: cleanup...
1539
1540
1541
1542
1543
  	/*
  	 * FIXME: this reiserfs_cut_from_item's return value may screw up
  	 * anybody, but it will panic if will not be able to find the
  	 * entry. This needs one more clean up
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1544
  	if (reiserfs_cut_from_item
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1545
  	    (&th, &old_entry_path, &old_de.de_entry_key, old_dir, NULL,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1546
  	     0) < 0)
0030b6457   Jeff Mahoney   reiserfs: use rei...
1547
1548
  		reiserfs_error(old_dir->i_sb, "vs-7060",
  			       "couldn't not cut old name. Fsck later?");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
  
  	old_dir->i_size -= DEH_SIZE + old_de.de_entrylen;
  
  	reiserfs_update_sd(&th, old_dir);
  	reiserfs_update_sd(&th, new_dir);
  	reiserfs_update_sd(&th, old_inode);
  
  	if (new_dentry_inode) {
  		if (savelink == 0)
  			add_save_link(&th, new_dentry_inode,
  				      0 /* not truncate */ );
  		reiserfs_update_sd(&th, new_dentry_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1562

58d854265   Jeff Mahoney   reiserfs: cleanup...
1563
  	retval = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1564
1565
  	reiserfs_write_unlock(old_dir->i_sb);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1566
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
1567
  /* directories can handle most operations...  */
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
1568
  const struct inode_operations reiserfs_dir_inode_operations = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
  	.create = reiserfs_create,
  	.lookup = reiserfs_lookup,
  	.link = reiserfs_link,
  	.unlink = reiserfs_unlink,
  	.symlink = reiserfs_symlink,
  	.mkdir = reiserfs_mkdir,
  	.rmdir = reiserfs_rmdir,
  	.mknod = reiserfs_mknod,
  	.rename = reiserfs_rename,
  	.setattr = reiserfs_setattr,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1579
  	.listxattr = reiserfs_listxattr,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1580
  	.permission = reiserfs_permission,
4e34e719e   Christoph Hellwig   fs: take the ACL ...
1581
  	.get_acl = reiserfs_get_acl,
47f70d08f   Christoph Hellwig   reiserfs: use gen...
1582
  	.set_acl = reiserfs_set_acl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
1584
1585
1586
1587
1588
  };
  
  /*
   * symlink operations.. same as page_symlink_inode_operations, with xattr
   * stuff added
   */
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
1589
  const struct inode_operations reiserfs_symlink_inode_operations = {
6b2553918   Al Viro   replace ->follow_...
1590
  	.get_link	= page_get_link,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1591
  	.setattr = reiserfs_setattr,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1592
  	.listxattr = reiserfs_listxattr,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1593
  	.permission = reiserfs_permission,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1594
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1595
1596
1597
  /*
   * special file operations.. just xattr/acl stuff
   */
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
1598
  const struct inode_operations reiserfs_special_inode_operations = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1599
  	.setattr = reiserfs_setattr,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1600
  	.listxattr = reiserfs_listxattr,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1601
  	.permission = reiserfs_permission,
4e34e719e   Christoph Hellwig   fs: take the ACL ...
1602
  	.get_acl = reiserfs_get_acl,
47f70d08f   Christoph Hellwig   reiserfs: use gen...
1603
  	.set_acl = reiserfs_set_acl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1604
  };