diff options
| -rw-r--r-- | fs/9p/vfs_dir.c | 54 | ||||
| -rw-r--r-- | include/net/9p/client.h | 5 | ||||
| -rw-r--r-- | net/9p/client.c | 103 |
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) | |||
| 69 | static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | 69 | static 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); | 117 | free_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); |
| 208 | struct p9_stat *p9_client_stat(struct p9_fid *fid); | 204 | struct p9_stat *p9_client_stat(struct p9_fid *fid); |
| 209 | int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); | 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 | struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); | 207 | struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); |
| 213 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req); | 208 | void 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 | } |
| 1263 | EXPORT_SYMBOL(p9_client_wstat); | 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); | ||
