diff options
Diffstat (limited to 'fs/afs/dir.c')
-rw-r--r-- | fs/afs/dir.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index d7697f6f3b7f..87368417e4d3 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -15,6 +15,7 @@ | |||
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/ctype.h> | ||
18 | #include "internal.h" | 19 | #include "internal.h" |
19 | 20 | ||
20 | static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, | 21 | static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, |
@@ -28,11 +29,13 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, | |||
28 | 29 | ||
29 | const struct file_operations afs_dir_file_operations = { | 30 | const struct file_operations afs_dir_file_operations = { |
30 | .open = afs_dir_open, | 31 | .open = afs_dir_open, |
32 | .release = afs_release, | ||
31 | .readdir = afs_dir_readdir, | 33 | .readdir = afs_dir_readdir, |
32 | }; | 34 | }; |
33 | 35 | ||
34 | const struct inode_operations afs_dir_inode_operations = { | 36 | const struct inode_operations afs_dir_inode_operations = { |
35 | .lookup = afs_dir_lookup, | 37 | .lookup = afs_dir_lookup, |
38 | .permission = afs_permission, | ||
36 | .getattr = afs_inode_getattr, | 39 | .getattr = afs_inode_getattr, |
37 | #if 0 /* TODO */ | 40 | #if 0 /* TODO */ |
38 | .create = afs_dir_create, | 41 | .create = afs_dir_create, |
@@ -169,13 +172,17 @@ static inline void afs_dir_put_page(struct page *page) | |||
169 | /* | 172 | /* |
170 | * get a page into the pagecache | 173 | * get a page into the pagecache |
171 | */ | 174 | */ |
172 | static struct page *afs_dir_get_page(struct inode *dir, unsigned long index) | 175 | static struct page *afs_dir_get_page(struct inode *dir, unsigned long index, |
176 | struct key *key) | ||
173 | { | 177 | { |
174 | struct page *page; | 178 | struct page *page; |
179 | struct file file = { | ||
180 | .private_data = key, | ||
181 | }; | ||
175 | 182 | ||
176 | _enter("{%lu},%lu", dir->i_ino, index); | 183 | _enter("{%lu},%lu", dir->i_ino, index); |
177 | 184 | ||
178 | page = read_mapping_page(dir->i_mapping, index, NULL); | 185 | page = read_mapping_page(dir->i_mapping, index, &file); |
179 | if (!IS_ERR(page)) { | 186 | if (!IS_ERR(page)) { |
180 | wait_on_page_locked(page); | 187 | wait_on_page_locked(page); |
181 | kmap(page); | 188 | kmap(page); |
@@ -207,8 +214,7 @@ static int afs_dir_open(struct inode *inode, struct file *file) | |||
207 | if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags)) | 214 | if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags)) |
208 | return -ENOENT; | 215 | return -ENOENT; |
209 | 216 | ||
210 | _leave(" = 0"); | 217 | return afs_open(inode, file); |
211 | return 0; | ||
212 | } | 218 | } |
213 | 219 | ||
214 | /* | 220 | /* |
@@ -311,7 +317,7 @@ static int afs_dir_iterate_block(unsigned *fpos, | |||
311 | * iterate through the data blob that lists the contents of an AFS directory | 317 | * iterate through the data blob that lists the contents of an AFS directory |
312 | */ | 318 | */ |
313 | static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, | 319 | static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, |
314 | filldir_t filldir) | 320 | filldir_t filldir, struct key *key) |
315 | { | 321 | { |
316 | union afs_dir_block *dblock; | 322 | union afs_dir_block *dblock; |
317 | struct afs_dir_page *dbuf; | 323 | struct afs_dir_page *dbuf; |
@@ -336,7 +342,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, | |||
336 | blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1); | 342 | blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1); |
337 | 343 | ||
338 | /* fetch the appropriate page from the directory */ | 344 | /* fetch the appropriate page from the directory */ |
339 | page = afs_dir_get_page(dir, blkoff / PAGE_SIZE); | 345 | page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key); |
340 | if (IS_ERR(page)) { | 346 | if (IS_ERR(page)) { |
341 | ret = PTR_ERR(page); | 347 | ret = PTR_ERR(page); |
342 | break; | 348 | break; |
@@ -381,9 +387,11 @@ static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir) | |||
381 | _enter("{%Ld,{%lu}}", | 387 | _enter("{%Ld,{%lu}}", |
382 | file->f_pos, file->f_path.dentry->d_inode->i_ino); | 388 | file->f_pos, file->f_path.dentry->d_inode->i_ino); |
383 | 389 | ||
390 | ASSERT(file->private_data != NULL); | ||
391 | |||
384 | fpos = file->f_pos; | 392 | fpos = file->f_pos; |
385 | ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, | 393 | ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, |
386 | cookie, filldir); | 394 | cookie, filldir, file->private_data); |
387 | file->f_pos = fpos; | 395 | file->f_pos = fpos; |
388 | 396 | ||
389 | _leave(" = %d", ret); | 397 | _leave(" = %d", ret); |
@@ -424,7 +432,7 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, | |||
424 | * do a lookup in a directory | 432 | * do a lookup in a directory |
425 | */ | 433 | */ |
426 | static int afs_do_lookup(struct inode *dir, struct dentry *dentry, | 434 | static int afs_do_lookup(struct inode *dir, struct dentry *dentry, |
427 | struct afs_fid *fid) | 435 | struct afs_fid *fid, struct key *key) |
428 | { | 436 | { |
429 | struct afs_dir_lookup_cookie cookie; | 437 | struct afs_dir_lookup_cookie cookie; |
430 | struct afs_super_info *as; | 438 | struct afs_super_info *as; |
@@ -442,7 +450,8 @@ static int afs_do_lookup(struct inode *dir, struct dentry *dentry, | |||
442 | cookie.found = 0; | 450 | cookie.found = 0; |
443 | 451 | ||
444 | fpos = 0; | 452 | fpos = 0; |
445 | ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir); | 453 | ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir, |
454 | key); | ||
446 | if (ret < 0) { | 455 | if (ret < 0) { |
447 | _leave(" = %d [iter]", ret); | 456 | _leave(" = %d [iter]", ret); |
448 | return ret; | 457 | return ret; |
@@ -468,6 +477,7 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, | |||
468 | struct afs_vnode *vnode; | 477 | struct afs_vnode *vnode; |
469 | struct afs_fid fid; | 478 | struct afs_fid fid; |
470 | struct inode *inode; | 479 | struct inode *inode; |
480 | struct key *key; | ||
471 | int ret; | 481 | int ret; |
472 | 482 | ||
473 | _enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name); | 483 | _enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name); |
@@ -483,14 +493,22 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, | |||
483 | return ERR_PTR(-ESTALE); | 493 | return ERR_PTR(-ESTALE); |
484 | } | 494 | } |
485 | 495 | ||
486 | ret = afs_do_lookup(dir, dentry, &fid); | 496 | key = afs_request_key(vnode->volume->cell); |
497 | if (IS_ERR(key)) { | ||
498 | _leave(" = %ld [key]", PTR_ERR(key)); | ||
499 | return ERR_PTR(PTR_ERR(key)); | ||
500 | } | ||
501 | |||
502 | ret = afs_do_lookup(dir, dentry, &fid, key); | ||
487 | if (ret < 0) { | 503 | if (ret < 0) { |
504 | key_put(key); | ||
488 | _leave(" = %d [do]", ret); | 505 | _leave(" = %d [do]", ret); |
489 | return ERR_PTR(ret); | 506 | return ERR_PTR(ret); |
490 | } | 507 | } |
491 | 508 | ||
492 | /* instantiate the dentry */ | 509 | /* instantiate the dentry */ |
493 | inode = afs_iget(dir->i_sb, &fid); | 510 | inode = afs_iget(dir->i_sb, key, &fid); |
511 | key_put(key); | ||
494 | if (IS_ERR(inode)) { | 512 | if (IS_ERR(inode)) { |
495 | _leave(" = %ld", PTR_ERR(inode)); | 513 | _leave(" = %ld", PTR_ERR(inode)); |
496 | return ERR_PTR(PTR_ERR(inode)); | 514 | return ERR_PTR(PTR_ERR(inode)); |
@@ -559,6 +577,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
559 | struct afs_fid fid; | 577 | struct afs_fid fid; |
560 | struct dentry *parent; | 578 | struct dentry *parent; |
561 | struct inode *inode, *dir; | 579 | struct inode *inode, *dir; |
580 | struct key *key; | ||
562 | int ret; | 581 | int ret; |
563 | 582 | ||
564 | vnode = AFS_FS_I(dentry->d_inode); | 583 | vnode = AFS_FS_I(dentry->d_inode); |
@@ -566,6 +585,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
566 | _enter("{sb=%p n=%s fl=%lx},", | 585 | _enter("{sb=%p n=%s fl=%lx},", |
567 | dentry->d_sb, dentry->d_name.name, vnode->flags); | 586 | dentry->d_sb, dentry->d_name.name, vnode->flags); |
568 | 587 | ||
588 | key = afs_request_key(vnode->volume->cell); | ||
589 | if (IS_ERR(key)) | ||
590 | key = NULL; | ||
591 | |||
569 | /* lock down the parent dentry so we can peer at it */ | 592 | /* lock down the parent dentry so we can peer at it */ |
570 | parent = dget_parent(dentry); | 593 | parent = dget_parent(dentry); |
571 | 594 | ||
@@ -595,7 +618,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
595 | _debug("dir modified"); | 618 | _debug("dir modified"); |
596 | 619 | ||
597 | /* search the directory for this vnode */ | 620 | /* search the directory for this vnode */ |
598 | ret = afs_do_lookup(dir, dentry, &fid); | 621 | ret = afs_do_lookup(dir, dentry, &fid, key); |
599 | if (ret == -ENOENT) { | 622 | if (ret == -ENOENT) { |
600 | _debug("%s: dirent not found", dentry->d_name.name); | 623 | _debug("%s: dirent not found", dentry->d_name.name); |
601 | goto not_found; | 624 | goto not_found; |
@@ -637,7 +660,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
637 | test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) { | 660 | test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) { |
638 | _debug("%s: changed", dentry->d_name.name); | 661 | _debug("%s: changed", dentry->d_name.name); |
639 | set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags); | 662 | set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags); |
640 | if (afs_vnode_fetch_status(vnode) < 0) { | 663 | if (afs_vnode_fetch_status(vnode, NULL, key) < 0) { |
641 | mutex_unlock(&vnode->cb_broken_lock); | 664 | mutex_unlock(&vnode->cb_broken_lock); |
642 | goto out_bad; | 665 | goto out_bad; |
643 | } | 666 | } |
@@ -667,6 +690,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
667 | 690 | ||
668 | out_valid: | 691 | out_valid: |
669 | dput(parent); | 692 | dput(parent); |
693 | key_put(key); | ||
670 | _leave(" = 1 [valid]"); | 694 | _leave(" = 1 [valid]"); |
671 | return 1; | 695 | return 1; |
672 | 696 | ||
@@ -688,6 +712,7 @@ out_bad: | |||
688 | shrink_dcache_parent(dentry); | 712 | shrink_dcache_parent(dentry); |
689 | d_drop(dentry); | 713 | d_drop(dentry); |
690 | dput(parent); | 714 | dput(parent); |
715 | key_put(key); | ||
691 | 716 | ||
692 | _leave(" = 0 [bad]"); | 717 | _leave(" = 0 [bad]"); |
693 | return 0; | 718 | return 0; |