aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/9p/client.c')
-rw-r--r--net/9p/client.c377
1 files changed, 260 insertions, 117 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index 9eb72505308f..9e3b0e640da1 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -61,13 +61,13 @@ static const match_table_t tokens = {
61 61
62inline int p9_is_proto_dotl(struct p9_client *clnt) 62inline int p9_is_proto_dotl(struct p9_client *clnt)
63{ 63{
64 return (clnt->proto_version == p9_proto_2000L); 64 return clnt->proto_version == p9_proto_2000L;
65} 65}
66EXPORT_SYMBOL(p9_is_proto_dotl); 66EXPORT_SYMBOL(p9_is_proto_dotl);
67 67
68inline int p9_is_proto_dotu(struct p9_client *clnt) 68inline int p9_is_proto_dotu(struct p9_client *clnt)
69{ 69{
70 return (clnt->proto_version == p9_proto_2000u); 70 return clnt->proto_version == p9_proto_2000u;
71} 71}
72EXPORT_SYMBOL(p9_is_proto_dotu); 72EXPORT_SYMBOL(p9_is_proto_dotu);
73 73
@@ -92,9 +92,6 @@ static int get_protocol_version(const substring_t *name)
92 return version; 92 return version;
93} 93}
94 94
95static struct p9_req_t *
96p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
97
98/** 95/**
99 * parse_options - parse mount options into client structure 96 * parse_options - parse mount options into client structure
100 * @opts: options string passed from mount 97 * @opts: options string passed from mount
@@ -178,7 +175,7 @@ free_and_return:
178 * @tag: numeric id for transaction 175 * @tag: numeric id for transaction
179 * 176 *
180 * this is a simple array lookup, but will grow the 177 * this is a simple array lookup, but will grow the
181 * request_slots as necessary to accomodate transaction 178 * request_slots as necessary to accommodate transaction
182 * ids which did not previously have a slot. 179 * ids which did not previously have a slot.
183 * 180 *
184 * this code relies on the client spinlock to manage locks, its 181 * this code relies on the client spinlock to manage locks, its
@@ -223,16 +220,29 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
223 220
224 req = &c->reqs[row][col]; 221 req = &c->reqs[row][col];
225 if (!req->tc) { 222 if (!req->tc) {
226 req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); 223 req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS);
227 if (!req->wq) { 224 if (!req->wq) {
228 printk(KERN_ERR "Couldn't grow tag array\n"); 225 printk(KERN_ERR "Couldn't grow tag array\n");
229 return ERR_PTR(-ENOMEM); 226 return ERR_PTR(-ENOMEM);
230 } 227 }
231 init_waitqueue_head(req->wq); 228 init_waitqueue_head(req->wq);
232 req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize, 229 if ((c->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
233 GFP_KERNEL); 230 P9_TRANS_PREF_PAYLOAD_SEP) {
234 req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize, 231 int alloc_msize = min(c->msize, 4096);
235 GFP_KERNEL); 232 req->tc = kmalloc(sizeof(struct p9_fcall)+alloc_msize,
233 GFP_NOFS);
234 req->tc->capacity = alloc_msize;
235 req->rc = kmalloc(sizeof(struct p9_fcall)+alloc_msize,
236 GFP_NOFS);
237 req->rc->capacity = alloc_msize;
238 } else {
239 req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
240 GFP_NOFS);
241 req->tc->capacity = c->msize;
242 req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
243 GFP_NOFS);
244 req->rc->capacity = c->msize;
245 }
236 if ((!req->tc) || (!req->rc)) { 246 if ((!req->tc) || (!req->rc)) {
237 printk(KERN_ERR "Couldn't grow tag array\n"); 247 printk(KERN_ERR "Couldn't grow tag array\n");
238 kfree(req->tc); 248 kfree(req->tc);
@@ -243,9 +253,7 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
243 return ERR_PTR(-ENOMEM); 253 return ERR_PTR(-ENOMEM);
244 } 254 }
245 req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); 255 req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
246 req->tc->capacity = c->msize;
247 req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall); 256 req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
248 req->rc->capacity = c->msize;
249 } 257 }
250 258
251 p9pdu_reset(req->tc); 259 p9pdu_reset(req->tc);
@@ -296,12 +304,13 @@ static int p9_tag_init(struct p9_client *c)
296 c->tagpool = p9_idpool_create(); 304 c->tagpool = p9_idpool_create();
297 if (IS_ERR(c->tagpool)) { 305 if (IS_ERR(c->tagpool)) {
298 err = PTR_ERR(c->tagpool); 306 err = PTR_ERR(c->tagpool);
299 c->tagpool = NULL;
300 goto error; 307 goto error;
301 } 308 }
302 309 err = p9_idpool_get(c->tagpool); /* reserve tag 0 */
303 p9_idpool_get(c->tagpool); /* reserve tag 0 */ 310 if (err < 0) {
304 311 p9_idpool_destroy(c->tagpool);
312 goto error;
313 }
305 c->max_tag = 0; 314 c->max_tag = 0;
306error: 315error:
307 return err; 316 return err;
@@ -443,6 +452,7 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
443{ 452{
444 int8_t type; 453 int8_t type;
445 int err; 454 int err;
455 int ecode;
446 456
447 err = p9_parse_header(req->rc, NULL, &type, NULL, 0); 457 err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
448 if (err) { 458 if (err) {
@@ -450,40 +460,71 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
450 return err; 460 return err;
451 } 461 }
452 462
453 if (type == P9_RERROR) { 463 if (type != P9_RERROR && type != P9_RLERROR)
454 int ecode; 464 return 0;
465
466 if (!p9_is_proto_dotl(c)) {
455 char *ename; 467 char *ename;
456 468
457 err = p9pdu_readf(req->rc, c->proto_version, "s?d", 469 if (req->tc->pbuf_size) {
458 &ename, &ecode); 470 /* Handle user buffers */
459 if (err) { 471 size_t len = req->rc->size - req->rc->offset;
460 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", 472 if (req->tc->pubuf) {
461 err); 473 /* User Buffer */
462 return err; 474 err = copy_from_user(
475 &req->rc->sdata[req->rc->offset],
476 req->tc->pubuf, len);
477 if (err) {
478 err = -EFAULT;
479 goto out_err;
480 }
481 } else {
482 /* Kernel Buffer */
483 memmove(&req->rc->sdata[req->rc->offset],
484 req->tc->pkbuf, len);
485 }
463 } 486 }
487 err = p9pdu_readf(req->rc, c->proto_version, "s?d",
488 &ename, &ecode);
489 if (err)
490 goto out_err;
464 491
465 if (p9_is_proto_dotu(c) || 492 if (p9_is_proto_dotu(c))
466 p9_is_proto_dotl(c))
467 err = -ecode; 493 err = -ecode;
468 494
469 if (!err || !IS_ERR_VALUE(err)) 495 if (!err || !IS_ERR_VALUE(err)) {
470 err = p9_errstr2errno(ename, strlen(ename)); 496 err = p9_errstr2errno(ename, strlen(ename));
471 497
472 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); 498 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode,
499 ename);
473 500
474 kfree(ename); 501 kfree(ename);
475 } else 502 }
476 err = 0; 503 } else {
504 err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
505 err = -ecode;
506
507 P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
508 }
509
510
511 return err;
512
513out_err:
514 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
477 515
478 return err; 516 return err;
479} 517}
480 518
519static struct p9_req_t *
520p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
521
481/** 522/**
482 * p9_client_flush - flush (cancel) a request 523 * p9_client_flush - flush (cancel) a request
483 * @c: client state 524 * @c: client state
484 * @oldreq: request to cancel 525 * @oldreq: request to cancel
485 * 526 *
486 * This sents a flush for a particular requests and links 527 * This sents a flush for a particular request and links
487 * the flush request to the original request. The current 528 * the flush request to the original request. The current
488 * code only supports a single flush request although the protocol 529 * code only supports a single flush request although the protocol
489 * allows for multiple flush requests to be sent for a single request. 530 * allows for multiple flush requests to be sent for a single request.
@@ -568,11 +609,14 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
568 va_start(ap, fmt); 609 va_start(ap, fmt);
569 err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); 610 err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap);
570 va_end(ap); 611 va_end(ap);
612 if (err)
613 goto reterr;
571 p9pdu_finalize(req->tc); 614 p9pdu_finalize(req->tc);
572 615
573 err = c->trans_mod->request(c, req); 616 err = c->trans_mod->request(c, req);
574 if (err < 0) { 617 if (err < 0) {
575 c->status = Disconnected; 618 if (err != -ERESTARTSYS && err != -EFAULT)
619 c->status = Disconnected;
576 goto reterr; 620 goto reterr;
577 } 621 }
578 622
@@ -671,7 +715,7 @@ static void p9_fid_destroy(struct p9_fid *fid)
671 kfree(fid); 715 kfree(fid);
672} 716}
673 717
674int p9_client_version(struct p9_client *c) 718static int p9_client_version(struct p9_client *c)
675{ 719{
676 int err = 0; 720 int err = 0;
677 struct p9_req_t *req; 721 struct p9_req_t *req;
@@ -730,7 +774,6 @@ error:
730 774
731 return err; 775 return err;
732} 776}
733EXPORT_SYMBOL(p9_client_version);
734 777
735struct p9_client *p9_client_create(const char *dev_name, char *options) 778struct p9_client *p9_client_create(const char *dev_name, char *options)
736{ 779{
@@ -747,11 +790,13 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
747 spin_lock_init(&clnt->lock); 790 spin_lock_init(&clnt->lock);
748 INIT_LIST_HEAD(&clnt->fidlist); 791 INIT_LIST_HEAD(&clnt->fidlist);
749 792
750 p9_tag_init(clnt); 793 err = p9_tag_init(clnt);
794 if (err < 0)
795 goto free_client;
751 796
752 err = parse_opts(options, clnt); 797 err = parse_opts(options, clnt);
753 if (err < 0) 798 if (err < 0)
754 goto free_client; 799 goto destroy_tagpool;
755 800
756 if (!clnt->trans_mod) 801 if (!clnt->trans_mod)
757 clnt->trans_mod = v9fs_get_default_trans(); 802 clnt->trans_mod = v9fs_get_default_trans();
@@ -760,13 +805,12 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
760 err = -EPROTONOSUPPORT; 805 err = -EPROTONOSUPPORT;
761 P9_DPRINTK(P9_DEBUG_ERROR, 806 P9_DPRINTK(P9_DEBUG_ERROR,
762 "No transport defined or default transport\n"); 807 "No transport defined or default transport\n");
763 goto free_client; 808 goto destroy_tagpool;
764 } 809 }
765 810
766 clnt->fidpool = p9_idpool_create(); 811 clnt->fidpool = p9_idpool_create();
767 if (IS_ERR(clnt->fidpool)) { 812 if (IS_ERR(clnt->fidpool)) {
768 err = PTR_ERR(clnt->fidpool); 813 err = PTR_ERR(clnt->fidpool);
769 clnt->fidpool = NULL;
770 goto put_trans; 814 goto put_trans;
771 } 815 }
772 816
@@ -792,6 +836,8 @@ destroy_fidpool:
792 p9_idpool_destroy(clnt->fidpool); 836 p9_idpool_destroy(clnt->fidpool);
793put_trans: 837put_trans:
794 v9fs_put_trans(clnt->trans_mod); 838 v9fs_put_trans(clnt->trans_mod);
839destroy_tagpool:
840 p9_idpool_destroy(clnt->tagpool);
795free_client: 841free_client:
796 kfree(clnt); 842 kfree(clnt);
797 return ERR_PTR(err); 843 return ERR_PTR(err);
@@ -887,63 +933,15 @@ error:
887} 933}
888EXPORT_SYMBOL(p9_client_attach); 934EXPORT_SYMBOL(p9_client_attach);
889 935
890struct p9_fid * 936struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
891p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname) 937 char **wnames, int clone)
892{
893 int err;
894 struct p9_req_t *req;
895 struct p9_qid qid;
896 struct p9_fid *afid;
897
898 P9_DPRINTK(P9_DEBUG_9P, ">>> TAUTH uname %s aname %s\n", uname, aname);
899 err = 0;
900
901 afid = p9_fid_create(clnt);
902 if (IS_ERR(afid)) {
903 err = PTR_ERR(afid);
904 afid = NULL;
905 goto error;
906 }
907
908 req = p9_client_rpc(clnt, P9_TAUTH, "dss?d",
909 afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
910 if (IS_ERR(req)) {
911 err = PTR_ERR(req);
912 goto error;
913 }
914
915 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
916 if (err) {
917 p9pdu_dump(1, req->rc);
918 p9_free_req(clnt, req);
919 goto error;
920 }
921
922 P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n",
923 qid.type,
924 (unsigned long long)qid.path,
925 qid.version);
926
927 memmove(&afid->qid, &qid, sizeof(struct p9_qid));
928 p9_free_req(clnt, req);
929 return afid;
930
931error:
932 if (afid)
933 p9_fid_destroy(afid);
934 return ERR_PTR(err);
935}
936EXPORT_SYMBOL(p9_client_auth);
937
938struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
939 int clone)
940{ 938{
941 int err; 939 int err;
942 struct p9_client *clnt; 940 struct p9_client *clnt;
943 struct p9_fid *fid; 941 struct p9_fid *fid;
944 struct p9_qid *wqids; 942 struct p9_qid *wqids;
945 struct p9_req_t *req; 943 struct p9_req_t *req;
946 int16_t nwqids, count; 944 uint16_t nwqids, count;
947 945
948 err = 0; 946 err = 0;
949 wqids = NULL; 947 wqids = NULL;
@@ -961,7 +959,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
961 fid = oldfid; 959 fid = oldfid;
962 960
963 961
964 P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n", 962 P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n",
965 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL); 963 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
966 964
967 req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid, 965 req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
@@ -1200,12 +1198,44 @@ int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname)
1200} 1198}
1201EXPORT_SYMBOL(p9_client_link); 1199EXPORT_SYMBOL(p9_client_link);
1202 1200
1201int p9_client_fsync(struct p9_fid *fid, int datasync)
1202{
1203 int err;
1204 struct p9_client *clnt;
1205 struct p9_req_t *req;
1206
1207 P9_DPRINTK(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n",
1208 fid->fid, datasync);
1209 err = 0;
1210 clnt = fid->clnt;
1211
1212 req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync);
1213 if (IS_ERR(req)) {
1214 err = PTR_ERR(req);
1215 goto error;
1216 }
1217
1218 P9_DPRINTK(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid);
1219
1220 p9_free_req(clnt, req);
1221
1222error:
1223 return err;
1224}
1225EXPORT_SYMBOL(p9_client_fsync);
1226
1203int p9_client_clunk(struct p9_fid *fid) 1227int p9_client_clunk(struct p9_fid *fid)
1204{ 1228{
1205 int err; 1229 int err;
1206 struct p9_client *clnt; 1230 struct p9_client *clnt;
1207 struct p9_req_t *req; 1231 struct p9_req_t *req;
1208 1232
1233 if (!fid) {
1234 P9_EPRINTK(KERN_WARNING, "Trying to clunk with NULL fid\n");
1235 dump_stack();
1236 return 0;
1237 }
1238
1209 P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); 1239 P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid);
1210 err = 0; 1240 err = 0;
1211 clnt = fid->clnt; 1241 clnt = fid->clnt;
@@ -1255,7 +1285,7 @@ int
1255p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, 1285p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1256 u32 count) 1286 u32 count)
1257{ 1287{
1258 int err, rsize, total; 1288 int err, rsize;
1259 struct p9_client *clnt; 1289 struct p9_client *clnt;
1260 struct p9_req_t *req; 1290 struct p9_req_t *req;
1261 char *dataptr; 1291 char *dataptr;
@@ -1264,7 +1294,6 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1264 (long long unsigned) offset, count); 1294 (long long unsigned) offset, count);
1265 err = 0; 1295 err = 0;
1266 clnt = fid->clnt; 1296 clnt = fid->clnt;
1267 total = 0;
1268 1297
1269 rsize = fid->iounit; 1298 rsize = fid->iounit;
1270 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1299 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
@@ -1273,7 +1302,15 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1273 if (count < rsize) 1302 if (count < rsize)
1274 rsize = count; 1303 rsize = count;
1275 1304
1276 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize); 1305 /* Don't bother zerocopy for small IO (< 1024) */
1306 if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
1307 P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) {
1308 req = p9_client_rpc(clnt, P9_TREAD, "dqE", fid->fid, offset,
1309 rsize, data, udata);
1310 } else {
1311 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
1312 rsize);
1313 }
1277 if (IS_ERR(req)) { 1314 if (IS_ERR(req)) {
1278 err = PTR_ERR(req); 1315 err = PTR_ERR(req);
1279 goto error; 1316 goto error;
@@ -1287,18 +1324,17 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1287 1324
1288 P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count); 1325 P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1289 1326
1290 if (data) { 1327 if (!req->tc->pbuf_size) {
1291 memmove(data, dataptr, count); 1328 if (data) {
1292 } 1329 memmove(data, dataptr, count);
1293 1330 } else {
1294 if (udata) { 1331 err = copy_to_user(udata, dataptr, count);
1295 err = copy_to_user(udata, dataptr, count); 1332 if (err) {
1296 if (err) { 1333 err = -EFAULT;
1297 err = -EFAULT; 1334 goto free_and_error;
1298 goto free_and_error; 1335 }
1299 } 1336 }
1300 } 1337 }
1301
1302 p9_free_req(clnt, req); 1338 p9_free_req(clnt, req);
1303 return count; 1339 return count;
1304 1340
@@ -1313,7 +1349,7 @@ int
1313p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, 1349p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1314 u64 offset, u32 count) 1350 u64 offset, u32 count)
1315{ 1351{
1316 int err, rsize, total; 1352 int err, rsize;
1317 struct p9_client *clnt; 1353 struct p9_client *clnt;
1318 struct p9_req_t *req; 1354 struct p9_req_t *req;
1319 1355
@@ -1321,7 +1357,6 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1321 fid->fid, (long long unsigned) offset, count); 1357 fid->fid, (long long unsigned) offset, count);
1322 err = 0; 1358 err = 0;
1323 clnt = fid->clnt; 1359 clnt = fid->clnt;
1324 total = 0;
1325 1360
1326 rsize = fid->iounit; 1361 rsize = fid->iounit;
1327 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1362 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
@@ -1329,12 +1364,21 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1329 1364
1330 if (count < rsize) 1365 if (count < rsize)
1331 rsize = count; 1366 rsize = count;
1332 if (data) 1367
1333 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset, 1368 /* Don't bother zerocopy form small IO (< 1024) */
1334 rsize, data); 1369 if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
1335 else 1370 P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) {
1336 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset, 1371 req = p9_client_rpc(clnt, P9_TWRITE, "dqE", fid->fid, offset,
1337 rsize, udata); 1372 rsize, data, udata);
1373 } else {
1374
1375 if (data)
1376 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid,
1377 offset, rsize, data);
1378 else
1379 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid,
1380 offset, rsize, udata);
1381 }
1338 if (IS_ERR(req)) { 1382 if (IS_ERR(req)) {
1339 err = PTR_ERR(req); 1383 err = PTR_ERR(req);
1340 goto error; 1384 goto error;
@@ -1703,7 +1747,7 @@ EXPORT_SYMBOL_GPL(p9_client_xattrcreate);
1703 1747
1704int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) 1748int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
1705{ 1749{
1706 int err, rsize, total; 1750 int err, rsize;
1707 struct p9_client *clnt; 1751 struct p9_client *clnt;
1708 struct p9_req_t *req; 1752 struct p9_req_t *req;
1709 char *dataptr; 1753 char *dataptr;
@@ -1713,7 +1757,6 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
1713 1757
1714 err = 0; 1758 err = 0;
1715 clnt = fid->clnt; 1759 clnt = fid->clnt;
1716 total = 0;
1717 1760
1718 rsize = fid->iounit; 1761 rsize = fid->iounit;
1719 if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ) 1762 if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ)
@@ -1722,7 +1765,14 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
1722 if (count < rsize) 1765 if (count < rsize)
1723 rsize = count; 1766 rsize = count;
1724 1767
1725 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, offset, rsize); 1768 if ((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
1769 P9_TRANS_PREF_PAYLOAD_SEP) {
1770 req = p9_client_rpc(clnt, P9_TREADDIR, "dqF", fid->fid,
1771 offset, rsize, data);
1772 } else {
1773 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid,
1774 offset, rsize);
1775 }
1726 if (IS_ERR(req)) { 1776 if (IS_ERR(req)) {
1727 err = PTR_ERR(req); 1777 err = PTR_ERR(req);
1728 goto error; 1778 goto error;
@@ -1736,7 +1786,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
1736 1786
1737 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); 1787 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
1738 1788
1739 if (data) 1789 if (!req->tc->pbuf_size && data)
1740 memmove(data, dataptr, count); 1790 memmove(data, dataptr, count);
1741 1791
1742 p9_free_req(clnt, req); 1792 p9_free_req(clnt, req);
@@ -1810,3 +1860,96 @@ error:
1810 1860
1811} 1861}
1812EXPORT_SYMBOL(p9_client_mkdir_dotl); 1862EXPORT_SYMBOL(p9_client_mkdir_dotl);
1863
1864int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status)
1865{
1866 int err;
1867 struct p9_client *clnt;
1868 struct p9_req_t *req;
1869
1870 err = 0;
1871 clnt = fid->clnt;
1872 P9_DPRINTK(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d "
1873 "start %lld length %lld proc_id %d client_id %s\n",
1874 fid->fid, flock->type, flock->flags, flock->start,
1875 flock->length, flock->proc_id, flock->client_id);
1876
1877 req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type,
1878 flock->flags, flock->start, flock->length,
1879 flock->proc_id, flock->client_id);
1880
1881 if (IS_ERR(req))
1882 return PTR_ERR(req);
1883
1884 err = p9pdu_readf(req->rc, clnt->proto_version, "b", status);
1885 if (err) {
1886 p9pdu_dump(1, req->rc);
1887 goto error;
1888 }
1889 P9_DPRINTK(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
1890error:
1891 p9_free_req(clnt, req);
1892 return err;
1893
1894}
1895EXPORT_SYMBOL(p9_client_lock_dotl);
1896
1897int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
1898{
1899 int err;
1900 struct p9_client *clnt;
1901 struct p9_req_t *req;
1902
1903 err = 0;
1904 clnt = fid->clnt;
1905 P9_DPRINTK(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld "
1906 "length %lld proc_id %d client_id %s\n", fid->fid, glock->type,
1907 glock->start, glock->length, glock->proc_id, glock->client_id);
1908
1909 req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid, glock->type,
1910 glock->start, glock->length, glock->proc_id, glock->client_id);
1911
1912 if (IS_ERR(req))
1913 return PTR_ERR(req);
1914
1915 err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type,
1916 &glock->start, &glock->length, &glock->proc_id,
1917 &glock->client_id);
1918 if (err) {
1919 p9pdu_dump(1, req->rc);
1920 goto error;
1921 }
1922 P9_DPRINTK(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld "
1923 "proc_id %d client_id %s\n", glock->type, glock->start,
1924 glock->length, glock->proc_id, glock->client_id);
1925error:
1926 p9_free_req(clnt, req);
1927 return err;
1928}
1929EXPORT_SYMBOL(p9_client_getlock_dotl);
1930
1931int p9_client_readlink(struct p9_fid *fid, char **target)
1932{
1933 int err;
1934 struct p9_client *clnt;
1935 struct p9_req_t *req;
1936
1937 err = 0;
1938 clnt = fid->clnt;
1939 P9_DPRINTK(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid);
1940
1941 req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid);
1942 if (IS_ERR(req))
1943 return PTR_ERR(req);
1944
1945 err = p9pdu_readf(req->rc, clnt->proto_version, "s", target);
1946 if (err) {
1947 p9pdu_dump(1, req->rc);
1948 goto error;
1949 }
1950 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
1951error:
1952 p9_free_req(clnt, req);
1953 return err;
1954}
1955EXPORT_SYMBOL(p9_client_readlink);