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.c157
1 files changed, 106 insertions, 51 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index a848bca9fbff..77367745be9b 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -178,7 +178,7 @@ free_and_return:
178 * @tag: numeric id for transaction 178 * @tag: numeric id for transaction
179 * 179 *
180 * this is a simple array lookup, but will grow the 180 * this is a simple array lookup, but will grow the
181 * request_slots as necessary to accomodate transaction 181 * request_slots as necessary to accommodate transaction
182 * ids which did not previously have a slot. 182 * ids which did not previously have a slot.
183 * 183 *
184 * this code relies on the client spinlock to manage locks, its 184 * this code relies on the client spinlock to manage locks, its
@@ -223,16 +223,29 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
223 223
224 req = &c->reqs[row][col]; 224 req = &c->reqs[row][col];
225 if (!req->tc) { 225 if (!req->tc) {
226 req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); 226 req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS);
227 if (!req->wq) { 227 if (!req->wq) {
228 printk(KERN_ERR "Couldn't grow tag array\n"); 228 printk(KERN_ERR "Couldn't grow tag array\n");
229 return ERR_PTR(-ENOMEM); 229 return ERR_PTR(-ENOMEM);
230 } 230 }
231 init_waitqueue_head(req->wq); 231 init_waitqueue_head(req->wq);
232 req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize, 232 if ((c->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
233 GFP_KERNEL); 233 P9_TRANS_PREF_PAYLOAD_SEP) {
234 req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize, 234 int alloc_msize = min(c->msize, 4096);
235 GFP_KERNEL); 235 req->tc = kmalloc(sizeof(struct p9_fcall)+alloc_msize,
236 GFP_NOFS);
237 req->tc->capacity = alloc_msize;
238 req->rc = kmalloc(sizeof(struct p9_fcall)+alloc_msize,
239 GFP_NOFS);
240 req->rc->capacity = alloc_msize;
241 } else {
242 req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
243 GFP_NOFS);
244 req->tc->capacity = c->msize;
245 req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
246 GFP_NOFS);
247 req->rc->capacity = c->msize;
248 }
236 if ((!req->tc) || (!req->rc)) { 249 if ((!req->tc) || (!req->rc)) {
237 printk(KERN_ERR "Couldn't grow tag array\n"); 250 printk(KERN_ERR "Couldn't grow tag array\n");
238 kfree(req->tc); 251 kfree(req->tc);
@@ -243,9 +256,7 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
243 return ERR_PTR(-ENOMEM); 256 return ERR_PTR(-ENOMEM);
244 } 257 }
245 req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); 258 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); 259 req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
248 req->rc->capacity = c->msize;
249 } 260 }
250 261
251 p9pdu_reset(req->tc); 262 p9pdu_reset(req->tc);
@@ -443,6 +454,7 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
443{ 454{
444 int8_t type; 455 int8_t type;
445 int err; 456 int err;
457 int ecode;
446 458
447 err = p9_parse_header(req->rc, NULL, &type, NULL, 0); 459 err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
448 if (err) { 460 if (err) {
@@ -450,36 +462,53 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
450 return err; 462 return err;
451 } 463 }
452 464
453 if (type == P9_RERROR || type == P9_RLERROR) { 465 if (type != P9_RERROR && type != P9_RLERROR)
454 int ecode; 466 return 0;
455
456 if (!p9_is_proto_dotl(c)) {
457 char *ename;
458
459 err = p9pdu_readf(req->rc, c->proto_version, "s?d",
460 &ename, &ecode);
461 if (err)
462 goto out_err;
463 467
464 if (p9_is_proto_dotu(c)) 468 if (!p9_is_proto_dotl(c)) {
465 err = -ecode; 469 char *ename;
470
471 if (req->tc->pbuf_size) {
472 /* Handle user buffers */
473 size_t len = req->rc->size - req->rc->offset;
474 if (req->tc->pubuf) {
475 /* User Buffer */
476 err = copy_from_user(
477 &req->rc->sdata[req->rc->offset],
478 req->tc->pubuf, len);
479 if (err) {
480 err = -EFAULT;
481 goto out_err;
482 }
483 } else {
484 /* Kernel Buffer */
485 memmove(&req->rc->sdata[req->rc->offset],
486 req->tc->pkbuf, len);
487 }
488 }
489 err = p9pdu_readf(req->rc, c->proto_version, "s?d",
490 &ename, &ecode);
491 if (err)
492 goto out_err;
466 493
467 if (!err || !IS_ERR_VALUE(err)) { 494 if (p9_is_proto_dotu(c))
468 err = p9_errstr2errno(ename, strlen(ename)); 495 err = -ecode;
469 496
470 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); 497 if (!err || !IS_ERR_VALUE(err)) {
498 err = p9_errstr2errno(ename, strlen(ename));
471 499
472 kfree(ename); 500 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode,
473 } 501 ename);
474 } else {
475 err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
476 err = -ecode;
477 502
478 P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); 503 kfree(ename);
479 } 504 }
505 } else {
506 err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
507 err = -ecode;
508
509 P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
510 }
480 511
481 } else
482 err = 0;
483 512
484 return err; 513 return err;
485 514
@@ -900,15 +929,15 @@ error:
900} 929}
901EXPORT_SYMBOL(p9_client_attach); 930EXPORT_SYMBOL(p9_client_attach);
902 931
903struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, 932struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
904 int clone) 933 char **wnames, int clone)
905{ 934{
906 int err; 935 int err;
907 struct p9_client *clnt; 936 struct p9_client *clnt;
908 struct p9_fid *fid; 937 struct p9_fid *fid;
909 struct p9_qid *wqids; 938 struct p9_qid *wqids;
910 struct p9_req_t *req; 939 struct p9_req_t *req;
911 int16_t nwqids, count; 940 uint16_t nwqids, count;
912 941
913 err = 0; 942 err = 0;
914 wqids = NULL; 943 wqids = NULL;
@@ -926,7 +955,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
926 fid = oldfid; 955 fid = oldfid;
927 956
928 957
929 P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n", 958 P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n",
930 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL); 959 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
931 960
932 req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid, 961 req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
@@ -1270,7 +1299,15 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1270 if (count < rsize) 1299 if (count < rsize)
1271 rsize = count; 1300 rsize = count;
1272 1301
1273 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize); 1302 /* Don't bother zerocopy form small IO (< 1024) */
1303 if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
1304 P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) {
1305 req = p9_client_rpc(clnt, P9_TREAD, "dqE", fid->fid, offset,
1306 rsize, data, udata);
1307 } else {
1308 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
1309 rsize);
1310 }
1274 if (IS_ERR(req)) { 1311 if (IS_ERR(req)) {
1275 err = PTR_ERR(req); 1312 err = PTR_ERR(req);
1276 goto error; 1313 goto error;
@@ -1284,13 +1321,15 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1284 1321
1285 P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count); 1322 P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1286 1323
1287 if (data) { 1324 if (!req->tc->pbuf_size) {
1288 memmove(data, dataptr, count); 1325 if (data) {
1289 } else { 1326 memmove(data, dataptr, count);
1290 err = copy_to_user(udata, dataptr, count); 1327 } else {
1291 if (err) { 1328 err = copy_to_user(udata, dataptr, count);
1292 err = -EFAULT; 1329 if (err) {
1293 goto free_and_error; 1330 err = -EFAULT;
1331 goto free_and_error;
1332 }
1294 } 1333 }
1295 } 1334 }
1296 p9_free_req(clnt, req); 1335 p9_free_req(clnt, req);
@@ -1323,12 +1362,21 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1323 1362
1324 if (count < rsize) 1363 if (count < rsize)
1325 rsize = count; 1364 rsize = count;
1326 if (data) 1365
1327 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset, 1366 /* Don't bother zerocopy form small IO (< 1024) */
1328 rsize, data); 1367 if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
1329 else 1368 P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) {
1330 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset, 1369 req = p9_client_rpc(clnt, P9_TWRITE, "dqE", fid->fid, offset,
1331 rsize, udata); 1370 rsize, data, udata);
1371 } else {
1372
1373 if (data)
1374 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid,
1375 offset, rsize, data);
1376 else
1377 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid,
1378 offset, rsize, udata);
1379 }
1332 if (IS_ERR(req)) { 1380 if (IS_ERR(req)) {
1333 err = PTR_ERR(req); 1381 err = PTR_ERR(req);
1334 goto error; 1382 goto error;
@@ -1716,7 +1764,14 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
1716 if (count < rsize) 1764 if (count < rsize)
1717 rsize = count; 1765 rsize = count;
1718 1766
1719 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, offset, rsize); 1767 if ((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
1768 P9_TRANS_PREF_PAYLOAD_SEP) {
1769 req = p9_client_rpc(clnt, P9_TREADDIR, "dqF", fid->fid,
1770 offset, rsize, data);
1771 } else {
1772 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid,
1773 offset, rsize);
1774 }
1720 if (IS_ERR(req)) { 1775 if (IS_ERR(req)) {
1721 err = PTR_ERR(req); 1776 err = PTR_ERR(req);
1722 goto error; 1777 goto error;
@@ -1730,7 +1785,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
1730 1785
1731 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); 1786 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
1732 1787
1733 if (data) 1788 if (!req->tc->pbuf_size && data)
1734 memmove(data, dataptr, count); 1789 memmove(data, dataptr, count);
1735 1790
1736 p9_free_req(clnt, req); 1791 p9_free_req(clnt, req);