aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/fid.c176
-rw-r--r--fs/9p/fid.h7
-rw-r--r--fs/9p/vfs_dentry.c2
-rw-r--r--fs/9p/vfs_dir.c11
-rw-r--r--fs/9p/vfs_file.c202
-rw-r--r--fs/9p/vfs_inode.c91
-rw-r--r--fs/9p/vfs_super.c19
7 files changed, 232 insertions, 276 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
74struct v9fs_fid *v9fs_fid_create(struct dentry *dentry) 74struct 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 */
122static 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
166clunk_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
122struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type) 182struct 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) { 235struct 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
29struct v9fs_fid { 30struct 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
55struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type); 56struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry);
57struct v9fs_fid *v9fs_fid_get_created(struct dentry *);
56void v9fs_fid_destroy(struct v9fs_fid *fid); 58void v9fs_fid_destroy(struct v9fs_fid *fid);
57struct v9fs_fid *v9fs_fid_create(struct dentry *); 59struct 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..bbc3cc63854f 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -53,30 +53,36 @@
53int v9fs_file_open(struct inode *inode, struct file *file) 53int 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;
@@ -207,16 +175,16 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
207} 175}
208 176
209/** 177/**
210 * v9fs_read - read from a file (internal) 178 * v9fs_file_read - read from a file
211 * @filep: file pointer to read 179 * @filep: file pointer to read
212 * @data: data buffer to read data into 180 * @data: data buffer to read data into
213 * @count: size of buffer 181 * @count: size of buffer
214 * @offset: offset at which to read data 182 * @offset: offset at which to read data
215 * 183 *
216 */ 184 */
217
218static ssize_t 185static ssize_t
219v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) 186v9fs_file_read(struct file *filp, char __user * data, size_t count,
187 loff_t * offset)
220{ 188{
221 struct inode *inode = filp->f_dentry->d_inode; 189 struct inode *inode = filp->f_dentry->d_inode;
222 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 190 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
@@ -226,6 +194,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset)
226 int rsize = 0; 194 int rsize = 0;
227 int result = 0; 195 int result = 0;
228 int total = 0; 196 int total = 0;
197 int n;
229 198
230 dprintk(DEBUG_VFS, "\n"); 199 dprintk(DEBUG_VFS, "\n");
231 200
@@ -248,10 +217,15 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset)
248 } else 217 } else
249 *offset += result; 218 *offset += result;
250 219
251 /* XXX - extra copy */ 220 n = copy_to_user(data, fcall->params.rread.data, result);
252 memcpy(buffer, fcall->params.rread.data, result); 221 if (n) {
222 dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n);
223 kfree(fcall);
224 return -EFAULT;
225 }
226
253 count -= result; 227 count -= result;
254 buffer += result; 228 data += result;
255 total += result; 229 total += result;
256 230
257 kfree(fcall); 231 kfree(fcall);
@@ -264,42 +238,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset)
264} 238}
265 239
266/** 240/**
267 * v9fs_file_read - read from a file 241 * v9fs_file_write - write to a file
268 * @filep: file pointer to read
269 * @data: data buffer to read data into
270 * @count: size of buffer
271 * @offset: offset at which to read data
272 *
273 */
274
275static ssize_t
276v9fs_file_read(struct file *filp, char __user * data, size_t count,
277 loff_t * offset)
278{
279 int retval = -1;
280 int ret = 0;
281 char *buffer;
282
283 buffer = kmalloc(count, GFP_KERNEL);
284 if (!buffer)
285 return -ENOMEM;
286
287 retval = v9fs_read(filp, buffer, count, offset);
288 if (retval > 0) {
289 if ((ret = copy_to_user(data, buffer, retval)) != 0) {
290 dprintk(DEBUG_ERROR, "Problem copying to user %d\n",
291 ret);
292 retval = ret;
293 }
294 }
295
296 kfree(buffer);
297
298 return retval;
299}
300
301/**
302 * v9fs_write - write to a file
303 * @filep: file pointer to write 242 * @filep: file pointer to write
304 * @data: data buffer to write data from 243 * @data: data buffer to write data from
305 * @count: size of buffer 244 * @count: size of buffer
@@ -308,7 +247,8 @@ v9fs_file_read(struct file *filp, char __user * data, size_t count,
308 */ 247 */
309 248
310static ssize_t 249static ssize_t
311v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) 250v9fs_file_write(struct file *filp, const char __user * data,
251 size_t count, loff_t * offset)
312{ 252{
313 struct inode *inode = filp->f_dentry->d_inode; 253 struct inode *inode = filp->f_dentry->d_inode;
314 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 254 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
@@ -318,30 +258,42 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset)
318 int result = -EIO; 258 int result = -EIO;
319 int rsize = 0; 259 int rsize = 0;
320 int total = 0; 260 int total = 0;
261 char *buf;
321 262
322 dprintk(DEBUG_VFS, "data %p count %d offset %x\n", buffer, (int)count, 263 dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count,
323 (int)*offset); 264 (int)*offset);
324 rsize = v9ses->maxdata - V9FS_IOHDRSZ; 265 rsize = v9ses->maxdata - V9FS_IOHDRSZ;
325 if (v9fid->iounit != 0 && rsize > v9fid->iounit) 266 if (v9fid->iounit != 0 && rsize > v9fid->iounit)
326 rsize = v9fid->iounit; 267 rsize = v9fid->iounit;
327 268
328 dump_data(buffer, count); 269 buf = kmalloc(v9ses->maxdata - V9FS_IOHDRSZ, GFP_KERNEL);
270 if (!buf)
271 return -ENOMEM;
329 272
330 do { 273 do {
331 if (count < rsize) 274 if (count < rsize)
332 rsize = count; 275 rsize = count;
333 276
334 result = 277 result = copy_from_user(buf, data, rsize);
335 v9fs_t_write(v9ses, fid, *offset, rsize, buffer, &fcall); 278 if (result) {
279 dprintk(DEBUG_ERROR, "Problem copying from user\n");
280 kfree(buf);
281 return -EFAULT;
282 }
283
284 dump_data(buf, rsize);
285 result = v9fs_t_write(v9ses, fid, *offset, rsize, buf, &fcall);
336 if (result < 0) { 286 if (result < 0) {
337 eprintk(KERN_ERR, "error while writing: %s(%d)\n", 287 eprintk(KERN_ERR, "error while writing: %s(%d)\n",
338 FCALL_ERROR(fcall), result); 288 FCALL_ERROR(fcall), result);
339 kfree(fcall); 289 kfree(fcall);
290 kfree(buf);
340 return result; 291 return result;
341 } else 292 } else
342 *offset += result; 293 *offset += result;
343 294
344 kfree(fcall); 295 kfree(fcall);
296 fcall = NULL;
345 297
346 if (result != rsize) { 298 if (result != rsize) {
347 eprintk(KERN_ERR, 299 eprintk(KERN_ERR,
@@ -351,46 +303,14 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset)
351 } 303 }
352 304
353 count -= result; 305 count -= result;
354 buffer += result; 306 data += result;
355 total += result; 307 total += result;
356 } while (count); 308 } while (count);
357 309
310 kfree(buf);
358 return total; 311 return total;
359} 312}
360 313
361/**
362 * v9fs_file_write - write to a file
363 * @filep: file pointer to write
364 * @data: data buffer to write data from
365 * @count: size of buffer
366 * @offset: offset at which to write data
367 *
368 */
369
370static ssize_t
371v9fs_file_write(struct file *filp, const char __user * data,
372 size_t count, loff_t * offset)
373{
374 int ret = -1;
375 char *buffer;
376
377 buffer = kmalloc(count, GFP_KERNEL);
378 if (buffer == NULL)
379 return -ENOMEM;
380
381 ret = copy_from_user(buffer, data, count);
382 if (ret) {
383 dprintk(DEBUG_ERROR, "Problem copying from user\n");
384 ret = -EFAULT;
385 } else {
386 ret = v9fs_write(filp, buffer, count, offset);
387 }
388
389 kfree(buffer);
390
391 return ret;
392}
393
394struct file_operations v9fs_file_operations = { 314struct file_operations v9fs_file_operations = {
395 .llseek = generic_file_llseek, 315 .llseek = generic_file_llseek,
396 .read = v9fs_file_read, 316 .read = v9fs_file_read,
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,
778static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) 805static 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..82c5b0084079 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -129,7 +129,6 @@ 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);
133 return ERR_PTR(newfid); 132 return ERR_PTR(newfid);
134 } 133 }
135 134
@@ -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);