aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/fid.c
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 /fs/9p/fid.c
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>
Diffstat (limited to 'fs/9p/fid.c')
-rw-r--r--fs/9p/fid.c94
1 files changed, 6 insertions, 88 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;