aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);