Commit 06b55b464ee5b305aca75cb7d9424b184bf07f68

Authored by Eric Van Hensbergen
1 parent dfb0ec2e13

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>

Showing 3 changed files with 38 additions and 124 deletions Side-by-side Diff

... ... @@ -69,32 +69,54 @@
69 69 static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
70 70 {
71 71 int over;
  72 + struct p9_stat st;
  73 + int err;
72 74 struct p9_fid *fid;
73   - struct v9fs_session_info *v9ses;
74   - struct inode *inode;
75   - struct p9_stat *st;
  75 + int buflen;
  76 + char *statbuf;
  77 + int n, i = 0;
76 78  
77 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 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,
86   - v9fs_qid2ino(&st->qid), dt_type(st));
  82 + buflen = fid->clnt->msize - P9_IOHDRSZ;
  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 91 break;
90 92  
91   - filp->f_pos += st->size;
92   - kfree(st);
93   - st = NULL;
  93 + n = err;
  94 + while (i < n) {
  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);
97   - return 0;
  117 +free_and_exit:
  118 + kfree(statbuf);
  119 + return err;
98 120 }
99 121  
100 122  
include/net/9p/client.h
... ... @@ -163,8 +163,6 @@
163 163 * @uid: the numeric uid of the local user who owns this handle
164 164 * @aux: transport specific information (unused?)
165 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 166 * @flist: per-client-instance fid tracking
169 167 * @dlist: per-dentry fid tracking
170 168 *
... ... @@ -181,8 +179,6 @@
181 179 void *aux;
182 180  
183 181 int rdir_fpos;
184   - int rdir_pos;
185   - struct p9_fcall *rdir_fcall;
186 182 struct list_head flist;
187 183 struct list_head dlist; /* list of all fids attached to a dentry */
188 184 };
... ... @@ -207,7 +203,6 @@
207 203 u64 offset, u32 count);
208 204 struct p9_stat *p9_client_stat(struct p9_fid *fid);
209 205 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
210   -struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset);
211 206  
212 207 struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
213 208 void p9_client_cb(struct p9_client *c, struct p9_req_t *req);
... ... @@ -559,8 +559,6 @@
559 559 memset(&fid->qid, 0, sizeof(struct p9_qid));
560 560 fid->mode = -1;
561 561 fid->rdir_fpos = 0;
562   - fid->rdir_pos = 0;
563   - fid->rdir_fcall = NULL;
564 562 fid->uid = current->fsuid;
565 563 fid->clnt = clnt;
566 564 fid->aux = NULL;
... ... @@ -586,7 +584,6 @@
586 584 spin_lock(&clnt->lock);
587 585 list_del(&fid->flist);
588 586 spin_unlock(&clnt->lock);
589   - kfree(fid->rdir_fcall);
590 587 kfree(fid);
591 588 }
592 589  
... ... @@ -1261,104 +1258,4 @@
1261 1258 return err;
1262 1259 }
1263 1260 EXPORT_SYMBOL(p9_client_wstat);
1264   -
1265   -struct 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   -
1352   -done:
1353   - kfree(tc);
1354   - kfree(rc);
1355   - return ret;
1356   -
1357   -error:
1358   - kfree(tc);
1359   - kfree(rc);
1360   - kfree(ret);
1361   - return ERR_PTR(err);
1362   -}
1363   -EXPORT_SYMBOL(p9_client_dirread);