| /* |
| * fs/nfs/nfs4xdr.c |
| * |
| * Client-side XDR for NFSv4. |
| * |
| * Copyright (c) 2002 The Regents of the University of Michigan. |
| * All rights reserved. |
| * |
| * Kendrick Smith <kmsmith@umich.edu> |
| * Andy Adamson <andros@umich.edu> |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the University nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <linux/param.h> |
| #include <linux/time.h> |
| #include <linux/mm.h> |
| #include <linux/errno.h> |
| #include <linux/string.h> |
| #include <linux/in.h> |
| #include <linux/pagemap.h> |
| #include <linux/proc_fs.h> |
| #include <linux/kdev_t.h> |
| #include <linux/module.h> |
| #include <linux/utsname.h> |
| #include <linux/sunrpc/clnt.h> |
| #include <linux/sunrpc/msg_prot.h> |
| #include <linux/sunrpc/gss_api.h> |
| #include <linux/nfs.h> |
| #include <linux/nfs4.h> |
| #include <linux/nfs_fs.h> |
| |
| #include "nfs4_fs.h" |
| #include "nfs4trace.h" |
| #include "internal.h" |
| #include "nfs4idmap.h" |
| #include "nfs4session.h" |
| #include "pnfs.h" |
| #include "netns.h" |
| |
| #define NFSDBG_FACILITY NFSDBG_XDR |
| |
| /* Mapping from NFS error code to "errno" error code. */ |
| #define errno_NFSERR_IO EIO |
| |
| struct compound_hdr; |
| static int nfs4_stat_to_errno(int); |
| static void encode_layoutget(struct xdr_stream *xdr, |
| const struct nfs4_layoutget_args *args, |
| struct compound_hdr *hdr); |
| static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, |
| struct nfs4_layoutget_res *res); |
| |
| /* NFSv4 COMPOUND tags are only wanted for debugging purposes */ |
| #ifdef DEBUG |
| #define NFS4_MAXTAGLEN 20 |
| #else |
| #define NFS4_MAXTAGLEN 0 |
| #endif |
| |
| /* lock,open owner id: |
| * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) |
| */ |
| #define pagepad_maxsz (1) |
| #define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2) |
| #define lock_owner_id_maxsz (1 + 1 + 4) |
| #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
| #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) |
| #define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) |
| #define op_encode_hdr_maxsz (1) |
| #define op_decode_hdr_maxsz (2) |
| #define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) |
| #define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) |
| #define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) |
| #define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) |
| #define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \ |
| (NFS4_FHSIZE >> 2)) |
| #define decode_putfh_maxsz (op_decode_hdr_maxsz) |
| #define encode_putrootfh_maxsz (op_encode_hdr_maxsz) |
| #define decode_putrootfh_maxsz (op_decode_hdr_maxsz) |
| #define encode_getfh_maxsz (op_encode_hdr_maxsz) |
| #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ |
| ((3+NFS4_FHSIZE) >> 2)) |
| #define nfs4_fattr_bitmap_maxsz 4 |
| #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) |
| #define nfstime4_maxsz (3) |
| #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) |
| #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) |
| #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
| #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
| #ifdef CONFIG_NFS_V4_SECURITY_LABEL |
| /* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */ |
| #define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN)) |
| #else |
| #define nfs4_label_maxsz 0 |
| #endif |
| /* We support only one layout type per file system */ |
| #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) |
| /* This is based on getfattr, which uses the most attributes: */ |
| #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ |
| 3*nfstime4_maxsz + \ |
| nfs4_owner_maxsz + \ |
| nfs4_group_maxsz + nfs4_label_maxsz + \ |
| decode_mdsthreshold_maxsz)) |
| #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ |
| nfs4_fattr_value_maxsz) |
| #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) |
| #define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \ |
| 1 + 2 + 1 + \ |
| nfs4_owner_maxsz + \ |
| nfs4_group_maxsz + \ |
| nfs4_label_maxsz + \ |
| 1 + nfstime4_maxsz + \ |
| 1 + nfstime4_maxsz) |
| #define encode_savefh_maxsz (op_encode_hdr_maxsz) |
| #define decode_savefh_maxsz (op_decode_hdr_maxsz) |
| #define encode_restorefh_maxsz (op_encode_hdr_maxsz) |
| #define decode_restorefh_maxsz (op_decode_hdr_maxsz) |
| #define encode_fsinfo_maxsz (encode_getattr_maxsz) |
| /* The 5 accounts for the PNFS attributes, and assumes that at most three |
| * layout types will be returned. |
| */ |
| #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + \ |
| nfs4_fattr_bitmap_maxsz + 1 + \ |
| 1 /* lease time */ + \ |
| 2 /* max filesize */ + \ |
| 2 /* max read */ + \ |
| 2 /* max write */ + \ |
| nfstime4_maxsz /* time delta */ + \ |
| 5 /* fs layout types */ + \ |
| 1 /* layout blksize */ + \ |
| 1 /* clone blksize */ + \ |
| 1 /* change attr type */ + \ |
| 1 /* xattr support */) |
| #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) |
| #define decode_renew_maxsz (op_decode_hdr_maxsz) |
| #define encode_setclientid_maxsz \ |
| (op_encode_hdr_maxsz + \ |
| XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ |
| /* client name */ \ |
| 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ |
| 1 /* sc_prog */ + \ |
| 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ |
| 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ |
| 1) /* sc_cb_ident */ |
| #define decode_setclientid_maxsz \ |
| (op_decode_hdr_maxsz + \ |
| 2 /* clientid */ + \ |
| XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ |
| 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ |
| 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN)) |
| #define encode_setclientid_confirm_maxsz \ |
| (op_encode_hdr_maxsz + \ |
| 3 + (NFS4_VERIFIER_SIZE >> 2)) |
| #define decode_setclientid_confirm_maxsz \ |
| (op_decode_hdr_maxsz) |
| #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) |
| #define decode_lookup_maxsz (op_decode_hdr_maxsz) |
| #define encode_lookupp_maxsz (op_encode_hdr_maxsz) |
| #define decode_lookupp_maxsz (op_decode_hdr_maxsz) |
| #define encode_share_access_maxsz \ |
| (2) |
| #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) |
| #define encode_opentype_maxsz (1 + encode_createmode_maxsz) |
| #define encode_claim_null_maxsz (1 + nfs4_name_maxsz) |
| #define encode_open_maxsz (op_encode_hdr_maxsz + \ |
| 2 + encode_share_access_maxsz + 2 + \ |
| open_owner_id_maxsz + \ |
| encode_opentype_maxsz + \ |
| encode_claim_null_maxsz) |
| #define decode_space_limit_maxsz (3) |
| #define decode_ace_maxsz (3 + nfs4_owner_maxsz) |
| #define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \ |
| decode_space_limit_maxsz + \ |
| decode_ace_maxsz) |
| #define decode_change_info_maxsz (5) |
| #define decode_open_maxsz (op_decode_hdr_maxsz + \ |
| decode_stateid_maxsz + \ |
| decode_change_info_maxsz + 1 + \ |
| nfs4_fattr_bitmap_maxsz + \ |
| decode_delegation_maxsz) |
| #define encode_open_confirm_maxsz \ |
| (op_encode_hdr_maxsz + \ |
| encode_stateid_maxsz + 1) |
| #define decode_open_confirm_maxsz \ |
| (op_decode_hdr_maxsz + \ |
| decode_stateid_maxsz) |
| #define encode_open_downgrade_maxsz \ |
| (op_encode_hdr_maxsz + \ |
| encode_stateid_maxsz + 1 + \ |
| encode_share_access_maxsz) |
| #define decode_open_downgrade_maxsz \ |
| (op_decode_hdr_maxsz + \ |
| decode_stateid_maxsz) |
| #define encode_close_maxsz (op_encode_hdr_maxsz + \ |
| 1 + encode_stateid_maxsz) |
| #define decode_close_maxsz (op_decode_hdr_maxsz + \ |
| decode_stateid_maxsz) |
| #define encode_setattr_maxsz (op_encode_hdr_maxsz + \ |
| encode_stateid_maxsz + \ |
| encode_attrs_maxsz) |
| #define decode_setattr_maxsz (op_decode_hdr_maxsz + \ |
| nfs4_fattr_bitmap_maxsz) |
| #define encode_delegattr_maxsz (op_encode_hdr_maxsz + \ |
| encode_stateid_maxsz + \ |
| nfs4_fattr_bitmap_maxsz + \ |
| 2*nfstime4_maxsz) |
| #define decode_delegattr_maxsz (decode_setattr_maxsz) |
| #define encode_read_maxsz (op_encode_hdr_maxsz + \ |
| encode_stateid_maxsz + 3) |
| #define decode_read_maxsz (op_decode_hdr_maxsz + 2 + pagepad_maxsz) |
| #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ |
| 2 + encode_verifier_maxsz + 5 + \ |
| nfs4_label_maxsz) |
| #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ |
| decode_verifier_maxsz + pagepad_maxsz) |
| #define encode_readlink_maxsz (op_encode_hdr_maxsz) |
| #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1 + pagepad_maxsz) |
| #define encode_write_maxsz (op_encode_hdr_maxsz + \ |
| encode_stateid_maxsz + 4) |
| #define decode_write_maxsz (op_decode_hdr_maxsz + \ |
| 2 + decode_verifier_maxsz) |
| #define encode_commit_maxsz (op_encode_hdr_maxsz + 3) |
| #define decode_commit_maxsz (op_decode_hdr_maxsz + \ |
| decode_verifier_maxsz) |
| #define encode_remove_maxsz (op_encode_hdr_maxsz + \ |
| nfs4_name_maxsz) |
| #define decode_remove_maxsz (op_decode_hdr_maxsz + \ |
| decode_change_info_maxsz) |
| #define encode_rename_maxsz (op_encode_hdr_maxsz + \ |
| 2 * nfs4_name_maxsz) |
| #define decode_rename_maxsz (op_decode_hdr_maxsz + \ |
| decode_change_info_maxsz + \ |
| decode_change_info_maxsz) |
| #define encode_link_maxsz (op_encode_hdr_maxsz + \ |
| nfs4_name_maxsz) |
| #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) |
| #define encode_lockowner_maxsz (7) |
| #define encode_lock_maxsz (op_encode_hdr_maxsz + \ |
| 7 + \ |
| 1 + encode_stateid_maxsz + 1 + \ |
| encode_lockowner_maxsz) |
| #define decode_lock_denied_maxsz \ |
| (8 + decode_lockowner_maxsz) |
| #define decode_lock_maxsz (op_decode_hdr_maxsz + \ |
| decode_lock_denied_maxsz) |
| #define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \ |
| encode_lockowner_maxsz) |
| #define decode_lockt_maxsz (op_decode_hdr_maxsz + \ |
| decode_lock_denied_maxsz) |
| #define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \ |
| encode_stateid_maxsz + \ |
| 4) |
| #define decode_locku_maxsz (op_decode_hdr_maxsz + \ |
| decode_stateid_maxsz) |
| #define encode_release_lockowner_maxsz \ |
| (op_encode_hdr_maxsz + \ |
| encode_lockowner_maxsz) |
| #define decode_release_lockowner_maxsz \ |
| (op_decode_hdr_maxsz) |
| #define encode_access_maxsz (op_encode_hdr_maxsz + 1) |
| #define decode_access_maxsz (op_decode_hdr_maxsz + 2) |
| #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ |
| 1 + nfs4_name_maxsz + \ |
| 1 + \ |
| nfs4_fattr_maxsz) |
| #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) |
| #define encode_create_maxsz (op_encode_hdr_maxsz + \ |
| 1 + 2 + nfs4_name_maxsz + \ |
| encode_attrs_maxsz) |
| #define decode_create_maxsz (op_decode_hdr_maxsz + \ |
| decode_change_info_maxsz + \ |
| nfs4_fattr_bitmap_maxsz) |
| #define encode_statfs_maxsz (encode_getattr_maxsz) |
| #define decode_statfs_maxsz (decode_getattr_maxsz) |
| #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) |
| #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) |
| #define encode_getacl_maxsz (encode_getattr_maxsz) |
| #define decode_getacl_maxsz (op_decode_hdr_maxsz + \ |
| nfs4_fattr_bitmap_maxsz + 1 + pagepad_maxsz) |
| #define encode_setacl_maxsz (op_encode_hdr_maxsz + \ |
| encode_stateid_maxsz + 3) |
| #define decode_setacl_maxsz (decode_setattr_maxsz) |
| #define encode_fs_locations_maxsz \ |
| (encode_getattr_maxsz) |
| #define decode_fs_locations_maxsz \ |
| (pagepad_maxsz) |
| #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) |
| #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4)) |
| |
| #if defined(CONFIG_NFS_V4_1) |
| #define NFS4_MAX_MACHINE_NAME_LEN (64) |
| #define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \ |
| sizeof(utsname()->version) + sizeof(utsname()->machine) + 8) |
| |
| #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ |
| encode_verifier_maxsz + \ |
| 1 /* co_ownerid.len */ + \ |
| /* eia_clientowner */ \ |
| 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ |
| 1 /* flags */ + \ |
| 1 /* spa_how */ + \ |
| /* max is SP4_MACH_CRED (for now) */ + \ |
| 1 + NFS4_OP_MAP_NUM_WORDS + \ |
| 1 + NFS4_OP_MAP_NUM_WORDS + \ |
| 1 /* implementation id array of size 1 */ + \ |
| 1 /* nii_domain */ + \ |
| XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ |
| 1 /* nii_name */ + \ |
| XDR_QUADLEN(IMPL_NAME_LIMIT) + \ |
| 3 /* nii_date */) |
| #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \ |
| 2 /* eir_clientid */ + \ |
| 1 /* eir_sequenceid */ + \ |
| 1 /* eir_flags */ + \ |
| 1 /* spr_how */ + \ |
| /* max is SP4_MACH_CRED (for now) */ + \ |
| 1 + NFS4_OP_MAP_NUM_WORDS + \ |
| 1 + NFS4_OP_MAP_NUM_WORDS + \ |
| 2 /* eir_server_owner.so_minor_id */ + \ |
| /* eir_server_owner.so_major_id<> */ \ |
| XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ |
| /* eir_server_scope<> */ \ |
| XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ |
| 1 /* eir_server_impl_id array length */ + \ |
| 1 /* nii_domain */ + \ |
| XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ |
| 1 /* nii_name */ + \ |
| XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ |
| 3 /* nii_date */) |
| #define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */) |
| #define decode_channel_attrs_maxsz (6 + \ |
| 1 /* ca_rdma_ird.len */ + \ |
| 1 /* ca_rdma_ird */) |
| #define encode_create_session_maxsz (op_encode_hdr_maxsz + \ |
| 2 /* csa_clientid */ + \ |
| 1 /* csa_sequence */ + \ |
| 1 /* csa_flags */ + \ |
| encode_channel_attrs_maxsz + \ |
| encode_channel_attrs_maxsz + \ |
| 1 /* csa_cb_program */ + \ |
| 1 /* csa_sec_parms.len (1) */ + \ |
| 1 /* cb_secflavor (AUTH_SYS) */ + \ |
| 1 /* stamp */ + \ |
| 1 /* machinename.len */ + \ |
| XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \ |
| 1 /* uid */ + \ |
| 1 /* gid */ + \ |
| 1 /* gids.len (0) */) |
| #define decode_create_session_maxsz (op_decode_hdr_maxsz + \ |
| XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ |
| 1 /* csr_sequence */ + \ |
| 1 /* csr_flags */ + \ |
| decode_channel_attrs_maxsz + \ |
| decode_channel_attrs_maxsz) |
| #define encode_bind_conn_to_session_maxsz (op_encode_hdr_maxsz + \ |
| /* bctsa_sessid */ \ |
| XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ |
| 1 /* bctsa_dir */ + \ |
| 1 /* bctsa_use_conn_in_rdma_mode */) |
| #define decode_bind_conn_to_session_maxsz (op_decode_hdr_maxsz + \ |
| /* bctsr_sessid */ \ |
| XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ |
| 1 /* bctsr_dir */ + \ |
| 1 /* bctsr_use_conn_in_rdma_mode */) |
| #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) |
| #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) |
| #define encode_destroy_clientid_maxsz (op_encode_hdr_maxsz + 2) |
| #define decode_destroy_clientid_maxsz (op_decode_hdr_maxsz) |
| #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ |
| XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) |
| #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ |
| XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) |
| #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) |
| #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) |
| #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + \ |
| XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \ |
| 1 /* layout type */ + \ |
| 1 /* maxcount */ + \ |
| 1 /* bitmap size */ + \ |
| 1 /* notification bitmap length */ + \ |
| 1 /* notification bitmap, word 0 */) |
| #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ |
| 1 /* layout type */ + \ |
| 1 /* opaque devaddr4 length */ + \ |
| /* devaddr4 payload is read into page */ \ |
| 1 /* notification bitmap length */ + \ |
| 1 /* notification bitmap, word 0 */ + \ |
| pagepad_maxsz /* possible XDR padding */) |
| #define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \ |
| encode_stateid_maxsz) |
| #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ |
| decode_stateid_maxsz + \ |
| XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE) + \ |
| pagepad_maxsz) |
| #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ |
| 2 /* offset */ + \ |
| 2 /* length */ + \ |
| 1 /* reclaim */ + \ |
| encode_stateid_maxsz + \ |
| 1 /* new offset (true) */ + \ |
| 2 /* last byte written */ + \ |
| 1 /* nt_timechanged (false) */ + \ |
| 1 /* layoutupdate4 layout type */ + \ |
| 1 /* layoutupdate4 opaqueue len */) |
| /* the actual content of layoutupdate4 should |
| be allocated by drivers and spliced in |
| using xdr_write_pages */ |
| #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) |
| #define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \ |
| encode_stateid_maxsz + \ |
| 1 + \ |
| XDR_QUADLEN(NFS4_OPAQUE_LIMIT)) |
| #define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \ |
| 1 + decode_stateid_maxsz) |
| #define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1) |
| #define decode_secinfo_no_name_maxsz decode_secinfo_maxsz |
| #define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \ |
| XDR_QUADLEN(NFS4_STATEID_SIZE)) |
| #define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1) |
| #define encode_free_stateid_maxsz (op_encode_hdr_maxsz + 1 + \ |
| XDR_QUADLEN(NFS4_STATEID_SIZE)) |
| #define decode_free_stateid_maxsz (op_decode_hdr_maxsz) |
| #else /* CONFIG_NFS_V4_1 */ |
| #define encode_sequence_maxsz 0 |
| #define decode_sequence_maxsz 0 |
| #define encode_layoutreturn_maxsz 0 |
| #define decode_layoutreturn_maxsz 0 |
| #define encode_layoutget_maxsz 0 |
| #define decode_layoutget_maxsz 0 |
| #endif /* CONFIG_NFS_V4_1 */ |
| |
| #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ |
| #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ |
| #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_read_maxsz) |
| #define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_read_maxsz) |
| #define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_readlink_maxsz) |
| #define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_readlink_maxsz) |
| #define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_readdir_maxsz) |
| #define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_readdir_maxsz) |
| #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_write_maxsz + \ |
| encode_getattr_maxsz) |
| #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_write_maxsz + \ |
| decode_getattr_maxsz) |
| #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_commit_maxsz) |
| #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_commit_maxsz) |
| #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_open_maxsz + \ |
| encode_access_maxsz + \ |
| encode_getfh_maxsz + \ |
| encode_getattr_maxsz + \ |
| encode_layoutget_maxsz) |
| #define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_open_maxsz + \ |
| decode_access_maxsz + \ |
| decode_getfh_maxsz + \ |
| decode_getattr_maxsz + \ |
| decode_layoutget_maxsz) |
| #define NFS4_enc_open_confirm_sz \ |
| (compound_encode_hdr_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_open_confirm_maxsz) |
| #define NFS4_dec_open_confirm_sz \ |
| (compound_decode_hdr_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_open_confirm_maxsz) |
| #define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_open_maxsz + \ |
| encode_access_maxsz + \ |
| encode_getattr_maxsz + \ |
| encode_layoutget_maxsz) |
| #define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_open_maxsz + \ |
| decode_access_maxsz + \ |
| decode_getattr_maxsz + \ |
| decode_layoutget_maxsz) |
| #define NFS4_enc_open_downgrade_sz \ |
| (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_layoutreturn_maxsz + \ |
| encode_open_downgrade_maxsz) |
| #define NFS4_dec_open_downgrade_sz \ |
| (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_layoutreturn_maxsz + \ |
| decode_open_downgrade_maxsz) |
| #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_layoutreturn_maxsz + \ |
| encode_close_maxsz + \ |
| encode_getattr_maxsz) |
| #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_layoutreturn_maxsz + \ |
| decode_close_maxsz + \ |
| decode_getattr_maxsz) |
| #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_setattr_maxsz + \ |
| encode_getattr_maxsz) |
| #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_setattr_maxsz + \ |
| decode_getattr_maxsz) |
| #define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_fsinfo_maxsz) |
| #define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_fsinfo_maxsz) |
| #define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \ |
| encode_renew_maxsz) |
| #define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \ |
| decode_renew_maxsz) |
| #define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \ |
| encode_setclientid_maxsz) |
| #define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \ |
| decode_setclientid_maxsz) |
| #define NFS4_enc_setclientid_confirm_sz \ |
| (compound_encode_hdr_maxsz + \ |
| encode_setclientid_confirm_maxsz) |
| #define NFS4_dec_setclientid_confirm_sz \ |
| (compound_decode_hdr_maxsz + \ |
| decode_setclientid_confirm_maxsz) |
| #define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_lock_maxsz) |
| #define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_lock_maxsz) |
| #define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_lockt_maxsz) |
| #define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_lockt_maxsz) |
| #define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_locku_maxsz) |
| #define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_locku_maxsz) |
| #define NFS4_enc_release_lockowner_sz \ |
| (compound_encode_hdr_maxsz + \ |
| encode_lockowner_maxsz) |
| #define NFS4_dec_release_lockowner_sz \ |
| (compound_decode_hdr_maxsz + \ |
| decode_lockowner_maxsz) |
| #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_access_maxsz + \ |
| encode_getattr_maxsz) |
| #define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_access_maxsz + \ |
| decode_getattr_maxsz) |
| #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_getattr_maxsz + \ |
| encode_renew_maxsz) |
| #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_getattr_maxsz + \ |
| decode_renew_maxsz) |
| #define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_lookup_maxsz + \ |
| encode_getattr_maxsz + \ |
| encode_getfh_maxsz) |
| #define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_lookup_maxsz + \ |
| decode_getattr_maxsz + \ |
| decode_getfh_maxsz) |
| #define NFS4_enc_lookupp_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_lookupp_maxsz + \ |
| encode_getattr_maxsz + \ |
| encode_getfh_maxsz) |
| #define NFS4_dec_lookupp_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_lookupp_maxsz + \ |
| decode_getattr_maxsz + \ |
| decode_getfh_maxsz) |
| #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putrootfh_maxsz + \ |
| encode_getattr_maxsz + \ |
| encode_getfh_maxsz) |
| #define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putrootfh_maxsz + \ |
| decode_getattr_maxsz + \ |
| decode_getfh_maxsz) |
| #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_remove_maxsz) |
| #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_remove_maxsz) |
| #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_savefh_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_rename_maxsz) |
| #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_savefh_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_rename_maxsz) |
| #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_savefh_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_link_maxsz + \ |
| encode_restorefh_maxsz + \ |
| encode_getattr_maxsz) |
| #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_savefh_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_link_maxsz + \ |
| decode_restorefh_maxsz + \ |
| decode_getattr_maxsz) |
| #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_symlink_maxsz + \ |
| encode_getattr_maxsz + \ |
| encode_getfh_maxsz) |
| #define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_symlink_maxsz + \ |
| decode_getattr_maxsz + \ |
| decode_getfh_maxsz) |
| #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_create_maxsz + \ |
| encode_getfh_maxsz + \ |
| encode_getattr_maxsz) |
| #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_create_maxsz + \ |
| decode_getfh_maxsz + \ |
| decode_getattr_maxsz) |
| #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_getattr_maxsz) |
| #define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_getattr_maxsz) |
| #define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_statfs_maxsz) |
| #define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_statfs_maxsz) |
| #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_getattr_maxsz) |
| #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_getattr_maxsz) |
| #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_layoutreturn_maxsz + \ |
| encode_delegattr_maxsz + \ |
| encode_delegreturn_maxsz + \ |
| encode_getattr_maxsz) |
| #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_layoutreturn_maxsz + \ |
| decode_delegattr_maxsz + \ |
| decode_delegreturn_maxsz + \ |
| decode_getattr_maxsz) |
| #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_getacl_maxsz) |
| #define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_getacl_maxsz) |
| #define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_setacl_maxsz) |
| #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_setacl_maxsz) |
| #define NFS4_enc_fs_locations_sz \ |
| (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_lookup_maxsz + \ |
| encode_fs_locations_maxsz + \ |
| encode_renew_maxsz) |
| #define NFS4_dec_fs_locations_sz \ |
| (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_lookup_maxsz + \ |
| decode_fs_locations_maxsz + \ |
| decode_renew_maxsz) |
| #define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_secinfo_maxsz) |
| #define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_secinfo_maxsz) |
| #define NFS4_enc_fsid_present_sz \ |
| (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_getfh_maxsz + \ |
| encode_renew_maxsz) |
| #define NFS4_dec_fsid_present_sz \ |
| (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_getfh_maxsz + \ |
| decode_renew_maxsz) |
| #if defined(CONFIG_NFS_V4_1) |
| #define NFS4_enc_bind_conn_to_session_sz \ |
| (compound_encode_hdr_maxsz + \ |
| encode_bind_conn_to_session_maxsz) |
| #define NFS4_dec_bind_conn_to_session_sz \ |
| (compound_decode_hdr_maxsz + \ |
| decode_bind_conn_to_session_maxsz) |
| #define NFS4_enc_exchange_id_sz \ |
| (compound_encode_hdr_maxsz + \ |
| encode_exchange_id_maxsz) |
| #define NFS4_dec_exchange_id_sz \ |
| (compound_decode_hdr_maxsz + \ |
| decode_exchange_id_maxsz) |
| #define NFS4_enc_create_session_sz \ |
| (compound_encode_hdr_maxsz + \ |
| encode_create_session_maxsz) |
| #define NFS4_dec_create_session_sz \ |
| (compound_decode_hdr_maxsz + \ |
| decode_create_session_maxsz) |
| #define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \ |
| encode_destroy_session_maxsz) |
| #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ |
| decode_destroy_session_maxsz) |
| #define NFS4_enc_destroy_clientid_sz (compound_encode_hdr_maxsz + \ |
| encode_destroy_clientid_maxsz) |
| #define NFS4_dec_destroy_clientid_sz (compound_decode_hdr_maxsz + \ |
| decode_destroy_clientid_maxsz) |
| #define NFS4_enc_sequence_sz \ |
| (compound_decode_hdr_maxsz + \ |
| encode_sequence_maxsz) |
| #define NFS4_dec_sequence_sz \ |
| (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz) |
| #endif |
| #define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putrootfh_maxsz + \ |
| encode_fsinfo_maxsz) |
| #define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putrootfh_maxsz + \ |
| decode_fsinfo_maxsz) |
| #if defined(CONFIG_NFS_V4_1) |
| #define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_reclaim_complete_maxsz) |
| #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_reclaim_complete_maxsz) |
| #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz +\ |
| encode_getdeviceinfo_maxsz) |
| #define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_getdeviceinfo_maxsz) |
| #define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_layoutget_maxsz) |
| #define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_layoutget_maxsz) |
| #define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz +\ |
| encode_putfh_maxsz + \ |
| encode_layoutcommit_maxsz + \ |
| encode_getattr_maxsz) |
| #define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_layoutcommit_maxsz + \ |
| decode_getattr_maxsz) |
| #define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putfh_maxsz + \ |
| encode_layoutreturn_maxsz) |
| #define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putfh_maxsz + \ |
| decode_layoutreturn_maxsz) |
| #define NFS4_enc_secinfo_no_name_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_putrootfh_maxsz +\ |
| encode_secinfo_no_name_maxsz) |
| #define NFS4_dec_secinfo_no_name_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_putrootfh_maxsz + \ |
| decode_secinfo_no_name_maxsz) |
| #define NFS4_enc_test_stateid_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_test_stateid_maxsz) |
| #define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_test_stateid_maxsz) |
| #define NFS4_enc_free_stateid_sz (compound_encode_hdr_maxsz + \ |
| encode_sequence_maxsz + \ |
| encode_free_stateid_maxsz) |
| #define NFS4_dec_free_stateid_sz (compound_decode_hdr_maxsz + \ |
| decode_sequence_maxsz + \ |
| decode_free_stateid_maxsz) |
| |
| const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + |
| compound_encode_hdr_maxsz + |
| encode_sequence_maxsz + |
| encode_putfh_maxsz + |
| encode_getattr_maxsz) * |
| XDR_UNIT); |
| |
| const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + |
| compound_decode_hdr_maxsz + |
| decode_sequence_maxsz + |
| decode_putfh_maxsz) * |
| XDR_UNIT); |
| |
| const u32 nfs41_maxgetdevinfo_overhead = ((RPC_MAX_REPHEADER_WITH_AUTH + |
| compound_decode_hdr_maxsz + |
| decode_sequence_maxsz) * |
| XDR_UNIT); |
| EXPORT_SYMBOL_GPL(nfs41_maxgetdevinfo_overhead); |
| #endif /* CONFIG_NFS_V4_1 */ |
| |
| static const umode_t nfs_type2fmt[] = { |
| [NF4BAD] = 0, |
| [NF4REG] = S_IFREG, |
| [NF4DIR] = S_IFDIR, |
| [NF4BLK] = S_IFBLK, |
| [NF4CHR] = S_IFCHR, |
| [NF4LNK] = S_IFLNK, |
| [NF4SOCK] = S_IFSOCK, |
| [NF4FIFO] = S_IFIFO, |
| [NF4ATTRDIR] = 0, |
| [NF4NAMEDATTR] = 0, |
| }; |
| |
| struct compound_hdr { |
| int32_t status; |
| uint32_t nops; |
| __be32 * nops_p; |
| uint32_t taglen; |
| char * tag; |
| uint32_t replen; /* expected reply words */ |
| u32 minorversion; |
| }; |
| |
| static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes) |
| { |
| __be32 *p = xdr_reserve_space(xdr, nbytes); |
| BUG_ON(!p); |
| return p; |
| } |
| |
| static void encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len) |
| { |
| WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, buf, len) < 0); |
| } |
| |
| static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) |
| { |
| WARN_ON_ONCE(xdr_stream_encode_opaque(xdr, str, len) < 0); |
| } |
| |
| static void encode_uint32(struct xdr_stream *xdr, u32 n) |
| { |
| WARN_ON_ONCE(xdr_stream_encode_u32(xdr, n) < 0); |
| } |
| |
| static void encode_uint64(struct xdr_stream *xdr, u64 n) |
| { |
| WARN_ON_ONCE(xdr_stream_encode_u64(xdr, n) < 0); |
| } |
| |
| static ssize_t xdr_encode_bitmap4(struct xdr_stream *xdr, |
| const __u32 *bitmap, size_t len) |
| { |
| ssize_t ret; |
| |
| /* Trim empty words */ |
| while (len > 0 && bitmap[len-1] == 0) |
| len--; |
| ret = xdr_stream_encode_uint32_array(xdr, bitmap, len); |
| if (WARN_ON_ONCE(ret < 0)) |
| return ret; |
| return len; |
| } |
| |
| static size_t mask_bitmap4(const __u32 *bitmap, const __u32 *mask, |
| __u32 *res, size_t len) |
| { |
| size_t i; |
| __u32 tmp; |
| |
| while (len > 0 && (bitmap[len-1] == 0 || mask[len-1] == 0)) |
| len--; |
| for (i = len; i-- > 0;) { |
| tmp = bitmap[i] & mask[i]; |
| res[i] = tmp; |
| } |
| return len; |
| } |
| |
| static void encode_nfs4_seqid(struct xdr_stream *xdr, |
| const struct nfs_seqid *seqid) |
| { |
| if (seqid != NULL) |
| encode_uint32(xdr, seqid->sequence->counter); |
| else |
| encode_uint32(xdr, 0); |
| } |
| |
| static void encode_compound_hdr(struct xdr_stream *xdr, |
| struct rpc_rqst *req, |
| struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| /* initialize running count of expected bytes in reply. |
| * NOTE: the replied tag SHOULD be the same is the one sent, |
| * but this is not required as a MUST for the server to do so. */ |
| hdr->replen = 3 + hdr->taglen; |
| |
| WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN); |
| encode_string(xdr, hdr->taglen, hdr->tag); |
| p = reserve_space(xdr, 8); |
| *p++ = cpu_to_be32(hdr->minorversion); |
| hdr->nops_p = p; |
| *p = cpu_to_be32(hdr->nops); |
| } |
| |
| static void encode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 op, |
| uint32_t replen, |
| struct compound_hdr *hdr) |
| { |
| encode_uint32(xdr, op); |
| hdr->nops++; |
| hdr->replen += replen; |
| } |
| |
| static void encode_nops(struct compound_hdr *hdr) |
| { |
| WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS); |
| *hdr->nops_p = htonl(hdr->nops); |
| } |
| |
| static void encode_nfs4_stateid(struct xdr_stream *xdr, |
| const nfs4_stateid *stateid) |
| { |
| encode_opaque_fixed(xdr, stateid->data, NFS4_STATEID_SIZE); |
| } |
| |
| static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf) |
| { |
| encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); |
| } |
| |
| static __be32 * |
| xdr_encode_nfstime4(__be32 *p, const struct timespec64 *t) |
| { |
| p = xdr_encode_hyper(p, t->tv_sec); |
| *p++ = cpu_to_be32(t->tv_nsec); |
| return p; |
| } |
| |
| static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, |
| const struct nfs4_label *label, |
| const umode_t *umask, |
| const struct nfs_server *server, |
| const uint32_t attrmask[]) |
| { |
| char owner_name[IDMAP_NAMESZ]; |
| char owner_group[IDMAP_NAMESZ]; |
| int owner_namelen = 0; |
| int owner_grouplen = 0; |
| __be32 *p; |
| uint32_t len = 0; |
| uint32_t bmval[3] = { 0 }; |
| |
| /* |
| * We reserve enough space to write the entire attribute buffer at once. |
| */ |
| if ((iap->ia_valid & ATTR_SIZE) && (attrmask[0] & FATTR4_WORD0_SIZE)) { |
| bmval[0] |= FATTR4_WORD0_SIZE; |
| len += 8; |
| } |
| if (iap->ia_valid & ATTR_MODE) { |
| if (umask && (attrmask[2] & FATTR4_WORD2_MODE_UMASK)) { |
| bmval[2] |= FATTR4_WORD2_MODE_UMASK; |
| len += 8; |
| } else if (attrmask[1] & FATTR4_WORD1_MODE) { |
| bmval[1] |= FATTR4_WORD1_MODE; |
| len += 4; |
| } |
| } |
| if ((iap->ia_valid & ATTR_UID) && (attrmask[1] & FATTR4_WORD1_OWNER)) { |
| owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); |
| if (owner_namelen < 0) { |
| dprintk("nfs: couldn't resolve uid %d to string\n", |
| from_kuid(&init_user_ns, iap->ia_uid)); |
| /* XXX */ |
| strcpy(owner_name, "nobody"); |
| owner_namelen = sizeof("nobody") - 1; |
| /* goto out; */ |
| } |
| bmval[1] |= FATTR4_WORD1_OWNER; |
| len += 4 + (XDR_QUADLEN(owner_namelen) << 2); |
| } |
| if ((iap->ia_valid & ATTR_GID) && |
| (attrmask[1] & FATTR4_WORD1_OWNER_GROUP)) { |
| owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ); |
| if (owner_grouplen < 0) { |
| dprintk("nfs: couldn't resolve gid %d to string\n", |
| from_kgid(&init_user_ns, iap->ia_gid)); |
| strcpy(owner_group, "nobody"); |
| owner_grouplen = sizeof("nobody") - 1; |
| /* goto out; */ |
| } |
| bmval[1] |= FATTR4_WORD1_OWNER_GROUP; |
| len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); |
| } |
| if (attrmask[1] & FATTR4_WORD1_TIME_ACCESS_SET) { |
| if (iap->ia_valid & ATTR_ATIME_SET) { |
| bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; |
| len += 4 + (nfstime4_maxsz << 2); |
| } else if (iap->ia_valid & ATTR_ATIME) { |
| bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; |
| len += 4; |
| } |
| } |
| if (attrmask[1] & FATTR4_WORD1_TIME_MODIFY_SET) { |
| if (iap->ia_valid & ATTR_MTIME_SET) { |
| bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; |
| len += 4 + (nfstime4_maxsz << 2); |
| } else if (iap->ia_valid & ATTR_MTIME) { |
| bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; |
| len += 4; |
| } |
| } |
| |
| if (label && (attrmask[2] & FATTR4_WORD2_SECURITY_LABEL)) { |
| len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); |
| bmval[2] |= FATTR4_WORD2_SECURITY_LABEL; |
| } |
| |
| xdr_encode_bitmap4(xdr, bmval, ARRAY_SIZE(bmval)); |
| xdr_stream_encode_opaque_inline(xdr, (void **)&p, len); |
| |
| if (bmval[0] & FATTR4_WORD0_SIZE) |
| p = xdr_encode_hyper(p, iap->ia_size); |
| if (bmval[1] & FATTR4_WORD1_MODE) |
| *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); |
| if (bmval[1] & FATTR4_WORD1_OWNER) |
| p = xdr_encode_opaque(p, owner_name, owner_namelen); |
| if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) |
| p = xdr_encode_opaque(p, owner_group, owner_grouplen); |
| if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { |
| if (iap->ia_valid & ATTR_ATIME_SET) { |
| *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); |
| p = xdr_encode_nfstime4(p, &iap->ia_atime); |
| } else |
| *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); |
| } |
| if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { |
| if (iap->ia_valid & ATTR_MTIME_SET) { |
| *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); |
| p = xdr_encode_nfstime4(p, &iap->ia_mtime); |
| } else |
| *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); |
| } |
| if (label && (bmval[2] & FATTR4_WORD2_SECURITY_LABEL)) { |
| *p++ = cpu_to_be32(label->lfs); |
| *p++ = cpu_to_be32(label->pi); |
| *p++ = cpu_to_be32(label->len); |
| p = xdr_encode_opaque_fixed(p, label->label, label->len); |
| } |
| if (bmval[2] & FATTR4_WORD2_MODE_UMASK) { |
| *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); |
| *p++ = cpu_to_be32(*umask); |
| } |
| |
| /* out: */ |
| } |
| |
| static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_ACCESS, decode_access_maxsz, hdr); |
| encode_uint32(xdr, access); |
| } |
| |
| static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_CLOSE, decode_close_maxsz, hdr); |
| encode_nfs4_seqid(xdr, arg->seqid); |
| encode_nfs4_stateid(xdr, &arg->stateid); |
| } |
| |
| static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr); |
| p = reserve_space(xdr, 12); |
| p = xdr_encode_hyper(p, args->offset); |
| *p = cpu_to_be32(args->count); |
| } |
| |
| static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_CREATE, decode_create_maxsz, hdr); |
| encode_uint32(xdr, create->ftype); |
| |
| switch (create->ftype) { |
| case NF4LNK: |
| p = reserve_space(xdr, 4); |
| *p = cpu_to_be32(create->u.symlink.len); |
| xdr_write_pages(xdr, create->u.symlink.pages, 0, |
| create->u.symlink.len); |
| xdr->buf->flags |= XDRBUF_WRITE; |
| break; |
| |
| case NF4BLK: case NF4CHR: |
| p = reserve_space(xdr, 8); |
| *p++ = cpu_to_be32(create->u.device.specdata1); |
| *p = cpu_to_be32(create->u.device.specdata2); |
| break; |
| |
| default: |
| break; |
| } |
| |
| encode_string(xdr, create->name->len, create->name->name); |
| encode_attrs(xdr, create->attrs, create->label, &create->umask, |
| create->server, create->server->attr_bitmask); |
| } |
| |
| static void encode_getattr(struct xdr_stream *xdr, |
| const __u32 *bitmap, const __u32 *mask, size_t len, |
| struct compound_hdr *hdr) |
| { |
| __u32 masked_bitmap[nfs4_fattr_bitmap_maxsz]; |
| |
| encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr); |
| if (mask) { |
| if (WARN_ON_ONCE(len > ARRAY_SIZE(masked_bitmap))) |
| len = ARRAY_SIZE(masked_bitmap); |
| len = mask_bitmap4(bitmap, mask, masked_bitmap, len); |
| bitmap = masked_bitmap; |
| } |
| xdr_encode_bitmap4(xdr, bitmap, len); |
| } |
| |
| static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
| { |
| encode_getattr(xdr, nfs4_fattr_bitmap, bitmask, |
| ARRAY_SIZE(nfs4_fattr_bitmap), hdr); |
| } |
| |
| static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, |
| const u32 *open_bitmap, |
| struct compound_hdr *hdr) |
| { |
| encode_getattr(xdr, open_bitmap, bitmask, 3, hdr); |
| } |
| |
| static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
| { |
| encode_getattr(xdr, nfs4_fsinfo_bitmap, bitmask, |
| ARRAY_SIZE(nfs4_fsinfo_bitmap), hdr); |
| } |
| |
| static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
| { |
| encode_getattr(xdr, nfs4_fs_locations_bitmap, bitmask, |
| ARRAY_SIZE(nfs4_fs_locations_bitmap), hdr); |
| } |
| |
| static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_GETFH, decode_getfh_maxsz, hdr); |
| } |
| |
| static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_LINK, decode_link_maxsz, hdr); |
| encode_string(xdr, name->len, name->name); |
| } |
| |
| static inline int nfs4_lock_type(struct file_lock *fl, int block) |
| { |
| if (lock_is_read(fl)) |
| return block ? NFS4_READW_LT : NFS4_READ_LT; |
| return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; |
| } |
| |
| static inline uint64_t nfs4_lock_length(struct file_lock *fl) |
| { |
| if (fl->fl_end == OFFSET_MAX) |
| return ~(uint64_t)0; |
| return fl->fl_end - fl->fl_start + 1; |
| } |
| |
| static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner) |
| { |
| __be32 *p; |
| |
| p = reserve_space(xdr, 32); |
| p = xdr_encode_hyper(p, lowner->clientid); |
| *p++ = cpu_to_be32(20); |
| p = xdr_encode_opaque_fixed(p, "lock id:", 8); |
| *p++ = cpu_to_be32(lowner->s_dev); |
| xdr_encode_hyper(p, lowner->id); |
| } |
| |
| /* |
| * opcode,type,reclaim,offset,length,new_lock_owner = 32 |
| * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 |
| */ |
| static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_LOCK, decode_lock_maxsz, hdr); |
| p = reserve_space(xdr, 28); |
| *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block)); |
| *p++ = cpu_to_be32(args->reclaim); |
| p = xdr_encode_hyper(p, args->fl->fl_start); |
| p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); |
| *p = cpu_to_be32(args->new_lock_owner); |
| if (args->new_lock_owner){ |
| encode_nfs4_seqid(xdr, args->open_seqid); |
| encode_nfs4_stateid(xdr, &args->open_stateid); |
| encode_nfs4_seqid(xdr, args->lock_seqid); |
| encode_lockowner(xdr, &args->lock_owner); |
| } |
| else { |
| encode_nfs4_stateid(xdr, &args->lock_stateid); |
| encode_nfs4_seqid(xdr, args->lock_seqid); |
| } |
| } |
| |
| static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_LOCKT, decode_lockt_maxsz, hdr); |
| p = reserve_space(xdr, 20); |
| *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); |
| p = xdr_encode_hyper(p, args->fl->fl_start); |
| p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); |
| encode_lockowner(xdr, &args->lock_owner); |
| } |
| |
| static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_LOCKU, decode_locku_maxsz, hdr); |
| encode_uint32(xdr, nfs4_lock_type(args->fl, 0)); |
| encode_nfs4_seqid(xdr, args->seqid); |
| encode_nfs4_stateid(xdr, &args->stateid); |
| p = reserve_space(xdr, 16); |
| p = xdr_encode_hyper(p, args->fl->fl_start); |
| xdr_encode_hyper(p, nfs4_lock_length(args->fl)); |
| } |
| |
| static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_RELEASE_LOCKOWNER, decode_release_lockowner_maxsz, hdr); |
| encode_lockowner(xdr, lowner); |
| } |
| |
| static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_LOOKUP, decode_lookup_maxsz, hdr); |
| encode_string(xdr, name->len, name->name); |
| } |
| |
| static void encode_lookupp(struct xdr_stream *xdr, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_LOOKUPP, decode_lookupp_maxsz, hdr); |
| } |
| |
| static void encode_share_access(struct xdr_stream *xdr, u32 share_access) |
| { |
| __be32 *p; |
| |
| p = reserve_space(xdr, 8); |
| *p++ = cpu_to_be32(share_access); |
| *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */ |
| } |
| |
| static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg) |
| { |
| __be32 *p; |
| /* |
| * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, |
| * owner 4 = 32 |
| */ |
| encode_nfs4_seqid(xdr, arg->seqid); |
| encode_share_access(xdr, arg->share_access); |
| p = reserve_space(xdr, 36); |
| p = xdr_encode_hyper(p, arg->clientid); |
| *p++ = cpu_to_be32(24); |
| p = xdr_encode_opaque_fixed(p, "open id:", 8); |
| *p++ = cpu_to_be32(arg->server->s_dev); |
| *p++ = cpu_to_be32(arg->id.uniquifier); |
| xdr_encode_hyper(p, arg->id.create_time); |
| } |
| |
| static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) |
| { |
| __be32 *p; |
| |
| p = reserve_space(xdr, 4); |
| switch(arg->createmode) { |
| case NFS4_CREATE_UNCHECKED: |
| *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); |
| encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask, |
| arg->server, arg->server->attr_bitmask); |
| break; |
| case NFS4_CREATE_GUARDED: |
| *p = cpu_to_be32(NFS4_CREATE_GUARDED); |
| encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask, |
| arg->server, arg->server->attr_bitmask); |
| break; |
| case NFS4_CREATE_EXCLUSIVE: |
| *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); |
| encode_nfs4_verifier(xdr, &arg->u.verifier); |
| break; |
| case NFS4_CREATE_EXCLUSIVE4_1: |
| *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); |
| encode_nfs4_verifier(xdr, &arg->u.verifier); |
| encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask, |
| arg->server, arg->server->exclcreat_bitmask); |
| } |
| } |
| |
| static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg) |
| { |
| __be32 *p; |
| |
| p = reserve_space(xdr, 4); |
| switch (arg->open_flags & O_CREAT) { |
| case 0: |
| *p = cpu_to_be32(NFS4_OPEN_NOCREATE); |
| break; |
| default: |
| *p = cpu_to_be32(NFS4_OPEN_CREATE); |
| encode_createmode(xdr, arg); |
| } |
| } |
| |
| static inline void encode_delegation_type(struct xdr_stream *xdr, u32 delegation_type) |
| { |
| __be32 *p; |
| |
| p = reserve_space(xdr, 4); |
| switch (delegation_type) { |
| case NFS4_OPEN_DELEGATE_NONE: |
| case NFS4_OPEN_DELEGATE_READ: |
| case NFS4_OPEN_DELEGATE_WRITE: |
| case NFS4_OPEN_DELEGATE_READ_ATTRS_DELEG: |
| case NFS4_OPEN_DELEGATE_WRITE_ATTRS_DELEG: |
| *p = cpu_to_be32(delegation_type); |
| break; |
| default: |
| BUG(); |
| } |
| } |
| |
| static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name) |
| { |
| __be32 *p; |
| |
| p = reserve_space(xdr, 4); |
| *p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL); |
| encode_string(xdr, name->len, name->name); |
| } |
| |
| static inline void encode_claim_previous(struct xdr_stream *xdr, u32 type) |
| { |
| __be32 *p; |
| |
| p = reserve_space(xdr, 4); |
| *p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS); |
| encode_delegation_type(xdr, type); |
| } |
| |
| static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid) |
| { |
| __be32 *p; |
| |
| p = reserve_space(xdr, 4); |
| *p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR); |
| encode_nfs4_stateid(xdr, stateid); |
| encode_string(xdr, name->len, name->name); |
| } |
| |
| static inline void encode_claim_fh(struct xdr_stream *xdr) |
| { |
| __be32 *p; |
| |
| p = reserve_space(xdr, 4); |
| *p = cpu_to_be32(NFS4_OPEN_CLAIM_FH); |
| } |
| |
| static inline void encode_claim_delegate_cur_fh(struct xdr_stream *xdr, const nfs4_stateid *stateid) |
| { |
| __be32 *p; |
| |
| p = reserve_space(xdr, 4); |
| *p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEG_CUR_FH); |
| encode_nfs4_stateid(xdr, stateid); |
| } |
| |
| static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_OPEN, decode_open_maxsz, hdr); |
| encode_openhdr(xdr, arg); |
| encode_opentype(xdr, arg); |
| switch (arg->claim) { |
| case NFS4_OPEN_CLAIM_NULL: |
| encode_claim_null(xdr, arg->name); |
| break; |
| case NFS4_OPEN_CLAIM_PREVIOUS: |
| encode_claim_previous(xdr, arg->u.delegation_type); |
| break; |
| case NFS4_OPEN_CLAIM_DELEGATE_CUR: |
| encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation); |
| break; |
| case NFS4_OPEN_CLAIM_FH: |
| encode_claim_fh(xdr); |
| break; |
| case NFS4_OPEN_CLAIM_DELEG_CUR_FH: |
| encode_claim_delegate_cur_fh(xdr, &arg->u.delegation); |
| break; |
| default: |
| BUG(); |
| } |
| } |
| |
| static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_OPEN_CONFIRM, decode_open_confirm_maxsz, hdr); |
| encode_nfs4_stateid(xdr, arg->stateid); |
| encode_nfs4_seqid(xdr, arg->seqid); |
| } |
| |
| static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr); |
| encode_nfs4_stateid(xdr, &arg->stateid); |
| encode_nfs4_seqid(xdr, arg->seqid); |
| encode_share_access(xdr, arg->share_access); |
| } |
| |
| static void |
| encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_PUTFH, decode_putfh_maxsz, hdr); |
| encode_string(xdr, fh->size, fh->data); |
| } |
| |
| static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr); |
| } |
| |
| static void encode_read(struct xdr_stream *xdr, const struct nfs_pgio_args *args, |
| struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr); |
| encode_nfs4_stateid(xdr, &args->stateid); |
| |
| p = reserve_space(xdr, 12); |
| p = xdr_encode_hyper(p, args->offset); |
| *p = cpu_to_be32(args->count); |
| } |
| |
| static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) |
| { |
| uint32_t attrs[3] = { |
| FATTR4_WORD0_TYPE |
| | FATTR4_WORD0_RDATTR_ERROR, |
| FATTR4_WORD1_MOUNTED_ON_FILEID, |
| }; |
| uint32_t dircount = readdir->count; |
| uint32_t maxcount = readdir->count; |
| __be32 *p, verf[2]; |
| uint32_t attrlen = 0; |
| unsigned int i; |
| |
| if (readdir->plus) { |
| attrs[0] |= FATTR4_WORD0_CHANGE |
| | FATTR4_WORD0_SIZE |
| | FATTR4_WORD0_FSID |
| | FATTR4_WORD0_FILEHANDLE |
| | FATTR4_WORD0_FILEID; |
| attrs[1] |= FATTR4_WORD1_MODE |
| | FATTR4_WORD1_NUMLINKS |
| | FATTR4_WORD1_OWNER |
| | FATTR4_WORD1_OWNER_GROUP |
| | FATTR4_WORD1_RAWDEV |
| | FATTR4_WORD1_SPACE_USED |
| | FATTR4_WORD1_TIME_ACCESS |
| | FATTR4_WORD1_TIME_METADATA |
| | FATTR4_WORD1_TIME_MODIFY; |
| attrs[2] |= FATTR4_WORD2_SECURITY_LABEL; |
| } |
| /* Use mounted_on_fileid only if the server supports it */ |
| if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) |
| attrs[0] |= FATTR4_WORD0_FILEID; |
| for (i = 0; i < ARRAY_SIZE(attrs); i++) { |
| attrs[i] &= readdir->bitmask[i]; |
| if (attrs[i] != 0) |
| attrlen = i+1; |
| } |
| |
| encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); |
| encode_uint64(xdr, readdir->cookie); |
| encode_nfs4_verifier(xdr, &readdir->verifier); |
| p = reserve_space(xdr, 12 + (attrlen << 2)); |
| *p++ = cpu_to_be32(dircount); |
| *p++ = cpu_to_be32(maxcount); |
| *p++ = cpu_to_be32(attrlen); |
| for (i = 0; i < attrlen; i++) |
| *p++ = cpu_to_be32(attrs[i]); |
| memcpy(verf, readdir->verifier.data, sizeof(verf)); |
| |
| dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n", |
| __func__, |
| (unsigned long long)readdir->cookie, |
| verf[0], verf[1], |
| attrs[0] & readdir->bitmask[0], |
| attrs[1] & readdir->bitmask[1], |
| attrs[2] & readdir->bitmask[2]); |
| } |
| |
| static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_READLINK, decode_readlink_maxsz, hdr); |
| } |
| |
| static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_REMOVE, decode_remove_maxsz, hdr); |
| encode_string(xdr, name->len, name->name); |
| } |
| |
| static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_RENAME, decode_rename_maxsz, hdr); |
| encode_string(xdr, oldname->len, oldname->name); |
| encode_string(xdr, newname->len, newname->name); |
| } |
| |
| static void encode_renew(struct xdr_stream *xdr, clientid4 clid, |
| struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_RENEW, decode_renew_maxsz, hdr); |
| encode_uint64(xdr, clid); |
| } |
| |
| static void |
| encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_RESTOREFH, decode_restorefh_maxsz, hdr); |
| } |
| |
| static void nfs4_acltype_to_bitmap(enum nfs4_acl_type type, __u32 bitmap[2]) |
| { |
| switch (type) { |
| default: |
| bitmap[0] = FATTR4_WORD0_ACL; |
| bitmap[1] = 0; |
| break; |
| case NFS4ACL_DACL: |
| bitmap[0] = 0; |
| bitmap[1] = FATTR4_WORD1_DACL; |
| break; |
| case NFS4ACL_SACL: |
| bitmap[0] = 0; |
| bitmap[1] = FATTR4_WORD1_SACL; |
| } |
| } |
| |
| static void encode_setacl(struct xdr_stream *xdr, |
| const struct nfs_setaclargs *arg, |
| struct compound_hdr *hdr) |
| { |
| __u32 bitmap[2]; |
| |
| nfs4_acltype_to_bitmap(arg->acl_type, bitmap); |
| |
| encode_op_hdr(xdr, OP_SETATTR, decode_setacl_maxsz, hdr); |
| encode_nfs4_stateid(xdr, &zero_stateid); |
| xdr_encode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap)); |
| encode_uint32(xdr, arg->acl_len); |
| xdr_write_pages(xdr, arg->acl_pages, 0, arg->acl_len); |
| } |
| |
| static void |
| encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_SAVEFH, decode_savefh_maxsz, hdr); |
| } |
| |
| static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); |
| encode_nfs4_stateid(xdr, &arg->stateid); |
| encode_attrs(xdr, arg->iap, arg->label, NULL, server, |
| server->attr_bitmask); |
| } |
| |
| static void encode_delegattr(struct xdr_stream *xdr, |
| const nfs4_stateid *stateid, |
| const struct nfs4_delegattr *attr, |
| struct compound_hdr *hdr) |
| { |
| uint32_t bitmap[3] = { 0 }; |
| uint32_t len = 0; |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_SETATTR, encode_delegattr_maxsz, hdr); |
| encode_nfs4_stateid(xdr, stateid); |
| if (attr->atime_set) { |
| bitmap[2] |= FATTR4_WORD2_TIME_DELEG_ACCESS; |
| len += (nfstime4_maxsz << 2); |
| } |
| if (attr->mtime_set) { |
| bitmap[2] |= FATTR4_WORD2_TIME_DELEG_MODIFY; |
| len += (nfstime4_maxsz << 2); |
| } |
| xdr_encode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap)); |
| xdr_stream_encode_opaque_inline(xdr, (void **)&p, len); |
| if (bitmap[2] & FATTR4_WORD2_TIME_DELEG_ACCESS) |
| p = xdr_encode_nfstime4(p, &attr->atime); |
| if (bitmap[2] & FATTR4_WORD2_TIME_DELEG_MODIFY) |
| p = xdr_encode_nfstime4(p, &attr->mtime); |
| } |
| |
| static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_SETCLIENTID, decode_setclientid_maxsz, hdr); |
| encode_nfs4_verifier(xdr, setclientid->sc_verifier); |
| |
| encode_string(xdr, strlen(setclientid->sc_clnt->cl_owner_id), |
| setclientid->sc_clnt->cl_owner_id); |
| p = reserve_space(xdr, 4); |
| *p = cpu_to_be32(setclientid->sc_prog); |
| encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid); |
| encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr); |
| p = reserve_space(xdr, 4); |
| *p = cpu_to_be32(setclientid->sc_clnt->cl_cb_ident); |
| } |
| |
| static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM, |
| decode_setclientid_confirm_maxsz, hdr); |
| encode_uint64(xdr, arg->clientid); |
| encode_nfs4_verifier(xdr, &arg->confirm); |
| } |
| |
| static void encode_write(struct xdr_stream *xdr, const struct nfs_pgio_args *args, |
| struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_WRITE, decode_write_maxsz, hdr); |
| encode_nfs4_stateid(xdr, &args->stateid); |
| |
| p = reserve_space(xdr, 16); |
| p = xdr_encode_hyper(p, args->offset); |
| *p++ = cpu_to_be32(args->stable); |
| *p = cpu_to_be32(args->count); |
| |
| xdr_write_pages(xdr, args->pages, args->pgbase, args->count); |
| } |
| |
| static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_DELEGRETURN, decode_delegreturn_maxsz, hdr); |
| encode_nfs4_stateid(xdr, stateid); |
| } |
| |
| static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_SECINFO, decode_secinfo_maxsz, hdr); |
| encode_string(xdr, name->len, name->name); |
| } |
| |
| #if defined(CONFIG_NFS_V4_1) |
| /* NFSv4.1 operations */ |
| static void encode_bind_conn_to_session(struct xdr_stream *xdr, |
| const struct nfs41_bind_conn_to_session_args *args, |
| struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION, |
| decode_bind_conn_to_session_maxsz, hdr); |
| encode_opaque_fixed(xdr, args->sessionid.data, NFS4_MAX_SESSIONID_LEN); |
| p = xdr_reserve_space(xdr, 8); |
| *p++ = cpu_to_be32(args->dir); |
| *p = (args->use_conn_in_rdma_mode) ? cpu_to_be32(1) : cpu_to_be32(0); |
| } |
| |
| static void encode_op_map(struct xdr_stream *xdr, const struct nfs4_op_map *op_map) |
| { |
| unsigned int i; |
| encode_uint32(xdr, NFS4_OP_MAP_NUM_WORDS); |
| for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++) |
| encode_uint32(xdr, op_map->u.words[i]); |
| } |
| |
| static void encode_exchange_id(struct xdr_stream *xdr, |
| const struct nfs41_exchange_id_args *args, |
| struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| char impl_name[IMPL_NAME_LIMIT]; |
| int len = 0; |
| |
| encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr); |
| encode_nfs4_verifier(xdr, &args->verifier); |
| |
| encode_string(xdr, strlen(args->client->cl_owner_id), |
| args->client->cl_owner_id); |
| |
| encode_uint32(xdr, args->flags); |
| encode_uint32(xdr, args->state_protect.how); |
| |
| switch (args->state_protect.how) { |
| case SP4_NONE: |
| break; |
| case SP4_MACH_CRED: |
| encode_op_map(xdr, &args->state_protect.enforce); |
| encode_op_map(xdr, &args->state_protect.allow); |
| break; |
| default: |
| WARN_ON_ONCE(1); |
| break; |
| } |
| |
| if (send_implementation_id && |
| sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 && |
| sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) |
| <= sizeof(impl_name) + 1) |
| len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s", |
| utsname()->sysname, utsname()->release, |
| utsname()->version, utsname()->machine); |
| |
| if (len > 0) { |
| encode_uint32(xdr, 1); /* implementation id array length=1 */ |
| |
| encode_string(xdr, |
| sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1, |
| CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN); |
| encode_string(xdr, len, impl_name); |
| /* just send zeros for nii_date - the date is in nii_name */ |
| p = reserve_space(xdr, 12); |
| p = xdr_encode_hyper(p, 0); |
| *p = cpu_to_be32(0); |
| } else |
| encode_uint32(xdr, 0); /* implementation id array length=0 */ |
| } |
| |
| static void encode_create_session(struct xdr_stream *xdr, |
| const struct nfs41_create_session_args *args, |
| struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| struct nfs_client *clp = args->client; |
| struct rpc_clnt *clnt = clp->cl_rpcclient; |
| struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); |
| u32 max_resp_sz_cached; |
| |
| /* |
| * Assumes OPEN is the biggest non-idempotent compound. |
| * 2 is the verifier. |
| */ |
| max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + 2) |
| * XDR_UNIT + RPC_MAX_AUTH_SIZE; |
| |
| encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr); |
| p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12); |
| p = xdr_encode_hyper(p, args->clientid); |
| *p++ = cpu_to_be32(args->seqid); /*Sequence id */ |
| *p++ = cpu_to_be32(args->flags); /*flags */ |
| |
| /* Fore Channel */ |
| *p++ = cpu_to_be32(0); /* header padding size */ |
| *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ |
| *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ |
| *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ |
| *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */ |
| *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */ |
| *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ |
| |
| /* Back Channel */ |
| *p++ = cpu_to_be32(0); /* header padding size */ |
| *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ |
| *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ |
| *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ |
| *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */ |
| *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */ |
| *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ |
| |
| *p++ = cpu_to_be32(args->cb_program); /* cb_program */ |
| *p++ = cpu_to_be32(1); |
| *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ |
| |
| /* authsys_parms rfc1831 */ |
| *p++ = cpu_to_be32(ktime_to_ns(nn->boot_time)); /* stamp */ |
| p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen); |
| *p++ = cpu_to_be32(0); /* UID */ |
| *p++ = cpu_to_be32(0); /* GID */ |
| *p = cpu_to_be32(0); /* No more gids */ |
| } |
| |
| static void encode_destroy_session(struct xdr_stream *xdr, |
| const struct nfs4_session *session, |
| struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_DESTROY_SESSION, decode_destroy_session_maxsz, hdr); |
| encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); |
| } |
| |
| static void encode_destroy_clientid(struct xdr_stream *xdr, |
| uint64_t clientid, |
| struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_DESTROY_CLIENTID, decode_destroy_clientid_maxsz, hdr); |
| encode_uint64(xdr, clientid); |
| } |
| |
| static void encode_reclaim_complete(struct xdr_stream *xdr, |
| const struct nfs41_reclaim_complete_args *args, |
| struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_RECLAIM_COMPLETE, decode_reclaim_complete_maxsz, hdr); |
| encode_uint32(xdr, args->one_fs); |
| } |
| #endif /* CONFIG_NFS_V4_1 */ |
| |
| static void encode_sequence(struct xdr_stream *xdr, |
| const struct nfs4_sequence_args *args, |
| struct compound_hdr *hdr) |
| { |
| #if defined(CONFIG_NFS_V4_1) |
| struct nfs4_session *session; |
| struct nfs4_slot_table *tp; |
| struct nfs4_slot *slot = args->sa_slot; |
| __be32 *p; |
| |
| tp = slot->table; |
| session = tp->session; |
| if (!session) |
| return; |
| |
| encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr); |
| |
| /* |
| * Sessionid + seqid + slotid + max slotid + cache_this |
| */ |
| dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d " |
| "max_slotid=%d cache_this=%d\n", |
| __func__, |
| ((u32 *)session->sess_id.data)[0], |
| ((u32 *)session->sess_id.data)[1], |
| ((u32 *)session->sess_id.data)[2], |
| ((u32 *)session->sess_id.data)[3], |
| slot->seq_nr, slot->slot_nr, |
| tp->highest_used_slotid, args->sa_cache_this); |
| p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16); |
| p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); |
| *p++ = cpu_to_be32(slot->seq_nr); |
| *p++ = cpu_to_be32(slot->slot_nr); |
| *p++ = cpu_to_be32(tp->highest_used_slotid); |
| *p = cpu_to_be32(args->sa_cache_this); |
| #endif /* CONFIG_NFS_V4_1 */ |
| } |
| |
| #ifdef CONFIG_NFS_V4_1 |
| static void |
| encode_getdeviceinfo(struct xdr_stream *xdr, |
| const struct nfs4_getdeviceinfo_args *args, |
| struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_GETDEVICEINFO, decode_getdeviceinfo_maxsz, hdr); |
| p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 4 + 4); |
| p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, |
| NFS4_DEVICEID4_SIZE); |
| *p++ = cpu_to_be32(args->pdev->layout_type); |
| *p++ = cpu_to_be32(args->pdev->maxcount); /* gdia_maxcount */ |
| |
| p = reserve_space(xdr, 4 + 4); |
| *p++ = cpu_to_be32(1); /* bitmap length */ |
| *p++ = cpu_to_be32(args->notify_types); |
| } |
| |
| static void |
| encode_layoutget(struct xdr_stream *xdr, |
| const struct nfs4_layoutget_args *args, |
| struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_LAYOUTGET, decode_layoutget_maxsz, hdr); |
| p = reserve_space(xdr, 36); |
| *p++ = cpu_to_be32(0); /* Signal layout available */ |
| *p++ = cpu_to_be32(args->type); |
| *p++ = cpu_to_be32(args->range.iomode); |
| p = xdr_encode_hyper(p, args->range.offset); |
| p = xdr_encode_hyper(p, args->range.length); |
| p = xdr_encode_hyper(p, args->minlength); |
| encode_nfs4_stateid(xdr, &args->stateid); |
| encode_uint32(xdr, args->maxcount); |
| |
| dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", |
| __func__, |
| args->type, |
| args->range.iomode, |
| (unsigned long)args->range.offset, |
| (unsigned long)args->range.length, |
| args->maxcount); |
| } |
| |
| static int |
| encode_layoutcommit(struct xdr_stream *xdr, |
| struct inode *inode, |
| const struct nfs4_layoutcommit_args *args, |
| struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, |
| NFS_SERVER(args->inode)->pnfs_curr_ld->id); |
| |
| encode_op_hdr(xdr, OP_LAYOUTCOMMIT, decode_layoutcommit_maxsz, hdr); |
| p = reserve_space(xdr, 20); |
| /* Only whole file layouts */ |
| p = xdr_encode_hyper(p, 0); /* offset */ |
| p = xdr_encode_hyper(p, args->lastbytewritten + 1); /* length */ |
| *p = cpu_to_be32(0); /* reclaim */ |
| encode_nfs4_stateid(xdr, &args->stateid); |
| if (args->lastbytewritten != U64_MAX) { |
| p = reserve_space(xdr, 20); |
| *p++ = cpu_to_be32(1); /* newoffset = TRUE */ |
| p = xdr_encode_hyper(p, args->lastbytewritten); |
| } else { |
| p = reserve_space(xdr, 12); |
| *p++ = cpu_to_be32(0); /* newoffset = FALSE */ |
| } |
| *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ |
| *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ |
| |
| encode_uint32(xdr, args->layoutupdate_len); |
| if (args->layoutupdate_pages) |
| xdr_write_pages(xdr, args->layoutupdate_pages, 0, |
| args->layoutupdate_len); |
| |
| return 0; |
| } |
| |
| static void |
| encode_layoutreturn(struct xdr_stream *xdr, |
| const struct nfs4_layoutreturn_args *args, |
| struct compound_hdr *hdr) |
| { |
| __be32 *p; |
| |
| encode_op_hdr(xdr, OP_LAYOUTRETURN, decode_layoutreturn_maxsz, hdr); |
| p = reserve_space(xdr, 16); |
| *p++ = cpu_to_be32(0); /* reclaim. always 0 for now */ |
| *p++ = cpu_to_be32(args->layout_type); |
| *p++ = cpu_to_be32(args->range.iomode); |
| *p = cpu_to_be32(RETURN_FILE); |
| p = reserve_space(xdr, 16); |
| p = xdr_encode_hyper(p, args->range.offset); |
| p = xdr_encode_hyper(p, args->range.length); |
| spin_lock(&args->inode->i_lock); |
| encode_nfs4_stateid(xdr, &args->stateid); |
| spin_unlock(&args->inode->i_lock); |
| if (args->ld_private->ops && args->ld_private->ops->encode) |
| args->ld_private->ops->encode(xdr, args, args->ld_private); |
| else |
| encode_uint32(xdr, 0); |
| } |
| |
| static int |
| encode_secinfo_no_name(struct xdr_stream *xdr, |
| const struct nfs41_secinfo_no_name_args *args, |
| struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_SECINFO_NO_NAME, decode_secinfo_no_name_maxsz, hdr); |
| encode_uint32(xdr, args->style); |
| return 0; |
| } |
| |
| static void encode_test_stateid(struct xdr_stream *xdr, |
| const struct nfs41_test_stateid_args *args, |
| struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_TEST_STATEID, decode_test_stateid_maxsz, hdr); |
| encode_uint32(xdr, 1); |
| encode_nfs4_stateid(xdr, &args->stateid); |
| } |
| |
| static void encode_free_stateid(struct xdr_stream *xdr, |
| const struct nfs41_free_stateid_args *args, |
| struct compound_hdr *hdr) |
| { |
| encode_op_hdr(xdr, OP_FREE_STATEID, decode_free_stateid_maxsz, hdr); |
| encode_nfs4_stateid(xdr, &args->stateid); |
| } |
| #else |
| static inline void |
| encode_layoutreturn(struct xdr_stream *xdr, |
| const struct nfs4_layoutreturn_args *args, |
| struct compound_hdr *hdr) |
| { |
| } |
| |
| static void |
| encode_layoutget(struct xdr_stream *xdr, |
| const struct nfs4_layoutget_args *args, |
| struct compound_hdr *hdr) |
| { |
| } |
| #endif /* CONFIG_NFS_V4_1 */ |
| |
| /* |
| * END OF "GENERIC" ENCODE ROUTINES. |
| */ |
| |
| static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) |
| { |
| #if defined(CONFIG_NFS_V4_1) |
| struct nfs4_session *session = args->sa_slot->table->session; |
| if (session) |
| return session->clp->cl_mvops->minor_version; |
| #endif /* CONFIG_NFS_V4_1 */ |
| return 0; |
| } |
| |
| /* |
| * Encode an ACCESS request |
| */ |
| static void nfs4_xdr_enc_access(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_accessargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_access(xdr, args->access, &hdr); |
| if (args->bitmask) |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode LOOKUP request |
| */ |
| static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_lookup_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->dir_fh, &hdr); |
| encode_lookup(xdr, args->name, &hdr); |
| encode_getfh(xdr, &hdr); |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode LOOKUPP request |
| */ |
| static void nfs4_xdr_enc_lookupp(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_lookupp_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_lookupp(xdr, &hdr); |
| encode_getfh(xdr, &hdr); |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode LOOKUP_ROOT request |
| */ |
| static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, |
| struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_lookup_root_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putrootfh(xdr, &hdr); |
| encode_getfh(xdr, &hdr); |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode REMOVE request |
| */ |
| static void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_removeargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_remove(xdr, &args->name, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode RENAME request |
| */ |
| static void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_renameargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->old_dir, &hdr); |
| encode_savefh(xdr, &hdr); |
| encode_putfh(xdr, args->new_dir, &hdr); |
| encode_rename(xdr, args->old_name, args->new_name, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode LINK request |
| */ |
| static void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_link_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_savefh(xdr, &hdr); |
| encode_putfh(xdr, args->dir_fh, &hdr); |
| encode_link(xdr, args->name, &hdr); |
| encode_restorefh(xdr, &hdr); |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode CREATE request |
| */ |
| static void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_create_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->dir_fh, &hdr); |
| encode_create(xdr, args, &hdr); |
| encode_getfh(xdr, &hdr); |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode SYMLINK request |
| */ |
| static void nfs4_xdr_enc_symlink(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_create_arg *args = data; |
| |
| nfs4_xdr_enc_create(req, xdr, args); |
| } |
| |
| /* |
| * Encode GETATTR request |
| */ |
| static void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_getattr_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode a CLOSE request |
| */ |
| static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_closeargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| if (args->lr_args) |
| encode_layoutreturn(xdr, args->lr_args, &hdr); |
| if (args->bitmask != NULL) |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_close(xdr, args, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode an OPEN request |
| */ |
| static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_openargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_open(xdr, args, &hdr); |
| encode_getfh(xdr, &hdr); |
| if (args->access) |
| encode_access(xdr, args->access, &hdr); |
| encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); |
| if (args->lg_args) { |
| encode_layoutget(xdr, args->lg_args, &hdr); |
| rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0, |
| args->lg_args->layout.pglen, |
| hdr.replen - pagepad_maxsz); |
| } |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode an OPEN_CONFIRM request |
| */ |
| static void nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, |
| struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_open_confirmargs *args = data; |
| struct compound_hdr hdr = { |
| .nops = 0, |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_open_confirm(xdr, args, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode an OPEN request with no attributes. |
| */ |
| static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, |
| struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_openargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_open(xdr, args, &hdr); |
| if (args->access) |
| encode_access(xdr, args->access, &hdr); |
| encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); |
| if (args->lg_args) { |
| encode_layoutget(xdr, args->lg_args, &hdr); |
| rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0, |
| args->lg_args->layout.pglen, |
| hdr.replen - pagepad_maxsz); |
| } |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode an OPEN_DOWNGRADE request |
| */ |
| static void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, |
| struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_closeargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| if (args->lr_args) |
| encode_layoutreturn(xdr, args->lr_args, &hdr); |
| encode_open_downgrade(xdr, args, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode a LOCK request |
| */ |
| static void nfs4_xdr_enc_lock(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_lock_args *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_lock(xdr, args, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode a LOCKT request |
| */ |
| static void nfs4_xdr_enc_lockt(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_lockt_args *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_lockt(xdr, args, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode a LOCKU request |
| */ |
| static void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_locku_args *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_locku(xdr, args, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, |
| struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_release_lockowner_args *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = 0, |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_release_lockowner(xdr, &args->lock_owner, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode a READLINK request |
| */ |
| static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_readlink *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_readlink(xdr, args, req, &hdr); |
| |
| rpc_prepare_reply_pages(req, args->pages, args->pgbase, |
| args->pglen, hdr.replen - pagepad_maxsz); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode a READDIR request |
| */ |
| static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_readdir_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_readdir(xdr, args, req, &hdr); |
| |
| rpc_prepare_reply_pages(req, args->pages, args->pgbase, |
| args->count, hdr.replen - pagepad_maxsz); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode a READ request |
| */ |
| static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_pgio_args *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_read(xdr, args, &hdr); |
| |
| rpc_prepare_reply_pages(req, args->pages, args->pgbase, |
| args->count, hdr.replen - pagepad_maxsz); |
| req->rq_rcv_buf.flags |= XDRBUF_READ; |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode an SETATTR request |
| */ |
| static void nfs4_xdr_enc_setattr(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_setattrargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_setattr(xdr, args, args->server, &hdr); |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode a GETACL request |
| */ |
| static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_getaclargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| __u32 nfs4_acl_bitmap[2]; |
| uint32_t replen; |
| |
| nfs4_acltype_to_bitmap(args->acl_type, nfs4_acl_bitmap); |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| replen = hdr.replen + op_decode_hdr_maxsz; |
| encode_getattr(xdr, nfs4_acl_bitmap, NULL, |
| ARRAY_SIZE(nfs4_acl_bitmap), &hdr); |
| |
| rpc_prepare_reply_pages(req, args->acl_pages, 0, |
| args->acl_len, replen); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode a WRITE request |
| */ |
| static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_pgio_args *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_write(xdr, args, &hdr); |
| req->rq_snd_buf.flags |= XDRBUF_WRITE; |
| if (args->bitmask) |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * a COMMIT request |
| */ |
| static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs_commitargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_commit(xdr, args, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * FSINFO request |
| */ |
| static void nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_fsinfo_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_fsinfo(xdr, args->bitmask, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * a PATHCONF request |
| */ |
| static void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_pathconf_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_getattr(xdr, nfs4_pathconf_bitmap, args->bitmask, |
| ARRAY_SIZE(nfs4_pathconf_bitmap), &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * a STATFS request |
| */ |
| static void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_statfs_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fh, &hdr); |
| encode_getattr(xdr, nfs4_statfs_bitmap, args->bitmask, |
| ARRAY_SIZE(nfs4_statfs_bitmap), &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * GETATTR_BITMAP request |
| */ |
| static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req, |
| struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_server_caps_arg *args = data; |
| const u32 *bitmask = args->bitmask; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fhandle, &hdr); |
| encode_getattr(xdr, bitmask, NULL, 3, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * a RENEW request |
| */ |
| static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr, |
| const void *data) |
| |
| { |
| const struct nfs_client *clp = data; |
| struct compound_hdr hdr = { |
| .nops = 0, |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_renew(xdr, clp->cl_clientid, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * a SETCLIENTID request |
| */ |
| static void nfs4_xdr_enc_setclientid(struct rpc_rqst *req, |
| struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_setclientid *sc = data; |
| struct compound_hdr hdr = { |
| .nops = 0, |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_setclientid(xdr, sc, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * a SETCLIENTID_CONFIRM request |
| */ |
| static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, |
| struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_setclientid_res *arg = data; |
| struct compound_hdr hdr = { |
| .nops = 0, |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_setclientid_confirm(xdr, arg, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * DELEGRETURN request |
| */ |
| static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, |
| struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_delegreturnargs *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| encode_putfh(xdr, args->fhandle, &hdr); |
| if (args->lr_args) |
| encode_layoutreturn(xdr, args->lr_args, &hdr); |
| if (args->sattr_args) |
| encode_delegattr(xdr, args->stateid, args->sattr_args, &hdr); |
| if (args->bitmask) |
| encode_getfattr(xdr, args->bitmask, &hdr); |
| encode_delegreturn(xdr, args->stateid, &hdr); |
| encode_nops(&hdr); |
| } |
| |
| /* |
| * Encode FS_LOCATIONS request |
| */ |
| static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, |
| struct xdr_stream *xdr, |
| const void *data) |
| { |
| const struct nfs4_fs_locations_arg *args = data; |
| struct compound_hdr hdr = { |
| .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
| }; |
| uint32_t replen; |
| |
| encode_compound_hdr(xdr, req, &hdr); |
| encode_sequence(xdr, &args->seq_args, &hdr); |
| if (args->migration) { |
| encode_putfh(xdr, args->fh, &hdr); |
| replen = hdr.replen; |
| encode_fs_locations(xdr, args->bitmask, &hdr); |
| if (args->renew) |
| encode_renew(xdr, args->clientid, &hdr); |
|
|