diff options
-rw-r--r-- | fs/9p/fid.c | 176 | ||||
-rw-r--r-- | fs/9p/fid.h | 7 | ||||
-rw-r--r-- | fs/9p/vfs_dentry.c | 2 | ||||
-rw-r--r-- | fs/9p/vfs_dir.c | 11 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 88 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 91 | ||||
-rw-r--r-- | fs/9p/vfs_super.c | 21 |
7 files changed, 200 insertions, 196 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 821c9c4d76aa..d95f8626d170 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
@@ -71,21 +71,28 @@ static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) | |||
71 | * | 71 | * |
72 | */ | 72 | */ |
73 | 73 | ||
74 | struct v9fs_fid *v9fs_fid_create(struct dentry *dentry) | 74 | struct v9fs_fid *v9fs_fid_create(struct dentry *dentry, |
75 | struct v9fs_session_info *v9ses, int fid, int create) | ||
75 | { | 76 | { |
76 | struct v9fs_fid *new; | 77 | struct v9fs_fid *new; |
77 | 78 | ||
79 | dprintk(DEBUG_9P, "fid create dentry %p, fid %d, create %d\n", | ||
80 | dentry, fid, create); | ||
81 | |||
78 | new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | 82 | new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); |
79 | if (new == NULL) { | 83 | if (new == NULL) { |
80 | dprintk(DEBUG_ERROR, "Out of Memory\n"); | 84 | dprintk(DEBUG_ERROR, "Out of Memory\n"); |
81 | return ERR_PTR(-ENOMEM); | 85 | return ERR_PTR(-ENOMEM); |
82 | } | 86 | } |
83 | 87 | ||
84 | new->fid = -1; | 88 | new->fid = fid; |
89 | new->v9ses = v9ses; | ||
85 | new->fidopen = 0; | 90 | new->fidopen = 0; |
86 | new->fidcreate = 0; | 91 | new->fidcreate = create; |
87 | new->fidclunked = 0; | 92 | new->fidclunked = 0; |
88 | new->iounit = 0; | 93 | new->iounit = 0; |
94 | new->rdir_pos = 0; | ||
95 | new->rdir_fcall = NULL; | ||
89 | 96 | ||
90 | if (v9fs_fid_insert(new, dentry) == 0) | 97 | if (v9fs_fid_insert(new, dentry) == 0) |
91 | return new; | 98 | return new; |
@@ -109,6 +116,59 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) | |||
109 | } | 116 | } |
110 | 117 | ||
111 | /** | 118 | /** |
119 | * v9fs_fid_walk_up - walks from the process current directory | ||
120 | * up to the specified dentry. | ||
121 | */ | ||
122 | static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry) | ||
123 | { | ||
124 | int fidnum, cfidnum, err; | ||
125 | struct v9fs_fid *cfid; | ||
126 | struct dentry *cde; | ||
127 | struct v9fs_session_info *v9ses; | ||
128 | |||
129 | v9ses = v9fs_inode2v9ses(current->fs->pwd->d_inode); | ||
130 | cfid = v9fs_fid_lookup(current->fs->pwd); | ||
131 | if (cfid == NULL) { | ||
132 | dprintk(DEBUG_ERROR, "process cwd doesn't have a fid\n"); | ||
133 | return ERR_PTR(-ENOENT); | ||
134 | } | ||
135 | |||
136 | cfidnum = cfid->fid; | ||
137 | cde = current->fs->pwd; | ||
138 | /* TODO: take advantage of multiwalk */ | ||
139 | |||
140 | fidnum = v9fs_get_idpool(&v9ses->fidpool); | ||
141 | if (fidnum < 0) { | ||
142 | dprintk(DEBUG_ERROR, "could not get a new fid num\n"); | ||
143 | err = -ENOENT; | ||
144 | goto clunk_fid; | ||
145 | } | ||
146 | |||
147 | while (cde != dentry) { | ||
148 | if (cde == cde->d_parent) { | ||
149 | dprintk(DEBUG_ERROR, "can't find dentry\n"); | ||
150 | err = -ENOENT; | ||
151 | goto clunk_fid; | ||
152 | } | ||
153 | |||
154 | err = v9fs_t_walk(v9ses, cfidnum, fidnum, "..", NULL); | ||
155 | if (err < 0) { | ||
156 | dprintk(DEBUG_ERROR, "problem walking to parent\n"); | ||
157 | goto clunk_fid; | ||
158 | } | ||
159 | |||
160 | cfidnum = fidnum; | ||
161 | cde = cde->d_parent; | ||
162 | } | ||
163 | |||
164 | return v9fs_fid_create(dentry, v9ses, fidnum, 0); | ||
165 | |||
166 | clunk_fid: | ||
167 | v9fs_t_clunk(v9ses, fidnum, NULL); | ||
168 | return ERR_PTR(err); | ||
169 | } | ||
170 | |||
171 | /** | ||
112 | * v9fs_fid_lookup - retrieve the right fid from a particular dentry | 172 | * v9fs_fid_lookup - retrieve the right fid from a particular dentry |
113 | * @dentry: dentry to look for fid in | 173 | * @dentry: dentry to look for fid in |
114 | * @type: intent of lookup (operation or traversal) | 174 | * @type: intent of lookup (operation or traversal) |
@@ -119,49 +179,25 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) | |||
119 | * | 179 | * |
120 | */ | 180 | */ |
121 | 181 | ||
122 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type) | 182 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) |
123 | { | 183 | { |
124 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; | 184 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; |
125 | struct v9fs_fid *current_fid = NULL; | 185 | struct v9fs_fid *current_fid = NULL; |
126 | struct v9fs_fid *temp = NULL; | 186 | struct v9fs_fid *temp = NULL; |
127 | struct v9fs_fid *return_fid = NULL; | 187 | struct v9fs_fid *return_fid = NULL; |
128 | int found_parent = 0; | ||
129 | int found_user = 0; | ||
130 | 188 | ||
131 | dprintk(DEBUG_9P, " dentry: %s (%p) type %d\n", dentry->d_iname, dentry, | 189 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
132 | type); | ||
133 | 190 | ||
134 | if (fid_list && !list_empty(fid_list)) { | 191 | if (fid_list) { |
135 | list_for_each_entry_safe(current_fid, temp, fid_list, list) { | 192 | list_for_each_entry_safe(current_fid, temp, fid_list, list) { |
136 | if (current_fid->uid == current->uid) { | 193 | if (!current_fid->fidcreate) { |
137 | if (return_fid == NULL) { | 194 | return_fid = current_fid; |
138 | if ((type == FID_OP) | 195 | break; |
139 | || (!current_fid->fidopen)) { | ||
140 | return_fid = current_fid; | ||
141 | found_user = 1; | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | if (current_fid->pid == current->real_parent->pid) { | ||
146 | if ((return_fid == NULL) || (found_parent) | ||
147 | || (found_user)) { | ||
148 | if ((type == FID_OP) | ||
149 | || (!current_fid->fidopen)) { | ||
150 | return_fid = current_fid; | ||
151 | found_parent = 1; | ||
152 | found_user = 0; | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | if (current_fid->pid == current->pid) { | ||
157 | if ((type == FID_OP) || | ||
158 | (!current_fid->fidopen)) { | ||
159 | return_fid = current_fid; | ||
160 | found_parent = 0; | ||
161 | found_user = 0; | ||
162 | } | ||
163 | } | 196 | } |
164 | } | 197 | } |
198 | |||
199 | if (!return_fid) | ||
200 | return_fid = current_fid; | ||
165 | } | 201 | } |
166 | 202 | ||
167 | /* we are at the root but didn't match */ | 203 | /* we are at the root but didn't match */ |
@@ -187,55 +223,33 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type) | |||
187 | 223 | ||
188 | /* XXX - there may be some duplication we can get rid of */ | 224 | /* XXX - there may be some duplication we can get rid of */ |
189 | if (par == dentry) { | 225 | if (par == dentry) { |
190 | /* we need to fid_lookup the starting point */ | 226 | return_fid = v9fs_fid_walk_up(dentry); |
191 | int fidnum = -1; | 227 | if (IS_ERR(return_fid)) |
192 | int oldfid = -1; | 228 | return_fid = NULL; |
193 | int result = -1; | 229 | } |
194 | struct v9fs_session_info *v9ses = | 230 | } |
195 | v9fs_inode2v9ses(current->fs->pwd->d_inode); | ||
196 | |||
197 | current_fid = | ||
198 | v9fs_fid_lookup(current->fs->pwd, FID_WALK); | ||
199 | if (current_fid == NULL) { | ||
200 | dprintk(DEBUG_ERROR, | ||
201 | "process cwd doesn't have a fid\n"); | ||
202 | return return_fid; | ||
203 | } | ||
204 | oldfid = current_fid->fid; | ||
205 | par = current->fs->pwd; | ||
206 | /* TODO: take advantage of multiwalk */ | ||
207 | 231 | ||
208 | fidnum = v9fs_get_idpool(&v9ses->fidpool); | 232 | return return_fid; |
209 | if (fidnum < 0) { | 233 | } |
210 | dprintk(DEBUG_ERROR, | ||
211 | "could not get a new fid num\n"); | ||
212 | return return_fid; | ||
213 | } | ||
214 | 234 | ||
215 | while (par != dentry) { | 235 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *dentry) |
216 | result = | 236 | { |
217 | v9fs_t_walk(v9ses, oldfid, fidnum, "..", | 237 | struct list_head *fid_list; |
218 | NULL); | 238 | struct v9fs_fid *fid, *ftmp, *ret; |
219 | if (result < 0) { | 239 | |
220 | dprintk(DEBUG_ERROR, | 240 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
221 | "problem walking to parent\n"); | 241 | fid_list = (struct list_head *)dentry->d_fsdata; |
222 | 242 | ret = NULL; | |
223 | break; | 243 | if (fid_list) { |
224 | } | 244 | list_for_each_entry_safe(fid, ftmp, fid_list, list) { |
225 | oldfid = fidnum; | 245 | if (fid->fidcreate && fid->pid == current->pid) { |
226 | if (par == par->d_parent) { | 246 | list_del(&fid->list); |
227 | dprintk(DEBUG_ERROR, | 247 | ret = fid; |
228 | "can't find dentry\n"); | 248 | break; |
229 | break; | ||
230 | } | ||
231 | par = par->d_parent; | ||
232 | } | ||
233 | if (par == dentry) { | ||
234 | return_fid = v9fs_fid_create(dentry); | ||
235 | return_fid->fid = fidnum; | ||
236 | } | 249 | } |
237 | } | 250 | } |
238 | } | 251 | } |
239 | 252 | ||
240 | return return_fid; | 253 | dprintk(DEBUG_9P, "return %p\n", ret); |
254 | return ret; | ||
241 | } | 255 | } |
diff --git a/fs/9p/fid.h b/fs/9p/fid.h index 7db478ccca36..84c673a44c83 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #define FID_OP 0 | 26 | #define FID_OP 0 |
27 | #define FID_WALK 1 | 27 | #define FID_WALK 1 |
28 | #define FID_CREATE 2 | ||
28 | 29 | ||
29 | struct v9fs_fid { | 30 | struct v9fs_fid { |
30 | struct list_head list; /* list of fids associated with a dentry */ | 31 | struct list_head list; /* list of fids associated with a dentry */ |
@@ -52,6 +53,8 @@ struct v9fs_fid { | |||
52 | struct v9fs_session_info *v9ses; /* session info for this FID */ | 53 | struct v9fs_session_info *v9ses; /* session info for this FID */ |
53 | }; | 54 | }; |
54 | 55 | ||
55 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type); | 56 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); |
57 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *); | ||
56 | void v9fs_fid_destroy(struct v9fs_fid *fid); | 58 | void v9fs_fid_destroy(struct v9fs_fid *fid); |
57 | struct v9fs_fid *v9fs_fid_create(struct dentry *); | 59 | struct v9fs_fid *v9fs_fid_create(struct dentry *, |
60 | struct v9fs_session_info *v9ses, int fid, int create); | ||
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index 306c96741f81..a6aa947de0f9 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c | |||
@@ -67,7 +67,7 @@ static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd) | |||
67 | struct dentry *dc = current->fs->pwd; | 67 | struct dentry *dc = current->fs->pwd; |
68 | 68 | ||
69 | dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry); | 69 | dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry); |
70 | if (v9fs_fid_lookup(dentry, FID_OP)) { | 70 | if (v9fs_fid_lookup(dentry)) { |
71 | dprintk(DEBUG_VFS, "VALID\n"); | 71 | dprintk(DEBUG_VFS, "VALID\n"); |
72 | return 1; | 72 | return 1; |
73 | } | 73 | } |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index c478a7384186..57a43b8feef5 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -197,21 +197,18 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) | |||
197 | filemap_fdatawait(inode->i_mapping); | 197 | filemap_fdatawait(inode->i_mapping); |
198 | 198 | ||
199 | if (fidnum >= 0) { | 199 | if (fidnum >= 0) { |
200 | fid->fidopen--; | ||
201 | dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, | 200 | dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, |
202 | fid->fid); | 201 | fid->fid); |
203 | 202 | ||
204 | if (fid->fidopen == 0) { | 203 | if (v9fs_t_clunk(v9ses, fidnum, NULL)) |
205 | if (v9fs_t_clunk(v9ses, fidnum, NULL)) | 204 | dprintk(DEBUG_ERROR, "clunk failed\n"); |
206 | dprintk(DEBUG_ERROR, "clunk failed\n"); | ||
207 | 205 | ||
208 | v9fs_put_idpool(fid->fid, &v9ses->fidpool); | 206 | v9fs_put_idpool(fid->fid, &v9ses->fidpool); |
209 | } | ||
210 | 207 | ||
211 | kfree(fid->rdir_fcall); | 208 | kfree(fid->rdir_fcall); |
209 | kfree(fid); | ||
212 | 210 | ||
213 | filp->private_data = NULL; | 211 | filp->private_data = NULL; |
214 | v9fs_fid_destroy(fid); | ||
215 | } | 212 | } |
216 | 213 | ||
217 | d_drop(filp->f_dentry); | 214 | d_drop(filp->f_dentry); |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 1f8ae7d580ab..a4799e971d1c 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -53,30 +53,36 @@ | |||
53 | int v9fs_file_open(struct inode *inode, struct file *file) | 53 | int v9fs_file_open(struct inode *inode, struct file *file) |
54 | { | 54 | { |
55 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 55 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
56 | struct v9fs_fid *v9fid = v9fs_fid_lookup(file->f_dentry, FID_WALK); | 56 | struct v9fs_fid *v9fid, *fid; |
57 | struct v9fs_fid *v9newfid = NULL; | ||
58 | struct v9fs_fcall *fcall = NULL; | 57 | struct v9fs_fcall *fcall = NULL; |
59 | int open_mode = 0; | 58 | int open_mode = 0; |
60 | unsigned int iounit = 0; | 59 | unsigned int iounit = 0; |
61 | int newfid = -1; | 60 | int newfid = -1; |
62 | long result = -1; | 61 | long result = -1; |
63 | 62 | ||
64 | dprintk(DEBUG_VFS, "inode: %p file: %p v9fid= %p\n", inode, file, | 63 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); |
65 | v9fid); | 64 | |
65 | v9fid = v9fs_fid_get_created(file->f_dentry); | ||
66 | if (!v9fid) | ||
67 | v9fid = v9fs_fid_lookup(file->f_dentry); | ||
66 | 68 | ||
67 | if (!v9fid) { | 69 | if (!v9fid) { |
68 | struct dentry *dentry = file->f_dentry; | ||
69 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); | 70 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); |
71 | return -EBADF; | ||
72 | } | ||
70 | 73 | ||
71 | /* XXX - some duplication from lookup, generalize later */ | 74 | if (!v9fid->fidcreate) { |
72 | /* basically vfs_lookup is too heavy weight */ | 75 | fid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); |
73 | v9fid = v9fs_fid_lookup(file->f_dentry, FID_OP); | 76 | if (fid == NULL) { |
74 | if (!v9fid) | 77 | dprintk(DEBUG_ERROR, "Out of Memory\n"); |
75 | return -EBADF; | 78 | return -ENOMEM; |
79 | } | ||
76 | 80 | ||
77 | v9fid = v9fs_fid_lookup(dentry->d_parent, FID_WALK); | 81 | fid->fidopen = 0; |
78 | if (!v9fid) | 82 | fid->fidcreate = 0; |
79 | return -EBADF; | 83 | fid->fidclunked = 0; |
84 | fid->iounit = 0; | ||
85 | fid->v9ses = v9ses; | ||
80 | 86 | ||
81 | newfid = v9fs_get_idpool(&v9ses->fidpool); | 87 | newfid = v9fs_get_idpool(&v9ses->fidpool); |
82 | if (newfid < 0) { | 88 | if (newfid < 0) { |
@@ -85,58 +91,16 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
85 | } | 91 | } |
86 | 92 | ||
87 | result = | 93 | result = |
88 | v9fs_t_walk(v9ses, v9fid->fid, newfid, | 94 | v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, NULL); |
89 | (char *)file->f_dentry->d_name.name, NULL); | 95 | |
90 | if (result < 0) { | 96 | if (result < 0) { |
91 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 97 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
92 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); | 98 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); |
93 | return -EBADF; | 99 | return -EBADF; |
94 | } | 100 | } |
95 | 101 | ||
96 | v9fid = v9fs_fid_create(dentry); | 102 | fid->fid = newfid; |
97 | if (v9fid == NULL) { | 103 | v9fid = fid; |
98 | dprintk(DEBUG_ERROR, "couldn't insert\n"); | ||
99 | return -ENOMEM; | ||
100 | } | ||
101 | v9fid->fid = newfid; | ||
102 | } | ||
103 | |||
104 | if (v9fid->fidcreate) { | ||
105 | /* create case */ | ||
106 | newfid = v9fid->fid; | ||
107 | iounit = v9fid->iounit; | ||
108 | v9fid->fidcreate = 0; | ||
109 | } else { | ||
110 | if (!S_ISDIR(inode->i_mode)) | ||
111 | newfid = v9fid->fid; | ||
112 | else { | ||
113 | newfid = v9fs_get_idpool(&v9ses->fidpool); | ||
114 | if (newfid < 0) { | ||
115 | eprintk(KERN_WARNING, "allocation failed\n"); | ||
116 | return -ENOSPC; | ||
117 | } | ||
118 | /* This would be a somewhat critical clone */ | ||
119 | result = | ||
120 | v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, | ||
121 | &fcall); | ||
122 | if (result < 0) { | ||
123 | dprintk(DEBUG_ERROR, "clone error: %s\n", | ||
124 | FCALL_ERROR(fcall)); | ||
125 | kfree(fcall); | ||
126 | return result; | ||
127 | } | ||
128 | |||
129 | v9newfid = v9fs_fid_create(file->f_dentry); | ||
130 | v9newfid->fid = newfid; | ||
131 | v9newfid->qid = v9fid->qid; | ||
132 | v9newfid->iounit = v9fid->iounit; | ||
133 | v9newfid->fidopen = 0; | ||
134 | v9newfid->fidclunked = 0; | ||
135 | v9newfid->v9ses = v9ses; | ||
136 | v9fid = v9newfid; | ||
137 | kfree(fcall); | ||
138 | } | ||
139 | |||
140 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ | 104 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ |
141 | /* translate open mode appropriately */ | 105 | /* translate open mode appropriately */ |
142 | open_mode = file->f_flags & 0x3; | 106 | open_mode = file->f_flags & 0x3; |
@@ -163,9 +127,13 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
163 | 127 | ||
164 | iounit = fcall->params.ropen.iounit; | 128 | iounit = fcall->params.ropen.iounit; |
165 | kfree(fcall); | 129 | kfree(fcall); |
130 | } else { | ||
131 | /* create case */ | ||
132 | newfid = v9fid->fid; | ||
133 | iounit = v9fid->iounit; | ||
134 | v9fid->fidcreate = 0; | ||
166 | } | 135 | } |
167 | 136 | ||
168 | |||
169 | file->private_data = v9fid; | 137 | file->private_data = v9fid; |
170 | 138 | ||
171 | v9fid->rdir_pos = 0; | 139 | v9fid->rdir_pos = 0; |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index b16322db5ce6..2b696ae6655a 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -307,7 +307,7 @@ v9fs_create(struct inode *dir, | |||
307 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 307 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); |
308 | struct super_block *sb = dir->i_sb; | 308 | struct super_block *sb = dir->i_sb; |
309 | struct v9fs_fid *dirfid = | 309 | struct v9fs_fid *dirfid = |
310 | v9fs_fid_lookup(file_dentry->d_parent, FID_WALK); | 310 | v9fs_fid_lookup(file_dentry->d_parent); |
311 | struct v9fs_fid *fid = NULL; | 311 | struct v9fs_fid *fid = NULL; |
312 | struct inode *file_inode = NULL; | 312 | struct inode *file_inode = NULL; |
313 | struct v9fs_fcall *fcall = NULL; | 313 | struct v9fs_fcall *fcall = NULL; |
@@ -317,6 +317,7 @@ v9fs_create(struct inode *dir, | |||
317 | long newfid = -1; | 317 | long newfid = -1; |
318 | int result = 0; | 318 | int result = 0; |
319 | unsigned int iounit = 0; | 319 | unsigned int iounit = 0; |
320 | int wfidno = -1; | ||
320 | 321 | ||
321 | perm = unixmode2p9mode(v9ses, perm); | 322 | perm = unixmode2p9mode(v9ses, perm); |
322 | 323 | ||
@@ -350,7 +351,7 @@ v9fs_create(struct inode *dir, | |||
350 | if (result < 0) { | 351 | if (result < 0) { |
351 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); | 352 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); |
352 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 353 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
353 | newfid = 0; | 354 | newfid = -1; |
354 | goto CleanUpFid; | 355 | goto CleanUpFid; |
355 | } | 356 | } |
356 | 357 | ||
@@ -369,20 +370,39 @@ v9fs_create(struct inode *dir, | |||
369 | qid = fcall->params.rcreate.qid; | 370 | qid = fcall->params.rcreate.qid; |
370 | kfree(fcall); | 371 | kfree(fcall); |
371 | 372 | ||
372 | fid = v9fs_fid_create(file_dentry); | 373 | fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); |
374 | dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); | ||
373 | if (!fid) { | 375 | if (!fid) { |
374 | result = -ENOMEM; | 376 | result = -ENOMEM; |
375 | goto CleanUpFid; | 377 | goto CleanUpFid; |
376 | } | 378 | } |
377 | 379 | ||
378 | fid->fid = newfid; | ||
379 | fid->fidopen = 0; | ||
380 | fid->fidcreate = 1; | ||
381 | fid->qid = qid; | 380 | fid->qid = qid; |
382 | fid->iounit = iounit; | 381 | fid->iounit = iounit; |
383 | fid->rdir_pos = 0; | 382 | |
384 | fid->rdir_fcall = NULL; | 383 | /* walk to the newly created file and put the fid in the dentry */ |
385 | fid->v9ses = v9ses; | 384 | wfidno = v9fs_get_idpool(&v9ses->fidpool); |
385 | if (newfid < 0) { | ||
386 | eprintk(KERN_WARNING, "no free fids available\n"); | ||
387 | return -ENOSPC; | ||
388 | } | ||
389 | |||
390 | result = v9fs_t_walk(v9ses, dirfidnum, wfidno, | ||
391 | (char *) file_dentry->d_name.name, NULL); | ||
392 | if (result < 0) { | ||
393 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); | ||
394 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
395 | wfidno = -1; | ||
396 | goto CleanUpFid; | ||
397 | } | ||
398 | |||
399 | if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { | ||
400 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) { | ||
401 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
402 | } | ||
403 | |||
404 | goto CleanUpFid; | ||
405 | } | ||
386 | 406 | ||
387 | if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || | 407 | if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || |
388 | (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || | 408 | (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || |
@@ -410,11 +430,11 @@ v9fs_create(struct inode *dir, | |||
410 | d_instantiate(file_dentry, file_inode); | 430 | d_instantiate(file_dentry, file_inode); |
411 | 431 | ||
412 | if (perm & V9FS_DMDIR) { | 432 | if (perm & V9FS_DMDIR) { |
413 | if (v9fs_t_clunk(v9ses, newfid, &fcall)) | 433 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) |
434 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
435 | else | ||
414 | dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n", | 436 | dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n", |
415 | FCALL_ERROR(fcall)); | 437 | FCALL_ERROR(fcall)); |
416 | |||
417 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
418 | kfree(fcall); | 438 | kfree(fcall); |
419 | fid->fidopen = 0; | 439 | fid->fidopen = 0; |
420 | fid->fidcreate = 0; | 440 | fid->fidcreate = 0; |
@@ -426,12 +446,22 @@ v9fs_create(struct inode *dir, | |||
426 | CleanUpFid: | 446 | CleanUpFid: |
427 | kfree(fcall); | 447 | kfree(fcall); |
428 | 448 | ||
429 | if (newfid) { | 449 | if (newfid >= 0) { |
430 | if (v9fs_t_clunk(v9ses, newfid, &fcall)) | 450 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) |
451 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
452 | else | ||
453 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", | ||
454 | FCALL_ERROR(fcall)); | ||
455 | |||
456 | kfree(fcall); | ||
457 | } | ||
458 | if (wfidno >= 0) { | ||
459 | if (!v9fs_t_clunk(v9ses, wfidno, &fcall)) | ||
460 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
461 | else | ||
431 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", | 462 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", |
432 | FCALL_ERROR(fcall)); | 463 | FCALL_ERROR(fcall)); |
433 | 464 | ||
434 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
435 | kfree(fcall); | 465 | kfree(fcall); |
436 | } | 466 | } |
437 | return result; | 467 | return result; |
@@ -461,7 +491,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
461 | file_inode = file->d_inode; | 491 | file_inode = file->d_inode; |
462 | sb = file_inode->i_sb; | 492 | sb = file_inode->i_sb; |
463 | v9ses = v9fs_inode2v9ses(file_inode); | 493 | v9ses = v9fs_inode2v9ses(file_inode); |
464 | v9fid = v9fs_fid_lookup(file, FID_OP); | 494 | v9fid = v9fs_fid_lookup(file); |
465 | 495 | ||
466 | if (!v9fid) { | 496 | if (!v9fid) { |
467 | dprintk(DEBUG_ERROR, | 497 | dprintk(DEBUG_ERROR, |
@@ -545,7 +575,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
545 | 575 | ||
546 | sb = dir->i_sb; | 576 | sb = dir->i_sb; |
547 | v9ses = v9fs_inode2v9ses(dir); | 577 | v9ses = v9fs_inode2v9ses(dir); |
548 | dirfid = v9fs_fid_lookup(dentry->d_parent, FID_WALK); | 578 | dirfid = v9fs_fid_lookup(dentry->d_parent); |
549 | 579 | ||
550 | if (!dirfid) { | 580 | if (!dirfid) { |
551 | dprintk(DEBUG_ERROR, "no dirfid\n"); | 581 | dprintk(DEBUG_ERROR, "no dirfid\n"); |
@@ -573,7 +603,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
573 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 603 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
574 | if (result == -ENOENT) { | 604 | if (result == -ENOENT) { |
575 | d_add(dentry, NULL); | 605 | d_add(dentry, NULL); |
576 | dprintk(DEBUG_ERROR, | 606 | dprintk(DEBUG_VFS, |
577 | "Return negative dentry %p count %d\n", | 607 | "Return negative dentry %p count %d\n", |
578 | dentry, atomic_read(&dentry->d_count)); | 608 | dentry, atomic_read(&dentry->d_count)); |
579 | return NULL; | 609 | return NULL; |
@@ -601,16 +631,13 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
601 | 631 | ||
602 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); | 632 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); |
603 | 633 | ||
604 | fid = v9fs_fid_create(dentry); | 634 | fid = v9fs_fid_create(dentry, v9ses, newfid, 0); |
605 | if (fid == NULL) { | 635 | if (fid == NULL) { |
606 | dprintk(DEBUG_ERROR, "couldn't insert\n"); | 636 | dprintk(DEBUG_ERROR, "couldn't insert\n"); |
607 | result = -ENOMEM; | 637 | result = -ENOMEM; |
608 | goto FreeFcall; | 638 | goto FreeFcall; |
609 | } | 639 | } |
610 | 640 | ||
611 | fid->fid = newfid; | ||
612 | fid->fidopen = 0; | ||
613 | fid->v9ses = v9ses; | ||
614 | fid->qid = fcall->params.rstat.stat->qid; | 641 | fid->qid = fcall->params.rstat.stat->qid; |
615 | 642 | ||
616 | dentry->d_op = &v9fs_dentry_operations; | 643 | dentry->d_op = &v9fs_dentry_operations; |
@@ -665,11 +692,11 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
665 | { | 692 | { |
666 | struct inode *old_inode = old_dentry->d_inode; | 693 | struct inode *old_inode = old_dentry->d_inode; |
667 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); | 694 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); |
668 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_WALK); | 695 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); |
669 | struct v9fs_fid *olddirfid = | 696 | struct v9fs_fid *olddirfid = |
670 | v9fs_fid_lookup(old_dentry->d_parent, FID_WALK); | 697 | v9fs_fid_lookup(old_dentry->d_parent); |
671 | struct v9fs_fid *newdirfid = | 698 | struct v9fs_fid *newdirfid = |
672 | v9fs_fid_lookup(new_dentry->d_parent, FID_WALK); | 699 | v9fs_fid_lookup(new_dentry->d_parent); |
673 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 700 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
674 | struct v9fs_fcall *fcall = NULL; | 701 | struct v9fs_fcall *fcall = NULL; |
675 | int fid = -1; | 702 | int fid = -1; |
@@ -744,7 +771,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
744 | { | 771 | { |
745 | struct v9fs_fcall *fcall = NULL; | 772 | struct v9fs_fcall *fcall = NULL; |
746 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 773 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
747 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 774 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
748 | int err = -EPERM; | 775 | int err = -EPERM; |
749 | 776 | ||
750 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); | 777 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); |
@@ -778,7 +805,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
778 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | 805 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) |
779 | { | 806 | { |
780 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 807 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
781 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 808 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
782 | struct v9fs_fcall *fcall = NULL; | 809 | struct v9fs_fcall *fcall = NULL; |
783 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 810 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
784 | int res = -EPERM; | 811 | int res = -EPERM; |
@@ -960,7 +987,7 @@ v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
960 | if (retval != 0) | 987 | if (retval != 0) |
961 | goto FreeFcall; | 988 | goto FreeFcall; |
962 | 989 | ||
963 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 990 | newfid = v9fs_fid_lookup(dentry); |
964 | 991 | ||
965 | /* issue a twstat */ | 992 | /* issue a twstat */ |
966 | v9fs_blank_mistat(v9ses, mistat); | 993 | v9fs_blank_mistat(v9ses, mistat); |
@@ -1004,7 +1031,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
1004 | 1031 | ||
1005 | struct v9fs_fcall *fcall = NULL; | 1032 | struct v9fs_fcall *fcall = NULL; |
1006 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 1033 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
1007 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 1034 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
1008 | 1035 | ||
1009 | if (!fid) { | 1036 | if (!fid) { |
1010 | dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); | 1037 | dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); |
@@ -1148,7 +1175,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
1148 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 1175 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); |
1149 | struct v9fs_fcall *fcall = NULL; | 1176 | struct v9fs_fcall *fcall = NULL; |
1150 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 1177 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
1151 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_OP); | 1178 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); |
1152 | struct v9fs_fid *newfid = NULL; | 1179 | struct v9fs_fid *newfid = NULL; |
1153 | char *symname = __getname(); | 1180 | char *symname = __getname(); |
1154 | 1181 | ||
@@ -1168,7 +1195,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
1168 | if (retval != 0) | 1195 | if (retval != 0) |
1169 | goto FreeMem; | 1196 | goto FreeMem; |
1170 | 1197 | ||
1171 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 1198 | newfid = v9fs_fid_lookup(dentry); |
1172 | if (!newfid) { | 1199 | if (!newfid) { |
1173 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); | 1200 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); |
1174 | goto FreeMem; | 1201 | goto FreeMem; |
@@ -1246,7 +1273,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1246 | if (retval != 0) | 1273 | if (retval != 0) |
1247 | goto FreeMem; | 1274 | goto FreeMem; |
1248 | 1275 | ||
1249 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 1276 | newfid = v9fs_fid_lookup(dentry); |
1250 | if (!newfid) { | 1277 | if (!newfid) { |
1251 | dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n"); | 1278 | dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n"); |
1252 | retval = -EINVAL; | 1279 | retval = -EINVAL; |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 1e2b2b54d300..0957f4da91d4 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -129,8 +129,7 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
129 | 129 | ||
130 | if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { | 130 | if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { |
131 | dprintk(DEBUG_ERROR, "problem initiating session\n"); | 131 | dprintk(DEBUG_ERROR, "problem initiating session\n"); |
132 | kfree(v9ses); | 132 | return newfid; |
133 | return ERR_PTR(newfid); | ||
134 | } | 133 | } |
135 | 134 | ||
136 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); | 135 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); |
@@ -155,23 +154,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
155 | 154 | ||
156 | sb->s_root = root; | 155 | sb->s_root = root; |
157 | 156 | ||
158 | /* Setup the Root Inode */ | ||
159 | root_fid = v9fs_fid_create(root); | ||
160 | if (root_fid == NULL) { | ||
161 | retval = -ENOMEM; | ||
162 | goto put_back_sb; | ||
163 | } | ||
164 | |||
165 | root_fid->fidopen = 0; | ||
166 | root_fid->v9ses = v9ses; | ||
167 | |||
168 | stat_result = v9fs_t_stat(v9ses, newfid, &fcall); | 157 | stat_result = v9fs_t_stat(v9ses, newfid, &fcall); |
169 | if (stat_result < 0) { | 158 | if (stat_result < 0) { |
170 | dprintk(DEBUG_ERROR, "stat error\n"); | 159 | dprintk(DEBUG_ERROR, "stat error\n"); |
171 | v9fs_t_clunk(v9ses, newfid, NULL); | 160 | v9fs_t_clunk(v9ses, newfid, NULL); |
172 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 161 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
173 | } else { | 162 | } else { |
174 | root_fid->fid = newfid; | 163 | /* Setup the Root Inode */ |
164 | root_fid = v9fs_fid_create(root, v9ses, newfid, 0); | ||
165 | if (root_fid == NULL) { | ||
166 | retval = -ENOMEM; | ||
167 | goto put_back_sb; | ||
168 | } | ||
169 | |||
175 | root_fid->qid = fcall->params.rstat.stat->qid; | 170 | root_fid->qid = fcall->params.rstat.stat->qid; |
176 | root->d_inode->i_ino = | 171 | root->d_inode->i_ino = |
177 | v9fs_qid2ino(&fcall->params.rstat.stat->qid); | 172 | v9fs_qid2ino(&fcall->params.rstat.stat->qid); |