aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@gmail.com>2006-03-02 05:54:33 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-02 11:33:07 -0500
commit46f6dac259717551916405ee3388de89fb152bca (patch)
tree0e6c8b4505339e90c05ec8326220286fd19fe1f4
parent74b8054c730785cd9db093e48f53337e521b6270 (diff)
[PATCH] v9fs: simplify fid mapping
v9fs has been plagued by an over-complicated approach trying to map Linux dentry semantics to Plan 9 fid semantics. Our previous approach called for aggressive flushing of the dcache resulting in several problems (including wierd cwd behavior when running /bin/pwd). This patch dramatically simplifies our handling of this fid management. Fids will not be clunked as promptly, but the new approach is more functionally correct. We now clunk un-open fids only when their dentry ref_count reaches 0 (and d_delete is called). Another simplification is we no longer seek to match fids to the process-id or uid of the action initiator. The uid-matching will need to be revisited when we fix the security model. Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/9p/fid.c94
-rw-r--r--fs/9p/fid.h1
-rw-r--r--fs/9p/v9fs.c1
-rw-r--r--fs/9p/vfs_dentry.c45
4 files changed, 15 insertions, 126 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index c27f546dd25b..c4d13bf904d2 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * V9FS FID Management 2 * V9FS FID Management
3 * 3 *
4 * Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com> 4 * Copyright (C) 2005, 2006 by Eric Van Hensbergen <ericvh@gmail.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -57,7 +57,6 @@ int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
57 } 57 }
58 58
59 fid->uid = current->uid; 59 fid->uid = current->uid;
60 fid->pid = current->pid;
61 list_add(&fid->list, fid_list); 60 list_add(&fid->list, fid_list);
62 return 0; 61 return 0;
63} 62}
@@ -88,7 +87,7 @@ struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid)
88 new->rdir_fcall = NULL; 87 new->rdir_fcall = NULL;
89 INIT_LIST_HEAD(&new->list); 88 INIT_LIST_HEAD(&new->list);
90 89
91 return new; 90 return new;
92} 91}
93 92
94/** 93/**
@@ -104,75 +103,13 @@ void v9fs_fid_destroy(struct v9fs_fid *fid)
104} 103}
105 104
106/** 105/**
107 * v9fs_fid_walk_up - walks from the process current directory
108 * up to the specified dentry.
109 */
110static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry)
111{
112 int fidnum, cfidnum, err;
113 struct v9fs_fid *cfid, *fid;
114 struct dentry *cde;
115 struct v9fs_session_info *v9ses;
116
117 v9ses = v9fs_inode2v9ses(current->fs->pwd->d_inode);
118 cfid = v9fs_fid_lookup(current->fs->pwd);
119 if (cfid == NULL) {
120 dprintk(DEBUG_ERROR, "process cwd doesn't have a fid\n");
121 return ERR_PTR(-ENOENT);
122 }
123
124 cfidnum = cfid->fid;
125 cde = current->fs->pwd;
126 /* TODO: take advantage of multiwalk */
127
128 fidnum = v9fs_get_idpool(&v9ses->fidpool);
129 if (fidnum < 0) {
130 dprintk(DEBUG_ERROR, "could not get a new fid num\n");
131 err = -ENOENT;
132 goto clunk_fid;
133 }
134
135 while (cde != dentry) {
136 if (cde == cde->d_parent) {
137 dprintk(DEBUG_ERROR, "can't find dentry\n");
138 err = -ENOENT;
139 goto clunk_fid;
140 }
141
142 err = v9fs_t_walk(v9ses, cfidnum, fidnum, "..", NULL);
143 if (err < 0) {
144 dprintk(DEBUG_ERROR, "problem walking to parent\n");
145 goto clunk_fid;
146 }
147
148 cfidnum = fidnum;
149 cde = cde->d_parent;
150 }
151
152 fid = v9fs_fid_create(v9ses, fidnum);
153 if (fid) {
154 err = v9fs_fid_insert(fid, dentry);
155 if (err < 0) {
156 kfree(fid);
157 goto clunk_fid;
158 }
159 }
160
161 return fid;
162
163clunk_fid:
164 v9fs_t_clunk(v9ses, fidnum);
165 return ERR_PTR(err);
166}
167
168/**
169 * v9fs_fid_lookup - retrieve the right fid from a particular dentry 106 * v9fs_fid_lookup - retrieve the right fid from a particular dentry
170 * @dentry: dentry to look for fid in 107 * @dentry: dentry to look for fid in
171 * @type: intent of lookup (operation or traversal) 108 * @type: intent of lookup (operation or traversal)
172 * 109 *
173 * search list of fids associated with a dentry for a fid with a matching 110 * find a fid in the dentry
174 * thread id or uid. If that fails, look up the dentry's parents to see if you 111 *
175 * can find a matching fid. 112 * TODO: only match fids that have the same uid as current user
176 * 113 *
177 */ 114 */
178 115
@@ -187,26 +124,7 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
187 return_fid = list_entry(fid_list->next, struct v9fs_fid, list); 124 return_fid = list_entry(fid_list->next, struct v9fs_fid, list);
188 125
189 if (!return_fid) { 126 if (!return_fid) {
190 struct dentry *par = current->fs->pwd->d_parent; 127 dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n");
191 int count = 1;
192 while (par != NULL) {
193 if (par == dentry)
194 break;
195 count++;
196 if (par == par->d_parent) {
197 dprintk(DEBUG_ERROR,
198 "got to root without finding dentry\n");
199 break;
200 }
201 par = par->d_parent;
202 }
203
204/* XXX - there may be some duplication we can get rid of */
205 if (par == dentry) {
206 return_fid = v9fs_fid_walk_up(dentry);
207 if (IS_ERR(return_fid))
208 return_fid = NULL;
209 }
210 } 128 }
211 129
212 return return_fid; 130 return return_fid;
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index 7ccf0d064e25..1fc2dd08d75a 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -44,7 +44,6 @@ struct v9fs_fid {
44 struct v9fs_fcall *rdir_fcall; 44 struct v9fs_fcall *rdir_fcall;
45 45
46 /* management stuff */ 46 /* management stuff */
47 pid_t pid; /* thread associated with this fid */
48 uid_t uid; /* user associated with this fid */ 47 uid_t uid; /* user associated with this fid */
49 48
50 /* private data */ 49 /* private data */
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index ef3386549140..61352491ba36 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -397,6 +397,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
397 } 397 }
398 398
399 if (v9ses->afid != ~0) { 399 if (v9ses->afid != ~0) {
400 dprintk(DEBUG_ERROR, "afid not equal to ~0\n");
400 if (v9fs_t_clunk(v9ses, v9ses->afid)) 401 if (v9fs_t_clunk(v9ses, v9ses->afid))
401 dprintk(DEBUG_ERROR, "clunk failed\n"); 402 dprintk(DEBUG_ERROR, "clunk failed\n");
402 } 403 }
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 2dd806dac9f1..12c9cc926b71 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -43,47 +43,18 @@
43#include "fid.h" 43#include "fid.h"
44 44
45/** 45/**
46 * v9fs_dentry_validate - VFS dcache hook to validate cache 46 * v9fs_dentry_delete - called when dentry refcount equals 0
47 * @dentry: dentry that is being validated 47 * @dentry: dentry in question
48 * @nd: path data
49 * 48 *
50 * dcache really shouldn't be used for 9P2000 as at all due to 49 * By returning 1 here we should remove cacheing of unused
51 * potential attached semantics to directory traversal (walk). 50 * dentry components.
52 *
53 * FUTURE: look into how to use dcache to allow multi-stage
54 * walks in Plan 9 & potential for better dcache operation which
55 * would remain valid for Plan 9 semantics. Older versions
56 * had validation via stat for those interested. However, since
57 * stat has the same approximate overhead as walk there really
58 * is no difference. The only improvement would be from a
59 * time-decay cache like NFS has and that undermines the
60 * synchronous nature of 9P2000.
61 * 51 *
62 */ 52 */
63 53
64static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd) 54int v9fs_dentry_delete(struct dentry *dentry)
65{ 55{
66 struct dentry *dc = current->fs->pwd; 56 dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
67 57 return 1;
68 dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry);
69 if (v9fs_fid_lookup(dentry)) {
70 dprintk(DEBUG_VFS, "VALID\n");
71 return 1;
72 }
73
74 while (dc != NULL) {
75 if (dc == dentry) {
76 dprintk(DEBUG_VFS, "VALID\n");
77 return 1;
78 }
79 if (dc == dc->d_parent)
80 break;
81
82 dc = dc->d_parent;
83 }
84
85 dprintk(DEBUG_VFS, "INVALID\n");
86 return 0;
87} 58}
88 59
89/** 60/**
@@ -118,6 +89,6 @@ void v9fs_dentry_release(struct dentry *dentry)
118} 89}
119 90
120struct dentry_operations v9fs_dentry_operations = { 91struct dentry_operations v9fs_dentry_operations = {
121 .d_revalidate = v9fs_dentry_validate, 92 .d_delete = v9fs_dentry_delete,
122 .d_release = v9fs_dentry_release, 93 .d_release = v9fs_dentry_release,
123}; 94};