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 d7697f6..8736841 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -15,6 +15,7 @@ #include <linux/slab.h> #include <linux/fs.h> #include <linux/pagemap.h> +#include <linux/ctype.h> #include "internal.h" 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, const struct file_operations afs_dir_file_operations = { .open = afs_dir_open, + .release = afs_release, .readdir = afs_dir_readdir, }; const struct inode_operations afs_dir_inode_operations = { .lookup = afs_dir_lookup, + .permission = afs_permission, .getattr = afs_inode_getattr, #if 0 /* TODO */ .create = afs_dir_create, @@ -169,13 +172,17 @@ static inline void afs_dir_put_page(struct page *page) /* * get a page into the pagecache */ -static struct page *afs_dir_get_page(struct inode *dir, unsigned long index) +static struct page *afs_dir_get_page(struct inode *dir, unsigned long index, + struct key *key) { struct page *page; + struct file file = { + .private_data = key, + }; _enter("{%lu},%lu", dir->i_ino, index); - page = read_mapping_page(dir->i_mapping, index, NULL); + page = read_mapping_page(dir->i_mapping, index, &file); if (!IS_ERR(page)) { wait_on_page_locked(page); kmap(page); @@ -207,8 +214,7 @@ static int afs_dir_open(struct inode *inode, struct file *file) if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags)) return -ENOENT; - _leave(" = 0"); - return 0; + return afs_open(inode, file); } /* @@ -311,7 +317,7 @@ static int afs_dir_iterate_block(unsigned *fpos, * iterate through the data blob that lists the contents of an AFS directory */ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, - filldir_t filldir) + filldir_t filldir, struct key *key) { union afs_dir_block *dblock; struct afs_dir_page *dbuf; @@ -336,7 +342,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1); /* fetch the appropriate page from the directory */ - page = afs_dir_get_page(dir, blkoff / PAGE_SIZE); + page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key); if (IS_ERR(page)) { ret = PTR_ERR(page); break; @@ -381,9 +387,11 @@ static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir) _enter("{%Ld,{%lu}}", file->f_pos, file->f_path.dentry->d_inode->i_ino); + ASSERT(file->private_data != NULL); + fpos = file->f_pos; ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, - cookie, filldir); + cookie, filldir, file->private_data); file->f_pos = fpos; _leave(" = %d", ret); @@ -424,7 +432,7 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, * do a lookup in a directory */ static int afs_do_lookup(struct inode *dir, struct dentry *dentry, - struct afs_fid *fid) + struct afs_fid *fid, struct key *key) { struct afs_dir_lookup_cookie cookie; struct afs_super_info *as; @@ -442,7 +450,8 @@ static int afs_do_lookup(struct inode *dir, struct dentry *dentry, cookie.found = 0; fpos = 0; - ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir); + ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir, + key); if (ret < 0) { _leave(" = %d [iter]", ret); return ret; @@ -468,6 +477,7 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, struct afs_vnode *vnode; struct afs_fid fid; struct inode *inode; + struct key *key; int ret; _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, return ERR_PTR(-ESTALE); } - ret = afs_do_lookup(dir, dentry, &fid); + key = afs_request_key(vnode->volume->cell); + if (IS_ERR(key)) { + _leave(" = %ld [key]", PTR_ERR(key)); + return ERR_PTR(PTR_ERR(key)); + } + + ret = afs_do_lookup(dir, dentry, &fid, key); if (ret < 0) { + key_put(key); _leave(" = %d [do]", ret); return ERR_PTR(ret); } /* instantiate the dentry */ - inode = afs_iget(dir->i_sb, &fid); + inode = afs_iget(dir->i_sb, key, &fid); + key_put(key); if (IS_ERR(inode)) { _leave(" = %ld", PTR_ERR(inode)); return ERR_PTR(PTR_ERR(inode)); @@ -559,6 +577,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) struct afs_fid fid; struct dentry *parent; struct inode *inode, *dir; + struct key *key; int ret; vnode = AFS_FS_I(dentry->d_inode); @@ -566,6 +585,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) _enter("{sb=%p n=%s fl=%lx},", dentry->d_sb, dentry->d_name.name, vnode->flags); + key = afs_request_key(vnode->volume->cell); + if (IS_ERR(key)) + key = NULL; + /* lock down the parent dentry so we can peer at it */ parent = dget_parent(dentry); @@ -595,7 +618,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) _debug("dir modified"); /* search the directory for this vnode */ - ret = afs_do_lookup(dir, dentry, &fid); + ret = afs_do_lookup(dir, dentry, &fid, key); if (ret == -ENOENT) { _debug("%s: dirent not found", dentry->d_name.name); goto not_found; @@ -637,7 +660,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) { _debug("%s: changed", dentry->d_name.name); set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags); - if (afs_vnode_fetch_status(vnode) < 0) { + if (afs_vnode_fetch_status(vnode, NULL, key) < 0) { mutex_unlock(&vnode->cb_broken_lock); goto out_bad; } @@ -667,6 +690,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) out_valid: dput(parent); + key_put(key); _leave(" = 1 [valid]"); return 1; @@ -688,6 +712,7 @@ out_bad: shrink_dcache_parent(dentry); d_drop(dentry); dput(parent); + key_put(key); _leave(" = 0 [bad]"); return 0; |