diff options
Diffstat (limited to 'net/9p/client.c')
-rw-r--r-- | net/9p/client.c | 233 |
1 files changed, 160 insertions, 73 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 9eb72505308f..a848bca9fbff 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -61,13 +61,13 @@ static const match_table_t tokens = { | |||
61 | 61 | ||
62 | inline int p9_is_proto_dotl(struct p9_client *clnt) | 62 | inline 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 | } |
66 | EXPORT_SYMBOL(p9_is_proto_dotl); | 66 | EXPORT_SYMBOL(p9_is_proto_dotl); |
67 | 67 | ||
68 | inline int p9_is_proto_dotu(struct p9_client *clnt) | 68 | inline 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 | } |
72 | EXPORT_SYMBOL(p9_is_proto_dotu); | 72 | EXPORT_SYMBOL(p9_is_proto_dotu); |
73 | 73 | ||
@@ -450,32 +450,43 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
450 | return err; | 450 | return err; |
451 | } | 451 | } |
452 | 452 | ||
453 | if (type == P9_RERROR) { | 453 | if (type == P9_RERROR || type == P9_RLERROR) { |
454 | int ecode; | 454 | int ecode; |
455 | char *ename; | ||
456 | 455 | ||
457 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", | 456 | if (!p9_is_proto_dotl(c)) { |
458 | &ename, &ecode); | 457 | char *ename; |
459 | if (err) { | ||
460 | P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", | ||
461 | err); | ||
462 | return err; | ||
463 | } | ||
464 | 458 | ||
465 | if (p9_is_proto_dotu(c) || | 459 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", |
466 | p9_is_proto_dotl(c)) | 460 | &ename, &ecode); |
467 | err = -ecode; | 461 | if (err) |
462 | goto out_err; | ||
463 | |||
464 | if (p9_is_proto_dotu(c)) | ||
465 | err = -ecode; | ||
468 | 466 | ||
469 | if (!err || !IS_ERR_VALUE(err)) | 467 | if (!err || !IS_ERR_VALUE(err)) { |
470 | err = p9_errstr2errno(ename, strlen(ename)); | 468 | err = p9_errstr2errno(ename, strlen(ename)); |
469 | |||
470 | P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); | ||
471 | |||
472 | kfree(ename); | ||
473 | } | ||
474 | } else { | ||
475 | err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); | ||
476 | err = -ecode; | ||
471 | 477 | ||
472 | P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); | 478 | P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); |
479 | } | ||
473 | 480 | ||
474 | kfree(ename); | ||
475 | } else | 481 | } else |
476 | err = 0; | 482 | err = 0; |
477 | 483 | ||
478 | return err; | 484 | return err; |
485 | |||
486 | out_err: | ||
487 | P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); | ||
488 | |||
489 | return err; | ||
479 | } | 490 | } |
480 | 491 | ||
481 | /** | 492 | /** |
@@ -568,11 +579,14 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
568 | va_start(ap, fmt); | 579 | va_start(ap, fmt); |
569 | err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); | 580 | err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); |
570 | va_end(ap); | 581 | va_end(ap); |
582 | if (err) | ||
583 | goto reterr; | ||
571 | p9pdu_finalize(req->tc); | 584 | p9pdu_finalize(req->tc); |
572 | 585 | ||
573 | err = c->trans_mod->request(c, req); | 586 | err = c->trans_mod->request(c, req); |
574 | if (err < 0) { | 587 | if (err < 0) { |
575 | c->status = Disconnected; | 588 | if (err != -ERESTARTSYS) |
589 | c->status = Disconnected; | ||
576 | goto reterr; | 590 | goto reterr; |
577 | } | 591 | } |
578 | 592 | ||
@@ -671,7 +685,7 @@ static void p9_fid_destroy(struct p9_fid *fid) | |||
671 | kfree(fid); | 685 | kfree(fid); |
672 | } | 686 | } |
673 | 687 | ||
674 | int p9_client_version(struct p9_client *c) | 688 | static int p9_client_version(struct p9_client *c) |
675 | { | 689 | { |
676 | int err = 0; | 690 | int err = 0; |
677 | struct p9_req_t *req; | 691 | struct p9_req_t *req; |
@@ -730,7 +744,6 @@ error: | |||
730 | 744 | ||
731 | return err; | 745 | return err; |
732 | } | 746 | } |
733 | EXPORT_SYMBOL(p9_client_version); | ||
734 | 747 | ||
735 | struct p9_client *p9_client_create(const char *dev_name, char *options) | 748 | struct p9_client *p9_client_create(const char *dev_name, char *options) |
736 | { | 749 | { |
@@ -887,54 +900,6 @@ error: | |||
887 | } | 900 | } |
888 | EXPORT_SYMBOL(p9_client_attach); | 901 | EXPORT_SYMBOL(p9_client_attach); |
889 | 902 | ||
890 | struct p9_fid * | ||
891 | p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname) | ||
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 | |||
931 | error: | ||
932 | if (afid) | ||
933 | p9_fid_destroy(afid); | ||
934 | return ERR_PTR(err); | ||
935 | } | ||
936 | EXPORT_SYMBOL(p9_client_auth); | ||
937 | |||
938 | struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | 903 | struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, |
939 | int clone) | 904 | int clone) |
940 | { | 905 | { |
@@ -1200,12 +1165,44 @@ int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname) | |||
1200 | } | 1165 | } |
1201 | EXPORT_SYMBOL(p9_client_link); | 1166 | EXPORT_SYMBOL(p9_client_link); |
1202 | 1167 | ||
1168 | int p9_client_fsync(struct p9_fid *fid, int datasync) | ||
1169 | { | ||
1170 | int err; | ||
1171 | struct p9_client *clnt; | ||
1172 | struct p9_req_t *req; | ||
1173 | |||
1174 | P9_DPRINTK(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n", | ||
1175 | fid->fid, datasync); | ||
1176 | err = 0; | ||
1177 | clnt = fid->clnt; | ||
1178 | |||
1179 | req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync); | ||
1180 | if (IS_ERR(req)) { | ||
1181 | err = PTR_ERR(req); | ||
1182 | goto error; | ||
1183 | } | ||
1184 | |||
1185 | P9_DPRINTK(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid); | ||
1186 | |||
1187 | p9_free_req(clnt, req); | ||
1188 | |||
1189 | error: | ||
1190 | return err; | ||
1191 | } | ||
1192 | EXPORT_SYMBOL(p9_client_fsync); | ||
1193 | |||
1203 | int p9_client_clunk(struct p9_fid *fid) | 1194 | int p9_client_clunk(struct p9_fid *fid) |
1204 | { | 1195 | { |
1205 | int err; | 1196 | int err; |
1206 | struct p9_client *clnt; | 1197 | struct p9_client *clnt; |
1207 | struct p9_req_t *req; | 1198 | struct p9_req_t *req; |
1208 | 1199 | ||
1200 | if (!fid) { | ||
1201 | P9_EPRINTK(KERN_WARNING, "Trying to clunk with NULL fid\n"); | ||
1202 | dump_stack(); | ||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1209 | P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); | 1206 | P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); |
1210 | err = 0; | 1207 | err = 0; |
1211 | clnt = fid->clnt; | 1208 | clnt = fid->clnt; |
@@ -1289,16 +1286,13 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | |||
1289 | 1286 | ||
1290 | if (data) { | 1287 | if (data) { |
1291 | memmove(data, dataptr, count); | 1288 | memmove(data, dataptr, count); |
1292 | } | 1289 | } else { |
1293 | |||
1294 | if (udata) { | ||
1295 | err = copy_to_user(udata, dataptr, count); | 1290 | err = copy_to_user(udata, dataptr, count); |
1296 | if (err) { | 1291 | if (err) { |
1297 | err = -EFAULT; | 1292 | err = -EFAULT; |
1298 | goto free_and_error; | 1293 | goto free_and_error; |
1299 | } | 1294 | } |
1300 | } | 1295 | } |
1301 | |||
1302 | p9_free_req(clnt, req); | 1296 | p9_free_req(clnt, req); |
1303 | return count; | 1297 | return count; |
1304 | 1298 | ||
@@ -1810,3 +1804,96 @@ error: | |||
1810 | 1804 | ||
1811 | } | 1805 | } |
1812 | EXPORT_SYMBOL(p9_client_mkdir_dotl); | 1806 | EXPORT_SYMBOL(p9_client_mkdir_dotl); |
1807 | |||
1808 | int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status) | ||
1809 | { | ||
1810 | int err; | ||
1811 | struct p9_client *clnt; | ||
1812 | struct p9_req_t *req; | ||
1813 | |||
1814 | err = 0; | ||
1815 | clnt = fid->clnt; | ||
1816 | P9_DPRINTK(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d " | ||
1817 | "start %lld length %lld proc_id %d client_id %s\n", | ||
1818 | fid->fid, flock->type, flock->flags, flock->start, | ||
1819 | flock->length, flock->proc_id, flock->client_id); | ||
1820 | |||
1821 | req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type, | ||
1822 | flock->flags, flock->start, flock->length, | ||
1823 | flock->proc_id, flock->client_id); | ||
1824 | |||
1825 | if (IS_ERR(req)) | ||
1826 | return PTR_ERR(req); | ||
1827 | |||
1828 | err = p9pdu_readf(req->rc, clnt->proto_version, "b", status); | ||
1829 | if (err) { | ||
1830 | p9pdu_dump(1, req->rc); | ||
1831 | goto error; | ||
1832 | } | ||
1833 | P9_DPRINTK(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status); | ||
1834 | error: | ||
1835 | p9_free_req(clnt, req); | ||
1836 | return err; | ||
1837 | |||
1838 | } | ||
1839 | EXPORT_SYMBOL(p9_client_lock_dotl); | ||
1840 | |||
1841 | int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock) | ||
1842 | { | ||
1843 | int err; | ||
1844 | struct p9_client *clnt; | ||
1845 | struct p9_req_t *req; | ||
1846 | |||
1847 | err = 0; | ||
1848 | clnt = fid->clnt; | ||
1849 | P9_DPRINTK(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld " | ||
1850 | "length %lld proc_id %d client_id %s\n", fid->fid, glock->type, | ||
1851 | glock->start, glock->length, glock->proc_id, glock->client_id); | ||
1852 | |||
1853 | req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid, glock->type, | ||
1854 | glock->start, glock->length, glock->proc_id, glock->client_id); | ||
1855 | |||
1856 | if (IS_ERR(req)) | ||
1857 | return PTR_ERR(req); | ||
1858 | |||
1859 | err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type, | ||
1860 | &glock->start, &glock->length, &glock->proc_id, | ||
1861 | &glock->client_id); | ||
1862 | if (err) { | ||
1863 | p9pdu_dump(1, req->rc); | ||
1864 | goto error; | ||
1865 | } | ||
1866 | P9_DPRINTK(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld " | ||
1867 | "proc_id %d client_id %s\n", glock->type, glock->start, | ||
1868 | glock->length, glock->proc_id, glock->client_id); | ||
1869 | error: | ||
1870 | p9_free_req(clnt, req); | ||
1871 | return err; | ||
1872 | } | ||
1873 | EXPORT_SYMBOL(p9_client_getlock_dotl); | ||
1874 | |||
1875 | int p9_client_readlink(struct p9_fid *fid, char **target) | ||
1876 | { | ||
1877 | int err; | ||
1878 | struct p9_client *clnt; | ||
1879 | struct p9_req_t *req; | ||
1880 | |||
1881 | err = 0; | ||
1882 | clnt = fid->clnt; | ||
1883 | P9_DPRINTK(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid); | ||
1884 | |||
1885 | req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid); | ||
1886 | if (IS_ERR(req)) | ||
1887 | return PTR_ERR(req); | ||
1888 | |||
1889 | err = p9pdu_readf(req->rc, clnt->proto_version, "s", target); | ||
1890 | if (err) { | ||
1891 | p9pdu_dump(1, req->rc); | ||
1892 | goto error; | ||
1893 | } | ||
1894 | P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target); | ||
1895 | error: | ||
1896 | p9_free_req(clnt, req); | ||
1897 | return err; | ||
1898 | } | ||
1899 | EXPORT_SYMBOL(p9_client_readlink); | ||