diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-03-14 18:05:45 -0500 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-03-14 18:05:45 -0500 |
commit | c5111f504d2a9b0d258d7c4752b4093523315989 (patch) | |
tree | 6a52864aff79691689aea21cb0cb928327d5de5b /fs/9p | |
parent | 69eb66d7da7dba2696281981347698e1693c2340 (diff) | |
parent | a488edc914aa1d766a4e2c982b5ae03d5657ec1b (diff) |
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'fs/9p')
-rw-r--r-- | fs/9p/9p.c | 1 | ||||
-rw-r--r-- | fs/9p/conv.c | 28 | ||||
-rw-r--r-- | fs/9p/fid.c | 145 | ||||
-rw-r--r-- | fs/9p/fid.h | 6 | ||||
-rw-r--r-- | fs/9p/mux.c | 15 | ||||
-rw-r--r-- | fs/9p/trans_fd.c | 1 | ||||
-rw-r--r-- | fs/9p/v9fs.c | 3 | ||||
-rw-r--r-- | fs/9p/v9fs_vfs.h | 1 | ||||
-rw-r--r-- | fs/9p/vfs_dentry.c | 45 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 106 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 470 | ||||
-rw-r--r-- | fs/9p/vfs_super.c | 10 |
12 files changed, 410 insertions, 421 deletions
diff --git a/fs/9p/9p.c b/fs/9p/9p.c index 1a6d08761f39..f86a28d1d6a6 100644 --- a/fs/9p/9p.c +++ b/fs/9p/9p.c | |||
@@ -111,7 +111,6 @@ static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc, | |||
111 | if (!rc) | 111 | if (!rc) |
112 | return; | 112 | return; |
113 | 113 | ||
114 | dprintk(DEBUG_9P, "tcall id %d rcall id %d\n", tc->id, rc->id); | ||
115 | v9ses = a; | 114 | v9ses = a; |
116 | if (rc->id == RCLUNK) | 115 | if (rc->id == RCLUNK) |
117 | v9fs_put_idpool(fid, &v9ses->fidpool); | 116 | v9fs_put_idpool(fid, &v9ses->fidpool); |
diff --git a/fs/9p/conv.c b/fs/9p/conv.c index 32a9f99154e2..bf1f10067960 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c | |||
@@ -116,13 +116,19 @@ static void buf_put_int64(struct cbuf *buf, u64 val) | |||
116 | } | 116 | } |
117 | } | 117 | } |
118 | 118 | ||
119 | static void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) | 119 | static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) |
120 | { | 120 | { |
121 | char *ret; | ||
122 | |||
123 | ret = NULL; | ||
121 | if (buf_check_size(buf, slen + 2)) { | 124 | if (buf_check_size(buf, slen + 2)) { |
122 | buf_put_int16(buf, slen); | 125 | buf_put_int16(buf, slen); |
126 | ret = buf->p; | ||
123 | memcpy(buf->p, s, slen); | 127 | memcpy(buf->p, s, slen); |
124 | buf->p += slen; | 128 | buf->p += slen; |
125 | } | 129 | } |
130 | |||
131 | return ret; | ||
126 | } | 132 | } |
127 | 133 | ||
128 | static inline void buf_put_string(struct cbuf *buf, const char *s) | 134 | static inline void buf_put_string(struct cbuf *buf, const char *s) |
@@ -430,15 +436,19 @@ static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p) | |||
430 | static void | 436 | static void |
431 | v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) | 437 | v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) |
432 | { | 438 | { |
433 | if (data) { | 439 | int len; |
434 | str->len = strlen(data); | 440 | char *s; |
435 | str->str = bufp->p; | 441 | |
436 | } else { | 442 | if (data) |
437 | str->len = 0; | 443 | len = strlen(data); |
438 | str->str = NULL; | 444 | else |
439 | } | 445 | len = 0; |
440 | 446 | ||
441 | buf_put_stringn(bufp, data, str->len); | 447 | s = buf_put_stringn(bufp, data, len); |
448 | if (str) { | ||
449 | str->len = len; | ||
450 | str->str = s; | ||
451 | } | ||
442 | } | 452 | } |
443 | 453 | ||
444 | static int | 454 | static int |
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index eda449778fa5..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 |
@@ -40,7 +40,7 @@ | |||
40 | * | 40 | * |
41 | */ | 41 | */ |
42 | 42 | ||
43 | static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) | 43 | int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) |
44 | { | 44 | { |
45 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; | 45 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; |
46 | dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid, | 46 | dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid, |
@@ -57,7 +57,6 @@ static 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 | } |
@@ -68,14 +67,11 @@ static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) | |||
68 | * | 67 | * |
69 | */ | 68 | */ |
70 | 69 | ||
71 | struct v9fs_fid *v9fs_fid_create(struct dentry *dentry, | 70 | struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid) |
72 | struct v9fs_session_info *v9ses, int fid, int create) | ||
73 | { | 71 | { |
74 | struct v9fs_fid *new; | 72 | struct v9fs_fid *new; |
75 | 73 | ||
76 | dprintk(DEBUG_9P, "fid create dentry %p, fid %d, create %d\n", | 74 | dprintk(DEBUG_9P, "fid create fid %d\n", fid); |
77 | dentry, fid, create); | ||
78 | |||
79 | new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | 75 | new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); |
80 | if (new == NULL) { | 76 | if (new == NULL) { |
81 | dprintk(DEBUG_ERROR, "Out of Memory\n"); | 77 | dprintk(DEBUG_ERROR, "Out of Memory\n"); |
@@ -85,19 +81,13 @@ struct v9fs_fid *v9fs_fid_create(struct dentry *dentry, | |||
85 | new->fid = fid; | 81 | new->fid = fid; |
86 | new->v9ses = v9ses; | 82 | new->v9ses = v9ses; |
87 | new->fidopen = 0; | 83 | new->fidopen = 0; |
88 | new->fidcreate = create; | ||
89 | new->fidclunked = 0; | 84 | new->fidclunked = 0; |
90 | new->iounit = 0; | 85 | new->iounit = 0; |
91 | new->rdir_pos = 0; | 86 | new->rdir_pos = 0; |
92 | new->rdir_fcall = NULL; | 87 | new->rdir_fcall = NULL; |
88 | INIT_LIST_HEAD(&new->list); | ||
93 | 89 | ||
94 | if (v9fs_fid_insert(new, dentry) == 0) | 90 | return new; |
95 | return new; | ||
96 | else { | ||
97 | dprintk(DEBUG_ERROR, "Problems inserting to dentry\n"); | ||
98 | kfree(new); | ||
99 | return NULL; | ||
100 | } | ||
101 | } | 91 | } |
102 | 92 | ||
103 | /** | 93 | /** |
@@ -113,140 +103,29 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) | |||
113 | } | 103 | } |
114 | 104 | ||
115 | /** | 105 | /** |
116 | * v9fs_fid_walk_up - walks from the process current directory | ||
117 | * up to the specified dentry. | ||
118 | */ | ||
119 | static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry) | ||
120 | { | ||
121 | int fidnum, cfidnum, err; | ||
122 | struct v9fs_fid *cfid; | ||
123 | struct dentry *cde; | ||
124 | struct v9fs_session_info *v9ses; | ||
125 | |||
126 | v9ses = v9fs_inode2v9ses(current->fs->pwd->d_inode); | ||
127 | cfid = v9fs_fid_lookup(current->fs->pwd); | ||
128 | if (cfid == NULL) { | ||
129 | dprintk(DEBUG_ERROR, "process cwd doesn't have a fid\n"); | ||
130 | return ERR_PTR(-ENOENT); | ||
131 | } | ||
132 | |||
133 | cfidnum = cfid->fid; | ||
134 | cde = current->fs->pwd; | ||
135 | /* TODO: take advantage of multiwalk */ | ||
136 | |||
137 | fidnum = v9fs_get_idpool(&v9ses->fidpool); | ||
138 | if (fidnum < 0) { | ||
139 | dprintk(DEBUG_ERROR, "could not get a new fid num\n"); | ||
140 | err = -ENOENT; | ||
141 | goto clunk_fid; | ||
142 | } | ||
143 | |||
144 | while (cde != dentry) { | ||
145 | if (cde == cde->d_parent) { | ||
146 | dprintk(DEBUG_ERROR, "can't find dentry\n"); | ||
147 | err = -ENOENT; | ||
148 | goto clunk_fid; | ||
149 | } | ||
150 | |||
151 | err = v9fs_t_walk(v9ses, cfidnum, fidnum, "..", NULL); | ||
152 | if (err < 0) { | ||
153 | dprintk(DEBUG_ERROR, "problem walking to parent\n"); | ||
154 | goto clunk_fid; | ||
155 | } | ||
156 | |||
157 | cfidnum = fidnum; | ||
158 | cde = cde->d_parent; | ||
159 | } | ||
160 | |||
161 | return v9fs_fid_create(dentry, v9ses, fidnum, 0); | ||
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 | ||
179 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) | 116 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) |
180 | { | 117 | { |
181 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; | 118 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; |
182 | struct v9fs_fid *current_fid = NULL; | ||
183 | struct v9fs_fid *temp = NULL; | ||
184 | struct v9fs_fid *return_fid = NULL; | 119 | struct v9fs_fid *return_fid = NULL; |
185 | 120 | ||
186 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); | 121 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
187 | 122 | ||
188 | if (fid_list) { | 123 | if (fid_list) |
189 | list_for_each_entry_safe(current_fid, temp, fid_list, list) { | 124 | return_fid = list_entry(fid_list->next, struct v9fs_fid, list); |
190 | if (!current_fid->fidcreate) { | ||
191 | return_fid = current_fid; | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | if (!return_fid) | ||
197 | return_fid = current_fid; | ||
198 | } | ||
199 | |||
200 | /* we are at the root but didn't match */ | ||
201 | if ((!return_fid) && (dentry->d_parent == dentry)) { | ||
202 | /* TODO: clone attach with new uid */ | ||
203 | return_fid = current_fid; | ||
204 | } | ||
205 | 125 | ||
206 | if (!return_fid) { | 126 | if (!return_fid) { |
207 | struct dentry *par = current->fs->pwd->d_parent; | 127 | dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n"); |
208 | int count = 1; | ||
209 | while (par != NULL) { | ||
210 | if (par == dentry) | ||
211 | break; | ||
212 | count++; | ||
213 | if (par == par->d_parent) { | ||
214 | dprintk(DEBUG_ERROR, | ||
215 | "got to root without finding dentry\n"); | ||
216 | break; | ||
217 | } | ||
218 | par = par->d_parent; | ||
219 | } | ||
220 | |||
221 | /* XXX - there may be some duplication we can get rid of */ | ||
222 | if (par == dentry) { | ||
223 | return_fid = v9fs_fid_walk_up(dentry); | ||
224 | if (IS_ERR(return_fid)) | ||
225 | return_fid = NULL; | ||
226 | } | ||
227 | } | 128 | } |
228 | 129 | ||
229 | return return_fid; | 130 | return return_fid; |
230 | } | 131 | } |
231 | |||
232 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *dentry) | ||
233 | { | ||
234 | struct list_head *fid_list; | ||
235 | struct v9fs_fid *fid, *ftmp, *ret; | ||
236 | |||
237 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); | ||
238 | fid_list = (struct list_head *)dentry->d_fsdata; | ||
239 | ret = NULL; | ||
240 | if (fid_list) { | ||
241 | list_for_each_entry_safe(fid, ftmp, fid_list, list) { | ||
242 | if (fid->fidcreate && fid->pid == current->pid) { | ||
243 | list_del(&fid->list); | ||
244 | ret = fid; | ||
245 | break; | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | |||
250 | dprintk(DEBUG_9P, "return %p\n", ret); | ||
251 | return ret; | ||
252 | } | ||
diff --git a/fs/9p/fid.h b/fs/9p/fid.h index 84c673a44c83..1fc2dd08d75a 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h | |||
@@ -33,7 +33,6 @@ struct v9fs_fid { | |||
33 | 33 | ||
34 | u32 fid; | 34 | u32 fid; |
35 | unsigned char fidopen; /* set when fid is opened */ | 35 | unsigned char fidopen; /* set when fid is opened */ |
36 | unsigned char fidcreate; /* set when fid was just created */ | ||
37 | unsigned char fidclunked; /* set when fid has already been clunked */ | 36 | unsigned char fidclunked; /* set when fid has already been clunked */ |
38 | 37 | ||
39 | struct v9fs_qid qid; | 38 | struct v9fs_qid qid; |
@@ -45,7 +44,6 @@ struct v9fs_fid { | |||
45 | struct v9fs_fcall *rdir_fcall; | 44 | struct v9fs_fcall *rdir_fcall; |
46 | 45 | ||
47 | /* management stuff */ | 46 | /* management stuff */ |
48 | pid_t pid; /* thread associated with this fid */ | ||
49 | uid_t uid; /* user associated with this fid */ | 47 | uid_t uid; /* user associated with this fid */ |
50 | 48 | ||
51 | /* private data */ | 49 | /* private data */ |
@@ -56,5 +54,5 @@ struct v9fs_fid { | |||
56 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); | 54 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); |
57 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *); | 55 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *); |
58 | void v9fs_fid_destroy(struct v9fs_fid *fid); | 56 | void v9fs_fid_destroy(struct v9fs_fid *fid); |
59 | struct v9fs_fid *v9fs_fid_create(struct dentry *, | 57 | struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid); |
60 | struct v9fs_session_info *v9ses, int fid, int create); | 58 | int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry); |
diff --git a/fs/9p/mux.c b/fs/9p/mux.c index 945cb368d451..ea1134eb47c8 100644 --- a/fs/9p/mux.c +++ b/fs/9p/mux.c | |||
@@ -471,10 +471,13 @@ static void v9fs_write_work(void *a) | |||
471 | } | 471 | } |
472 | 472 | ||
473 | spin_lock(&m->lock); | 473 | spin_lock(&m->lock); |
474 | req = | 474 | again: |
475 | list_entry(m->unsent_req_list.next, struct v9fs_req, | 475 | req = list_entry(m->unsent_req_list.next, struct v9fs_req, |
476 | req_list); | 476 | req_list); |
477 | list_move_tail(&req->req_list, &m->req_list); | 477 | list_move_tail(&req->req_list, &m->req_list); |
478 | if (req->err == ERREQFLUSH) | ||
479 | goto again; | ||
480 | |||
478 | m->wbuf = req->tcall->sdata; | 481 | m->wbuf = req->tcall->sdata; |
479 | m->wsize = req->tcall->size; | 482 | m->wsize = req->tcall->size; |
480 | m->wpos = 0; | 483 | m->wpos = 0; |
@@ -525,7 +528,7 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) | |||
525 | struct v9fs_str *ename; | 528 | struct v9fs_str *ename; |
526 | 529 | ||
527 | tag = req->tag; | 530 | tag = req->tag; |
528 | if (req->rcall->id == RERROR && !req->err) { | 531 | if (!req->err && req->rcall->id == RERROR) { |
529 | ecode = req->rcall->params.rerror.errno; | 532 | ecode = req->rcall->params.rerror.errno; |
530 | ename = &req->rcall->params.rerror.error; | 533 | ename = &req->rcall->params.rerror.error; |
531 | 534 | ||
@@ -551,7 +554,10 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) | |||
551 | req->err = -EIO; | 554 | req->err = -EIO; |
552 | } | 555 | } |
553 | 556 | ||
554 | if (req->cb && req->err != ERREQFLUSH) { | 557 | if (req->err == ERREQFLUSH) |
558 | return; | ||
559 | |||
560 | if (req->cb) { | ||
555 | dprintk(DEBUG_MUX, "calling callback tcall %p rcall %p\n", | 561 | dprintk(DEBUG_MUX, "calling callback tcall %p rcall %p\n", |
556 | req->tcall, req->rcall); | 562 | req->tcall, req->rcall); |
557 | 563 | ||
@@ -812,6 +818,7 @@ v9fs_mux_rpc_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc, int err) | |||
812 | struct v9fs_mux_rpc *r; | 818 | struct v9fs_mux_rpc *r; |
813 | 819 | ||
814 | if (err == ERREQFLUSH) { | 820 | if (err == ERREQFLUSH) { |
821 | kfree(rc); | ||
815 | dprintk(DEBUG_MUX, "err req flush\n"); | 822 | dprintk(DEBUG_MUX, "err req flush\n"); |
816 | return; | 823 | return; |
817 | } | 824 | } |
diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c index 1a28ef97a3d1..5b2ce21b10fa 100644 --- a/fs/9p/trans_fd.c +++ b/fs/9p/trans_fd.c | |||
@@ -80,6 +80,7 @@ static int v9fs_fd_send(struct v9fs_transport *trans, void *v, int len) | |||
80 | if (!trans || trans->status != Connected || !ts) | 80 | if (!trans || trans->status != Connected || !ts) |
81 | return -EIO; | 81 | return -EIO; |
82 | 82 | ||
83 | oldfs = get_fs(); | ||
83 | set_fs(get_ds()); | 84 | set_fs(get_ds()); |
84 | /* The cast to a user pointer is valid due to the set_fs() */ | 85 | /* The cast to a user pointer is valid due to the set_fs() */ |
85 | ret = vfs_write(ts->out_file, (void __user *)v, len, &ts->out_file->f_pos); | 86 | ret = vfs_write(ts->out_file, (void __user *)v, len, &ts->out_file->f_pos); |
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 5250c428fc1f..61352491ba36 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -66,7 +66,7 @@ static match_table_t tokens = { | |||
66 | {Opt_afid, "afid=%u"}, | 66 | {Opt_afid, "afid=%u"}, |
67 | {Opt_rfdno, "rfdno=%u"}, | 67 | {Opt_rfdno, "rfdno=%u"}, |
68 | {Opt_wfdno, "wfdno=%u"}, | 68 | {Opt_wfdno, "wfdno=%u"}, |
69 | {Opt_debug, "debug=%u"}, | 69 | {Opt_debug, "debug=%x"}, |
70 | {Opt_name, "name=%s"}, | 70 | {Opt_name, "name=%s"}, |
71 | {Opt_remotename, "aname=%s"}, | 71 | {Opt_remotename, "aname=%s"}, |
72 | {Opt_unix, "proto=unix"}, | 72 | {Opt_unix, "proto=unix"}, |
@@ -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/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 69cf2905dc90..a759278acaae 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
@@ -51,3 +51,4 @@ int v9fs_dir_release(struct inode *inode, struct file *filp); | |||
51 | int v9fs_file_open(struct inode *inode, struct file *file); | 51 | int v9fs_file_open(struct inode *inode, struct file *file); |
52 | void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat); | 52 | void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat); |
53 | void v9fs_dentry_release(struct dentry *); | 53 | void v9fs_dentry_release(struct dentry *); |
54 | int v9fs_uflags2omode(int uflags); | ||
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 | }; |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index c7e14d917215..de3a129698da 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -53,94 +53,70 @@ | |||
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, *fid; | 56 | struct v9fs_fid *vfid; |
57 | struct v9fs_fcall *fcall = NULL; | 57 | struct v9fs_fcall *fcall = NULL; |
58 | int open_mode = 0; | 58 | int omode; |
59 | unsigned int iounit = 0; | 59 | int fid = V9FS_NOFID; |
60 | int newfid = -1; | 60 | int err; |
61 | long result = -1; | ||
62 | 61 | ||
63 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); | 62 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); |
64 | 63 | ||
65 | v9fid = v9fs_fid_get_created(file->f_dentry); | 64 | vfid = v9fs_fid_lookup(file->f_dentry); |
66 | if (!v9fid) | 65 | if (!vfid) { |
67 | v9fid = v9fs_fid_lookup(file->f_dentry); | ||
68 | |||
69 | if (!v9fid) { | ||
70 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); | 66 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); |
71 | return -EBADF; | 67 | return -EBADF; |
72 | } | 68 | } |
73 | 69 | ||
74 | if (!v9fid->fidcreate) { | 70 | fid = v9fs_get_idpool(&v9ses->fidpool); |
75 | fid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | 71 | if (fid < 0) { |
76 | if (fid == NULL) { | ||
77 | dprintk(DEBUG_ERROR, "Out of Memory\n"); | ||
78 | return -ENOMEM; | ||
79 | } | ||
80 | |||
81 | fid->fidopen = 0; | ||
82 | fid->fidcreate = 0; | ||
83 | fid->fidclunked = 0; | ||
84 | fid->iounit = 0; | ||
85 | fid->v9ses = v9ses; | ||
86 | |||
87 | newfid = v9fs_get_idpool(&v9ses->fidpool); | ||
88 | if (newfid < 0) { | ||
89 | eprintk(KERN_WARNING, "newfid fails!\n"); | 72 | eprintk(KERN_WARNING, "newfid fails!\n"); |
90 | return -ENOSPC; | 73 | return -ENOSPC; |
91 | } | 74 | } |
92 | 75 | ||
93 | result = | 76 | err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, NULL); |
94 | v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, NULL); | 77 | if (err < 0) { |
95 | |||
96 | if (result < 0) { | ||
97 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
98 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); | 78 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); |
99 | return -EBADF; | 79 | goto put_fid; |
80 | } | ||
81 | |||
82 | vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | ||
83 | if (vfid == NULL) { | ||
84 | dprintk(DEBUG_ERROR, "out of memory\n"); | ||
85 | goto clunk_fid; | ||
100 | } | 86 | } |
101 | 87 | ||
102 | fid->fid = newfid; | ||
103 | v9fid = fid; | ||
104 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ | 88 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ |
105 | /* translate open mode appropriately */ | 89 | /* translate open mode appropriately */ |
106 | open_mode = file->f_flags & 0x3; | 90 | omode = v9fs_uflags2omode(file->f_flags); |
91 | err = v9fs_t_open(v9ses, fid, omode, &fcall); | ||
92 | if (err < 0) { | ||
93 | PRINT_FCALL_ERROR("open failed", fcall); | ||
94 | goto destroy_vfid; | ||
95 | } | ||
107 | 96 | ||
108 | if (file->f_flags & O_EXCL) | 97 | file->private_data = vfid; |
109 | open_mode |= V9FS_OEXCL; | 98 | vfid->fid = fid; |
99 | vfid->fidopen = 1; | ||
100 | vfid->fidclunked = 0; | ||
101 | vfid->iounit = fcall->params.ropen.iounit; | ||
102 | vfid->rdir_pos = 0; | ||
103 | vfid->rdir_fcall = NULL; | ||
104 | vfid->filp = file; | ||
105 | kfree(fcall); | ||
110 | 106 | ||
111 | if (v9ses->extended) { | 107 | return 0; |
112 | if (file->f_flags & O_TRUNC) | ||
113 | open_mode |= V9FS_OTRUNC; | ||
114 | 108 | ||
115 | if (file->f_flags & O_APPEND) | 109 | destroy_vfid: |
116 | open_mode |= V9FS_OAPPEND; | 110 | v9fs_fid_destroy(vfid); |
117 | } | ||
118 | 111 | ||
119 | result = v9fs_t_open(v9ses, newfid, open_mode, &fcall); | 112 | clunk_fid: |
120 | if (result < 0) { | 113 | v9fs_t_clunk(v9ses, fid); |
121 | PRINT_FCALL_ERROR("open failed", fcall); | ||
122 | kfree(fcall); | ||
123 | return result; | ||
124 | } | ||
125 | 114 | ||
126 | iounit = fcall->params.ropen.iounit; | 115 | put_fid: |
116 | v9fs_put_idpool(fid, &v9ses->fidpool); | ||
127 | kfree(fcall); | 117 | kfree(fcall); |
128 | } else { | ||
129 | /* create case */ | ||
130 | newfid = v9fid->fid; | ||
131 | iounit = v9fid->iounit; | ||
132 | v9fid->fidcreate = 0; | ||
133 | } | ||
134 | |||
135 | file->private_data = v9fid; | ||
136 | |||
137 | v9fid->rdir_pos = 0; | ||
138 | v9fid->rdir_fcall = NULL; | ||
139 | v9fid->fidopen = 1; | ||
140 | v9fid->filp = file; | ||
141 | v9fid->iounit = iounit; | ||
142 | 118 | ||
143 | return 0; | 119 | return err; |
144 | } | 120 | } |
145 | 121 | ||
146 | /** | 122 | /** |
@@ -289,9 +265,7 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
289 | total += result; | 265 | total += result; |
290 | } while (count); | 266 | } while (count); |
291 | 267 | ||
292 | if(inode->i_mapping->nrpages) | ||
293 | invalidate_inode_pages2(inode->i_mapping); | 268 | invalidate_inode_pages2(inode->i_mapping); |
294 | |||
295 | return total; | 269 | return total; |
296 | } | 270 | } |
297 | 271 | ||
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 91f552454c76..3ad8455f8577 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -125,6 +125,38 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) | |||
125 | return res; | 125 | return res; |
126 | } | 126 | } |
127 | 127 | ||
128 | int v9fs_uflags2omode(int uflags) | ||
129 | { | ||
130 | int ret; | ||
131 | |||
132 | ret = 0; | ||
133 | switch (uflags&3) { | ||
134 | default: | ||
135 | case O_RDONLY: | ||
136 | ret = V9FS_OREAD; | ||
137 | break; | ||
138 | |||
139 | case O_WRONLY: | ||
140 | ret = V9FS_OWRITE; | ||
141 | break; | ||
142 | |||
143 | case O_RDWR: | ||
144 | ret = V9FS_ORDWR; | ||
145 | break; | ||
146 | } | ||
147 | |||
148 | if (uflags & O_EXCL) | ||
149 | ret |= V9FS_OEXCL; | ||
150 | |||
151 | if (uflags & O_TRUNC) | ||
152 | ret |= V9FS_OTRUNC; | ||
153 | |||
154 | if (uflags & O_APPEND) | ||
155 | ret |= V9FS_OAPPEND; | ||
156 | |||
157 | return ret; | ||
158 | } | ||
159 | |||
128 | /** | 160 | /** |
129 | * v9fs_blank_wstat - helper function to setup a 9P stat structure | 161 | * v9fs_blank_wstat - helper function to setup a 9P stat structure |
130 | * @v9ses: 9P session info (for determining extended mode) | 162 | * @v9ses: 9P session info (for determining extended mode) |
@@ -163,7 +195,7 @@ v9fs_blank_wstat(struct v9fs_wstat *wstat) | |||
163 | 195 | ||
164 | struct inode *v9fs_get_inode(struct super_block *sb, int mode) | 196 | struct inode *v9fs_get_inode(struct super_block *sb, int mode) |
165 | { | 197 | { |
166 | struct inode *inode = NULL; | 198 | struct inode *inode; |
167 | struct v9fs_session_info *v9ses = sb->s_fs_info; | 199 | struct v9fs_session_info *v9ses = sb->s_fs_info; |
168 | 200 | ||
169 | dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); | 201 | dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); |
@@ -222,171 +254,133 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
222 | return inode; | 254 | return inode; |
223 | } | 255 | } |
224 | 256 | ||
225 | /** | ||
226 | * v9fs_create - helper function to create files and directories | ||
227 | * @dir: directory inode file is being created in | ||
228 | * @file_dentry: dentry file is being created in | ||
229 | * @perm: permissions file is being created with | ||
230 | * @open_mode: resulting open mode for file | ||
231 | * | ||
232 | */ | ||
233 | |||
234 | static int | 257 | static int |
235 | v9fs_create(struct inode *dir, | 258 | v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, |
236 | struct dentry *file_dentry, | 259 | u32 perm, u8 mode, u32 *fidp, struct v9fs_qid *qid, u32 *iounit) |
237 | unsigned int perm, unsigned int open_mode) | ||
238 | { | 260 | { |
239 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 261 | u32 fid; |
240 | struct super_block *sb = dir->i_sb; | ||
241 | struct v9fs_fid *dirfid = | ||
242 | v9fs_fid_lookup(file_dentry->d_parent); | ||
243 | struct v9fs_fid *fid = NULL; | ||
244 | struct inode *file_inode = NULL; | ||
245 | struct v9fs_fcall *fcall = NULL; | ||
246 | struct v9fs_qid qid; | ||
247 | int dirfidnum = -1; | ||
248 | long newfid = -1; | ||
249 | int result = 0; | ||
250 | unsigned int iounit = 0; | ||
251 | int wfidno = -1; | ||
252 | int err; | 262 | int err; |
263 | struct v9fs_fcall *fcall; | ||
253 | 264 | ||
254 | perm = unixmode2p9mode(v9ses, perm); | 265 | fid = v9fs_get_idpool(&v9ses->fidpool); |
255 | 266 | if (fid < 0) { | |
256 | dprintk(DEBUG_VFS, "dir: %p dentry: %p perm: %o mode: %o\n", dir, | ||
257 | file_dentry, perm, open_mode); | ||
258 | |||
259 | if (!dirfid) | ||
260 | return -EBADF; | ||
261 | |||
262 | dirfidnum = dirfid->fid; | ||
263 | if (dirfidnum < 0) { | ||
264 | dprintk(DEBUG_ERROR, "No fid for the directory #%lu\n", | ||
265 | dir->i_ino); | ||
266 | return -EBADF; | ||
267 | } | ||
268 | |||
269 | if (file_dentry->d_inode) { | ||
270 | dprintk(DEBUG_ERROR, | ||
271 | "Odd. There is an inode for dir %lu, name :%s:\n", | ||
272 | dir->i_ino, file_dentry->d_name.name); | ||
273 | return -EEXIST; | ||
274 | } | ||
275 | |||
276 | newfid = v9fs_get_idpool(&v9ses->fidpool); | ||
277 | if (newfid < 0) { | ||
278 | eprintk(KERN_WARNING, "no free fids available\n"); | 267 | eprintk(KERN_WARNING, "no free fids available\n"); |
279 | return -ENOSPC; | 268 | return -ENOSPC; |
280 | } | 269 | } |
281 | 270 | ||
282 | result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall); | 271 | err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall); |
283 | if (result < 0) { | 272 | if (err < 0) { |
284 | PRINT_FCALL_ERROR("clone error", fcall); | 273 | PRINT_FCALL_ERROR("clone error", fcall); |
285 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 274 | goto error; |
286 | newfid = -1; | ||
287 | goto CleanUpFid; | ||
288 | } | 275 | } |
289 | |||
290 | kfree(fcall); | 276 | kfree(fcall); |
291 | fcall = NULL; | ||
292 | 277 | ||
293 | result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name, | 278 | err = v9fs_t_create(v9ses, fid, name, perm, mode, &fcall); |
294 | perm, open_mode, &fcall); | 279 | if (err < 0) { |
295 | if (result < 0) { | ||
296 | PRINT_FCALL_ERROR("create fails", fcall); | 280 | PRINT_FCALL_ERROR("create fails", fcall); |
297 | goto CleanUpFid; | 281 | goto error; |
298 | } | 282 | } |
299 | 283 | ||
300 | iounit = fcall->params.rcreate.iounit; | 284 | if (iounit) |
301 | qid = fcall->params.rcreate.qid; | 285 | *iounit = fcall->params.rcreate.iounit; |
286 | |||
287 | if (qid) | ||
288 | *qid = fcall->params.rcreate.qid; | ||
289 | |||
290 | if (fidp) | ||
291 | *fidp = fid; | ||
292 | |||
302 | kfree(fcall); | 293 | kfree(fcall); |
303 | fcall = NULL; | 294 | return 0; |
304 | 295 | ||
305 | if (!(perm&V9FS_DMDIR)) { | 296 | error: |
306 | fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); | 297 | if (fid >= 0) |
307 | dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); | 298 | v9fs_put_idpool(fid, &v9ses->fidpool); |
308 | if (!fid) { | ||
309 | result = -ENOMEM; | ||
310 | goto CleanUpFid; | ||
311 | } | ||
312 | 299 | ||
313 | fid->qid = qid; | 300 | kfree(fcall); |
314 | fid->iounit = iounit; | 301 | return err; |
315 | } else { | 302 | } |
316 | err = v9fs_t_clunk(v9ses, newfid); | 303 | |
317 | newfid = -1; | 304 | static struct v9fs_fid* |
318 | if (err < 0) | 305 | v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) |
319 | dprintk(DEBUG_ERROR, "clunk for mkdir failed: %d\n", err); | 306 | { |
320 | } | 307 | int err; |
308 | u32 nfid; | ||
309 | struct v9fs_fid *ret; | ||
310 | struct v9fs_fcall *fcall; | ||
321 | 311 | ||
322 | /* walk to the newly created file and put the fid in the dentry */ | 312 | nfid = v9fs_get_idpool(&v9ses->fidpool); |
323 | wfidno = v9fs_get_idpool(&v9ses->fidpool); | 313 | if (nfid < 0) { |
324 | if (wfidno < 0) { | ||
325 | eprintk(KERN_WARNING, "no free fids available\n"); | 314 | eprintk(KERN_WARNING, "no free fids available\n"); |
326 | return -ENOSPC; | 315 | return ERR_PTR(-ENOSPC); |
327 | } | 316 | } |
328 | 317 | ||
329 | result = v9fs_t_walk(v9ses, dirfidnum, wfidno, | 318 | err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name, |
330 | (char *) file_dentry->d_name.name, &fcall); | 319 | &fcall); |
331 | if (result < 0) { | 320 | |
332 | PRINT_FCALL_ERROR("clone error", fcall); | 321 | if (err < 0) { |
333 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | 322 | PRINT_FCALL_ERROR("walk error", fcall); |
334 | wfidno = -1; | 323 | v9fs_put_idpool(nfid, &v9ses->fidpool); |
335 | goto CleanUpFid; | 324 | goto error; |
336 | } | 325 | } |
326 | |||
337 | kfree(fcall); | 327 | kfree(fcall); |
338 | fcall = NULL; | 328 | fcall = NULL; |
329 | ret = v9fs_fid_create(v9ses, nfid); | ||
330 | if (!ret) { | ||
331 | err = -ENOMEM; | ||
332 | goto clunk_fid; | ||
333 | } | ||
339 | 334 | ||
340 | if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { | 335 | err = v9fs_fid_insert(ret, dentry); |
341 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | 336 | if (err < 0) { |
342 | 337 | v9fs_fid_destroy(ret); | |
343 | goto CleanUpFid; | 338 | goto clunk_fid; |
344 | } | 339 | } |
345 | 340 | ||
346 | if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || | 341 | return ret; |
347 | (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || | ||
348 | (perm & V9FS_DMDEVICE)) | ||
349 | return 0; | ||
350 | 342 | ||
351 | result = v9fs_t_stat(v9ses, wfidno, &fcall); | 343 | clunk_fid: |
352 | if (result < 0) { | 344 | v9fs_t_clunk(v9ses, nfid); |
353 | PRINT_FCALL_ERROR("stat error", fcall); | ||
354 | goto CleanUpFid; | ||
355 | } | ||
356 | 345 | ||
346 | error: | ||
347 | kfree(fcall); | ||
348 | return ERR_PTR(err); | ||
349 | } | ||
357 | 350 | ||
358 | file_inode = v9fs_get_inode(sb, | 351 | struct inode * |
359 | p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode)); | 352 | v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid, |
353 | struct super_block *sb) | ||
354 | { | ||
355 | int err, umode; | ||
356 | struct inode *ret; | ||
357 | struct v9fs_fcall *fcall; | ||
360 | 358 | ||
361 | if ((!file_inode) || IS_ERR(file_inode)) { | 359 | ret = NULL; |
362 | dprintk(DEBUG_ERROR, "create inode failed\n"); | 360 | err = v9fs_t_stat(v9ses, fid, &fcall); |
363 | result = -EBADF; | 361 | if (err) { |
364 | goto CleanUpFid; | 362 | PRINT_FCALL_ERROR("stat error", fcall); |
363 | goto error; | ||
365 | } | 364 | } |
366 | 365 | ||
367 | v9fs_stat2inode(&fcall->params.rstat.stat, file_inode, sb); | 366 | umode = p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode); |
368 | kfree(fcall); | 367 | ret = v9fs_get_inode(sb, umode); |
369 | fcall = NULL; | 368 | if (IS_ERR(ret)) { |
370 | file_dentry->d_op = &v9fs_dentry_operations; | 369 | err = PTR_ERR(ret); |
371 | d_instantiate(file_dentry, file_inode); | 370 | ret = NULL; |
371 | goto error; | ||
372 | } | ||
372 | 373 | ||
373 | return 0; | 374 | v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb); |
375 | kfree(fcall); | ||
376 | return ret; | ||
374 | 377 | ||
375 | CleanUpFid: | 378 | error: |
376 | kfree(fcall); | 379 | kfree(fcall); |
377 | fcall = NULL; | 380 | if (ret) |
381 | iput(ret); | ||
378 | 382 | ||
379 | if (newfid >= 0) { | 383 | return ERR_PTR(err); |
380 | err = v9fs_t_clunk(v9ses, newfid); | ||
381 | if (err < 0) | ||
382 | dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); | ||
383 | } | ||
384 | if (wfidno >= 0) { | ||
385 | err = v9fs_t_clunk(v9ses, wfidno); | ||
386 | if (err < 0) | ||
387 | dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); | ||
388 | } | ||
389 | return result; | ||
390 | } | 384 | } |
391 | 385 | ||
392 | /** | 386 | /** |
@@ -440,20 +434,97 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
440 | return result; | 434 | return result; |
441 | } | 435 | } |
442 | 436 | ||
437 | static int | ||
438 | v9fs_open_created(struct inode *inode, struct file *file) | ||
439 | { | ||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | /** | 443 | /** |
444 | * v9fs_vfs_create - VFS hook to create files | 444 | * v9fs_vfs_create - VFS hook to create files |
445 | * @inode: directory inode that is being deleted | 445 | * @inode: directory inode that is being deleted |
446 | * @dentry: dentry that is being deleted | 446 | * @dentry: dentry that is being deleted |
447 | * @perm: create permissions | 447 | * @mode: create permissions |
448 | * @nd: path information | 448 | * @nd: path information |
449 | * | 449 | * |
450 | */ | 450 | */ |
451 | 451 | ||
452 | static int | 452 | static int |
453 | v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm, | 453 | v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, |
454 | struct nameidata *nd) | 454 | struct nameidata *nd) |
455 | { | 455 | { |
456 | return v9fs_create(inode, dentry, perm, O_RDWR); | 456 | int err; |
457 | u32 fid, perm, iounit; | ||
458 | int flags; | ||
459 | struct v9fs_session_info *v9ses; | ||
460 | struct v9fs_fid *dfid, *vfid, *ffid; | ||
461 | struct inode *inode; | ||
462 | struct v9fs_qid qid; | ||
463 | struct file *filp; | ||
464 | |||
465 | inode = NULL; | ||
466 | vfid = NULL; | ||
467 | v9ses = v9fs_inode2v9ses(dir); | ||
468 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
469 | perm = unixmode2p9mode(v9ses, mode); | ||
470 | |||
471 | if (nd && nd->flags & LOOKUP_OPEN) | ||
472 | flags = nd->intent.open.flags - 1; | ||
473 | else | ||
474 | flags = O_RDWR; | ||
475 | |||
476 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, | ||
477 | perm, v9fs_uflags2omode(flags), &fid, &qid, &iounit); | ||
478 | |||
479 | if (err) | ||
480 | goto error; | ||
481 | |||
482 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | ||
483 | if (IS_ERR(vfid)) { | ||
484 | err = PTR_ERR(vfid); | ||
485 | vfid = NULL; | ||
486 | goto error; | ||
487 | } | ||
488 | |||
489 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); | ||
490 | if (IS_ERR(inode)) { | ||
491 | err = PTR_ERR(inode); | ||
492 | inode = NULL; | ||
493 | goto error; | ||
494 | } | ||
495 | |||
496 | dentry->d_op = &v9fs_dentry_operations; | ||
497 | d_instantiate(dentry, inode); | ||
498 | |||
499 | if (nd && nd->flags & LOOKUP_OPEN) { | ||
500 | ffid = v9fs_fid_create(v9ses, fid); | ||
501 | if (!ffid) | ||
502 | return -ENOMEM; | ||
503 | |||
504 | filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); | ||
505 | if (IS_ERR(filp)) { | ||
506 | v9fs_fid_destroy(ffid); | ||
507 | return PTR_ERR(filp); | ||
508 | } | ||
509 | |||
510 | ffid->rdir_pos = 0; | ||
511 | ffid->rdir_fcall = NULL; | ||
512 | ffid->fidopen = 1; | ||
513 | ffid->iounit = iounit; | ||
514 | ffid->filp = filp; | ||
515 | filp->private_data = ffid; | ||
516 | } | ||
517 | |||
518 | return 0; | ||
519 | |||
520 | error: | ||
521 | if (vfid) | ||
522 | v9fs_fid_destroy(vfid); | ||
523 | |||
524 | if (inode) | ||
525 | iput(inode); | ||
526 | |||
527 | return err; | ||
457 | } | 528 | } |
458 | 529 | ||
459 | /** | 530 | /** |
@@ -464,9 +535,57 @@ v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm, | |||
464 | * | 535 | * |
465 | */ | 536 | */ |
466 | 537 | ||
467 | static int v9fs_vfs_mkdir(struct inode *inode, struct dentry *dentry, int mode) | 538 | static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
468 | { | 539 | { |
469 | return v9fs_create(inode, dentry, mode | S_IFDIR, O_RDONLY); | 540 | int err; |
541 | u32 fid, perm; | ||
542 | struct v9fs_session_info *v9ses; | ||
543 | struct v9fs_fid *dfid, *vfid; | ||
544 | struct inode *inode; | ||
545 | |||
546 | inode = NULL; | ||
547 | vfid = NULL; | ||
548 | v9ses = v9fs_inode2v9ses(dir); | ||
549 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
550 | perm = unixmode2p9mode(v9ses, mode | S_IFDIR); | ||
551 | |||
552 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, | ||
553 | perm, V9FS_OREAD, &fid, NULL, NULL); | ||
554 | |||
555 | if (err) { | ||
556 | dprintk(DEBUG_ERROR, "create error %d\n", err); | ||
557 | goto error; | ||
558 | } | ||
559 | |||
560 | err = v9fs_t_clunk(v9ses, fid); | ||
561 | if (err) { | ||
562 | dprintk(DEBUG_ERROR, "clunk error %d\n", err); | ||
563 | goto error; | ||
564 | } | ||
565 | |||
566 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | ||
567 | if (IS_ERR(vfid)) { | ||
568 | err = PTR_ERR(vfid); | ||
569 | vfid = NULL; | ||
570 | goto error; | ||
571 | } | ||
572 | |||
573 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); | ||
574 | if (IS_ERR(inode)) { | ||
575 | err = PTR_ERR(inode); | ||
576 | inode = NULL; | ||
577 | goto error; | ||
578 | } | ||
579 | |||
580 | dentry->d_op = &v9fs_dentry_operations; | ||
581 | d_instantiate(dentry, inode); | ||
582 | return 0; | ||
583 | |||
584 | error: | ||
585 | if (vfid) | ||
586 | v9fs_fid_destroy(vfid); | ||
587 | |||
588 | return err; | ||
470 | } | 589 | } |
471 | 590 | ||
472 | /** | 591 | /** |
@@ -491,7 +610,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
491 | int result = 0; | 610 | int result = 0; |
492 | 611 | ||
493 | dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", | 612 | dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", |
494 | dir, dentry->d_iname, dentry, nameidata); | 613 | dir, dentry->d_name.name, dentry, nameidata); |
495 | 614 | ||
496 | sb = dir->i_sb; | 615 | sb = dir->i_sb; |
497 | v9ses = v9fs_inode2v9ses(dir); | 616 | v9ses = v9fs_inode2v9ses(dir); |
@@ -516,9 +635,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
516 | return ERR_PTR(-ENOSPC); | 635 | return ERR_PTR(-ENOSPC); |
517 | } | 636 | } |
518 | 637 | ||
519 | result = | 638 | result = v9fs_t_walk(v9ses, dirfidnum, newfid, |
520 | v9fs_t_walk(v9ses, dirfidnum, newfid, (char *)dentry->d_name.name, | 639 | (char *)dentry->d_name.name, NULL); |
521 | NULL); | ||
522 | if (result < 0) { | 640 | if (result < 0) { |
523 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 641 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
524 | if (result == -ENOENT) { | 642 | if (result == -ENOENT) { |
@@ -551,13 +669,17 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
551 | 669 | ||
552 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); | 670 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); |
553 | 671 | ||
554 | fid = v9fs_fid_create(dentry, v9ses, newfid, 0); | 672 | fid = v9fs_fid_create(v9ses, newfid); |
555 | if (fid == NULL) { | 673 | if (fid == NULL) { |
556 | dprintk(DEBUG_ERROR, "couldn't insert\n"); | 674 | dprintk(DEBUG_ERROR, "couldn't insert\n"); |
557 | result = -ENOMEM; | 675 | result = -ENOMEM; |
558 | goto FreeFcall; | 676 | goto FreeFcall; |
559 | } | 677 | } |
560 | 678 | ||
679 | result = v9fs_fid_insert(fid, dentry); | ||
680 | if (result < 0) | ||
681 | goto FreeFcall; | ||
682 | |||
561 | fid->qid = fcall->params.rstat.stat.qid; | 683 | fid->qid = fcall->params.rstat.stat.qid; |
562 | 684 | ||
563 | dentry->d_op = &v9fs_dentry_operations; | 685 | dentry->d_op = &v9fs_dentry_operations; |
@@ -983,53 +1105,75 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void | |||
983 | static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, | 1105 | static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, |
984 | int mode, const char *extension) | 1106 | int mode, const char *extension) |
985 | { | 1107 | { |
986 | int err, retval; | 1108 | int err; |
1109 | u32 fid, perm; | ||
987 | struct v9fs_session_info *v9ses; | 1110 | struct v9fs_session_info *v9ses; |
1111 | struct v9fs_fid *dfid, *vfid; | ||
1112 | struct inode *inode; | ||
988 | struct v9fs_fcall *fcall; | 1113 | struct v9fs_fcall *fcall; |
989 | struct v9fs_fid *fid; | ||
990 | struct v9fs_wstat wstat; | 1114 | struct v9fs_wstat wstat; |
991 | 1115 | ||
992 | v9ses = v9fs_inode2v9ses(dir); | ||
993 | retval = -EPERM; | ||
994 | fcall = NULL; | 1116 | fcall = NULL; |
1117 | inode = NULL; | ||
1118 | vfid = NULL; | ||
1119 | v9ses = v9fs_inode2v9ses(dir); | ||
1120 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
1121 | perm = unixmode2p9mode(v9ses, mode); | ||
995 | 1122 | ||
996 | if (!v9ses->extended) { | 1123 | if (!v9ses->extended) { |
997 | dprintk(DEBUG_ERROR, "not extended\n"); | 1124 | dprintk(DEBUG_ERROR, "not extended\n"); |
998 | goto free_mem; | 1125 | return -EPERM; |
999 | } | 1126 | } |
1000 | 1127 | ||
1001 | /* issue a create */ | 1128 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, |
1002 | retval = v9fs_create(dir, dentry, mode, 0); | 1129 | perm, V9FS_OREAD, &fid, NULL, NULL); |
1003 | if (retval != 0) | ||
1004 | goto free_mem; | ||
1005 | 1130 | ||
1006 | fid = v9fs_fid_get_created(dentry); | 1131 | if (err) |
1007 | if (!fid) { | 1132 | goto error; |
1008 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); | 1133 | |
1009 | goto free_mem; | 1134 | err = v9fs_t_clunk(v9ses, fid); |
1135 | if (err) | ||
1136 | goto error; | ||
1137 | |||
1138 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | ||
1139 | if (IS_ERR(vfid)) { | ||
1140 | err = PTR_ERR(vfid); | ||
1141 | vfid = NULL; | ||
1142 | goto error; | ||
1143 | } | ||
1144 | |||
1145 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); | ||
1146 | if (IS_ERR(inode)) { | ||
1147 | err = PTR_ERR(inode); | ||
1148 | inode = NULL; | ||
1149 | goto error; | ||
1010 | } | 1150 | } |
1011 | 1151 | ||
1012 | /* issue a Twstat */ | 1152 | /* issue a Twstat */ |
1013 | v9fs_blank_wstat(&wstat); | 1153 | v9fs_blank_wstat(&wstat); |
1014 | wstat.muid = v9ses->name; | 1154 | wstat.muid = v9ses->name; |
1015 | wstat.extension = (char *) extension; | 1155 | wstat.extension = (char *) extension; |
1016 | retval = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall); | 1156 | err = v9fs_t_wstat(v9ses, vfid->fid, &wstat, &fcall); |
1017 | if (retval < 0) { | ||
1018 | PRINT_FCALL_ERROR("wstat error", fcall); | ||
1019 | goto free_mem; | ||
1020 | } | ||
1021 | |||
1022 | err = v9fs_t_clunk(v9ses, fid->fid); | ||
1023 | if (err < 0) { | 1157 | if (err < 0) { |
1024 | dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); | 1158 | PRINT_FCALL_ERROR("wstat error", fcall); |
1025 | goto free_mem; | 1159 | goto error; |
1026 | } | 1160 | } |
1027 | 1161 | ||
1028 | d_drop(dentry); /* FID - will this also clunk? */ | 1162 | kfree(fcall); |
1163 | dentry->d_op = &v9fs_dentry_operations; | ||
1164 | d_instantiate(dentry, inode); | ||
1165 | return 0; | ||
1029 | 1166 | ||
1030 | free_mem: | 1167 | error: |
1031 | kfree(fcall); | 1168 | kfree(fcall); |
1032 | return retval; | 1169 | if (vfid) |
1170 | v9fs_fid_destroy(vfid); | ||
1171 | |||
1172 | if (inode) | ||
1173 | iput(inode); | ||
1174 | |||
1175 | return err; | ||
1176 | |||
1033 | } | 1177 | } |
1034 | 1178 | ||
1035 | /** | 1179 | /** |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 2c4fa75be025..d05318fa684e 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -146,7 +146,6 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
146 | inode->i_gid = gid; | 146 | inode->i_gid = gid; |
147 | 147 | ||
148 | root = d_alloc_root(inode); | 148 | root = d_alloc_root(inode); |
149 | |||
150 | if (!root) { | 149 | if (!root) { |
151 | retval = -ENOMEM; | 150 | retval = -ENOMEM; |
152 | goto put_back_sb; | 151 | goto put_back_sb; |
@@ -158,15 +157,20 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
158 | if (stat_result < 0) { | 157 | if (stat_result < 0) { |
159 | dprintk(DEBUG_ERROR, "stat error\n"); | 158 | dprintk(DEBUG_ERROR, "stat error\n"); |
160 | v9fs_t_clunk(v9ses, newfid); | 159 | v9fs_t_clunk(v9ses, newfid); |
161 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
162 | } else { | 160 | } else { |
163 | /* Setup the Root Inode */ | 161 | /* Setup the Root Inode */ |
164 | root_fid = v9fs_fid_create(root, v9ses, newfid, 0); | 162 | root_fid = v9fs_fid_create(v9ses, newfid); |
165 | if (root_fid == NULL) { | 163 | if (root_fid == NULL) { |
166 | retval = -ENOMEM; | 164 | retval = -ENOMEM; |
167 | goto put_back_sb; | 165 | goto put_back_sb; |
168 | } | 166 | } |
169 | 167 | ||
168 | retval = v9fs_fid_insert(root_fid, root); | ||
169 | if (retval < 0) { | ||
170 | kfree(fcall); | ||
171 | goto put_back_sb; | ||
172 | } | ||
173 | |||
170 | root_fid->qid = fcall->params.rstat.stat.qid; | 174 | root_fid->qid = fcall->params.rstat.stat.qid; |
171 | root->d_inode->i_ino = | 175 | root->d_inode->i_ino = |
172 | v9fs_qid2ino(&fcall->params.rstat.stat.qid); | 176 | v9fs_qid2ino(&fcall->params.rstat.stat.qid); |