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); | ||