aboutsummaryrefslogtreecommitdiff
path: root/fs/9p/vfs_dentry.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p/vfs_dentry.c')
-rw-r--r--fs/9p/vfs_dentry.c128
1 files changed, 62 insertions, 66 deletions
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index a6aa947de0f..b03dd23feda 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -7,9 +7,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -31,59 +30,31 @@
#include <linux/pagemap.h>
#include <linux/stat.h>
#include <linux/string.h>
-#include <linux/smp_lock.h>
#include <linux/inet.h>
#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>
-#include "debug.h"
#include "v9fs.h"
-#include "9p.h"
#include "v9fs_vfs.h"
-#include "conv.h"
#include "fid.h"
/**
- * v9fs_dentry_validate - VFS dcache hook to validate cache
- * @dentry: dentry that is being validated
- * @nd: path data
- *
- * dcache really shouldn't be used for 9P2000 as at all due to
- * potential attached semantics to directory traversal (walk).
- *
- * FUTURE: look into how to use dcache to allow multi-stage
- * walks in Plan 9 & potential for better dcache operation which
- * would remain valid for Plan 9 semantics. Older versions
- * had validation via stat for those interested. However, since
- * stat has the same approximate overhead as walk there really
- * is no difference. The only improvement would be from a
- * time-decay cache like NFS has and that undermines the
- * synchronous nature of 9P2000.
+ * v9fs_cached_dentry_delete - called when dentry refcount equals 0
+ * @dentry: dentry in question
*
*/
-
-static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd)
+static int v9fs_cached_dentry_delete(const struct dentry *dentry)
{
- struct dentry *dc = current->fs->pwd;
+ p9_debug(P9_DEBUG_VFS, " dentry: %s (%p)\n",
+ dentry->d_name.name, dentry);
- dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry);
- if (v9fs_fid_lookup(dentry)) {
- dprintk(DEBUG_VFS, "VALID\n");
+ /* Don't cache negative dentries */
+ if (!dentry->d_inode)
return 1;
- }
-
- while (dc != NULL) {
- if (dc == dentry) {
- dprintk(DEBUG_VFS, "VALID\n");
- return 1;
- }
- if (dc == dc->d_parent)
- break;
-
- dc = dc->d_parent;
- }
-
- dprintk(DEBUG_VFS, "INVALID\n");
return 0;
}
@@ -93,34 +64,59 @@ static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd)
*
*/
-void v9fs_dentry_release(struct dentry *dentry)
+static void v9fs_dentry_release(struct dentry *dentry)
{
- dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
-
- if (dentry->d_fsdata != NULL) {
- struct list_head *fid_list = dentry->d_fsdata;
- struct v9fs_fid *temp = NULL;
- struct v9fs_fid *current_fid = NULL;
- struct v9fs_fcall *fcall = NULL;
-
- list_for_each_entry_safe(current_fid, temp, fid_list, list) {
- if (v9fs_t_clunk
- (current_fid->v9ses, current_fid->fid, &fcall))
- dprintk(DEBUG_ERROR, "clunk failed: %s\n",
- FCALL_ERROR(fcall));
-
- v9fs_put_idpool(current_fid->fid,
- &current_fid->v9ses->fidpool);
-
- kfree(fcall);
- v9fs_fid_destroy(current_fid);
- }
+ 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;
+}
- kfree(dentry->d_fsdata); /* free the list_head */
+static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
+{
+ struct p9_fid *fid;
+ struct inode *inode;
+ struct v9fs_inode *v9inode;
+
+ if (flags & LOOKUP_RCU)
+ return -ECHILD;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out_valid;
+
+ 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;
}
-struct dentry_operations v9fs_dentry_operations = {
- .d_revalidate = v9fs_dentry_validate,
+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 = always_delete_dentry,
.d_release = v9fs_dentry_release,
};