aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@gmail.com>2008-10-13 21:36:15 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2008-10-17 12:04:43 -0400
commit06b55b464ee5b305aca75cb7d9424b184bf07f68 (patch)
treefb2bba4546ad4b800f1e49a75774b01fc6fcdb6b
parentdfb0ec2e13a906ff19a0bbfa9208caab50cfc2e3 (diff)
9p: move dirread to fs layer
Currently reading a directory is implemented in the client code. This function is not actually a wire operation, but a meta operation which calls read operations and processes the results. This patch moves this functionality to the fs layer and calls component wire operations instead of constructing their packets. This provides a cleaner separation and will help when we reorganize the client functions and protocol processing methods. Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--fs/9p/vfs_dir.c54
-rw-r--r--include/net/9p/client.h5
-rw-r--r--net/9p/client.c103
3 files changed, 38 insertions, 124 deletions
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index e298fe194093..d7d0ac5a2ca3 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -69,32 +69,54 @@ static inline int dt_type(struct p9_stat *mistat)
69static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) 69static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
70{ 70{
71 int over; 71 int over;
72 struct p9_stat st;
73 int err;
72 struct p9_fid *fid; 74 struct p9_fid *fid;
73 struct v9fs_session_info *v9ses; 75 int buflen;
74 struct inode *inode; 76 char *statbuf;
75 struct p9_stat *st; 77 int n, i = 0;
76 78
77 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); 79 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
78 inode = filp->f_path.dentry->d_inode;
79 v9ses = v9fs_inode2v9ses(inode);
80 fid = filp->private_data; 80 fid = filp->private_data;
81 while ((st = p9_client_dirread(fid, filp->f_pos)) != NULL) {
82 if (IS_ERR(st))
83 return PTR_ERR(st);
84 81
85 over = filldir(dirent, st->name.str, st->name.len, filp->f_pos, 82 buflen = fid->clnt->msize - P9_IOHDRSZ;
86 v9fs_qid2ino(&st->qid), dt_type(st)); 83 statbuf = kmalloc(buflen, GFP_KERNEL);
84 if (!statbuf)
85 return -ENOMEM;
87 86
88 if (over) 87 while (1) {
88 err = v9fs_file_readn(filp, statbuf, NULL, fid->rdir_fpos,
89 buflen);
90 if (err <= 0)
89 break; 91 break;
90 92
91 filp->f_pos += st->size; 93 n = err;
92 kfree(st); 94 while (i < n) {
93 st = NULL; 95 err = p9_deserialize_stat(statbuf + i, buflen-i, &st,
96 fid->clnt->dotu);
97 if (!err) {
98 err = -EIO;
99 goto free_and_exit;
100 }
101
102 i += err;
103 fid->rdir_fpos += err;
104
105 over = filldir(dirent, st.name.str, st.name.len,
106 filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st));
107
108 filp->f_pos += st.size;
109
110 if (over) {
111 err = 0;
112 goto free_and_exit;
113 }
114 }
94 } 115 }
95 116
96 kfree(st); 117free_and_exit:
97 return 0; 118 kfree(statbuf);
119 return err;
98} 120}
99 121
100 122
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index bb8b0ede132d..eeb7d922816e 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -163,8 +163,6 @@ struct p9_client {
163 * @uid: the numeric uid of the local user who owns this handle 163 * @uid: the numeric uid of the local user who owns this handle
164 * @aux: transport specific information (unused?) 164 * @aux: transport specific information (unused?)
165 * @rdir_fpos: tracks offset of file position when reading directory contents 165 * @rdir_fpos: tracks offset of file position when reading directory contents
166 * @rdir_pos: (unused?)
167 * @rdir_fcall: holds response of last directory read request
168 * @flist: per-client-instance fid tracking 166 * @flist: per-client-instance fid tracking
169 * @dlist: per-dentry fid tracking 167 * @dlist: per-dentry fid tracking
170 * 168 *
@@ -181,8 +179,6 @@ struct p9_fid {
181 void *aux; 179 void *aux;
182 180
183 int rdir_fpos; 181 int rdir_fpos;
184 int rdir_pos;
185 struct p9_fcall *rdir_fcall;
186 struct list_head flist; 182 struct list_head flist;
187 struct list_head dlist; /* list of all fids attached to a dentry */ 183 struct list_head dlist; /* list of all fids attached to a dentry */
188}; 184};
@@ -207,7 +203,6 @@ int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
207 u64 offset, u32 count); 203 u64 offset, u32 count);
208struct p9_stat *p9_client_stat(struct p9_fid *fid); 204struct p9_stat *p9_client_stat(struct p9_fid *fid);
209int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); 205int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
210struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset);
211 206
212struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); 207struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
213void p9_client_cb(struct p9_client *c, struct p9_req_t *req); 208void p9_client_cb(struct p9_client *c, struct p9_req_t *req);
diff --git a/net/9p/client.c b/net/9p/client.c
index d5ea042eabb0..90ee9efeede3 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -559,8 +559,6 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
559 memset(&fid->qid, 0, sizeof(struct p9_qid)); 559 memset(&fid->qid, 0, sizeof(struct p9_qid));
560 fid->mode = -1; 560 fid->mode = -1;
561 fid->rdir_fpos = 0; 561 fid->rdir_fpos = 0;
562 fid->rdir_pos = 0;
563 fid->rdir_fcall = NULL;
564 fid->uid = current->fsuid; 562 fid->uid = current->fsuid;
565 fid->clnt = clnt; 563 fid->clnt = clnt;
566 fid->aux = NULL; 564 fid->aux = NULL;
@@ -586,7 +584,6 @@ static void p9_fid_destroy(struct p9_fid *fid)
586 spin_lock(&clnt->lock); 584 spin_lock(&clnt->lock);
587 list_del(&fid->flist); 585 list_del(&fid->flist);
588 spin_unlock(&clnt->lock); 586 spin_unlock(&clnt->lock);
589 kfree(fid->rdir_fcall);
590 kfree(fid); 587 kfree(fid);
591} 588}
592 589
@@ -1261,103 +1258,3 @@ done:
1261 return err; 1258 return err;
1262} 1259}
1263EXPORT_SYMBOL(p9_client_wstat); 1260EXPORT_SYMBOL(p9_client_wstat);
1264
1265struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset)
1266{
1267 int err, n, m;
1268 struct p9_fcall *tc, *rc;
1269 struct p9_client *clnt;
1270 struct p9_stat st, *ret;
1271
1272 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu\n", fid->fid,
1273 (long long unsigned) offset);
1274 err = 0;
1275 tc = NULL;
1276 rc = NULL;
1277 ret = NULL;
1278 clnt = fid->clnt;
1279
1280 /* if the offset is below or above the current response, free it */
1281 if (offset < fid->rdir_fpos || (fid->rdir_fcall &&
1282 offset >= fid->rdir_fpos+fid->rdir_fcall->params.rread.count)) {
1283 fid->rdir_pos = 0;
1284 if (fid->rdir_fcall)
1285 fid->rdir_fpos += fid->rdir_fcall->params.rread.count;
1286
1287 kfree(fid->rdir_fcall);
1288 fid->rdir_fcall = NULL;
1289 if (offset < fid->rdir_fpos)
1290 fid->rdir_fpos = 0;
1291 }
1292
1293 if (!fid->rdir_fcall) {
1294 n = fid->iounit;
1295 if (!n || n > clnt->msize-P9_IOHDRSZ)
1296 n = clnt->msize - P9_IOHDRSZ;
1297
1298 while (1) {
1299 if (fid->rdir_fcall) {
1300 fid->rdir_fpos +=
1301 fid->rdir_fcall->params.rread.count;
1302 kfree(fid->rdir_fcall);
1303 fid->rdir_fcall = NULL;
1304 }
1305
1306 tc = p9_create_tread(fid->fid, fid->rdir_fpos, n);
1307 if (IS_ERR(tc)) {
1308 err = PTR_ERR(tc);
1309 tc = NULL;
1310 goto error;
1311 }
1312
1313 err = p9_client_rpc(clnt, tc, &rc);
1314 if (err)
1315 goto error;
1316
1317 n = rc->params.rread.count;
1318 if (n == 0)
1319 goto done;
1320
1321 fid->rdir_fcall = rc;
1322 rc = NULL;
1323 if (offset >= fid->rdir_fpos &&
1324 offset < fid->rdir_fpos+n)
1325 break;
1326 }
1327
1328 fid->rdir_pos = 0;
1329 }
1330
1331 m = offset - fid->rdir_fpos;
1332 if (m < 0)
1333 goto done;
1334
1335 n = p9_deserialize_stat(fid->rdir_fcall->params.rread.data + m,
1336 fid->rdir_fcall->params.rread.count - m, &st, clnt->dotu);
1337
1338 if (!n) {
1339 err = -EIO;
1340 goto error;
1341 }
1342
1343 fid->rdir_pos += n;
1344 st.size = n;
1345 ret = p9_clone_stat(&st, clnt->dotu);
1346 if (IS_ERR(ret)) {
1347 err = PTR_ERR(ret);
1348 ret = NULL;
1349 goto error;
1350 }
1351
1352done:
1353 kfree(tc);
1354 kfree(rc);
1355 return ret;
1356
1357error:
1358 kfree(tc);
1359 kfree(rc);
1360 kfree(ret);
1361 return ERR_PTR(err);
1362}
1363EXPORT_SYMBOL(p9_client_dirread);