diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/reiserfs/namei.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'fs/reiserfs/namei.c')
-rw-r--r-- | fs/reiserfs/namei.c | 1491 |
1 files changed, 1491 insertions, 0 deletions
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c new file mode 100644 index 000000000000..80e92d9b81cb --- /dev/null +++ b/fs/reiserfs/namei.c | |||
@@ -0,0 +1,1491 @@ | |||
1 | /* | ||
2 | * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README | ||
3 | * | ||
4 | * Trivial changes by Alan Cox to remove EHASHCOLLISION for compatibility | ||
5 | * | ||
6 | * Trivial Changes: | ||
7 | * Rights granted to Hans Reiser to redistribute under other terms providing | ||
8 | * he accepts all liability including but not limited to patent, fitness | ||
9 | * for purpose, and direct or indirect claims arising from failure to perform. | ||
10 | * | ||
11 | * NO WARRANTY | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/time.h> | ||
16 | #include <linux/bitops.h> | ||
17 | #include <linux/reiserfs_fs.h> | ||
18 | #include <linux/reiserfs_acl.h> | ||
19 | #include <linux/reiserfs_xattr.h> | ||
20 | #include <linux/smp_lock.h> | ||
21 | #include <linux/quotaops.h> | ||
22 | |||
23 | #define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { i->i_nlink++; if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; } | ||
24 | #define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) i->i_nlink--; | ||
25 | |||
26 | // directory item contains array of entry headers. This performs | ||
27 | // binary search through that array | ||
28 | static int bin_search_in_dir_item (struct reiserfs_dir_entry * de, loff_t off) | ||
29 | { | ||
30 | struct item_head * ih = de->de_ih; | ||
31 | struct reiserfs_de_head * deh = de->de_deh; | ||
32 | int rbound, lbound, j; | ||
33 | |||
34 | lbound = 0; | ||
35 | rbound = I_ENTRY_COUNT (ih) - 1; | ||
36 | |||
37 | for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) { | ||
38 | if (off < deh_offset (deh + j)) { | ||
39 | rbound = j - 1; | ||
40 | continue; | ||
41 | } | ||
42 | if (off > deh_offset (deh + j)) { | ||
43 | lbound = j + 1; | ||
44 | continue; | ||
45 | } | ||
46 | // this is not name found, but matched third key component | ||
47 | de->de_entry_num = j; | ||
48 | return NAME_FOUND; | ||
49 | } | ||
50 | |||
51 | de->de_entry_num = lbound; | ||
52 | return NAME_NOT_FOUND; | ||
53 | } | ||
54 | |||
55 | |||
56 | // comment? maybe something like set de to point to what the path points to? | ||
57 | static inline void set_de_item_location (struct reiserfs_dir_entry * de, struct path * path) | ||
58 | { | ||
59 | de->de_bh = get_last_bh (path); | ||
60 | de->de_ih = get_ih (path); | ||
61 | de->de_deh = B_I_DEH (de->de_bh, de->de_ih); | ||
62 | de->de_item_num = PATH_LAST_POSITION (path); | ||
63 | } | ||
64 | |||
65 | |||
66 | // de_bh, de_ih, de_deh (points to first element of array), de_item_num is set | ||
67 | inline void set_de_name_and_namelen (struct reiserfs_dir_entry * de) | ||
68 | { | ||
69 | struct reiserfs_de_head * deh = de->de_deh + de->de_entry_num; | ||
70 | |||
71 | if (de->de_entry_num >= ih_entry_count (de->de_ih)) | ||
72 | BUG (); | ||
73 | |||
74 | de->de_entrylen = entry_length (de->de_bh, de->de_ih, de->de_entry_num); | ||
75 | de->de_namelen = de->de_entrylen - (de_with_sd (deh) ? SD_SIZE : 0); | ||
76 | de->de_name = B_I_PITEM (de->de_bh, de->de_ih) + deh_location(deh); | ||
77 | if (de->de_name[de->de_namelen - 1] == 0) | ||
78 | de->de_namelen = strlen (de->de_name); | ||
79 | } | ||
80 | |||
81 | |||
82 | // what entry points to | ||
83 | static inline void set_de_object_key (struct reiserfs_dir_entry * de) | ||
84 | { | ||
85 | if (de->de_entry_num >= ih_entry_count (de->de_ih)) | ||
86 | BUG (); | ||
87 | de->de_dir_id = deh_dir_id( &(de->de_deh[de->de_entry_num])); | ||
88 | de->de_objectid = deh_objectid( &(de->de_deh[de->de_entry_num])); | ||
89 | } | ||
90 | |||
91 | |||
92 | static inline void store_de_entry_key (struct reiserfs_dir_entry * de) | ||
93 | { | ||
94 | struct reiserfs_de_head * deh = de->de_deh + de->de_entry_num; | ||
95 | |||
96 | if (de->de_entry_num >= ih_entry_count (de->de_ih)) | ||
97 | BUG (); | ||
98 | |||
99 | /* store key of the found entry */ | ||
100 | de->de_entry_key.version = KEY_FORMAT_3_5; | ||
101 | de->de_entry_key.on_disk_key.k_dir_id = le32_to_cpu (de->de_ih->ih_key.k_dir_id); | ||
102 | de->de_entry_key.on_disk_key.k_objectid = le32_to_cpu (de->de_ih->ih_key.k_objectid); | ||
103 | set_cpu_key_k_offset (&(de->de_entry_key), deh_offset (deh)); | ||
104 | set_cpu_key_k_type (&(de->de_entry_key), TYPE_DIRENTRY); | ||
105 | } | ||
106 | |||
107 | |||
108 | /* We assign a key to each directory item, and place multiple entries | ||
109 | in a single directory item. A directory item has a key equal to the | ||
110 | key of the first directory entry in it. | ||
111 | |||
112 | This function first calls search_by_key, then, if item whose first | ||
113 | entry matches is not found it looks for the entry inside directory | ||
114 | item found by search_by_key. Fills the path to the entry, and to the | ||
115 | entry position in the item | ||
116 | |||
117 | */ | ||
118 | |||
119 | /* The function is NOT SCHEDULE-SAFE! */ | ||
120 | int search_by_entry_key (struct super_block * sb, const struct cpu_key * key, | ||
121 | struct path * path, struct reiserfs_dir_entry * de) | ||
122 | { | ||
123 | int retval; | ||
124 | |||
125 | retval = search_item (sb, key, path); | ||
126 | switch (retval) { | ||
127 | case ITEM_NOT_FOUND: | ||
128 | if (!PATH_LAST_POSITION (path)) { | ||
129 | reiserfs_warning (sb, "vs-7000: search_by_entry_key: search_by_key returned item position == 0"); | ||
130 | pathrelse(path) ; | ||
131 | return IO_ERROR ; | ||
132 | } | ||
133 | PATH_LAST_POSITION (path) --; | ||
134 | |||
135 | case ITEM_FOUND: | ||
136 | break; | ||
137 | |||
138 | case IO_ERROR: | ||
139 | return retval; | ||
140 | |||
141 | default: | ||
142 | pathrelse (path); | ||
143 | reiserfs_warning (sb, "vs-7002: search_by_entry_key: no path to here"); | ||
144 | return IO_ERROR; | ||
145 | } | ||
146 | |||
147 | set_de_item_location (de, path); | ||
148 | |||
149 | #ifdef CONFIG_REISERFS_CHECK | ||
150 | if (!is_direntry_le_ih (de->de_ih) || | ||
151 | COMP_SHORT_KEYS (&(de->de_ih->ih_key), key)) { | ||
152 | print_block (de->de_bh, 0, -1, -1); | ||
153 | reiserfs_panic (sb, "vs-7005: search_by_entry_key: found item %h is not directory item or " | ||
154 | "does not belong to the same directory as key %K", de->de_ih, key); | ||
155 | } | ||
156 | #endif /* CONFIG_REISERFS_CHECK */ | ||
157 | |||
158 | /* binary search in directory item by third componen t of the | ||
159 | key. sets de->de_entry_num of de */ | ||
160 | retval = bin_search_in_dir_item (de, cpu_key_k_offset (key)); | ||
161 | path->pos_in_item = de->de_entry_num; | ||
162 | if (retval != NAME_NOT_FOUND) { | ||
163 | // ugly, but rename needs de_bh, de_deh, de_name, de_namelen, de_objectid set | ||
164 | set_de_name_and_namelen (de); | ||
165 | set_de_object_key (de); | ||
166 | } | ||
167 | return retval; | ||
168 | } | ||
169 | |||
170 | |||
171 | |||
172 | /* Keyed 32-bit hash function using TEA in a Davis-Meyer function */ | ||
173 | |||
174 | /* The third component is hashed, and you can choose from more than | ||
175 | one hash function. Per directory hashes are not yet implemented | ||
176 | but are thought about. This function should be moved to hashes.c | ||
177 | Jedi, please do so. -Hans */ | ||
178 | |||
179 | static __u32 get_third_component (struct super_block * s, | ||
180 | const char * name, int len) | ||
181 | { | ||
182 | __u32 res; | ||
183 | |||
184 | if (!len || (len == 1 && name[0] == '.')) | ||
185 | return DOT_OFFSET; | ||
186 | if (len == 2 && name[0] == '.' && name[1] == '.') | ||
187 | return DOT_DOT_OFFSET; | ||
188 | |||
189 | res = REISERFS_SB(s)->s_hash_function (name, len); | ||
190 | |||
191 | // take bits from 7-th to 30-th including both bounds | ||
192 | res = GET_HASH_VALUE(res); | ||
193 | if (res == 0) | ||
194 | // needed to have no names before "." and ".." those have hash | ||
195 | // value == 0 and generation conters 1 and 2 accordingly | ||
196 | res = 128; | ||
197 | return res + MAX_GENERATION_NUMBER; | ||
198 | } | ||
199 | |||
200 | |||
201 | static int reiserfs_match (struct reiserfs_dir_entry * de, | ||
202 | const char * name, int namelen) | ||
203 | { | ||
204 | int retval = NAME_NOT_FOUND; | ||
205 | |||
206 | if ((namelen == de->de_namelen) && | ||
207 | !memcmp(de->de_name, name, de->de_namelen)) | ||
208 | retval = (de_visible (de->de_deh + de->de_entry_num) ? NAME_FOUND : NAME_FOUND_INVISIBLE); | ||
209 | |||
210 | return retval; | ||
211 | } | ||
212 | |||
213 | |||
214 | /* de's de_bh, de_ih, de_deh, de_item_num, de_entry_num are set already */ | ||
215 | |||
216 | /* used when hash collisions exist */ | ||
217 | |||
218 | |||
219 | static int linear_search_in_dir_item (struct cpu_key * key, struct reiserfs_dir_entry * de, | ||
220 | const char * name, int namelen) | ||
221 | { | ||
222 | struct reiserfs_de_head * deh = de->de_deh; | ||
223 | int retval; | ||
224 | int i; | ||
225 | |||
226 | i = de->de_entry_num; | ||
227 | |||
228 | if (i == I_ENTRY_COUNT (de->de_ih) || | ||
229 | GET_HASH_VALUE (deh_offset (deh + i)) != GET_HASH_VALUE (cpu_key_k_offset (key))) { | ||
230 | i --; | ||
231 | } | ||
232 | |||
233 | RFALSE( de->de_deh != B_I_DEH (de->de_bh, de->de_ih), | ||
234 | "vs-7010: array of entry headers not found"); | ||
235 | |||
236 | deh += i; | ||
237 | |||
238 | for (; i >= 0; i --, deh --) { | ||
239 | if (GET_HASH_VALUE (deh_offset (deh)) != | ||
240 | GET_HASH_VALUE (cpu_key_k_offset (key))) { | ||
241 | // hash value does not match, no need to check whole name | ||
242 | return NAME_NOT_FOUND; | ||
243 | } | ||
244 | |||
245 | /* mark, that this generation number is used */ | ||
246 | if (de->de_gen_number_bit_string) | ||
247 | set_bit (GET_GENERATION_NUMBER (deh_offset (deh)), (unsigned long *)de->de_gen_number_bit_string); | ||
248 | |||
249 | // calculate pointer to name and namelen | ||
250 | de->de_entry_num = i; | ||
251 | set_de_name_and_namelen (de); | ||
252 | |||
253 | if ((retval = reiserfs_match (de, name, namelen)) != NAME_NOT_FOUND) { | ||
254 | // de's de_name, de_namelen, de_recordlen are set. Fill the rest: | ||
255 | |||
256 | // key of pointed object | ||
257 | set_de_object_key (de); | ||
258 | |||
259 | store_de_entry_key (de); | ||
260 | |||
261 | // retval can be NAME_FOUND or NAME_FOUND_INVISIBLE | ||
262 | return retval; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | if (GET_GENERATION_NUMBER (le_ih_k_offset (de->de_ih)) == 0) | ||
267 | /* we have reached left most entry in the node. In common we | ||
268 | have to go to the left neighbor, but if generation counter | ||
269 | is 0 already, we know for sure, that there is no name with | ||
270 | the same hash value */ | ||
271 | // FIXME: this work correctly only because hash value can not | ||
272 | // be 0. Btw, in case of Yura's hash it is probably possible, | ||
273 | // so, this is a bug | ||
274 | return NAME_NOT_FOUND; | ||
275 | |||
276 | RFALSE( de->de_item_num, | ||
277 | "vs-7015: two diritems of the same directory in one node?"); | ||
278 | |||
279 | return GOTO_PREVIOUS_ITEM; | ||
280 | } | ||
281 | |||
282 | |||
283 | // may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND | ||
284 | // FIXME: should add something like IOERROR | ||
285 | static int reiserfs_find_entry (struct inode * dir, const char * name, int namelen, | ||
286 | struct path * path_to_entry, struct reiserfs_dir_entry * de) | ||
287 | { | ||
288 | struct cpu_key key_to_search; | ||
289 | int retval; | ||
290 | |||
291 | |||
292 | if (namelen > REISERFS_MAX_NAME (dir->i_sb->s_blocksize)) | ||
293 | return NAME_NOT_FOUND; | ||
294 | |||
295 | /* we will search for this key in the tree */ | ||
296 | make_cpu_key (&key_to_search, dir, | ||
297 | get_third_component (dir->i_sb, name, namelen), TYPE_DIRENTRY, 3); | ||
298 | |||
299 | while (1) { | ||
300 | retval = search_by_entry_key (dir->i_sb, &key_to_search, path_to_entry, de); | ||
301 | if (retval == IO_ERROR) { | ||
302 | reiserfs_warning (dir->i_sb, "zam-7001: io error in %s", | ||
303 | __FUNCTION__); | ||
304 | return IO_ERROR; | ||
305 | } | ||
306 | |||
307 | /* compare names for all entries having given hash value */ | ||
308 | retval = linear_search_in_dir_item (&key_to_search, de, name, namelen); | ||
309 | if (retval != GOTO_PREVIOUS_ITEM) { | ||
310 | /* there is no need to scan directory anymore. Given entry found or does not exist */ | ||
311 | path_to_entry->pos_in_item = de->de_entry_num; | ||
312 | return retval; | ||
313 | } | ||
314 | |||
315 | /* there is left neighboring item of this directory and given entry can be there */ | ||
316 | set_cpu_key_k_offset (&key_to_search, le_ih_k_offset (de->de_ih) - 1); | ||
317 | pathrelse (path_to_entry); | ||
318 | |||
319 | } /* while (1) */ | ||
320 | } | ||
321 | |||
322 | |||
323 | static struct dentry * reiserfs_lookup (struct inode * dir, struct dentry * dentry, struct nameidata *nd) | ||
324 | { | ||
325 | int retval; | ||
326 | struct inode * inode = NULL; | ||
327 | struct reiserfs_dir_entry de; | ||
328 | INITIALIZE_PATH (path_to_entry); | ||
329 | |||
330 | if (REISERFS_MAX_NAME (dir->i_sb->s_blocksize) < dentry->d_name.len) | ||
331 | return ERR_PTR(-ENAMETOOLONG); | ||
332 | |||
333 | reiserfs_write_lock(dir->i_sb); | ||
334 | de.de_gen_number_bit_string = NULL; | ||
335 | retval = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de); | ||
336 | pathrelse (&path_to_entry); | ||
337 | if (retval == NAME_FOUND) { | ||
338 | /* Hide the .reiserfs_priv directory */ | ||
339 | if (reiserfs_xattrs (dir->i_sb) && | ||
340 | !old_format_only(dir->i_sb) && | ||
341 | REISERFS_SB(dir->i_sb)->priv_root && | ||
342 | REISERFS_SB(dir->i_sb)->priv_root->d_inode && | ||
343 | de.de_objectid == le32_to_cpu (INODE_PKEY(REISERFS_SB(dir->i_sb)->priv_root->d_inode)->k_objectid)) { | ||
344 | reiserfs_write_unlock (dir->i_sb); | ||
345 | return ERR_PTR (-EACCES); | ||
346 | } | ||
347 | |||
348 | inode = reiserfs_iget (dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); | ||
349 | if (!inode || IS_ERR(inode)) { | ||
350 | reiserfs_write_unlock(dir->i_sb); | ||
351 | return ERR_PTR(-EACCES); | ||
352 | } | ||
353 | |||
354 | /* Propogate the priv_object flag so we know we're in the priv tree */ | ||
355 | if (is_reiserfs_priv_object (dir)) | ||
356 | reiserfs_mark_inode_private (inode); | ||
357 | } | ||
358 | reiserfs_write_unlock(dir->i_sb); | ||
359 | if ( retval == IO_ERROR ) { | ||
360 | return ERR_PTR(-EIO); | ||
361 | } | ||
362 | |||
363 | if (inode) | ||
364 | return d_splice_alias(inode, dentry); | ||
365 | |||
366 | d_add(dentry, inode); | ||
367 | return NULL; | ||
368 | } | ||
369 | |||
370 | |||
371 | /* | ||
372 | ** looks up the dentry of the parent directory for child. | ||
373 | ** taken from ext2_get_parent | ||
374 | */ | ||
375 | struct dentry *reiserfs_get_parent(struct dentry *child) | ||
376 | { | ||
377 | int retval; | ||
378 | struct inode * inode = NULL; | ||
379 | struct reiserfs_dir_entry de; | ||
380 | INITIALIZE_PATH (path_to_entry); | ||
381 | struct dentry *parent; | ||
382 | struct inode *dir = child->d_inode ; | ||
383 | |||
384 | |||
385 | if (dir->i_nlink == 0) { | ||
386 | return ERR_PTR(-ENOENT); | ||
387 | } | ||
388 | de.de_gen_number_bit_string = NULL; | ||
389 | |||
390 | reiserfs_write_lock(dir->i_sb); | ||
391 | retval = reiserfs_find_entry (dir, "..", 2, &path_to_entry, &de); | ||
392 | pathrelse (&path_to_entry); | ||
393 | if (retval != NAME_FOUND) { | ||
394 | reiserfs_write_unlock(dir->i_sb); | ||
395 | return ERR_PTR(-ENOENT); | ||
396 | } | ||
397 | inode = reiserfs_iget (dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); | ||
398 | reiserfs_write_unlock(dir->i_sb); | ||
399 | |||
400 | if (!inode || IS_ERR(inode)) { | ||
401 | return ERR_PTR(-EACCES); | ||
402 | } | ||
403 | parent = d_alloc_anon(inode); | ||
404 | if (!parent) { | ||
405 | iput(inode); | ||
406 | parent = ERR_PTR(-ENOMEM); | ||
407 | } | ||
408 | return parent; | ||
409 | } | ||
410 | |||
411 | |||
412 | /* add entry to the directory (entry can be hidden). | ||
413 | |||
414 | insert definition of when hidden directories are used here -Hans | ||
415 | |||
416 | Does not mark dir inode dirty, do it after successesfull call to it */ | ||
417 | |||
418 | static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct inode * dir, | ||
419 | const char * name, int namelen, struct inode * inode, | ||
420 | int visible) | ||
421 | { | ||
422 | struct cpu_key entry_key; | ||
423 | struct reiserfs_de_head * deh; | ||
424 | INITIALIZE_PATH (path); | ||
425 | struct reiserfs_dir_entry de; | ||
426 | int bit_string [MAX_GENERATION_NUMBER / (sizeof(int) * 8) + 1]; | ||
427 | int gen_number; | ||
428 | char small_buf[32+DEH_SIZE] ; /* 48 bytes now and we avoid kmalloc | ||
429 | if we create file with short name */ | ||
430 | char * buffer; | ||
431 | int buflen, paste_size; | ||
432 | int retval; | ||
433 | |||
434 | BUG_ON (!th->t_trans_id); | ||
435 | |||
436 | /* cannot allow items to be added into a busy deleted directory */ | ||
437 | if (!namelen) | ||
438 | return -EINVAL; | ||
439 | |||
440 | if (namelen > REISERFS_MAX_NAME (dir->i_sb->s_blocksize)) | ||
441 | return -ENAMETOOLONG; | ||
442 | |||
443 | /* each entry has unique key. compose it */ | ||
444 | make_cpu_key (&entry_key, dir, | ||
445 | get_third_component (dir->i_sb, name, namelen), TYPE_DIRENTRY, 3); | ||
446 | |||
447 | /* get memory for composing the entry */ | ||
448 | buflen = DEH_SIZE + ROUND_UP (namelen); | ||
449 | if (buflen > sizeof (small_buf)) { | ||
450 | buffer = reiserfs_kmalloc (buflen, GFP_NOFS, dir->i_sb); | ||
451 | if (buffer == 0) | ||
452 | return -ENOMEM; | ||
453 | } else | ||
454 | buffer = small_buf; | ||
455 | |||
456 | paste_size = (get_inode_sd_version (dir) == STAT_DATA_V1) ? (DEH_SIZE + namelen) : buflen; | ||
457 | |||
458 | /* fill buffer : directory entry head, name[, dir objectid | , stat data | ,stat data, dir objectid ] */ | ||
459 | deh = (struct reiserfs_de_head *)buffer; | ||
460 | deh->deh_location = 0; /* JDM Endian safe if 0 */ | ||
461 | put_deh_offset( deh, cpu_key_k_offset( &entry_key ) ); | ||
462 | deh->deh_state = 0; /* JDM Endian safe if 0 */ | ||
463 | /* put key (ino analog) to de */ | ||
464 | deh->deh_dir_id = INODE_PKEY (inode)->k_dir_id; /* safe: k_dir_id is le */ | ||
465 | deh->deh_objectid = INODE_PKEY (inode)->k_objectid; /* safe: k_objectid is le */ | ||
466 | |||
467 | /* copy name */ | ||
468 | memcpy ((char *)(deh + 1), name, namelen); | ||
469 | /* padd by 0s to the 4 byte boundary */ | ||
470 | padd_item ((char *)(deh + 1), ROUND_UP (namelen), namelen); | ||
471 | |||
472 | /* entry is ready to be pasted into tree, set 'visibility' and 'stat data in entry' attributes */ | ||
473 | mark_de_without_sd (deh); | ||
474 | visible ? mark_de_visible (deh) : mark_de_hidden (deh); | ||
475 | |||
476 | /* find the proper place for the new entry */ | ||
477 | memset (bit_string, 0, sizeof (bit_string)); | ||
478 | de.de_gen_number_bit_string = (char *)bit_string; | ||
479 | retval = reiserfs_find_entry (dir, name, namelen, &path, &de); | ||
480 | if( retval != NAME_NOT_FOUND ) { | ||
481 | if (buffer != small_buf) | ||
482 | reiserfs_kfree (buffer, buflen, dir->i_sb); | ||
483 | pathrelse (&path); | ||
484 | |||
485 | if ( retval == IO_ERROR ) { | ||
486 | return -EIO; | ||
487 | } | ||
488 | |||
489 | if (retval != NAME_FOUND) { | ||
490 | reiserfs_warning (dir->i_sb, "zam-7002:%s: \"reiserfs_find_entry\" " | ||
491 | "has returned unexpected value (%d)", | ||
492 | __FUNCTION__, retval); | ||
493 | } | ||
494 | |||
495 | return -EEXIST; | ||
496 | } | ||
497 | |||
498 | gen_number = find_first_zero_bit ((unsigned long *)bit_string, MAX_GENERATION_NUMBER + 1); | ||
499 | if (gen_number > MAX_GENERATION_NUMBER) { | ||
500 | /* there is no free generation number */ | ||
501 | reiserfs_warning (dir->i_sb, "reiserfs_add_entry: Congratulations! we have got hash function screwed up"); | ||
502 | if (buffer != small_buf) | ||
503 | reiserfs_kfree (buffer, buflen, dir->i_sb); | ||
504 | pathrelse (&path); | ||
505 | return -EBUSY; | ||
506 | } | ||
507 | /* adjust offset of directory enrty */ | ||
508 | put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number)); | ||
509 | set_cpu_key_k_offset (&entry_key, deh_offset(deh)); | ||
510 | |||
511 | /* update max-hash-collisions counter in reiserfs_sb_info */ | ||
512 | PROC_INFO_MAX( th -> t_super, max_hash_collisions, gen_number ); | ||
513 | |||
514 | if (gen_number != 0) { /* we need to re-search for the insertion point */ | ||
515 | if (search_by_entry_key (dir->i_sb, &entry_key, &path, &de) != NAME_NOT_FOUND) { | ||
516 | reiserfs_warning (dir->i_sb, "vs-7032: reiserfs_add_entry: " | ||
517 | "entry with this key (%K) already exists", | ||
518 | &entry_key); | ||
519 | |||
520 | if (buffer != small_buf) | ||
521 | reiserfs_kfree (buffer, buflen, dir->i_sb); | ||
522 | pathrelse (&path); | ||
523 | return -EBUSY; | ||
524 | } | ||
525 | } | ||
526 | |||
527 | /* perform the insertion of the entry that we have prepared */ | ||
528 | retval = reiserfs_paste_into_item (th, &path, &entry_key, dir, buffer, paste_size); | ||
529 | if (buffer != small_buf) | ||
530 | reiserfs_kfree (buffer, buflen, dir->i_sb); | ||
531 | if (retval) { | ||
532 | reiserfs_check_path(&path) ; | ||
533 | return retval; | ||
534 | } | ||
535 | |||
536 | dir->i_size += paste_size; | ||
537 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | ||
538 | if (!S_ISDIR (inode->i_mode) && visible) | ||
539 | // reiserfs_mkdir or reiserfs_rename will do that by itself | ||
540 | reiserfs_update_sd (th, dir); | ||
541 | |||
542 | reiserfs_check_path(&path) ; | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | /* quota utility function, call if you've had to abort after calling | ||
547 | ** new_inode_init, and have not called reiserfs_new_inode yet. | ||
548 | ** This should only be called on inodes that do not have stat data | ||
549 | ** inserted into the tree yet. | ||
550 | */ | ||
551 | static int drop_new_inode(struct inode *inode) { | ||
552 | DQUOT_DROP(inode); | ||
553 | make_bad_inode(inode) ; | ||
554 | inode->i_flags |= S_NOQUOTA; | ||
555 | iput(inode) ; | ||
556 | return 0 ; | ||
557 | } | ||
558 | |||
559 | /* utility function that does setup for reiserfs_new_inode. | ||
560 | ** DQUOT_INIT needs lots of credits so it's better to have it | ||
561 | ** outside of a transaction, so we had to pull some bits of | ||
562 | ** reiserfs_new_inode out into this func. | ||
563 | */ | ||
564 | static int new_inode_init(struct inode *inode, struct inode *dir, int mode) { | ||
565 | |||
566 | /* the quota init calls have to know who to charge the quota to, so | ||
567 | ** we have to set uid and gid here | ||
568 | */ | ||
569 | inode->i_uid = current->fsuid; | ||
570 | inode->i_mode = mode; | ||
571 | |||
572 | if (dir->i_mode & S_ISGID) { | ||
573 | inode->i_gid = dir->i_gid; | ||
574 | if (S_ISDIR(mode)) | ||
575 | inode->i_mode |= S_ISGID; | ||
576 | } else { | ||
577 | inode->i_gid = current->fsgid; | ||
578 | } | ||
579 | DQUOT_INIT(inode); | ||
580 | return 0 ; | ||
581 | } | ||
582 | |||
583 | static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode, | ||
584 | struct nameidata *nd) | ||
585 | { | ||
586 | int retval; | ||
587 | struct inode * inode; | ||
588 | /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ | ||
589 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); | ||
590 | struct reiserfs_transaction_handle th ; | ||
591 | int locked; | ||
592 | |||
593 | if (!(inode = new_inode(dir->i_sb))) { | ||
594 | return -ENOMEM ; | ||
595 | } | ||
596 | new_inode_init(inode, dir, mode); | ||
597 | |||
598 | locked = reiserfs_cache_default_acl (dir); | ||
599 | |||
600 | reiserfs_write_lock(dir->i_sb); | ||
601 | |||
602 | if (locked) | ||
603 | reiserfs_write_lock_xattrs (dir->i_sb); | ||
604 | |||
605 | retval = journal_begin(&th, dir->i_sb, jbegin_count); | ||
606 | if (retval) { | ||
607 | drop_new_inode (inode); | ||
608 | goto out_failed; | ||
609 | } | ||
610 | |||
611 | retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode); | ||
612 | if (retval) | ||
613 | goto out_failed; | ||
614 | |||
615 | if (locked) { | ||
616 | reiserfs_write_unlock_xattrs (dir->i_sb); | ||
617 | locked = 0; | ||
618 | } | ||
619 | |||
620 | inode->i_op = &reiserfs_file_inode_operations; | ||
621 | inode->i_fop = &reiserfs_file_operations; | ||
622 | inode->i_mapping->a_ops = &reiserfs_address_space_operations ; | ||
623 | |||
624 | retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, | ||
625 | inode, 1/*visible*/); | ||
626 | if (retval) { | ||
627 | int err; | ||
628 | inode->i_nlink--; | ||
629 | reiserfs_update_sd (&th, inode); | ||
630 | err = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
631 | if (err) | ||
632 | retval = err; | ||
633 | iput (inode); | ||
634 | goto out_failed; | ||
635 | } | ||
636 | reiserfs_update_inode_transaction(inode) ; | ||
637 | reiserfs_update_inode_transaction(dir) ; | ||
638 | |||
639 | d_instantiate(dentry, inode); | ||
640 | retval = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
641 | |||
642 | out_failed: | ||
643 | if (locked) | ||
644 | reiserfs_write_unlock_xattrs (dir->i_sb); | ||
645 | reiserfs_write_unlock(dir->i_sb); | ||
646 | return retval; | ||
647 | } | ||
648 | |||
649 | |||
650 | static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) | ||
651 | { | ||
652 | int retval; | ||
653 | struct inode * inode; | ||
654 | struct reiserfs_transaction_handle th ; | ||
655 | /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ | ||
656 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); | ||
657 | int locked; | ||
658 | |||
659 | if (!new_valid_dev(rdev)) | ||
660 | return -EINVAL; | ||
661 | |||
662 | if (!(inode = new_inode(dir->i_sb))) { | ||
663 | return -ENOMEM ; | ||
664 | } | ||
665 | new_inode_init(inode, dir, mode); | ||
666 | |||
667 | locked = reiserfs_cache_default_acl (dir); | ||
668 | |||
669 | reiserfs_write_lock(dir->i_sb); | ||
670 | |||
671 | if (locked) | ||
672 | reiserfs_write_lock_xattrs (dir->i_sb); | ||
673 | |||
674 | retval = journal_begin(&th, dir->i_sb, jbegin_count) ; | ||
675 | if (retval) { | ||
676 | drop_new_inode (inode); | ||
677 | goto out_failed; | ||
678 | } | ||
679 | |||
680 | retval = reiserfs_new_inode (&th, dir, mode, NULL, 0/*i_size*/, dentry, inode); | ||
681 | if (retval) { | ||
682 | goto out_failed; | ||
683 | } | ||
684 | |||
685 | if (locked) { | ||
686 | reiserfs_write_unlock_xattrs (dir->i_sb); | ||
687 | locked = 0; | ||
688 | } | ||
689 | |||
690 | |||
691 | inode->i_op = &reiserfs_special_inode_operations; | ||
692 | init_special_inode(inode, inode->i_mode, rdev) ; | ||
693 | |||
694 | //FIXME: needed for block and char devices only | ||
695 | reiserfs_update_sd (&th, inode); | ||
696 | |||
697 | reiserfs_update_inode_transaction(inode) ; | ||
698 | reiserfs_update_inode_transaction(dir) ; | ||
699 | |||
700 | retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, | ||
701 | inode, 1/*visible*/); | ||
702 | if (retval) { | ||
703 | int err; | ||
704 | inode->i_nlink--; | ||
705 | reiserfs_update_sd (&th, inode); | ||
706 | err = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
707 | if (err) | ||
708 | retval = err; | ||
709 | iput (inode); | ||
710 | goto out_failed; | ||
711 | } | ||
712 | |||
713 | d_instantiate(dentry, inode); | ||
714 | retval = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
715 | |||
716 | out_failed: | ||
717 | if (locked) | ||
718 | reiserfs_write_unlock_xattrs (dir->i_sb); | ||
719 | reiserfs_write_unlock(dir->i_sb); | ||
720 | return retval; | ||
721 | } | ||
722 | |||
723 | |||
724 | static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode) | ||
725 | { | ||
726 | int retval; | ||
727 | struct inode * inode; | ||
728 | struct reiserfs_transaction_handle th ; | ||
729 | /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ | ||
730 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); | ||
731 | int locked; | ||
732 | |||
733 | #ifdef DISPLACE_NEW_PACKING_LOCALITIES | ||
734 | /* set flag that new packing locality created and new blocks for the content * of that directory are not displaced yet */ | ||
735 | REISERFS_I(dir)->new_packing_locality = 1; | ||
736 | #endif | ||
737 | mode = S_IFDIR | mode; | ||
738 | if (!(inode = new_inode(dir->i_sb))) { | ||
739 | return -ENOMEM ; | ||
740 | } | ||
741 | new_inode_init(inode, dir, mode); | ||
742 | |||
743 | locked = reiserfs_cache_default_acl (dir); | ||
744 | |||
745 | reiserfs_write_lock(dir->i_sb); | ||
746 | if (locked) | ||
747 | reiserfs_write_lock_xattrs (dir->i_sb); | ||
748 | |||
749 | retval = journal_begin(&th, dir->i_sb, jbegin_count) ; | ||
750 | if (retval) { | ||
751 | drop_new_inode (inode); | ||
752 | goto out_failed; | ||
753 | } | ||
754 | |||
755 | |||
756 | /* inc the link count now, so another writer doesn't overflow it while | ||
757 | ** we sleep later on. | ||
758 | */ | ||
759 | INC_DIR_INODE_NLINK(dir) | ||
760 | |||
761 | retval = reiserfs_new_inode (&th, dir, mode, NULL/*symlink*/, | ||
762 | old_format_only (dir->i_sb) ? | ||
763 | EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, | ||
764 | dentry, inode); | ||
765 | if (retval) { | ||
766 | dir->i_nlink-- ; | ||
767 | goto out_failed; | ||
768 | } | ||
769 | |||
770 | if (locked) { | ||
771 | reiserfs_write_unlock_xattrs (dir->i_sb); | ||
772 | locked = 0; | ||
773 | } | ||
774 | |||
775 | reiserfs_update_inode_transaction(inode) ; | ||
776 | reiserfs_update_inode_transaction(dir) ; | ||
777 | |||
778 | inode->i_op = &reiserfs_dir_inode_operations; | ||
779 | inode->i_fop = &reiserfs_dir_operations; | ||
780 | |||
781 | // note, _this_ add_entry will not update dir's stat data | ||
782 | retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, | ||
783 | inode, 1/*visible*/); | ||
784 | if (retval) { | ||
785 | int err; | ||
786 | inode->i_nlink = 0; | ||
787 | DEC_DIR_INODE_NLINK(dir); | ||
788 | reiserfs_update_sd (&th, inode); | ||
789 | err = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
790 | if (err) | ||
791 | retval = err; | ||
792 | iput (inode); | ||
793 | goto out_failed; | ||
794 | } | ||
795 | |||
796 | // the above add_entry did not update dir's stat data | ||
797 | reiserfs_update_sd (&th, dir); | ||
798 | |||
799 | d_instantiate(dentry, inode); | ||
800 | retval = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
801 | out_failed: | ||
802 | if (locked) | ||
803 | reiserfs_write_unlock_xattrs (dir->i_sb); | ||
804 | reiserfs_write_unlock(dir->i_sb); | ||
805 | return retval; | ||
806 | } | ||
807 | |||
808 | static inline int reiserfs_empty_dir(struct inode *inode) { | ||
809 | /* we can cheat because an old format dir cannot have | ||
810 | ** EMPTY_DIR_SIZE, and a new format dir cannot have | ||
811 | ** EMPTY_DIR_SIZE_V1. So, if the inode is either size, | ||
812 | ** regardless of disk format version, the directory is empty. | ||
813 | */ | ||
814 | if (inode->i_size != EMPTY_DIR_SIZE && | ||
815 | inode->i_size != EMPTY_DIR_SIZE_V1) { | ||
816 | return 0 ; | ||
817 | } | ||
818 | return 1 ; | ||
819 | } | ||
820 | |||
821 | static int reiserfs_rmdir (struct inode * dir, struct dentry *dentry) | ||
822 | { | ||
823 | int retval, err; | ||
824 | struct inode * inode; | ||
825 | struct reiserfs_transaction_handle th ; | ||
826 | int jbegin_count; | ||
827 | INITIALIZE_PATH (path); | ||
828 | struct reiserfs_dir_entry de; | ||
829 | |||
830 | |||
831 | /* we will be doing 2 balancings and update 2 stat data, we change quotas | ||
832 | * of the owner of the directory and of the owner of the parent directory */ | ||
833 | jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); | ||
834 | |||
835 | reiserfs_write_lock(dir->i_sb); | ||
836 | retval = journal_begin(&th, dir->i_sb, jbegin_count) ; | ||
837 | if (retval) | ||
838 | goto out_rmdir; | ||
839 | |||
840 | de.de_gen_number_bit_string = NULL; | ||
841 | if ( (retval = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path, &de)) == NAME_NOT_FOUND) { | ||
842 | retval = -ENOENT; | ||
843 | goto end_rmdir; | ||
844 | } else if ( retval == IO_ERROR) { | ||
845 | retval = -EIO; | ||
846 | goto end_rmdir; | ||
847 | } | ||
848 | |||
849 | inode = dentry->d_inode; | ||
850 | |||
851 | reiserfs_update_inode_transaction(inode) ; | ||
852 | reiserfs_update_inode_transaction(dir) ; | ||
853 | |||
854 | if (de.de_objectid != inode->i_ino) { | ||
855 | // FIXME: compare key of an object and a key found in the | ||
856 | // entry | ||
857 | retval = -EIO; | ||
858 | goto end_rmdir; | ||
859 | } | ||
860 | if (!reiserfs_empty_dir(inode)) { | ||
861 | retval = -ENOTEMPTY; | ||
862 | goto end_rmdir; | ||
863 | } | ||
864 | |||
865 | /* cut entry from dir directory */ | ||
866 | retval = reiserfs_cut_from_item (&th, &path, &(de.de_entry_key), dir, | ||
867 | NULL, /* page */ | ||
868 | 0/*new file size - not used here*/); | ||
869 | if (retval < 0) | ||
870 | goto end_rmdir; | ||
871 | |||
872 | if ( inode->i_nlink != 2 && inode->i_nlink != 1 ) | ||
873 | reiserfs_warning (inode->i_sb, "%s: empty directory has nlink " | ||
874 | "!= 2 (%d)", __FUNCTION__, inode->i_nlink); | ||
875 | |||
876 | inode->i_nlink = 0; | ||
877 | inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; | ||
878 | reiserfs_update_sd (&th, inode); | ||
879 | |||
880 | DEC_DIR_INODE_NLINK(dir) | ||
881 | dir->i_size -= (DEH_SIZE + de.de_entrylen); | ||
882 | reiserfs_update_sd (&th, dir); | ||
883 | |||
884 | /* prevent empty directory from getting lost */ | ||
885 | add_save_link (&th, inode, 0/* not truncate */); | ||
886 | |||
887 | retval = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
888 | reiserfs_check_path(&path) ; | ||
889 | out_rmdir: | ||
890 | reiserfs_write_unlock(dir->i_sb); | ||
891 | return retval; | ||
892 | |||
893 | end_rmdir: | ||
894 | /* we must release path, because we did not call | ||
895 | reiserfs_cut_from_item, or reiserfs_cut_from_item does not | ||
896 | release path if operation was not complete */ | ||
897 | pathrelse (&path); | ||
898 | err = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
899 | reiserfs_write_unlock(dir->i_sb); | ||
900 | return err ? err : retval; | ||
901 | } | ||
902 | |||
903 | static int reiserfs_unlink (struct inode * dir, struct dentry *dentry) | ||
904 | { | ||
905 | int retval, err; | ||
906 | struct inode * inode; | ||
907 | struct reiserfs_dir_entry de; | ||
908 | INITIALIZE_PATH (path); | ||
909 | struct reiserfs_transaction_handle th ; | ||
910 | int jbegin_count; | ||
911 | unsigned long savelink; | ||
912 | |||
913 | inode = dentry->d_inode; | ||
914 | |||
915 | /* in this transaction we can be doing at max two balancings and update | ||
916 | two stat datas, we change quotas of the owner of the directory and of | ||
917 | the owner of the parent directory */ | ||
918 | jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); | ||
919 | |||
920 | reiserfs_write_lock(dir->i_sb); | ||
921 | retval = journal_begin(&th, dir->i_sb, jbegin_count) ; | ||
922 | if (retval) | ||
923 | goto out_unlink; | ||
924 | |||
925 | de.de_gen_number_bit_string = NULL; | ||
926 | if ( (retval = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path, &de)) == NAME_NOT_FOUND) { | ||
927 | retval = -ENOENT; | ||
928 | goto end_unlink; | ||
929 | } else if (retval == IO_ERROR) { | ||
930 | retval = -EIO; | ||
931 | goto end_unlink; | ||
932 | } | ||
933 | |||
934 | reiserfs_update_inode_transaction(inode) ; | ||
935 | reiserfs_update_inode_transaction(dir) ; | ||
936 | |||
937 | if (de.de_objectid != inode->i_ino) { | ||
938 | // FIXME: compare key of an object and a key found in the | ||
939 | // entry | ||
940 | retval = -EIO; | ||
941 | goto end_unlink; | ||
942 | } | ||
943 | |||
944 | if (!inode->i_nlink) { | ||
945 | reiserfs_warning (inode->i_sb, "%s: deleting nonexistent file " | ||
946 | "(%s:%lu), %d", __FUNCTION__, | ||
947 | reiserfs_bdevname (inode->i_sb), inode->i_ino, | ||
948 | inode->i_nlink); | ||
949 | inode->i_nlink = 1; | ||
950 | } | ||
951 | |||
952 | inode->i_nlink--; | ||
953 | |||
954 | /* | ||
955 | * we schedule before doing the add_save_link call, save the link | ||
956 | * count so we don't race | ||
957 | */ | ||
958 | savelink = inode->i_nlink; | ||
959 | |||
960 | |||
961 | retval = reiserfs_cut_from_item (&th, &path, &(de.de_entry_key), dir, NULL, 0); | ||
962 | if (retval < 0) { | ||
963 | inode->i_nlink++; | ||
964 | goto end_unlink; | ||
965 | } | ||
966 | inode->i_ctime = CURRENT_TIME_SEC; | ||
967 | reiserfs_update_sd (&th, inode); | ||
968 | |||
969 | dir->i_size -= (de.de_entrylen + DEH_SIZE); | ||
970 | dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; | ||
971 | reiserfs_update_sd (&th, dir); | ||
972 | |||
973 | if (!savelink) | ||
974 | /* prevent file from getting lost */ | ||
975 | add_save_link (&th, inode, 0/* not truncate */); | ||
976 | |||
977 | retval = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
978 | reiserfs_check_path(&path) ; | ||
979 | reiserfs_write_unlock(dir->i_sb); | ||
980 | return retval; | ||
981 | |||
982 | end_unlink: | ||
983 | pathrelse (&path); | ||
984 | err = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
985 | reiserfs_check_path(&path) ; | ||
986 | if (err) | ||
987 | retval = err; | ||
988 | out_unlink: | ||
989 | reiserfs_write_unlock(dir->i_sb); | ||
990 | return retval; | ||
991 | } | ||
992 | |||
993 | static int reiserfs_symlink (struct inode * parent_dir, | ||
994 | struct dentry * dentry, const char * symname) | ||
995 | { | ||
996 | int retval; | ||
997 | struct inode * inode; | ||
998 | char * name; | ||
999 | int item_len; | ||
1000 | struct reiserfs_transaction_handle th ; | ||
1001 | int mode = S_IFLNK | S_IRWXUGO; | ||
1002 | /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ | ||
1003 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); | ||
1004 | |||
1005 | if (!(inode = new_inode(parent_dir->i_sb))) { | ||
1006 | return -ENOMEM ; | ||
1007 | } | ||
1008 | new_inode_init(inode, parent_dir, mode); | ||
1009 | |||
1010 | reiserfs_write_lock(parent_dir->i_sb); | ||
1011 | item_len = ROUND_UP (strlen (symname)); | ||
1012 | if (item_len > MAX_DIRECT_ITEM_LEN (parent_dir->i_sb->s_blocksize)) { | ||
1013 | retval = -ENAMETOOLONG; | ||
1014 | drop_new_inode(inode); | ||
1015 | goto out_failed; | ||
1016 | } | ||
1017 | |||
1018 | name = reiserfs_kmalloc (item_len, GFP_NOFS, parent_dir->i_sb); | ||
1019 | if (!name) { | ||
1020 | drop_new_inode(inode); | ||
1021 | retval = -ENOMEM; | ||
1022 | goto out_failed; | ||
1023 | } | ||
1024 | memcpy (name, symname, strlen (symname)); | ||
1025 | padd_item (name, item_len, strlen (symname)); | ||
1026 | |||
1027 | /* We would inherit the default ACL here, but symlinks don't get ACLs */ | ||
1028 | |||
1029 | retval = journal_begin(&th, parent_dir->i_sb, jbegin_count) ; | ||
1030 | if (retval) { | ||
1031 | drop_new_inode (inode); | ||
1032 | reiserfs_kfree (name, item_len, parent_dir->i_sb); | ||
1033 | goto out_failed; | ||
1034 | } | ||
1035 | |||
1036 | retval = reiserfs_new_inode (&th, parent_dir, mode, name, strlen (symname), | ||
1037 | dentry, inode); | ||
1038 | reiserfs_kfree (name, item_len, parent_dir->i_sb); | ||
1039 | if (retval) { /* reiserfs_new_inode iputs for us */ | ||
1040 | goto out_failed; | ||
1041 | } | ||
1042 | |||
1043 | reiserfs_update_inode_transaction(inode) ; | ||
1044 | reiserfs_update_inode_transaction(parent_dir) ; | ||
1045 | |||
1046 | inode->i_op = &reiserfs_symlink_inode_operations; | ||
1047 | inode->i_mapping->a_ops = &reiserfs_address_space_operations; | ||
1048 | |||
1049 | // must be sure this inode is written with this transaction | ||
1050 | // | ||
1051 | //reiserfs_update_sd (&th, inode, READ_BLOCKS); | ||
1052 | |||
1053 | retval = reiserfs_add_entry (&th, parent_dir, dentry->d_name.name, | ||
1054 | dentry->d_name.len, inode, 1/*visible*/); | ||
1055 | if (retval) { | ||
1056 | int err; | ||
1057 | inode->i_nlink--; | ||
1058 | reiserfs_update_sd (&th, inode); | ||
1059 | err = journal_end(&th, parent_dir->i_sb, jbegin_count) ; | ||
1060 | if (err) | ||
1061 | retval = err; | ||
1062 | iput (inode); | ||
1063 | goto out_failed; | ||
1064 | } | ||
1065 | |||
1066 | d_instantiate(dentry, inode); | ||
1067 | retval = journal_end(&th, parent_dir->i_sb, jbegin_count) ; | ||
1068 | out_failed: | ||
1069 | reiserfs_write_unlock(parent_dir->i_sb); | ||
1070 | return retval; | ||
1071 | } | ||
1072 | |||
1073 | static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct dentry * dentry) | ||
1074 | { | ||
1075 | int retval; | ||
1076 | struct inode *inode = old_dentry->d_inode; | ||
1077 | struct reiserfs_transaction_handle th ; | ||
1078 | /* We need blocks for transaction + update of quotas for the owners of the directory */ | ||
1079 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS; | ||
1080 | |||
1081 | reiserfs_write_lock(dir->i_sb); | ||
1082 | if (inode->i_nlink >= REISERFS_LINK_MAX) { | ||
1083 | //FIXME: sd_nlink is 32 bit for new files | ||
1084 | reiserfs_write_unlock(dir->i_sb); | ||
1085 | return -EMLINK; | ||
1086 | } | ||
1087 | if (inode->i_nlink == 0) { | ||
1088 | reiserfs_write_unlock(dir->i_sb); | ||
1089 | return -ENOENT; | ||
1090 | } | ||
1091 | |||
1092 | /* inc before scheduling so reiserfs_unlink knows we are here */ | ||
1093 | inode->i_nlink++; | ||
1094 | |||
1095 | retval = journal_begin(&th, dir->i_sb, jbegin_count) ; | ||
1096 | if (retval) { | ||
1097 | inode->i_nlink--; | ||
1098 | reiserfs_write_unlock (dir->i_sb); | ||
1099 | return retval; | ||
1100 | } | ||
1101 | |||
1102 | /* create new entry */ | ||
1103 | retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, | ||
1104 | inode, 1/*visible*/); | ||
1105 | |||
1106 | reiserfs_update_inode_transaction(inode) ; | ||
1107 | reiserfs_update_inode_transaction(dir) ; | ||
1108 | |||
1109 | if (retval) { | ||
1110 | int err; | ||
1111 | inode->i_nlink--; | ||
1112 | err = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
1113 | reiserfs_write_unlock(dir->i_sb); | ||
1114 | return err ? err : retval; | ||
1115 | } | ||
1116 | |||
1117 | inode->i_ctime = CURRENT_TIME_SEC; | ||
1118 | reiserfs_update_sd (&th, inode); | ||
1119 | |||
1120 | atomic_inc(&inode->i_count) ; | ||
1121 | d_instantiate(dentry, inode); | ||
1122 | retval = journal_end(&th, dir->i_sb, jbegin_count) ; | ||
1123 | reiserfs_write_unlock(dir->i_sb); | ||
1124 | return retval; | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | // de contains information pointing to an entry which | ||
1129 | static int de_still_valid (const char * name, int len, struct reiserfs_dir_entry * de) | ||
1130 | { | ||
1131 | struct reiserfs_dir_entry tmp = *de; | ||
1132 | |||
1133 | // recalculate pointer to name and name length | ||
1134 | set_de_name_and_namelen (&tmp); | ||
1135 | // FIXME: could check more | ||
1136 | if (tmp.de_namelen != len || memcmp (name, de->de_name, len)) | ||
1137 | return 0; | ||
1138 | return 1; | ||
1139 | } | ||
1140 | |||
1141 | |||
1142 | static int entry_points_to_object (const char * name, int len, struct reiserfs_dir_entry * de, struct inode * inode) | ||
1143 | { | ||
1144 | if (!de_still_valid (name, len, de)) | ||
1145 | return 0; | ||
1146 | |||
1147 | if (inode) { | ||
1148 | if (!de_visible (de->de_deh + de->de_entry_num)) | ||
1149 | reiserfs_panic (NULL, "vs-7042: entry_points_to_object: entry must be visible"); | ||
1150 | return (de->de_objectid == inode->i_ino) ? 1 : 0; | ||
1151 | } | ||
1152 | |||
1153 | /* this must be added hidden entry */ | ||
1154 | if (de_visible (de->de_deh + de->de_entry_num)) | ||
1155 | reiserfs_panic (NULL, "vs-7043: entry_points_to_object: entry must be visible"); | ||
1156 | |||
1157 | return 1; | ||
1158 | } | ||
1159 | |||
1160 | |||
1161 | /* sets key of objectid the entry has to point to */ | ||
1162 | static void set_ino_in_dir_entry (struct reiserfs_dir_entry * de, struct reiserfs_key * key) | ||
1163 | { | ||
1164 | /* JDM These operations are endian safe - both are le */ | ||
1165 | de->de_deh[de->de_entry_num].deh_dir_id = key->k_dir_id; | ||
1166 | de->de_deh[de->de_entry_num].deh_objectid = key->k_objectid; | ||
1167 | } | ||
1168 | |||
1169 | |||
1170 | /* | ||
1171 | * process, that is going to call fix_nodes/do_balance must hold only | ||
1172 | * one path. If it holds 2 or more, it can get into endless waiting in | ||
1173 | * get_empty_nodes or its clones | ||
1174 | */ | ||
1175 | static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry, | ||
1176 | struct inode * new_dir, struct dentry *new_dentry) | ||
1177 | { | ||
1178 | int retval; | ||
1179 | INITIALIZE_PATH (old_entry_path); | ||
1180 | INITIALIZE_PATH (new_entry_path); | ||
1181 | INITIALIZE_PATH (dot_dot_entry_path); | ||
1182 | struct item_head new_entry_ih, old_entry_ih, dot_dot_ih ; | ||
1183 | struct reiserfs_dir_entry old_de, new_de, dot_dot_de; | ||
1184 | struct inode * old_inode, * new_dentry_inode; | ||
1185 | struct reiserfs_transaction_handle th ; | ||
1186 | int jbegin_count ; | ||
1187 | umode_t old_inode_mode; | ||
1188 | unsigned long savelink = 1; | ||
1189 | struct timespec ctime; | ||
1190 | |||
1191 | /* three balancings: (1) old name removal, (2) new name insertion | ||
1192 | and (3) maybe "save" link insertion | ||
1193 | stat data updates: (1) old directory, | ||
1194 | (2) new directory and (3) maybe old object stat data (when it is | ||
1195 | directory) and (4) maybe stat data of object to which new entry | ||
1196 | pointed initially and (5) maybe block containing ".." of | ||
1197 | renamed directory | ||
1198 | quota updates: two parent directories */ | ||
1199 | jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 5 + 4 * REISERFS_QUOTA_TRANS_BLOCKS; | ||
1200 | |||
1201 | old_inode = old_dentry->d_inode; | ||
1202 | new_dentry_inode = new_dentry->d_inode; | ||
1203 | |||
1204 | // make sure, that oldname still exists and points to an object we | ||
1205 | // are going to rename | ||
1206 | old_de.de_gen_number_bit_string = NULL; | ||
1207 | reiserfs_write_lock(old_dir->i_sb); | ||
1208 | retval = reiserfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, | ||
1209 | &old_entry_path, &old_de); | ||
1210 | pathrelse (&old_entry_path); | ||
1211 | if (retval == IO_ERROR) { | ||
1212 | reiserfs_write_unlock(old_dir->i_sb); | ||
1213 | return -EIO; | ||
1214 | } | ||
1215 | |||
1216 | if (retval != NAME_FOUND || old_de.de_objectid != old_inode->i_ino) { | ||
1217 | reiserfs_write_unlock(old_dir->i_sb); | ||
1218 | return -ENOENT; | ||
1219 | } | ||
1220 | |||
1221 | old_inode_mode = old_inode->i_mode; | ||
1222 | if (S_ISDIR(old_inode_mode)) { | ||
1223 | // make sure, that directory being renamed has correct ".." | ||
1224 | // and that its new parent directory has not too many links | ||
1225 | // already | ||
1226 | |||
1227 | if (new_dentry_inode) { | ||
1228 | if (!reiserfs_empty_dir(new_dentry_inode)) { | ||
1229 | reiserfs_write_unlock(old_dir->i_sb); | ||
1230 | return -ENOTEMPTY; | ||
1231 | } | ||
1232 | } | ||
1233 | |||
1234 | /* directory is renamed, its parent directory will be changed, | ||
1235 | ** so find ".." entry | ||
1236 | */ | ||
1237 | dot_dot_de.de_gen_number_bit_string = NULL; | ||
1238 | retval = reiserfs_find_entry (old_inode, "..", 2, &dot_dot_entry_path, &dot_dot_de); | ||
1239 | pathrelse (&dot_dot_entry_path); | ||
1240 | if (retval != NAME_FOUND) { | ||
1241 | reiserfs_write_unlock(old_dir->i_sb); | ||
1242 | return -EIO; | ||
1243 | } | ||
1244 | |||
1245 | /* inode number of .. must equal old_dir->i_ino */ | ||
1246 | if (dot_dot_de.de_objectid != old_dir->i_ino) { | ||
1247 | reiserfs_write_unlock(old_dir->i_sb); | ||
1248 | return -EIO; | ||
1249 | } | ||
1250 | } | ||
1251 | |||
1252 | retval = journal_begin(&th, old_dir->i_sb, jbegin_count) ; | ||
1253 | if (retval) { | ||
1254 | reiserfs_write_unlock (old_dir->i_sb); | ||
1255 | return retval; | ||
1256 | } | ||
1257 | |||
1258 | /* add new entry (or find the existing one) */ | ||
1259 | retval = reiserfs_add_entry (&th, new_dir, new_dentry->d_name.name, new_dentry->d_name.len, | ||
1260 | old_inode, 0); | ||
1261 | if (retval == -EEXIST) { | ||
1262 | if (!new_dentry_inode) { | ||
1263 | reiserfs_panic (old_dir->i_sb, | ||
1264 | "vs-7050: new entry is found, new inode == 0\n"); | ||
1265 | } | ||
1266 | } else if (retval) { | ||
1267 | int err = journal_end(&th, old_dir->i_sb, jbegin_count) ; | ||
1268 | reiserfs_write_unlock(old_dir->i_sb); | ||
1269 | return err ? err : retval; | ||
1270 | } | ||
1271 | |||
1272 | reiserfs_update_inode_transaction(old_dir) ; | ||
1273 | reiserfs_update_inode_transaction(new_dir) ; | ||
1274 | |||
1275 | /* this makes it so an fsync on an open fd for the old name will | ||
1276 | ** commit the rename operation | ||
1277 | */ | ||
1278 | reiserfs_update_inode_transaction(old_inode) ; | ||
1279 | |||
1280 | if (new_dentry_inode) | ||
1281 | reiserfs_update_inode_transaction(new_dentry_inode) ; | ||
1282 | |||
1283 | while (1) { | ||
1284 | // look for old name using corresponding entry key (found by reiserfs_find_entry) | ||
1285 | if ((retval = search_by_entry_key (new_dir->i_sb, &old_de.de_entry_key, | ||
1286 | &old_entry_path, &old_de)) != NAME_FOUND) { | ||
1287 | pathrelse(&old_entry_path); | ||
1288 | journal_end(&th, old_dir->i_sb, jbegin_count); | ||
1289 | reiserfs_write_unlock(old_dir->i_sb); | ||
1290 | return -EIO; | ||
1291 | } | ||
1292 | |||
1293 | copy_item_head(&old_entry_ih, get_ih(&old_entry_path)) ; | ||
1294 | |||
1295 | reiserfs_prepare_for_journal(old_inode->i_sb, old_de.de_bh, 1) ; | ||
1296 | |||
1297 | // look for new name by reiserfs_find_entry | ||
1298 | new_de.de_gen_number_bit_string = NULL; | ||
1299 | retval = reiserfs_find_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, | ||
1300 | &new_entry_path, &new_de); | ||
1301 | // reiserfs_add_entry should not return IO_ERROR, because it is called with essentially same parameters from | ||
1302 | // reiserfs_add_entry above, and we'll catch any i/o errors before we get here. | ||
1303 | if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) { | ||
1304 | pathrelse(&new_entry_path); | ||
1305 | pathrelse(&old_entry_path); | ||
1306 | journal_end(&th, old_dir->i_sb, jbegin_count); | ||
1307 | reiserfs_write_unlock(old_dir->i_sb); | ||
1308 | return -EIO; | ||
1309 | } | ||
1310 | |||
1311 | copy_item_head(&new_entry_ih, get_ih(&new_entry_path)) ; | ||
1312 | |||
1313 | reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1) ; | ||
1314 | |||
1315 | if (S_ISDIR(old_inode->i_mode)) { | ||
1316 | if ((retval = search_by_entry_key (new_dir->i_sb, &dot_dot_de.de_entry_key, | ||
1317 | &dot_dot_entry_path, &dot_dot_de)) != NAME_FOUND) { | ||
1318 | pathrelse(&dot_dot_entry_path); | ||
1319 | pathrelse(&new_entry_path); | ||
1320 | pathrelse(&old_entry_path); | ||
1321 | journal_end(&th, old_dir->i_sb, jbegin_count); | ||
1322 | reiserfs_write_unlock(old_dir->i_sb); | ||
1323 | return -EIO; | ||
1324 | } | ||
1325 | copy_item_head(&dot_dot_ih, get_ih(&dot_dot_entry_path)) ; | ||
1326 | // node containing ".." gets into transaction | ||
1327 | reiserfs_prepare_for_journal(old_inode->i_sb, dot_dot_de.de_bh, 1) ; | ||
1328 | } | ||
1329 | /* we should check seals here, not do | ||
1330 | this stuff, yes? Then, having | ||
1331 | gathered everything into RAM we | ||
1332 | should lock the buffers, yes? -Hans */ | ||
1333 | /* probably. our rename needs to hold more | ||
1334 | ** than one path at once. The seals would | ||
1335 | ** have to be written to deal with multi-path | ||
1336 | ** issues -chris | ||
1337 | */ | ||
1338 | /* sanity checking before doing the rename - avoid races many | ||
1339 | ** of the above checks could have scheduled. We have to be | ||
1340 | ** sure our items haven't been shifted by another process. | ||
1341 | */ | ||
1342 | if (item_moved(&new_entry_ih, &new_entry_path) || | ||
1343 | !entry_points_to_object(new_dentry->d_name.name, | ||
1344 | new_dentry->d_name.len, | ||
1345 | &new_de, new_dentry_inode) || | ||
1346 | item_moved(&old_entry_ih, &old_entry_path) || | ||
1347 | !entry_points_to_object (old_dentry->d_name.name, | ||
1348 | old_dentry->d_name.len, | ||
1349 | &old_de, old_inode)) { | ||
1350 | reiserfs_restore_prepared_buffer (old_inode->i_sb, new_de.de_bh); | ||
1351 | reiserfs_restore_prepared_buffer (old_inode->i_sb, old_de.de_bh); | ||
1352 | if (S_ISDIR(old_inode_mode)) | ||
1353 | reiserfs_restore_prepared_buffer (old_inode->i_sb, dot_dot_de.de_bh); | ||
1354 | continue; | ||
1355 | } | ||
1356 | if (S_ISDIR(old_inode_mode)) { | ||
1357 | if ( item_moved(&dot_dot_ih, &dot_dot_entry_path) || | ||
1358 | !entry_points_to_object ( "..", 2, &dot_dot_de, old_dir) ) { | ||
1359 | reiserfs_restore_prepared_buffer (old_inode->i_sb, old_de.de_bh); | ||
1360 | reiserfs_restore_prepared_buffer (old_inode->i_sb, new_de.de_bh); | ||
1361 | reiserfs_restore_prepared_buffer (old_inode->i_sb, dot_dot_de.de_bh); | ||
1362 | continue; | ||
1363 | } | ||
1364 | } | ||
1365 | |||
1366 | RFALSE( S_ISDIR(old_inode_mode) && | ||
1367 | !buffer_journal_prepared(dot_dot_de.de_bh), "" ); | ||
1368 | |||
1369 | break; | ||
1370 | } | ||
1371 | |||
1372 | /* ok, all the changes can be done in one fell swoop when we | ||
1373 | have claimed all the buffers needed.*/ | ||
1374 | |||
1375 | mark_de_visible (new_de.de_deh + new_de.de_entry_num); | ||
1376 | set_ino_in_dir_entry (&new_de, INODE_PKEY (old_inode)); | ||
1377 | journal_mark_dirty (&th, old_dir->i_sb, new_de.de_bh); | ||
1378 | |||
1379 | mark_de_hidden (old_de.de_deh + old_de.de_entry_num); | ||
1380 | journal_mark_dirty (&th, old_dir->i_sb, old_de.de_bh); | ||
1381 | ctime = CURRENT_TIME_SEC; | ||
1382 | old_dir->i_ctime = old_dir->i_mtime = ctime; | ||
1383 | new_dir->i_ctime = new_dir->i_mtime = ctime; | ||
1384 | /* thanks to Alex Adriaanse <alex_a@caltech.edu> for patch which adds ctime update of | ||
1385 | renamed object */ | ||
1386 | old_inode->i_ctime = ctime; | ||
1387 | |||
1388 | if (new_dentry_inode) { | ||
1389 | // adjust link number of the victim | ||
1390 | if (S_ISDIR(new_dentry_inode->i_mode)) { | ||
1391 | new_dentry_inode->i_nlink = 0; | ||
1392 | } else { | ||
1393 | new_dentry_inode->i_nlink--; | ||
1394 | } | ||
1395 | new_dentry_inode->i_ctime = ctime; | ||
1396 | savelink = new_dentry_inode->i_nlink; | ||
1397 | } | ||
1398 | |||
1399 | if (S_ISDIR(old_inode_mode)) { | ||
1400 | // adjust ".." of renamed directory | ||
1401 | set_ino_in_dir_entry (&dot_dot_de, INODE_PKEY (new_dir)); | ||
1402 | journal_mark_dirty (&th, new_dir->i_sb, dot_dot_de.de_bh); | ||
1403 | |||
1404 | if (!new_dentry_inode) | ||
1405 | /* there (in new_dir) was no directory, so it got new link | ||
1406 | (".." of renamed directory) */ | ||
1407 | INC_DIR_INODE_NLINK(new_dir); | ||
1408 | |||
1409 | /* old directory lost one link - ".. " of renamed directory */ | ||
1410 | DEC_DIR_INODE_NLINK(old_dir); | ||
1411 | } | ||
1412 | |||
1413 | // looks like in 2.3.99pre3 brelse is atomic. so we can use pathrelse | ||
1414 | pathrelse (&new_entry_path); | ||
1415 | pathrelse (&dot_dot_entry_path); | ||
1416 | |||
1417 | // FIXME: this reiserfs_cut_from_item's return value may screw up | ||
1418 | // anybody, but it will panic if will not be able to find the | ||
1419 | // entry. This needs one more clean up | ||
1420 | if (reiserfs_cut_from_item (&th, &old_entry_path, &(old_de.de_entry_key), old_dir, NULL, 0) < 0) | ||
1421 | reiserfs_warning (old_dir->i_sb, "vs-7060: reiserfs_rename: couldn't not cut old name. Fsck later?"); | ||
1422 | |||
1423 | old_dir->i_size -= DEH_SIZE + old_de.de_entrylen; | ||
1424 | |||
1425 | reiserfs_update_sd (&th, old_dir); | ||
1426 | reiserfs_update_sd (&th, new_dir); | ||
1427 | reiserfs_update_sd (&th, old_inode); | ||
1428 | |||
1429 | if (new_dentry_inode) { | ||
1430 | if (savelink == 0) | ||
1431 | add_save_link (&th, new_dentry_inode, 0/* not truncate */); | ||
1432 | reiserfs_update_sd (&th, new_dentry_inode); | ||
1433 | } | ||
1434 | |||
1435 | retval = journal_end(&th, old_dir->i_sb, jbegin_count) ; | ||
1436 | reiserfs_write_unlock(old_dir->i_sb); | ||
1437 | return retval; | ||
1438 | } | ||
1439 | |||
1440 | /* | ||
1441 | * directories can handle most operations... | ||
1442 | */ | ||
1443 | struct inode_operations reiserfs_dir_inode_operations = { | ||
1444 | //&reiserfs_dir_operations, /* default_file_ops */ | ||
1445 | .create = reiserfs_create, | ||
1446 | .lookup = reiserfs_lookup, | ||
1447 | .link = reiserfs_link, | ||
1448 | .unlink = reiserfs_unlink, | ||
1449 | .symlink = reiserfs_symlink, | ||
1450 | .mkdir = reiserfs_mkdir, | ||
1451 | .rmdir = reiserfs_rmdir, | ||
1452 | .mknod = reiserfs_mknod, | ||
1453 | .rename = reiserfs_rename, | ||
1454 | .setattr = reiserfs_setattr, | ||
1455 | .setxattr = reiserfs_setxattr, | ||
1456 | .getxattr = reiserfs_getxattr, | ||
1457 | .listxattr = reiserfs_listxattr, | ||
1458 | .removexattr = reiserfs_removexattr, | ||
1459 | .permission = reiserfs_permission, | ||
1460 | }; | ||
1461 | |||
1462 | /* | ||
1463 | * symlink operations.. same as page_symlink_inode_operations, with xattr | ||
1464 | * stuff added | ||
1465 | */ | ||
1466 | struct inode_operations reiserfs_symlink_inode_operations = { | ||
1467 | .readlink = generic_readlink, | ||
1468 | .follow_link = page_follow_link_light, | ||
1469 | .put_link = page_put_link, | ||
1470 | .setattr = reiserfs_setattr, | ||
1471 | .setxattr = reiserfs_setxattr, | ||
1472 | .getxattr = reiserfs_getxattr, | ||
1473 | .listxattr = reiserfs_listxattr, | ||
1474 | .removexattr = reiserfs_removexattr, | ||
1475 | .permission = reiserfs_permission, | ||
1476 | |||
1477 | }; | ||
1478 | |||
1479 | |||
1480 | /* | ||
1481 | * special file operations.. just xattr/acl stuff | ||
1482 | */ | ||
1483 | struct inode_operations reiserfs_special_inode_operations = { | ||
1484 | .setattr = reiserfs_setattr, | ||
1485 | .setxattr = reiserfs_setxattr, | ||
1486 | .getxattr = reiserfs_getxattr, | ||
1487 | .listxattr = reiserfs_listxattr, | ||
1488 | .removexattr = reiserfs_removexattr, | ||
1489 | .permission = reiserfs_permission, | ||
1490 | |||
1491 | }; | ||