diff options
author | Eric Van Hensbergen <ericvh@gmail.com> | 2006-03-02 05:54:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-02 11:33:07 -0500 |
commit | 46f6dac259717551916405ee3388de89fb152bca (patch) | |
tree | 0e6c8b4505339e90c05ec8326220286fd19fe1f4 /fs | |
parent | 74b8054c730785cd9db093e48f53337e521b6270 (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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/9p/fid.c | 94 | ||||
-rw-r--r-- | fs/9p/fid.h | 1 | ||||
-rw-r--r-- | fs/9p/v9fs.c | 1 | ||||
-rw-r--r-- | fs/9p/vfs_dentry.c | 45 |
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 | */ | ||
110 | static 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 | |||
163 | clunk_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 | ||
64 | static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd) | 54 | int 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 | ||
120 | struct dentry_operations v9fs_dentry_operations = { | 91 | struct 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 | }; |