diff options
Diffstat (limited to 'fs/9p/vfs_dentry.c')
| -rw-r--r-- | fs/9p/vfs_dentry.c | 89 |
1 files changed, 48 insertions, 41 deletions
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index d74325295b1..b03dd23feda 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -34,6 +34,7 @@ #include <linux/namei.h> #include <linux/idr.h> #include <linux/sched.h> +#include <linux/slab.h> #include <net/9p/9p.h> #include <net/9p/client.h> @@ -42,40 +43,18 @@ #include "fid.h" /** - * v9fs_dentry_delete - called when dentry refcount equals 0 - * @dentry: dentry in question - * - * By returning 1 here we should remove cacheing of unused - * dentry components. - * - */ - -static int v9fs_dentry_delete(struct dentry *dentry) -{ - P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name, - dentry); - - return 1; -} - -/** * v9fs_cached_dentry_delete - called when dentry refcount equals 0 * @dentry: dentry in question * - * Only return 1 if our inode is invalid. Only non-synthetic files - * (ones without mtime == 0) should be calling this function. - * */ - -static int v9fs_cached_dentry_delete(struct dentry *dentry) +static int v9fs_cached_dentry_delete(const struct dentry *dentry) { - struct inode *inode = dentry->d_inode; - P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name, - dentry); + p9_debug(P9_DEBUG_VFS, " dentry: %s (%p)\n", + dentry->d_name.name, dentry); - if(!inode) + /* Don't cache negative dentries */ + if (!dentry->d_inode) return 1; - return 0; } @@ -85,31 +64,59 @@ static int v9fs_cached_dentry_delete(struct dentry *dentry) * */ -void v9fs_dentry_release(struct dentry *dentry) +static void v9fs_dentry_release(struct dentry *dentry) +{ + struct hlist_node *p, *n; + p9_debug(P9_DEBUG_VFS, " dentry: %s (%p)\n", + dentry->d_name.name, dentry); + hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata) + p9_client_clunk(hlist_entry(p, struct p9_fid, dlist)); + dentry->d_fsdata = NULL; +} + +static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) { - struct v9fs_dentry *dent; - struct p9_fid *temp, *current_fid; + struct p9_fid *fid; + struct inode *inode; + struct v9fs_inode *v9inode; + + if (flags & LOOKUP_RCU) + return -ECHILD; - P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name, - dentry); - dent = dentry->d_fsdata; - if (dent) { - list_for_each_entry_safe(current_fid, temp, &dent->fidlist, - dlist) { - p9_client_clunk(current_fid); - } + inode = dentry->d_inode; + if (!inode) + goto out_valid; - kfree(dent); - dentry->d_fsdata = NULL; + v9inode = V9FS_I(inode); + if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { + int retval; + struct v9fs_session_info *v9ses; + fid = v9fs_fid_lookup(dentry); + if (IS_ERR(fid)) + return PTR_ERR(fid); + + v9ses = v9fs_inode2v9ses(inode); + if (v9fs_proto_dotl(v9ses)) + retval = v9fs_refresh_inode_dotl(fid, inode); + else + retval = v9fs_refresh_inode(fid, inode); + if (retval == -ENOENT) + return 0; + if (retval < 0) + return retval; } +out_valid: + return 1; } const struct dentry_operations v9fs_cached_dentry_operations = { + .d_revalidate = v9fs_lookup_revalidate, + .d_weak_revalidate = v9fs_lookup_revalidate, .d_delete = v9fs_cached_dentry_delete, .d_release = v9fs_dentry_release, }; const struct dentry_operations v9fs_dentry_operations = { - .d_delete = v9fs_dentry_delete, + .d_delete = always_delete_dentry, .d_release = v9fs_dentry_release, }; |
