diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 113 |
1 files changed, 71 insertions, 42 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index cb4376b78ed9..e23a0a664e12 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -946,7 +946,10 @@ static void encode_uint64(struct xdr_stream *xdr, u64 n) | |||
| 946 | static void encode_nfs4_seqid(struct xdr_stream *xdr, | 946 | static void encode_nfs4_seqid(struct xdr_stream *xdr, |
| 947 | const struct nfs_seqid *seqid) | 947 | const struct nfs_seqid *seqid) |
| 948 | { | 948 | { |
| 949 | encode_uint32(xdr, seqid->sequence->counter); | 949 | if (seqid != NULL) |
| 950 | encode_uint32(xdr, seqid->sequence->counter); | ||
| 951 | else | ||
| 952 | encode_uint32(xdr, 0); | ||
| 950 | } | 953 | } |
| 951 | 954 | ||
| 952 | static void encode_compound_hdr(struct xdr_stream *xdr, | 955 | static void encode_compound_hdr(struct xdr_stream *xdr, |
| @@ -1125,7 +1128,7 @@ static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg | |||
| 1125 | { | 1128 | { |
| 1126 | encode_op_hdr(xdr, OP_CLOSE, decode_close_maxsz, hdr); | 1129 | encode_op_hdr(xdr, OP_CLOSE, decode_close_maxsz, hdr); |
| 1127 | encode_nfs4_seqid(xdr, arg->seqid); | 1130 | encode_nfs4_seqid(xdr, arg->seqid); |
| 1128 | encode_nfs4_stateid(xdr, arg->stateid); | 1131 | encode_nfs4_stateid(xdr, &arg->stateid); |
| 1129 | } | 1132 | } |
| 1130 | 1133 | ||
| 1131 | static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr) | 1134 | static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr) |
| @@ -1301,12 +1304,12 @@ static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args | |||
| 1301 | *p = cpu_to_be32(args->new_lock_owner); | 1304 | *p = cpu_to_be32(args->new_lock_owner); |
| 1302 | if (args->new_lock_owner){ | 1305 | if (args->new_lock_owner){ |
| 1303 | encode_nfs4_seqid(xdr, args->open_seqid); | 1306 | encode_nfs4_seqid(xdr, args->open_seqid); |
| 1304 | encode_nfs4_stateid(xdr, args->open_stateid); | 1307 | encode_nfs4_stateid(xdr, &args->open_stateid); |
| 1305 | encode_nfs4_seqid(xdr, args->lock_seqid); | 1308 | encode_nfs4_seqid(xdr, args->lock_seqid); |
| 1306 | encode_lockowner(xdr, &args->lock_owner); | 1309 | encode_lockowner(xdr, &args->lock_owner); |
| 1307 | } | 1310 | } |
| 1308 | else { | 1311 | else { |
| 1309 | encode_nfs4_stateid(xdr, args->lock_stateid); | 1312 | encode_nfs4_stateid(xdr, &args->lock_stateid); |
| 1310 | encode_nfs4_seqid(xdr, args->lock_seqid); | 1313 | encode_nfs4_seqid(xdr, args->lock_seqid); |
| 1311 | } | 1314 | } |
| 1312 | } | 1315 | } |
| @@ -1330,7 +1333,7 @@ static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *ar | |||
| 1330 | encode_op_hdr(xdr, OP_LOCKU, decode_locku_maxsz, hdr); | 1333 | encode_op_hdr(xdr, OP_LOCKU, decode_locku_maxsz, hdr); |
| 1331 | encode_uint32(xdr, nfs4_lock_type(args->fl, 0)); | 1334 | encode_uint32(xdr, nfs4_lock_type(args->fl, 0)); |
| 1332 | encode_nfs4_seqid(xdr, args->seqid); | 1335 | encode_nfs4_seqid(xdr, args->seqid); |
| 1333 | encode_nfs4_stateid(xdr, args->stateid); | 1336 | encode_nfs4_stateid(xdr, &args->stateid); |
| 1334 | p = reserve_space(xdr, 16); | 1337 | p = reserve_space(xdr, 16); |
| 1335 | p = xdr_encode_hyper(p, args->fl->fl_start); | 1338 | p = xdr_encode_hyper(p, args->fl->fl_start); |
| 1336 | xdr_encode_hyper(p, nfs4_lock_length(args->fl)); | 1339 | xdr_encode_hyper(p, nfs4_lock_length(args->fl)); |
| @@ -1348,24 +1351,12 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc | |||
| 1348 | encode_string(xdr, name->len, name->name); | 1351 | encode_string(xdr, name->len, name->name); |
| 1349 | } | 1352 | } |
| 1350 | 1353 | ||
| 1351 | static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode) | 1354 | static void encode_share_access(struct xdr_stream *xdr, u32 share_access) |
| 1352 | { | 1355 | { |
| 1353 | __be32 *p; | 1356 | __be32 *p; |
| 1354 | 1357 | ||
| 1355 | p = reserve_space(xdr, 8); | 1358 | p = reserve_space(xdr, 8); |
| 1356 | switch (fmode & (FMODE_READ|FMODE_WRITE)) { | 1359 | *p++ = cpu_to_be32(share_access); |
| 1357 | case FMODE_READ: | ||
| 1358 | *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ); | ||
| 1359 | break; | ||
| 1360 | case FMODE_WRITE: | ||
| 1361 | *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE); | ||
| 1362 | break; | ||
| 1363 | case FMODE_READ|FMODE_WRITE: | ||
| 1364 | *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH); | ||
| 1365 | break; | ||
| 1366 | default: | ||
| 1367 | *p++ = cpu_to_be32(0); | ||
| 1368 | } | ||
| 1369 | *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */ | 1360 | *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */ |
| 1370 | } | 1361 | } |
| 1371 | 1362 | ||
| @@ -1377,7 +1368,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena | |||
| 1377 | * owner 4 = 32 | 1368 | * owner 4 = 32 |
| 1378 | */ | 1369 | */ |
| 1379 | encode_nfs4_seqid(xdr, arg->seqid); | 1370 | encode_nfs4_seqid(xdr, arg->seqid); |
| 1380 | encode_share_access(xdr, arg->fmode); | 1371 | encode_share_access(xdr, arg->share_access); |
| 1381 | p = reserve_space(xdr, 36); | 1372 | p = reserve_space(xdr, 36); |
| 1382 | p = xdr_encode_hyper(p, arg->clientid); | 1373 | p = xdr_encode_hyper(p, arg->clientid); |
| 1383 | *p++ = cpu_to_be32(24); | 1374 | *p++ = cpu_to_be32(24); |
| @@ -1530,9 +1521,9 @@ static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_co | |||
| 1530 | static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) | 1521 | static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) |
| 1531 | { | 1522 | { |
| 1532 | encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr); | 1523 | encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr); |
| 1533 | encode_nfs4_stateid(xdr, arg->stateid); | 1524 | encode_nfs4_stateid(xdr, &arg->stateid); |
| 1534 | encode_nfs4_seqid(xdr, arg->seqid); | 1525 | encode_nfs4_seqid(xdr, arg->seqid); |
| 1535 | encode_share_access(xdr, arg->fmode); | 1526 | encode_share_access(xdr, arg->share_access); |
| 1536 | } | 1527 | } |
| 1537 | 1528 | ||
| 1538 | static void | 1529 | static void |
| @@ -1801,9 +1792,8 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
| 1801 | struct compound_hdr *hdr) | 1792 | struct compound_hdr *hdr) |
| 1802 | { | 1793 | { |
| 1803 | __be32 *p; | 1794 | __be32 *p; |
| 1804 | char machine_name[NFS4_MAX_MACHINE_NAME_LEN]; | ||
| 1805 | uint32_t len; | ||
| 1806 | struct nfs_client *clp = args->client; | 1795 | struct nfs_client *clp = args->client; |
| 1796 | struct rpc_clnt *clnt = clp->cl_rpcclient; | ||
| 1807 | struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); | 1797 | struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); |
| 1808 | u32 max_resp_sz_cached; | 1798 | u32 max_resp_sz_cached; |
| 1809 | 1799 | ||
| @@ -1814,11 +1804,8 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
| 1814 | max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + | 1804 | max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + |
| 1815 | RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT; | 1805 | RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT; |
| 1816 | 1806 | ||
| 1817 | len = scnprintf(machine_name, sizeof(machine_name), "%s", | ||
| 1818 | clp->cl_ipaddr); | ||
| 1819 | |||
| 1820 | encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr); | 1807 | encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr); |
| 1821 | p = reserve_space(xdr, 16 + 2*28 + 20 + len + 12); | 1808 | p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12); |
| 1822 | p = xdr_encode_hyper(p, clp->cl_clientid); | 1809 | p = xdr_encode_hyper(p, clp->cl_clientid); |
| 1823 | *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ | 1810 | *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ |
| 1824 | *p++ = cpu_to_be32(args->flags); /*flags */ | 1811 | *p++ = cpu_to_be32(args->flags); /*flags */ |
| @@ -1847,7 +1834,7 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
| 1847 | 1834 | ||
| 1848 | /* authsys_parms rfc1831 */ | 1835 | /* authsys_parms rfc1831 */ |
| 1849 | *p++ = cpu_to_be32(nn->boot_time.tv_nsec); /* stamp */ | 1836 | *p++ = cpu_to_be32(nn->boot_time.tv_nsec); /* stamp */ |
| 1850 | p = xdr_encode_opaque(p, machine_name, len); | 1837 | p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen); |
| 1851 | *p++ = cpu_to_be32(0); /* UID */ | 1838 | *p++ = cpu_to_be32(0); /* UID */ |
| 1852 | *p++ = cpu_to_be32(0); /* GID */ | 1839 | *p++ = cpu_to_be32(0); /* GID */ |
| 1853 | *p = cpu_to_be32(0); /* No more gids */ | 1840 | *p = cpu_to_be32(0); /* No more gids */ |
| @@ -2012,11 +1999,11 @@ encode_layoutreturn(struct xdr_stream *xdr, | |||
| 2012 | p = reserve_space(xdr, 16); | 1999 | p = reserve_space(xdr, 16); |
| 2013 | *p++ = cpu_to_be32(0); /* reclaim. always 0 for now */ | 2000 | *p++ = cpu_to_be32(0); /* reclaim. always 0 for now */ |
| 2014 | *p++ = cpu_to_be32(args->layout_type); | 2001 | *p++ = cpu_to_be32(args->layout_type); |
| 2015 | *p++ = cpu_to_be32(IOMODE_ANY); | 2002 | *p++ = cpu_to_be32(args->range.iomode); |
| 2016 | *p = cpu_to_be32(RETURN_FILE); | 2003 | *p = cpu_to_be32(RETURN_FILE); |
| 2017 | p = reserve_space(xdr, 16); | 2004 | p = reserve_space(xdr, 16); |
| 2018 | p = xdr_encode_hyper(p, 0); | 2005 | p = xdr_encode_hyper(p, args->range.offset); |
| 2019 | p = xdr_encode_hyper(p, NFS4_MAX_UINT64); | 2006 | p = xdr_encode_hyper(p, args->range.length); |
| 2020 | spin_lock(&args->inode->i_lock); | 2007 | spin_lock(&args->inode->i_lock); |
| 2021 | encode_nfs4_stateid(xdr, &args->stateid); | 2008 | encode_nfs4_stateid(xdr, &args->stateid); |
| 2022 | spin_unlock(&args->inode->i_lock); | 2009 | spin_unlock(&args->inode->i_lock); |
| @@ -4936,20 +4923,13 @@ out_overflow: | |||
| 4936 | return -EIO; | 4923 | return -EIO; |
| 4937 | } | 4924 | } |
| 4938 | 4925 | ||
| 4939 | static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | 4926 | static int decode_rw_delegation(struct xdr_stream *xdr, |
| 4927 | uint32_t delegation_type, | ||
| 4928 | struct nfs_openres *res) | ||
| 4940 | { | 4929 | { |
| 4941 | __be32 *p; | 4930 | __be32 *p; |
| 4942 | uint32_t delegation_type; | ||
| 4943 | int status; | 4931 | int status; |
| 4944 | 4932 | ||
| 4945 | p = xdr_inline_decode(xdr, 4); | ||
| 4946 | if (unlikely(!p)) | ||
| 4947 | goto out_overflow; | ||
| 4948 | delegation_type = be32_to_cpup(p); | ||
| 4949 | if (delegation_type == NFS4_OPEN_DELEGATE_NONE) { | ||
| 4950 | res->delegation_type = 0; | ||
| 4951 | return 0; | ||
| 4952 | } | ||
| 4953 | status = decode_stateid(xdr, &res->delegation); | 4933 | status = decode_stateid(xdr, &res->delegation); |
| 4954 | if (unlikely(status)) | 4934 | if (unlikely(status)) |
| 4955 | return status; | 4935 | return status; |
| @@ -4973,6 +4953,52 @@ out_overflow: | |||
| 4973 | return -EIO; | 4953 | return -EIO; |
| 4974 | } | 4954 | } |
| 4975 | 4955 | ||
| 4956 | static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | ||
| 4957 | { | ||
| 4958 | __be32 *p; | ||
| 4959 | uint32_t why_no_delegation; | ||
| 4960 | |||
| 4961 | p = xdr_inline_decode(xdr, 4); | ||
| 4962 | if (unlikely(!p)) | ||
| 4963 | goto out_overflow; | ||
| 4964 | why_no_delegation = be32_to_cpup(p); | ||
| 4965 | switch (why_no_delegation) { | ||
| 4966 | case WND4_CONTENTION: | ||
| 4967 | case WND4_RESOURCE: | ||
| 4968 | xdr_inline_decode(xdr, 4); | ||
| 4969 | /* Ignore for now */ | ||
| 4970 | } | ||
| 4971 | return 0; | ||
| 4972 | out_overflow: | ||
| 4973 | print_overflow_msg(__func__, xdr); | ||
| 4974 | return -EIO; | ||
| 4975 | } | ||
| 4976 | |||
| 4977 | static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | ||
| 4978 | { | ||
| 4979 | __be32 *p; | ||
| 4980 | uint32_t delegation_type; | ||
| 4981 | |||
| 4982 | p = xdr_inline_decode(xdr, 4); | ||
| 4983 | if (unlikely(!p)) | ||
| 4984 | goto out_overflow; | ||
| 4985 | delegation_type = be32_to_cpup(p); | ||
| 4986 | res->delegation_type = 0; | ||
| 4987 | switch (delegation_type) { | ||
| 4988 | case NFS4_OPEN_DELEGATE_NONE: | ||
| 4989 | return 0; | ||
| 4990 | case NFS4_OPEN_DELEGATE_READ: | ||
| 4991 | case NFS4_OPEN_DELEGATE_WRITE: | ||
| 4992 | return decode_rw_delegation(xdr, delegation_type, res); | ||
| 4993 | case NFS4_OPEN_DELEGATE_NONE_EXT: | ||
| 4994 | return decode_no_delegation(xdr, res); | ||
| 4995 | } | ||
| 4996 | return -EIO; | ||
| 4997 | out_overflow: | ||
| 4998 | print_overflow_msg(__func__, xdr); | ||
| 4999 | return -EIO; | ||
| 5000 | } | ||
| 5001 | |||
| 4976 | static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | 5002 | static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) |
| 4977 | { | 5003 | { |
| 4978 | __be32 *p; | 5004 | __be32 *p; |
| @@ -6567,6 +6593,7 @@ static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
| 6567 | int status; | 6593 | int status; |
| 6568 | 6594 | ||
| 6569 | status = decode_compound_hdr(xdr, &hdr); | 6595 | status = decode_compound_hdr(xdr, &hdr); |
| 6596 | res->op_status = hdr.status; | ||
| 6570 | if (status) | 6597 | if (status) |
| 6571 | goto out; | 6598 | goto out; |
| 6572 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6599 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
| @@ -6592,6 +6619,7 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
| 6592 | int status; | 6619 | int status; |
| 6593 | 6620 | ||
| 6594 | status = decode_compound_hdr(xdr, &hdr); | 6621 | status = decode_compound_hdr(xdr, &hdr); |
| 6622 | res->op_status = hdr.status; | ||
| 6595 | if (status) | 6623 | if (status) |
| 6596 | goto out; | 6624 | goto out; |
| 6597 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6625 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
| @@ -6621,6 +6649,7 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
| 6621 | int status; | 6649 | int status; |
| 6622 | 6650 | ||
| 6623 | status = decode_compound_hdr(xdr, &hdr); | 6651 | status = decode_compound_hdr(xdr, &hdr); |
| 6652 | res->op_status = hdr.status; | ||
| 6624 | if (status) | 6653 | if (status) |
| 6625 | goto out; | 6654 | goto out; |
| 6626 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6655 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
