aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/dir.c')
-rw-r--r--fs/afs/dir.c852
1 files changed, 665 insertions, 187 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index b6dc2ebe47a..dac5b990c0c 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -15,45 +15,53 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/fs.h> 16#include <linux/fs.h>
17#include <linux/pagemap.h> 17#include <linux/pagemap.h>
18#include <linux/smp_lock.h> 18#include <linux/ctype.h>
19#include "vnode.h"
20#include "volume.h"
21#include <rxrpc/call.h>
22#include "super.h"
23#include "internal.h" 19#include "internal.h"
24 20
25static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, 21static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
26 struct nameidata *nd); 22 struct nameidata *nd);
27static int afs_dir_open(struct inode *inode, struct file *file); 23static int afs_dir_open(struct inode *inode, struct file *file);
28static int afs_dir_readdir(struct file *file, void *dirent, filldir_t filldir); 24static int afs_readdir(struct file *file, void *dirent, filldir_t filldir);
29static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd); 25static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd);
30static int afs_d_delete(struct dentry *dentry); 26static int afs_d_delete(struct dentry *dentry);
31static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, 27static void afs_d_release(struct dentry *dentry);
28static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
32 loff_t fpos, u64 ino, unsigned dtype); 29 loff_t fpos, u64 ino, unsigned dtype);
30static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
31 struct nameidata *nd);
32static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
33static int afs_rmdir(struct inode *dir, struct dentry *dentry);
34static int afs_unlink(struct inode *dir, struct dentry *dentry);
35static int afs_link(struct dentry *from, struct inode *dir,
36 struct dentry *dentry);
37static int afs_symlink(struct inode *dir, struct dentry *dentry,
38 const char *content);
39static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
40 struct inode *new_dir, struct dentry *new_dentry);
33 41
34const struct file_operations afs_dir_file_operations = { 42const struct file_operations afs_dir_file_operations = {
35 .open = afs_dir_open, 43 .open = afs_dir_open,
36 .readdir = afs_dir_readdir, 44 .release = afs_release,
45 .readdir = afs_readdir,
37}; 46};
38 47
39const struct inode_operations afs_dir_inode_operations = { 48const struct inode_operations afs_dir_inode_operations = {
40 .lookup = afs_dir_lookup, 49 .create = afs_create,
50 .lookup = afs_lookup,
51 .link = afs_link,
52 .unlink = afs_unlink,
53 .symlink = afs_symlink,
54 .mkdir = afs_mkdir,
55 .rmdir = afs_rmdir,
56 .rename = afs_rename,
57 .permission = afs_permission,
41 .getattr = afs_inode_getattr, 58 .getattr = afs_inode_getattr,
42#if 0 /* TODO */
43 .create = afs_dir_create,
44 .link = afs_dir_link,
45 .unlink = afs_dir_unlink,
46 .symlink = afs_dir_symlink,
47 .mkdir = afs_dir_mkdir,
48 .rmdir = afs_dir_rmdir,
49 .mknod = afs_dir_mknod,
50 .rename = afs_dir_rename,
51#endif
52}; 59};
53 60
54static struct dentry_operations afs_fs_dentry_operations = { 61static struct dentry_operations afs_fs_dentry_operations = {
55 .d_revalidate = afs_d_revalidate, 62 .d_revalidate = afs_d_revalidate,
56 .d_delete = afs_d_delete, 63 .d_delete = afs_d_delete,
64 .d_release = afs_d_release,
57}; 65};
58 66
59#define AFS_DIR_HASHTBL_SIZE 128 67#define AFS_DIR_HASHTBL_SIZE 128
@@ -105,14 +113,13 @@ struct afs_dir_page {
105 union afs_dir_block blocks[PAGE_SIZE / sizeof(union afs_dir_block)]; 113 union afs_dir_block blocks[PAGE_SIZE / sizeof(union afs_dir_block)];
106}; 114};
107 115
108struct afs_dir_lookup_cookie { 116struct afs_lookup_cookie {
109 struct afs_fid fid; 117 struct afs_fid fid;
110 const char *name; 118 const char *name;
111 size_t nlen; 119 size_t nlen;
112 int found; 120 int found;
113}; 121};
114 122
115/*****************************************************************************/
116/* 123/*
117 * check that a directory page is valid 124 * check that a directory page is valid
118 */ 125 */
@@ -128,9 +135,10 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page)
128 if (qty == 0) 135 if (qty == 0)
129 goto error; 136 goto error;
130 137
131 if (page->index==0 && qty!=ntohs(dbuf->blocks[0].pagehdr.npages)) { 138 if (page->index == 0 && qty != ntohs(dbuf->blocks[0].pagehdr.npages)) {
132 printk("kAFS: %s(%lu): wrong number of dir blocks %d!=%hu\n", 139 printk("kAFS: %s(%lu): wrong number of dir blocks %d!=%hu\n",
133 __FUNCTION__,dir->i_ino,qty,ntohs(dbuf->blocks[0].pagehdr.npages)); 140 __FUNCTION__, dir->i_ino, qty,
141 ntohs(dbuf->blocks[0].pagehdr.npages));
134 goto error; 142 goto error;
135 } 143 }
136#endif 144#endif
@@ -157,13 +165,11 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page)
157 SetPageChecked(page); 165 SetPageChecked(page);
158 return; 166 return;
159 167
160 error: 168error:
161 SetPageChecked(page); 169 SetPageChecked(page);
162 SetPageError(page); 170 SetPageError(page);
171}
163 172
164} /* end afs_dir_check_page() */
165
166/*****************************************************************************/
167/* 173/*
168 * discard a page cached in the pagecache 174 * discard a page cached in the pagecache
169 */ 175 */
@@ -171,20 +177,22 @@ static inline void afs_dir_put_page(struct page *page)
171{ 177{
172 kunmap(page); 178 kunmap(page);
173 page_cache_release(page); 179 page_cache_release(page);
180}
174 181
175} /* end afs_dir_put_page() */
176
177/*****************************************************************************/
178/* 182/*
179 * get a page into the pagecache 183 * get a page into the pagecache
180 */ 184 */
181static struct page *afs_dir_get_page(struct inode *dir, unsigned long index) 185static struct page *afs_dir_get_page(struct inode *dir, unsigned long index,
186 struct key *key)
182{ 187{
183 struct page *page; 188 struct page *page;
189 struct file file = {
190 .private_data = key,
191 };
184 192
185 _enter("{%lu},%lu", dir->i_ino, index); 193 _enter("{%lu},%lu", dir->i_ino, index);
186 194
187 page = read_mapping_page(dir->i_mapping, index, NULL); 195 page = read_mapping_page(dir->i_mapping, index, &file);
188 if (!IS_ERR(page)) { 196 if (!IS_ERR(page)) {
189 wait_on_page_locked(page); 197 wait_on_page_locked(page);
190 kmap(page); 198 kmap(page);
@@ -197,12 +205,12 @@ static struct page *afs_dir_get_page(struct inode *dir, unsigned long index)
197 } 205 }
198 return page; 206 return page;
199 207
200 fail: 208fail:
201 afs_dir_put_page(page); 209 afs_dir_put_page(page);
210 _leave(" = -EIO");
202 return ERR_PTR(-EIO); 211 return ERR_PTR(-EIO);
203} /* end afs_dir_get_page() */ 212}
204 213
205/*****************************************************************************/
206/* 214/*
207 * open an AFS directory file 215 * open an AFS directory file
208 */ 216 */
@@ -213,15 +221,12 @@ static int afs_dir_open(struct inode *inode, struct file *file)
213 BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048); 221 BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
214 BUILD_BUG_ON(sizeof(union afs_dirent) != 32); 222 BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
215 223
216 if (AFS_FS_I(inode)->flags & AFS_VNODE_DELETED) 224 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags))
217 return -ENOENT; 225 return -ENOENT;
218 226
219 _leave(" = 0"); 227 return afs_open(inode, file);
220 return 0; 228}
221
222} /* end afs_dir_open() */
223 229
224/*****************************************************************************/
225/* 230/*
226 * deal with one block in an AFS directory 231 * deal with one block in an AFS directory
227 */ 232 */
@@ -250,7 +255,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
250 /* skip entries marked unused in the bitmap */ 255 /* skip entries marked unused in the bitmap */
251 if (!(block->pagehdr.bitmap[offset / 8] & 256 if (!(block->pagehdr.bitmap[offset / 8] &
252 (1 << (offset % 8)))) { 257 (1 << (offset % 8)))) {
253 _debug("ENT[%Zu.%u]: unused\n", 258 _debug("ENT[%Zu.%u]: unused",
254 blkoff / sizeof(union afs_dir_block), offset); 259 blkoff / sizeof(union afs_dir_block), offset);
255 if (offset >= curr) 260 if (offset >= curr)
256 *fpos = blkoff + 261 *fpos = blkoff +
@@ -264,7 +269,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
264 sizeof(*block) - 269 sizeof(*block) -
265 offset * sizeof(union afs_dirent)); 270 offset * sizeof(union afs_dirent));
266 271
267 _debug("ENT[%Zu.%u]: %s %Zu \"%s\"\n", 272 _debug("ENT[%Zu.%u]: %s %Zu \"%s\"",
268 blkoff / sizeof(union afs_dir_block), offset, 273 blkoff / sizeof(union afs_dir_block), offset,
269 (offset < curr ? "skip" : "fill"), 274 (offset < curr ? "skip" : "fill"),
270 nlen, dire->u.name); 275 nlen, dire->u.name);
@@ -274,7 +279,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
274 if (next >= AFS_DIRENT_PER_BLOCK) { 279 if (next >= AFS_DIRENT_PER_BLOCK) {
275 _debug("ENT[%Zu.%u]:" 280 _debug("ENT[%Zu.%u]:"
276 " %u travelled beyond end dir block" 281 " %u travelled beyond end dir block"
277 " (len %u/%Zu)\n", 282 " (len %u/%Zu)",
278 blkoff / sizeof(union afs_dir_block), 283 blkoff / sizeof(union afs_dir_block),
279 offset, next, tmp, nlen); 284 offset, next, tmp, nlen);
280 return -EIO; 285 return -EIO;
@@ -282,13 +287,13 @@ static int afs_dir_iterate_block(unsigned *fpos,
282 if (!(block->pagehdr.bitmap[next / 8] & 287 if (!(block->pagehdr.bitmap[next / 8] &
283 (1 << (next % 8)))) { 288 (1 << (next % 8)))) {
284 _debug("ENT[%Zu.%u]:" 289 _debug("ENT[%Zu.%u]:"
285 " %u unmarked extension (len %u/%Zu)\n", 290 " %u unmarked extension (len %u/%Zu)",
286 blkoff / sizeof(union afs_dir_block), 291 blkoff / sizeof(union afs_dir_block),
287 offset, next, tmp, nlen); 292 offset, next, tmp, nlen);
288 return -EIO; 293 return -EIO;
289 } 294 }
290 295
291 _debug("ENT[%Zu.%u]: ext %u/%Zu\n", 296 _debug("ENT[%Zu.%u]: ext %u/%Zu",
292 blkoff / sizeof(union afs_dir_block), 297 blkoff / sizeof(union afs_dir_block),
293 next, tmp, nlen); 298 next, tmp, nlen);
294 next++; 299 next++;
@@ -304,7 +309,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
304 nlen, 309 nlen,
305 blkoff + offset * sizeof(union afs_dirent), 310 blkoff + offset * sizeof(union afs_dirent),
306 ntohl(dire->u.vnode), 311 ntohl(dire->u.vnode),
307 filldir == afs_dir_lookup_filldir ? 312 filldir == afs_lookup_filldir ?
308 ntohl(dire->u.unique) : DT_UNKNOWN); 313 ntohl(dire->u.unique) : DT_UNKNOWN);
309 if (ret < 0) { 314 if (ret < 0) {
310 _leave(" = 0 [full]"); 315 _leave(" = 0 [full]");
@@ -316,16 +321,15 @@ static int afs_dir_iterate_block(unsigned *fpos,
316 321
317 _leave(" = 1 [more]"); 322 _leave(" = 1 [more]");
318 return 1; 323 return 1;
319} /* end afs_dir_iterate_block() */ 324}
320 325
321/*****************************************************************************/
322/* 326/*
323 * read an AFS directory 327 * iterate through the data blob that lists the contents of an AFS directory
324 */ 328 */
325static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, 329static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
326 filldir_t filldir) 330 filldir_t filldir, struct key *key)
327{ 331{
328 union afs_dir_block *dblock; 332 union afs_dir_block *dblock;
329 struct afs_dir_page *dbuf; 333 struct afs_dir_page *dbuf;
330 struct page *page; 334 struct page *page;
331 unsigned blkoff, limit; 335 unsigned blkoff, limit;
@@ -333,7 +337,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
333 337
334 _enter("{%lu},%u,,", dir->i_ino, *fpos); 338 _enter("{%lu},%u,,", dir->i_ino, *fpos);
335 339
336 if (AFS_FS_I(dir)->flags & AFS_VNODE_DELETED) { 340 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) {
337 _leave(" = -ESTALE"); 341 _leave(" = -ESTALE");
338 return -ESTALE; 342 return -ESTALE;
339 } 343 }
@@ -348,7 +352,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
348 blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1); 352 blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1);
349 353
350 /* fetch the appropriate page from the directory */ 354 /* fetch the appropriate page from the directory */
351 page = afs_dir_get_page(dir, blkoff / PAGE_SIZE); 355 page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key);
352 if (IS_ERR(page)) { 356 if (IS_ERR(page)) {
353 ret = PTR_ERR(page); 357 ret = PTR_ERR(page);
354 break; 358 break;
@@ -377,43 +381,50 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
377 ret = 0; 381 ret = 0;
378 } 382 }
379 383
380 out: 384out:
381 _leave(" = %d", ret); 385 _leave(" = %d", ret);
382 return ret; 386 return ret;
383} /* end afs_dir_iterate() */ 387}
384 388
385/*****************************************************************************/
386/* 389/*
387 * read an AFS directory 390 * read an AFS directory
388 */ 391 */
389static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir) 392static int afs_readdir(struct file *file, void *cookie, filldir_t filldir)
390{ 393{
391 unsigned fpos; 394 unsigned fpos;
392 int ret; 395 int ret;
393 396
394 _enter("{%Ld,{%lu}}", file->f_pos, file->f_path.dentry->d_inode->i_ino); 397 _enter("{%Ld,{%lu}}",
398 file->f_pos, file->f_path.dentry->d_inode->i_ino);
399
400 ASSERT(file->private_data != NULL);
395 401
396 fpos = file->f_pos; 402 fpos = file->f_pos;
397 ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, cookie, filldir); 403 ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos,
404 cookie, filldir, file->private_data);
398 file->f_pos = fpos; 405 file->f_pos = fpos;
399 406
400 _leave(" = %d", ret); 407 _leave(" = %d", ret);
401 return ret; 408 return ret;
402} /* end afs_dir_readdir() */ 409}
403 410
404/*****************************************************************************/
405/* 411/*
406 * search the directory for a name 412 * search the directory for a name
407 * - if afs_dir_iterate_block() spots this function, it'll pass the FID 413 * - if afs_dir_iterate_block() spots this function, it'll pass the FID
408 * uniquifier through dtype 414 * uniquifier through dtype
409 */ 415 */
410static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, 416static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
411 loff_t fpos, u64 ino, unsigned dtype) 417 loff_t fpos, u64 ino, unsigned dtype)
412{ 418{
413 struct afs_dir_lookup_cookie *cookie = _cookie; 419 struct afs_lookup_cookie *cookie = _cookie;
414 420
415 _enter("{%s,%Zu},%s,%u,,%lu,%u", 421 _enter("{%s,%Zu},%s,%u,,%llu,%u",
416 cookie->name, cookie->nlen, name, nlen, ino, dtype); 422 cookie->name, cookie->nlen, name, nlen,
423 (unsigned long long) ino, dtype);
424
425 /* insanity checks first */
426 BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
427 BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
417 428
418 if (cookie->nlen != nlen || memcmp(cookie->name, name, nlen) != 0) { 429 if (cookie->nlen != nlen || memcmp(cookie->name, name, nlen) != 0) {
419 _leave(" = 0 [no]"); 430 _leave(" = 0 [no]");
@@ -426,216 +437,254 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
426 437
427 _leave(" = -1 [found]"); 438 _leave(" = -1 [found]");
428 return -1; 439 return -1;
429} /* end afs_dir_lookup_filldir() */ 440}
430 441
431/*****************************************************************************/
432/* 442/*
433 * look up an entry in a directory 443 * do a lookup in a directory
444 * - just returns the FID the dentry name maps to if found
434 */ 445 */
435static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, 446static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
436 struct nameidata *nd) 447 struct afs_fid *fid, struct key *key)
437{ 448{
438 struct afs_dir_lookup_cookie cookie; 449 struct afs_lookup_cookie cookie;
439 struct afs_super_info *as; 450 struct afs_super_info *as;
451 unsigned fpos;
452 int ret;
453
454 _enter("{%lu},%p{%s},", dir->i_ino, dentry, dentry->d_name.name);
455
456 as = dir->i_sb->s_fs_info;
457
458 /* search the directory */
459 cookie.name = dentry->d_name.name;
460 cookie.nlen = dentry->d_name.len;
461 cookie.fid.vid = as->volume->vid;
462 cookie.found = 0;
463
464 fpos = 0;
465 ret = afs_dir_iterate(dir, &fpos, &cookie, afs_lookup_filldir,
466 key);
467 if (ret < 0) {
468 _leave(" = %d [iter]", ret);
469 return ret;
470 }
471
472 ret = -ENOENT;
473 if (!cookie.found) {
474 _leave(" = -ENOENT [not found]");
475 return -ENOENT;
476 }
477
478 *fid = cookie.fid;
479 _leave(" = 0 { vn=%u u=%u }", fid->vnode, fid->unique);
480 return 0;
481}
482
483/*
484 * look up an entry in a directory
485 */
486static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
487 struct nameidata *nd)
488{
440 struct afs_vnode *vnode; 489 struct afs_vnode *vnode;
490 struct afs_fid fid;
441 struct inode *inode; 491 struct inode *inode;
442 unsigned fpos; 492 struct key *key;
443 int ret; 493 int ret;
444 494
445 _enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name); 495 vnode = AFS_FS_I(dir);
446 496
447 /* insanity checks first */ 497 _enter("{%x:%d},%p{%s},",
448 BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048); 498 vnode->fid.vid, vnode->fid.vnode, dentry, dentry->d_name.name);
449 BUILD_BUG_ON(sizeof(union afs_dirent) != 32); 499
500 ASSERTCMP(dentry->d_inode, ==, NULL);
450 501
451 if (dentry->d_name.len > 255) { 502 if (dentry->d_name.len > 255) {
452 _leave(" = -ENAMETOOLONG"); 503 _leave(" = -ENAMETOOLONG");
453 return ERR_PTR(-ENAMETOOLONG); 504 return ERR_PTR(-ENAMETOOLONG);
454 } 505 }
455 506
456 vnode = AFS_FS_I(dir); 507 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
457 if (vnode->flags & AFS_VNODE_DELETED) {
458 _leave(" = -ESTALE"); 508 _leave(" = -ESTALE");
459 return ERR_PTR(-ESTALE); 509 return ERR_PTR(-ESTALE);
460 } 510 }
461 511
462 as = dir->i_sb->s_fs_info; 512 key = afs_request_key(vnode->volume->cell);
463 513 if (IS_ERR(key)) {
464 /* search the directory */ 514 _leave(" = %ld [key]", PTR_ERR(key));
465 cookie.name = dentry->d_name.name; 515 return ERR_PTR(PTR_ERR(key));
466 cookie.nlen = dentry->d_name.len; 516 }
467 cookie.fid.vid = as->volume->vid;
468 cookie.found = 0;
469 517
470 fpos = 0; 518 ret = afs_validate(vnode, key);
471 ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir);
472 if (ret < 0) { 519 if (ret < 0) {
473 _leave(" = %d", ret); 520 key_put(key);
521 _leave(" = %d [val]", ret);
474 return ERR_PTR(ret); 522 return ERR_PTR(ret);
475 } 523 }
476 524
477 ret = -ENOENT; 525 ret = afs_do_lookup(dir, dentry, &fid, key);
478 if (!cookie.found) { 526 if (ret < 0) {
479 _leave(" = %d", ret); 527 key_put(key);
528 if (ret == -ENOENT) {
529 d_add(dentry, NULL);
530 _leave(" = NULL [negative]");
531 return NULL;
532 }
533 _leave(" = %d [do]", ret);
480 return ERR_PTR(ret); 534 return ERR_PTR(ret);
481 } 535 }
536 dentry->d_fsdata = (void *)(unsigned long) vnode->status.data_version;
482 537
483 /* instantiate the dentry */ 538 /* instantiate the dentry */
484 ret = afs_iget(dir->i_sb, &cookie.fid, &inode); 539 inode = afs_iget(dir->i_sb, key, &fid, NULL, NULL);
485 if (ret < 0) { 540 key_put(key);
486 _leave(" = %d", ret); 541 if (IS_ERR(inode)) {
487 return ERR_PTR(ret); 542 _leave(" = %ld", PTR_ERR(inode));
543 return ERR_PTR(PTR_ERR(inode));
488 } 544 }
489 545
490 dentry->d_op = &afs_fs_dentry_operations; 546 dentry->d_op = &afs_fs_dentry_operations;
491 dentry->d_fsdata = (void *) (unsigned long) vnode->status.version;
492 547
493 d_add(dentry, inode); 548 d_add(dentry, inode);
494 _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%lu }", 549 _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%lu }",
495 cookie.fid.vnode, 550 fid.vnode,
496 cookie.fid.unique, 551 fid.unique,
497 dentry->d_inode->i_ino, 552 dentry->d_inode->i_ino,
498 dentry->d_inode->i_version); 553 dentry->d_inode->i_version);
499 554
500 return NULL; 555 return NULL;
501} /* end afs_dir_lookup() */ 556}
502 557
503/*****************************************************************************/
504/* 558/*
505 * check that a dentry lookup hit has found a valid entry 559 * check that a dentry lookup hit has found a valid entry
506 * - NOTE! the hit can be a negative hit too, so we can't assume we have an 560 * - NOTE! the hit can be a negative hit too, so we can't assume we have an
507 * inode 561 * inode
508 * (derived from nfs_lookup_revalidate)
509 */ 562 */
510static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) 563static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
511{ 564{
512 struct afs_dir_lookup_cookie cookie; 565 struct afs_vnode *vnode, *dir;
566 struct afs_fid fid;
513 struct dentry *parent; 567 struct dentry *parent;
514 struct inode *inode, *dir; 568 struct key *key;
515 unsigned fpos; 569 void *dir_version;
516 int ret; 570 int ret;
517 571
518 _enter("{sb=%p n=%s},", dentry->d_sb, dentry->d_name.name); 572 vnode = AFS_FS_I(dentry->d_inode);
519 573
520 /* lock down the parent dentry so we can peer at it */ 574 if (dentry->d_inode)
521 parent = dget_parent(dentry->d_parent); 575 _enter("{v={%x:%u} n=%s fl=%lx},",
576 vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,
577 vnode->flags);
578 else
579 _enter("{neg n=%s}", dentry->d_name.name);
522 580
523 dir = parent->d_inode; 581 key = afs_request_key(AFS_FS_S(dentry->d_sb)->volume->cell);
524 inode = dentry->d_inode; 582 if (IS_ERR(key))
583 key = NULL;
525 584
526 /* handle a negative dentry */ 585 /* lock down the parent dentry so we can peer at it */
527 if (!inode) 586 parent = dget_parent(dentry);
587 if (!parent->d_inode)
528 goto out_bad; 588 goto out_bad;
529 589
530 /* handle a bad inode */ 590 dir = AFS_FS_I(parent->d_inode);
531 if (is_bad_inode(inode)) {
532 printk("kAFS: afs_d_revalidate: %s/%s has bad inode\n",
533 dentry->d_parent->d_name.name, dentry->d_name.name);
534 goto out_bad;
535 }
536 591
537 /* force a full look up if the parent directory changed since last the 592 /* validate the parent directory */
538 * server was consulted 593 if (test_bit(AFS_VNODE_MODIFIED, &dir->flags))
539 * - otherwise this inode must still exist, even if the inode details 594 afs_validate(dir, key);
540 * themselves have changed
541 */
542 if (AFS_FS_I(dir)->flags & AFS_VNODE_CHANGED)
543 afs_vnode_fetch_status(AFS_FS_I(dir));
544 595
545 if (AFS_FS_I(dir)->flags & AFS_VNODE_DELETED) { 596 if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
546 _debug("%s: parent dir deleted", dentry->d_name.name); 597 _debug("%s: parent dir deleted", dentry->d_name.name);
547 goto out_bad; 598 goto out_bad;
548 } 599 }
549 600
550 if (AFS_FS_I(inode)->flags & AFS_VNODE_DELETED) { 601 dir_version = (void *) (unsigned long) dir->status.data_version;
551 _debug("%s: file already deleted", dentry->d_name.name); 602 if (dentry->d_fsdata == dir_version)
552 goto out_bad; 603 goto out_valid; /* the dir contents are unchanged */
553 }
554
555 if ((unsigned long) dentry->d_fsdata !=
556 (unsigned long) AFS_FS_I(dir)->status.version) {
557 _debug("%s: parent changed %lu -> %u",
558 dentry->d_name.name,
559 (unsigned long) dentry->d_fsdata,
560 (unsigned) AFS_FS_I(dir)->status.version);
561 604
562 /* search the directory for this vnode */ 605 _debug("dir modified");
563 cookie.name = dentry->d_name.name;
564 cookie.nlen = dentry->d_name.len;
565 cookie.fid.vid = AFS_FS_I(inode)->volume->vid;
566 cookie.found = 0;
567 606
568 fpos = 0; 607 /* search the directory for this vnode */
569 ret = afs_dir_iterate(dir, &fpos, &cookie, 608 ret = afs_do_lookup(&dir->vfs_inode, dentry, &fid, key);
570 afs_dir_lookup_filldir); 609 switch (ret) {
571 if (ret < 0) { 610 case 0:
572 _debug("failed to iterate dir %s: %d", 611 /* the filename maps to something */
573 parent->d_name.name, ret); 612 if (!dentry->d_inode)
613 goto out_bad;
614 if (is_bad_inode(dentry->d_inode)) {
615 printk("kAFS: afs_d_revalidate: %s/%s has bad inode\n",
616 parent->d_name.name, dentry->d_name.name);
574 goto out_bad; 617 goto out_bad;
575 }
576
577 if (!cookie.found) {
578 _debug("%s: dirent not found", dentry->d_name.name);
579 goto not_found;
580 } 618 }
581 619
582 /* if the vnode ID has changed, then the dirent points to a 620 /* if the vnode ID has changed, then the dirent points to a
583 * different file */ 621 * different file */
584 if (cookie.fid.vnode != AFS_FS_I(inode)->fid.vnode) { 622 if (fid.vnode != vnode->fid.vnode) {
585 _debug("%s: dirent changed", dentry->d_name.name); 623 _debug("%s: dirent changed [%u != %u]",
624 dentry->d_name.name, fid.vnode,
625 vnode->fid.vnode);
586 goto not_found; 626 goto not_found;
587 } 627 }
588 628
589 /* if the vnode ID uniqifier has changed, then the file has 629 /* if the vnode ID uniqifier has changed, then the file has
590 * been deleted */ 630 * been deleted and replaced, and the original vnode ID has
591 if (cookie.fid.unique != AFS_FS_I(inode)->fid.unique) { 631 * been reused */
632 if (fid.unique != vnode->fid.unique) {
592 _debug("%s: file deleted (uq %u -> %u I:%lu)", 633 _debug("%s: file deleted (uq %u -> %u I:%lu)",
593 dentry->d_name.name, 634 dentry->d_name.name, fid.unique,
594 cookie.fid.unique, 635 vnode->fid.unique, dentry->d_inode->i_version);
595 AFS_FS_I(inode)->fid.unique, 636 spin_lock(&vnode->lock);
596 inode->i_version); 637 set_bit(AFS_VNODE_DELETED, &vnode->flags);
597 spin_lock(&AFS_FS_I(inode)->lock); 638 spin_unlock(&vnode->lock);
598 AFS_FS_I(inode)->flags |= AFS_VNODE_DELETED; 639 goto not_found;
599 spin_unlock(&AFS_FS_I(inode)->lock);
600 invalidate_remote_inode(inode);
601 goto out_bad;
602 } 640 }
641 goto out_valid;
642
643 case -ENOENT:
644 /* the filename is unknown */
645 _debug("%s: dirent not found", dentry->d_name.name);
646 if (dentry->d_inode)
647 goto not_found;
648 goto out_valid;
603 649
604 dentry->d_fsdata = 650 default:
605 (void *) (unsigned long) AFS_FS_I(dir)->status.version; 651 _debug("failed to iterate dir %s: %d",
652 parent->d_name.name, ret);
653 goto out_bad;
606 } 654 }
607 655
608 out_valid: 656out_valid:
657 dentry->d_fsdata = dir_version;
658out_skip:
609 dput(parent); 659 dput(parent);
660 key_put(key);
610 _leave(" = 1 [valid]"); 661 _leave(" = 1 [valid]");
611 return 1; 662 return 1;
612 663
613 /* the dirent, if it exists, now points to a different vnode */ 664 /* the dirent, if it exists, now points to a different vnode */
614 not_found: 665not_found:
615 spin_lock(&dentry->d_lock); 666 spin_lock(&dentry->d_lock);
616 dentry->d_flags |= DCACHE_NFSFS_RENAMED; 667 dentry->d_flags |= DCACHE_NFSFS_RENAMED;
617 spin_unlock(&dentry->d_lock); 668 spin_unlock(&dentry->d_lock);
618 669
619 out_bad: 670out_bad:
620 if (inode) { 671 if (dentry->d_inode) {
621 /* don't unhash if we have submounts */ 672 /* don't unhash if we have submounts */
622 if (have_submounts(dentry)) 673 if (have_submounts(dentry))
623 goto out_valid; 674 goto out_skip;
624 } 675 }
625 676
626 shrink_dcache_parent(dentry);
627
628 _debug("dropping dentry %s/%s", 677 _debug("dropping dentry %s/%s",
629 dentry->d_parent->d_name.name, dentry->d_name.name); 678 parent->d_name.name, dentry->d_name.name);
679 shrink_dcache_parent(dentry);
630 d_drop(dentry); 680 d_drop(dentry);
631
632 dput(parent); 681 dput(parent);
682 key_put(key);
633 683
634 _leave(" = 0 [bad]"); 684 _leave(" = 0 [bad]");
635 return 0; 685 return 0;
636} /* end afs_d_revalidate() */ 686}
637 687
638/*****************************************************************************/
639/* 688/*
640 * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't 689 * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
641 * sleep) 690 * sleep)
@@ -649,15 +698,444 @@ static int afs_d_delete(struct dentry *dentry)
649 if (dentry->d_flags & DCACHE_NFSFS_RENAMED) 698 if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
650 goto zap; 699 goto zap;
651 700
652 if (dentry->d_inode) { 701 if (dentry->d_inode &&
653 if (AFS_FS_I(dentry->d_inode)->flags & AFS_VNODE_DELETED) 702 test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dentry->d_inode)->flags))
654 goto zap; 703 goto zap;
655 }
656 704
657 _leave(" = 0 [keep]"); 705 _leave(" = 0 [keep]");
658 return 0; 706 return 0;
659 707
660 zap: 708zap:
661 _leave(" = 1 [zap]"); 709 _leave(" = 1 [zap]");
662 return 1; 710 return 1;
663} /* end afs_d_delete() */ 711}
712
713/*
714 * handle dentry release
715 */
716static void afs_d_release(struct dentry *dentry)
717{
718 _enter("%s", dentry->d_name.name);
719}
720
721/*
722 * create a directory on an AFS filesystem
723 */
724static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
725{
726 struct afs_file_status status;
727 struct afs_callback cb;
728 struct afs_server *server;
729 struct afs_vnode *dvnode, *vnode;
730 struct afs_fid fid;
731 struct inode *inode;
732 struct key *key;
733 int ret;
734
735 dvnode = AFS_FS_I(dir);
736
737 _enter("{%x:%d},{%s},%o",
738 dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
739
740 ret = -ENAMETOOLONG;
741 if (dentry->d_name.len > 255)
742 goto error;
743
744 key = afs_request_key(dvnode->volume->cell);
745 if (IS_ERR(key)) {
746 ret = PTR_ERR(key);
747 goto error;
748 }
749
750 mode |= S_IFDIR;
751 ret = afs_vnode_create(dvnode, key, dentry->d_name.name,
752 mode, &fid, &status, &cb, &server);
753 if (ret < 0)
754 goto mkdir_error;
755
756 inode = afs_iget(dir->i_sb, key, &fid, &status, &cb);
757 if (IS_ERR(inode)) {
758 /* ENOMEM at a really inconvenient time - just abandon the new
759 * directory on the server */
760 ret = PTR_ERR(inode);
761 goto iget_error;
762 }
763
764 /* apply the status report we've got for the new vnode */
765 vnode = AFS_FS_I(inode);
766 spin_lock(&vnode->lock);
767 vnode->update_cnt++;
768 spin_unlock(&vnode->lock);
769 afs_vnode_finalise_status_update(vnode, server);
770 afs_put_server(server);
771
772 d_instantiate(dentry, inode);
773 if (d_unhashed(dentry)) {
774 _debug("not hashed");
775 d_rehash(dentry);
776 }
777 key_put(key);
778 _leave(" = 0");
779 return 0;
780
781iget_error:
782 afs_put_server(server);
783mkdir_error:
784 key_put(key);
785error:
786 d_drop(dentry);
787 _leave(" = %d", ret);
788 return ret;
789}
790
791/*
792 * remove a directory from an AFS filesystem
793 */
794static int afs_rmdir(struct inode *dir, struct dentry *dentry)
795{
796 struct afs_vnode *dvnode, *vnode;
797 struct key *key;
798 int ret;
799
800 dvnode = AFS_FS_I(dir);
801
802 _enter("{%x:%d},{%s}",
803 dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
804
805 ret = -ENAMETOOLONG;
806 if (dentry->d_name.len > 255)
807 goto error;
808
809 key = afs_request_key(dvnode->volume->cell);
810 if (IS_ERR(key)) {
811 ret = PTR_ERR(key);
812 goto error;
813 }
814
815 ret = afs_vnode_remove(dvnode, key, dentry->d_name.name, true);
816 if (ret < 0)
817 goto rmdir_error;
818
819 if (dentry->d_inode) {
820 vnode = AFS_FS_I(dentry->d_inode);
821 clear_nlink(&vnode->vfs_inode);
822 set_bit(AFS_VNODE_DELETED, &vnode->flags);
823 afs_discard_callback_on_delete(vnode);
824 }
825
826 key_put(key);
827 _leave(" = 0");
828 return 0;
829
830rmdir_error:
831 key_put(key);
832error:
833 _leave(" = %d", ret);
834 return ret;
835}
836
837/*
838 * remove a file from an AFS filesystem
839 */
840static int afs_unlink(struct inode *dir, struct dentry *dentry)
841{
842 struct afs_vnode *dvnode, *vnode;
843 struct key *key;
844 int ret;
845
846 dvnode = AFS_FS_I(dir);
847
848 _enter("{%x:%d},{%s}",
849 dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
850
851 ret = -ENAMETOOLONG;
852 if (dentry->d_name.len > 255)
853 goto error;
854
855 key = afs_request_key(dvnode->volume->cell);
856 if (IS_ERR(key)) {
857 ret = PTR_ERR(key);
858 goto error;
859 }
860
861 if (dentry->d_inode) {
862 vnode = AFS_FS_I(dentry->d_inode);
863
864 /* make sure we have a callback promise on the victim */
865 ret = afs_validate(vnode, key);
866 if (ret < 0)
867 goto error;
868 }
869
870 ret = afs_vnode_remove(dvnode, key, dentry->d_name.name, false);
871 if (ret < 0)
872 goto remove_error;
873
874 if (dentry->d_inode) {
875 /* if the file wasn't deleted due to excess hard links, the
876 * fileserver will break the callback promise on the file - if
877 * it had one - before it returns to us, and if it was deleted,
878 * it won't
879 *
880 * however, if we didn't have a callback promise outstanding,
881 * or it was outstanding on a different server, then it won't
882 * break it either...
883 */
884 vnode = AFS_FS_I(dentry->d_inode);
885 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
886 _debug("AFS_VNODE_DELETED");
887 if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags))
888 _debug("AFS_VNODE_CB_BROKEN");
889 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
890 ret = afs_validate(vnode, key);
891 _debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret);
892 }
893
894 key_put(key);
895 _leave(" = 0");
896 return 0;
897
898remove_error:
899 key_put(key);
900error:
901 _leave(" = %d", ret);
902 return ret;
903}
904
905/*
906 * create a regular file on an AFS filesystem
907 */
908static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
909 struct nameidata *nd)
910{
911 struct afs_file_status status;
912 struct afs_callback cb;
913 struct afs_server *server;
914 struct afs_vnode *dvnode, *vnode;
915 struct afs_fid fid;
916 struct inode *inode;
917 struct key *key;
918 int ret;
919
920 dvnode = AFS_FS_I(dir);
921
922 _enter("{%x:%d},{%s},%o,",
923 dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
924
925 ret = -ENAMETOOLONG;
926 if (dentry->d_name.len > 255)
927 goto error;
928
929 key = afs_request_key(dvnode->volume->cell);
930 if (IS_ERR(key)) {
931 ret = PTR_ERR(key);
932 goto error;
933 }
934
935 mode |= S_IFREG;
936 ret = afs_vnode_create(dvnode, key, dentry->d_name.name,
937 mode, &fid, &status, &cb, &server);
938 if (ret < 0)
939 goto create_error;
940
941 inode = afs_iget(dir->i_sb, key, &fid, &status, &cb);
942 if (IS_ERR(inode)) {
943 /* ENOMEM at a really inconvenient time - just abandon the new
944 * directory on the server */
945 ret = PTR_ERR(inode);
946 goto iget_error;
947 }
948
949 /* apply the status report we've got for the new vnode */
950 vnode = AFS_FS_I(inode);
951 spin_lock(&vnode->lock);
952 vnode->update_cnt++;
953 spin_unlock(&vnode->lock);
954 afs_vnode_finalise_status_update(vnode, server);
955 afs_put_server(server);
956
957 d_instantiate(dentry, inode);
958 if (d_unhashed(dentry)) {
959 _debug("not hashed");
960 d_rehash(dentry);
961 }
962 key_put(key);
963 _leave(" = 0");
964 return 0;
965
966iget_error:
967 afs_put_server(server);
968create_error:
969 key_put(key);
970error:
971 d_drop(dentry);
972 _leave(" = %d", ret);
973 return ret;
974}
975
976/*
977 * create a hard link between files in an AFS filesystem
978 */
979static int afs_link(struct dentry *from, struct inode *dir,
980 struct dentry *dentry)
981{
982 struct afs_vnode *dvnode, *vnode;
983 struct key *key;
984 int ret;
985
986 vnode = AFS_FS_I(from->d_inode);
987 dvnode = AFS_FS_I(dir);
988
989 _enter("{%x:%d},{%x:%d},{%s}",
990 vnode->fid.vid, vnode->fid.vnode,
991 dvnode->fid.vid, dvnode->fid.vnode,
992 dentry->d_name.name);
993
994 ret = -ENAMETOOLONG;
995 if (dentry->d_name.len > 255)
996 goto error;
997
998 key = afs_request_key(dvnode->volume->cell);
999 if (IS_ERR(key)) {
1000 ret = PTR_ERR(key);
1001 goto error;
1002 }
1003
1004 ret = afs_vnode_link(dvnode, vnode, key, dentry->d_name.name);
1005 if (ret < 0)
1006 goto link_error;
1007
1008 atomic_inc(&vnode->vfs_inode.i_count);
1009 d_instantiate(dentry, &vnode->vfs_inode);
1010 key_put(key);
1011 _leave(" = 0");
1012 return 0;
1013
1014link_error:
1015 key_put(key);
1016error:
1017 d_drop(dentry);
1018 _leave(" = %d", ret);
1019 return ret;
1020}
1021
1022/*
1023 * create a symlink in an AFS filesystem
1024 */
1025static int afs_symlink(struct inode *dir, struct dentry *dentry,
1026 const char *content)
1027{
1028 struct afs_file_status status;
1029 struct afs_server *server;
1030 struct afs_vnode *dvnode, *vnode;
1031 struct afs_fid fid;
1032 struct inode *inode;
1033 struct key *key;
1034 int ret;
1035
1036 dvnode = AFS_FS_I(dir);
1037
1038 _enter("{%x:%d},{%s},%s",
1039 dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name,
1040 content);
1041
1042 ret = -ENAMETOOLONG;
1043 if (dentry->d_name.len > 255)
1044 goto error;
1045
1046 ret = -EINVAL;
1047 if (strlen(content) > 1023)
1048 goto error;
1049
1050 key = afs_request_key(dvnode->volume->cell);
1051 if (IS_ERR(key)) {
1052 ret = PTR_ERR(key);
1053 goto error;
1054 }
1055
1056 ret = afs_vnode_symlink(dvnode, key, dentry->d_name.name, content,
1057 &fid, &status, &server);
1058 if (ret < 0)
1059 goto create_error;
1060
1061 inode = afs_iget(dir->i_sb, key, &fid, &status, NULL);
1062 if (IS_ERR(inode)) {
1063 /* ENOMEM at a really inconvenient time - just abandon the new
1064 * directory on the server */
1065 ret = PTR_ERR(inode);
1066 goto iget_error;
1067 }
1068
1069 /* apply the status report we've got for the new vnode */
1070 vnode = AFS_FS_I(inode);
1071 spin_lock(&vnode->lock);
1072 vnode->update_cnt++;
1073 spin_unlock(&vnode->lock);
1074 afs_vnode_finalise_status_update(vnode, server);
1075 afs_put_server(server);
1076
1077 d_instantiate(dentry, inode);
1078 if (d_unhashed(dentry)) {
1079 _debug("not hashed");
1080 d_rehash(dentry);
1081 }
1082 key_put(key);
1083 _leave(" = 0");
1084 return 0;
1085
1086iget_error:
1087 afs_put_server(server);
1088create_error:
1089 key_put(key);
1090error:
1091 d_drop(dentry);
1092 _leave(" = %d", ret);
1093 return ret;
1094}
1095
1096/*
1097 * rename a file in an AFS filesystem and/or move it between directories
1098 */
1099static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1100 struct inode *new_dir, struct dentry *new_dentry)
1101{
1102 struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
1103 struct key *key;
1104 int ret;
1105
1106 vnode = AFS_FS_I(old_dentry->d_inode);
1107 orig_dvnode = AFS_FS_I(old_dir);
1108 new_dvnode = AFS_FS_I(new_dir);
1109
1110 _enter("{%x:%d},{%x:%d},{%x:%d},{%s}",
1111 orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
1112 vnode->fid.vid, vnode->fid.vnode,
1113 new_dvnode->fid.vid, new_dvnode->fid.vnode,
1114 new_dentry->d_name.name);
1115
1116 ret = -ENAMETOOLONG;
1117 if (new_dentry->d_name.len > 255)
1118 goto error;
1119
1120 key = afs_request_key(orig_dvnode->volume->cell);
1121 if (IS_ERR(key)) {
1122 ret = PTR_ERR(key);
1123 goto error;
1124 }
1125
1126 ret = afs_vnode_rename(orig_dvnode, new_dvnode, key,
1127 old_dentry->d_name.name,
1128 new_dentry->d_name.name);
1129 if (ret < 0)
1130 goto rename_error;
1131 key_put(key);
1132 _leave(" = 0");
1133 return 0;
1134
1135rename_error:
1136 key_put(key);
1137error:
1138 d_drop(new_dentry);
1139 _leave(" = %d", ret);
1140 return ret;
1141}