diff options
Diffstat (limited to 'net/9p/client.c')
| -rw-r--r-- | net/9p/client.c | 178 |
1 files changed, 157 insertions, 21 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 83bf0541d66f..a848bca9fbff 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
| @@ -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; | ||
| 466 | |||
| 467 | if (!err || !IS_ERR_VALUE(err)) { | ||
| 468 | err = p9_errstr2errno(ename, strlen(ename)); | ||
| 469 | |||
| 470 | P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); | ||
| 468 | 471 | ||
| 469 | if (!err || !IS_ERR_VALUE(err)) | 472 | kfree(ename); |
| 470 | err = p9_errstr2errno(ename, strlen(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 | ||
| @@ -1151,12 +1165,44 @@ int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname) | |||
| 1151 | } | 1165 | } |
| 1152 | EXPORT_SYMBOL(p9_client_link); | 1166 | EXPORT_SYMBOL(p9_client_link); |
| 1153 | 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 | |||
| 1154 | int p9_client_clunk(struct p9_fid *fid) | 1194 | int p9_client_clunk(struct p9_fid *fid) |
| 1155 | { | 1195 | { |
| 1156 | int err; | 1196 | int err; |
| 1157 | struct p9_client *clnt; | 1197 | struct p9_client *clnt; |
| 1158 | struct p9_req_t *req; | 1198 | struct p9_req_t *req; |
| 1159 | 1199 | ||
| 1200 | if (!fid) { | ||
| 1201 | P9_EPRINTK(KERN_WARNING, "Trying to clunk with NULL fid\n"); | ||
| 1202 | dump_stack(); | ||
| 1203 | return 0; | ||
| 1204 | } | ||
| 1205 | |||
| 1160 | P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); | 1206 | P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); |
| 1161 | err = 0; | 1207 | err = 0; |
| 1162 | clnt = fid->clnt; | 1208 | clnt = fid->clnt; |
| @@ -1240,16 +1286,13 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | |||
| 1240 | 1286 | ||
| 1241 | if (data) { | 1287 | if (data) { |
| 1242 | memmove(data, dataptr, count); | 1288 | memmove(data, dataptr, count); |
| 1243 | } | 1289 | } else { |
| 1244 | |||
| 1245 | if (udata) { | ||
| 1246 | err = copy_to_user(udata, dataptr, count); | 1290 | err = copy_to_user(udata, dataptr, count); |
| 1247 | if (err) { | 1291 | if (err) { |
| 1248 | err = -EFAULT; | 1292 | err = -EFAULT; |
| 1249 | goto free_and_error; | 1293 | goto free_and_error; |
| 1250 | } | 1294 | } |
| 1251 | } | 1295 | } |
| 1252 | |||
| 1253 | p9_free_req(clnt, req); | 1296 | p9_free_req(clnt, req); |
| 1254 | return count; | 1297 | return count; |
| 1255 | 1298 | ||
| @@ -1761,3 +1804,96 @@ error: | |||
| 1761 | 1804 | ||
| 1762 | } | 1805 | } |
| 1763 | 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); | ||
