diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 452 |
1 files changed, 336 insertions, 116 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c74fdb114b48..ee4a74db95d0 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -53,9 +53,11 @@ | |||
53 | #include <linux/nfs4.h> | 53 | #include <linux/nfs4.h> |
54 | #include <linux/nfs_fs.h> | 54 | #include <linux/nfs_fs.h> |
55 | #include <linux/nfs_idmap.h> | 55 | #include <linux/nfs_idmap.h> |
56 | |||
56 | #include "nfs4_fs.h" | 57 | #include "nfs4_fs.h" |
57 | #include "internal.h" | 58 | #include "internal.h" |
58 | #include "pnfs.h" | 59 | #include "pnfs.h" |
60 | #include "netns.h" | ||
59 | 61 | ||
60 | #define NFSDBG_FACILITY NFSDBG_XDR | 62 | #define NFSDBG_FACILITY NFSDBG_XDR |
61 | 63 | ||
@@ -74,7 +76,7 @@ static int nfs4_stat_to_errno(int); | |||
74 | /* lock,open owner id: | 76 | /* lock,open owner id: |
75 | * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) | 77 | * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) |
76 | */ | 78 | */ |
77 | #define open_owner_id_maxsz (1 + 1 + 4) | 79 | #define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2) |
78 | #define lock_owner_id_maxsz (1 + 1 + 4) | 80 | #define lock_owner_id_maxsz (1 + 1 + 4) |
79 | #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 81 | #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
80 | #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) | 82 | #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) |
@@ -99,9 +101,12 @@ static int nfs4_stat_to_errno(int); | |||
99 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) | 101 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) |
100 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 102 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
101 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 103 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
104 | /* We support only one layout type per file system */ | ||
105 | #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) | ||
102 | /* This is based on getfattr, which uses the most attributes: */ | 106 | /* This is based on getfattr, which uses the most attributes: */ |
103 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ | 107 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ |
104 | 3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz)) | 108 | 3 + 3 + 3 + nfs4_owner_maxsz + \ |
109 | nfs4_group_maxsz + decode_mdsthreshold_maxsz)) | ||
105 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ | 110 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ |
106 | nfs4_fattr_value_maxsz) | 111 | nfs4_fattr_value_maxsz) |
107 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) | 112 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) |
@@ -321,8 +326,20 @@ static int nfs4_stat_to_errno(int); | |||
321 | 1 /* csr_flags */ + \ | 326 | 1 /* csr_flags */ + \ |
322 | decode_channel_attrs_maxsz + \ | 327 | decode_channel_attrs_maxsz + \ |
323 | decode_channel_attrs_maxsz) | 328 | decode_channel_attrs_maxsz) |
329 | #define encode_bind_conn_to_session_maxsz (op_encode_hdr_maxsz + \ | ||
330 | /* bctsa_sessid */ \ | ||
331 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ | ||
332 | 1 /* bctsa_dir */ + \ | ||
333 | 1 /* bctsa_use_conn_in_rdma_mode */) | ||
334 | #define decode_bind_conn_to_session_maxsz (op_decode_hdr_maxsz + \ | ||
335 | /* bctsr_sessid */ \ | ||
336 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ | ||
337 | 1 /* bctsr_dir */ + \ | ||
338 | 1 /* bctsr_use_conn_in_rdma_mode */) | ||
324 | #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) | 339 | #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) |
325 | #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) | 340 | #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) |
341 | #define encode_destroy_clientid_maxsz (op_encode_hdr_maxsz + 2) | ||
342 | #define decode_destroy_clientid_maxsz (op_decode_hdr_maxsz) | ||
326 | #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ | 343 | #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ |
327 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) | 344 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) |
328 | #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ | 345 | #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ |
@@ -421,30 +438,22 @@ static int nfs4_stat_to_errno(int); | |||
421 | #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ | 438 | #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ |
422 | encode_sequence_maxsz + \ | 439 | encode_sequence_maxsz + \ |
423 | encode_putfh_maxsz + \ | 440 | encode_putfh_maxsz + \ |
424 | encode_commit_maxsz + \ | 441 | encode_commit_maxsz) |
425 | encode_getattr_maxsz) | ||
426 | #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ | 442 | #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ |
427 | decode_sequence_maxsz + \ | 443 | decode_sequence_maxsz + \ |
428 | decode_putfh_maxsz + \ | 444 | decode_putfh_maxsz + \ |
429 | decode_commit_maxsz + \ | 445 | decode_commit_maxsz) |
430 | decode_getattr_maxsz) | ||
431 | #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ | 446 | #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ |
432 | encode_sequence_maxsz + \ | 447 | encode_sequence_maxsz + \ |
433 | encode_putfh_maxsz + \ | 448 | encode_putfh_maxsz + \ |
434 | encode_savefh_maxsz + \ | ||
435 | encode_open_maxsz + \ | 449 | encode_open_maxsz + \ |
436 | encode_getfh_maxsz + \ | 450 | encode_getfh_maxsz + \ |
437 | encode_getattr_maxsz + \ | ||
438 | encode_restorefh_maxsz + \ | ||
439 | encode_getattr_maxsz) | 451 | encode_getattr_maxsz) |
440 | #define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ | 452 | #define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ |
441 | decode_sequence_maxsz + \ | 453 | decode_sequence_maxsz + \ |
442 | decode_putfh_maxsz + \ | 454 | decode_putfh_maxsz + \ |
443 | decode_savefh_maxsz + \ | ||
444 | decode_open_maxsz + \ | 455 | decode_open_maxsz + \ |
445 | decode_getfh_maxsz + \ | 456 | decode_getfh_maxsz + \ |
446 | decode_getattr_maxsz + \ | ||
447 | decode_restorefh_maxsz + \ | ||
448 | decode_getattr_maxsz) | 457 | decode_getattr_maxsz) |
449 | #define NFS4_enc_open_confirm_sz \ | 458 | #define NFS4_enc_open_confirm_sz \ |
450 | (compound_encode_hdr_maxsz + \ | 459 | (compound_encode_hdr_maxsz + \ |
@@ -595,47 +604,37 @@ static int nfs4_stat_to_errno(int); | |||
595 | #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ | 604 | #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ |
596 | encode_sequence_maxsz + \ | 605 | encode_sequence_maxsz + \ |
597 | encode_putfh_maxsz + \ | 606 | encode_putfh_maxsz + \ |
598 | encode_remove_maxsz + \ | 607 | encode_remove_maxsz) |
599 | encode_getattr_maxsz) | ||
600 | #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ | 608 | #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ |
601 | decode_sequence_maxsz + \ | 609 | decode_sequence_maxsz + \ |
602 | decode_putfh_maxsz + \ | 610 | decode_putfh_maxsz + \ |
603 | decode_remove_maxsz + \ | 611 | decode_remove_maxsz) |
604 | decode_getattr_maxsz) | ||
605 | #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ | 612 | #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ |
606 | encode_sequence_maxsz + \ | 613 | encode_sequence_maxsz + \ |
607 | encode_putfh_maxsz + \ | 614 | encode_putfh_maxsz + \ |
608 | encode_savefh_maxsz + \ | 615 | encode_savefh_maxsz + \ |
609 | encode_putfh_maxsz + \ | 616 | encode_putfh_maxsz + \ |
610 | encode_rename_maxsz + \ | 617 | encode_rename_maxsz) |
611 | encode_getattr_maxsz + \ | ||
612 | encode_restorefh_maxsz + \ | ||
613 | encode_getattr_maxsz) | ||
614 | #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ | 618 | #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ |
615 | decode_sequence_maxsz + \ | 619 | decode_sequence_maxsz + \ |
616 | decode_putfh_maxsz + \ | 620 | decode_putfh_maxsz + \ |
617 | decode_savefh_maxsz + \ | 621 | decode_savefh_maxsz + \ |
618 | decode_putfh_maxsz + \ | 622 | decode_putfh_maxsz + \ |
619 | decode_rename_maxsz + \ | 623 | decode_rename_maxsz) |
620 | decode_getattr_maxsz + \ | ||
621 | decode_restorefh_maxsz + \ | ||
622 | decode_getattr_maxsz) | ||
623 | #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ | 624 | #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ |
624 | encode_sequence_maxsz + \ | 625 | encode_sequence_maxsz + \ |
625 | encode_putfh_maxsz + \ | 626 | encode_putfh_maxsz + \ |
626 | encode_savefh_maxsz + \ | 627 | encode_savefh_maxsz + \ |
627 | encode_putfh_maxsz + \ | 628 | encode_putfh_maxsz + \ |
628 | encode_link_maxsz + \ | 629 | encode_link_maxsz + \ |
629 | decode_getattr_maxsz + \ | ||
630 | encode_restorefh_maxsz + \ | 630 | encode_restorefh_maxsz + \ |
631 | decode_getattr_maxsz) | 631 | encode_getattr_maxsz) |
632 | #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ | 632 | #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ |
633 | decode_sequence_maxsz + \ | 633 | decode_sequence_maxsz + \ |
634 | decode_putfh_maxsz + \ | 634 | decode_putfh_maxsz + \ |
635 | decode_savefh_maxsz + \ | 635 | decode_savefh_maxsz + \ |
636 | decode_putfh_maxsz + \ | 636 | decode_putfh_maxsz + \ |
637 | decode_link_maxsz + \ | 637 | decode_link_maxsz + \ |
638 | decode_getattr_maxsz + \ | ||
639 | decode_restorefh_maxsz + \ | 638 | decode_restorefh_maxsz + \ |
640 | decode_getattr_maxsz) | 639 | decode_getattr_maxsz) |
641 | #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ | 640 | #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ |
@@ -653,20 +652,14 @@ static int nfs4_stat_to_errno(int); | |||
653 | #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ | 652 | #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ |
654 | encode_sequence_maxsz + \ | 653 | encode_sequence_maxsz + \ |
655 | encode_putfh_maxsz + \ | 654 | encode_putfh_maxsz + \ |
656 | encode_savefh_maxsz + \ | ||
657 | encode_create_maxsz + \ | 655 | encode_create_maxsz + \ |
658 | encode_getfh_maxsz + \ | 656 | encode_getfh_maxsz + \ |
659 | encode_getattr_maxsz + \ | ||
660 | encode_restorefh_maxsz + \ | ||
661 | encode_getattr_maxsz) | 657 | encode_getattr_maxsz) |
662 | #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ | 658 | #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ |
663 | decode_sequence_maxsz + \ | 659 | decode_sequence_maxsz + \ |
664 | decode_putfh_maxsz + \ | 660 | decode_putfh_maxsz + \ |
665 | decode_savefh_maxsz + \ | ||
666 | decode_create_maxsz + \ | 661 | decode_create_maxsz + \ |
667 | decode_getfh_maxsz + \ | 662 | decode_getfh_maxsz + \ |
668 | decode_getattr_maxsz + \ | ||
669 | decode_restorefh_maxsz + \ | ||
670 | decode_getattr_maxsz) | 663 | decode_getattr_maxsz) |
671 | #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ | 664 | #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ |
672 | encode_sequence_maxsz + \ | 665 | encode_sequence_maxsz + \ |
@@ -738,6 +731,12 @@ static int nfs4_stat_to_errno(int); | |||
738 | decode_putfh_maxsz + \ | 731 | decode_putfh_maxsz + \ |
739 | decode_secinfo_maxsz) | 732 | decode_secinfo_maxsz) |
740 | #if defined(CONFIG_NFS_V4_1) | 733 | #if defined(CONFIG_NFS_V4_1) |
734 | #define NFS4_enc_bind_conn_to_session_sz \ | ||
735 | (compound_encode_hdr_maxsz + \ | ||
736 | encode_bind_conn_to_session_maxsz) | ||
737 | #define NFS4_dec_bind_conn_to_session_sz \ | ||
738 | (compound_decode_hdr_maxsz + \ | ||
739 | decode_bind_conn_to_session_maxsz) | ||
741 | #define NFS4_enc_exchange_id_sz \ | 740 | #define NFS4_enc_exchange_id_sz \ |
742 | (compound_encode_hdr_maxsz + \ | 741 | (compound_encode_hdr_maxsz + \ |
743 | encode_exchange_id_maxsz) | 742 | encode_exchange_id_maxsz) |
@@ -754,6 +753,10 @@ static int nfs4_stat_to_errno(int); | |||
754 | encode_destroy_session_maxsz) | 753 | encode_destroy_session_maxsz) |
755 | #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ | 754 | #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ |
756 | decode_destroy_session_maxsz) | 755 | decode_destroy_session_maxsz) |
756 | #define NFS4_enc_destroy_clientid_sz (compound_encode_hdr_maxsz + \ | ||
757 | encode_destroy_clientid_maxsz) | ||
758 | #define NFS4_dec_destroy_clientid_sz (compound_decode_hdr_maxsz + \ | ||
759 | decode_destroy_clientid_maxsz) | ||
757 | #define NFS4_enc_sequence_sz \ | 760 | #define NFS4_enc_sequence_sz \ |
758 | (compound_decode_hdr_maxsz + \ | 761 | (compound_decode_hdr_maxsz + \ |
759 | encode_sequence_maxsz) | 762 | encode_sequence_maxsz) |
@@ -1103,7 +1106,7 @@ static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg | |||
1103 | encode_nfs4_stateid(xdr, arg->stateid); | 1106 | encode_nfs4_stateid(xdr, arg->stateid); |
1104 | } | 1107 | } |
1105 | 1108 | ||
1106 | static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) | 1109 | static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr) |
1107 | { | 1110 | { |
1108 | __be32 *p; | 1111 | __be32 *p; |
1109 | 1112 | ||
@@ -1194,6 +1197,16 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c | |||
1194 | bitmask[1] & nfs4_fattr_bitmap[1], hdr); | 1197 | bitmask[1] & nfs4_fattr_bitmap[1], hdr); |
1195 | } | 1198 | } |
1196 | 1199 | ||
1200 | static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, | ||
1201 | struct compound_hdr *hdr) | ||
1202 | { | ||
1203 | encode_getattr_three(xdr, | ||
1204 | bitmask[0] & nfs4_fattr_bitmap[0], | ||
1205 | bitmask[1] & nfs4_fattr_bitmap[1], | ||
1206 | bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD, | ||
1207 | hdr); | ||
1208 | } | ||
1209 | |||
1197 | static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1210 | static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1198 | { | 1211 | { |
1199 | encode_getattr_three(xdr, | 1212 | encode_getattr_three(xdr, |
@@ -1340,12 +1353,13 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena | |||
1340 | */ | 1353 | */ |
1341 | encode_nfs4_seqid(xdr, arg->seqid); | 1354 | encode_nfs4_seqid(xdr, arg->seqid); |
1342 | encode_share_access(xdr, arg->fmode); | 1355 | encode_share_access(xdr, arg->fmode); |
1343 | p = reserve_space(xdr, 32); | 1356 | p = reserve_space(xdr, 36); |
1344 | p = xdr_encode_hyper(p, arg->clientid); | 1357 | p = xdr_encode_hyper(p, arg->clientid); |
1345 | *p++ = cpu_to_be32(20); | 1358 | *p++ = cpu_to_be32(24); |
1346 | p = xdr_encode_opaque_fixed(p, "open id:", 8); | 1359 | p = xdr_encode_opaque_fixed(p, "open id:", 8); |
1347 | *p++ = cpu_to_be32(arg->server->s_dev); | 1360 | *p++ = cpu_to_be32(arg->server->s_dev); |
1348 | xdr_encode_hyper(p, arg->id); | 1361 | *p++ = cpu_to_be32(arg->id.uniquifier); |
1362 | xdr_encode_hyper(p, arg->id.create_time); | ||
1349 | } | 1363 | } |
1350 | 1364 | ||
1351 | static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) | 1365 | static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) |
@@ -1677,6 +1691,20 @@ static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, stru | |||
1677 | 1691 | ||
1678 | #if defined(CONFIG_NFS_V4_1) | 1692 | #if defined(CONFIG_NFS_V4_1) |
1679 | /* NFSv4.1 operations */ | 1693 | /* NFSv4.1 operations */ |
1694 | static void encode_bind_conn_to_session(struct xdr_stream *xdr, | ||
1695 | struct nfs4_session *session, | ||
1696 | struct compound_hdr *hdr) | ||
1697 | { | ||
1698 | __be32 *p; | ||
1699 | |||
1700 | encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION, | ||
1701 | decode_bind_conn_to_session_maxsz, hdr); | ||
1702 | encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); | ||
1703 | p = xdr_reserve_space(xdr, 8); | ||
1704 | *p++ = cpu_to_be32(NFS4_CDFC4_BACK_OR_BOTH); | ||
1705 | *p = 0; /* use_conn_in_rdma_mode = False */ | ||
1706 | } | ||
1707 | |||
1680 | static void encode_exchange_id(struct xdr_stream *xdr, | 1708 | static void encode_exchange_id(struct xdr_stream *xdr, |
1681 | struct nfs41_exchange_id_args *args, | 1709 | struct nfs41_exchange_id_args *args, |
1682 | struct compound_hdr *hdr) | 1710 | struct compound_hdr *hdr) |
@@ -1725,6 +1753,7 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
1725 | char machine_name[NFS4_MAX_MACHINE_NAME_LEN]; | 1753 | char machine_name[NFS4_MAX_MACHINE_NAME_LEN]; |
1726 | uint32_t len; | 1754 | uint32_t len; |
1727 | struct nfs_client *clp = args->client; | 1755 | struct nfs_client *clp = args->client; |
1756 | struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); | ||
1728 | u32 max_resp_sz_cached; | 1757 | u32 max_resp_sz_cached; |
1729 | 1758 | ||
1730 | /* | 1759 | /* |
@@ -1766,7 +1795,7 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
1766 | *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ | 1795 | *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ |
1767 | 1796 | ||
1768 | /* authsys_parms rfc1831 */ | 1797 | /* authsys_parms rfc1831 */ |
1769 | *p++ = cpu_to_be32((u32)clp->cl_boot_time.tv_nsec); /* stamp */ | 1798 | *p++ = (__be32)nn->boot_time.tv_nsec; /* stamp */ |
1770 | p = xdr_encode_opaque(p, machine_name, len); | 1799 | p = xdr_encode_opaque(p, machine_name, len); |
1771 | *p++ = cpu_to_be32(0); /* UID */ | 1800 | *p++ = cpu_to_be32(0); /* UID */ |
1772 | *p++ = cpu_to_be32(0); /* GID */ | 1801 | *p++ = cpu_to_be32(0); /* GID */ |
@@ -1781,6 +1810,14 @@ static void encode_destroy_session(struct xdr_stream *xdr, | |||
1781 | encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); | 1810 | encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); |
1782 | } | 1811 | } |
1783 | 1812 | ||
1813 | static void encode_destroy_clientid(struct xdr_stream *xdr, | ||
1814 | uint64_t clientid, | ||
1815 | struct compound_hdr *hdr) | ||
1816 | { | ||
1817 | encode_op_hdr(xdr, OP_DESTROY_CLIENTID, decode_destroy_clientid_maxsz, hdr); | ||
1818 | encode_uint64(xdr, clientid); | ||
1819 | } | ||
1820 | |||
1784 | static void encode_reclaim_complete(struct xdr_stream *xdr, | 1821 | static void encode_reclaim_complete(struct xdr_stream *xdr, |
1785 | struct nfs41_reclaim_complete_args *args, | 1822 | struct nfs41_reclaim_complete_args *args, |
1786 | struct compound_hdr *hdr) | 1823 | struct compound_hdr *hdr) |
@@ -2063,7 +2100,6 @@ static void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2063 | encode_sequence(xdr, &args->seq_args, &hdr); | 2100 | encode_sequence(xdr, &args->seq_args, &hdr); |
2064 | encode_putfh(xdr, args->fh, &hdr); | 2101 | encode_putfh(xdr, args->fh, &hdr); |
2065 | encode_remove(xdr, &args->name, &hdr); | 2102 | encode_remove(xdr, &args->name, &hdr); |
2066 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
2067 | encode_nops(&hdr); | 2103 | encode_nops(&hdr); |
2068 | } | 2104 | } |
2069 | 2105 | ||
@@ -2083,9 +2119,6 @@ static void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2083 | encode_savefh(xdr, &hdr); | 2119 | encode_savefh(xdr, &hdr); |
2084 | encode_putfh(xdr, args->new_dir, &hdr); | 2120 | encode_putfh(xdr, args->new_dir, &hdr); |
2085 | encode_rename(xdr, args->old_name, args->new_name, &hdr); | 2121 | encode_rename(xdr, args->old_name, args->new_name, &hdr); |
2086 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
2087 | encode_restorefh(xdr, &hdr); | ||
2088 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
2089 | encode_nops(&hdr); | 2122 | encode_nops(&hdr); |
2090 | } | 2123 | } |
2091 | 2124 | ||
@@ -2105,7 +2138,6 @@ static void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2105 | encode_savefh(xdr, &hdr); | 2138 | encode_savefh(xdr, &hdr); |
2106 | encode_putfh(xdr, args->dir_fh, &hdr); | 2139 | encode_putfh(xdr, args->dir_fh, &hdr); |
2107 | encode_link(xdr, args->name, &hdr); | 2140 | encode_link(xdr, args->name, &hdr); |
2108 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
2109 | encode_restorefh(xdr, &hdr); | 2141 | encode_restorefh(xdr, &hdr); |
2110 | encode_getfattr(xdr, args->bitmask, &hdr); | 2142 | encode_getfattr(xdr, args->bitmask, &hdr); |
2111 | encode_nops(&hdr); | 2143 | encode_nops(&hdr); |
@@ -2124,12 +2156,9 @@ static void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2124 | encode_compound_hdr(xdr, req, &hdr); | 2156 | encode_compound_hdr(xdr, req, &hdr); |
2125 | encode_sequence(xdr, &args->seq_args, &hdr); | 2157 | encode_sequence(xdr, &args->seq_args, &hdr); |
2126 | encode_putfh(xdr, args->dir_fh, &hdr); | 2158 | encode_putfh(xdr, args->dir_fh, &hdr); |
2127 | encode_savefh(xdr, &hdr); | ||
2128 | encode_create(xdr, args, &hdr); | 2159 | encode_create(xdr, args, &hdr); |
2129 | encode_getfh(xdr, &hdr); | 2160 | encode_getfh(xdr, &hdr); |
2130 | encode_getfattr(xdr, args->bitmask, &hdr); | 2161 | encode_getfattr(xdr, args->bitmask, &hdr); |
2131 | encode_restorefh(xdr, &hdr); | ||
2132 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
2133 | encode_nops(&hdr); | 2162 | encode_nops(&hdr); |
2134 | } | 2163 | } |
2135 | 2164 | ||
@@ -2190,12 +2219,9 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2190 | encode_compound_hdr(xdr, req, &hdr); | 2219 | encode_compound_hdr(xdr, req, &hdr); |
2191 | encode_sequence(xdr, &args->seq_args, &hdr); | 2220 | encode_sequence(xdr, &args->seq_args, &hdr); |
2192 | encode_putfh(xdr, args->fh, &hdr); | 2221 | encode_putfh(xdr, args->fh, &hdr); |
2193 | encode_savefh(xdr, &hdr); | ||
2194 | encode_open(xdr, args, &hdr); | 2222 | encode_open(xdr, args, &hdr); |
2195 | encode_getfh(xdr, &hdr); | 2223 | encode_getfh(xdr, &hdr); |
2196 | encode_getfattr(xdr, args->bitmask, &hdr); | 2224 | encode_getfattr_open(xdr, args->bitmask, &hdr); |
2197 | encode_restorefh(xdr, &hdr); | ||
2198 | encode_getfattr(xdr, args->dir_bitmask, &hdr); | ||
2199 | encode_nops(&hdr); | 2225 | encode_nops(&hdr); |
2200 | } | 2226 | } |
2201 | 2227 | ||
@@ -2447,7 +2473,7 @@ static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2447 | * a COMMIT request | 2473 | * a COMMIT request |
2448 | */ | 2474 | */ |
2449 | static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, | 2475 | static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, |
2450 | struct nfs_writeargs *args) | 2476 | struct nfs_commitargs *args) |
2451 | { | 2477 | { |
2452 | struct compound_hdr hdr = { | 2478 | struct compound_hdr hdr = { |
2453 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2479 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
@@ -2457,8 +2483,6 @@ static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2457 | encode_sequence(xdr, &args->seq_args, &hdr); | 2483 | encode_sequence(xdr, &args->seq_args, &hdr); |
2458 | encode_putfh(xdr, args->fh, &hdr); | 2484 | encode_putfh(xdr, args->fh, &hdr); |
2459 | encode_commit(xdr, args, &hdr); | 2485 | encode_commit(xdr, args, &hdr); |
2460 | if (args->bitmask) | ||
2461 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
2462 | encode_nops(&hdr); | 2486 | encode_nops(&hdr); |
2463 | } | 2487 | } |
2464 | 2488 | ||
@@ -2601,8 +2625,8 @@ static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, | |||
2601 | encode_compound_hdr(xdr, req, &hdr); | 2625 | encode_compound_hdr(xdr, req, &hdr); |
2602 | encode_sequence(xdr, &args->seq_args, &hdr); | 2626 | encode_sequence(xdr, &args->seq_args, &hdr); |
2603 | encode_putfh(xdr, args->fhandle, &hdr); | 2627 | encode_putfh(xdr, args->fhandle, &hdr); |
2604 | encode_delegreturn(xdr, args->stateid, &hdr); | ||
2605 | encode_getfattr(xdr, args->bitmask, &hdr); | 2628 | encode_getfattr(xdr, args->bitmask, &hdr); |
2629 | encode_delegreturn(xdr, args->stateid, &hdr); | ||
2606 | encode_nops(&hdr); | 2630 | encode_nops(&hdr); |
2607 | } | 2631 | } |
2608 | 2632 | ||
@@ -2650,6 +2674,22 @@ static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req, | |||
2650 | 2674 | ||
2651 | #if defined(CONFIG_NFS_V4_1) | 2675 | #if defined(CONFIG_NFS_V4_1) |
2652 | /* | 2676 | /* |
2677 | * BIND_CONN_TO_SESSION request | ||
2678 | */ | ||
2679 | static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req, | ||
2680 | struct xdr_stream *xdr, | ||
2681 | struct nfs_client *clp) | ||
2682 | { | ||
2683 | struct compound_hdr hdr = { | ||
2684 | .minorversion = clp->cl_mvops->minor_version, | ||
2685 | }; | ||
2686 | |||
2687 | encode_compound_hdr(xdr, req, &hdr); | ||
2688 | encode_bind_conn_to_session(xdr, clp->cl_session, &hdr); | ||
2689 | encode_nops(&hdr); | ||
2690 | } | ||
2691 | |||
2692 | /* | ||
2653 | * EXCHANGE_ID request | 2693 | * EXCHANGE_ID request |
2654 | */ | 2694 | */ |
2655 | static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, | 2695 | static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, |
@@ -2698,6 +2738,22 @@ static void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, | |||
2698 | } | 2738 | } |
2699 | 2739 | ||
2700 | /* | 2740 | /* |
2741 | * a DESTROY_CLIENTID request | ||
2742 | */ | ||
2743 | static void nfs4_xdr_enc_destroy_clientid(struct rpc_rqst *req, | ||
2744 | struct xdr_stream *xdr, | ||
2745 | struct nfs_client *clp) | ||
2746 | { | ||
2747 | struct compound_hdr hdr = { | ||
2748 | .minorversion = clp->cl_mvops->minor_version, | ||
2749 | }; | ||
2750 | |||
2751 | encode_compound_hdr(xdr, req, &hdr); | ||
2752 | encode_destroy_clientid(xdr, clp->cl_clientid, &hdr); | ||
2753 | encode_nops(&hdr); | ||
2754 | } | ||
2755 | |||
2756 | /* | ||
2701 | * a SEQUENCE request | 2757 | * a SEQUENCE request |
2702 | */ | 2758 | */ |
2703 | static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr, | 2759 | static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr, |
@@ -4101,7 +4157,7 @@ static int decode_verifier(struct xdr_stream *xdr, void *verifier) | |||
4101 | return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE); | 4157 | return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE); |
4102 | } | 4158 | } |
4103 | 4159 | ||
4104 | static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res) | 4160 | static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res) |
4105 | { | 4161 | { |
4106 | int status; | 4162 | int status; |
4107 | 4163 | ||
@@ -4219,6 +4275,110 @@ xdr_error: | |||
4219 | return status; | 4275 | return status; |
4220 | } | 4276 | } |
4221 | 4277 | ||
4278 | static int decode_threshold_hint(struct xdr_stream *xdr, | ||
4279 | uint32_t *bitmap, | ||
4280 | uint64_t *res, | ||
4281 | uint32_t hint_bit) | ||
4282 | { | ||
4283 | __be32 *p; | ||
4284 | |||
4285 | *res = 0; | ||
4286 | if (likely(bitmap[0] & hint_bit)) { | ||
4287 | p = xdr_inline_decode(xdr, 8); | ||
4288 | if (unlikely(!p)) | ||
4289 | goto out_overflow; | ||
4290 | xdr_decode_hyper(p, res); | ||
4291 | } | ||
4292 | return 0; | ||
4293 | out_overflow: | ||
4294 | print_overflow_msg(__func__, xdr); | ||
4295 | return -EIO; | ||
4296 | } | ||
4297 | |||
4298 | static int decode_first_threshold_item4(struct xdr_stream *xdr, | ||
4299 | struct nfs4_threshold *res) | ||
4300 | { | ||
4301 | __be32 *p, *savep; | ||
4302 | uint32_t bitmap[3] = {0,}, attrlen; | ||
4303 | int status; | ||
4304 | |||
4305 | /* layout type */ | ||
4306 | p = xdr_inline_decode(xdr, 4); | ||
4307 | if (unlikely(!p)) { | ||
4308 | print_overflow_msg(__func__, xdr); | ||
4309 | return -EIO; | ||
4310 | } | ||
4311 | res->l_type = be32_to_cpup(p); | ||
4312 | |||
4313 | /* thi_hintset bitmap */ | ||
4314 | status = decode_attr_bitmap(xdr, bitmap); | ||
4315 | if (status < 0) | ||
4316 | goto xdr_error; | ||
4317 | |||
4318 | /* thi_hintlist length */ | ||
4319 | status = decode_attr_length(xdr, &attrlen, &savep); | ||
4320 | if (status < 0) | ||
4321 | goto xdr_error; | ||
4322 | /* thi_hintlist */ | ||
4323 | status = decode_threshold_hint(xdr, bitmap, &res->rd_sz, THRESHOLD_RD); | ||
4324 | if (status < 0) | ||
4325 | goto xdr_error; | ||
4326 | status = decode_threshold_hint(xdr, bitmap, &res->wr_sz, THRESHOLD_WR); | ||
4327 | if (status < 0) | ||
4328 | goto xdr_error; | ||
4329 | status = decode_threshold_hint(xdr, bitmap, &res->rd_io_sz, | ||
4330 | THRESHOLD_RD_IO); | ||
4331 | if (status < 0) | ||
4332 | goto xdr_error; | ||
4333 | status = decode_threshold_hint(xdr, bitmap, &res->wr_io_sz, | ||
4334 | THRESHOLD_WR_IO); | ||
4335 | if (status < 0) | ||
4336 | goto xdr_error; | ||
4337 | |||
4338 | status = verify_attr_len(xdr, savep, attrlen); | ||
4339 | res->bm = bitmap[0]; | ||
4340 | |||
4341 | dprintk("%s bm=0x%x rd_sz=%llu wr_sz=%llu rd_io=%llu wr_io=%llu\n", | ||
4342 | __func__, res->bm, res->rd_sz, res->wr_sz, res->rd_io_sz, | ||
4343 | res->wr_io_sz); | ||
4344 | xdr_error: | ||
4345 | dprintk("%s ret=%d!\n", __func__, status); | ||
4346 | return status; | ||
4347 | } | ||
4348 | |||
4349 | /* | ||
4350 | * Thresholds on pNFS direct I/O vrs MDS I/O | ||
4351 | */ | ||
4352 | static int decode_attr_mdsthreshold(struct xdr_stream *xdr, | ||
4353 | uint32_t *bitmap, | ||
4354 | struct nfs4_threshold *res) | ||
4355 | { | ||
4356 | __be32 *p; | ||
4357 | int status = 0; | ||
4358 | uint32_t num; | ||
4359 | |||
4360 | if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U))) | ||
4361 | return -EIO; | ||
4362 | if (likely(bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD)) { | ||
4363 | p = xdr_inline_decode(xdr, 4); | ||
4364 | if (unlikely(!p)) | ||
4365 | goto out_overflow; | ||
4366 | num = be32_to_cpup(p); | ||
4367 | if (num == 0) | ||
4368 | return 0; | ||
4369 | if (num > 1) | ||
4370 | printk(KERN_INFO "%s: Warning: Multiple pNFS layout " | ||
4371 | "drivers per filesystem not supported\n", | ||
4372 | __func__); | ||
4373 | |||
4374 | status = decode_first_threshold_item4(xdr, res); | ||
4375 | } | ||
4376 | return status; | ||
4377 | out_overflow: | ||
4378 | print_overflow_msg(__func__, xdr); | ||
4379 | return -EIO; | ||
4380 | } | ||
4381 | |||
4222 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | 4382 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, |
4223 | struct nfs_fattr *fattr, struct nfs_fh *fh, | 4383 | struct nfs_fattr *fattr, struct nfs_fh *fh, |
4224 | struct nfs4_fs_locations *fs_loc, | 4384 | struct nfs4_fs_locations *fs_loc, |
@@ -4257,8 +4417,6 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4257 | status = decode_attr_error(xdr, bitmap, &err); | 4417 | status = decode_attr_error(xdr, bitmap, &err); |
4258 | if (status < 0) | 4418 | if (status < 0) |
4259 | goto xdr_error; | 4419 | goto xdr_error; |
4260 | if (err == -NFS4ERR_WRONGSEC) | ||
4261 | nfs_fixup_secinfo_attributes(fattr, fh); | ||
4262 | 4420 | ||
4263 | status = decode_attr_filehandle(xdr, bitmap, fh); | 4421 | status = decode_attr_filehandle(xdr, bitmap, fh); |
4264 | if (status < 0) | 4422 | if (status < 0) |
@@ -4327,6 +4485,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4327 | goto xdr_error; | 4485 | goto xdr_error; |
4328 | fattr->valid |= status; | 4486 | fattr->valid |= status; |
4329 | 4487 | ||
4488 | status = decode_attr_mdsthreshold(xdr, bitmap, fattr->mdsthreshold); | ||
4489 | if (status < 0) | ||
4490 | goto xdr_error; | ||
4491 | |||
4330 | xdr_error: | 4492 | xdr_error: |
4331 | dprintk("%s: xdr returned %d\n", __func__, -status); | 4493 | dprintk("%s: xdr returned %d\n", __func__, -status); |
4332 | return status; | 4494 | return status; |
@@ -4901,11 +5063,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
4901 | bitmap[3] = {0}; | 5063 | bitmap[3] = {0}; |
4902 | struct kvec *iov = req->rq_rcv_buf.head; | 5064 | struct kvec *iov = req->rq_rcv_buf.head; |
4903 | int status; | 5065 | int status; |
5066 | size_t page_len = xdr->buf->page_len; | ||
4904 | 5067 | ||
4905 | res->acl_len = 0; | 5068 | res->acl_len = 0; |
4906 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 5069 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
4907 | goto out; | 5070 | goto out; |
5071 | |||
4908 | bm_p = xdr->p; | 5072 | bm_p = xdr->p; |
5073 | res->acl_data_offset = be32_to_cpup(bm_p) + 2; | ||
5074 | res->acl_data_offset <<= 2; | ||
5075 | /* Check if the acl data starts beyond the allocated buffer */ | ||
5076 | if (res->acl_data_offset > page_len) | ||
5077 | return -ERANGE; | ||
5078 | |||
4909 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | 5079 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) |
4910 | goto out; | 5080 | goto out; |
4911 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) | 5081 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) |
@@ -4915,28 +5085,24 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
4915 | return -EIO; | 5085 | return -EIO; |
4916 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { | 5086 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { |
4917 | size_t hdrlen; | 5087 | size_t hdrlen; |
4918 | u32 recvd; | ||
4919 | 5088 | ||
4920 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words | 5089 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words |
4921 | * are stored with the acl data to handle the problem of | 5090 | * are stored with the acl data to handle the problem of |
4922 | * variable length bitmaps.*/ | 5091 | * variable length bitmaps.*/ |
4923 | xdr->p = bm_p; | 5092 | xdr->p = bm_p; |
4924 | res->acl_data_offset = be32_to_cpup(bm_p) + 2; | ||
4925 | res->acl_data_offset <<= 2; | ||
4926 | 5093 | ||
4927 | /* We ignore &savep and don't do consistency checks on | 5094 | /* We ignore &savep and don't do consistency checks on |
4928 | * the attr length. Let userspace figure it out.... */ | 5095 | * the attr length. Let userspace figure it out.... */ |
4929 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; | 5096 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; |
4930 | attrlen += res->acl_data_offset; | 5097 | attrlen += res->acl_data_offset; |
4931 | recvd = req->rq_rcv_buf.len - hdrlen; | 5098 | if (attrlen > page_len) { |
4932 | if (attrlen > recvd) { | ||
4933 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { | 5099 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { |
4934 | /* getxattr interface called with a NULL buf */ | 5100 | /* getxattr interface called with a NULL buf */ |
4935 | res->acl_len = attrlen; | 5101 | res->acl_len = attrlen; |
4936 | goto out; | 5102 | goto out; |
4937 | } | 5103 | } |
4938 | dprintk("NFS: acl reply: attrlen %u > recvd %u\n", | 5104 | dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", |
4939 | attrlen, recvd); | 5105 | attrlen, page_len); |
4940 | return -EINVAL; | 5106 | return -EINVAL; |
4941 | } | 5107 | } |
4942 | xdr_read_pages(xdr, attrlen); | 5108 | xdr_read_pages(xdr, attrlen); |
@@ -5089,16 +5255,13 @@ out_err: | |||
5089 | return -EINVAL; | 5255 | return -EINVAL; |
5090 | } | 5256 | } |
5091 | 5257 | ||
5092 | static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | 5258 | static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) |
5093 | { | 5259 | { |
5094 | struct nfs4_secinfo_flavor *sec_flavor; | 5260 | struct nfs4_secinfo_flavor *sec_flavor; |
5095 | int status; | 5261 | int status; |
5096 | __be32 *p; | 5262 | __be32 *p; |
5097 | int i, num_flavors; | 5263 | int i, num_flavors; |
5098 | 5264 | ||
5099 | status = decode_op_hdr(xdr, OP_SECINFO); | ||
5100 | if (status) | ||
5101 | goto out; | ||
5102 | p = xdr_inline_decode(xdr, 4); | 5265 | p = xdr_inline_decode(xdr, 4); |
5103 | if (unlikely(!p)) | 5266 | if (unlikely(!p)) |
5104 | goto out_overflow; | 5267 | goto out_overflow; |
@@ -5124,6 +5287,7 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | |||
5124 | res->flavors->num_flavors++; | 5287 | res->flavors->num_flavors++; |
5125 | } | 5288 | } |
5126 | 5289 | ||
5290 | status = 0; | ||
5127 | out: | 5291 | out: |
5128 | return status; | 5292 | return status; |
5129 | out_overflow: | 5293 | out_overflow: |
@@ -5131,7 +5295,23 @@ out_overflow: | |||
5131 | return -EIO; | 5295 | return -EIO; |
5132 | } | 5296 | } |
5133 | 5297 | ||
5298 | static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | ||
5299 | { | ||
5300 | int status = decode_op_hdr(xdr, OP_SECINFO); | ||
5301 | if (status) | ||
5302 | return status; | ||
5303 | return decode_secinfo_common(xdr, res); | ||
5304 | } | ||
5305 | |||
5134 | #if defined(CONFIG_NFS_V4_1) | 5306 | #if defined(CONFIG_NFS_V4_1) |
5307 | static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | ||
5308 | { | ||
5309 | int status = decode_op_hdr(xdr, OP_SECINFO_NO_NAME); | ||
5310 | if (status) | ||
5311 | return status; | ||
5312 | return decode_secinfo_common(xdr, res); | ||
5313 | } | ||
5314 | |||
5135 | static int decode_exchange_id(struct xdr_stream *xdr, | 5315 | static int decode_exchange_id(struct xdr_stream *xdr, |
5136 | struct nfs41_exchange_id_res *res) | 5316 | struct nfs41_exchange_id_res *res) |
5137 | { | 5317 | { |
@@ -5139,7 +5319,6 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5139 | uint32_t dummy; | 5319 | uint32_t dummy; |
5140 | char *dummy_str; | 5320 | char *dummy_str; |
5141 | int status; | 5321 | int status; |
5142 | struct nfs_client *clp = res->client; | ||
5143 | uint32_t impl_id_count; | 5322 | uint32_t impl_id_count; |
5144 | 5323 | ||
5145 | status = decode_op_hdr(xdr, OP_EXCHANGE_ID); | 5324 | status = decode_op_hdr(xdr, OP_EXCHANGE_ID); |
@@ -5149,36 +5328,39 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5149 | p = xdr_inline_decode(xdr, 8); | 5328 | p = xdr_inline_decode(xdr, 8); |
5150 | if (unlikely(!p)) | 5329 | if (unlikely(!p)) |
5151 | goto out_overflow; | 5330 | goto out_overflow; |
5152 | xdr_decode_hyper(p, &clp->cl_clientid); | 5331 | xdr_decode_hyper(p, &res->clientid); |
5153 | p = xdr_inline_decode(xdr, 12); | 5332 | p = xdr_inline_decode(xdr, 12); |
5154 | if (unlikely(!p)) | 5333 | if (unlikely(!p)) |
5155 | goto out_overflow; | 5334 | goto out_overflow; |
5156 | clp->cl_seqid = be32_to_cpup(p++); | 5335 | res->seqid = be32_to_cpup(p++); |
5157 | clp->cl_exchange_flags = be32_to_cpup(p++); | 5336 | res->flags = be32_to_cpup(p++); |
5158 | 5337 | ||
5159 | /* We ask for SP4_NONE */ | 5338 | /* We ask for SP4_NONE */ |
5160 | dummy = be32_to_cpup(p); | 5339 | dummy = be32_to_cpup(p); |
5161 | if (dummy != SP4_NONE) | 5340 | if (dummy != SP4_NONE) |
5162 | return -EIO; | 5341 | return -EIO; |
5163 | 5342 | ||
5164 | /* Throw away minor_id */ | 5343 | /* server_owner4.so_minor_id */ |
5165 | p = xdr_inline_decode(xdr, 8); | 5344 | p = xdr_inline_decode(xdr, 8); |
5166 | if (unlikely(!p)) | 5345 | if (unlikely(!p)) |
5167 | goto out_overflow; | 5346 | goto out_overflow; |
5347 | p = xdr_decode_hyper(p, &res->server_owner->minor_id); | ||
5168 | 5348 | ||
5169 | /* Throw away Major id */ | 5349 | /* server_owner4.so_major_id */ |
5170 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | 5350 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); |
5171 | if (unlikely(status)) | 5351 | if (unlikely(status)) |
5172 | return status; | 5352 | return status; |
5353 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) | ||
5354 | return -EIO; | ||
5355 | memcpy(res->server_owner->major_id, dummy_str, dummy); | ||
5356 | res->server_owner->major_id_sz = dummy; | ||
5173 | 5357 | ||
5174 | /* Save server_scope */ | 5358 | /* server_scope4 */ |
5175 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | 5359 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); |
5176 | if (unlikely(status)) | 5360 | if (unlikely(status)) |
5177 | return status; | 5361 | return status; |
5178 | |||
5179 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) | 5362 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) |
5180 | return -EIO; | 5363 | return -EIO; |
5181 | |||
5182 | memcpy(res->server_scope->server_scope, dummy_str, dummy); | 5364 | memcpy(res->server_scope->server_scope, dummy_str, dummy); |
5183 | res->server_scope->server_scope_sz = dummy; | 5365 | res->server_scope->server_scope_sz = dummy; |
5184 | 5366 | ||
@@ -5259,6 +5441,37 @@ static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid) | |||
5259 | return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN); | 5441 | return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN); |
5260 | } | 5442 | } |
5261 | 5443 | ||
5444 | static int decode_bind_conn_to_session(struct xdr_stream *xdr, | ||
5445 | struct nfs41_bind_conn_to_session_res *res) | ||
5446 | { | ||
5447 | __be32 *p; | ||
5448 | int status; | ||
5449 | |||
5450 | status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION); | ||
5451 | if (!status) | ||
5452 | status = decode_sessionid(xdr, &res->session->sess_id); | ||
5453 | if (unlikely(status)) | ||
5454 | return status; | ||
5455 | |||
5456 | /* dir flags, rdma mode bool */ | ||
5457 | p = xdr_inline_decode(xdr, 8); | ||
5458 | if (unlikely(!p)) | ||
5459 | goto out_overflow; | ||
5460 | |||
5461 | res->dir = be32_to_cpup(p++); | ||
5462 | if (res->dir == 0 || res->dir > NFS4_CDFS4_BOTH) | ||
5463 | return -EIO; | ||
5464 | if (be32_to_cpup(p) == 0) | ||
5465 | res->use_conn_in_rdma_mode = false; | ||
5466 | else | ||
5467 | res->use_conn_in_rdma_mode = true; | ||
5468 | |||
5469 | return 0; | ||
5470 | out_overflow: | ||
5471 | print_overflow_msg(__func__, xdr); | ||
5472 | return -EIO; | ||
5473 | } | ||
5474 | |||
5262 | static int decode_create_session(struct xdr_stream *xdr, | 5475 | static int decode_create_session(struct xdr_stream *xdr, |
5263 | struct nfs41_create_session_res *res) | 5476 | struct nfs41_create_session_res *res) |
5264 | { | 5477 | { |
@@ -5295,6 +5508,11 @@ static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) | |||
5295 | return decode_op_hdr(xdr, OP_DESTROY_SESSION); | 5508 | return decode_op_hdr(xdr, OP_DESTROY_SESSION); |
5296 | } | 5509 | } |
5297 | 5510 | ||
5511 | static int decode_destroy_clientid(struct xdr_stream *xdr, void *dummy) | ||
5512 | { | ||
5513 | return decode_op_hdr(xdr, OP_DESTROY_CLIENTID); | ||
5514 | } | ||
5515 | |||
5298 | static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) | 5516 | static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) |
5299 | { | 5517 | { |
5300 | return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); | 5518 | return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); |
@@ -5783,9 +6001,6 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
5783 | if (status) | 6001 | if (status) |
5784 | goto out; | 6002 | goto out; |
5785 | status = decode_remove(xdr, &res->cinfo); | 6003 | status = decode_remove(xdr, &res->cinfo); |
5786 | if (status) | ||
5787 | goto out; | ||
5788 | decode_getfattr(xdr, res->dir_attr, res->server); | ||
5789 | out: | 6004 | out: |
5790 | return status; | 6005 | return status; |
5791 | } | 6006 | } |
@@ -5815,15 +6030,6 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
5815 | if (status) | 6030 | if (status) |
5816 | goto out; | 6031 | goto out; |
5817 | status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo); | 6032 | status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo); |
5818 | if (status) | ||
5819 | goto out; | ||
5820 | /* Current FH is target directory */ | ||
5821 | if (decode_getfattr(xdr, res->new_fattr, res->server)) | ||
5822 | goto out; | ||
5823 | status = decode_restorefh(xdr); | ||
5824 | if (status) | ||
5825 | goto out; | ||
5826 | decode_getfattr(xdr, res->old_fattr, res->server); | ||
5827 | out: | 6033 | out: |
5828 | return status; | 6034 | return status; |
5829 | } | 6035 | } |
@@ -5859,8 +6065,6 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
5859 | * Note order: OP_LINK leaves the directory as the current | 6065 | * Note order: OP_LINK leaves the directory as the current |
5860 | * filehandle. | 6066 | * filehandle. |
5861 | */ | 6067 | */ |
5862 | if (decode_getfattr(xdr, res->dir_attr, res->server)) | ||
5863 | goto out; | ||
5864 | status = decode_restorefh(xdr); | 6068 | status = decode_restorefh(xdr); |
5865 | if (status) | 6069 | if (status) |
5866 | goto out; | 6070 | goto out; |
@@ -5887,21 +6091,13 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
5887 | status = decode_putfh(xdr); | 6091 | status = decode_putfh(xdr); |
5888 | if (status) | 6092 | if (status) |
5889 | goto out; | 6093 | goto out; |
5890 | status = decode_savefh(xdr); | ||
5891 | if (status) | ||
5892 | goto out; | ||
5893 | status = decode_create(xdr, &res->dir_cinfo); | 6094 | status = decode_create(xdr, &res->dir_cinfo); |
5894 | if (status) | 6095 | if (status) |
5895 | goto out; | 6096 | goto out; |
5896 | status = decode_getfh(xdr, res->fh); | 6097 | status = decode_getfh(xdr, res->fh); |
5897 | if (status) | 6098 | if (status) |
5898 | goto out; | 6099 | goto out; |
5899 | if (decode_getfattr(xdr, res->fattr, res->server)) | 6100 | decode_getfattr(xdr, res->fattr, res->server); |
5900 | goto out; | ||
5901 | status = decode_restorefh(xdr); | ||
5902 | if (status) | ||
5903 | goto out; | ||
5904 | decode_getfattr(xdr, res->dir_fattr, res->server); | ||
5905 | out: | 6101 | out: |
5906 | return status; | 6102 | return status; |
5907 | } | 6103 | } |
@@ -6058,19 +6254,12 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6058 | status = decode_putfh(xdr); | 6254 | status = decode_putfh(xdr); |
6059 | if (status) | 6255 | if (status) |
6060 | goto out; | 6256 | goto out; |
6061 | status = decode_savefh(xdr); | ||
6062 | if (status) | ||
6063 | goto out; | ||
6064 | status = decode_open(xdr, res); | 6257 | status = decode_open(xdr, res); |
6065 | if (status) | 6258 | if (status) |
6066 | goto out; | 6259 | goto out; |
6067 | if (decode_getfh(xdr, &res->fh) != 0) | 6260 | if (decode_getfh(xdr, &res->fh) != 0) |
6068 | goto out; | 6261 | goto out; |
6069 | if (decode_getfattr(xdr, res->f_attr, res->server) != 0) | 6262 | decode_getfattr(xdr, res->f_attr, res->server); |
6070 | goto out; | ||
6071 | if (decode_restorefh(xdr) != 0) | ||
6072 | goto out; | ||
6073 | decode_getfattr(xdr, res->dir_attr, res->server); | ||
6074 | out: | 6263 | out: |
6075 | return status; | 6264 | return status; |
6076 | } | 6265 | } |
@@ -6336,7 +6525,7 @@ out: | |||
6336 | * Decode COMMIT response | 6525 | * Decode COMMIT response |
6337 | */ | 6526 | */ |
6338 | static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6527 | static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6339 | struct nfs_writeres *res) | 6528 | struct nfs_commitres *res) |
6340 | { | 6529 | { |
6341 | struct compound_hdr hdr; | 6530 | struct compound_hdr hdr; |
6342 | int status; | 6531 | int status; |
@@ -6351,10 +6540,6 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6351 | if (status) | 6540 | if (status) |
6352 | goto out; | 6541 | goto out; |
6353 | status = decode_commit(xdr, res); | 6542 | status = decode_commit(xdr, res); |
6354 | if (status) | ||
6355 | goto out; | ||
6356 | if (res->fattr) | ||
6357 | decode_getfattr(xdr, res->fattr, res->server); | ||
6358 | out: | 6543 | out: |
6359 | return status; | 6544 | return status; |
6360 | } | 6545 | } |
@@ -6510,10 +6695,10 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, | |||
6510 | status = decode_putfh(xdr); | 6695 | status = decode_putfh(xdr); |
6511 | if (status != 0) | 6696 | if (status != 0) |
6512 | goto out; | 6697 | goto out; |
6513 | status = decode_delegreturn(xdr); | 6698 | status = decode_getfattr(xdr, res->fattr, res->server); |
6514 | if (status != 0) | 6699 | if (status != 0) |
6515 | goto out; | 6700 | goto out; |
6516 | decode_getfattr(xdr, res->fattr, res->server); | 6701 | status = decode_delegreturn(xdr); |
6517 | out: | 6702 | out: |
6518 | return status; | 6703 | return status; |
6519 | } | 6704 | } |
@@ -6574,6 +6759,22 @@ out: | |||
6574 | 6759 | ||
6575 | #if defined(CONFIG_NFS_V4_1) | 6760 | #if defined(CONFIG_NFS_V4_1) |
6576 | /* | 6761 | /* |
6762 | * Decode BIND_CONN_TO_SESSION response | ||
6763 | */ | ||
6764 | static int nfs4_xdr_dec_bind_conn_to_session(struct rpc_rqst *rqstp, | ||
6765 | struct xdr_stream *xdr, | ||
6766 | void *res) | ||
6767 | { | ||
6768 | struct compound_hdr hdr; | ||
6769 | int status; | ||
6770 | |||
6771 | status = decode_compound_hdr(xdr, &hdr); | ||
6772 | if (!status) | ||
6773 | status = decode_bind_conn_to_session(xdr, res); | ||
6774 | return status; | ||
6775 | } | ||
6776 | |||
6777 | /* | ||
6577 | * Decode EXCHANGE_ID response | 6778 | * Decode EXCHANGE_ID response |
6578 | */ | 6779 | */ |
6579 | static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, | 6780 | static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, |
@@ -6622,6 +6823,22 @@ static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, | |||
6622 | } | 6823 | } |
6623 | 6824 | ||
6624 | /* | 6825 | /* |
6826 | * Decode DESTROY_CLIENTID response | ||
6827 | */ | ||
6828 | static int nfs4_xdr_dec_destroy_clientid(struct rpc_rqst *rqstp, | ||
6829 | struct xdr_stream *xdr, | ||
6830 | void *res) | ||
6831 | { | ||
6832 | struct compound_hdr hdr; | ||
6833 | int status; | ||
6834 | |||
6835 | status = decode_compound_hdr(xdr, &hdr); | ||
6836 | if (!status) | ||
6837 | status = decode_destroy_clientid(xdr, res); | ||
6838 | return status; | ||
6839 | } | ||
6840 | |||
6841 | /* | ||
6625 | * Decode SEQUENCE response | 6842 | * Decode SEQUENCE response |
6626 | */ | 6843 | */ |
6627 | static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, | 6844 | static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, |
@@ -6816,7 +7033,7 @@ static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp, | |||
6816 | status = decode_putrootfh(xdr); | 7033 | status = decode_putrootfh(xdr); |
6817 | if (status) | 7034 | if (status) |
6818 | goto out; | 7035 | goto out; |
6819 | status = decode_secinfo(xdr, res); | 7036 | status = decode_secinfo_no_name(xdr, res); |
6820 | out: | 7037 | out: |
6821 | return status; | 7038 | return status; |
6822 | } | 7039 | } |
@@ -7068,6 +7285,9 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
7068 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), | 7285 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), |
7069 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), | 7286 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), |
7070 | PROC(GETDEVICELIST, enc_getdevicelist, dec_getdevicelist), | 7287 | PROC(GETDEVICELIST, enc_getdevicelist, dec_getdevicelist), |
7288 | PROC(BIND_CONN_TO_SESSION, | ||
7289 | enc_bind_conn_to_session, dec_bind_conn_to_session), | ||
7290 | PROC(DESTROY_CLIENTID, enc_destroy_clientid, dec_destroy_clientid), | ||
7071 | #endif /* CONFIG_NFS_V4_1 */ | 7291 | #endif /* CONFIG_NFS_V4_1 */ |
7072 | }; | 7292 | }; |
7073 | 7293 | ||