11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * fs/nfs/nfs4xdr.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Client-side XDR for NFSv4. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Copyright (c) 2002 The Regents of the University of Michigan. 71da177e4SLinus Torvalds * All rights reserved. 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Kendrick Smith <kmsmith@umich.edu> 101da177e4SLinus Torvalds * Andy Adamson <andros@umich.edu> 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or without 131da177e4SLinus Torvalds * modification, are permitted provided that the following conditions 141da177e4SLinus Torvalds * are met: 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * 1. Redistributions of source code must retain the above copyright 171da177e4SLinus Torvalds * notice, this list of conditions and the following disclaimer. 181da177e4SLinus Torvalds * 2. Redistributions in binary form must reproduce the above copyright 191da177e4SLinus Torvalds * notice, this list of conditions and the following disclaimer in the 201da177e4SLinus Torvalds * documentation and/or other materials provided with the distribution. 211da177e4SLinus Torvalds * 3. Neither the name of the University nor the names of its 221da177e4SLinus Torvalds * contributors may be used to endorse or promote products derived 231da177e4SLinus Torvalds * from this software without specific prior written permission. 241da177e4SLinus Torvalds * 251da177e4SLinus Torvalds * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 261da177e4SLinus Torvalds * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 271da177e4SLinus Torvalds * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 281da177e4SLinus Torvalds * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291da177e4SLinus Torvalds * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 301da177e4SLinus Torvalds * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 311da177e4SLinus Torvalds * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 321da177e4SLinus Torvalds * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 331da177e4SLinus Torvalds * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 341da177e4SLinus Torvalds * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 351da177e4SLinus Torvalds * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 361da177e4SLinus Torvalds */ 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds #include <linux/param.h> 391da177e4SLinus Torvalds #include <linux/time.h> 401da177e4SLinus Torvalds #include <linux/mm.h> 411da177e4SLinus Torvalds #include <linux/errno.h> 421da177e4SLinus Torvalds #include <linux/string.h> 431da177e4SLinus Torvalds #include <linux/in.h> 441da177e4SLinus Torvalds #include <linux/pagemap.h> 451da177e4SLinus Torvalds #include <linux/proc_fs.h> 461da177e4SLinus Torvalds #include <linux/kdev_t.h> 47db8ac8baSWeston Andros Adamson #include <linux/module.h> 48db8ac8baSWeston Andros Adamson #include <linux/utsname.h> 491da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h> 502449ea2eSAlexandros Batsakis #include <linux/sunrpc/msg_prot.h> 515a5ea0d4SBryan Schumaker #include <linux/sunrpc/gss_api.h> 521da177e4SLinus Torvalds #include <linux/nfs.h> 531da177e4SLinus Torvalds #include <linux/nfs4.h> 541da177e4SLinus Torvalds #include <linux/nfs_fs.h> 55f092075dSChuck Lever 564ce79717STrond Myklebust #include "nfs4_fs.h" 57f23f6584SChuck Lever #include "nfs4trace.h" 584882ef72SAlexandros Batsakis #include "internal.h" 5940c64c26SAnna Schumaker #include "nfs4idmap.h" 6076e697baSTrond Myklebust #include "nfs4session.h" 61b1f69b75SAndy Adamson #include "pnfs.h" 62f092075dSChuck Lever #include "netns.h" 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds #define NFSDBG_FACILITY NFSDBG_XDR 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds /* Mapping from NFS error code to "errno" error code. */ 671da177e4SLinus Torvalds #define errno_NFSERR_IO EIO 681da177e4SLinus Torvalds 6956f487f8SFred Isaman struct compound_hdr; 700a8ea437SDavid Howells static int nfs4_stat_to_errno(int); 7156f487f8SFred Isaman static void encode_layoutget(struct xdr_stream *xdr, 7256f487f8SFred Isaman const struct nfs4_layoutget_args *args, 7356f487f8SFred Isaman struct compound_hdr *hdr); 7456f487f8SFred Isaman static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, 7556f487f8SFred Isaman struct nfs4_layoutget_res *res); 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds /* NFSv4 COMPOUND tags are only wanted for debugging purposes */ 781da177e4SLinus Torvalds #ifdef DEBUG 791da177e4SLinus Torvalds #define NFS4_MAXTAGLEN 20 801da177e4SLinus Torvalds #else 811da177e4SLinus Torvalds #define NFS4_MAXTAGLEN 0 821da177e4SLinus Torvalds #endif 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds /* lock,open owner id: 859f958ab8STrond Myklebust * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) 861da177e4SLinus Torvalds */ 879ed5af26STrond Myklebust #define pagepad_maxsz (1) 8895b72eb0STrond Myklebust #define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2) 89d035c36cSTrond Myklebust #define lock_owner_id_maxsz (1 + 1 + 4) 909104a55dSTrond Myklebust #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 911da177e4SLinus Torvalds #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) 921da177e4SLinus Torvalds #define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) 931da177e4SLinus Torvalds #define op_encode_hdr_maxsz (1) 941da177e4SLinus Torvalds #define op_decode_hdr_maxsz (2) 959104a55dSTrond Myklebust #define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) 969104a55dSTrond Myklebust #define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) 979104a55dSTrond Myklebust #define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) 989104a55dSTrond Myklebust #define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) 991da177e4SLinus Torvalds #define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \ 1001da177e4SLinus Torvalds (NFS4_FHSIZE >> 2)) 1011da177e4SLinus Torvalds #define decode_putfh_maxsz (op_decode_hdr_maxsz) 1021da177e4SLinus Torvalds #define encode_putrootfh_maxsz (op_encode_hdr_maxsz) 1031da177e4SLinus Torvalds #define decode_putrootfh_maxsz (op_decode_hdr_maxsz) 1041da177e4SLinus Torvalds #define encode_getfh_maxsz (op_encode_hdr_maxsz) 1051da177e4SLinus Torvalds #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ 1061da177e4SLinus Torvalds ((3+NFS4_FHSIZE) >> 2)) 107e5012d1fSAndy Adamson #define nfs4_fattr_bitmap_maxsz 4 10896928206SJ. Bruce Fields #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) 10936b3743fSTrond Myklebust #define nfstime4_maxsz (3) 1101da177e4SLinus Torvalds #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) 1111da177e4SLinus Torvalds #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) 112bd625ba8STrond Myklebust #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 113bd625ba8STrond Myklebust #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 114aa9c2669SDavid Quigley #ifdef CONFIG_NFS_V4_SECURITY_LABEL 115aa9c2669SDavid Quigley /* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */ 116aa9c2669SDavid Quigley #define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN)) 117aa9c2669SDavid Quigley #else 118aa9c2669SDavid Quigley #define nfs4_label_maxsz 0 119aa9c2669SDavid Quigley #endif 12088034c3dSAndy Adamson /* We support only one layout type per file system */ 12188034c3dSAndy Adamson #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) 12296928206SJ. Bruce Fields /* This is based on getfattr, which uses the most attributes: */ 12396928206SJ. Bruce Fields #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ 12436b3743fSTrond Myklebust 3*nfstime4_maxsz + \ 12536b3743fSTrond Myklebust nfs4_owner_maxsz + \ 126aa9c2669SDavid Quigley nfs4_group_maxsz + nfs4_label_maxsz + \ 127aa9c2669SDavid Quigley decode_mdsthreshold_maxsz)) 12896928206SJ. Bruce Fields #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ 12996928206SJ. Bruce Fields nfs4_fattr_value_maxsz) 13096928206SJ. Bruce Fields #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) 1319104a55dSTrond Myklebust #define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \ 1329104a55dSTrond Myklebust 1 + 2 + 1 + \ 1339104a55dSTrond Myklebust nfs4_owner_maxsz + \ 1349104a55dSTrond Myklebust nfs4_group_maxsz + \ 135aa9c2669SDavid Quigley nfs4_label_maxsz + \ 13636b3743fSTrond Myklebust 1 + nfstime4_maxsz + \ 13736b3743fSTrond Myklebust 1 + nfstime4_maxsz) 1381da177e4SLinus Torvalds #define encode_savefh_maxsz (op_encode_hdr_maxsz) 1391da177e4SLinus Torvalds #define decode_savefh_maxsz (op_decode_hdr_maxsz) 14056ae19f3STrond Myklebust #define encode_restorefh_maxsz (op_encode_hdr_maxsz) 14156ae19f3STrond Myklebust #define decode_restorefh_maxsz (op_decode_hdr_maxsz) 1422f42b5d0SFred Isaman #define encode_fsinfo_maxsz (encode_getattr_maxsz) 143dae100c2SFred Isaman /* The 5 accounts for the PNFS attributes, and assumes that at most three 144dae100c2SFred Isaman * layout types will be returned. 145dae100c2SFred Isaman */ 146dae100c2SFred Isaman #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + \ 147dae100c2SFred Isaman nfs4_fattr_bitmap_maxsz + 4 + 8 + 5) 1481da177e4SLinus Torvalds #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) 1491da177e4SLinus Torvalds #define decode_renew_maxsz (op_decode_hdr_maxsz) 1501da177e4SLinus Torvalds #define encode_setclientid_maxsz \ 1511da177e4SLinus Torvalds (op_encode_hdr_maxsz + \ 152cc38bac3SChuck Lever XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ 153b8fb2f59SJeff Layton /* client name */ \ 154b8fb2f59SJeff Layton 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 155cc38bac3SChuck Lever 1 /* sc_prog */ + \ 1566dd3436bSChuck Lever 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ 1576dd3436bSChuck Lever 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ 158cc38bac3SChuck Lever 1) /* sc_cb_ident */ 1591da177e4SLinus Torvalds #define decode_setclientid_maxsz \ 1601da177e4SLinus Torvalds (op_decode_hdr_maxsz + \ 1616dd3436bSChuck Lever 2 /* clientid */ + \ 1626dd3436bSChuck Lever XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ 1636dd3436bSChuck Lever 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ 1646dd3436bSChuck Lever 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN)) 1651da177e4SLinus Torvalds #define encode_setclientid_confirm_maxsz \ 1661da177e4SLinus Torvalds (op_encode_hdr_maxsz + \ 1671da177e4SLinus Torvalds 3 + (NFS4_VERIFIER_SIZE >> 2)) 1681da177e4SLinus Torvalds #define decode_setclientid_confirm_maxsz \ 1691da177e4SLinus Torvalds (op_decode_hdr_maxsz) 170e6889620STrond Myklebust #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) 171e6889620STrond Myklebust #define decode_lookup_maxsz (op_decode_hdr_maxsz) 1725b5faaf6SJeff Layton #define encode_lookupp_maxsz (op_encode_hdr_maxsz) 1735b5faaf6SJeff Layton #define decode_lookupp_maxsz (op_decode_hdr_maxsz) 1742cebf828STrond Myklebust #define encode_share_access_maxsz \ 1752cebf828STrond Myklebust (2) 1764882ef72SAlexandros Batsakis #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) 1772cebf828STrond Myklebust #define encode_opentype_maxsz (1 + encode_createmode_maxsz) 1782cebf828STrond Myklebust #define encode_claim_null_maxsz (1 + nfs4_name_maxsz) 1792cebf828STrond Myklebust #define encode_open_maxsz (op_encode_hdr_maxsz + \ 1802cebf828STrond Myklebust 2 + encode_share_access_maxsz + 2 + \ 1812cebf828STrond Myklebust open_owner_id_maxsz + \ 1822cebf828STrond Myklebust encode_opentype_maxsz + \ 1832cebf828STrond Myklebust encode_claim_null_maxsz) 1845a1f6d9eSTrond Myklebust #define decode_space_limit_maxsz (3) 1852cebf828STrond Myklebust #define decode_ace_maxsz (3 + nfs4_owner_maxsz) 1869104a55dSTrond Myklebust #define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \ 1875a1f6d9eSTrond Myklebust decode_space_limit_maxsz + \ 1882cebf828STrond Myklebust decode_ace_maxsz) 1892cebf828STrond Myklebust #define decode_change_info_maxsz (5) 1902cebf828STrond Myklebust #define decode_open_maxsz (op_decode_hdr_maxsz + \ 1919104a55dSTrond Myklebust decode_stateid_maxsz + \ 1922cebf828STrond Myklebust decode_change_info_maxsz + 1 + \ 1932cebf828STrond Myklebust nfs4_fattr_bitmap_maxsz + \ 1942cebf828STrond Myklebust decode_delegation_maxsz) 1959104a55dSTrond Myklebust #define encode_open_confirm_maxsz \ 1969104a55dSTrond Myklebust (op_encode_hdr_maxsz + \ 1979104a55dSTrond Myklebust encode_stateid_maxsz + 1) 1989104a55dSTrond Myklebust #define decode_open_confirm_maxsz \ 1999104a55dSTrond Myklebust (op_decode_hdr_maxsz + \ 2009104a55dSTrond Myklebust decode_stateid_maxsz) 2019104a55dSTrond Myklebust #define encode_open_downgrade_maxsz \ 2029104a55dSTrond Myklebust (op_encode_hdr_maxsz + \ 2039104a55dSTrond Myklebust encode_stateid_maxsz + 1 + \ 2049104a55dSTrond Myklebust encode_share_access_maxsz) 2059104a55dSTrond Myklebust #define decode_open_downgrade_maxsz \ 2069104a55dSTrond Myklebust (op_decode_hdr_maxsz + \ 2079104a55dSTrond Myklebust decode_stateid_maxsz) 2089104a55dSTrond Myklebust #define encode_close_maxsz (op_encode_hdr_maxsz + \ 2099104a55dSTrond Myklebust 1 + encode_stateid_maxsz) 2109104a55dSTrond Myklebust #define decode_close_maxsz (op_decode_hdr_maxsz + \ 2119104a55dSTrond Myklebust decode_stateid_maxsz) 2129104a55dSTrond Myklebust #define encode_setattr_maxsz (op_encode_hdr_maxsz + \ 2139104a55dSTrond Myklebust encode_stateid_maxsz + \ 2149104a55dSTrond Myklebust encode_attrs_maxsz) 2159104a55dSTrond Myklebust #define decode_setattr_maxsz (op_decode_hdr_maxsz + \ 2169104a55dSTrond Myklebust nfs4_fattr_bitmap_maxsz) 2179104a55dSTrond Myklebust #define encode_read_maxsz (op_encode_hdr_maxsz + \ 2189104a55dSTrond Myklebust encode_stateid_maxsz + 3) 2199ed5af26STrond Myklebust #define decode_read_maxsz (op_decode_hdr_maxsz + 2 + pagepad_maxsz) 2209104a55dSTrond Myklebust #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ 221aa9c2669SDavid Quigley 2 + encode_verifier_maxsz + 5 + \ 222aa9c2669SDavid Quigley nfs4_label_maxsz) 2239104a55dSTrond Myklebust #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ 2249ed5af26STrond Myklebust decode_verifier_maxsz + pagepad_maxsz) 2259104a55dSTrond Myklebust #define encode_readlink_maxsz (op_encode_hdr_maxsz) 2269ed5af26STrond Myklebust #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1 + pagepad_maxsz) 2279104a55dSTrond Myklebust #define encode_write_maxsz (op_encode_hdr_maxsz + \ 2289104a55dSTrond Myklebust encode_stateid_maxsz + 4) 2299104a55dSTrond Myklebust #define decode_write_maxsz (op_decode_hdr_maxsz + \ 2309104a55dSTrond Myklebust 2 + decode_verifier_maxsz) 2319104a55dSTrond Myklebust #define encode_commit_maxsz (op_encode_hdr_maxsz + 3) 2329104a55dSTrond Myklebust #define decode_commit_maxsz (op_decode_hdr_maxsz + \ 2339104a55dSTrond Myklebust decode_verifier_maxsz) 2341da177e4SLinus Torvalds #define encode_remove_maxsz (op_encode_hdr_maxsz + \ 2351da177e4SLinus Torvalds nfs4_name_maxsz) 2366ce18391SBenny Halevy #define decode_remove_maxsz (op_decode_hdr_maxsz + \ 2376ce18391SBenny Halevy decode_change_info_maxsz) 2381da177e4SLinus Torvalds #define encode_rename_maxsz (op_encode_hdr_maxsz + \ 2391da177e4SLinus Torvalds 2 * nfs4_name_maxsz) 2406ce18391SBenny Halevy #define decode_rename_maxsz (op_decode_hdr_maxsz + \ 2416ce18391SBenny Halevy decode_change_info_maxsz + \ 2426ce18391SBenny Halevy decode_change_info_maxsz) 2431da177e4SLinus Torvalds #define encode_link_maxsz (op_encode_hdr_maxsz + \ 2441da177e4SLinus Torvalds nfs4_name_maxsz) 2456ce18391SBenny Halevy #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) 246daccbdedSTrond Myklebust #define encode_lockowner_maxsz (7) 2479104a55dSTrond Myklebust #define encode_lock_maxsz (op_encode_hdr_maxsz + \ 2489104a55dSTrond Myklebust 7 + \ 249daccbdedSTrond Myklebust 1 + encode_stateid_maxsz + 1 + \ 250daccbdedSTrond Myklebust encode_lockowner_maxsz) 2519104a55dSTrond Myklebust #define decode_lock_denied_maxsz \ 2529104a55dSTrond Myklebust (8 + decode_lockowner_maxsz) 2539104a55dSTrond Myklebust #define decode_lock_maxsz (op_decode_hdr_maxsz + \ 2549104a55dSTrond Myklebust decode_lock_denied_maxsz) 255daccbdedSTrond Myklebust #define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \ 256daccbdedSTrond Myklebust encode_lockowner_maxsz) 2579104a55dSTrond Myklebust #define decode_lockt_maxsz (op_decode_hdr_maxsz + \ 2589104a55dSTrond Myklebust decode_lock_denied_maxsz) 2599104a55dSTrond Myklebust #define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \ 2609104a55dSTrond Myklebust encode_stateid_maxsz + \ 2619104a55dSTrond Myklebust 4) 2629104a55dSTrond Myklebust #define decode_locku_maxsz (op_decode_hdr_maxsz + \ 2639104a55dSTrond Myklebust decode_stateid_maxsz) 264d3c7b7ccSTrond Myklebust #define encode_release_lockowner_maxsz \ 265d3c7b7ccSTrond Myklebust (op_encode_hdr_maxsz + \ 266d3c7b7ccSTrond Myklebust encode_lockowner_maxsz) 267d3c7b7ccSTrond Myklebust #define decode_release_lockowner_maxsz \ 268d3c7b7ccSTrond Myklebust (op_decode_hdr_maxsz) 2699104a55dSTrond Myklebust #define encode_access_maxsz (op_encode_hdr_maxsz + 1) 2709104a55dSTrond Myklebust #define decode_access_maxsz (op_decode_hdr_maxsz + 2) 2711da177e4SLinus Torvalds #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ 2721da177e4SLinus Torvalds 1 + nfs4_name_maxsz + \ 27394a6d753SChuck Lever 1 + \ 27496928206SJ. Bruce Fields nfs4_fattr_maxsz) 2751da177e4SLinus Torvalds #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) 2761da177e4SLinus Torvalds #define encode_create_maxsz (op_encode_hdr_maxsz + \ 2779104a55dSTrond Myklebust 1 + 2 + nfs4_name_maxsz + \ 2789104a55dSTrond Myklebust encode_attrs_maxsz) 2792cebf828STrond Myklebust #define decode_create_maxsz (op_decode_hdr_maxsz + \ 2802cebf828STrond Myklebust decode_change_info_maxsz + \ 2812cebf828STrond Myklebust nfs4_fattr_bitmap_maxsz) 2829104a55dSTrond Myklebust #define encode_statfs_maxsz (encode_getattr_maxsz) 2839104a55dSTrond Myklebust #define decode_statfs_maxsz (decode_getattr_maxsz) 2841da177e4SLinus Torvalds #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) 2851da177e4SLinus Torvalds #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) 2869104a55dSTrond Myklebust #define encode_getacl_maxsz (encode_getattr_maxsz) 2879104a55dSTrond Myklebust #define decode_getacl_maxsz (op_decode_hdr_maxsz + \ 2889ed5af26STrond Myklebust nfs4_fattr_bitmap_maxsz + 1 + pagepad_maxsz) 2899104a55dSTrond Myklebust #define encode_setacl_maxsz (op_encode_hdr_maxsz + \ 2909104a55dSTrond Myklebust encode_stateid_maxsz + 3) 2919104a55dSTrond Myklebust #define decode_setacl_maxsz (decode_setattr_maxsz) 292e6889620STrond Myklebust #define encode_fs_locations_maxsz \ 293e6889620STrond Myklebust (encode_getattr_maxsz) 294e6889620STrond Myklebust #define decode_fs_locations_maxsz \ 2959ed5af26STrond Myklebust (pagepad_maxsz) 2965a5ea0d4SBryan Schumaker #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) 2971650add2SBryan Schumaker #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4)) 2989b7b9fccSAndy Adamson 2999b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 300fc931582SAndy Adamson #define NFS4_MAX_MACHINE_NAME_LEN (64) 301d751f748SJim Rees #define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \ 302d751f748SJim Rees sizeof(utsname()->version) + sizeof(utsname()->machine) + 8) 303fc931582SAndy Adamson 30499fe60d0SBenny Halevy #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ 30599fe60d0SBenny Halevy encode_verifier_maxsz + \ 30699fe60d0SBenny Halevy 1 /* co_ownerid.len */ + \ 307b8fb2f59SJeff Layton /* eia_clientowner */ \ 308b8fb2f59SJeff Layton 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 30999fe60d0SBenny Halevy 1 /* flags */ + \ 31099fe60d0SBenny Halevy 1 /* spa_how */ + \ 3112031cd1aSWeston Andros Adamson /* max is SP4_MACH_CRED (for now) */ + \ 3122031cd1aSWeston Andros Adamson 1 + NFS4_OP_MAP_NUM_WORDS + \ 3132031cd1aSWeston Andros Adamson 1 + NFS4_OP_MAP_NUM_WORDS + \ 314db8ac8baSWeston Andros Adamson 1 /* implementation id array of size 1 */ + \ 315db8ac8baSWeston Andros Adamson 1 /* nii_domain */ + \ 316db8ac8baSWeston Andros Adamson XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 317db8ac8baSWeston Andros Adamson 1 /* nii_name */ + \ 318d751f748SJim Rees XDR_QUADLEN(IMPL_NAME_LIMIT) + \ 319db8ac8baSWeston Andros Adamson 3 /* nii_date */) 32099fe60d0SBenny Halevy #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \ 32199fe60d0SBenny Halevy 2 /* eir_clientid */ + \ 32299fe60d0SBenny Halevy 1 /* eir_sequenceid */ + \ 32399fe60d0SBenny Halevy 1 /* eir_flags */ + \ 32499fe60d0SBenny Halevy 1 /* spr_how */ + \ 3252031cd1aSWeston Andros Adamson /* max is SP4_MACH_CRED (for now) */ + \ 3262031cd1aSWeston Andros Adamson 1 + NFS4_OP_MAP_NUM_WORDS + \ 3272031cd1aSWeston Andros Adamson 1 + NFS4_OP_MAP_NUM_WORDS + \ 32899fe60d0SBenny Halevy 2 /* eir_server_owner.so_minor_id */ + \ 32999fe60d0SBenny Halevy /* eir_server_owner.so_major_id<> */ \ 33099fe60d0SBenny Halevy XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ 33199fe60d0SBenny Halevy /* eir_server_scope<> */ \ 33299fe60d0SBenny Halevy XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ 33399fe60d0SBenny Halevy 1 /* eir_server_impl_id array length */ + \ 3347d2ed9acSWeston Andros Adamson 1 /* nii_domain */ + \ 3357d2ed9acSWeston Andros Adamson XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 3367d2ed9acSWeston Andros Adamson 1 /* nii_name */ + \ 3377d2ed9acSWeston Andros Adamson XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 3387d2ed9acSWeston Andros Adamson 3 /* nii_date */) 339fc931582SAndy Adamson #define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */) 340fc931582SAndy Adamson #define decode_channel_attrs_maxsz (6 + \ 341fc931582SAndy Adamson 1 /* ca_rdma_ird.len */ + \ 342fc931582SAndy Adamson 1 /* ca_rdma_ird */) 343fc931582SAndy Adamson #define encode_create_session_maxsz (op_encode_hdr_maxsz + \ 344fc931582SAndy Adamson 2 /* csa_clientid */ + \ 345fc931582SAndy Adamson 1 /* csa_sequence */ + \ 346fc931582SAndy Adamson 1 /* csa_flags */ + \ 347fc931582SAndy Adamson encode_channel_attrs_maxsz + \ 348fc931582SAndy Adamson encode_channel_attrs_maxsz + \ 349fc931582SAndy Adamson 1 /* csa_cb_program */ + \ 350fc931582SAndy Adamson 1 /* csa_sec_parms.len (1) */ + \ 351fc931582SAndy Adamson 1 /* cb_secflavor (AUTH_SYS) */ + \ 352fc931582SAndy Adamson 1 /* stamp */ + \ 353fc931582SAndy Adamson 1 /* machinename.len */ + \ 354fc931582SAndy Adamson XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \ 355fc931582SAndy Adamson 1 /* uid */ + \ 356fc931582SAndy Adamson 1 /* gid */ + \ 357fc931582SAndy Adamson 1 /* gids.len (0) */) 358fc931582SAndy Adamson #define decode_create_session_maxsz (op_decode_hdr_maxsz + \ 359fc931582SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ 360fc931582SAndy Adamson 1 /* csr_sequence */ + \ 361fc931582SAndy Adamson 1 /* csr_flags */ + \ 362fc931582SAndy Adamson decode_channel_attrs_maxsz + \ 363fc931582SAndy Adamson decode_channel_attrs_maxsz) 3647c44f1aeSWeston Andros Adamson #define encode_bind_conn_to_session_maxsz (op_encode_hdr_maxsz + \ 3657c44f1aeSWeston Andros Adamson /* bctsa_sessid */ \ 3667c44f1aeSWeston Andros Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ 3677c44f1aeSWeston Andros Adamson 1 /* bctsa_dir */ + \ 3687c44f1aeSWeston Andros Adamson 1 /* bctsa_use_conn_in_rdma_mode */) 3697c44f1aeSWeston Andros Adamson #define decode_bind_conn_to_session_maxsz (op_decode_hdr_maxsz + \ 3707c44f1aeSWeston Andros Adamson /* bctsr_sessid */ \ 3717c44f1aeSWeston Andros Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ 3727c44f1aeSWeston Andros Adamson 1 /* bctsr_dir */ + \ 3737c44f1aeSWeston Andros Adamson 1 /* bctsr_use_conn_in_rdma_mode */) 3740f3e66c6SAndy Adamson #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) 3750f3e66c6SAndy Adamson #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) 37666245539STrond Myklebust #define encode_destroy_clientid_maxsz (op_encode_hdr_maxsz + 2) 37766245539STrond Myklebust #define decode_destroy_clientid_maxsz (op_decode_hdr_maxsz) 378fc01cea9SAndy Adamson #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ 379fc01cea9SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) 380fc01cea9SAndy Adamson #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ 381fc01cea9SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) 38218019753SRicardo Labiaga #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) 38318019753SRicardo Labiaga #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) 38484c9dee3SChristoph Hellwig #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + \ 38584c9dee3SChristoph Hellwig XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \ 38684c9dee3SChristoph Hellwig 1 /* layout type */ + \ 38784c9dee3SChristoph Hellwig 1 /* maxcount */ + \ 38884c9dee3SChristoph Hellwig 1 /* bitmap size */ + \ 38984c9dee3SChristoph Hellwig 1 /* notification bitmap length */ + \ 39084c9dee3SChristoph Hellwig 1 /* notification bitmap, word 0 */) 391b1f69b75SAndy Adamson #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ 392b1f69b75SAndy Adamson 1 /* layout type */ + \ 393b1f69b75SAndy Adamson 1 /* opaque devaddr4 length */ + \ 394b1f69b75SAndy Adamson /* devaddr4 payload is read into page */ \ 395b1f69b75SAndy Adamson 1 /* notification bitmap length */ + \ 39602ef04e4SChuck Lever 1 /* notification bitmap, word 0 */ + \ 3979ed5af26STrond Myklebust pagepad_maxsz /* possible XDR padding */) 398b1f69b75SAndy Adamson #define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \ 399b1f69b75SAndy Adamson encode_stateid_maxsz) 400b1f69b75SAndy Adamson #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ 401b1f69b75SAndy Adamson decode_stateid_maxsz + \ 4029ed5af26STrond Myklebust XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE) + \ 4039ed5af26STrond Myklebust pagepad_maxsz) 404863a3c6cSAndy Adamson #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ 405863a3c6cSAndy Adamson 2 /* offset */ + \ 406863a3c6cSAndy Adamson 2 /* length */ + \ 407863a3c6cSAndy Adamson 1 /* reclaim */ + \ 408863a3c6cSAndy Adamson encode_stateid_maxsz + \ 409863a3c6cSAndy Adamson 1 /* new offset (true) */ + \ 410863a3c6cSAndy Adamson 2 /* last byte written */ + \ 411863a3c6cSAndy Adamson 1 /* nt_timechanged (false) */ + \ 412863a3c6cSAndy Adamson 1 /* layoutupdate4 layout type */ + \ 4135f919c9fSChristoph Hellwig 1 /* layoutupdate4 opaqueue len */) 4145f919c9fSChristoph Hellwig /* the actual content of layoutupdate4 should 4155f919c9fSChristoph Hellwig be allocated by drivers and spliced in 4165f919c9fSChristoph Hellwig using xdr_write_pages */ 417863a3c6cSAndy Adamson #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) 418cbe82603SBenny Halevy #define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \ 419cbe82603SBenny Halevy encode_stateid_maxsz + \ 4206669cb8bSTrond Myklebust 1 + \ 4216669cb8bSTrond Myklebust XDR_QUADLEN(NFS4_OPAQUE_LIMIT)) 422cbe82603SBenny Halevy #define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \ 423cbe82603SBenny Halevy 1 + decode_stateid_maxsz) 424fca78d6dSBryan Schumaker #define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1) 425fca78d6dSBryan Schumaker #define decode_secinfo_no_name_maxsz decode_secinfo_maxsz 4267d974794SBryan Schumaker #define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \ 4277d974794SBryan Schumaker XDR_QUADLEN(NFS4_STATEID_SIZE)) 4287d974794SBryan Schumaker #define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1) 4299aeda35fSBryan Schumaker #define encode_free_stateid_maxsz (op_encode_hdr_maxsz + 1 + \ 4309aeda35fSBryan Schumaker XDR_QUADLEN(NFS4_STATEID_SIZE)) 4319f79fb48SAndy Adamson #define decode_free_stateid_maxsz (op_decode_hdr_maxsz) 4329b7b9fccSAndy Adamson #else /* CONFIG_NFS_V4_1 */ 4339b7b9fccSAndy Adamson #define encode_sequence_maxsz 0 4349b7b9fccSAndy Adamson #define decode_sequence_maxsz 0 435cf805165STrond Myklebust #define encode_layoutreturn_maxsz 0 436cf805165STrond Myklebust #define decode_layoutreturn_maxsz 0 43756f487f8SFred Isaman #define encode_layoutget_maxsz 0 43856f487f8SFred Isaman #define decode_layoutget_maxsz 0 4399b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 4409b7b9fccSAndy Adamson 4411da177e4SLinus Torvalds #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ 4421da177e4SLinus Torvalds #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ 4431da177e4SLinus Torvalds #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ 4449b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4451da177e4SLinus Torvalds encode_putfh_maxsz + \ 4469104a55dSTrond Myklebust encode_read_maxsz) 4471da177e4SLinus Torvalds #define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \ 4489b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4491da177e4SLinus Torvalds decode_putfh_maxsz + \ 4509104a55dSTrond Myklebust decode_read_maxsz) 4511da177e4SLinus Torvalds #define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \ 4529b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4531da177e4SLinus Torvalds encode_putfh_maxsz + \ 4549104a55dSTrond Myklebust encode_readlink_maxsz) 4551da177e4SLinus Torvalds #define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \ 4569b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4571da177e4SLinus Torvalds decode_putfh_maxsz + \ 4589104a55dSTrond Myklebust decode_readlink_maxsz) 4591da177e4SLinus Torvalds #define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \ 4609b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4611da177e4SLinus Torvalds encode_putfh_maxsz + \ 4629104a55dSTrond Myklebust encode_readdir_maxsz) 4631da177e4SLinus Torvalds #define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \ 4649b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4651da177e4SLinus Torvalds decode_putfh_maxsz + \ 4669104a55dSTrond Myklebust decode_readdir_maxsz) 4671da177e4SLinus Torvalds #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ 4689b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4691da177e4SLinus Torvalds encode_putfh_maxsz + \ 4709104a55dSTrond Myklebust encode_write_maxsz + \ 4714f9838c7STrond Myklebust encode_getattr_maxsz) 4721da177e4SLinus Torvalds #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ 4739b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4741da177e4SLinus Torvalds decode_putfh_maxsz + \ 4759104a55dSTrond Myklebust decode_write_maxsz + \ 4764f9838c7STrond Myklebust decode_getattr_maxsz) 4771da177e4SLinus Torvalds #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ 4789b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4791da177e4SLinus Torvalds encode_putfh_maxsz + \ 4808582715eSTrond Myklebust encode_commit_maxsz) 4811da177e4SLinus Torvalds #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ 4829b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4831da177e4SLinus Torvalds decode_putfh_maxsz + \ 4848582715eSTrond Myklebust decode_commit_maxsz) 4851da177e4SLinus Torvalds #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ 4869b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4871da177e4SLinus Torvalds encode_putfh_maxsz + \ 4882cebf828STrond Myklebust encode_open_maxsz + \ 4896168f62cSWeston Andros Adamson encode_access_maxsz + \ 4902cebf828STrond Myklebust encode_getfh_maxsz + \ 49156f487f8SFred Isaman encode_getattr_maxsz + \ 49256f487f8SFred Isaman encode_layoutget_maxsz) 4931da177e4SLinus Torvalds #define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ 4949b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4951da177e4SLinus Torvalds decode_putfh_maxsz + \ 4962cebf828STrond Myklebust decode_open_maxsz + \ 4976168f62cSWeston Andros Adamson decode_access_maxsz + \ 4982cebf828STrond Myklebust decode_getfh_maxsz + \ 49956f487f8SFred Isaman decode_getattr_maxsz + \ 50056f487f8SFred Isaman decode_layoutget_maxsz) 5011da177e4SLinus Torvalds #define NFS4_enc_open_confirm_sz \ 5021da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 5031da177e4SLinus Torvalds encode_putfh_maxsz + \ 5049104a55dSTrond Myklebust encode_open_confirm_maxsz) 5059104a55dSTrond Myklebust #define NFS4_dec_open_confirm_sz \ 5069104a55dSTrond Myklebust (compound_decode_hdr_maxsz + \ 5071da177e4SLinus Torvalds decode_putfh_maxsz + \ 5089104a55dSTrond Myklebust decode_open_confirm_maxsz) 5091da177e4SLinus Torvalds #define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \ 5109b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5111da177e4SLinus Torvalds encode_putfh_maxsz + \ 5122cebf828STrond Myklebust encode_open_maxsz + \ 5136168f62cSWeston Andros Adamson encode_access_maxsz + \ 51456f487f8SFred Isaman encode_getattr_maxsz + \ 51556f487f8SFred Isaman encode_layoutget_maxsz) 5161da177e4SLinus Torvalds #define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \ 5179b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5181da177e4SLinus Torvalds decode_putfh_maxsz + \ 5192cebf828STrond Myklebust decode_open_maxsz + \ 5206168f62cSWeston Andros Adamson decode_access_maxsz + \ 52156f487f8SFred Isaman decode_getattr_maxsz + \ 52256f487f8SFred Isaman decode_layoutget_maxsz) 5231da177e4SLinus Torvalds #define NFS4_enc_open_downgrade_sz \ 5241da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 5259b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5261da177e4SLinus Torvalds encode_putfh_maxsz + \ 527b6808145STrond Myklebust encode_layoutreturn_maxsz + \ 5283947b74dSTrond Myklebust encode_open_downgrade_maxsz) 5291da177e4SLinus Torvalds #define NFS4_dec_open_downgrade_sz \ 5301da177e4SLinus Torvalds (compound_decode_hdr_maxsz + \ 5319b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5321da177e4SLinus Torvalds decode_putfh_maxsz + \ 533b6808145STrond Myklebust decode_layoutreturn_maxsz + \ 5343947b74dSTrond Myklebust decode_open_downgrade_maxsz) 5351da177e4SLinus Torvalds #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ 5369b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5371da177e4SLinus Torvalds encode_putfh_maxsz + \ 538cf805165STrond Myklebust encode_layoutreturn_maxsz + \ 5399104a55dSTrond Myklebust encode_close_maxsz + \ 540516a6af6STrond Myklebust encode_getattr_maxsz) 5411da177e4SLinus Torvalds #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ 5429b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5431da177e4SLinus Torvalds decode_putfh_maxsz + \ 544cf805165STrond Myklebust decode_layoutreturn_maxsz + \ 5459104a55dSTrond Myklebust decode_close_maxsz + \ 546516a6af6STrond Myklebust decode_getattr_maxsz) 5471da177e4SLinus Torvalds #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ 5489b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5491da177e4SLinus Torvalds encode_putfh_maxsz + \ 5509104a55dSTrond Myklebust encode_setattr_maxsz + \ 5511da177e4SLinus Torvalds encode_getattr_maxsz) 5521da177e4SLinus Torvalds #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ 5539b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5541da177e4SLinus Torvalds decode_putfh_maxsz + \ 5559104a55dSTrond Myklebust decode_setattr_maxsz + \ 5569104a55dSTrond Myklebust decode_getattr_maxsz) 5571da177e4SLinus Torvalds #define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \ 5589b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5591da177e4SLinus Torvalds encode_putfh_maxsz + \ 5601da177e4SLinus Torvalds encode_fsinfo_maxsz) 5611da177e4SLinus Torvalds #define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \ 5629b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5631da177e4SLinus Torvalds decode_putfh_maxsz + \ 5641da177e4SLinus Torvalds decode_fsinfo_maxsz) 5651da177e4SLinus Torvalds #define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \ 5661da177e4SLinus Torvalds encode_renew_maxsz) 5671da177e4SLinus Torvalds #define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \ 5681da177e4SLinus Torvalds decode_renew_maxsz) 5691da177e4SLinus Torvalds #define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \ 5701da177e4SLinus Torvalds encode_setclientid_maxsz) 5711da177e4SLinus Torvalds #define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \ 5721da177e4SLinus Torvalds decode_setclientid_maxsz) 5731da177e4SLinus Torvalds #define NFS4_enc_setclientid_confirm_sz \ 5741da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 57583ca7f5aSChuck Lever encode_setclientid_confirm_maxsz) 5761da177e4SLinus Torvalds #define NFS4_dec_setclientid_confirm_sz \ 5771da177e4SLinus Torvalds (compound_decode_hdr_maxsz + \ 57883ca7f5aSChuck Lever decode_setclientid_confirm_maxsz) 5791da177e4SLinus Torvalds #define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \ 5809b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5811da177e4SLinus Torvalds encode_putfh_maxsz + \ 5829104a55dSTrond Myklebust encode_lock_maxsz) 5831da177e4SLinus Torvalds #define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \ 5849b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5851da177e4SLinus Torvalds decode_putfh_maxsz + \ 5869104a55dSTrond Myklebust decode_lock_maxsz) 5871da177e4SLinus Torvalds #define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \ 5889b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5891da177e4SLinus Torvalds encode_putfh_maxsz + \ 5909104a55dSTrond Myklebust encode_lockt_maxsz) 5919104a55dSTrond Myklebust #define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \ 5929b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5939104a55dSTrond Myklebust decode_putfh_maxsz + \ 5949104a55dSTrond Myklebust decode_lockt_maxsz) 5951da177e4SLinus Torvalds #define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \ 5969b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5971da177e4SLinus Torvalds encode_putfh_maxsz + \ 5989104a55dSTrond Myklebust encode_locku_maxsz) 5991da177e4SLinus Torvalds #define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \ 6009b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6011da177e4SLinus Torvalds decode_putfh_maxsz + \ 6029104a55dSTrond Myklebust decode_locku_maxsz) 603d3c7b7ccSTrond Myklebust #define NFS4_enc_release_lockowner_sz \ 604d3c7b7ccSTrond Myklebust (compound_encode_hdr_maxsz + \ 605d3c7b7ccSTrond Myklebust encode_lockowner_maxsz) 606d3c7b7ccSTrond Myklebust #define NFS4_dec_release_lockowner_sz \ 607d3c7b7ccSTrond Myklebust (compound_decode_hdr_maxsz + \ 608d3c7b7ccSTrond Myklebust decode_lockowner_maxsz) 6091da177e4SLinus Torvalds #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ 6109b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6111da177e4SLinus Torvalds encode_putfh_maxsz + \ 61276b32999STrond Myklebust encode_access_maxsz + \ 61376b32999STrond Myklebust encode_getattr_maxsz) 6141da177e4SLinus Torvalds #define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ 6159b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6161da177e4SLinus Torvalds decode_putfh_maxsz + \ 61776b32999STrond Myklebust decode_access_maxsz + \ 61876b32999STrond Myklebust decode_getattr_maxsz) 6191da177e4SLinus Torvalds #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ 6209b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6211da177e4SLinus Torvalds encode_putfh_maxsz + \ 62244c99933SChuck Lever encode_getattr_maxsz + \ 62344c99933SChuck Lever encode_renew_maxsz) 6241da177e4SLinus Torvalds #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ 6259b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6261da177e4SLinus Torvalds decode_putfh_maxsz + \ 62744c99933SChuck Lever decode_getattr_maxsz + \ 62844c99933SChuck Lever decode_renew_maxsz) 6291da177e4SLinus Torvalds #define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ 6309b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6311da177e4SLinus Torvalds encode_putfh_maxsz + \ 6321da177e4SLinus Torvalds encode_lookup_maxsz + \ 6331da177e4SLinus Torvalds encode_getattr_maxsz + \ 6341da177e4SLinus Torvalds encode_getfh_maxsz) 6351da177e4SLinus Torvalds #define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \ 6369b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6371da177e4SLinus Torvalds decode_putfh_maxsz + \ 638e6889620STrond Myklebust decode_lookup_maxsz + \ 6391da177e4SLinus Torvalds decode_getattr_maxsz + \ 6401da177e4SLinus Torvalds decode_getfh_maxsz) 6415b5faaf6SJeff Layton #define NFS4_enc_lookupp_sz (compound_encode_hdr_maxsz + \ 6425b5faaf6SJeff Layton encode_sequence_maxsz + \ 6435b5faaf6SJeff Layton encode_putfh_maxsz + \ 6445b5faaf6SJeff Layton encode_lookupp_maxsz + \ 6455b5faaf6SJeff Layton encode_getattr_maxsz + \ 6465b5faaf6SJeff Layton encode_getfh_maxsz) 6475b5faaf6SJeff Layton #define NFS4_dec_lookupp_sz (compound_decode_hdr_maxsz + \ 6485b5faaf6SJeff Layton decode_sequence_maxsz + \ 6495b5faaf6SJeff Layton decode_putfh_maxsz + \ 6505b5faaf6SJeff Layton decode_lookupp_maxsz + \ 6515b5faaf6SJeff Layton decode_getattr_maxsz + \ 6525b5faaf6SJeff Layton decode_getfh_maxsz) 6531da177e4SLinus Torvalds #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ 6549b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6551da177e4SLinus Torvalds encode_putrootfh_maxsz + \ 6561da177e4SLinus Torvalds encode_getattr_maxsz + \ 6571da177e4SLinus Torvalds encode_getfh_maxsz) 6581da177e4SLinus Torvalds #define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \ 6599b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6601da177e4SLinus Torvalds decode_putrootfh_maxsz + \ 6611da177e4SLinus Torvalds decode_getattr_maxsz + \ 6621da177e4SLinus Torvalds decode_getfh_maxsz) 6631da177e4SLinus Torvalds #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ 6649b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6651da177e4SLinus Torvalds encode_putfh_maxsz + \ 666778d2817STrond Myklebust encode_remove_maxsz) 6671da177e4SLinus Torvalds #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ 6689b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6691da177e4SLinus Torvalds decode_putfh_maxsz + \ 670778d2817STrond Myklebust decode_remove_maxsz) 6711da177e4SLinus Torvalds #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ 6729b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6731da177e4SLinus Torvalds encode_putfh_maxsz + \ 6741da177e4SLinus Torvalds encode_savefh_maxsz + \ 6751da177e4SLinus Torvalds encode_putfh_maxsz + \ 676778d2817STrond Myklebust encode_rename_maxsz) 6771da177e4SLinus Torvalds #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ 6789b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6791da177e4SLinus Torvalds decode_putfh_maxsz + \ 6801da177e4SLinus Torvalds decode_savefh_maxsz + \ 6811da177e4SLinus Torvalds decode_putfh_maxsz + \ 682778d2817STrond Myklebust decode_rename_maxsz) 6831da177e4SLinus Torvalds #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ 6849b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6851da177e4SLinus Torvalds encode_putfh_maxsz + \ 6861da177e4SLinus Torvalds encode_savefh_maxsz + \ 6871da177e4SLinus Torvalds encode_putfh_maxsz + \ 68891ba2eeeSTrond Myklebust encode_link_maxsz + \ 68991ba2eeeSTrond Myklebust encode_restorefh_maxsz + \ 690a9f6991bSTrond Myklebust encode_getattr_maxsz) 6911da177e4SLinus Torvalds #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ 6929b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6931da177e4SLinus Torvalds decode_putfh_maxsz + \ 6941da177e4SLinus Torvalds decode_savefh_maxsz + \ 6951da177e4SLinus Torvalds decode_putfh_maxsz + \ 69691ba2eeeSTrond Myklebust decode_link_maxsz + \ 69791ba2eeeSTrond Myklebust decode_restorefh_maxsz + \ 69891ba2eeeSTrond Myklebust decode_getattr_maxsz) 6991da177e4SLinus Torvalds #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ 7009b7b9fccSAndy Adamson encode_sequence_maxsz + \ 7011da177e4SLinus Torvalds encode_putfh_maxsz + \ 7021da177e4SLinus Torvalds encode_symlink_maxsz + \ 7031da177e4SLinus Torvalds encode_getattr_maxsz + \ 7041da177e4SLinus Torvalds encode_getfh_maxsz) 7051da177e4SLinus Torvalds #define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \ 7069b7b9fccSAndy Adamson decode_sequence_maxsz + \ 7071da177e4SLinus Torvalds decode_putfh_maxsz + \ 7081da177e4SLinus Torvalds decode_symlink_maxsz + \ 7091da177e4SLinus Torvalds decode_getattr_maxsz + \ 7101da177e4SLinus Torvalds decode_getfh_maxsz) 7111da177e4SLinus Torvalds #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ 7129b7b9fccSAndy Adamson encode_sequence_maxsz + \ 7131da177e4SLinus Torvalds encode_putfh_maxsz + \ 7141da177e4SLinus Torvalds encode_create_maxsz + \ 71556ae19f3STrond Myklebust encode_getfh_maxsz + \ 71656ae19f3STrond Myklebust encode_getattr_maxsz) 7171da177e4SLinus Torvalds #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ 7189b7b9fccSAndy Adamson decode_sequence_maxsz + \ 7191da177e4SLinus Torvalds decode_putfh_maxsz + \ 7201da177e4SLinus Torvalds decode_create_maxsz + \ 72156ae19f3STrond Myklebust decode_getfh_maxsz + \ 72256ae19f3STrond Myklebust decode_getattr_maxsz) 7231da177e4SLinus Torvalds #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ 7249b7b9fccSAndy Adamson encode_sequence_maxsz + \ 7251da177e4SLinus Torvalds encode_putfh_maxsz + \ 7261da177e4SLinus Torvalds encode_getattr_maxsz) 7271da177e4SLinus Torvalds #define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \ 7289b7b9fccSAndy Adamson decode_sequence_maxsz + \ 7291da177e4SLinus Torvalds decode_putfh_maxsz + \ 7301da177e4SLinus Torvalds decode_getattr_maxsz) 7311da177e4SLinus Torvalds #define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \ 7329b7b9fccSAndy Adamson encode_sequence_maxsz + \ 7331da177e4SLinus Torvalds encode_putfh_maxsz + \ 7349104a55dSTrond Myklebust encode_statfs_maxsz) 7351da177e4SLinus Torvalds #define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \ 7369b7b9fccSAndy Adamson decode_sequence_maxsz + \ 7371da177e4SLinus Torvalds decode_putfh_maxsz + \ 7389104a55dSTrond Myklebust decode_statfs_maxsz) 7391da177e4SLinus Torvalds #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ 7409b7b9fccSAndy Adamson encode_sequence_maxsz + \ 741ab91f264STrond Myklebust encode_putfh_maxsz + \ 7421da177e4SLinus Torvalds encode_getattr_maxsz) 7431da177e4SLinus Torvalds #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ 7449b7b9fccSAndy Adamson decode_sequence_maxsz + \ 745ab91f264STrond Myklebust decode_putfh_maxsz + \ 7461da177e4SLinus Torvalds decode_getattr_maxsz) 7471da177e4SLinus Torvalds #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ 7489b7b9fccSAndy Adamson encode_sequence_maxsz + \ 7491da177e4SLinus Torvalds encode_putfh_maxsz + \ 750586f1c39STrond Myklebust encode_layoutreturn_maxsz + \ 751fa178f29STrond Myklebust encode_delegreturn_maxsz + \ 752fa178f29STrond Myklebust encode_getattr_maxsz) 7531da177e4SLinus Torvalds #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ 7549b7b9fccSAndy Adamson decode_sequence_maxsz + \ 755d8434d4cSTrond Myklebust decode_putfh_maxsz + \ 756586f1c39STrond Myklebust decode_layoutreturn_maxsz + \ 757fa178f29STrond Myklebust decode_delegreturn_maxsz + \ 758fa178f29STrond Myklebust decode_getattr_maxsz) 759029d105eSJ. Bruce Fields #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ 7609b7b9fccSAndy Adamson encode_sequence_maxsz + \ 761029d105eSJ. Bruce Fields encode_putfh_maxsz + \ 7629104a55dSTrond Myklebust encode_getacl_maxsz) 763029d105eSJ. Bruce Fields #define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ 7649b7b9fccSAndy Adamson decode_sequence_maxsz + \ 765029d105eSJ. Bruce Fields decode_putfh_maxsz + \ 7669104a55dSTrond Myklebust decode_getacl_maxsz) 76723ec6965SJ. Bruce Fields #define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ 7689b7b9fccSAndy Adamson encode_sequence_maxsz + \ 76923ec6965SJ. Bruce Fields encode_putfh_maxsz + \ 7709104a55dSTrond Myklebust encode_setacl_maxsz) 77123ec6965SJ. Bruce Fields #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ 7729b7b9fccSAndy Adamson decode_sequence_maxsz + \ 77323ec6965SJ. Bruce Fields decode_putfh_maxsz + \ 7749104a55dSTrond Myklebust decode_setacl_maxsz) 775683b57b4STrond Myklebust #define NFS4_enc_fs_locations_sz \ 776683b57b4STrond Myklebust (compound_encode_hdr_maxsz + \ 7779b7b9fccSAndy Adamson encode_sequence_maxsz + \ 778683b57b4STrond Myklebust encode_putfh_maxsz + \ 779e6889620STrond Myklebust encode_lookup_maxsz + \ 780b03d735bSChuck Lever encode_fs_locations_maxsz + \ 781b03d735bSChuck Lever encode_renew_maxsz) 782683b57b4STrond Myklebust #define NFS4_dec_fs_locations_sz \ 783683b57b4STrond Myklebust (compound_decode_hdr_maxsz + \ 7849b7b9fccSAndy Adamson decode_sequence_maxsz + \ 785683b57b4STrond Myklebust decode_putfh_maxsz + \ 786e6889620STrond Myklebust decode_lookup_maxsz + \ 787b03d735bSChuck Lever decode_fs_locations_maxsz + \ 788b03d735bSChuck Lever decode_renew_maxsz) 7895a5ea0d4SBryan Schumaker #define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \ 7905a5ea0d4SBryan Schumaker encode_sequence_maxsz + \ 7915a5ea0d4SBryan Schumaker encode_putfh_maxsz + \ 7925a5ea0d4SBryan Schumaker encode_secinfo_maxsz) 7935a5ea0d4SBryan Schumaker #define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \ 7945a5ea0d4SBryan Schumaker decode_sequence_maxsz + \ 7955a5ea0d4SBryan Schumaker decode_putfh_maxsz + \ 7965a5ea0d4SBryan Schumaker decode_secinfo_maxsz) 79744c99933SChuck Lever #define NFS4_enc_fsid_present_sz \ 79844c99933SChuck Lever (compound_encode_hdr_maxsz + \ 79944c99933SChuck Lever encode_sequence_maxsz + \ 80044c99933SChuck Lever encode_putfh_maxsz + \ 80144c99933SChuck Lever encode_getfh_maxsz + \ 80244c99933SChuck Lever encode_renew_maxsz) 80344c99933SChuck Lever #define NFS4_dec_fsid_present_sz \ 80444c99933SChuck Lever (compound_decode_hdr_maxsz + \ 80544c99933SChuck Lever decode_sequence_maxsz + \ 80644c99933SChuck Lever decode_putfh_maxsz + \ 80744c99933SChuck Lever decode_getfh_maxsz + \ 80844c99933SChuck Lever decode_renew_maxsz) 80999fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 8107c44f1aeSWeston Andros Adamson #define NFS4_enc_bind_conn_to_session_sz \ 8117c44f1aeSWeston Andros Adamson (compound_encode_hdr_maxsz + \ 8127c44f1aeSWeston Andros Adamson encode_bind_conn_to_session_maxsz) 8137c44f1aeSWeston Andros Adamson #define NFS4_dec_bind_conn_to_session_sz \ 8147c44f1aeSWeston Andros Adamson (compound_decode_hdr_maxsz + \ 8157c44f1aeSWeston Andros Adamson decode_bind_conn_to_session_maxsz) 81699fe60d0SBenny Halevy #define NFS4_enc_exchange_id_sz \ 81799fe60d0SBenny Halevy (compound_encode_hdr_maxsz + \ 81899fe60d0SBenny Halevy encode_exchange_id_maxsz) 81999fe60d0SBenny Halevy #define NFS4_dec_exchange_id_sz \ 82099fe60d0SBenny Halevy (compound_decode_hdr_maxsz + \ 82199fe60d0SBenny Halevy decode_exchange_id_maxsz) 822fc931582SAndy Adamson #define NFS4_enc_create_session_sz \ 823fc931582SAndy Adamson (compound_encode_hdr_maxsz + \ 824fc931582SAndy Adamson encode_create_session_maxsz) 825fc931582SAndy Adamson #define NFS4_dec_create_session_sz \ 826fc931582SAndy Adamson (compound_decode_hdr_maxsz + \ 827fc931582SAndy Adamson decode_create_session_maxsz) 8280f3e66c6SAndy Adamson #define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \ 8290f3e66c6SAndy Adamson encode_destroy_session_maxsz) 8300f3e66c6SAndy Adamson #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ 8310f3e66c6SAndy Adamson decode_destroy_session_maxsz) 83266245539STrond Myklebust #define NFS4_enc_destroy_clientid_sz (compound_encode_hdr_maxsz + \ 83366245539STrond Myklebust encode_destroy_clientid_maxsz) 83466245539STrond Myklebust #define NFS4_dec_destroy_clientid_sz (compound_decode_hdr_maxsz + \ 83566245539STrond Myklebust decode_destroy_clientid_maxsz) 836fc01cea9SAndy Adamson #define NFS4_enc_sequence_sz \ 837fc01cea9SAndy Adamson (compound_decode_hdr_maxsz + \ 838fc01cea9SAndy Adamson encode_sequence_maxsz) 839fc01cea9SAndy Adamson #define NFS4_dec_sequence_sz \ 840fc01cea9SAndy Adamson (compound_decode_hdr_maxsz + \ 841fc01cea9SAndy Adamson decode_sequence_maxsz) 8420efb01b2SDonald Buczek #endif 8432050f0ccSAndy Adamson #define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \ 8442050f0ccSAndy Adamson encode_sequence_maxsz + \ 8452050f0ccSAndy Adamson encode_putrootfh_maxsz + \ 8462050f0ccSAndy Adamson encode_fsinfo_maxsz) 8472050f0ccSAndy Adamson #define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \ 8482050f0ccSAndy Adamson decode_sequence_maxsz + \ 8492050f0ccSAndy Adamson decode_putrootfh_maxsz + \ 8502050f0ccSAndy Adamson decode_fsinfo_maxsz) 8510efb01b2SDonald Buczek #if defined(CONFIG_NFS_V4_1) 85218019753SRicardo Labiaga #define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \ 85318019753SRicardo Labiaga encode_sequence_maxsz + \ 85418019753SRicardo Labiaga encode_reclaim_complete_maxsz) 85518019753SRicardo Labiaga #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ 85618019753SRicardo Labiaga decode_sequence_maxsz + \ 85718019753SRicardo Labiaga decode_reclaim_complete_maxsz) 858b1f69b75SAndy Adamson #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ 859b1f69b75SAndy Adamson encode_sequence_maxsz +\ 860b1f69b75SAndy Adamson encode_getdeviceinfo_maxsz) 861b1f69b75SAndy Adamson #define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \ 862b1f69b75SAndy Adamson decode_sequence_maxsz + \ 863b1f69b75SAndy Adamson decode_getdeviceinfo_maxsz) 864b1f69b75SAndy Adamson #define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \ 865b1f69b75SAndy Adamson encode_sequence_maxsz + \ 866b1f69b75SAndy Adamson encode_putfh_maxsz + \ 867b1f69b75SAndy Adamson encode_layoutget_maxsz) 868b1f69b75SAndy Adamson #define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \ 869b1f69b75SAndy Adamson decode_sequence_maxsz + \ 870b1f69b75SAndy Adamson decode_putfh_maxsz + \ 871b1f69b75SAndy Adamson decode_layoutget_maxsz) 872863a3c6cSAndy Adamson #define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ 873863a3c6cSAndy Adamson encode_sequence_maxsz +\ 874863a3c6cSAndy Adamson encode_putfh_maxsz + \ 875863a3c6cSAndy Adamson encode_layoutcommit_maxsz + \ 876863a3c6cSAndy Adamson encode_getattr_maxsz) 877863a3c6cSAndy Adamson #define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ 878863a3c6cSAndy Adamson decode_sequence_maxsz + \ 879863a3c6cSAndy Adamson decode_putfh_maxsz + \ 880863a3c6cSAndy Adamson decode_layoutcommit_maxsz + \ 881863a3c6cSAndy Adamson decode_getattr_maxsz) 882cbe82603SBenny Halevy #define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \ 883cbe82603SBenny Halevy encode_sequence_maxsz + \ 884cbe82603SBenny Halevy encode_putfh_maxsz + \ 885cbe82603SBenny Halevy encode_layoutreturn_maxsz) 886cbe82603SBenny Halevy #define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \ 887cbe82603SBenny Halevy decode_sequence_maxsz + \ 888cbe82603SBenny Halevy decode_putfh_maxsz + \ 889cbe82603SBenny Halevy decode_layoutreturn_maxsz) 890fca78d6dSBryan Schumaker #define NFS4_enc_secinfo_no_name_sz (compound_encode_hdr_maxsz + \ 891fca78d6dSBryan Schumaker encode_sequence_maxsz + \ 892fca78d6dSBryan Schumaker encode_putrootfh_maxsz +\ 893fca78d6dSBryan Schumaker encode_secinfo_no_name_maxsz) 894fca78d6dSBryan Schumaker #define NFS4_dec_secinfo_no_name_sz (compound_decode_hdr_maxsz + \ 895fca78d6dSBryan Schumaker decode_sequence_maxsz + \ 896fca78d6dSBryan Schumaker decode_putrootfh_maxsz + \ 897fca78d6dSBryan Schumaker decode_secinfo_no_name_maxsz) 8987d974794SBryan Schumaker #define NFS4_enc_test_stateid_sz (compound_encode_hdr_maxsz + \ 8997d974794SBryan Schumaker encode_sequence_maxsz + \ 9007d974794SBryan Schumaker encode_test_stateid_maxsz) 9017d974794SBryan Schumaker #define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \ 9027d974794SBryan Schumaker decode_sequence_maxsz + \ 9037d974794SBryan Schumaker decode_test_stateid_maxsz) 9049aeda35fSBryan Schumaker #define NFS4_enc_free_stateid_sz (compound_encode_hdr_maxsz + \ 9059aeda35fSBryan Schumaker encode_sequence_maxsz + \ 9069aeda35fSBryan Schumaker encode_free_stateid_maxsz) 9079aeda35fSBryan Schumaker #define NFS4_dec_free_stateid_sz (compound_decode_hdr_maxsz + \ 9089aeda35fSBryan Schumaker decode_sequence_maxsz + \ 9099aeda35fSBryan Schumaker decode_free_stateid_maxsz) 9102449ea2eSAlexandros Batsakis 9112449ea2eSAlexandros Batsakis const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 9122449ea2eSAlexandros Batsakis compound_encode_hdr_maxsz + 9132449ea2eSAlexandros Batsakis encode_sequence_maxsz + 9142449ea2eSAlexandros Batsakis encode_putfh_maxsz + 9152449ea2eSAlexandros Batsakis encode_getattr_maxsz) * 9162449ea2eSAlexandros Batsakis XDR_UNIT); 9172449ea2eSAlexandros Batsakis 9182449ea2eSAlexandros Batsakis const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 9192449ea2eSAlexandros Batsakis compound_decode_hdr_maxsz + 9202449ea2eSAlexandros Batsakis decode_sequence_maxsz + 9212449ea2eSAlexandros Batsakis decode_putfh_maxsz) * 9222449ea2eSAlexandros Batsakis XDR_UNIT); 923f1c097beSAndy Adamson 924f1c097beSAndy Adamson const u32 nfs41_maxgetdevinfo_overhead = ((RPC_MAX_REPHEADER_WITH_AUTH + 925f1c097beSAndy Adamson compound_decode_hdr_maxsz + 926f1c097beSAndy Adamson decode_sequence_maxsz) * 927f1c097beSAndy Adamson XDR_UNIT); 928f1c097beSAndy Adamson EXPORT_SYMBOL_GPL(nfs41_maxgetdevinfo_overhead); 92999fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 9301da177e4SLinus Torvalds 931bca79478STrond Myklebust static const umode_t nfs_type2fmt[] = { 932bca79478STrond Myklebust [NF4BAD] = 0, 933bca79478STrond Myklebust [NF4REG] = S_IFREG, 934bca79478STrond Myklebust [NF4DIR] = S_IFDIR, 935bca79478STrond Myklebust [NF4BLK] = S_IFBLK, 936bca79478STrond Myklebust [NF4CHR] = S_IFCHR, 937bca79478STrond Myklebust [NF4LNK] = S_IFLNK, 938bca79478STrond Myklebust [NF4SOCK] = S_IFSOCK, 939bca79478STrond Myklebust [NF4FIFO] = S_IFIFO, 940bca79478STrond Myklebust [NF4ATTRDIR] = 0, 941bca79478STrond Myklebust [NF4NAMEDATTR] = 0, 9421da177e4SLinus Torvalds }; 9431da177e4SLinus Torvalds 9441da177e4SLinus Torvalds struct compound_hdr { 9451da177e4SLinus Torvalds int32_t status; 9461da177e4SLinus Torvalds uint32_t nops; 947d017931cSAndy Adamson __be32 * nops_p; 9481da177e4SLinus Torvalds uint32_t taglen; 9491da177e4SLinus Torvalds char * tag; 9500c4e8c18SBenny Halevy uint32_t replen; /* expected reply words */ 95166cc0429SBenny Halevy u32 minorversion; 9521da177e4SLinus Torvalds }; 9531da177e4SLinus Torvalds 95413c65ce9SBenny Halevy static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes) 95513c65ce9SBenny Halevy { 95613c65ce9SBenny Halevy __be32 *p = xdr_reserve_space(xdr, nbytes); 95713c65ce9SBenny Halevy BUG_ON(!p); 95813c65ce9SBenny Halevy return p; 95913c65ce9SBenny Halevy } 9601da177e4SLinus Torvalds 961cb17e556STrond Myklebust static void encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len) 962cb17e556STrond Myklebust { 963ab6e9aafSTrond Myklebust WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, buf, len) < 0); 964cb17e556STrond Myklebust } 965cb17e556STrond Myklebust 9661da177e4SLinus Torvalds static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) 9671da177e4SLinus Torvalds { 968ab6e9aafSTrond Myklebust WARN_ON_ONCE(xdr_stream_encode_opaque(xdr, str, len) < 0); 9691da177e4SLinus Torvalds } 9701da177e4SLinus Torvalds 9714ade9821STrond Myklebust static void encode_uint32(struct xdr_stream *xdr, u32 n) 9724ade9821STrond Myklebust { 973ab6e9aafSTrond Myklebust WARN_ON_ONCE(xdr_stream_encode_u32(xdr, n) < 0); 9744ade9821STrond Myklebust } 9754ade9821STrond Myklebust 976ff2eb681STrond Myklebust static void encode_uint64(struct xdr_stream *xdr, u64 n) 977ff2eb681STrond Myklebust { 978ab6e9aafSTrond Myklebust WARN_ON_ONCE(xdr_stream_encode_u64(xdr, n) < 0); 979ff2eb681STrond Myklebust } 980ff2eb681STrond Myklebust 98137c88763STrond Myklebust static ssize_t xdr_encode_bitmap4(struct xdr_stream *xdr, 98237c88763STrond Myklebust const __u32 *bitmap, size_t len) 98337c88763STrond Myklebust { 98437c88763STrond Myklebust ssize_t ret; 98537c88763STrond Myklebust 98637c88763STrond Myklebust /* Trim empty words */ 98737c88763STrond Myklebust while (len > 0 && bitmap[len-1] == 0) 98837c88763STrond Myklebust len--; 98937c88763STrond Myklebust ret = xdr_stream_encode_uint32_array(xdr, bitmap, len); 99037c88763STrond Myklebust if (WARN_ON_ONCE(ret < 0)) 99137c88763STrond Myklebust return ret; 99237c88763STrond Myklebust return len; 99337c88763STrond Myklebust } 99437c88763STrond Myklebust 99537c88763STrond Myklebust static size_t mask_bitmap4(const __u32 *bitmap, const __u32 *mask, 99637c88763STrond Myklebust __u32 *res, size_t len) 99737c88763STrond Myklebust { 99837c88763STrond Myklebust size_t i; 99937c88763STrond Myklebust __u32 tmp; 100037c88763STrond Myklebust 100137c88763STrond Myklebust while (len > 0 && (bitmap[len-1] == 0 || mask[len-1] == 0)) 100237c88763STrond Myklebust len--; 100337c88763STrond Myklebust for (i = len; i-- > 0;) { 100437c88763STrond Myklebust tmp = bitmap[i] & mask[i]; 100537c88763STrond Myklebust res[i] = tmp; 100637c88763STrond Myklebust } 100737c88763STrond Myklebust return len; 100837c88763STrond Myklebust } 100937c88763STrond Myklebust 10104ade9821STrond Myklebust static void encode_nfs4_seqid(struct xdr_stream *xdr, 10114ade9821STrond Myklebust const struct nfs_seqid *seqid) 10124ade9821STrond Myklebust { 1013a6796419STrond Myklebust if (seqid != NULL) 10144ade9821STrond Myklebust encode_uint32(xdr, seqid->sequence->counter); 1015a6796419STrond Myklebust else 1016a6796419STrond Myklebust encode_uint32(xdr, 0); 10174ade9821STrond Myklebust } 10184ade9821STrond Myklebust 10190c4e8c18SBenny Halevy static void encode_compound_hdr(struct xdr_stream *xdr, 10200c4e8c18SBenny Halevy struct rpc_rqst *req, 10210c4e8c18SBenny Halevy struct compound_hdr *hdr) 10221da177e4SLinus Torvalds { 10238687b63aSAl Viro __be32 *p; 10240c4e8c18SBenny Halevy 10250c4e8c18SBenny Halevy /* initialize running count of expected bytes in reply. 10260c4e8c18SBenny Halevy * NOTE: the replied tag SHOULD be the same is the one sent, 10270c4e8c18SBenny Halevy * but this is not required as a MUST for the server to do so. */ 1028cf500bacSChuck Lever hdr->replen = 3 + hdr->taglen; 10291da177e4SLinus Torvalds 10307fc38846STrond Myklebust WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN); 10316fdfb0bcSTrond Myklebust encode_string(xdr, hdr->taglen, hdr->tag); 10326fdfb0bcSTrond Myklebust p = reserve_space(xdr, 8); 1033e75bc1c8SBenny Halevy *p++ = cpu_to_be32(hdr->minorversion); 1034d017931cSAndy Adamson hdr->nops_p = p; 103534558513SBenny Halevy *p = cpu_to_be32(hdr->nops); 1036d017931cSAndy Adamson } 1037d017931cSAndy Adamson 1038ab19b481STrond Myklebust static void encode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 op, 1039ab19b481STrond Myklebust uint32_t replen, 1040ab19b481STrond Myklebust struct compound_hdr *hdr) 1041ab19b481STrond Myklebust { 1042ab19b481STrond Myklebust encode_uint32(xdr, op); 1043ab19b481STrond Myklebust hdr->nops++; 1044ab19b481STrond Myklebust hdr->replen += replen; 1045ab19b481STrond Myklebust } 1046ab19b481STrond Myklebust 1047d017931cSAndy Adamson static void encode_nops(struct compound_hdr *hdr) 1048d017931cSAndy Adamson { 10497fc38846STrond Myklebust WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS); 1050d017931cSAndy Adamson *hdr->nops_p = htonl(hdr->nops); 10511da177e4SLinus Torvalds } 10521da177e4SLinus Torvalds 1053ea9d23f5STrond Myklebust static void encode_nfs4_stateid(struct xdr_stream *xdr, const nfs4_stateid *stateid) 1054ea9d23f5STrond Myklebust { 10552d2f24adSTrond Myklebust encode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE); 1056ea9d23f5STrond Myklebust } 1057ea9d23f5STrond Myklebust 10581da177e4SLinus Torvalds static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf) 10591da177e4SLinus Torvalds { 1060cb17e556STrond Myklebust encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); 10611da177e4SLinus Torvalds } 10621da177e4SLinus Torvalds 106336b3743fSTrond Myklebust static __be32 * 1064e7d4b05cSTrond Myklebust xdr_encode_nfstime4(__be32 *p, const struct timespec64 *t) 106536b3743fSTrond Myklebust { 1066a3167dacSArnd Bergmann p = xdr_encode_hyper(p, t->tv_sec); 106736b3743fSTrond Myklebust *p++ = cpu_to_be32(t->tv_nsec); 106836b3743fSTrond Myklebust return p; 106936b3743fSTrond Myklebust } 107036b3743fSTrond Myklebust 1071aa9c2669SDavid Quigley static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, 1072aa9c2669SDavid Quigley const struct nfs4_label *label, 107328cf22d0STrond Myklebust const umode_t *umask, 10745334c5bdSKinglong Mee const struct nfs_server *server, 107528cf22d0STrond Myklebust const uint32_t attrmask[]) 10761da177e4SLinus Torvalds { 10771da177e4SLinus Torvalds char owner_name[IDMAP_NAMESZ]; 10781da177e4SLinus Torvalds char owner_group[IDMAP_NAMESZ]; 10791da177e4SLinus Torvalds int owner_namelen = 0; 10801da177e4SLinus Torvalds int owner_grouplen = 0; 10818687b63aSAl Viro __be32 *p; 1082d7067b2dSTrond Myklebust uint32_t len = 0; 1083d7067b2dSTrond Myklebust uint32_t bmval[3] = { 0 }; 10841da177e4SLinus Torvalds 10851da177e4SLinus Torvalds /* 10861da177e4SLinus Torvalds * We reserve enough space to write the entire attribute buffer at once. 10871da177e4SLinus Torvalds */ 108828cf22d0STrond Myklebust if ((iap->ia_valid & ATTR_SIZE) && (attrmask[0] & FATTR4_WORD0_SIZE)) { 1089d7067b2dSTrond Myklebust bmval[0] |= FATTR4_WORD0_SIZE; 10901da177e4SLinus Torvalds len += 8; 1091d7067b2dSTrond Myklebust } 1092d7067b2dSTrond Myklebust if (iap->ia_valid & ATTR_MODE) { 109328cf22d0STrond Myklebust if (umask && (attrmask[2] & FATTR4_WORD2_MODE_UMASK)) { 1094dff25ddbSAndreas Gruenbacher bmval[2] |= FATTR4_WORD2_MODE_UMASK; 1095dff25ddbSAndreas Gruenbacher len += 8; 109628cf22d0STrond Myklebust } else if (attrmask[1] & FATTR4_WORD1_MODE) { 1097d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_MODE; 10981da177e4SLinus Torvalds len += 4; 1099d7067b2dSTrond Myklebust } 1100dff25ddbSAndreas Gruenbacher } 110128cf22d0STrond Myklebust if ((iap->ia_valid & ATTR_UID) && (attrmask[1] & FATTR4_WORD1_OWNER)) { 1102e4fd72a1STrond Myklebust owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); 11031da177e4SLinus Torvalds if (owner_namelen < 0) { 1104fe82a183SChuck Lever dprintk("nfs: couldn't resolve uid %d to string\n", 1105e5782076SEric W. Biederman from_kuid(&init_user_ns, iap->ia_uid)); 11061da177e4SLinus Torvalds /* XXX */ 11071da177e4SLinus Torvalds strcpy(owner_name, "nobody"); 11081da177e4SLinus Torvalds owner_namelen = sizeof("nobody") - 1; 11091da177e4SLinus Torvalds /* goto out; */ 11101da177e4SLinus Torvalds } 1111d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_OWNER; 11121da177e4SLinus Torvalds len += 4 + (XDR_QUADLEN(owner_namelen) << 2); 11131da177e4SLinus Torvalds } 111428cf22d0STrond Myklebust if ((iap->ia_valid & ATTR_GID) && 111528cf22d0STrond Myklebust (attrmask[1] & FATTR4_WORD1_OWNER_GROUP)) { 1116e4fd72a1STrond Myklebust owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ); 11171da177e4SLinus Torvalds if (owner_grouplen < 0) { 1118fe82a183SChuck Lever dprintk("nfs: couldn't resolve gid %d to string\n", 1119e5782076SEric W. Biederman from_kgid(&init_user_ns, iap->ia_gid)); 11201da177e4SLinus Torvalds strcpy(owner_group, "nobody"); 11211da177e4SLinus Torvalds owner_grouplen = sizeof("nobody") - 1; 11221da177e4SLinus Torvalds /* goto out; */ 11231da177e4SLinus Torvalds } 1124d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_OWNER_GROUP; 11251da177e4SLinus Torvalds len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); 11261da177e4SLinus Torvalds } 112728cf22d0STrond Myklebust if (attrmask[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 1128d7067b2dSTrond Myklebust if (iap->ia_valid & ATTR_ATIME_SET) { 1129d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; 113036b3743fSTrond Myklebust len += 4 + (nfstime4_maxsz << 2); 1131d7067b2dSTrond Myklebust } else if (iap->ia_valid & ATTR_ATIME) { 1132d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; 11331da177e4SLinus Torvalds len += 4; 1134d7067b2dSTrond Myklebust } 113528cf22d0STrond Myklebust } 113628cf22d0STrond Myklebust if (attrmask[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 1137d7067b2dSTrond Myklebust if (iap->ia_valid & ATTR_MTIME_SET) { 1138d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; 113936b3743fSTrond Myklebust len += 4 + (nfstime4_maxsz << 2); 1140d7067b2dSTrond Myklebust } else if (iap->ia_valid & ATTR_MTIME) { 1141d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; 11421da177e4SLinus Torvalds len += 4; 1143d7067b2dSTrond Myklebust } 11445334c5bdSKinglong Mee } 11455334c5bdSKinglong Mee 114628cf22d0STrond Myklebust if (label && (attrmask[2] & FATTR4_WORD2_SECURITY_LABEL)) { 1147b4a2cf76STrond Myklebust len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); 1148d7067b2dSTrond Myklebust bmval[2] |= FATTR4_WORD2_SECURITY_LABEL; 1149d7067b2dSTrond Myklebust } 1150d7067b2dSTrond Myklebust 115140a3426cSTrond Myklebust xdr_encode_bitmap4(xdr, bmval, ARRAY_SIZE(bmval)); 115240a3426cSTrond Myklebust xdr_stream_encode_opaque_inline(xdr, (void **)&p, len); 11531da177e4SLinus Torvalds 1154d7067b2dSTrond Myklebust if (bmval[0] & FATTR4_WORD0_SIZE) 1155b95be5a9SBenny Halevy p = xdr_encode_hyper(p, iap->ia_size); 1156d7067b2dSTrond Myklebust if (bmval[1] & FATTR4_WORD1_MODE) 1157e75bc1c8SBenny Halevy *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); 1158d7067b2dSTrond Myklebust if (bmval[1] & FATTR4_WORD1_OWNER) 1159811652bdSBenny Halevy p = xdr_encode_opaque(p, owner_name, owner_namelen); 1160d7067b2dSTrond Myklebust if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) 1161811652bdSBenny Halevy p = xdr_encode_opaque(p, owner_group, owner_grouplen); 1162d7067b2dSTrond Myklebust if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 11631da177e4SLinus Torvalds if (iap->ia_valid & ATTR_ATIME_SET) { 1164e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 1165e7d4b05cSTrond Myklebust p = xdr_encode_nfstime4(p, &iap->ia_atime); 1166d7067b2dSTrond Myklebust } else 1167e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); 11681da177e4SLinus Torvalds } 1169d7067b2dSTrond Myklebust if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 11701da177e4SLinus Torvalds if (iap->ia_valid & ATTR_MTIME_SET) { 1171e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 1172e7d4b05cSTrond Myklebust p = xdr_encode_nfstime4(p, &iap->ia_mtime); 1173d7067b2dSTrond Myklebust } else 1174e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); 11751da177e4SLinus Torvalds } 1176e2751463SJia-Ju Bai if (label && (bmval[2] & FATTR4_WORD2_SECURITY_LABEL)) { 1177aa9c2669SDavid Quigley *p++ = cpu_to_be32(label->lfs); 1178aa9c2669SDavid Quigley *p++ = cpu_to_be32(label->pi); 1179aa9c2669SDavid Quigley *p++ = cpu_to_be32(label->len); 1180aa9c2669SDavid Quigley p = xdr_encode_opaque_fixed(p, label->label, label->len); 1181aa9c2669SDavid Quigley } 1182dff25ddbSAndreas Gruenbacher if (bmval[2] & FATTR4_WORD2_MODE_UMASK) { 1183dff25ddbSAndreas Gruenbacher *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); 1184dff25ddbSAndreas Gruenbacher *p++ = cpu_to_be32(*umask); 1185dff25ddbSAndreas Gruenbacher } 11861da177e4SLinus Torvalds 11871da177e4SLinus Torvalds /* out: */ 11881da177e4SLinus Torvalds } 11891da177e4SLinus Torvalds 1190cf8cdbe5SAndy Adamson static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr) 11911da177e4SLinus Torvalds { 1192475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_ACCESS, decode_access_maxsz, hdr); 1193475d4ba0STrond Myklebust encode_uint32(xdr, access); 11941da177e4SLinus Torvalds } 11951da177e4SLinus Torvalds 1196cf8cdbe5SAndy Adamson static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) 11971da177e4SLinus Torvalds { 1198ab19b481STrond Myklebust encode_op_hdr(xdr, OP_CLOSE, decode_close_maxsz, hdr); 11994ade9821STrond Myklebust encode_nfs4_seqid(xdr, arg->seqid); 1200566fcec6STrond Myklebust encode_nfs4_stateid(xdr, &arg->stateid); 12011da177e4SLinus Torvalds } 12021da177e4SLinus Torvalds 12030b7c0153SFred Isaman static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr) 12041da177e4SLinus Torvalds { 12058687b63aSAl Viro __be32 *p; 12061da177e4SLinus Torvalds 1207475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr); 1208475d4ba0STrond Myklebust p = reserve_space(xdr, 12); 1209b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 121034558513SBenny Halevy *p = cpu_to_be32(args->count); 12111da177e4SLinus Torvalds } 12121da177e4SLinus Torvalds 1213cf8cdbe5SAndy Adamson static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr) 12141da177e4SLinus Torvalds { 12158687b63aSAl Viro __be32 *p; 12161da177e4SLinus Torvalds 1217475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_CREATE, decode_create_maxsz, hdr); 1218475d4ba0STrond Myklebust encode_uint32(xdr, create->ftype); 12191da177e4SLinus Torvalds 12201da177e4SLinus Torvalds switch (create->ftype) { 12211da177e4SLinus Torvalds case NF4LNK: 122213c65ce9SBenny Halevy p = reserve_space(xdr, 4); 122334558513SBenny Halevy *p = cpu_to_be32(create->u.symlink.len); 12242fcc213aSChuck Lever xdr_write_pages(xdr, create->u.symlink.pages, 0, 12252fcc213aSChuck Lever create->u.symlink.len); 12262fcc213aSChuck Lever xdr->buf->flags |= XDRBUF_WRITE; 12271da177e4SLinus Torvalds break; 12281da177e4SLinus Torvalds 12291da177e4SLinus Torvalds case NF4BLK: case NF4CHR: 123013c65ce9SBenny Halevy p = reserve_space(xdr, 8); 1231e75bc1c8SBenny Halevy *p++ = cpu_to_be32(create->u.device.specdata1); 123234558513SBenny Halevy *p = cpu_to_be32(create->u.device.specdata2); 12331da177e4SLinus Torvalds break; 12341da177e4SLinus Torvalds 12351da177e4SLinus Torvalds default: 12361da177e4SLinus Torvalds break; 12371da177e4SLinus Torvalds } 12381da177e4SLinus Torvalds 1239811652bdSBenny Halevy encode_string(xdr, create->name->len, create->name->name); 124028cf22d0STrond Myklebust encode_attrs(xdr, create->attrs, create->label, &create->umask, 124128cf22d0STrond Myklebust create->server, create->server->attr_bitmask); 12421da177e4SLinus Torvalds } 12431da177e4SLinus Torvalds 124437c88763STrond Myklebust static void encode_getattr(struct xdr_stream *xdr, 124537c88763STrond Myklebust const __u32 *bitmap, const __u32 *mask, size_t len, 1246dae100c2SFred Isaman struct compound_hdr *hdr) 1247dae100c2SFred Isaman { 124837c88763STrond Myklebust __u32 masked_bitmap[nfs4_fattr_bitmap_maxsz]; 1249dae100c2SFred Isaman 1250ab19b481STrond Myklebust encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr); 125137c88763STrond Myklebust if (mask) { 125237c88763STrond Myklebust if (WARN_ON_ONCE(len > ARRAY_SIZE(masked_bitmap))) 125337c88763STrond Myklebust len = ARRAY_SIZE(masked_bitmap); 125437c88763STrond Myklebust len = mask_bitmap4(bitmap, mask, masked_bitmap, len); 125537c88763STrond Myklebust bitmap = masked_bitmap; 1256dae100c2SFred Isaman } 125737c88763STrond Myklebust xdr_encode_bitmap4(xdr, bitmap, len); 1258dae100c2SFred Isaman } 1259dae100c2SFred Isaman 1260cf8cdbe5SAndy Adamson static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 12611da177e4SLinus Torvalds { 126237c88763STrond Myklebust encode_getattr(xdr, nfs4_fattr_bitmap, bitmask, 126337c88763STrond Myklebust ARRAY_SIZE(nfs4_fattr_bitmap), hdr); 12641da177e4SLinus Torvalds } 12651da177e4SLinus Torvalds 126688034c3dSAndy Adamson static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, 12671549210fSTrond Myklebust const u32 *open_bitmap, 126888034c3dSAndy Adamson struct compound_hdr *hdr) 126988034c3dSAndy Adamson { 127037c88763STrond Myklebust encode_getattr(xdr, open_bitmap, bitmask, 3, hdr); 127188034c3dSAndy Adamson } 127288034c3dSAndy Adamson 1273cf8cdbe5SAndy Adamson static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 12741da177e4SLinus Torvalds { 127537c88763STrond Myklebust encode_getattr(xdr, nfs4_fsinfo_bitmap, bitmask, 127637c88763STrond Myklebust ARRAY_SIZE(nfs4_fsinfo_bitmap), hdr); 12771da177e4SLinus Torvalds } 12781da177e4SLinus Torvalds 1279cf8cdbe5SAndy Adamson static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 1280830b8e33SManoj Naik { 128137c88763STrond Myklebust encode_getattr(xdr, nfs4_fs_locations_bitmap, bitmask, 128237c88763STrond Myklebust ARRAY_SIZE(nfs4_fs_locations_bitmap), hdr); 1283830b8e33SManoj Naik } 1284830b8e33SManoj Naik 1285cf8cdbe5SAndy Adamson static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr) 12861da177e4SLinus Torvalds { 1287ab19b481STrond Myklebust encode_op_hdr(xdr, OP_GETFH, decode_getfh_maxsz, hdr); 12881da177e4SLinus Torvalds } 12891da177e4SLinus Torvalds 1290cf8cdbe5SAndy Adamson static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 12911da177e4SLinus Torvalds { 1292ab19b481STrond Myklebust encode_op_hdr(xdr, OP_LINK, decode_link_maxsz, hdr); 12936fdfb0bcSTrond Myklebust encode_string(xdr, name->len, name->name); 12941da177e4SLinus Torvalds } 12951da177e4SLinus Torvalds 1296911d1aafSTrond Myklebust static inline int nfs4_lock_type(struct file_lock *fl, int block) 1297911d1aafSTrond Myklebust { 1298f44106e2SJeff Layton if (fl->fl_type == F_RDLCK) 1299911d1aafSTrond Myklebust return block ? NFS4_READW_LT : NFS4_READ_LT; 1300911d1aafSTrond Myklebust return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; 1301911d1aafSTrond Myklebust } 1302911d1aafSTrond Myklebust 1303911d1aafSTrond Myklebust static inline uint64_t nfs4_lock_length(struct file_lock *fl) 1304911d1aafSTrond Myklebust { 1305911d1aafSTrond Myklebust if (fl->fl_end == OFFSET_MAX) 1306911d1aafSTrond Myklebust return ~(uint64_t)0; 1307911d1aafSTrond Myklebust return fl->fl_end - fl->fl_start + 1; 1308911d1aafSTrond Myklebust } 1309911d1aafSTrond Myklebust 1310daccbdedSTrond Myklebust static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner) 1311daccbdedSTrond Myklebust { 1312daccbdedSTrond Myklebust __be32 *p; 1313daccbdedSTrond Myklebust 1314d035c36cSTrond Myklebust p = reserve_space(xdr, 32); 1315daccbdedSTrond Myklebust p = xdr_encode_hyper(p, lowner->clientid); 1316d035c36cSTrond Myklebust *p++ = cpu_to_be32(20); 1317daccbdedSTrond Myklebust p = xdr_encode_opaque_fixed(p, "lock id:", 8); 1318d035c36cSTrond Myklebust *p++ = cpu_to_be32(lowner->s_dev); 1319daccbdedSTrond Myklebust xdr_encode_hyper(p, lowner->id); 1320daccbdedSTrond Myklebust } 1321daccbdedSTrond Myklebust 13221da177e4SLinus Torvalds /* 13231da177e4SLinus Torvalds * opcode,type,reclaim,offset,length,new_lock_owner = 32 13241da177e4SLinus Torvalds * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 13251da177e4SLinus Torvalds */ 1326cf8cdbe5SAndy Adamson static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr) 13271da177e4SLinus Torvalds { 13288687b63aSAl Viro __be32 *p; 13291da177e4SLinus Torvalds 1330475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LOCK, decode_lock_maxsz, hdr); 1331475d4ba0STrond Myklebust p = reserve_space(xdr, 28); 1332e75bc1c8SBenny Halevy *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block)); 1333e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->reclaim); 1334b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 1335b95be5a9SBenny Halevy p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 133634558513SBenny Halevy *p = cpu_to_be32(args->new_lock_owner); 1337911d1aafSTrond Myklebust if (args->new_lock_owner){ 13384ade9821STrond Myklebust encode_nfs4_seqid(xdr, args->open_seqid); 1339425c1d4eSTrond Myklebust encode_nfs4_stateid(xdr, &args->open_stateid); 13404ade9821STrond Myklebust encode_nfs4_seqid(xdr, args->lock_seqid); 1341daccbdedSTrond Myklebust encode_lockowner(xdr, &args->lock_owner); 13421da177e4SLinus Torvalds } 13431da177e4SLinus Torvalds else { 1344425c1d4eSTrond Myklebust encode_nfs4_stateid(xdr, &args->lock_stateid); 13454ade9821STrond Myklebust encode_nfs4_seqid(xdr, args->lock_seqid); 13461da177e4SLinus Torvalds } 13471da177e4SLinus Torvalds } 13481da177e4SLinus Torvalds 1349cf8cdbe5SAndy Adamson static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr) 13501da177e4SLinus Torvalds { 13518687b63aSAl Viro __be32 *p; 13521da177e4SLinus Torvalds 1353475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LOCKT, decode_lockt_maxsz, hdr); 1354475d4ba0STrond Myklebust p = reserve_space(xdr, 20); 1355e75bc1c8SBenny Halevy *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); 1356b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 1357b95be5a9SBenny Halevy p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 1358daccbdedSTrond Myklebust encode_lockowner(xdr, &args->lock_owner); 13591da177e4SLinus Torvalds } 13601da177e4SLinus Torvalds 1361cf8cdbe5SAndy Adamson static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr) 13621da177e4SLinus Torvalds { 13638687b63aSAl Viro __be32 *p; 13641da177e4SLinus Torvalds 1365475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LOCKU, decode_locku_maxsz, hdr); 1366475d4ba0STrond Myklebust encode_uint32(xdr, nfs4_lock_type(args->fl, 0)); 13674ade9821STrond Myklebust encode_nfs4_seqid(xdr, args->seqid); 1368425c1d4eSTrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 1369ea9d23f5STrond Myklebust p = reserve_space(xdr, 16); 1370b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 137134558513SBenny Halevy xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 13721da177e4SLinus Torvalds } 13731da177e4SLinus Torvalds 1374d3c7b7ccSTrond Myklebust static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr) 1375d3c7b7ccSTrond Myklebust { 1376ab19b481STrond Myklebust encode_op_hdr(xdr, OP_RELEASE_LOCKOWNER, decode_release_lockowner_maxsz, hdr); 1377d3c7b7ccSTrond Myklebust encode_lockowner(xdr, lowner); 1378d3c7b7ccSTrond Myklebust } 1379d3c7b7ccSTrond Myklebust 1380cf8cdbe5SAndy Adamson static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 13811da177e4SLinus Torvalds { 1382ab19b481STrond Myklebust encode_op_hdr(xdr, OP_LOOKUP, decode_lookup_maxsz, hdr); 13836fdfb0bcSTrond Myklebust encode_string(xdr, name->len, name->name); 13841da177e4SLinus Torvalds } 13851da177e4SLinus Torvalds 13865b5faaf6SJeff Layton static void encode_lookupp(struct xdr_stream *xdr, struct compound_hdr *hdr) 13875b5faaf6SJeff Layton { 13885b5faaf6SJeff Layton encode_op_hdr(xdr, OP_LOOKUPP, decode_lookupp_maxsz, hdr); 13895b5faaf6SJeff Layton } 13905b5faaf6SJeff Layton 13916ae37339STrond Myklebust static void encode_share_access(struct xdr_stream *xdr, u32 share_access) 13921da177e4SLinus Torvalds { 13938687b63aSAl Viro __be32 *p; 13941da177e4SLinus Torvalds 139513c65ce9SBenny Halevy p = reserve_space(xdr, 8); 13966ae37339STrond Myklebust *p++ = cpu_to_be32(share_access); 139734558513SBenny Halevy *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */ 13981da177e4SLinus Torvalds } 13991da177e4SLinus Torvalds 14001da177e4SLinus Torvalds static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg) 14011da177e4SLinus Torvalds { 14028687b63aSAl Viro __be32 *p; 14031da177e4SLinus Torvalds /* 14041da177e4SLinus Torvalds * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, 14051da177e4SLinus Torvalds * owner 4 = 32 14061da177e4SLinus Torvalds */ 14074ade9821STrond Myklebust encode_nfs4_seqid(xdr, arg->seqid); 14086ae37339STrond Myklebust encode_share_access(xdr, arg->share_access); 140995b72eb0STrond Myklebust p = reserve_space(xdr, 36); 1410b95be5a9SBenny Halevy p = xdr_encode_hyper(p, arg->clientid); 141195b72eb0STrond Myklebust *p++ = cpu_to_be32(24); 141293f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, "open id:", 8); 1413d035c36cSTrond Myklebust *p++ = cpu_to_be32(arg->server->s_dev); 141495b72eb0STrond Myklebust *p++ = cpu_to_be32(arg->id.uniquifier); 141595b72eb0STrond Myklebust xdr_encode_hyper(p, arg->id.create_time); 14161da177e4SLinus Torvalds } 14171da177e4SLinus Torvalds 14181da177e4SLinus Torvalds static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) 14191da177e4SLinus Torvalds { 14208687b63aSAl Viro __be32 *p; 14211da177e4SLinus Torvalds 142213c65ce9SBenny Halevy p = reserve_space(xdr, 4); 1423549b19ccSTrond Myklebust switch(arg->createmode) { 1424549b19ccSTrond Myklebust case NFS4_CREATE_UNCHECKED: 142534558513SBenny Halevy *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); 142628cf22d0STrond Myklebust encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask, 142728cf22d0STrond Myklebust arg->server, arg->server->attr_bitmask); 14281da177e4SLinus Torvalds break; 1429549b19ccSTrond Myklebust case NFS4_CREATE_GUARDED: 14304882ef72SAlexandros Batsakis *p = cpu_to_be32(NFS4_CREATE_GUARDED); 143128cf22d0STrond Myklebust encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask, 143228cf22d0STrond Myklebust arg->server, arg->server->attr_bitmask); 1433549b19ccSTrond Myklebust break; 1434549b19ccSTrond Myklebust case NFS4_CREATE_EXCLUSIVE: 1435549b19ccSTrond Myklebust *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); 1436549b19ccSTrond Myklebust encode_nfs4_verifier(xdr, &arg->u.verifier); 1437549b19ccSTrond Myklebust break; 1438549b19ccSTrond Myklebust case NFS4_CREATE_EXCLUSIVE4_1: 14394882ef72SAlexandros Batsakis *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); 14404882ef72SAlexandros Batsakis encode_nfs4_verifier(xdr, &arg->u.verifier); 144128cf22d0STrond Myklebust encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask, 144228cf22d0STrond Myklebust arg->server, arg->server->exclcreat_bitmask); 14434882ef72SAlexandros Batsakis } 14444882ef72SAlexandros Batsakis } 14451da177e4SLinus Torvalds 14461da177e4SLinus Torvalds static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg) 14471da177e4SLinus Torvalds { 14488687b63aSAl Viro __be32 *p; 14491da177e4SLinus Torvalds 145013c65ce9SBenny Halevy p = reserve_space(xdr, 4); 14511da177e4SLinus Torvalds switch (arg->open_flags & O_CREAT) { 14521da177e4SLinus Torvalds case 0: 145334558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_NOCREATE); 14541da177e4SLinus Torvalds break; 14551da177e4SLinus Torvalds default: 145634558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CREATE); 14571da177e4SLinus Torvalds encode_createmode(xdr, arg); 14581da177e4SLinus Torvalds } 14591da177e4SLinus Torvalds } 14601da177e4SLinus Torvalds 1461bd7bf9d5STrond Myklebust static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type) 14621da177e4SLinus Torvalds { 14638687b63aSAl Viro __be32 *p; 14641da177e4SLinus Torvalds 146513c65ce9SBenny Halevy p = reserve_space(xdr, 4); 14661da177e4SLinus Torvalds switch (delegation_type) { 14671da177e4SLinus Torvalds case 0: 146834558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE); 14691da177e4SLinus Torvalds break; 14701da177e4SLinus Torvalds case FMODE_READ: 147134558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ); 14721da177e4SLinus Torvalds break; 14731da177e4SLinus Torvalds case FMODE_WRITE|FMODE_READ: 147434558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE); 14751da177e4SLinus Torvalds break; 14761da177e4SLinus Torvalds default: 14771da177e4SLinus Torvalds BUG(); 14781da177e4SLinus Torvalds } 14791da177e4SLinus Torvalds } 14801da177e4SLinus Torvalds 14811da177e4SLinus Torvalds static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name) 14821da177e4SLinus Torvalds { 14838687b63aSAl Viro __be32 *p; 14841da177e4SLinus Torvalds 148513c65ce9SBenny Halevy p = reserve_space(xdr, 4); 148634558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL); 14871da177e4SLinus Torvalds encode_string(xdr, name->len, name->name); 14881da177e4SLinus Torvalds } 14891da177e4SLinus Torvalds 1490bd7bf9d5STrond Myklebust static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type) 14911da177e4SLinus Torvalds { 14928687b63aSAl Viro __be32 *p; 14931da177e4SLinus Torvalds 149413c65ce9SBenny Halevy p = reserve_space(xdr, 4); 149534558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS); 14961da177e4SLinus Torvalds encode_delegation_type(xdr, type); 14971da177e4SLinus Torvalds } 14981da177e4SLinus Torvalds 14991da177e4SLinus Torvalds static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid) 15001da177e4SLinus Torvalds { 15018687b63aSAl Viro __be32 *p; 15021da177e4SLinus Torvalds 1503ea9d23f5STrond Myklebust p = reserve_space(xdr, 4); 1504ea9d23f5STrond Myklebust *p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR); 1505ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, stateid); 15061da177e4SLinus Torvalds encode_string(xdr, name->len, name->name); 15071da177e4SLinus Torvalds } 15081da177e4SLinus Torvalds 1509d9fc6619STrond Myklebust static inline void encode_claim_fh(struct xdr_stream *xdr) 1510d9fc6619STrond Myklebust { 1511d9fc6619STrond Myklebust __be32 *p; 1512d9fc6619STrond Myklebust 1513d9fc6619STrond Myklebust p = reserve_space(xdr, 4); 1514d9fc6619STrond Myklebust *p = cpu_to_be32(NFS4_OPEN_CLAIM_FH); 1515d9fc6619STrond Myklebust } 1516d9fc6619STrond Myklebust 1517d9fc6619STrond Myklebust static inline void encode_claim_delegate_cur_fh(struct xdr_stream *xdr, const nfs4_stateid *stateid) 1518d9fc6619STrond Myklebust { 1519d9fc6619STrond Myklebust __be32 *p; 1520d9fc6619STrond Myklebust 1521d9fc6619STrond Myklebust p = reserve_space(xdr, 4); 1522d9fc6619STrond Myklebust *p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEG_CUR_FH); 1523d9fc6619STrond Myklebust encode_nfs4_stateid(xdr, stateid); 1524d9fc6619STrond Myklebust } 1525d9fc6619STrond Myklebust 1526cf8cdbe5SAndy Adamson static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr) 15271da177e4SLinus Torvalds { 1528ab19b481STrond Myklebust encode_op_hdr(xdr, OP_OPEN, decode_open_maxsz, hdr); 15291da177e4SLinus Torvalds encode_openhdr(xdr, arg); 15301da177e4SLinus Torvalds encode_opentype(xdr, arg); 15311da177e4SLinus Torvalds switch (arg->claim) { 15321da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_NULL: 15331da177e4SLinus Torvalds encode_claim_null(xdr, arg->name); 15341da177e4SLinus Torvalds break; 15351da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_PREVIOUS: 15361da177e4SLinus Torvalds encode_claim_previous(xdr, arg->u.delegation_type); 15371da177e4SLinus Torvalds break; 15381da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_DELEGATE_CUR: 15391da177e4SLinus Torvalds encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation); 15401da177e4SLinus Torvalds break; 1541d9fc6619STrond Myklebust case NFS4_OPEN_CLAIM_FH: 1542d9fc6619STrond Myklebust encode_claim_fh(xdr); 1543d9fc6619STrond Myklebust break; 1544d9fc6619STrond Myklebust case NFS4_OPEN_CLAIM_DELEG_CUR_FH: 1545d9fc6619STrond Myklebust encode_claim_delegate_cur_fh(xdr, &arg->u.delegation); 1546d9fc6619STrond Myklebust break; 15471da177e4SLinus Torvalds default: 15481da177e4SLinus Torvalds BUG(); 15491da177e4SLinus Torvalds } 15501da177e4SLinus Torvalds } 15511da177e4SLinus Torvalds 1552cf8cdbe5SAndy Adamson static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr) 15531da177e4SLinus Torvalds { 1554ab19b481STrond Myklebust encode_op_hdr(xdr, OP_OPEN_CONFIRM, decode_open_confirm_maxsz, hdr); 1555ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, arg->stateid); 15564ade9821STrond Myklebust encode_nfs4_seqid(xdr, arg->seqid); 15571da177e4SLinus Torvalds } 15581da177e4SLinus Torvalds 1559cf8cdbe5SAndy Adamson static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) 15601da177e4SLinus Torvalds { 1561ab19b481STrond Myklebust encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr); 1562566fcec6STrond Myklebust encode_nfs4_stateid(xdr, &arg->stateid); 15634ade9821STrond Myklebust encode_nfs4_seqid(xdr, arg->seqid); 15646ae37339STrond Myklebust encode_share_access(xdr, arg->share_access); 15651da177e4SLinus Torvalds } 15661da177e4SLinus Torvalds 1567cf8cdbe5SAndy Adamson static void 1568d017931cSAndy Adamson encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr) 15691da177e4SLinus Torvalds { 1570ab19b481STrond Myklebust encode_op_hdr(xdr, OP_PUTFH, decode_putfh_maxsz, hdr); 15716fdfb0bcSTrond Myklebust encode_string(xdr, fh->size, fh->data); 15721da177e4SLinus Torvalds } 15731da177e4SLinus Torvalds 1574cf8cdbe5SAndy Adamson static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr) 15751da177e4SLinus Torvalds { 1576ab19b481STrond Myklebust encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr); 15771da177e4SLinus Torvalds } 15781da177e4SLinus Torvalds 15793c6b899cSAnna Schumaker static void encode_read(struct xdr_stream *xdr, const struct nfs_pgio_args *args, 15803c6b899cSAnna Schumaker struct compound_hdr *hdr) 15811da177e4SLinus Torvalds { 15828687b63aSAl Viro __be32 *p; 15831da177e4SLinus Torvalds 1584ab19b481STrond Myklebust encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr); 15859b206149STrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 15861da177e4SLinus Torvalds 158713c65ce9SBenny Halevy p = reserve_space(xdr, 12); 1588b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 158934558513SBenny Halevy *p = cpu_to_be32(args->count); 15901da177e4SLinus Torvalds } 15911da177e4SLinus Torvalds 1592cf8cdbe5SAndy Adamson static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) 15931da177e4SLinus Torvalds { 1594aa9c2669SDavid Quigley uint32_t attrs[3] = { 159528331a46STrond Myklebust FATTR4_WORD0_RDATTR_ERROR, 159628331a46STrond Myklebust FATTR4_WORD1_MOUNTED_ON_FILEID, 159728331a46STrond Myklebust }; 15986f7a35bdSTrond Myklebust uint32_t dircount = readdir->count >> 1; 1599cd93710eSChuck Lever __be32 *p, verf[2]; 1600d204c5d2STrond Myklebust uint32_t attrlen = 0; 1601d204c5d2STrond Myklebust unsigned int i; 16021da177e4SLinus Torvalds 160382f2e547SBryan Schumaker if (readdir->plus) { 160482f2e547SBryan Schumaker attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| 160528331a46STrond Myklebust FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID; 160682f2e547SBryan Schumaker attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER| 160782f2e547SBryan Schumaker FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| 160882f2e547SBryan Schumaker FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| 160982f2e547SBryan Schumaker FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; 1610d204c5d2STrond Myklebust attrs[2] |= FATTR4_WORD2_SECURITY_LABEL; 16116f7a35bdSTrond Myklebust dircount >>= 1; 161282f2e547SBryan Schumaker } 161328331a46STrond Myklebust /* Use mounted_on_fileid only if the server supports it */ 161428331a46STrond Myklebust if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) 161528331a46STrond Myklebust attrs[0] |= FATTR4_WORD0_FILEID; 1616d204c5d2STrond Myklebust for (i = 0; i < ARRAY_SIZE(attrs); i++) { 1617d204c5d2STrond Myklebust attrs[i] &= readdir->bitmask[i]; 1618d204c5d2STrond Myklebust if (attrs[i] != 0) 1619d204c5d2STrond Myklebust attrlen = i+1; 1620d204c5d2STrond Myklebust } 16216f7a35bdSTrond Myklebust 1622475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); 1623ff2eb681STrond Myklebust encode_uint64(xdr, readdir->cookie); 1624cd93710eSChuck Lever encode_nfs4_verifier(xdr, &readdir->verifier); 1625d204c5d2STrond Myklebust p = reserve_space(xdr, 12 + (attrlen << 2)); 16266f7a35bdSTrond Myklebust *p++ = cpu_to_be32(dircount); 16276f7a35bdSTrond Myklebust *p++ = cpu_to_be32(readdir->count); 1628d204c5d2STrond Myklebust *p++ = cpu_to_be32(attrlen); 1629d204c5d2STrond Myklebust for (i = 0; i < attrlen; i++) 1630d204c5d2STrond Myklebust *p++ = cpu_to_be32(attrs[i]); 1631cd93710eSChuck Lever memcpy(verf, readdir->verifier.data, sizeof(verf)); 1632aa9c2669SDavid Quigley 1633aa9c2669SDavid Quigley dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n", 163444109241SFred Isaman __func__, 1635eadf4598STrond Myklebust (unsigned long long)readdir->cookie, 1636cd93710eSChuck Lever verf[0], verf[1], 1637eadf4598STrond Myklebust attrs[0] & readdir->bitmask[0], 1638aa9c2669SDavid Quigley attrs[1] & readdir->bitmask[1], 1639aa9c2669SDavid Quigley attrs[2] & readdir->bitmask[2]); 16401da177e4SLinus Torvalds } 16411da177e4SLinus Torvalds 1642cf8cdbe5SAndy Adamson static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) 16431da177e4SLinus Torvalds { 1644ab19b481STrond Myklebust encode_op_hdr(xdr, OP_READLINK, decode_readlink_maxsz, hdr); 16451da177e4SLinus Torvalds } 16461da177e4SLinus Torvalds 1647cf8cdbe5SAndy Adamson static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 16481da177e4SLinus Torvalds { 1649ab19b481STrond Myklebust encode_op_hdr(xdr, OP_REMOVE, decode_remove_maxsz, hdr); 16506fdfb0bcSTrond Myklebust encode_string(xdr, name->len, name->name); 16511da177e4SLinus Torvalds } 16521da177e4SLinus Torvalds 1653cf8cdbe5SAndy Adamson static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr) 16541da177e4SLinus Torvalds { 1655ab19b481STrond Myklebust encode_op_hdr(xdr, OP_RENAME, decode_rename_maxsz, hdr); 1656811652bdSBenny Halevy encode_string(xdr, oldname->len, oldname->name); 1657811652bdSBenny Halevy encode_string(xdr, newname->len, newname->name); 16581da177e4SLinus Torvalds } 16591da177e4SLinus Torvalds 1660bb4dae5eSChuck Lever static void encode_renew(struct xdr_stream *xdr, clientid4 clid, 1661bb4dae5eSChuck Lever struct compound_hdr *hdr) 16621da177e4SLinus Torvalds { 1663475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_RENEW, decode_renew_maxsz, hdr); 1664ff2eb681STrond Myklebust encode_uint64(xdr, clid); 16651da177e4SLinus Torvalds } 16661da177e4SLinus Torvalds 1667cf8cdbe5SAndy Adamson static void 1668d017931cSAndy Adamson encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr) 166956ae19f3STrond Myklebust { 1670ab19b481STrond Myklebust encode_op_hdr(xdr, OP_RESTOREFH, decode_restorefh_maxsz, hdr); 167156ae19f3STrond Myklebust } 167256ae19f3STrond Myklebust 16739f06c719SChuck Lever static void 1674fcc85819SChristoph Hellwig encode_setacl(struct xdr_stream *xdr, const struct nfs_setaclargs *arg, 1675fcc85819SChristoph Hellwig struct compound_hdr *hdr) 167623ec6965SJ. Bruce Fields { 16778687b63aSAl Viro __be32 *p; 167823ec6965SJ. Bruce Fields 1679ab19b481STrond Myklebust encode_op_hdr(xdr, OP_SETATTR, decode_setacl_maxsz, hdr); 1680ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, &zero_stateid); 168113c65ce9SBenny Halevy p = reserve_space(xdr, 2*4); 1682e75bc1c8SBenny Halevy *p++ = cpu_to_be32(1); 168334558513SBenny Halevy *p = cpu_to_be32(FATTR4_WORD0_ACL); 168413c65ce9SBenny Halevy p = reserve_space(xdr, 4); 168534558513SBenny Halevy *p = cpu_to_be32(arg->acl_len); 16868fbcf237SAndreas Gruenbacher xdr_write_pages(xdr, arg->acl_pages, 0, arg->acl_len); 168723ec6965SJ. Bruce Fields } 168823ec6965SJ. Bruce Fields 1689cf8cdbe5SAndy Adamson static void 1690d017931cSAndy Adamson encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr) 16911da177e4SLinus Torvalds { 1692ab19b481STrond Myklebust encode_op_hdr(xdr, OP_SAVEFH, decode_savefh_maxsz, hdr); 16931da177e4SLinus Torvalds } 16941da177e4SLinus Torvalds 1695cf8cdbe5SAndy Adamson static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr) 16961da177e4SLinus Torvalds { 1697ab19b481STrond Myklebust encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); 1698ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, &arg->stateid); 169928cf22d0STrond Myklebust encode_attrs(xdr, arg->iap, arg->label, NULL, server, 170028cf22d0STrond Myklebust server->attr_bitmask); 17011da177e4SLinus Torvalds } 17021da177e4SLinus Torvalds 1703cf8cdbe5SAndy Adamson static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) 17041da177e4SLinus Torvalds { 17058687b63aSAl Viro __be32 *p; 17061da177e4SLinus Torvalds 170770019514STrond Myklebust encode_op_hdr(xdr, OP_SETCLIENTID, decode_setclientid_maxsz, hdr); 1708cd93710eSChuck Lever encode_nfs4_verifier(xdr, setclientid->sc_verifier); 17091da177e4SLinus Torvalds 17103a6bb738SJeff Layton encode_string(xdr, strlen(setclientid->sc_clnt->cl_owner_id), 17113a6bb738SJeff Layton setclientid->sc_clnt->cl_owner_id); 171213c65ce9SBenny Halevy p = reserve_space(xdr, 4); 171334558513SBenny Halevy *p = cpu_to_be32(setclientid->sc_prog); 17141da177e4SLinus Torvalds encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid); 17151da177e4SLinus Torvalds encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr); 171613c65ce9SBenny Halevy p = reserve_space(xdr, 4); 17173a6bb738SJeff Layton *p = cpu_to_be32(setclientid->sc_clnt->cl_cb_ident); 17181da177e4SLinus Torvalds } 17191da177e4SLinus Torvalds 1720bb8b27e5STrond Myklebust static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr) 17211da177e4SLinus Torvalds { 1722475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM, 1723475d4ba0STrond Myklebust decode_setclientid_confirm_maxsz, hdr); 1724ff2eb681STrond Myklebust encode_uint64(xdr, arg->clientid); 1725cd93710eSChuck Lever encode_nfs4_verifier(xdr, &arg->confirm); 17261da177e4SLinus Torvalds } 17271da177e4SLinus Torvalds 17283c6b899cSAnna Schumaker static void encode_write(struct xdr_stream *xdr, const struct nfs_pgio_args *args, 17293c6b899cSAnna Schumaker struct compound_hdr *hdr) 17301da177e4SLinus Torvalds { 17318687b63aSAl Viro __be32 *p; 17321da177e4SLinus Torvalds 1733ab19b481STrond Myklebust encode_op_hdr(xdr, OP_WRITE, decode_write_maxsz, hdr); 17349b206149STrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 17351da177e4SLinus Torvalds 173613c65ce9SBenny Halevy p = reserve_space(xdr, 16); 1737b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 1738e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->stable); 173934558513SBenny Halevy *p = cpu_to_be32(args->count); 17401da177e4SLinus Torvalds 17411da177e4SLinus Torvalds xdr_write_pages(xdr, args->pages, args->pgbase, args->count); 17421da177e4SLinus Torvalds } 17431da177e4SLinus Torvalds 1744cf8cdbe5SAndy Adamson static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr) 17451da177e4SLinus Torvalds { 1746ab19b481STrond Myklebust encode_op_hdr(xdr, OP_DELEGRETURN, decode_delegreturn_maxsz, hdr); 1747ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, stateid); 17481da177e4SLinus Torvalds } 17499b7b9fccSAndy Adamson 17505a5ea0d4SBryan Schumaker static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 17515a5ea0d4SBryan Schumaker { 1752ab19b481STrond Myklebust encode_op_hdr(xdr, OP_SECINFO, decode_secinfo_maxsz, hdr); 17536fdfb0bcSTrond Myklebust encode_string(xdr, name->len, name->name); 17545a5ea0d4SBryan Schumaker } 17555a5ea0d4SBryan Schumaker 175699fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 17579b7b9fccSAndy Adamson /* NFSv4.1 operations */ 17587c44f1aeSWeston Andros Adamson static void encode_bind_conn_to_session(struct xdr_stream *xdr, 1759fcc85819SChristoph Hellwig const struct nfs41_bind_conn_to_session_args *args, 17607c44f1aeSWeston Andros Adamson struct compound_hdr *hdr) 17617c44f1aeSWeston Andros Adamson { 17627c44f1aeSWeston Andros Adamson __be32 *p; 17637c44f1aeSWeston Andros Adamson 17647c44f1aeSWeston Andros Adamson encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION, 17657c44f1aeSWeston Andros Adamson decode_bind_conn_to_session_maxsz, hdr); 176671a097c6STrond Myklebust encode_opaque_fixed(xdr, args->sessionid.data, NFS4_MAX_SESSIONID_LEN); 17677c44f1aeSWeston Andros Adamson p = xdr_reserve_space(xdr, 8); 176871a097c6STrond Myklebust *p++ = cpu_to_be32(args->dir); 176971a097c6STrond Myklebust *p = (args->use_conn_in_rdma_mode) ? cpu_to_be32(1) : cpu_to_be32(0); 17707c44f1aeSWeston Andros Adamson } 17717c44f1aeSWeston Andros Adamson 1772fcc85819SChristoph Hellwig static void encode_op_map(struct xdr_stream *xdr, const struct nfs4_op_map *op_map) 17732031cd1aSWeston Andros Adamson { 17742031cd1aSWeston Andros Adamson unsigned int i; 17752031cd1aSWeston Andros Adamson encode_uint32(xdr, NFS4_OP_MAP_NUM_WORDS); 17762031cd1aSWeston Andros Adamson for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++) 17772031cd1aSWeston Andros Adamson encode_uint32(xdr, op_map->u.words[i]); 17782031cd1aSWeston Andros Adamson } 17792031cd1aSWeston Andros Adamson 178099fe60d0SBenny Halevy static void encode_exchange_id(struct xdr_stream *xdr, 1781fcc85819SChristoph Hellwig const struct nfs41_exchange_id_args *args, 178299fe60d0SBenny Halevy struct compound_hdr *hdr) 178399fe60d0SBenny Halevy { 178499fe60d0SBenny Halevy __be32 *p; 1785d751f748SJim Rees char impl_name[IMPL_NAME_LIMIT]; 1786db8ac8baSWeston Andros Adamson int len = 0; 178799fe60d0SBenny Halevy 178870019514STrond Myklebust encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr); 1789fd40559cSTrond Myklebust encode_nfs4_verifier(xdr, &args->verifier); 179099fe60d0SBenny Halevy 17913a6bb738SJeff Layton encode_string(xdr, strlen(args->client->cl_owner_id), 17923a6bb738SJeff Layton args->client->cl_owner_id); 179399fe60d0SBenny Halevy 17942031cd1aSWeston Andros Adamson encode_uint32(xdr, args->flags); 17952031cd1aSWeston Andros Adamson encode_uint32(xdr, args->state_protect.how); 17962031cd1aSWeston Andros Adamson 17972031cd1aSWeston Andros Adamson switch (args->state_protect.how) { 17982031cd1aSWeston Andros Adamson case SP4_NONE: 17992031cd1aSWeston Andros Adamson break; 18002031cd1aSWeston Andros Adamson case SP4_MACH_CRED: 18012031cd1aSWeston Andros Adamson encode_op_map(xdr, &args->state_protect.enforce); 18022031cd1aSWeston Andros Adamson encode_op_map(xdr, &args->state_protect.allow); 18032031cd1aSWeston Andros Adamson break; 18042031cd1aSWeston Andros Adamson default: 18052031cd1aSWeston Andros Adamson WARN_ON_ONCE(1); 18062031cd1aSWeston Andros Adamson break; 18072031cd1aSWeston Andros Adamson } 1808db8ac8baSWeston Andros Adamson 1809db8ac8baSWeston Andros Adamson if (send_implementation_id && 1810db8ac8baSWeston Andros Adamson sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 && 1811db8ac8baSWeston Andros Adamson sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) 1812d751f748SJim Rees <= sizeof(impl_name) + 1) 1813db8ac8baSWeston Andros Adamson len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s", 1814db8ac8baSWeston Andros Adamson utsname()->sysname, utsname()->release, 1815db8ac8baSWeston Andros Adamson utsname()->version, utsname()->machine); 1816db8ac8baSWeston Andros Adamson 1817db8ac8baSWeston Andros Adamson if (len > 0) { 18182031cd1aSWeston Andros Adamson encode_uint32(xdr, 1); /* implementation id array length=1 */ 1819db8ac8baSWeston Andros Adamson 1820db8ac8baSWeston Andros Adamson encode_string(xdr, 1821db8ac8baSWeston Andros Adamson sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1, 1822db8ac8baSWeston Andros Adamson CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN); 1823db8ac8baSWeston Andros Adamson encode_string(xdr, len, impl_name); 1824db8ac8baSWeston Andros Adamson /* just send zeros for nii_date - the date is in nii_name */ 1825db8ac8baSWeston Andros Adamson p = reserve_space(xdr, 12); 1826db8ac8baSWeston Andros Adamson p = xdr_encode_hyper(p, 0); 1827db8ac8baSWeston Andros Adamson *p = cpu_to_be32(0); 1828db8ac8baSWeston Andros Adamson } else 18292031cd1aSWeston Andros Adamson encode_uint32(xdr, 0); /* implementation id array length=0 */ 183099fe60d0SBenny Halevy } 1831fc931582SAndy Adamson 1832fc931582SAndy Adamson static void encode_create_session(struct xdr_stream *xdr, 1833fcc85819SChristoph Hellwig const struct nfs41_create_session_args *args, 1834fc931582SAndy Adamson struct compound_hdr *hdr) 1835fc931582SAndy Adamson { 1836fc931582SAndy Adamson __be32 *p; 1837fc931582SAndy Adamson struct nfs_client *clp = args->client; 183889f0ff38STrond Myklebust struct rpc_clnt *clnt = clp->cl_rpcclient; 1839f092075dSChuck Lever struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); 18408e0d46e1SMike Sager u32 max_resp_sz_cached; 18418e0d46e1SMike Sager 18428e0d46e1SMike Sager /* 18438e0d46e1SMike Sager * Assumes OPEN is the biggest non-idempotent compound. 18448e0d46e1SMike Sager * 2 is the verifier. 18458e0d46e1SMike Sager */ 184635c036efSJ. Bruce Fields max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + 2) 184735c036efSJ. Bruce Fields * XDR_UNIT + RPC_MAX_AUTH_SIZE; 1848fc931582SAndy Adamson 1849475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr); 185089f0ff38STrond Myklebust p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12); 185179969dd1STrond Myklebust p = xdr_encode_hyper(p, args->clientid); 185279969dd1STrond Myklebust *p++ = cpu_to_be32(args->seqid); /*Sequence id */ 1853e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->flags); /*flags */ 1854fc931582SAndy Adamson 1855fc931582SAndy Adamson /* Fore Channel */ 1856c9c30dd5SBenny Halevy *p++ = cpu_to_be32(0); /* header padding size */ 1857e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ 1858e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ 18598e0d46e1SMike Sager *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ 1860e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */ 1861e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */ 1862e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ 1863fc931582SAndy Adamson 1864fc931582SAndy Adamson /* Back Channel */ 1865c9c30dd5SBenny Halevy *p++ = cpu_to_be32(0); /* header padding size */ 1866e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ 1867e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ 1868e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ 1869e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */ 1870e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */ 1871e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ 1872fc931582SAndy Adamson 1873e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->cb_program); /* cb_program */ 1874e75bc1c8SBenny Halevy *p++ = cpu_to_be32(1); 1875e75bc1c8SBenny Halevy *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ 1876fc931582SAndy Adamson 1877fc931582SAndy Adamson /* authsys_parms rfc1831 */ 18782f86e091SDeepa Dinamani *p++ = cpu_to_be32(ktime_to_ns(nn->boot_time)); /* stamp */ 187989f0ff38STrond Myklebust p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen); 1880e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* UID */ 1881e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* GID */ 188234558513SBenny Halevy *p = cpu_to_be32(0); /* No more gids */ 1883fc931582SAndy Adamson } 18840f3e66c6SAndy Adamson 18850f3e66c6SAndy Adamson static void encode_destroy_session(struct xdr_stream *xdr, 1886fcc85819SChristoph Hellwig const struct nfs4_session *session, 18870f3e66c6SAndy Adamson struct compound_hdr *hdr) 18880f3e66c6SAndy Adamson { 1889475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_DESTROY_SESSION, decode_destroy_session_maxsz, hdr); 1890475d4ba0STrond Myklebust encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); 18910f3e66c6SAndy Adamson } 189218019753SRicardo Labiaga 189366245539STrond Myklebust static void encode_destroy_clientid(struct xdr_stream *xdr, 189466245539STrond Myklebust uint64_t clientid, 189566245539STrond Myklebust struct compound_hdr *hdr) 189666245539STrond Myklebust { 189766245539STrond Myklebust encode_op_hdr(xdr, OP_DESTROY_CLIENTID, decode_destroy_clientid_maxsz, hdr); 189866245539STrond Myklebust encode_uint64(xdr, clientid); 189966245539STrond Myklebust } 190066245539STrond Myklebust 190118019753SRicardo Labiaga static void encode_reclaim_complete(struct xdr_stream *xdr, 1902fcc85819SChristoph Hellwig const struct nfs41_reclaim_complete_args *args, 190318019753SRicardo Labiaga struct compound_hdr *hdr) 190418019753SRicardo Labiaga { 1905475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_RECLAIM_COMPLETE, decode_reclaim_complete_maxsz, hdr); 1906475d4ba0STrond Myklebust encode_uint32(xdr, args->one_fs); 190718019753SRicardo Labiaga } 190899fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 190999fe60d0SBenny Halevy 19109b7b9fccSAndy Adamson static void encode_sequence(struct xdr_stream *xdr, 19119b7b9fccSAndy Adamson const struct nfs4_sequence_args *args, 19129b7b9fccSAndy Adamson struct compound_hdr *hdr) 19139b7b9fccSAndy Adamson { 19149b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 19152b2fa717STrond Myklebust struct nfs4_session *session; 1916fc01cea9SAndy Adamson struct nfs4_slot_table *tp; 19172b2fa717STrond Myklebust struct nfs4_slot *slot = args->sa_slot; 1918fc01cea9SAndy Adamson __be32 *p; 19199b7b9fccSAndy Adamson 19202b2fa717STrond Myklebust tp = slot->table; 19212b2fa717STrond Myklebust session = tp->session; 19223bd2384aSChuck Lever if (!session) 19233bd2384aSChuck Lever return; 1924fc01cea9SAndy Adamson 1925475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr); 1926fc01cea9SAndy Adamson 1927fc01cea9SAndy Adamson /* 1928fc01cea9SAndy Adamson * Sessionid + seqid + slotid + max slotid + cache_this 1929fc01cea9SAndy Adamson */ 1930fc01cea9SAndy Adamson dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d " 1931fc01cea9SAndy Adamson "max_slotid=%d cache_this=%d\n", 1932fc01cea9SAndy Adamson __func__, 1933fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[0], 1934fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[1], 1935fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[2], 1936fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[3], 19372b2fa717STrond Myklebust slot->seq_nr, slot->slot_nr, 1938fc01cea9SAndy Adamson tp->highest_used_slotid, args->sa_cache_this); 1939475d4ba0STrond Myklebust p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16); 194093f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); 1941e75bc1c8SBenny Halevy *p++ = cpu_to_be32(slot->seq_nr); 19422b2fa717STrond Myklebust *p++ = cpu_to_be32(slot->slot_nr); 1943e75bc1c8SBenny Halevy *p++ = cpu_to_be32(tp->highest_used_slotid); 194434558513SBenny Halevy *p = cpu_to_be32(args->sa_cache_this); 19459b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 19469b7b9fccSAndy Adamson } 19479b7b9fccSAndy Adamson 1948b1f69b75SAndy Adamson #ifdef CONFIG_NFS_V4_1 1949b1f69b75SAndy Adamson static void 1950b1f69b75SAndy Adamson encode_getdeviceinfo(struct xdr_stream *xdr, 1951b1f69b75SAndy Adamson const struct nfs4_getdeviceinfo_args *args, 1952b1f69b75SAndy Adamson struct compound_hdr *hdr) 1953b1f69b75SAndy Adamson { 1954b1f69b75SAndy Adamson __be32 *p; 1955b1f69b75SAndy Adamson 1956475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_GETDEVICEINFO, decode_getdeviceinfo_maxsz, hdr); 195784c9dee3SChristoph Hellwig p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 4 + 4); 1958b1f69b75SAndy Adamson p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, 1959b1f69b75SAndy Adamson NFS4_DEVICEID4_SIZE); 1960b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->pdev->layout_type); 1961f1c097beSAndy Adamson *p++ = cpu_to_be32(args->pdev->maxcount); /* gdia_maxcount */ 196284c9dee3SChristoph Hellwig 196384c9dee3SChristoph Hellwig p = reserve_space(xdr, 4 + 4); 196484c9dee3SChristoph Hellwig *p++ = cpu_to_be32(1); /* bitmap length */ 19654e590803STrond Myklebust *p++ = cpu_to_be32(args->notify_types); 1966b1f69b75SAndy Adamson } 1967b1f69b75SAndy Adamson 1968b1f69b75SAndy Adamson static void 1969b1f69b75SAndy Adamson encode_layoutget(struct xdr_stream *xdr, 1970b1f69b75SAndy Adamson const struct nfs4_layoutget_args *args, 1971b1f69b75SAndy Adamson struct compound_hdr *hdr) 1972b1f69b75SAndy Adamson { 1973b1f69b75SAndy Adamson __be32 *p; 1974b1f69b75SAndy Adamson 1975475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LAYOUTGET, decode_layoutget_maxsz, hdr); 1976475d4ba0STrond Myklebust p = reserve_space(xdr, 36); 1977b1f69b75SAndy Adamson *p++ = cpu_to_be32(0); /* Signal layout available */ 1978b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->type); 1979b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->range.iomode); 1980b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->range.offset); 1981b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->range.length); 1982b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->minlength); 1983ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 1984475d4ba0STrond Myklebust encode_uint32(xdr, args->maxcount); 1985b1f69b75SAndy Adamson 1986b1f69b75SAndy Adamson dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", 1987b1f69b75SAndy Adamson __func__, 1988b1f69b75SAndy Adamson args->type, 1989b1f69b75SAndy Adamson args->range.iomode, 1990b1f69b75SAndy Adamson (unsigned long)args->range.offset, 1991b1f69b75SAndy Adamson (unsigned long)args->range.length, 1992b1f69b75SAndy Adamson args->maxcount); 1993b1f69b75SAndy Adamson } 1994863a3c6cSAndy Adamson 1995863a3c6cSAndy Adamson static int 1996863a3c6cSAndy Adamson encode_layoutcommit(struct xdr_stream *xdr, 1997ac7db726SBenny Halevy struct inode *inode, 1998fcc85819SChristoph Hellwig const struct nfs4_layoutcommit_args *args, 1999863a3c6cSAndy Adamson struct compound_hdr *hdr) 2000863a3c6cSAndy Adamson { 2001863a3c6cSAndy Adamson __be32 *p; 2002863a3c6cSAndy Adamson 2003863a3c6cSAndy Adamson dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, 2004863a3c6cSAndy Adamson NFS_SERVER(args->inode)->pnfs_curr_ld->id); 2005863a3c6cSAndy Adamson 2006475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LAYOUTCOMMIT, decode_layoutcommit_maxsz, hdr); 2007475d4ba0STrond Myklebust p = reserve_space(xdr, 20); 2008863a3c6cSAndy Adamson /* Only whole file layouts */ 2009863a3c6cSAndy Adamson p = xdr_encode_hyper(p, 0); /* offset */ 20103557c6c3SPeng Tao p = xdr_encode_hyper(p, args->lastbytewritten + 1); /* length */ 2011ea9d23f5STrond Myklebust *p = cpu_to_be32(0); /* reclaim */ 2012ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 20132e18d4d8STrond Myklebust if (args->lastbytewritten != U64_MAX) { 2014ea9d23f5STrond Myklebust p = reserve_space(xdr, 20); 2015863a3c6cSAndy Adamson *p++ = cpu_to_be32(1); /* newoffset = TRUE */ 2016863a3c6cSAndy Adamson p = xdr_encode_hyper(p, args->lastbytewritten); 20172e18d4d8STrond Myklebust } else { 20182e18d4d8STrond Myklebust p = reserve_space(xdr, 12); 20192e18d4d8STrond Myklebust *p++ = cpu_to_be32(0); /* newoffset = FALSE */ 20202e18d4d8STrond Myklebust } 2021863a3c6cSAndy Adamson *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ 2022863a3c6cSAndy Adamson *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ 2023ac7db726SBenny Halevy 20245f919c9fSChristoph Hellwig encode_uint32(xdr, args->layoutupdate_len); 202573504740STrond Myklebust if (args->layoutupdate_pages) 20265f919c9fSChristoph Hellwig xdr_write_pages(xdr, args->layoutupdate_pages, 0, 20275f919c9fSChristoph Hellwig args->layoutupdate_len); 2028863a3c6cSAndy Adamson 2029863a3c6cSAndy Adamson return 0; 2030863a3c6cSAndy Adamson } 2031cbe82603SBenny Halevy 2032cbe82603SBenny Halevy static void 2033cbe82603SBenny Halevy encode_layoutreturn(struct xdr_stream *xdr, 2034cbe82603SBenny Halevy const struct nfs4_layoutreturn_args *args, 2035cbe82603SBenny Halevy struct compound_hdr *hdr) 2036cbe82603SBenny Halevy { 2037cbe82603SBenny Halevy __be32 *p; 2038cbe82603SBenny Halevy 2039475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LAYOUTRETURN, decode_layoutreturn_maxsz, hdr); 2040475d4ba0STrond Myklebust p = reserve_space(xdr, 16); 2041cbe82603SBenny Halevy *p++ = cpu_to_be32(0); /* reclaim. always 0 for now */ 2042cbe82603SBenny Halevy *p++ = cpu_to_be32(args->layout_type); 204315eb67c1SPeng Tao *p++ = cpu_to_be32(args->range.iomode); 2044cbe82603SBenny Halevy *p = cpu_to_be32(RETURN_FILE); 2045ea9d23f5STrond Myklebust p = reserve_space(xdr, 16); 204615eb67c1SPeng Tao p = xdr_encode_hyper(p, args->range.offset); 204715eb67c1SPeng Tao p = xdr_encode_hyper(p, args->range.length); 2048cbe82603SBenny Halevy spin_lock(&args->inode->i_lock); 2049ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 2050cbe82603SBenny Halevy spin_unlock(&args->inode->i_lock); 20514d796d75STrond Myklebust if (args->ld_private->ops && args->ld_private->ops->encode) 20524d796d75STrond Myklebust args->ld_private->ops->encode(xdr, args, args->ld_private); 205394e5c571STrond Myklebust else 2054475d4ba0STrond Myklebust encode_uint32(xdr, 0); 2055cbe82603SBenny Halevy } 2056fca78d6dSBryan Schumaker 2057fca78d6dSBryan Schumaker static int 2058fca78d6dSBryan Schumaker encode_secinfo_no_name(struct xdr_stream *xdr, 2059fca78d6dSBryan Schumaker const struct nfs41_secinfo_no_name_args *args, 2060fca78d6dSBryan Schumaker struct compound_hdr *hdr) 2061fca78d6dSBryan Schumaker { 2062475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_SECINFO_NO_NAME, decode_secinfo_no_name_maxsz, hdr); 2063475d4ba0STrond Myklebust encode_uint32(xdr, args->style); 2064fca78d6dSBryan Schumaker return 0; 2065fca78d6dSBryan Schumaker } 20667d974794SBryan Schumaker 20677d974794SBryan Schumaker static void encode_test_stateid(struct xdr_stream *xdr, 2068fcc85819SChristoph Hellwig const struct nfs41_test_stateid_args *args, 20697d974794SBryan Schumaker struct compound_hdr *hdr) 20707d974794SBryan Schumaker { 2071475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_TEST_STATEID, decode_test_stateid_maxsz, hdr); 2072475d4ba0STrond Myklebust encode_uint32(xdr, 1); 2073ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, args->stateid); 20747d974794SBryan Schumaker } 20759aeda35fSBryan Schumaker 20769aeda35fSBryan Schumaker static void encode_free_stateid(struct xdr_stream *xdr, 2077fcc85819SChristoph Hellwig const struct nfs41_free_stateid_args *args, 20789aeda35fSBryan Schumaker struct compound_hdr *hdr) 20799aeda35fSBryan Schumaker { 2080ab19b481STrond Myklebust encode_op_hdr(xdr, OP_FREE_STATEID, decode_free_stateid_maxsz, hdr); 20817c1d5faeSTrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 20829aeda35fSBryan Schumaker } 2083cf805165STrond Myklebust #else 2084cf805165STrond Myklebust static inline void 2085cf805165STrond Myklebust encode_layoutreturn(struct xdr_stream *xdr, 2086cf805165STrond Myklebust const struct nfs4_layoutreturn_args *args, 2087cf805165STrond Myklebust struct compound_hdr *hdr) 2088cf805165STrond Myklebust { 2089cf805165STrond Myklebust } 209056f487f8SFred Isaman 209156f487f8SFred Isaman static void 209256f487f8SFred Isaman encode_layoutget(struct xdr_stream *xdr, 209356f487f8SFred Isaman const struct nfs4_layoutget_args *args, 209456f487f8SFred Isaman struct compound_hdr *hdr) 209556f487f8SFred Isaman { 209656f487f8SFred Isaman } 2097b1f69b75SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 2098b1f69b75SAndy Adamson 20991da177e4SLinus Torvalds /* 21001da177e4SLinus Torvalds * END OF "GENERIC" ENCODE ROUTINES. 21011da177e4SLinus Torvalds */ 21021da177e4SLinus Torvalds 210366cc0429SBenny Halevy static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) 210466cc0429SBenny Halevy { 210566cc0429SBenny Halevy #if defined(CONFIG_NFS_V4_1) 21063bd2384aSChuck Lever struct nfs4_session *session = args->sa_slot->table->session; 21073bd2384aSChuck Lever if (session) 21083bd2384aSChuck Lever return session->clp->cl_mvops->minor_version; 210966cc0429SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 211066cc0429SBenny Halevy return 0; 211166cc0429SBenny Halevy } 211266cc0429SBenny Halevy 21131da177e4SLinus Torvalds /* 21141da177e4SLinus Torvalds * Encode an ACCESS request 21151da177e4SLinus Torvalds */ 21169f06c719SChuck Lever static void nfs4_xdr_enc_access(struct rpc_rqst *req, struct xdr_stream *xdr, 2117fcc85819SChristoph Hellwig const void *data) 21181da177e4SLinus Torvalds { 2119fcc85819SChristoph Hellwig const struct nfs4_accessargs *args = data; 21201da177e4SLinus Torvalds struct compound_hdr hdr = { 212166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21221da177e4SLinus Torvalds }; 21231da177e4SLinus Torvalds 21249f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21259f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21269f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21279f06c719SChuck Lever encode_access(xdr, args->access, &hdr); 21288bcbe7d9STrond Myklebust if (args->bitmask) 21299f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2130d017931cSAndy Adamson encode_nops(&hdr); 21311da177e4SLinus Torvalds } 21321da177e4SLinus Torvalds 21331da177e4SLinus Torvalds /* 21341da177e4SLinus Torvalds * Encode LOOKUP request 21351da177e4SLinus Torvalds */ 21369f06c719SChuck Lever static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr, 2137fcc85819SChristoph Hellwig const void *data) 21381da177e4SLinus Torvalds { 2139fcc85819SChristoph Hellwig const struct nfs4_lookup_arg *args = data; 21401da177e4SLinus Torvalds struct compound_hdr hdr = { 214166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21421da177e4SLinus Torvalds }; 21431da177e4SLinus Torvalds 21449f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21459f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21469f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 21479f06c719SChuck Lever encode_lookup(xdr, args->name, &hdr); 21489f06c719SChuck Lever encode_getfh(xdr, &hdr); 21499f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2150d017931cSAndy Adamson encode_nops(&hdr); 21511da177e4SLinus Torvalds } 21521da177e4SLinus Torvalds 21531da177e4SLinus Torvalds /* 21545b5faaf6SJeff Layton * Encode LOOKUPP request 21555b5faaf6SJeff Layton */ 21565b5faaf6SJeff Layton static void nfs4_xdr_enc_lookupp(struct rpc_rqst *req, struct xdr_stream *xdr, 21575b5faaf6SJeff Layton const void *data) 21585b5faaf6SJeff Layton { 21595b5faaf6SJeff Layton const struct nfs4_lookupp_arg *args = data; 21605b5faaf6SJeff Layton struct compound_hdr hdr = { 21615b5faaf6SJeff Layton .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21625b5faaf6SJeff Layton }; 21635b5faaf6SJeff Layton 21645b5faaf6SJeff Layton encode_compound_hdr(xdr, req, &hdr); 21655b5faaf6SJeff Layton encode_sequence(xdr, &args->seq_args, &hdr); 21665b5faaf6SJeff Layton encode_putfh(xdr, args->fh, &hdr); 21675b5faaf6SJeff Layton encode_lookupp(xdr, &hdr); 21685b5faaf6SJeff Layton encode_getfh(xdr, &hdr); 21695b5faaf6SJeff Layton encode_getfattr(xdr, args->bitmask, &hdr); 21705b5faaf6SJeff Layton encode_nops(&hdr); 21715b5faaf6SJeff Layton } 21725b5faaf6SJeff Layton 21735b5faaf6SJeff Layton /* 21741da177e4SLinus Torvalds * Encode LOOKUP_ROOT request 21751da177e4SLinus Torvalds */ 21769f06c719SChuck Lever static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, 21779f06c719SChuck Lever struct xdr_stream *xdr, 2178fcc85819SChristoph Hellwig const void *data) 21791da177e4SLinus Torvalds { 2180fcc85819SChristoph Hellwig const struct nfs4_lookup_root_arg *args = data; 21811da177e4SLinus Torvalds struct compound_hdr hdr = { 218266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21831da177e4SLinus Torvalds }; 21841da177e4SLinus Torvalds 21859f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21869f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21879f06c719SChuck Lever encode_putrootfh(xdr, &hdr); 21889f06c719SChuck Lever encode_getfh(xdr, &hdr); 21899f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2190d017931cSAndy Adamson encode_nops(&hdr); 21911da177e4SLinus Torvalds } 21921da177e4SLinus Torvalds 21931da177e4SLinus Torvalds /* 21941da177e4SLinus Torvalds * Encode REMOVE request 21951da177e4SLinus Torvalds */ 21969f06c719SChuck Lever static void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr, 2197fcc85819SChristoph Hellwig const void *data) 21981da177e4SLinus Torvalds { 2199fcc85819SChristoph Hellwig const struct nfs_removeargs *args = data; 22001da177e4SLinus Torvalds struct compound_hdr hdr = { 220166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22021da177e4SLinus Torvalds }; 22031da177e4SLinus Torvalds 22049f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22059f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22069f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22079f06c719SChuck Lever encode_remove(xdr, &args->name, &hdr); 2208d017931cSAndy Adamson encode_nops(&hdr); 22091da177e4SLinus Torvalds } 22101da177e4SLinus Torvalds 22111da177e4SLinus Torvalds /* 22121da177e4SLinus Torvalds * Encode RENAME request 22131da177e4SLinus Torvalds */ 22149f06c719SChuck Lever static void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr, 2215fcc85819SChristoph Hellwig const void *data) 22161da177e4SLinus Torvalds { 2217fcc85819SChristoph Hellwig const struct nfs_renameargs *args = data; 22181da177e4SLinus Torvalds struct compound_hdr hdr = { 221966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22201da177e4SLinus Torvalds }; 22211da177e4SLinus Torvalds 22229f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22239f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22249f06c719SChuck Lever encode_putfh(xdr, args->old_dir, &hdr); 22259f06c719SChuck Lever encode_savefh(xdr, &hdr); 22269f06c719SChuck Lever encode_putfh(xdr, args->new_dir, &hdr); 22279f06c719SChuck Lever encode_rename(xdr, args->old_name, args->new_name, &hdr); 2228d017931cSAndy Adamson encode_nops(&hdr); 22291da177e4SLinus Torvalds } 22301da177e4SLinus Torvalds 22311da177e4SLinus Torvalds /* 22321da177e4SLinus Torvalds * Encode LINK request 22331da177e4SLinus Torvalds */ 22349f06c719SChuck Lever static void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr, 2235fcc85819SChristoph Hellwig const void *data) 22361da177e4SLinus Torvalds { 2237fcc85819SChristoph Hellwig const struct nfs4_link_arg *args = data; 22381da177e4SLinus Torvalds struct compound_hdr hdr = { 223966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22401da177e4SLinus Torvalds }; 22411da177e4SLinus Torvalds 22429f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22439f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22449f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22459f06c719SChuck Lever encode_savefh(xdr, &hdr); 22469f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 22479f06c719SChuck Lever encode_link(xdr, args->name, &hdr); 22489f06c719SChuck Lever encode_restorefh(xdr, &hdr); 22499f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2250d017931cSAndy Adamson encode_nops(&hdr); 22511da177e4SLinus Torvalds } 22521da177e4SLinus Torvalds 22531da177e4SLinus Torvalds /* 22541da177e4SLinus Torvalds * Encode CREATE request 22551da177e4SLinus Torvalds */ 22569f06c719SChuck Lever static void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr, 2257fcc85819SChristoph Hellwig const void *data) 22581da177e4SLinus Torvalds { 2259fcc85819SChristoph Hellwig const struct nfs4_create_arg *args = data; 22601da177e4SLinus Torvalds struct compound_hdr hdr = { 226166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22621da177e4SLinus Torvalds }; 22631da177e4SLinus Torvalds 22649f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22659f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22669f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 22679f06c719SChuck Lever encode_create(xdr, args, &hdr); 22689f06c719SChuck Lever encode_getfh(xdr, &hdr); 22699f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2270d017931cSAndy Adamson encode_nops(&hdr); 22711da177e4SLinus Torvalds } 22721da177e4SLinus Torvalds 22731da177e4SLinus Torvalds /* 22741da177e4SLinus Torvalds * Encode SYMLINK request 22751da177e4SLinus Torvalds */ 22769f06c719SChuck Lever static void nfs4_xdr_enc_symlink(struct rpc_rqst *req, struct xdr_stream *xdr, 2277fcc85819SChristoph Hellwig const void *data) 22781da177e4SLinus Torvalds { 2279fcc85819SChristoph Hellwig const struct nfs4_create_arg *args = data; 2280fcc85819SChristoph Hellwig 22819f06c719SChuck Lever nfs4_xdr_enc_create(req, xdr, args); 22821da177e4SLinus Torvalds } 22831da177e4SLinus Torvalds 22841da177e4SLinus Torvalds /* 22851da177e4SLinus Torvalds * Encode GETATTR request 22861da177e4SLinus Torvalds */ 22879f06c719SChuck Lever static void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr, 2288fcc85819SChristoph Hellwig const void *data) 22891da177e4SLinus Torvalds { 2290fcc85819SChristoph Hellwig const struct nfs4_getattr_arg *args = data; 22911da177e4SLinus Torvalds struct compound_hdr hdr = { 229266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22931da177e4SLinus Torvalds }; 22941da177e4SLinus Torvalds 22959f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22969f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22979f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22989f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2299d017931cSAndy Adamson encode_nops(&hdr); 23001da177e4SLinus Torvalds } 23011da177e4SLinus Torvalds 23021da177e4SLinus Torvalds /* 23031da177e4SLinus Torvalds * Encode a CLOSE request 23041da177e4SLinus Torvalds */ 23059f06c719SChuck Lever static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr, 2306fcc85819SChristoph Hellwig const void *data) 23071da177e4SLinus Torvalds { 2308fcc85819SChristoph Hellwig const struct nfs_closeargs *args = data; 23091da177e4SLinus Torvalds struct compound_hdr hdr = { 231066cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23111da177e4SLinus Torvalds }; 23121da177e4SLinus Torvalds 23139f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23149f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23159f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 2316cf805165STrond Myklebust if (args->lr_args) 2317cf805165STrond Myklebust encode_layoutreturn(xdr, args->lr_args, &hdr); 23183ecefc92STrond Myklebust if (args->bitmask != NULL) 23199f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2320d8d84983STrond Myklebust encode_close(xdr, args, &hdr); 2321d017931cSAndy Adamson encode_nops(&hdr); 23221da177e4SLinus Torvalds } 23231da177e4SLinus Torvalds 23241da177e4SLinus Torvalds /* 23251da177e4SLinus Torvalds * Encode an OPEN request 23261da177e4SLinus Torvalds */ 23279f06c719SChuck Lever static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, 2328fcc85819SChristoph Hellwig const void *data) 23291da177e4SLinus Torvalds { 2330fcc85819SChristoph Hellwig const struct nfs_openargs *args = data; 23311da177e4SLinus Torvalds struct compound_hdr hdr = { 233266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23331da177e4SLinus Torvalds }; 23341da177e4SLinus Torvalds 23359f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23369f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23379f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23389f06c719SChuck Lever encode_open(xdr, args, &hdr); 23399f06c719SChuck Lever encode_getfh(xdr, &hdr); 2340ae2bb032SWeston Andros Adamson if (args->access) 23416168f62cSWeston Andros Adamson encode_access(xdr, args->access, &hdr); 23421549210fSTrond Myklebust encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); 234356f487f8SFred Isaman if (args->lg_args) { 234456f487f8SFred Isaman encode_layoutget(xdr, args->lg_args, &hdr); 2345cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0, 2346cf500bacSChuck Lever args->lg_args->layout.pglen, 23479ed5af26STrond Myklebust hdr.replen - pagepad_maxsz); 234856f487f8SFred Isaman } 2349d017931cSAndy Adamson encode_nops(&hdr); 23501da177e4SLinus Torvalds } 23511da177e4SLinus Torvalds 23521da177e4SLinus Torvalds /* 23531da177e4SLinus Torvalds * Encode an OPEN_CONFIRM request 23541da177e4SLinus Torvalds */ 23559f06c719SChuck Lever static void nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, 23569f06c719SChuck Lever struct xdr_stream *xdr, 2357fcc85819SChristoph Hellwig const void *data) 23581da177e4SLinus Torvalds { 2359fcc85819SChristoph Hellwig const struct nfs_open_confirmargs *args = data; 23601da177e4SLinus Torvalds struct compound_hdr hdr = { 2361d017931cSAndy Adamson .nops = 0, 23621da177e4SLinus Torvalds }; 23631da177e4SLinus Torvalds 23649f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23659f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23669f06c719SChuck Lever encode_open_confirm(xdr, args, &hdr); 2367d017931cSAndy Adamson encode_nops(&hdr); 23681da177e4SLinus Torvalds } 23691da177e4SLinus Torvalds 23701da177e4SLinus Torvalds /* 23711da177e4SLinus Torvalds * Encode an OPEN request with no attributes. 23721da177e4SLinus Torvalds */ 23739f06c719SChuck Lever static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, 23749f06c719SChuck Lever struct xdr_stream *xdr, 2375fcc85819SChristoph Hellwig const void *data) 23761da177e4SLinus Torvalds { 2377fcc85819SChristoph Hellwig const struct nfs_openargs *args = data; 23781da177e4SLinus Torvalds struct compound_hdr hdr = { 237966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23801da177e4SLinus Torvalds }; 23811da177e4SLinus Torvalds 23829f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23839f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23849f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23859f06c719SChuck Lever encode_open(xdr, args, &hdr); 2386ae2bb032SWeston Andros Adamson if (args->access) 23876168f62cSWeston Andros Adamson encode_access(xdr, args->access, &hdr); 2388e23008ecSAndy Adamson encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); 238956f487f8SFred Isaman if (args->lg_args) { 239056f487f8SFred Isaman encode_layoutget(xdr, args->lg_args, &hdr); 2391cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0, 2392cf500bacSChuck Lever args->lg_args->layout.pglen, 23939ed5af26STrond Myklebust hdr.replen - pagepad_maxsz); 239456f487f8SFred Isaman } 2395d017931cSAndy Adamson encode_nops(&hdr); 23961da177e4SLinus Torvalds } 23971da177e4SLinus Torvalds 23981da177e4SLinus Torvalds /* 23991da177e4SLinus Torvalds * Encode an OPEN_DOWNGRADE request 24001da177e4SLinus Torvalds */ 24019f06c719SChuck Lever static void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, 24029f06c719SChuck Lever struct xdr_stream *xdr, 2403fcc85819SChristoph Hellwig const void *data) 24041da177e4SLinus Torvalds { 2405fcc85819SChristoph Hellwig const struct nfs_closeargs *args = data; 24061da177e4SLinus Torvalds struct compound_hdr hdr = { 240766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24081da177e4SLinus Torvalds }; 24091da177e4SLinus Torvalds 24109f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24119f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24129f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 2413b6808145STrond Myklebust if (args->lr_args) 2414b6808145STrond Myklebust encode_layoutreturn(xdr, args->lr_args, &hdr); 24159f06c719SChuck Lever encode_open_downgrade(xdr, args, &hdr); 2416d017931cSAndy Adamson encode_nops(&hdr); 24171da177e4SLinus Torvalds } 24181da177e4SLinus Torvalds 24191da177e4SLinus Torvalds /* 24201da177e4SLinus Torvalds * Encode a LOCK request 24211da177e4SLinus Torvalds */ 24229f06c719SChuck Lever static void nfs4_xdr_enc_lock(struct rpc_rqst *req, struct xdr_stream *xdr, 2423fcc85819SChristoph Hellwig const void *data) 24241da177e4SLinus Torvalds { 2425fcc85819SChristoph Hellwig const struct nfs_lock_args *args = data; 24261da177e4SLinus Torvalds struct compound_hdr hdr = { 242766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24281da177e4SLinus Torvalds }; 24291da177e4SLinus Torvalds 24309f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24319f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24329f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24339f06c719SChuck Lever encode_lock(xdr, args, &hdr); 2434d017931cSAndy Adamson encode_nops(&hdr); 24351da177e4SLinus Torvalds } 24361da177e4SLinus Torvalds 24371da177e4SLinus Torvalds /* 24381da177e4SLinus Torvalds * Encode a LOCKT request 24391da177e4SLinus Torvalds */ 24409f06c719SChuck Lever static void nfs4_xdr_enc_lockt(struct rpc_rqst *req, struct xdr_stream *xdr, 2441fcc85819SChristoph Hellwig const void *data) 24421da177e4SLinus Torvalds { 2443fcc85819SChristoph Hellwig const struct nfs_lockt_args *args = data; 24441da177e4SLinus Torvalds struct compound_hdr hdr = { 244566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24461da177e4SLinus Torvalds }; 24471da177e4SLinus Torvalds 24489f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24499f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24509f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24519f06c719SChuck Lever encode_lockt(xdr, args, &hdr); 2452d017931cSAndy Adamson encode_nops(&hdr); 24531da177e4SLinus Torvalds } 24541da177e4SLinus Torvalds 24551da177e4SLinus Torvalds /* 24561da177e4SLinus Torvalds * Encode a LOCKU request 24571da177e4SLinus Torvalds */ 24589f06c719SChuck Lever static void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr, 2459fcc85819SChristoph Hellwig const void *data) 24601da177e4SLinus Torvalds { 2461fcc85819SChristoph Hellwig const struct nfs_locku_args *args = data; 24621da177e4SLinus Torvalds struct compound_hdr hdr = { 246366cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24641da177e4SLinus Torvalds }; 24651da177e4SLinus Torvalds 24669f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24679f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24689f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24699f06c719SChuck Lever encode_locku(xdr, args, &hdr); 2470d017931cSAndy Adamson encode_nops(&hdr); 24711da177e4SLinus Torvalds } 24721da177e4SLinus Torvalds 24739f06c719SChuck Lever static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, 24749f06c719SChuck Lever struct xdr_stream *xdr, 2475fcc85819SChristoph Hellwig const void *data) 2476d3c7b7ccSTrond Myklebust { 2477fcc85819SChristoph Hellwig const struct nfs_release_lockowner_args *args = data; 2478d3c7b7ccSTrond Myklebust struct compound_hdr hdr = { 2479d3c7b7ccSTrond Myklebust .minorversion = 0, 2480d3c7b7ccSTrond Myklebust }; 2481d3c7b7ccSTrond Myklebust 24829f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24839f06c719SChuck Lever encode_release_lockowner(xdr, &args->lock_owner, &hdr); 2484d3c7b7ccSTrond Myklebust encode_nops(&hdr); 2485d3c7b7ccSTrond Myklebust } 2486d3c7b7ccSTrond Myklebust 24871da177e4SLinus Torvalds /* 24881da177e4SLinus Torvalds * Encode a READLINK request 24891da177e4SLinus Torvalds */ 24909f06c719SChuck Lever static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr, 2491fcc85819SChristoph Hellwig const void *data) 24921da177e4SLinus Torvalds { 2493fcc85819SChristoph Hellwig const struct nfs4_readlink *args = data; 24941da177e4SLinus Torvalds struct compound_hdr hdr = { 249566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24961da177e4SLinus Torvalds }; 24971da177e4SLinus Torvalds 24989f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24999f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25009f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 25019f06c719SChuck Lever encode_readlink(xdr, args, req, &hdr); 2502e3a535e1STrond Myklebust 2503cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->pages, args->pgbase, 25049ed5af26STrond Myklebust args->pglen, hdr.replen - pagepad_maxsz); 2505d017931cSAndy Adamson encode_nops(&hdr); 25061da177e4SLinus Torvalds } 25071da177e4SLinus Torvalds 25081da177e4SLinus Torvalds /* 25091da177e4SLinus Torvalds * Encode a READDIR request 25101da177e4SLinus Torvalds */ 25119f06c719SChuck Lever static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr, 2512fcc85819SChristoph Hellwig const void *data) 25131da177e4SLinus Torvalds { 2514fcc85819SChristoph Hellwig const struct nfs4_readdir_arg *args = data; 25151da177e4SLinus Torvalds struct compound_hdr hdr = { 251666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 25171da177e4SLinus Torvalds }; 25181da177e4SLinus Torvalds 25199f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25209f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25219f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 25229f06c719SChuck Lever encode_readdir(xdr, args, req, &hdr); 2523d6ac02dfSTrond Myklebust 2524cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->pages, args->pgbase, 25259ed5af26STrond Myklebust args->count, hdr.replen - pagepad_maxsz); 2526d017931cSAndy Adamson encode_nops(&hdr); 25271da177e4SLinus Torvalds } 25281da177e4SLinus Torvalds 25291da177e4SLinus Torvalds /* 25301da177e4SLinus Torvalds * Encode a READ request 25311da177e4SLinus Torvalds */ 25329f06c719SChuck Lever static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr, 2533fcc85819SChristoph Hellwig const void *data) 25341da177e4SLinus Torvalds { 2535fcc85819SChristoph Hellwig const struct nfs_pgio_args *args = data; 25361da177e4SLinus Torvalds struct compound_hdr hdr = { 253766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 25381da177e4SLinus Torvalds }; 25391da177e4SLinus Torvalds 25409f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25419f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25429f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 25439f06c719SChuck Lever encode_read(xdr, args, &hdr); 25441da177e4SLinus Torvalds 2545cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->pages, args->pgbase, 25469ed5af26STrond Myklebust args->count, hdr.replen - pagepad_maxsz); 25474f22ccc3S\"Talpey, Thomas\ req->rq_rcv_buf.flags |= XDRBUF_READ; 2548d017931cSAndy Adamson encode_nops(&hdr); 25491da177e4SLinus Torvalds } 25501da177e4SLinus Torvalds 25511da177e4SLinus Torvalds /* 25521da177e4SLinus Torvalds * Encode an SETATTR request 25531da177e4SLinus Torvalds */ 25549f06c719SChuck Lever static void nfs4_xdr_enc_setattr(struct rpc_rqst *req, struct xdr_stream *xdr, 2555fcc85819SChristoph Hellwig const void *data) 25561da177e4SLinus Torvalds { 2557fcc85819SChristoph Hellwig const struct nfs_setattrargs *args = data; 25581da177e4SLinus Torvalds struct compound_hdr hdr = { 255966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 25601da177e4SLinus Torvalds }; 25611da177e4SLinus Torvalds 25629f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25639f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25649f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 25659f06c719SChuck Lever encode_setattr(xdr, args, args->server, &hdr); 25669f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2567d017931cSAndy Adamson encode_nops(&hdr); 25681da177e4SLinus Torvalds } 25691da177e4SLinus Torvalds 25701da177e4SLinus Torvalds /* 2571029d105eSJ. Bruce Fields * Encode a GETACL request 2572029d105eSJ. Bruce Fields */ 25739f06c719SChuck Lever static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, 2574fcc85819SChristoph Hellwig const void *data) 2575029d105eSJ. Bruce Fields { 2576fcc85819SChristoph Hellwig const struct nfs_getaclargs *args = data; 2577029d105eSJ. Bruce Fields struct compound_hdr hdr = { 257866cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2579029d105eSJ. Bruce Fields }; 258037c88763STrond Myklebust const __u32 nfs4_acl_bitmap[1] = { 258137c88763STrond Myklebust [0] = FATTR4_WORD0_ACL, 258237c88763STrond Myklebust }; 258328f56694SBenny Halevy uint32_t replen; 2584029d105eSJ. Bruce Fields 25859f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25869f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25879f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 25886682c14bSJ. Bruce Fields replen = hdr.replen + op_decode_hdr_maxsz; 258937c88763STrond Myklebust encode_getattr(xdr, nfs4_acl_bitmap, NULL, 259037c88763STrond Myklebust ARRAY_SIZE(nfs4_acl_bitmap), &hdr); 2591cf8cdbe5SAndy Adamson 2592cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->acl_pages, 0, 25939ed5af26STrond Myklebust args->acl_len, replen); 2594d017931cSAndy Adamson encode_nops(&hdr); 2595029d105eSJ. Bruce Fields } 2596029d105eSJ. Bruce Fields 2597029d105eSJ. Bruce Fields /* 25981da177e4SLinus Torvalds * Encode a WRITE request 25991da177e4SLinus Torvalds */ 26009f06c719SChuck Lever static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr, 2601fcc85819SChristoph Hellwig const void *data) 26021da177e4SLinus Torvalds { 2603fcc85819SChristoph Hellwig const struct nfs_pgio_args *args = data; 26041da177e4SLinus Torvalds struct compound_hdr hdr = { 260566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26061da177e4SLinus Torvalds }; 26071da177e4SLinus Torvalds 26089f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26099f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26109f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 26119f06c719SChuck Lever encode_write(xdr, args, &hdr); 26124f22ccc3S\"Talpey, Thomas\ req->rq_snd_buf.flags |= XDRBUF_WRITE; 26137ffd1064SFred Isaman if (args->bitmask) 26149f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2615d017931cSAndy Adamson encode_nops(&hdr); 26161da177e4SLinus Torvalds } 26171da177e4SLinus Torvalds 26181da177e4SLinus Torvalds /* 26191da177e4SLinus Torvalds * a COMMIT request 26201da177e4SLinus Torvalds */ 26219f06c719SChuck Lever static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, 2622fcc85819SChristoph Hellwig const void *data) 26231da177e4SLinus Torvalds { 2624fcc85819SChristoph Hellwig const struct nfs_commitargs *args = data; 26251da177e4SLinus Torvalds struct compound_hdr hdr = { 262666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26271da177e4SLinus Torvalds }; 26281da177e4SLinus Torvalds 26299f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26309f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26319f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 26329f06c719SChuck Lever encode_commit(xdr, args, &hdr); 2633d017931cSAndy Adamson encode_nops(&hdr); 26341da177e4SLinus Torvalds } 26351da177e4SLinus Torvalds 26361da177e4SLinus Torvalds /* 26371da177e4SLinus Torvalds * FSINFO request 26381da177e4SLinus Torvalds */ 26399f06c719SChuck Lever static void nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, 2640fcc85819SChristoph Hellwig const void *data) 26411da177e4SLinus Torvalds { 2642fcc85819SChristoph Hellwig const struct nfs4_fsinfo_arg *args = data; 26431da177e4SLinus Torvalds struct compound_hdr hdr = { 264466cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26451da177e4SLinus Torvalds }; 26461da177e4SLinus Torvalds 26479f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26489f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26499f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 26509f06c719SChuck Lever encode_fsinfo(xdr, args->bitmask, &hdr); 2651d017931cSAndy Adamson encode_nops(&hdr); 26521da177e4SLinus Torvalds } 26531da177e4SLinus Torvalds 26541da177e4SLinus Torvalds /* 26551da177e4SLinus Torvalds * a PATHCONF request 26561da177e4SLinus Torvalds */ 26579f06c719SChuck Lever static void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, 2658fcc85819SChristoph Hellwig const void *data) 26591da177e4SLinus Torvalds { 2660fcc85819SChristoph Hellwig const struct nfs4_pathconf_arg *args = data; 26611da177e4SLinus Torvalds struct compound_hdr hdr = { 266266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26631da177e4SLinus Torvalds }; 26641da177e4SLinus Torvalds 26659f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26669f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26679f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 266837c88763STrond Myklebust encode_getattr(xdr, nfs4_pathconf_bitmap, args->bitmask, 266937c88763STrond Myklebust ARRAY_SIZE(nfs4_pathconf_bitmap), &hdr); 2670d017931cSAndy Adamson encode_nops(&hdr); 26711da177e4SLinus Torvalds } 26721da177e4SLinus Torvalds 26731da177e4SLinus Torvalds /* 26741da177e4SLinus Torvalds * a STATFS request 26751da177e4SLinus Torvalds */ 26769f06c719SChuck Lever static void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, 2677fcc85819SChristoph Hellwig const void *data) 26781da177e4SLinus Torvalds { 2679fcc85819SChristoph Hellwig const struct nfs4_statfs_arg *args = data; 26801da177e4SLinus Torvalds struct compound_hdr hdr = { 268166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26821da177e4SLinus Torvalds }; 26831da177e4SLinus Torvalds 26849f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26859f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26869f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 268737c88763STrond Myklebust encode_getattr(xdr, nfs4_statfs_bitmap, args->bitmask, 268837c88763STrond Myklebust ARRAY_SIZE(nfs4_statfs_bitmap), &hdr); 2689d017931cSAndy Adamson encode_nops(&hdr); 26901da177e4SLinus Torvalds } 26911da177e4SLinus Torvalds 26921da177e4SLinus Torvalds /* 26931da177e4SLinus Torvalds * GETATTR_BITMAP request 26941da177e4SLinus Torvalds */ 26959f06c719SChuck Lever static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req, 26969f06c719SChuck Lever struct xdr_stream *xdr, 2697fcc85819SChristoph Hellwig const void *data) 26981da177e4SLinus Torvalds { 2699fcc85819SChristoph Hellwig const struct nfs4_server_caps_arg *args = data; 27008c61282fSKinglong Mee const u32 *bitmask = args->bitmask; 27011da177e4SLinus Torvalds struct compound_hdr hdr = { 270266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 27031da177e4SLinus Torvalds }; 27041da177e4SLinus Torvalds 27059f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27069f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 27079f06c719SChuck Lever encode_putfh(xdr, args->fhandle, &hdr); 270837c88763STrond Myklebust encode_getattr(xdr, bitmask, NULL, 3, &hdr); 2709d017931cSAndy Adamson encode_nops(&hdr); 27101da177e4SLinus Torvalds } 27111da177e4SLinus Torvalds 27121da177e4SLinus Torvalds /* 27131da177e4SLinus Torvalds * a RENEW request 27141da177e4SLinus Torvalds */ 27159f06c719SChuck Lever static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr, 2716fcc85819SChristoph Hellwig const void *data) 2717fcc85819SChristoph Hellwig 27181da177e4SLinus Torvalds { 2719fcc85819SChristoph Hellwig const struct nfs_client *clp = data; 27201da177e4SLinus Torvalds struct compound_hdr hdr = { 2721d017931cSAndy Adamson .nops = 0, 27221da177e4SLinus Torvalds }; 27231da177e4SLinus Torvalds 27249f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 2725bb4dae5eSChuck Lever encode_renew(xdr, clp->cl_clientid, &hdr); 2726d017931cSAndy Adamson encode_nops(&hdr); 27271da177e4SLinus Torvalds } 27281da177e4SLinus Torvalds 27291da177e4SLinus Torvalds /* 27301da177e4SLinus Torvalds * a SETCLIENTID request 27311da177e4SLinus Torvalds */ 27329f06c719SChuck Lever static void nfs4_xdr_enc_setclientid(struct rpc_rqst *req, 27339f06c719SChuck Lever struct xdr_stream *xdr, 2734fcc85819SChristoph Hellwig const void *data) 27351da177e4SLinus Torvalds { 2736fcc85819SChristoph Hellwig const struct nfs4_setclientid *sc = data; 27371da177e4SLinus Torvalds struct compound_hdr hdr = { 2738d017931cSAndy Adamson .nops = 0, 27391da177e4SLinus Torvalds }; 27401da177e4SLinus Torvalds 27419f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27429f06c719SChuck Lever encode_setclientid(xdr, sc, &hdr); 2743d017931cSAndy Adamson encode_nops(&hdr); 27441da177e4SLinus Torvalds } 27451da177e4SLinus Torvalds 27461da177e4SLinus Torvalds /* 27471da177e4SLinus Torvalds * a SETCLIENTID_CONFIRM request 27481da177e4SLinus Torvalds */ 27499f06c719SChuck Lever static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, 27509f06c719SChuck Lever struct xdr_stream *xdr, 2751fcc85819SChristoph Hellwig const void *data) 27521da177e4SLinus Torvalds { 2753fcc85819SChristoph Hellwig const struct nfs4_setclientid_res *arg = data; 27541da177e4SLinus Torvalds struct compound_hdr hdr = { 2755d017931cSAndy Adamson .nops = 0, 27561da177e4SLinus Torvalds }; 27571da177e4SLinus Torvalds 27589f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27599f06c719SChuck Lever encode_setclientid_confirm(xdr, arg, &hdr); 2760d017931cSAndy Adamson encode_nops(&hdr); 27611da177e4SLinus Torvalds } 27621da177e4SLinus Torvalds 27631da177e4SLinus Torvalds /* 27641da177e4SLinus Torvalds * DELEGRETURN request 27651da177e4SLinus Torvalds */ 27669f06c719SChuck Lever static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, 27679f06c719SChuck Lever struct xdr_stream *xdr, 2768fcc85819SChristoph Hellwig const void *data) 27691da177e4SLinus Torvalds { 2770fcc85819SChristoph Hellwig const struct nfs4_delegreturnargs *args = data; 27711da177e4SLinus Torvalds struct compound_hdr hdr = { 277266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 27731da177e4SLinus Torvalds }; 27741da177e4SLinus Torvalds 27759f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27769f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 27779f06c719SChuck Lever encode_putfh(xdr, args->fhandle, &hdr); 2778586f1c39STrond Myklebust if (args->lr_args) 2779586f1c39STrond Myklebust encode_layoutreturn(xdr, args->lr_args, &hdr); 27808ac2b422STrond Myklebust if (args->bitmask) 27819f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2782e144cbccSTrond Myklebust encode_delegreturn(xdr, args->stateid, &hdr); 2783d017931cSAndy Adamson encode_nops(&hdr); 27841da177e4SLinus Torvalds } 27851da177e4SLinus Torvalds 27861da177e4SLinus Torvalds /* 2787683b57b4STrond Myklebust * Encode FS_LOCATIONS request 2788683b57b4STrond Myklebust */ 27899f06c719SChuck Lever static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, 27909f06c719SChuck Lever struct xdr_stream *xdr, 2791fcc85819SChristoph Hellwig const void *data) 2792683b57b4STrond Myklebust { 2793fcc85819SChristoph Hellwig const struct nfs4_fs_locations_arg *args = data; 2794683b57b4STrond Myklebust struct compound_hdr hdr = { 279566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2796683b57b4STrond Myklebust }; 279728f56694SBenny Halevy uint32_t replen; 2798683b57b4STrond Myklebust 27999f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 28009f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 2801b03d735bSChuck Lever if (args->migration) { 2802b03d735bSChuck Lever encode_putfh(xdr, args->fh, &hdr); 2803b03d735bSChuck Lever replen = hdr.replen; 2804b03d735bSChuck Lever encode_fs_locations(xdr, args->bitmask, &hdr); 2805b03d735bSChuck Lever if (args->renew) 2806b03d735bSChuck Lever encode_renew(xdr, args->clientid, &hdr); 2807b03d735bSChuck Lever } else { 28089f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 28099f06c719SChuck Lever encode_lookup(xdr, args->name, &hdr); 2810b03d735bSChuck Lever replen = hdr.replen; 28119f06c719SChuck Lever encode_fs_locations(xdr, args->bitmask, &hdr); 2812b03d735bSChuck Lever } 2813cf8cdbe5SAndy Adamson 2814cf500bacSChuck Lever rpc_prepare_reply_pages(req, (struct page **)&args->page, 0, 28159ed5af26STrond Myklebust PAGE_SIZE, replen); 2816d017931cSAndy Adamson encode_nops(&hdr); 2817683b57b4STrond Myklebust } 2818683b57b4STrond Myklebust 28195a5ea0d4SBryan Schumaker /* 28205a5ea0d4SBryan Schumaker * Encode SECINFO request 28215a5ea0d4SBryan Schumaker */ 28225a5ea0d4SBryan Schumaker static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req, 28235a5ea0d4SBryan Schumaker struct xdr_stream *xdr, 2824fcc85819SChristoph Hellwig const void *data) 28255a5ea0d4SBryan Schumaker { 2826fcc85819SChristoph Hellwig const struct nfs4_secinfo_arg *args = data; 28275a5ea0d4SBryan Schumaker struct compound_hdr hdr = { 28285a5ea0d4SBryan Schumaker .minorversion = nfs4_xdr_minorversion(&args->seq_args), 28295a5ea0d4SBryan Schumaker }; 28305a5ea0d4SBryan Schumaker 28315a5ea0d4SBryan Schumaker encode_compound_hdr(xdr, req, &hdr); 28325a5ea0d4SBryan Schumaker encode_sequence(xdr, &args->seq_args, &hdr); 28335a5ea0d4SBryan Schumaker encode_putfh(xdr, args->dir_fh, &hdr); 28345a5ea0d4SBryan Schumaker encode_secinfo(xdr, args->name, &hdr); 28355a5ea0d4SBryan Schumaker encode_nops(&hdr); 28365a5ea0d4SBryan Schumaker } 28375a5ea0d4SBryan Schumaker 283844c99933SChuck Lever /* 283944c99933SChuck Lever * Encode FSID_PRESENT request 284044c99933SChuck Lever */ 284144c99933SChuck Lever static void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req, 284244c99933SChuck Lever struct xdr_stream *xdr, 2843fcc85819SChristoph Hellwig const void *data) 284444c99933SChuck Lever { 2845fcc85819SChristoph Hellwig const struct nfs4_fsid_present_arg *args = data; 284644c99933SChuck Lever struct compound_hdr hdr = { 284744c99933SChuck Lever .minorversion = nfs4_xdr_minorversion(&args->seq_args), 284844c99933SChuck Lever }; 284944c99933SChuck Lever 285044c99933SChuck Lever encode_compound_hdr(xdr, req, &hdr); 285144c99933SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 285244c99933SChuck Lever encode_putfh(xdr, args->fh, &hdr); 285344c99933SChuck Lever encode_getfh(xdr, &hdr); 285444c99933SChuck Lever if (args->renew) 285544c99933SChuck Lever encode_renew(xdr, args->clientid, &hdr); 285644c99933SChuck Lever encode_nops(&hdr); 285744c99933SChuck Lever } 285844c99933SChuck Lever 285999fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 286099fe60d0SBenny Halevy /* 28617c44f1aeSWeston Andros Adamson * BIND_CONN_TO_SESSION request 28627c44f1aeSWeston Andros Adamson */ 28637c44f1aeSWeston Andros Adamson static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req, 28647c44f1aeSWeston Andros Adamson struct xdr_stream *xdr, 2865fcc85819SChristoph Hellwig const void *data) 28667c44f1aeSWeston Andros Adamson { 2867fcc85819SChristoph Hellwig const struct nfs41_bind_conn_to_session_args *args = data; 28687c44f1aeSWeston Andros Adamson struct compound_hdr hdr = { 286971a097c6STrond Myklebust .minorversion = args->client->cl_mvops->minor_version, 28707c44f1aeSWeston Andros Adamson }; 28717c44f1aeSWeston Andros Adamson 28727c44f1aeSWeston Andros Adamson encode_compound_hdr(xdr, req, &hdr); 287371a097c6STrond Myklebust encode_bind_conn_to_session(xdr, args, &hdr); 28747c44f1aeSWeston Andros Adamson encode_nops(&hdr); 28757c44f1aeSWeston Andros Adamson } 28767c44f1aeSWeston Andros Adamson 28777c44f1aeSWeston Andros Adamson /* 287899fe60d0SBenny Halevy * EXCHANGE_ID request 287999fe60d0SBenny Halevy */ 28809f06c719SChuck Lever static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, 28819f06c719SChuck Lever struct xdr_stream *xdr, 2882fcc85819SChristoph Hellwig const void *data) 288399fe60d0SBenny Halevy { 2884fcc85819SChristoph Hellwig const struct nfs41_exchange_id_args *args = data; 288599fe60d0SBenny Halevy struct compound_hdr hdr = { 2886a4432345STrond Myklebust .minorversion = args->client->cl_mvops->minor_version, 288799fe60d0SBenny Halevy }; 288899fe60d0SBenny Halevy 28899f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 28909f06c719SChuck Lever encode_exchange_id(xdr, args, &hdr); 289199fe60d0SBenny Halevy encode_nops(&hdr); 289299fe60d0SBenny Halevy } 28932050f0ccSAndy Adamson 28942050f0ccSAndy Adamson /* 2895fc931582SAndy Adamson * a CREATE_SESSION request 2896fc931582SAndy Adamson */ 28979f06c719SChuck Lever static void nfs4_xdr_enc_create_session(struct rpc_rqst *req, 28989f06c719SChuck Lever struct xdr_stream *xdr, 2899fcc85819SChristoph Hellwig const void *data) 2900fc931582SAndy Adamson { 2901fcc85819SChristoph Hellwig const struct nfs41_create_session_args *args = data; 2902fc931582SAndy Adamson struct compound_hdr hdr = { 2903a4432345STrond Myklebust .minorversion = args->client->cl_mvops->minor_version, 2904fc931582SAndy Adamson }; 2905fc931582SAndy Adamson 29069f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 29079f06c719SChuck Lever encode_create_session(xdr, args, &hdr); 2908fc931582SAndy Adamson encode_nops(&hdr); 2909fc931582SAndy Adamson } 2910fc931582SAndy Adamson 2911fc931582SAndy Adamson /* 29120f3e66c6SAndy Adamson * a DESTROY_SESSION request 29130f3e66c6SAndy Adamson */ 29149f06c719SChuck Lever static void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, 29159f06c719SChuck Lever struct xdr_stream *xdr, 2916fcc85819SChristoph Hellwig const void *data) 29170f3e66c6SAndy Adamson { 2918fcc85819SChristoph Hellwig const struct nfs4_session *session = data; 29190f3e66c6SAndy Adamson struct compound_hdr hdr = { 2920a4432345STrond Myklebust .minorversion = session->clp->cl_mvops->minor_version, 29210f3e66c6SAndy Adamson }; 29220f3e66c6SAndy Adamson 29239f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 29249f06c719SChuck Lever encode_destroy_session(xdr, session, &hdr); 29250f3e66c6SAndy Adamson encode_nops(&hdr); 29260f3e66c6SAndy Adamson } 29270f3e66c6SAndy Adamson 29280f3e66c6SAndy Adamson /* 292966245539STrond Myklebust * a DESTROY_CLIENTID request 293066245539STrond Myklebust */ 293166245539STrond Myklebust static void nfs4_xdr_enc_destroy_clientid(struct rpc_rqst *req, 293266245539STrond Myklebust struct xdr_stream *xdr, 2933fcc85819SChristoph Hellwig const void *data) 293466245539STrond Myklebust { 2935fcc85819SChristoph Hellwig const struct nfs_client *clp = data; 293666245539STrond Myklebust struct compound_hdr hdr = { 293766245539STrond Myklebust .minorversion = clp->cl_mvops->minor_version, 293866245539STrond Myklebust }; 293966245539STrond Myklebust 294066245539STrond Myklebust encode_compound_hdr(xdr, req, &hdr); 294166245539STrond Myklebust encode_destroy_clientid(xdr, clp->cl_clientid, &hdr); 294266245539STrond Myklebust encode_nops(&hdr); 294366245539STrond Myklebust } 294466245539STrond Myklebust 294566245539STrond Myklebust /* 2946fc01cea9SAndy Adamson * a SEQUENCE request 2947fc01cea9SAndy Adamson */ 29489f06c719SChuck Lever static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr, 2949fcc85819SChristoph Hellwig const void *data) 2950fc01cea9SAndy Adamson { 2951fcc85819SChristoph Hellwig const struct nfs4_sequence_args *args = data; 2952fc01cea9SAndy Adamson struct compound_hdr hdr = { 2953fc01cea9SAndy Adamson .minorversion = nfs4_xdr_minorversion(args), 2954fc01cea9SAndy Adamson }; 2955fc01cea9SAndy Adamson 29569f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 29579f06c719SChuck Lever encode_sequence(xdr, args, &hdr); 2958fc01cea9SAndy Adamson encode_nops(&hdr); 2959fc01cea9SAndy Adamson } 2960fc01cea9SAndy Adamson 29610efb01b2SDonald Buczek #endif 29620efb01b2SDonald Buczek 2963fc01cea9SAndy Adamson /* 29642050f0ccSAndy Adamson * a GET_LEASE_TIME request 29652050f0ccSAndy Adamson */ 29669f06c719SChuck Lever static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, 29679f06c719SChuck Lever struct xdr_stream *xdr, 2968fcc85819SChristoph Hellwig const void *data) 29692050f0ccSAndy Adamson { 2970fcc85819SChristoph Hellwig const struct nfs4_get_lease_time_args *args = data; 29712050f0ccSAndy Adamson struct compound_hdr hdr = { 29722050f0ccSAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->la_seq_args), 29732050f0ccSAndy Adamson }; 2974dae100c2SFred Isaman const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME }; 29752050f0ccSAndy Adamson 29769f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 29779f06c719SChuck Lever encode_sequence(xdr, &args->la_seq_args, &hdr); 29789f06c719SChuck Lever encode_putrootfh(xdr, &hdr); 29799f06c719SChuck Lever encode_fsinfo(xdr, lease_bitmap, &hdr); 29802050f0ccSAndy Adamson encode_nops(&hdr); 29812050f0ccSAndy Adamson } 298218019753SRicardo Labiaga 29830efb01b2SDonald Buczek #ifdef CONFIG_NFS_V4_1 29840efb01b2SDonald Buczek 298518019753SRicardo Labiaga /* 298618019753SRicardo Labiaga * a RECLAIM_COMPLETE request 298718019753SRicardo Labiaga */ 29889f06c719SChuck Lever static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, 29899f06c719SChuck Lever struct xdr_stream *xdr, 2990fcc85819SChristoph Hellwig const void *data) 299118019753SRicardo Labiaga { 2992fcc85819SChristoph Hellwig const struct nfs41_reclaim_complete_args *args = data; 299318019753SRicardo Labiaga struct compound_hdr hdr = { 299418019753SRicardo Labiaga .minorversion = nfs4_xdr_minorversion(&args->seq_args) 299518019753SRicardo Labiaga }; 299618019753SRicardo Labiaga 29979f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 29989f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 29999f06c719SChuck Lever encode_reclaim_complete(xdr, args, &hdr); 300018019753SRicardo Labiaga encode_nops(&hdr); 300118019753SRicardo Labiaga } 300218019753SRicardo Labiaga 3003b1f69b75SAndy Adamson /* 3004b1f69b75SAndy Adamson * Encode GETDEVICEINFO request 3005b1f69b75SAndy Adamson */ 30069f06c719SChuck Lever static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, 30079f06c719SChuck Lever struct xdr_stream *xdr, 3008fcc85819SChristoph Hellwig const void *data) 3009b1f69b75SAndy Adamson { 3010fcc85819SChristoph Hellwig const struct nfs4_getdeviceinfo_args *args = data; 3011b1f69b75SAndy Adamson struct compound_hdr hdr = { 3012b1f69b75SAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 3013b1f69b75SAndy Adamson }; 3014046e5ccbSTrond Myklebust uint32_t replen; 3015b1f69b75SAndy Adamson 30169f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 30179f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 3018046e5ccbSTrond Myklebust 30199ed5af26STrond Myklebust replen = hdr.replen + op_decode_hdr_maxsz + 2; 3020046e5ccbSTrond Myklebust 30219f06c719SChuck Lever encode_getdeviceinfo(xdr, args, &hdr); 3022b1f69b75SAndy Adamson 3023046e5ccbSTrond Myklebust /* set up reply kvec. device_addr4 opaque data is read into the 3024046e5ccbSTrond Myklebust * pages */ 3025cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->pdev->pages, args->pdev->pgbase, 30269ed5af26STrond Myklebust args->pdev->pglen, replen); 3027b1f69b75SAndy Adamson encode_nops(&hdr); 3028b1f69b75SAndy Adamson } 3029b1f69b75SAndy Adamson 3030b1f69b75SAndy Adamson /* 3031b1f69b75SAndy Adamson * Encode LAYOUTGET request 3032b1f69b75SAndy Adamson */ 30339f06c719SChuck Lever static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, 30349f06c719SChuck Lever struct xdr_stream *xdr, 3035fcc85819SChristoph Hellwig const void *data) 3036b1f69b75SAndy Adamson { 3037fcc85819SChristoph Hellwig const struct nfs4_layoutget_args *args = data; 3038b1f69b75SAndy Adamson struct compound_hdr hdr = { 3039b1f69b75SAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 3040b1f69b75SAndy Adamson }; 3041b1f69b75SAndy Adamson 30429f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 30439f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 30449f06c719SChuck Lever encode_putfh(xdr, NFS_FH(args->inode), &hdr); 30459f06c719SChuck Lever encode_layoutget(xdr, args, &hdr); 304635124a09SWeston Andros Adamson 3047cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->layout.pages, 0, 30489ed5af26STrond Myklebust args->layout.pglen, hdr.replen - pagepad_maxsz); 3049b1f69b75SAndy Adamson encode_nops(&hdr); 3050b1f69b75SAndy Adamson } 3051863a3c6cSAndy Adamson 3052863a3c6cSAndy Adamson /* 3053863a3c6cSAndy Adamson * Encode LAYOUTCOMMIT request 3054863a3c6cSAndy Adamson */ 3055cbe82603SBenny Halevy static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, 3056863a3c6cSAndy Adamson struct xdr_stream *xdr, 3057fcc85819SChristoph Hellwig const void *priv) 3058863a3c6cSAndy Adamson { 3059fcc85819SChristoph Hellwig const struct nfs4_layoutcommit_args *args = priv; 3060ac7db726SBenny Halevy struct nfs4_layoutcommit_data *data = 3061ac7db726SBenny Halevy container_of(args, struct nfs4_layoutcommit_data, args); 3062863a3c6cSAndy Adamson struct compound_hdr hdr = { 3063863a3c6cSAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 3064863a3c6cSAndy Adamson }; 3065863a3c6cSAndy Adamson 3066863a3c6cSAndy Adamson encode_compound_hdr(xdr, req, &hdr); 3067863a3c6cSAndy Adamson encode_sequence(xdr, &args->seq_args, &hdr); 3068863a3c6cSAndy Adamson encode_putfh(xdr, NFS_FH(args->inode), &hdr); 3069ac7db726SBenny Halevy encode_layoutcommit(xdr, data->args.inode, args, &hdr); 3070863a3c6cSAndy Adamson encode_getfattr(xdr, args->bitmask, &hdr); 3071863a3c6cSAndy Adamson encode_nops(&hdr); 3072cbe82603SBenny Halevy } 3073cbe82603SBenny Halevy 3074cbe82603SBenny Halevy /* 3075cbe82603SBenny Halevy * Encode LAYOUTRETURN request 3076cbe82603SBenny Halevy */ 3077cbe82603SBenny Halevy static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req, 3078cbe82603SBenny Halevy struct xdr_stream *xdr, 3079fcc85819SChristoph Hellwig const void *data) 3080cbe82603SBenny Halevy { 3081fcc85819SChristoph Hellwig const struct nfs4_layoutreturn_args *args = data; 3082cbe82603SBenny Halevy struct compound_hdr hdr = { 3083cbe82603SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 3084cbe82603SBenny Halevy }; 3085cbe82603SBenny Halevy 3086cbe82603SBenny Halevy encode_compound_hdr(xdr, req, &hdr); 3087cbe82603SBenny Halevy encode_sequence(xdr, &args->seq_args, &hdr); 3088cbe82603SBenny Halevy encode_putfh(xdr, NFS_FH(args->inode), &hdr); 3089cbe82603SBenny Halevy encode_layoutreturn(xdr, args, &hdr); 3090cbe82603SBenny Halevy encode_nops(&hdr); 3091863a3c6cSAndy Adamson } 3092fca78d6dSBryan Schumaker 3093fca78d6dSBryan Schumaker /* 3094fca78d6dSBryan Schumaker * Encode SECINFO_NO_NAME request 3095fca78d6dSBryan Schumaker */ 3096fcc85819SChristoph Hellwig static void nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req, 3097fca78d6dSBryan Schumaker struct xdr_stream *xdr, 3098fcc85819SChristoph Hellwig const void *data) 3099fca78d6dSBryan Schumaker { 3100fcc85819SChristoph Hellwig const struct nfs41_secinfo_no_name_args *args = data; 3101fca78d6dSBryan Schumaker struct compound_hdr hdr = { 3102fca78d6dSBryan Schumaker .minorversion = nfs4_xdr_minorversion(&args->seq_args), 3103fca78d6dSBryan Schumaker }; 3104fca78d6dSBryan Schumaker 3105fca78d6dSBryan Schumaker encode_compound_hdr(xdr, req, &hdr); 3106fca78d6dSBryan Schumaker encode_sequence(xdr, &args->seq_args, &hdr); 3107fca78d6dSBryan Schumaker encode_putrootfh(xdr, &hdr); 3108fca78d6dSBryan Schumaker encode_secinfo_no_name(xdr, args, &hdr); 3109fca78d6dSBryan Schumaker encode_nops(&hdr); 3110fca78d6dSBryan Schumaker } 31117d974794SBryan Schumaker 31127d974794SBryan Schumaker /* 31137d974794SBryan Schumaker * Encode TEST_STATEID request 31147d974794SBryan Schumaker */ 31157d974794SBryan Schumaker static void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req, 31167d974794SBryan Schumaker struct xdr_stream *xdr, 3117fcc85819SChristoph Hellwig const void *data) 31187d974794SBryan Schumaker { 3119fcc85819SChristoph Hellwig const struct nfs41_test_stateid_args *args = data; 31207d974794SBryan Schumaker struct compound_hdr hdr = { 31217d974794SBryan Schumaker .minorversion = nfs4_xdr_minorversion(&args->seq_args), 31227d974794SBryan Schumaker }; 31237d974794SBryan Schumaker 31247d974794SBryan Schumaker encode_compound_hdr(xdr, req, &hdr); 31257d974794SBryan Schumaker encode_sequence(xdr, &args->seq_args, &hdr); 31267d974794SBryan Schumaker encode_test_stateid(xdr, args, &hdr); 31277d974794SBryan Schumaker encode_nops(&hdr); 31287d974794SBryan Schumaker } 31299aeda35fSBryan Schumaker 31309aeda35fSBryan Schumaker /* 31319aeda35fSBryan Schumaker * Encode FREE_STATEID request 31329aeda35fSBryan Schumaker */ 31339aeda35fSBryan Schumaker static void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req, 31349aeda35fSBryan Schumaker struct xdr_stream *xdr, 3135fcc85819SChristoph Hellwig const void *data) 31369aeda35fSBryan Schumaker { 3137fcc85819SChristoph Hellwig const struct nfs41_free_stateid_args *args = data; 31389aeda35fSBryan Schumaker struct compound_hdr hdr = { 31399aeda35fSBryan Schumaker .minorversion = nfs4_xdr_minorversion(&args->seq_args), 31409aeda35fSBryan Schumaker }; 31419aeda35fSBryan Schumaker 31429aeda35fSBryan Schumaker encode_compound_hdr(xdr, req, &hdr); 31439aeda35fSBryan Schumaker encode_sequence(xdr, &args->seq_args, &hdr); 31449aeda35fSBryan Schumaker encode_free_stateid(xdr, args, &hdr); 31459aeda35fSBryan Schumaker encode_nops(&hdr); 31469aeda35fSBryan Schumaker } 314799fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 314899fe60d0SBenny Halevy 3149683b57b4STrond Myklebust static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) 31501da177e4SLinus Torvalds { 31516da59ce2STrond Myklebust ssize_t ret = xdr_stream_decode_opaque_inline(xdr, (void **)string, 31526da59ce2STrond Myklebust NFS4_OPAQUE_LIMIT); 3153eb72f484SChuck Lever if (unlikely(ret < 0)) 3154c0eae66eSBenny Halevy return -EIO; 31556da59ce2STrond Myklebust *len = ret; 31566da59ce2STrond Myklebust return 0; 31576da59ce2STrond Myklebust } 31581da177e4SLinus Torvalds 31591da177e4SLinus Torvalds static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) 31601da177e4SLinus Torvalds { 31618687b63aSAl Viro __be32 *p; 31621da177e4SLinus Torvalds 3163c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3164c0eae66eSBenny Halevy if (unlikely(!p)) 3165eb72f484SChuck Lever return -EIO; 31666f723f77SBenny Halevy hdr->status = be32_to_cpup(p++); 3167cccddf4fSBenny Halevy hdr->taglen = be32_to_cpup(p); 31681da177e4SLinus Torvalds 3169c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, hdr->taglen + 4); 3170c0eae66eSBenny Halevy if (unlikely(!p)) 3171eb72f484SChuck Lever return -EIO; 31721da177e4SLinus Torvalds hdr->tag = (char *)p; 31731da177e4SLinus Torvalds p += XDR_QUADLEN(hdr->taglen); 3174cccddf4fSBenny Halevy hdr->nops = be32_to_cpup(p); 3175aadf6152SBenny Halevy if (unlikely(hdr->nops < 1)) 3176aadf6152SBenny Halevy return nfs4_stat_to_errno(hdr->status); 31771da177e4SLinus Torvalds return 0; 31781da177e4SLinus Torvalds } 31791da177e4SLinus Torvalds 3180c7848f69STrond Myklebust static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected, 3181c7848f69STrond Myklebust int *nfs_retval) 31821da177e4SLinus Torvalds { 31838687b63aSAl Viro __be32 *p; 31841da177e4SLinus Torvalds uint32_t opnum; 31851da177e4SLinus Torvalds int32_t nfserr; 31861da177e4SLinus Torvalds 3187c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3188c0eae66eSBenny Halevy if (unlikely(!p)) 3189c0eae66eSBenny Halevy goto out_overflow; 31906f723f77SBenny Halevy opnum = be32_to_cpup(p++); 3191c7848f69STrond Myklebust if (unlikely(opnum != expected)) 3192c7848f69STrond Myklebust goto out_bad_operation; 3193f23f6584SChuck Lever if (unlikely(*p != cpu_to_be32(NFS_OK))) 3194f23f6584SChuck Lever goto out_status; 3195c7848f69STrond Myklebust *nfs_retval = 0; 3196f23f6584SChuck Lever return true; 3197f23f6584SChuck Lever out_status: 3198f23f6584SChuck Lever nfserr = be32_to_cpup(p); 319962a92ba9SChuck Lever trace_nfs4_xdr_status(xdr, opnum, nfserr); 3200c7848f69STrond Myklebust *nfs_retval = nfs4_stat_to_errno(nfserr); 3201c7848f69STrond Myklebust return true; 3202c7848f69STrond Myklebust out_bad_operation: 3203fe82a183SChuck Lever dprintk("nfs: Server returned operation" 32041da177e4SLinus Torvalds " %d but we issued a request for %d\n", 32051da177e4SLinus Torvalds opnum, expected); 3206c7848f69STrond Myklebust *nfs_retval = -EREMOTEIO; 3207c7848f69STrond Myklebust return false; 3208c0eae66eSBenny Halevy out_overflow: 3209c7848f69STrond Myklebust *nfs_retval = -EIO; 3210c7848f69STrond Myklebust return false; 3211c7848f69STrond Myklebust } 3212c7848f69STrond Myklebust 3213c7848f69STrond Myklebust static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) 3214c7848f69STrond Myklebust { 3215c7848f69STrond Myklebust int retval; 3216c7848f69STrond Myklebust 3217c7848f69STrond Myklebust __decode_op_hdr(xdr, expected, &retval); 3218c7848f69STrond Myklebust return retval; 32191da177e4SLinus Torvalds } 32201da177e4SLinus Torvalds 32211da177e4SLinus Torvalds /* Dummy routine */ 32221bbe60ffSTrond Myklebust static int decode_ace(struct xdr_stream *xdr, void *ace) 32231da177e4SLinus Torvalds { 32248687b63aSAl Viro __be32 *p; 3225683b57b4STrond Myklebust unsigned int strlen; 32261da177e4SLinus Torvalds char *str; 32271da177e4SLinus Torvalds 3228c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 3229eb72f484SChuck Lever if (unlikely(!p)) 3230c0eae66eSBenny Halevy return -EIO; 3231eb72f484SChuck Lever return decode_opaque_inline(xdr, &strlen, &str); 32321da177e4SLinus Torvalds } 32331da177e4SLinus Torvalds 323437c88763STrond Myklebust static ssize_t 323537c88763STrond Myklebust decode_bitmap4(struct xdr_stream *xdr, uint32_t *bitmap, size_t sz) 32361da177e4SLinus Torvalds { 323737c88763STrond Myklebust ssize_t ret; 32381da177e4SLinus Torvalds 323937c88763STrond Myklebust ret = xdr_stream_decode_uint32_array(xdr, bitmap, sz); 324037c88763STrond Myklebust if (likely(ret >= 0)) 324137c88763STrond Myklebust return ret; 3242eb72f484SChuck Lever if (ret != -EMSGSIZE) 3243c0eae66eSBenny Halevy return -EIO; 3244eb72f484SChuck Lever return sz; 32451da177e4SLinus Torvalds } 32461da177e4SLinus Torvalds 324737c88763STrond Myklebust static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) 324837c88763STrond Myklebust { 324937c88763STrond Myklebust ssize_t ret; 325037c88763STrond Myklebust ret = decode_bitmap4(xdr, bitmap, 3); 325137c88763STrond Myklebust return ret < 0 ? ret : 0; 325237c88763STrond Myklebust } 325337c88763STrond Myklebust 3254256e48bbSTrond Myklebust static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigned int *savep) 32551da177e4SLinus Torvalds { 32568687b63aSAl Viro __be32 *p; 32571da177e4SLinus Torvalds 3258c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3259c0eae66eSBenny Halevy if (unlikely(!p)) 3260eb72f484SChuck Lever return -EIO; 3261cccddf4fSBenny Halevy *attrlen = be32_to_cpup(p); 3262256e48bbSTrond Myklebust *savep = xdr_stream_pos(xdr); 32631da177e4SLinus Torvalds return 0; 32641da177e4SLinus Torvalds } 32651da177e4SLinus Torvalds 32661da177e4SLinus Torvalds static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask) 32671da177e4SLinus Torvalds { 32681da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) { 32693388bff5SRoman Borisov int ret; 32703388bff5SRoman Borisov ret = decode_attr_bitmap(xdr, bitmask); 32713388bff5SRoman Borisov if (unlikely(ret < 0)) 32723388bff5SRoman Borisov return ret; 32731da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS; 32741da177e4SLinus Torvalds } else 3275dae100c2SFred Isaman bitmask[0] = bitmask[1] = bitmask[2] = 0; 3276dae100c2SFred Isaman dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__, 3277dae100c2SFred Isaman bitmask[0], bitmask[1], bitmask[2]); 32781da177e4SLinus Torvalds return 0; 32791da177e4SLinus Torvalds } 32801da177e4SLinus Torvalds 32811da177e4SLinus Torvalds static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type) 32821da177e4SLinus Torvalds { 32838687b63aSAl Viro __be32 *p; 3284409924e4STrond Myklebust int ret = 0; 32851da177e4SLinus Torvalds 32861da177e4SLinus Torvalds *type = 0; 32871da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U))) 32881da177e4SLinus Torvalds return -EIO; 32891da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) { 3290c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3291c0eae66eSBenny Halevy if (unlikely(!p)) 3292eb72f484SChuck Lever return -EIO; 3293cccddf4fSBenny Halevy *type = be32_to_cpup(p); 32941da177e4SLinus Torvalds if (*type < NF4REG || *type > NF4NAMEDATTR) { 32953110ff80SHarvey Harrison dprintk("%s: bad type %d\n", __func__, *type); 32961da177e4SLinus Torvalds return -EIO; 32971da177e4SLinus Torvalds } 32981da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_TYPE; 3299409924e4STrond Myklebust ret = NFS_ATTR_FATTR_TYPE; 33001da177e4SLinus Torvalds } 3301bca79478STrond Myklebust dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]); 3302409924e4STrond Myklebust return ret; 33031da177e4SLinus Torvalds } 33041da177e4SLinus Torvalds 3305264e6351SChuck Lever static int decode_attr_fh_expire_type(struct xdr_stream *xdr, 3306264e6351SChuck Lever uint32_t *bitmap, uint32_t *type) 3307264e6351SChuck Lever { 3308264e6351SChuck Lever __be32 *p; 3309264e6351SChuck Lever 3310264e6351SChuck Lever *type = 0; 3311264e6351SChuck Lever if (unlikely(bitmap[0] & (FATTR4_WORD0_FH_EXPIRE_TYPE - 1U))) 3312264e6351SChuck Lever return -EIO; 3313264e6351SChuck Lever if (likely(bitmap[0] & FATTR4_WORD0_FH_EXPIRE_TYPE)) { 3314264e6351SChuck Lever p = xdr_inline_decode(xdr, 4); 3315264e6351SChuck Lever if (unlikely(!p)) 3316eb72f484SChuck Lever return -EIO; 3317264e6351SChuck Lever *type = be32_to_cpup(p); 3318264e6351SChuck Lever bitmap[0] &= ~FATTR4_WORD0_FH_EXPIRE_TYPE; 3319264e6351SChuck Lever } 3320264e6351SChuck Lever dprintk("%s: expire type=0x%x\n", __func__, *type); 3321264e6351SChuck Lever return 0; 3322264e6351SChuck Lever } 3323264e6351SChuck Lever 33241da177e4SLinus Torvalds static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) 33251da177e4SLinus Torvalds { 33268687b63aSAl Viro __be32 *p; 3327409924e4STrond Myklebust int ret = 0; 33281da177e4SLinus Torvalds 33291da177e4SLinus Torvalds *change = 0; 33301da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U))) 33311da177e4SLinus Torvalds return -EIO; 33321da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) { 3333c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3334c0eae66eSBenny Halevy if (unlikely(!p)) 3335eb72f484SChuck Lever return -EIO; 3336cccddf4fSBenny Halevy xdr_decode_hyper(p, change); 33371da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_CHANGE; 3338409924e4STrond Myklebust ret = NFS_ATTR_FATTR_CHANGE; 33391da177e4SLinus Torvalds } 33403110ff80SHarvey Harrison dprintk("%s: change attribute=%Lu\n", __func__, 33411da177e4SLinus Torvalds (unsigned long long)*change); 3342409924e4STrond Myklebust return ret; 33431da177e4SLinus Torvalds } 33441da177e4SLinus Torvalds 33451da177e4SLinus Torvalds static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) 33461da177e4SLinus Torvalds { 33478687b63aSAl Viro __be32 *p; 3348409924e4STrond Myklebust int ret = 0; 33491da177e4SLinus Torvalds 33501da177e4SLinus Torvalds *size = 0; 33511da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U))) 33521da177e4SLinus Torvalds return -EIO; 33531da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) { 3354c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3355c0eae66eSBenny Halevy if (unlikely(!p)) 3356eb72f484SChuck Lever return -EIO; 3357cccddf4fSBenny Halevy xdr_decode_hyper(p, size); 33581da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SIZE; 3359409924e4STrond Myklebust ret = NFS_ATTR_FATTR_SIZE; 33601da177e4SLinus Torvalds } 33613110ff80SHarvey Harrison dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size); 3362409924e4STrond Myklebust return ret; 33631da177e4SLinus Torvalds } 33641da177e4SLinus Torvalds 33651da177e4SLinus Torvalds static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 33661da177e4SLinus Torvalds { 33678687b63aSAl Viro __be32 *p; 33681da177e4SLinus Torvalds 33691da177e4SLinus Torvalds *res = 0; 33701da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U))) 33711da177e4SLinus Torvalds return -EIO; 33721da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) { 3373c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3374c0eae66eSBenny Halevy if (unlikely(!p)) 3375eb72f484SChuck Lever return -EIO; 3376cccddf4fSBenny Halevy *res = be32_to_cpup(p); 33771da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT; 33781da177e4SLinus Torvalds } 33793110ff80SHarvey Harrison dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true"); 33801da177e4SLinus Torvalds return 0; 33811da177e4SLinus Torvalds } 33821da177e4SLinus Torvalds 33831da177e4SLinus Torvalds static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 33841da177e4SLinus Torvalds { 33858687b63aSAl Viro __be32 *p; 33861da177e4SLinus Torvalds 33871da177e4SLinus Torvalds *res = 0; 33881da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U))) 33891da177e4SLinus Torvalds return -EIO; 33901da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) { 3391c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3392c0eae66eSBenny Halevy if (unlikely(!p)) 3393eb72f484SChuck Lever return -EIO; 3394cccddf4fSBenny Halevy *res = be32_to_cpup(p); 33951da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT; 33961da177e4SLinus Torvalds } 33973110ff80SHarvey Harrison dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true"); 33981da177e4SLinus Torvalds return 0; 33991da177e4SLinus Torvalds } 34001da177e4SLinus Torvalds 34018b4bdcf8STrond Myklebust static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) 34021da177e4SLinus Torvalds { 34038687b63aSAl Viro __be32 *p; 3404409924e4STrond Myklebust int ret = 0; 34051da177e4SLinus Torvalds 34061da177e4SLinus Torvalds fsid->major = 0; 34071da177e4SLinus Torvalds fsid->minor = 0; 34081da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U))) 34091da177e4SLinus Torvalds return -EIO; 34101da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FSID)) { 3411c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 16); 3412c0eae66eSBenny Halevy if (unlikely(!p)) 3413eb72f484SChuck Lever return -EIO; 34143ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &fsid->major); 3415cccddf4fSBenny Halevy xdr_decode_hyper(p, &fsid->minor); 34161da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FSID; 3417409924e4STrond Myklebust ret = NFS_ATTR_FATTR_FSID; 34181da177e4SLinus Torvalds } 34193110ff80SHarvey Harrison dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__, 34201da177e4SLinus Torvalds (unsigned long long)fsid->major, 34211da177e4SLinus Torvalds (unsigned long long)fsid->minor); 3422409924e4STrond Myklebust return ret; 34231da177e4SLinus Torvalds } 34241da177e4SLinus Torvalds 34251da177e4SLinus Torvalds static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 34261da177e4SLinus Torvalds { 34278687b63aSAl Viro __be32 *p; 34281da177e4SLinus Torvalds 34291da177e4SLinus Torvalds *res = 60; 34301da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U))) 34311da177e4SLinus Torvalds return -EIO; 34321da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) { 3433c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3434c0eae66eSBenny Halevy if (unlikely(!p)) 3435eb72f484SChuck Lever return -EIO; 3436cccddf4fSBenny Halevy *res = be32_to_cpup(p); 34371da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME; 34381da177e4SLinus Torvalds } 34392eaf426dSDonald Buczek dprintk("%s: lease time=%u\n", __func__, (unsigned int)*res); 34401da177e4SLinus Torvalds return 0; 34411da177e4SLinus Torvalds } 34421da177e4SLinus Torvalds 3443ee7b75fcSTrond Myklebust static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res) 3444ae42c70aSBryan Schumaker { 3445ae42c70aSBryan Schumaker __be32 *p; 3446ae42c70aSBryan Schumaker 3447ae42c70aSBryan Schumaker if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U))) 3448ae42c70aSBryan Schumaker return -EIO; 3449ae42c70aSBryan Schumaker if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) { 3450ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, 4); 3451ae42c70aSBryan Schumaker if (unlikely(!p)) 3452eb72f484SChuck Lever return -EIO; 3453ae42c70aSBryan Schumaker bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; 3454ee7b75fcSTrond Myklebust *res = -be32_to_cpup(p); 3455ae42c70aSBryan Schumaker } 3456ae42c70aSBryan Schumaker return 0; 3457ae42c70aSBryan Schumaker } 3458ae42c70aSBryan Schumaker 34598c61282fSKinglong Mee static int decode_attr_exclcreat_supported(struct xdr_stream *xdr, 34608c61282fSKinglong Mee uint32_t *bitmap, uint32_t *bitmask) 34618c61282fSKinglong Mee { 34628c61282fSKinglong Mee if (likely(bitmap[2] & FATTR4_WORD2_SUPPATTR_EXCLCREAT)) { 34638c61282fSKinglong Mee int ret; 34648c61282fSKinglong Mee ret = decode_attr_bitmap(xdr, bitmask); 34658c61282fSKinglong Mee if (unlikely(ret < 0)) 34668c61282fSKinglong Mee return ret; 34678c61282fSKinglong Mee bitmap[2] &= ~FATTR4_WORD2_SUPPATTR_EXCLCREAT; 34688c61282fSKinglong Mee } else 34698c61282fSKinglong Mee bitmask[0] = bitmask[1] = bitmask[2] = 0; 34708c61282fSKinglong Mee dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__, 34718c61282fSKinglong Mee bitmask[0], bitmask[1], bitmask[2]); 34728c61282fSKinglong Mee return 0; 34738c61282fSKinglong Mee } 34748c61282fSKinglong Mee 3475ae42c70aSBryan Schumaker static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh) 3476ae42c70aSBryan Schumaker { 3477ae42c70aSBryan Schumaker __be32 *p; 347886bbd742SFrank Sorenson u32 len; 3479ae42c70aSBryan Schumaker 34807ad07353STrond Myklebust if (fh != NULL) 3481ae42c70aSBryan Schumaker memset(fh, 0, sizeof(*fh)); 3482ae42c70aSBryan Schumaker 3483ae42c70aSBryan Schumaker if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U))) 3484ae42c70aSBryan Schumaker return -EIO; 3485ae42c70aSBryan Schumaker if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) { 3486ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, 4); 3487ae42c70aSBryan Schumaker if (unlikely(!p)) 3488eb72f484SChuck Lever return -EIO; 3489ae42c70aSBryan Schumaker len = be32_to_cpup(p); 3490ae42c70aSBryan Schumaker if (len > NFS4_FHSIZE) 3491ae42c70aSBryan Schumaker return -EIO; 3492ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, len); 3493ae42c70aSBryan Schumaker if (unlikely(!p)) 3494eb72f484SChuck Lever return -EIO; 34957ad07353STrond Myklebust if (fh != NULL) { 3496ae42c70aSBryan Schumaker memcpy(fh->data, p, len); 34977ad07353STrond Myklebust fh->size = len; 34987ad07353STrond Myklebust } 3499ae42c70aSBryan Schumaker bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE; 3500ae42c70aSBryan Schumaker } 3501ae42c70aSBryan Schumaker return 0; 3502ae42c70aSBryan Schumaker } 3503ae42c70aSBryan Schumaker 35041da177e4SLinus Torvalds static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 35051da177e4SLinus Torvalds { 35068687b63aSAl Viro __be32 *p; 35071da177e4SLinus Torvalds 3508a1800acaSMalahal Naineni *res = 0; 35091da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U))) 35101da177e4SLinus Torvalds return -EIO; 35111da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { 3512c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3513c0eae66eSBenny Halevy if (unlikely(!p)) 3514eb72f484SChuck Lever return -EIO; 3515cccddf4fSBenny Halevy *res = be32_to_cpup(p); 35161da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT; 35171da177e4SLinus Torvalds } 35183110ff80SHarvey Harrison dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res); 35191da177e4SLinus Torvalds return 0; 35201da177e4SLinus Torvalds } 35211da177e4SLinus Torvalds 35221da177e4SLinus Torvalds static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) 35231da177e4SLinus Torvalds { 35248687b63aSAl Viro __be32 *p; 3525409924e4STrond Myklebust int ret = 0; 35261da177e4SLinus Torvalds 35271da177e4SLinus Torvalds *fileid = 0; 35281da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U))) 35291da177e4SLinus Torvalds return -EIO; 35301da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) { 3531c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3532c0eae66eSBenny Halevy if (unlikely(!p)) 3533eb72f484SChuck Lever return -EIO; 3534cccddf4fSBenny Halevy xdr_decode_hyper(p, fileid); 35351da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILEID; 3536409924e4STrond Myklebust ret = NFS_ATTR_FATTR_FILEID; 35371da177e4SLinus Torvalds } 35383110ff80SHarvey Harrison dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); 3539409924e4STrond Myklebust return ret; 35401da177e4SLinus Torvalds } 35411da177e4SLinus Torvalds 354299baf625SManoj Naik static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) 354399baf625SManoj Naik { 35448687b63aSAl Viro __be32 *p; 3545409924e4STrond Myklebust int ret = 0; 354699baf625SManoj Naik 354799baf625SManoj Naik *fileid = 0; 354899baf625SManoj Naik if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U))) 354999baf625SManoj Naik return -EIO; 355099baf625SManoj Naik if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) { 3551c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3552c0eae66eSBenny Halevy if (unlikely(!p)) 3553eb72f484SChuck Lever return -EIO; 3554cccddf4fSBenny Halevy xdr_decode_hyper(p, fileid); 355599baf625SManoj Naik bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; 355628331a46STrond Myklebust ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID; 355799baf625SManoj Naik } 35583110ff80SHarvey Harrison dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); 3559409924e4STrond Myklebust return ret; 356099baf625SManoj Naik } 356199baf625SManoj Naik 35621da177e4SLinus Torvalds static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 35631da177e4SLinus Torvalds { 35648687b63aSAl Viro __be32 *p; 35651da177e4SLinus Torvalds int status = 0; 35661da177e4SLinus Torvalds 35671da177e4SLinus Torvalds *res = 0; 35681da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U))) 35691da177e4SLinus Torvalds return -EIO; 35701da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) { 3571c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3572c0eae66eSBenny Halevy if (unlikely(!p)) 3573eb72f484SChuck Lever return -EIO; 3574cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 35751da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL; 35761da177e4SLinus Torvalds } 35773110ff80SHarvey Harrison dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res); 35781da177e4SLinus Torvalds return status; 35791da177e4SLinus Torvalds } 35801da177e4SLinus Torvalds 35811da177e4SLinus Torvalds static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 35821da177e4SLinus Torvalds { 35838687b63aSAl Viro __be32 *p; 35841da177e4SLinus Torvalds int status = 0; 35851da177e4SLinus Torvalds 35861da177e4SLinus Torvalds *res = 0; 35871da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U))) 35881da177e4SLinus Torvalds return -EIO; 35891da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) { 3590c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3591c0eae66eSBenny Halevy if (unlikely(!p)) 3592eb72f484SChuck Lever return -EIO; 3593cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 35941da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_FREE; 35951da177e4SLinus Torvalds } 35963110ff80SHarvey Harrison dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res); 35971da177e4SLinus Torvalds return status; 35981da177e4SLinus Torvalds } 35991da177e4SLinus Torvalds 36001da177e4SLinus Torvalds static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 36011da177e4SLinus Torvalds { 36028687b63aSAl Viro __be32 *p; 36031da177e4SLinus Torvalds int status = 0; 36041da177e4SLinus Torvalds 36051da177e4SLinus Torvalds *res = 0; 36061da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U))) 36071da177e4SLinus Torvalds return -EIO; 36081da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) { 3609c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3610c0eae66eSBenny Halevy if (unlikely(!p)) 3611eb72f484SChuck Lever return -EIO; 3612cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 36131da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL; 36141da177e4SLinus Torvalds } 36153110ff80SHarvey Harrison dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res); 36161da177e4SLinus Torvalds return status; 36171da177e4SLinus Torvalds } 36181da177e4SLinus Torvalds 36197aaa0b3bSManoj Naik static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) 36207aaa0b3bSManoj Naik { 3621464ad6b1SChuck Lever u32 n; 36228687b63aSAl Viro __be32 *p; 36237aaa0b3bSManoj Naik int status = 0; 36247aaa0b3bSManoj Naik 3625c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3626c0eae66eSBenny Halevy if (unlikely(!p)) 3627eb72f484SChuck Lever return -EIO; 3628cccddf4fSBenny Halevy n = be32_to_cpup(p); 362933a43f28SAndy Adamson if (n == 0) 363033a43f28SAndy Adamson goto root_path; 363102a2976cSChuck Lever dprintk("pathname4: "); 3632809b426cSTrond Myklebust if (n > NFS4_PATHNAME_MAXCOMPONENTS) { 3633809b426cSTrond Myklebust dprintk("cannot parse %d components in path\n", n); 3634809b426cSTrond Myklebust goto out_eio; 3635809b426cSTrond Myklebust } 3636809b426cSTrond Myklebust for (path->ncomponents = 0; path->ncomponents < n; path->ncomponents++) { 36377aaa0b3bSManoj Naik struct nfs4_string *component = &path->components[path->ncomponents]; 36387aaa0b3bSManoj Naik status = decode_opaque_inline(xdr, &component->len, &component->data); 36397aaa0b3bSManoj Naik if (unlikely(status != 0)) 36407aaa0b3bSManoj Naik goto out_eio; 364195a13f7bSTrond Myklebust ifdebug (XDR) 364202a2976cSChuck Lever pr_cont("%s%.*s ", 364302a2976cSChuck Lever (path->ncomponents != n ? "/ " : ""), 364402a2976cSChuck Lever component->len, component->data); 36457aaa0b3bSManoj Naik } 36467aaa0b3bSManoj Naik out: 36477aaa0b3bSManoj Naik return status; 364833a43f28SAndy Adamson root_path: 364933a43f28SAndy Adamson /* a root pathname is sent as a zero component4 */ 365033a43f28SAndy Adamson path->ncomponents = 1; 365133a43f28SAndy Adamson path->components[0].len=0; 365233a43f28SAndy Adamson path->components[0].data=NULL; 365302a2976cSChuck Lever dprintk("pathname4: /\n"); 365433a43f28SAndy Adamson goto out; 36557aaa0b3bSManoj Naik out_eio: 36567aaa0b3bSManoj Naik dprintk(" status %d", status); 36577aaa0b3bSManoj Naik status = -EIO; 36587aaa0b3bSManoj Naik goto out; 36597aaa0b3bSManoj Naik } 36607aaa0b3bSManoj Naik 36617aaa0b3bSManoj Naik static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) 3662683b57b4STrond Myklebust { 3663683b57b4STrond Myklebust int n; 36648687b63aSAl Viro __be32 *p; 3665683b57b4STrond Myklebust int status = -EIO; 3666683b57b4STrond Myklebust 3667683b57b4STrond Myklebust if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U))) 3668683b57b4STrond Myklebust goto out; 3669683b57b4STrond Myklebust status = 0; 3670683b57b4STrond Myklebust if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) 3671683b57b4STrond Myklebust goto out; 3672f54423a1SKinglong Mee bitmap[0] &= ~FATTR4_WORD0_FS_LOCATIONS; 36738b7e3f49STrond Myklebust status = -EIO; 36748b7e3f49STrond Myklebust /* Ignore borken servers that return unrequested attrs */ 36758b7e3f49STrond Myklebust if (unlikely(res == NULL)) 36768b7e3f49STrond Myklebust goto out; 367702a2976cSChuck Lever dprintk("%s: fsroot:\n", __func__); 36787aaa0b3bSManoj Naik status = decode_pathname(xdr, &res->fs_path); 3679683b57b4STrond Myklebust if (unlikely(status != 0)) 3680683b57b4STrond Myklebust goto out; 3681c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3682c0eae66eSBenny Halevy if (unlikely(!p)) 3683eb72f484SChuck Lever goto out_eio; 3684cccddf4fSBenny Halevy n = be32_to_cpup(p); 3685683b57b4STrond Myklebust if (n <= 0) 3686683b57b4STrond Myklebust goto out_eio; 3687809b426cSTrond Myklebust for (res->nlocations = 0; res->nlocations < n; res->nlocations++) { 3688464ad6b1SChuck Lever u32 m; 3689809b426cSTrond Myklebust struct nfs4_fs_location *loc; 3690683b57b4STrond Myklebust 3691809b426cSTrond Myklebust if (res->nlocations == NFS4_FS_LOCATIONS_MAXENTRIES) 3692809b426cSTrond Myklebust break; 3693809b426cSTrond Myklebust loc = &res->locations[res->nlocations]; 3694c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3695c0eae66eSBenny Halevy if (unlikely(!p)) 3696eb72f484SChuck Lever goto out_eio; 3697cccddf4fSBenny Halevy m = be32_to_cpup(p); 36987aaa0b3bSManoj Naik 369902a2976cSChuck Lever dprintk("%s: servers:\n", __func__); 3700809b426cSTrond Myklebust for (loc->nservers = 0; loc->nservers < m; loc->nservers++) { 3701809b426cSTrond Myklebust struct nfs4_string *server; 3702809b426cSTrond Myklebust 3703809b426cSTrond Myklebust if (loc->nservers == NFS4_FS_LOCATION_MAXSERVERS) { 3704464ad6b1SChuck Lever unsigned int i; 3705464ad6b1SChuck Lever dprintk("%s: using first %u of %u servers " 3706464ad6b1SChuck Lever "returned for location %u\n", 37073110ff80SHarvey Harrison __func__, 3708464ad6b1SChuck Lever NFS4_FS_LOCATION_MAXSERVERS, 3709464ad6b1SChuck Lever m, res->nlocations); 37107aaa0b3bSManoj Naik for (i = loc->nservers; i < m; i++) { 37112e42c3e2STrond Myklebust unsigned int len; 37127aaa0b3bSManoj Naik char *data; 37137aaa0b3bSManoj Naik status = decode_opaque_inline(xdr, &len, &data); 3714683b57b4STrond Myklebust if (unlikely(status != 0)) 3715683b57b4STrond Myklebust goto out_eio; 37167aaa0b3bSManoj Naik } 3717809b426cSTrond Myklebust break; 37187aaa0b3bSManoj Naik } 3719809b426cSTrond Myklebust server = &loc->servers[loc->nservers]; 3720809b426cSTrond Myklebust status = decode_opaque_inline(xdr, &server->len, &server->data); 3721809b426cSTrond Myklebust if (unlikely(status != 0)) 3722809b426cSTrond Myklebust goto out_eio; 3723809b426cSTrond Myklebust dprintk("%s ", server->data); 37247aaa0b3bSManoj Naik } 37257aaa0b3bSManoj Naik status = decode_pathname(xdr, &loc->rootpath); 37267aaa0b3bSManoj Naik if (unlikely(status != 0)) 37277aaa0b3bSManoj Naik goto out_eio; 3728683b57b4STrond Myklebust } 3729409924e4STrond Myklebust if (res->nlocations != 0) 373081934ddbSChuck Lever status = NFS_ATTR_FATTR_V4_LOCATIONS; 3731683b57b4STrond Myklebust out: 37323110ff80SHarvey Harrison dprintk("%s: fs_locations done, error = %d\n", __func__, status); 3733683b57b4STrond Myklebust return status; 3734683b57b4STrond Myklebust out_eio: 3735683b57b4STrond Myklebust status = -EIO; 3736683b57b4STrond Myklebust goto out; 3737683b57b4STrond Myklebust } 3738683b57b4STrond Myklebust 37391da177e4SLinus Torvalds static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 37401da177e4SLinus Torvalds { 37418687b63aSAl Viro __be32 *p; 37421da177e4SLinus Torvalds int status = 0; 37431da177e4SLinus Torvalds 37441da177e4SLinus Torvalds *res = 0; 37451da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U))) 37461da177e4SLinus Torvalds return -EIO; 37471da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) { 3748c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3749c0eae66eSBenny Halevy if (unlikely(!p)) 3750eb72f484SChuck Lever return -EIO; 3751cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 37521da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE; 37531da177e4SLinus Torvalds } 37543110ff80SHarvey Harrison dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res); 37551da177e4SLinus Torvalds return status; 37561da177e4SLinus Torvalds } 37571da177e4SLinus Torvalds 37581da177e4SLinus Torvalds static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink) 37591da177e4SLinus Torvalds { 37608687b63aSAl Viro __be32 *p; 37611da177e4SLinus Torvalds int status = 0; 37621da177e4SLinus Torvalds 37631da177e4SLinus Torvalds *maxlink = 1; 37641da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U))) 37651da177e4SLinus Torvalds return -EIO; 37661da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) { 3767c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3768c0eae66eSBenny Halevy if (unlikely(!p)) 3769eb72f484SChuck Lever return -EIO; 3770cccddf4fSBenny Halevy *maxlink = be32_to_cpup(p); 37711da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXLINK; 37721da177e4SLinus Torvalds } 37733110ff80SHarvey Harrison dprintk("%s: maxlink=%u\n", __func__, *maxlink); 37741da177e4SLinus Torvalds return status; 37751da177e4SLinus Torvalds } 37761da177e4SLinus Torvalds 37771da177e4SLinus Torvalds static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname) 37781da177e4SLinus Torvalds { 37798687b63aSAl Viro __be32 *p; 37801da177e4SLinus Torvalds int status = 0; 37811da177e4SLinus Torvalds 37821da177e4SLinus Torvalds *maxname = 1024; 37831da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U))) 37841da177e4SLinus Torvalds return -EIO; 37851da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) { 3786c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3787c0eae66eSBenny Halevy if (unlikely(!p)) 3788eb72f484SChuck Lever return -EIO; 3789cccddf4fSBenny Halevy *maxname = be32_to_cpup(p); 37901da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXNAME; 37911da177e4SLinus Torvalds } 37923110ff80SHarvey Harrison dprintk("%s: maxname=%u\n", __func__, *maxname); 37931da177e4SLinus Torvalds return status; 37941da177e4SLinus Torvalds } 37951da177e4SLinus Torvalds 37961da177e4SLinus Torvalds static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 37971da177e4SLinus Torvalds { 37988687b63aSAl Viro __be32 *p; 37991da177e4SLinus Torvalds int status = 0; 38001da177e4SLinus Torvalds 38011da177e4SLinus Torvalds *res = 1024; 38021da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U))) 38031da177e4SLinus Torvalds return -EIO; 38041da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) { 38051da177e4SLinus Torvalds uint64_t maxread; 3806c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3807c0eae66eSBenny Halevy if (unlikely(!p)) 3808eb72f484SChuck Lever return -EIO; 3809cccddf4fSBenny Halevy xdr_decode_hyper(p, &maxread); 38101da177e4SLinus Torvalds if (maxread > 0x7FFFFFFF) 38111da177e4SLinus Torvalds maxread = 0x7FFFFFFF; 38121da177e4SLinus Torvalds *res = (uint32_t)maxread; 38131da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXREAD; 38141da177e4SLinus Torvalds } 38153110ff80SHarvey Harrison dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res); 38161da177e4SLinus Torvalds return status; 38171da177e4SLinus Torvalds } 38181da177e4SLinus Torvalds 38191da177e4SLinus Torvalds static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 38201da177e4SLinus Torvalds { 38218687b63aSAl Viro __be32 *p; 38221da177e4SLinus Torvalds int status = 0; 38231da177e4SLinus Torvalds 38241da177e4SLinus Torvalds *res = 1024; 38251da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U))) 38261da177e4SLinus Torvalds return -EIO; 38271da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) { 38281da177e4SLinus Torvalds uint64_t maxwrite; 3829c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3830c0eae66eSBenny Halevy if (unlikely(!p)) 3831eb72f484SChuck Lever return -EIO; 3832cccddf4fSBenny Halevy xdr_decode_hyper(p, &maxwrite); 38331da177e4SLinus Torvalds if (maxwrite > 0x7FFFFFFF) 38341da177e4SLinus Torvalds maxwrite = 0x7FFFFFFF; 38351da177e4SLinus Torvalds *res = (uint32_t)maxwrite; 38361da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXWRITE; 38371da177e4SLinus Torvalds } 38383110ff80SHarvey Harrison dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res); 38391da177e4SLinus Torvalds return status; 38401da177e4SLinus Torvalds } 38411da177e4SLinus Torvalds 3842bca79478STrond Myklebust static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode) 38431da177e4SLinus Torvalds { 3844bca79478STrond Myklebust uint32_t tmp; 38458687b63aSAl Viro __be32 *p; 3846409924e4STrond Myklebust int ret = 0; 38471da177e4SLinus Torvalds 38481da177e4SLinus Torvalds *mode = 0; 38491da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U))) 38501da177e4SLinus Torvalds return -EIO; 38511da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_MODE)) { 3852c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3853c0eae66eSBenny Halevy if (unlikely(!p)) 3854eb72f484SChuck Lever return -EIO; 3855cccddf4fSBenny Halevy tmp = be32_to_cpup(p); 3856bca79478STrond Myklebust *mode = tmp & ~S_IFMT; 38571da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_MODE; 3858409924e4STrond Myklebust ret = NFS_ATTR_FATTR_MODE; 38591da177e4SLinus Torvalds } 38603110ff80SHarvey Harrison dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode); 3861409924e4STrond Myklebust return ret; 38621da177e4SLinus Torvalds } 38631da177e4SLinus Torvalds 38641da177e4SLinus Torvalds static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) 38651da177e4SLinus Torvalds { 38668687b63aSAl Viro __be32 *p; 3867409924e4STrond Myklebust int ret = 0; 38681da177e4SLinus Torvalds 38691da177e4SLinus Torvalds *nlink = 1; 38701da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U))) 38711da177e4SLinus Torvalds return -EIO; 38721da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) { 3873c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3874c0eae66eSBenny Halevy if (unlikely(!p)) 3875eb72f484SChuck Lever return -EIO; 3876cccddf4fSBenny Halevy *nlink = be32_to_cpup(p); 38771da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_NUMLINKS; 3878409924e4STrond Myklebust ret = NFS_ATTR_FATTR_NLINK; 38791da177e4SLinus Torvalds } 38803110ff80SHarvey Harrison dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink); 3881409924e4STrond Myklebust return ret; 38821da177e4SLinus Torvalds } 38831da177e4SLinus Torvalds 3884686a816aSTrond Myklebust static ssize_t decode_nfs4_string(struct xdr_stream *xdr, 3885686a816aSTrond Myklebust struct nfs4_string *name, gfp_t gfp_flags) 3886686a816aSTrond Myklebust { 3887686a816aSTrond Myklebust ssize_t ret; 3888686a816aSTrond Myklebust 3889686a816aSTrond Myklebust ret = xdr_stream_decode_string_dup(xdr, &name->data, 3890686a816aSTrond Myklebust XDR_MAX_NETOBJ, gfp_flags); 3891686a816aSTrond Myklebust name->len = 0; 3892686a816aSTrond Myklebust if (ret > 0) 3893686a816aSTrond Myklebust name->len = ret; 3894686a816aSTrond Myklebust return ret; 3895686a816aSTrond Myklebust } 3896686a816aSTrond Myklebust 389780e52aceSTrond Myklebust static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, 3898e5782076SEric W. Biederman const struct nfs_server *server, kuid_t *uid, 38996926afd1STrond Myklebust struct nfs4_string *owner_name) 39001da177e4SLinus Torvalds { 3901686a816aSTrond Myklebust ssize_t len; 3902686a816aSTrond Myklebust char *p; 39031da177e4SLinus Torvalds 3904e5782076SEric W. Biederman *uid = make_kuid(&init_user_ns, -2); 39051da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U))) 39061da177e4SLinus Torvalds return -EIO; 3907686a816aSTrond Myklebust if (!(bitmap[1] & FATTR4_WORD1_OWNER)) 3908686a816aSTrond Myklebust return 0; 39091da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_OWNER; 3910686a816aSTrond Myklebust 3911686a816aSTrond Myklebust if (owner_name != NULL) { 3912e8d8aa46STrond Myklebust len = decode_nfs4_string(xdr, owner_name, GFP_NOIO); 3913686a816aSTrond Myklebust if (len <= 0) 3914686a816aSTrond Myklebust goto out; 3915686a816aSTrond Myklebust dprintk("%s: name=%s\n", __func__, owner_name->data); 3916686a816aSTrond Myklebust return NFS_ATTR_FATTR_OWNER_NAME; 3917686a816aSTrond Myklebust } else { 3918686a816aSTrond Myklebust len = xdr_stream_decode_opaque_inline(xdr, (void **)&p, 3919686a816aSTrond Myklebust XDR_MAX_NETOBJ); 3920686a816aSTrond Myklebust if (len <= 0 || nfs_map_name_to_uid(server, p, len, uid) != 0) 3921686a816aSTrond Myklebust goto out; 3922e5782076SEric W. Biederman dprintk("%s: uid=%d\n", __func__, (int)from_kuid(&init_user_ns, *uid)); 3923686a816aSTrond Myklebust return NFS_ATTR_FATTR_OWNER; 3924686a816aSTrond Myklebust } 3925686a816aSTrond Myklebust out: 3926eb72f484SChuck Lever if (len == -EBADMSG) 3927c0eae66eSBenny Halevy return -EIO; 3928eb72f484SChuck Lever return 0; 39291da177e4SLinus Torvalds } 39301da177e4SLinus Torvalds 393180e52aceSTrond Myklebust static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, 3932e5782076SEric W. Biederman const struct nfs_server *server, kgid_t *gid, 39336926afd1STrond Myklebust struct nfs4_string *group_name) 39341da177e4SLinus Torvalds { 3935686a816aSTrond Myklebust ssize_t len; 3936686a816aSTrond Myklebust char *p; 39371da177e4SLinus Torvalds 3938e5782076SEric W. Biederman *gid = make_kgid(&init_user_ns, -2); 39391da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U))) 39401da177e4SLinus Torvalds return -EIO; 3941686a816aSTrond Myklebust if (!(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) 3942686a816aSTrond Myklebust return 0; 39431da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP; 3944686a816aSTrond Myklebust 3945686a816aSTrond Myklebust if (group_name != NULL) { 3946e8d8aa46STrond Myklebust len = decode_nfs4_string(xdr, group_name, GFP_NOIO); 3947686a816aSTrond Myklebust if (len <= 0) 3948686a816aSTrond Myklebust goto out; 3949686a816aSTrond Myklebust dprintk("%s: name=%s\n", __func__, group_name->data); 39506f1f6220SKinglong Mee return NFS_ATTR_FATTR_GROUP_NAME; 3951686a816aSTrond Myklebust } else { 3952686a816aSTrond Myklebust len = xdr_stream_decode_opaque_inline(xdr, (void **)&p, 3953686a816aSTrond Myklebust XDR_MAX_NETOBJ); 3954686a816aSTrond Myklebust if (len <= 0 || nfs_map_group_to_gid(server, p, len, gid) != 0) 3955686a816aSTrond Myklebust goto out; 3956e5782076SEric W. Biederman dprintk("%s: gid=%d\n", __func__, (int)from_kgid(&init_user_ns, *gid)); 3957686a816aSTrond Myklebust return NFS_ATTR_FATTR_GROUP; 3958686a816aSTrond Myklebust } 3959686a816aSTrond Myklebust out: 3960eb72f484SChuck Lever if (len == -EBADMSG) 3961c0eae66eSBenny Halevy return -EIO; 3962eb72f484SChuck Lever return 0; 39631da177e4SLinus Torvalds } 39641da177e4SLinus Torvalds 39651da177e4SLinus Torvalds static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) 39661da177e4SLinus Torvalds { 39678687b63aSAl Viro uint32_t major = 0, minor = 0; 39688687b63aSAl Viro __be32 *p; 3969409924e4STrond Myklebust int ret = 0; 39701da177e4SLinus Torvalds 39711da177e4SLinus Torvalds *rdev = MKDEV(0,0); 39721da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U))) 39731da177e4SLinus Torvalds return -EIO; 39741da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) { 39751da177e4SLinus Torvalds dev_t tmp; 39761da177e4SLinus Torvalds 3977c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3978c0eae66eSBenny Halevy if (unlikely(!p)) 3979eb72f484SChuck Lever return -EIO; 39806f723f77SBenny Halevy major = be32_to_cpup(p++); 3981cccddf4fSBenny Halevy minor = be32_to_cpup(p); 39821da177e4SLinus Torvalds tmp = MKDEV(major, minor); 39831da177e4SLinus Torvalds if (MAJOR(tmp) == major && MINOR(tmp) == minor) 39841da177e4SLinus Torvalds *rdev = tmp; 39851da177e4SLinus Torvalds bitmap[1] &= ~ FATTR4_WORD1_RAWDEV; 3986409924e4STrond Myklebust ret = NFS_ATTR_FATTR_RDEV; 39871da177e4SLinus Torvalds } 39883110ff80SHarvey Harrison dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor); 3989409924e4STrond Myklebust return ret; 39901da177e4SLinus Torvalds } 39911da177e4SLinus Torvalds 39921da177e4SLinus Torvalds static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 39931da177e4SLinus Torvalds { 39948687b63aSAl Viro __be32 *p; 39951da177e4SLinus Torvalds int status = 0; 39961da177e4SLinus Torvalds 39971da177e4SLinus Torvalds *res = 0; 39981da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U))) 39991da177e4SLinus Torvalds return -EIO; 40001da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) { 4001c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4002c0eae66eSBenny Halevy if (unlikely(!p)) 4003eb72f484SChuck Lever return -EIO; 4004cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 40051da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL; 40061da177e4SLinus Torvalds } 40073110ff80SHarvey Harrison dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res); 40081da177e4SLinus Torvalds return status; 40091da177e4SLinus Torvalds } 40101da177e4SLinus Torvalds 40111da177e4SLinus Torvalds static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 40121da177e4SLinus Torvalds { 40138687b63aSAl Viro __be32 *p; 40141da177e4SLinus Torvalds int status = 0; 40151da177e4SLinus Torvalds 40161da177e4SLinus Torvalds *res = 0; 40171da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U))) 40181da177e4SLinus Torvalds return -EIO; 40191da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) { 4020c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4021c0eae66eSBenny Halevy if (unlikely(!p)) 4022eb72f484SChuck Lever return -EIO; 4023cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 40241da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE; 40251da177e4SLinus Torvalds } 40263110ff80SHarvey Harrison dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res); 40271da177e4SLinus Torvalds return status; 40281da177e4SLinus Torvalds } 40291da177e4SLinus Torvalds 40301da177e4SLinus Torvalds static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 40311da177e4SLinus Torvalds { 40328687b63aSAl Viro __be32 *p; 40331da177e4SLinus Torvalds int status = 0; 40341da177e4SLinus Torvalds 40351da177e4SLinus Torvalds *res = 0; 40361da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U))) 40371da177e4SLinus Torvalds return -EIO; 40381da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) { 4039c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4040c0eae66eSBenny Halevy if (unlikely(!p)) 4041eb72f484SChuck Lever return -EIO; 4042cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 40431da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL; 40441da177e4SLinus Torvalds } 40453110ff80SHarvey Harrison dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res); 40461da177e4SLinus Torvalds return status; 40471da177e4SLinus Torvalds } 40481da177e4SLinus Torvalds 40491da177e4SLinus Torvalds static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) 40501da177e4SLinus Torvalds { 40518687b63aSAl Viro __be32 *p; 4052409924e4STrond Myklebust int ret = 0; 40531da177e4SLinus Torvalds 40541da177e4SLinus Torvalds *used = 0; 40551da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U))) 40561da177e4SLinus Torvalds return -EIO; 40571da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) { 4058c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4059c0eae66eSBenny Halevy if (unlikely(!p)) 4060eb72f484SChuck Lever return -EIO; 4061cccddf4fSBenny Halevy xdr_decode_hyper(p, used); 40621da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_USED; 4063409924e4STrond Myklebust ret = NFS_ATTR_FATTR_SPACE_USED; 40641da177e4SLinus Torvalds } 40653110ff80SHarvey Harrison dprintk("%s: space used=%Lu\n", __func__, 40661da177e4SLinus Torvalds (unsigned long long)*used); 4067409924e4STrond Myklebust return ret; 40681da177e4SLinus Torvalds } 40691da177e4SLinus Torvalds 407036b3743fSTrond Myklebust static __be32 * 4071e86d5a02STrond Myklebust xdr_decode_nfstime4(__be32 *p, struct timespec64 *t) 407236b3743fSTrond Myklebust { 407336b3743fSTrond Myklebust __u64 sec; 407436b3743fSTrond Myklebust 407536b3743fSTrond Myklebust p = xdr_decode_hyper(p, &sec); 4076e86d5a02STrond Myklebust t-> tv_sec = sec; 407736b3743fSTrond Myklebust t->tv_nsec = be32_to_cpup(p++); 407836b3743fSTrond Myklebust return p; 407936b3743fSTrond Myklebust } 408036b3743fSTrond Myklebust 4081e86d5a02STrond Myklebust static int decode_attr_time(struct xdr_stream *xdr, struct timespec64 *time) 40821da177e4SLinus Torvalds { 40838687b63aSAl Viro __be32 *p; 40841da177e4SLinus Torvalds 408536b3743fSTrond Myklebust p = xdr_inline_decode(xdr, nfstime4_maxsz << 2); 4086c0eae66eSBenny Halevy if (unlikely(!p)) 4087eb72f484SChuck Lever return -EIO; 408836b3743fSTrond Myklebust xdr_decode_nfstime4(p, time); 40891da177e4SLinus Torvalds return 0; 40901da177e4SLinus Torvalds } 40911da177e4SLinus Torvalds 4092e86d5a02STrond Myklebust static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time) 40931da177e4SLinus Torvalds { 40941da177e4SLinus Torvalds int status = 0; 40951da177e4SLinus Torvalds 40961da177e4SLinus Torvalds time->tv_sec = 0; 40971da177e4SLinus Torvalds time->tv_nsec = 0; 40981da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U))) 40991da177e4SLinus Torvalds return -EIO; 41001da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) { 41011da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 4102409924e4STrond Myklebust if (status == 0) 4103409924e4STrond Myklebust status = NFS_ATTR_FATTR_ATIME; 41041da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS; 41051da177e4SLinus Torvalds } 4106ae08483cSArnd Bergmann dprintk("%s: atime=%lld\n", __func__, time->tv_sec); 41071da177e4SLinus Torvalds return status; 41081da177e4SLinus Torvalds } 41091da177e4SLinus Torvalds 4110e86d5a02STrond Myklebust static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time) 41111da177e4SLinus Torvalds { 41121da177e4SLinus Torvalds int status = 0; 41131da177e4SLinus Torvalds 41141da177e4SLinus Torvalds time->tv_sec = 0; 41151da177e4SLinus Torvalds time->tv_nsec = 0; 41161da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U))) 41171da177e4SLinus Torvalds return -EIO; 41181da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) { 41191da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 4120409924e4STrond Myklebust if (status == 0) 4121409924e4STrond Myklebust status = NFS_ATTR_FATTR_CTIME; 41221da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA; 41231da177e4SLinus Torvalds } 4124ae08483cSArnd Bergmann dprintk("%s: ctime=%lld\n", __func__, time->tv_sec); 41251da177e4SLinus Torvalds return status; 41261da177e4SLinus Torvalds } 41271da177e4SLinus Torvalds 412855b6e774SRicardo Labiaga static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, 4129e86d5a02STrond Myklebust struct timespec64 *time) 413055b6e774SRicardo Labiaga { 413155b6e774SRicardo Labiaga int status = 0; 413255b6e774SRicardo Labiaga 413355b6e774SRicardo Labiaga time->tv_sec = 0; 413455b6e774SRicardo Labiaga time->tv_nsec = 0; 413555b6e774SRicardo Labiaga if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U))) 413655b6e774SRicardo Labiaga return -EIO; 413755b6e774SRicardo Labiaga if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) { 413855b6e774SRicardo Labiaga status = decode_attr_time(xdr, time); 413955b6e774SRicardo Labiaga bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA; 414055b6e774SRicardo Labiaga } 4141ae08483cSArnd Bergmann dprintk("%s: time_delta=%lld %ld\n", __func__, time->tv_sec, 4142ae08483cSArnd Bergmann time->tv_nsec); 414355b6e774SRicardo Labiaga return status; 414455b6e774SRicardo Labiaga } 414555b6e774SRicardo Labiaga 4146aa9c2669SDavid Quigley static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, 4147aa9c2669SDavid Quigley struct nfs4_label *label) 4148aa9c2669SDavid Quigley { 4149aa9c2669SDavid Quigley uint32_t pi = 0; 4150aa9c2669SDavid Quigley uint32_t lfs = 0; 4151aa9c2669SDavid Quigley __u32 len; 4152aa9c2669SDavid Quigley __be32 *p; 4153aa9c2669SDavid Quigley int status = 0; 4154aa9c2669SDavid Quigley 4155aa9c2669SDavid Quigley if (unlikely(bitmap[2] & (FATTR4_WORD2_SECURITY_LABEL - 1U))) 4156aa9c2669SDavid Quigley return -EIO; 4157aa9c2669SDavid Quigley if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) { 4158aa9c2669SDavid Quigley p = xdr_inline_decode(xdr, 4); 4159aa9c2669SDavid Quigley if (unlikely(!p)) 4160eb72f484SChuck Lever return -EIO; 4161aa9c2669SDavid Quigley lfs = be32_to_cpup(p++); 4162aa9c2669SDavid Quigley p = xdr_inline_decode(xdr, 4); 4163aa9c2669SDavid Quigley if (unlikely(!p)) 4164eb72f484SChuck Lever return -EIO; 4165aa9c2669SDavid Quigley pi = be32_to_cpup(p++); 4166aa9c2669SDavid Quigley p = xdr_inline_decode(xdr, 4); 4167aa9c2669SDavid Quigley if (unlikely(!p)) 4168eb72f484SChuck Lever return -EIO; 4169aa9c2669SDavid Quigley len = be32_to_cpup(p++); 4170aa9c2669SDavid Quigley p = xdr_inline_decode(xdr, len); 4171aa9c2669SDavid Quigley if (unlikely(!p)) 4172eb72f484SChuck Lever return -EIO; 4173aa9c2669SDavid Quigley if (len < NFS4_MAXLABELLEN) { 4174aa9c2669SDavid Quigley if (label) { 4175b4487b93SJeffrey Mitchell if (label->len) { 4176b4487b93SJeffrey Mitchell if (label->len < len) 4177b4487b93SJeffrey Mitchell return -ERANGE; 4178aa9c2669SDavid Quigley memcpy(label->label, p, len); 4179b4487b93SJeffrey Mitchell } 4180aa9c2669SDavid Quigley label->len = len; 4181aa9c2669SDavid Quigley label->pi = pi; 4182aa9c2669SDavid Quigley label->lfs = lfs; 4183aa9c2669SDavid Quigley status = NFS_ATTR_FATTR_V4_SECURITY_LABEL; 4184aa9c2669SDavid Quigley } 4185aa9c2669SDavid Quigley bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; 4186aa9c2669SDavid Quigley } else 4187aa9c2669SDavid Quigley printk(KERN_WARNING "%s: label too long (%u)!\n", 4188aa9c2669SDavid Quigley __func__, len); 4189aa9c2669SDavid Quigley } 4190aa9c2669SDavid Quigley if (label && label->label) 4191aa9c2669SDavid Quigley dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__, 4192aa9c2669SDavid Quigley (char *)label->label, label->len, label->pi, label->lfs); 4193aa9c2669SDavid Quigley return status; 4194aa9c2669SDavid Quigley } 4195aa9c2669SDavid Quigley 4196e86d5a02STrond Myklebust static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time) 41971da177e4SLinus Torvalds { 41981da177e4SLinus Torvalds int status = 0; 41991da177e4SLinus Torvalds 42001da177e4SLinus Torvalds time->tv_sec = 0; 42011da177e4SLinus Torvalds time->tv_nsec = 0; 42021da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U))) 42031da177e4SLinus Torvalds return -EIO; 42041da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) { 42051da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 4206409924e4STrond Myklebust if (status == 0) 4207409924e4STrond Myklebust status = NFS_ATTR_FATTR_MTIME; 42081da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY; 42091da177e4SLinus Torvalds } 4210ae08483cSArnd Bergmann dprintk("%s: mtime=%lld\n", __func__, time->tv_sec); 42111da177e4SLinus Torvalds return status; 42121da177e4SLinus Torvalds } 42131da177e4SLinus Torvalds 4214b78ef845SFrank van der Linden static int decode_attr_xattrsupport(struct xdr_stream *xdr, uint32_t *bitmap, 4215b78ef845SFrank van der Linden uint32_t *res) 4216b78ef845SFrank van der Linden { 4217b78ef845SFrank van der Linden __be32 *p; 4218b78ef845SFrank van der Linden 4219b78ef845SFrank van der Linden *res = 0; 4220b78ef845SFrank van der Linden if (unlikely(bitmap[2] & (FATTR4_WORD2_XATTR_SUPPORT - 1U))) 4221b78ef845SFrank van der Linden return -EIO; 4222b78ef845SFrank van der Linden if (likely(bitmap[2] & FATTR4_WORD2_XATTR_SUPPORT)) { 4223b78ef845SFrank van der Linden p = xdr_inline_decode(xdr, 4); 4224b78ef845SFrank van der Linden if (unlikely(!p)) 4225b78ef845SFrank van der Linden return -EIO; 4226b78ef845SFrank van der Linden *res = be32_to_cpup(p); 4227b78ef845SFrank van der Linden bitmap[2] &= ~FATTR4_WORD2_XATTR_SUPPORT; 4228b78ef845SFrank van der Linden } 4229b78ef845SFrank van der Linden dprintk("%s: XATTR support=%s\n", __func__, 4230b78ef845SFrank van der Linden *res == 0 ? "false" : "true"); 4231b78ef845SFrank van der Linden return 0; 4232b78ef845SFrank van der Linden } 4233b78ef845SFrank van der Linden 4234256e48bbSTrond Myklebust static int verify_attr_len(struct xdr_stream *xdr, unsigned int savep, uint32_t attrlen) 42351da177e4SLinus Torvalds { 42361da177e4SLinus Torvalds unsigned int attrwords = XDR_QUADLEN(attrlen); 4237256e48bbSTrond Myklebust unsigned int nwords = (xdr_stream_pos(xdr) - savep) >> 2; 42381da177e4SLinus Torvalds 42391da177e4SLinus Torvalds if (unlikely(attrwords != nwords)) { 4240fe82a183SChuck Lever dprintk("%s: server returned incorrect attribute length: " 4241fe82a183SChuck Lever "%u %c %u\n", 42423110ff80SHarvey Harrison __func__, 42431da177e4SLinus Torvalds attrwords << 2, 42441da177e4SLinus Torvalds (attrwords < nwords) ? '<' : '>', 42451da177e4SLinus Torvalds nwords << 2); 42461da177e4SLinus Torvalds return -EIO; 42471da177e4SLinus Torvalds } 42481da177e4SLinus Torvalds return 0; 42491da177e4SLinus Torvalds } 42501da177e4SLinus Torvalds 42511da177e4SLinus Torvalds static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 42521da177e4SLinus Torvalds { 42538687b63aSAl Viro __be32 *p; 42541da177e4SLinus Torvalds 4255c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 20); 4256c0eae66eSBenny Halevy if (unlikely(!p)) 4257eb72f484SChuck Lever return -EIO; 42586f723f77SBenny Halevy cinfo->atomic = be32_to_cpup(p++); 42593ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &cinfo->before); 4260cccddf4fSBenny Halevy xdr_decode_hyper(p, &cinfo->after); 42611da177e4SLinus Torvalds return 0; 42621da177e4SLinus Torvalds } 42631da177e4SLinus Torvalds 42646168f62cSWeston Andros Adamson static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access) 42651da177e4SLinus Torvalds { 42668687b63aSAl Viro __be32 *p; 42671da177e4SLinus Torvalds uint32_t supp, acc; 42681da177e4SLinus Torvalds int status; 42691da177e4SLinus Torvalds 42701da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_ACCESS); 42711da177e4SLinus Torvalds if (status) 42721da177e4SLinus Torvalds return status; 4273c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4274c0eae66eSBenny Halevy if (unlikely(!p)) 4275eb72f484SChuck Lever return -EIO; 42766f723f77SBenny Halevy supp = be32_to_cpup(p++); 4277cccddf4fSBenny Halevy acc = be32_to_cpup(p); 42786168f62cSWeston Andros Adamson *supported = supp; 42796168f62cSWeston Andros Adamson *access = acc; 42801da177e4SLinus Torvalds return 0; 42811da177e4SLinus Torvalds } 42821da177e4SLinus Torvalds 428307d30434SBenny Halevy static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len) 42841da177e4SLinus Torvalds { 4285ab6e9aafSTrond Myklebust ssize_t ret = xdr_stream_decode_opaque_fixed(xdr, buf, len); 4286eb72f484SChuck Lever if (unlikely(ret < 0)) 428707d30434SBenny Halevy return -EIO; 4288ab6e9aafSTrond Myklebust return 0; 4289ab6e9aafSTrond Myklebust } 429007d30434SBenny Halevy 429107d30434SBenny Halevy static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 429207d30434SBenny Halevy { 42932d2f24adSTrond Myklebust return decode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE); 42941da177e4SLinus Torvalds } 42951da177e4SLinus Torvalds 429693b717fdSTrond Myklebust static int decode_open_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 429793b717fdSTrond Myklebust { 429893b717fdSTrond Myklebust stateid->type = NFS4_OPEN_STATEID_TYPE; 429993b717fdSTrond Myklebust return decode_stateid(xdr, stateid); 430093b717fdSTrond Myklebust } 430193b717fdSTrond Myklebust 430293b717fdSTrond Myklebust static int decode_lock_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 430393b717fdSTrond Myklebust { 430493b717fdSTrond Myklebust stateid->type = NFS4_LOCK_STATEID_TYPE; 430593b717fdSTrond Myklebust return decode_stateid(xdr, stateid); 430693b717fdSTrond Myklebust } 430793b717fdSTrond Myklebust 430893b717fdSTrond Myklebust static int decode_delegation_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 430993b717fdSTrond Myklebust { 431093b717fdSTrond Myklebust stateid->type = NFS4_DELEGATION_STATEID_TYPE; 431193b717fdSTrond Myklebust return decode_stateid(xdr, stateid); 431293b717fdSTrond Myklebust } 431393b717fdSTrond Myklebust 4314fcd8843cSTrond Myklebust static int decode_invalid_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 4315fcd8843cSTrond Myklebust { 4316fcd8843cSTrond Myklebust nfs4_stateid dummy; 4317fcd8843cSTrond Myklebust 4318fcd8843cSTrond Myklebust nfs4_stateid_copy(stateid, &invalid_stateid); 4319fcd8843cSTrond Myklebust return decode_stateid(xdr, &dummy); 4320fcd8843cSTrond Myklebust } 4321fcd8843cSTrond Myklebust 43221da177e4SLinus Torvalds static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) 43231da177e4SLinus Torvalds { 43241da177e4SLinus Torvalds int status; 43251da177e4SLinus Torvalds 43261da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_CLOSE); 4327c1d51931STrond Myklebust if (status != -EIO) 4328c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 432907d30434SBenny Halevy if (!status) 4330fcd8843cSTrond Myklebust status = decode_invalid_stateid(xdr, &res->stateid); 43311da177e4SLinus Torvalds return status; 43321da177e4SLinus Torvalds } 43331da177e4SLinus Torvalds 4334db942bbdSBenny Halevy static int decode_verifier(struct xdr_stream *xdr, void *verifier) 4335db942bbdSBenny Halevy { 4336cd93710eSChuck Lever return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE); 43371da177e4SLinus Torvalds } 43381da177e4SLinus Torvalds 43392f2c63bcSTrond Myklebust static int decode_write_verifier(struct xdr_stream *xdr, struct nfs_write_verifier *verifier) 43402f2c63bcSTrond Myklebust { 43412f2c63bcSTrond Myklebust return decode_opaque_fixed(xdr, verifier->data, NFS4_VERIFIER_SIZE); 43422f2c63bcSTrond Myklebust } 43432f2c63bcSTrond Myklebust 43440b7c0153SFred Isaman static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res) 43451da177e4SLinus Torvalds { 4346221203ceSTrond Myklebust struct nfs_writeverf *verf = res->verf; 43471da177e4SLinus Torvalds int status; 43481da177e4SLinus Torvalds 43491da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_COMMIT); 4350db942bbdSBenny Halevy if (!status) 4351221203ceSTrond Myklebust status = decode_write_verifier(xdr, &verf->verifier); 4352221203ceSTrond Myklebust if (!status) 4353221203ceSTrond Myklebust verf->committed = NFS_FILE_SYNC; 43541da177e4SLinus Torvalds return status; 43551da177e4SLinus Torvalds } 43561da177e4SLinus Torvalds 43571da177e4SLinus Torvalds static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 43581da177e4SLinus Torvalds { 43598687b63aSAl Viro __be32 *p; 43601da177e4SLinus Torvalds uint32_t bmlen; 43611da177e4SLinus Torvalds int status; 43621da177e4SLinus Torvalds 43631da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_CREATE); 43641da177e4SLinus Torvalds if (status) 43651da177e4SLinus Torvalds return status; 43661da177e4SLinus Torvalds if ((status = decode_change_info(xdr, cinfo))) 43671da177e4SLinus Torvalds return status; 4368c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4369c0eae66eSBenny Halevy if (unlikely(!p)) 4370eb72f484SChuck Lever return -EIO; 4371cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 4372c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, bmlen << 2); 4373c0eae66eSBenny Halevy if (likely(p)) 43741da177e4SLinus Torvalds return 0; 4375c0eae66eSBenny Halevy return -EIO; 43761da177e4SLinus Torvalds } 43771da177e4SLinus Torvalds 43781da177e4SLinus Torvalds static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) 43791da177e4SLinus Torvalds { 4380256e48bbSTrond Myklebust unsigned int savep; 4381dae100c2SFred Isaman uint32_t attrlen, bitmap[3] = {0}; 43821da177e4SLinus Torvalds int status; 43831da177e4SLinus Torvalds 43841da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 43851da177e4SLinus Torvalds goto xdr_error; 43861da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 43871da177e4SLinus Torvalds goto xdr_error; 43881da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 43891da177e4SLinus Torvalds goto xdr_error; 43901da177e4SLinus Torvalds if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0) 43911da177e4SLinus Torvalds goto xdr_error; 4392264e6351SChuck Lever if ((status = decode_attr_fh_expire_type(xdr, bitmap, 4393264e6351SChuck Lever &res->fh_expire_type)) != 0) 4394264e6351SChuck Lever goto xdr_error; 43951da177e4SLinus Torvalds if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0) 43961da177e4SLinus Torvalds goto xdr_error; 43971da177e4SLinus Torvalds if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0) 43981da177e4SLinus Torvalds goto xdr_error; 43991da177e4SLinus Torvalds if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0) 44001da177e4SLinus Torvalds goto xdr_error; 44018c61282fSKinglong Mee if ((status = decode_attr_exclcreat_supported(xdr, bitmap, 44028c61282fSKinglong Mee res->exclcreat_bitmask)) != 0) 44038c61282fSKinglong Mee goto xdr_error; 44041da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 44051da177e4SLinus Torvalds xdr_error: 44063110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 44071da177e4SLinus Torvalds return status; 44081da177e4SLinus Torvalds } 44091da177e4SLinus Torvalds 44101da177e4SLinus Torvalds static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) 44111da177e4SLinus Torvalds { 4412256e48bbSTrond Myklebust unsigned int savep; 4413dae100c2SFred Isaman uint32_t attrlen, bitmap[3] = {0}; 44141da177e4SLinus Torvalds int status; 44151da177e4SLinus Torvalds 44161da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 44171da177e4SLinus Torvalds goto xdr_error; 44181da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 44191da177e4SLinus Torvalds goto xdr_error; 44201da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 44211da177e4SLinus Torvalds goto xdr_error; 44221da177e4SLinus Torvalds 44231da177e4SLinus Torvalds if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0) 44241da177e4SLinus Torvalds goto xdr_error; 44251da177e4SLinus Torvalds if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0) 44261da177e4SLinus Torvalds goto xdr_error; 44271da177e4SLinus Torvalds if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0) 44281da177e4SLinus Torvalds goto xdr_error; 44291ca843a2SAndreas Gruenbacher 44301ca843a2SAndreas Gruenbacher status = -EIO; 44311ca843a2SAndreas Gruenbacher if (unlikely(bitmap[0])) 44321ca843a2SAndreas Gruenbacher goto xdr_error; 44331ca843a2SAndreas Gruenbacher 44341da177e4SLinus Torvalds if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0) 44351da177e4SLinus Torvalds goto xdr_error; 44361da177e4SLinus Torvalds if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0) 44371da177e4SLinus Torvalds goto xdr_error; 44381da177e4SLinus Torvalds if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0) 44391da177e4SLinus Torvalds goto xdr_error; 44401da177e4SLinus Torvalds 44411da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 44421da177e4SLinus Torvalds xdr_error: 44433110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 44441da177e4SLinus Torvalds return status; 44451da177e4SLinus Torvalds } 44461da177e4SLinus Torvalds 44471da177e4SLinus Torvalds static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) 44481da177e4SLinus Torvalds { 4449256e48bbSTrond Myklebust unsigned int savep; 4450dae100c2SFred Isaman uint32_t attrlen, bitmap[3] = {0}; 44511da177e4SLinus Torvalds int status; 44521da177e4SLinus Torvalds 44531da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 44541da177e4SLinus Torvalds goto xdr_error; 44551da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 44561da177e4SLinus Torvalds goto xdr_error; 44571da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 44581da177e4SLinus Torvalds goto xdr_error; 44591da177e4SLinus Torvalds 44601da177e4SLinus Torvalds if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0) 44611da177e4SLinus Torvalds goto xdr_error; 44621da177e4SLinus Torvalds if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0) 44631da177e4SLinus Torvalds goto xdr_error; 44641da177e4SLinus Torvalds 44651da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 44661da177e4SLinus Torvalds xdr_error: 44673110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 44681da177e4SLinus Torvalds return status; 44691da177e4SLinus Torvalds } 44701da177e4SLinus Torvalds 447188034c3dSAndy Adamson static int decode_threshold_hint(struct xdr_stream *xdr, 447288034c3dSAndy Adamson uint32_t *bitmap, 447388034c3dSAndy Adamson uint64_t *res, 447488034c3dSAndy Adamson uint32_t hint_bit) 447588034c3dSAndy Adamson { 447688034c3dSAndy Adamson __be32 *p; 447788034c3dSAndy Adamson 447888034c3dSAndy Adamson *res = 0; 447988034c3dSAndy Adamson if (likely(bitmap[0] & hint_bit)) { 448088034c3dSAndy Adamson p = xdr_inline_decode(xdr, 8); 448188034c3dSAndy Adamson if (unlikely(!p)) 4482eb72f484SChuck Lever return -EIO; 448388034c3dSAndy Adamson xdr_decode_hyper(p, res); 448488034c3dSAndy Adamson } 448588034c3dSAndy Adamson return 0; 448688034c3dSAndy Adamson } 448788034c3dSAndy Adamson 448888034c3dSAndy Adamson static int decode_first_threshold_item4(struct xdr_stream *xdr, 448988034c3dSAndy Adamson struct nfs4_threshold *res) 449088034c3dSAndy Adamson { 4491256e48bbSTrond Myklebust __be32 *p; 4492256e48bbSTrond Myklebust unsigned int savep; 449388034c3dSAndy Adamson uint32_t bitmap[3] = {0,}, attrlen; 449488034c3dSAndy Adamson int status; 449588034c3dSAndy Adamson 449688034c3dSAndy Adamson /* layout type */ 449788034c3dSAndy Adamson p = xdr_inline_decode(xdr, 4); 4498eb72f484SChuck Lever if (unlikely(!p)) 449988034c3dSAndy Adamson return -EIO; 450088034c3dSAndy Adamson res->l_type = be32_to_cpup(p); 450188034c3dSAndy Adamson 450288034c3dSAndy Adamson /* thi_hintset bitmap */ 450388034c3dSAndy Adamson status = decode_attr_bitmap(xdr, bitmap); 450488034c3dSAndy Adamson if (status < 0) 450588034c3dSAndy Adamson goto xdr_error; 450688034c3dSAndy Adamson 450788034c3dSAndy Adamson /* thi_hintlist length */ 450888034c3dSAndy Adamson status = decode_attr_length(xdr, &attrlen, &savep); 450988034c3dSAndy Adamson if (status < 0) 451088034c3dSAndy Adamson goto xdr_error; 451188034c3dSAndy Adamson /* thi_hintlist */ 451288034c3dSAndy Adamson status = decode_threshold_hint(xdr, bitmap, &res->rd_sz, THRESHOLD_RD); 451388034c3dSAndy Adamson if (status < 0) 451488034c3dSAndy Adamson goto xdr_error; 451588034c3dSAndy Adamson status = decode_threshold_hint(xdr, bitmap, &res->wr_sz, THRESHOLD_WR); 451688034c3dSAndy Adamson if (status < 0) 451788034c3dSAndy Adamson goto xdr_error; 451888034c3dSAndy Adamson status = decode_threshold_hint(xdr, bitmap, &res->rd_io_sz, 451988034c3dSAndy Adamson THRESHOLD_RD_IO); 452088034c3dSAndy Adamson if (status < 0) 452188034c3dSAndy Adamson goto xdr_error; 452288034c3dSAndy Adamson status = decode_threshold_hint(xdr, bitmap, &res->wr_io_sz, 452388034c3dSAndy Adamson THRESHOLD_WR_IO); 452488034c3dSAndy Adamson if (status < 0) 452588034c3dSAndy Adamson goto xdr_error; 452688034c3dSAndy Adamson 452788034c3dSAndy Adamson status = verify_attr_len(xdr, savep, attrlen); 452888034c3dSAndy Adamson res->bm = bitmap[0]; 452988034c3dSAndy Adamson 453088034c3dSAndy Adamson dprintk("%s bm=0x%x rd_sz=%llu wr_sz=%llu rd_io=%llu wr_io=%llu\n", 453188034c3dSAndy Adamson __func__, res->bm, res->rd_sz, res->wr_sz, res->rd_io_sz, 453288034c3dSAndy Adamson res->wr_io_sz); 453388034c3dSAndy Adamson xdr_error: 453488034c3dSAndy Adamson dprintk("%s ret=%d!\n", __func__, status); 453588034c3dSAndy Adamson return status; 453688034c3dSAndy Adamson } 453788034c3dSAndy Adamson 453888034c3dSAndy Adamson /* 453988034c3dSAndy Adamson * Thresholds on pNFS direct I/O vrs MDS I/O 454088034c3dSAndy Adamson */ 454188034c3dSAndy Adamson static int decode_attr_mdsthreshold(struct xdr_stream *xdr, 454288034c3dSAndy Adamson uint32_t *bitmap, 454388034c3dSAndy Adamson struct nfs4_threshold *res) 454488034c3dSAndy Adamson { 454588034c3dSAndy Adamson __be32 *p; 454688034c3dSAndy Adamson int status = 0; 454788034c3dSAndy Adamson uint32_t num; 454888034c3dSAndy Adamson 454988034c3dSAndy Adamson if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U))) 455088034c3dSAndy Adamson return -EIO; 4551029c5347STrond Myklebust if (bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD) { 45521549210fSTrond Myklebust /* Did the server return an unrequested attribute? */ 45531549210fSTrond Myklebust if (unlikely(res == NULL)) 45541549210fSTrond Myklebust return -EREMOTEIO; 455588034c3dSAndy Adamson p = xdr_inline_decode(xdr, 4); 455688034c3dSAndy Adamson if (unlikely(!p)) 4557eb72f484SChuck Lever return -EIO; 455888034c3dSAndy Adamson num = be32_to_cpup(p); 455988034c3dSAndy Adamson if (num == 0) 456088034c3dSAndy Adamson return 0; 456188034c3dSAndy Adamson if (num > 1) 456288034c3dSAndy Adamson printk(KERN_INFO "%s: Warning: Multiple pNFS layout " 456388034c3dSAndy Adamson "drivers per filesystem not supported\n", 456488034c3dSAndy Adamson __func__); 456588034c3dSAndy Adamson 456688034c3dSAndy Adamson status = decode_first_threshold_item4(xdr, res); 4567029c5347STrond Myklebust bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD; 456888034c3dSAndy Adamson } 456988034c3dSAndy Adamson return status; 457088034c3dSAndy Adamson } 457188034c3dSAndy Adamson 4572ae42c70aSBryan Schumaker static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, 4573ae42c70aSBryan Schumaker struct nfs_fattr *fattr, struct nfs_fh *fh, 4574aa9c2669SDavid Quigley struct nfs4_fs_locations *fs_loc, struct nfs4_label *label, 45756926afd1STrond Myklebust const struct nfs_server *server) 45761da177e4SLinus Torvalds { 4577bca79478STrond Myklebust int status; 4578bca79478STrond Myklebust umode_t fmode = 0; 4579ae42c70aSBryan Schumaker uint32_t type; 4580ee7b75fcSTrond Myklebust int32_t err; 45811da177e4SLinus Torvalds 4582f26c7a78STrond Myklebust status = decode_attr_type(xdr, bitmap, &type); 4583f26c7a78STrond Myklebust if (status < 0) 45841da177e4SLinus Torvalds goto xdr_error; 4585409924e4STrond Myklebust fattr->mode = 0; 4586409924e4STrond Myklebust if (status != 0) { 4587409924e4STrond Myklebust fattr->mode |= nfs_type2fmt[type]; 4588409924e4STrond Myklebust fattr->valid |= status; 4589409924e4STrond Myklebust } 45901da177e4SLinus Torvalds 4591f26c7a78STrond Myklebust status = decode_attr_change(xdr, bitmap, &fattr->change_attr); 4592f26c7a78STrond Myklebust if (status < 0) 45931da177e4SLinus Torvalds goto xdr_error; 4594409924e4STrond Myklebust fattr->valid |= status; 4595f26c7a78STrond Myklebust 4596f26c7a78STrond Myklebust status = decode_attr_size(xdr, bitmap, &fattr->size); 4597f26c7a78STrond Myklebust if (status < 0) 45981da177e4SLinus Torvalds goto xdr_error; 4599409924e4STrond Myklebust fattr->valid |= status; 4600f26c7a78STrond Myklebust 4601f26c7a78STrond Myklebust status = decode_attr_fsid(xdr, bitmap, &fattr->fsid); 4602f26c7a78STrond Myklebust if (status < 0) 46031da177e4SLinus Torvalds goto xdr_error; 4604409924e4STrond Myklebust fattr->valid |= status; 4605f26c7a78STrond Myklebust 4606ee7b75fcSTrond Myklebust err = 0; 4607ee7b75fcSTrond Myklebust status = decode_attr_error(xdr, bitmap, &err); 4608ae42c70aSBryan Schumaker if (status < 0) 4609ae42c70aSBryan Schumaker goto xdr_error; 4610ae42c70aSBryan Schumaker 4611ae42c70aSBryan Schumaker status = decode_attr_filehandle(xdr, bitmap, fh); 4612ae42c70aSBryan Schumaker if (status < 0) 4613ae42c70aSBryan Schumaker goto xdr_error; 4614ae42c70aSBryan Schumaker 4615f26c7a78STrond Myklebust status = decode_attr_fileid(xdr, bitmap, &fattr->fileid); 4616f26c7a78STrond Myklebust if (status < 0) 46171da177e4SLinus Torvalds goto xdr_error; 4618409924e4STrond Myklebust fattr->valid |= status; 4619f26c7a78STrond Myklebust 46208b7e3f49STrond Myklebust status = decode_attr_fs_locations(xdr, bitmap, fs_loc); 4621f26c7a78STrond Myklebust if (status < 0) 4622683b57b4STrond Myklebust goto xdr_error; 4623409924e4STrond Myklebust fattr->valid |= status; 4624f26c7a78STrond Myklebust 46251ca843a2SAndreas Gruenbacher status = -EIO; 46261ca843a2SAndreas Gruenbacher if (unlikely(bitmap[0])) 46271ca843a2SAndreas Gruenbacher goto xdr_error; 46281ca843a2SAndreas Gruenbacher 4629f26c7a78STrond Myklebust status = decode_attr_mode(xdr, bitmap, &fmode); 4630f26c7a78STrond Myklebust if (status < 0) 46311da177e4SLinus Torvalds goto xdr_error; 4632409924e4STrond Myklebust if (status != 0) { 46331da177e4SLinus Torvalds fattr->mode |= fmode; 4634409924e4STrond Myklebust fattr->valid |= status; 4635409924e4STrond Myklebust } 4636f26c7a78STrond Myklebust 4637f26c7a78STrond Myklebust status = decode_attr_nlink(xdr, bitmap, &fattr->nlink); 4638f26c7a78STrond Myklebust if (status < 0) 46391da177e4SLinus Torvalds goto xdr_error; 4640409924e4STrond Myklebust fattr->valid |= status; 4641f26c7a78STrond Myklebust 46426926afd1STrond Myklebust status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name); 4643f26c7a78STrond Myklebust if (status < 0) 46441da177e4SLinus Torvalds goto xdr_error; 4645409924e4STrond Myklebust fattr->valid |= status; 4646f26c7a78STrond Myklebust 46476926afd1STrond Myklebust status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name); 4648f26c7a78STrond Myklebust if (status < 0) 46491da177e4SLinus Torvalds goto xdr_error; 4650409924e4STrond Myklebust fattr->valid |= status; 4651f26c7a78STrond Myklebust 4652f26c7a78STrond Myklebust status = decode_attr_rdev(xdr, bitmap, &fattr->rdev); 4653f26c7a78STrond Myklebust if (status < 0) 46541da177e4SLinus Torvalds goto xdr_error; 4655409924e4STrond Myklebust fattr->valid |= status; 4656f26c7a78STrond Myklebust 4657f26c7a78STrond Myklebust status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used); 4658f26c7a78STrond Myklebust if (status < 0) 46591da177e4SLinus Torvalds goto xdr_error; 4660409924e4STrond Myklebust fattr->valid |= status; 4661f26c7a78STrond Myklebust 4662f26c7a78STrond Myklebust status = decode_attr_time_access(xdr, bitmap, &fattr->atime); 4663f26c7a78STrond Myklebust if (status < 0) 46641da177e4SLinus Torvalds goto xdr_error; 4665409924e4STrond Myklebust fattr->valid |= status; 4666f26c7a78STrond Myklebust 4667f26c7a78STrond Myklebust status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime); 4668f26c7a78STrond Myklebust if (status < 0) 46691da177e4SLinus Torvalds goto xdr_error; 4670409924e4STrond Myklebust fattr->valid |= status; 4671f26c7a78STrond Myklebust 4672f26c7a78STrond Myklebust status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime); 4673f26c7a78STrond Myklebust if (status < 0) 46741da177e4SLinus Torvalds goto xdr_error; 4675409924e4STrond Myklebust fattr->valid |= status; 4676f26c7a78STrond Myklebust 467728331a46STrond Myklebust status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid); 4678f26c7a78STrond Myklebust if (status < 0) 467999baf625SManoj Naik goto xdr_error; 4680409924e4STrond Myklebust fattr->valid |= status; 4681f26c7a78STrond Myklebust 46821ca843a2SAndreas Gruenbacher status = -EIO; 46831ca843a2SAndreas Gruenbacher if (unlikely(bitmap[1])) 46841ca843a2SAndreas Gruenbacher goto xdr_error; 46851ca843a2SAndreas Gruenbacher 468688034c3dSAndy Adamson status = decode_attr_mdsthreshold(xdr, bitmap, fattr->mdsthreshold); 468788034c3dSAndy Adamson if (status < 0) 468888034c3dSAndy Adamson goto xdr_error; 468988034c3dSAndy Adamson 4690aa9c2669SDavid Quigley if (label) { 4691aa9c2669SDavid Quigley status = decode_attr_security_label(xdr, bitmap, label); 4692aa9c2669SDavid Quigley if (status < 0) 4693aa9c2669SDavid Quigley goto xdr_error; 4694aa9c2669SDavid Quigley fattr->valid |= status; 4695aa9c2669SDavid Quigley } 4696aa9c2669SDavid Quigley 4697ae42c70aSBryan Schumaker xdr_error: 4698ae42c70aSBryan Schumaker dprintk("%s: xdr returned %d\n", __func__, -status); 4699ae42c70aSBryan Schumaker return status; 4700ae42c70aSBryan Schumaker } 4701ae42c70aSBryan Schumaker 4702ae42c70aSBryan Schumaker static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, 47038b7e3f49STrond Myklebust struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, 4704aa9c2669SDavid Quigley struct nfs4_label *label, const struct nfs_server *server) 4705ae42c70aSBryan Schumaker { 4706256e48bbSTrond Myklebust unsigned int savep; 4707ae42c70aSBryan Schumaker uint32_t attrlen, 4708dae100c2SFred Isaman bitmap[3] = {0}; 4709ae42c70aSBryan Schumaker int status; 4710ae42c70aSBryan Schumaker 4711ae42c70aSBryan Schumaker status = decode_op_hdr(xdr, OP_GETATTR); 4712ae42c70aSBryan Schumaker if (status < 0) 4713ae42c70aSBryan Schumaker goto xdr_error; 4714ae42c70aSBryan Schumaker 4715ae42c70aSBryan Schumaker status = decode_attr_bitmap(xdr, bitmap); 4716ae42c70aSBryan Schumaker if (status < 0) 4717ae42c70aSBryan Schumaker goto xdr_error; 4718ae42c70aSBryan Schumaker 4719ae42c70aSBryan Schumaker status = decode_attr_length(xdr, &attrlen, &savep); 4720ae42c70aSBryan Schumaker if (status < 0) 4721ae42c70aSBryan Schumaker goto xdr_error; 4722ae42c70aSBryan Schumaker 4723aa9c2669SDavid Quigley status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, 4724aa9c2669SDavid Quigley label, server); 4725ae42c70aSBryan Schumaker if (status < 0) 4726ae42c70aSBryan Schumaker goto xdr_error; 4727ae42c70aSBryan Schumaker 4728f26c7a78STrond Myklebust status = verify_attr_len(xdr, savep, attrlen); 47291da177e4SLinus Torvalds xdr_error: 47303110ff80SHarvey Harrison dprintk("%s: xdr returned %d\n", __func__, -status); 47311da177e4SLinus Torvalds return status; 47321da177e4SLinus Torvalds } 47331da177e4SLinus Torvalds 4734aa9c2669SDavid Quigley static int decode_getfattr_label(struct xdr_stream *xdr, struct nfs_fattr *fattr, 4735aa9c2669SDavid Quigley struct nfs4_label *label, const struct nfs_server *server) 4736aa9c2669SDavid Quigley { 4737aa9c2669SDavid Quigley return decode_getfattr_generic(xdr, fattr, NULL, NULL, label, server); 4738aa9c2669SDavid Quigley } 4739aa9c2669SDavid Quigley 4740ae42c70aSBryan Schumaker static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, 47416926afd1STrond Myklebust const struct nfs_server *server) 4742ae42c70aSBryan Schumaker { 4743aa9c2669SDavid Quigley return decode_getfattr_generic(xdr, fattr, NULL, NULL, NULL, server); 4744ae42c70aSBryan Schumaker } 47451da177e4SLinus Torvalds 4746504913fbSAndy Adamson /* 47473132e49eSJeff Layton * Decode potentially multiple layout types. 4748504913fbSAndy Adamson */ 47493132e49eSJeff Layton static int decode_pnfs_layout_types(struct xdr_stream *xdr, 4750ca440c38SJeff Layton struct nfs_fsinfo *fsinfo) 4751504913fbSAndy Adamson { 4752b8a8a0ddSTrond Myklebust __be32 *p; 4753ca440c38SJeff Layton uint32_t i; 4754504913fbSAndy Adamson 4755504913fbSAndy Adamson p = xdr_inline_decode(xdr, 4); 4756504913fbSAndy Adamson if (unlikely(!p)) 4757eb72f484SChuck Lever return -EIO; 4758ca440c38SJeff Layton fsinfo->nlayouttypes = be32_to_cpup(p); 4759504913fbSAndy Adamson 4760504913fbSAndy Adamson /* pNFS is not supported by the underlying file system */ 4761ca440c38SJeff Layton if (fsinfo->nlayouttypes == 0) 4762504913fbSAndy Adamson return 0; 4763504913fbSAndy Adamson 4764504913fbSAndy Adamson /* Decode and set first layout type, move xdr->p past unused types */ 4765ca440c38SJeff Layton p = xdr_inline_decode(xdr, fsinfo->nlayouttypes * 4); 4766504913fbSAndy Adamson if (unlikely(!p)) 4767eb72f484SChuck Lever return -EIO; 4768ca440c38SJeff Layton 4769ca440c38SJeff Layton /* If we get too many, then just cap it at the max */ 4770ca440c38SJeff Layton if (fsinfo->nlayouttypes > NFS_MAX_LAYOUT_TYPES) { 4771ca440c38SJeff Layton printk(KERN_INFO "NFS: %s: Warning: Too many (%u) pNFS layout types\n", 4772ca440c38SJeff Layton __func__, fsinfo->nlayouttypes); 4773ca440c38SJeff Layton fsinfo->nlayouttypes = NFS_MAX_LAYOUT_TYPES; 4774ca440c38SJeff Layton } 4775ca440c38SJeff Layton 4776ca440c38SJeff Layton for(i = 0; i < fsinfo->nlayouttypes; ++i) 4777ca440c38SJeff Layton fsinfo->layouttype[i] = be32_to_cpup(p++); 4778504913fbSAndy Adamson return 0; 4779504913fbSAndy Adamson } 4780504913fbSAndy Adamson 4781504913fbSAndy Adamson /* 4782504913fbSAndy Adamson * The type of file system exported. 4783504913fbSAndy Adamson * Note we must ensure that layouttype is set in any non-error case. 4784504913fbSAndy Adamson */ 4785504913fbSAndy Adamson static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap, 4786ca440c38SJeff Layton struct nfs_fsinfo *fsinfo) 4787504913fbSAndy Adamson { 4788504913fbSAndy Adamson int status = 0; 4789504913fbSAndy Adamson 4790504913fbSAndy Adamson dprintk("%s: bitmap is %x\n", __func__, bitmap[1]); 4791504913fbSAndy Adamson if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U))) 4792504913fbSAndy Adamson return -EIO; 4793504913fbSAndy Adamson if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) { 4794ca440c38SJeff Layton status = decode_pnfs_layout_types(xdr, fsinfo); 4795504913fbSAndy Adamson bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES; 47963132e49eSJeff Layton } 4797504913fbSAndy Adamson return status; 4798504913fbSAndy Adamson } 4799504913fbSAndy Adamson 4800dae100c2SFred Isaman /* 4801dae100c2SFred Isaman * The prefered block size for layout directed io 4802dae100c2SFred Isaman */ 4803dae100c2SFred Isaman static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap, 4804dae100c2SFred Isaman uint32_t *res) 4805dae100c2SFred Isaman { 4806dae100c2SFred Isaman __be32 *p; 4807dae100c2SFred Isaman 4808dae100c2SFred Isaman dprintk("%s: bitmap is %x\n", __func__, bitmap[2]); 4809dae100c2SFred Isaman *res = 0; 4810dae100c2SFred Isaman if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) { 4811dae100c2SFred Isaman p = xdr_inline_decode(xdr, 4); 4812eb72f484SChuck Lever if (unlikely(!p)) 4813dae100c2SFred Isaman return -EIO; 4814dae100c2SFred Isaman *res = be32_to_cpup(p); 4815dae100c2SFred Isaman bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE; 4816dae100c2SFred Isaman } 4817dae100c2SFred Isaman return 0; 4818dae100c2SFred Isaman } 4819dae100c2SFred Isaman 48202a92ee92SPeng Tao /* 48212a92ee92SPeng Tao * The granularity of a CLONE operation. 48222a92ee92SPeng Tao */ 48232a92ee92SPeng Tao static int decode_attr_clone_blksize(struct xdr_stream *xdr, uint32_t *bitmap, 48242a92ee92SPeng Tao uint32_t *res) 48252a92ee92SPeng Tao { 48262a92ee92SPeng Tao __be32 *p; 48272a92ee92SPeng Tao 48282a92ee92SPeng Tao dprintk("%s: bitmap is %x\n", __func__, bitmap[2]); 48292a92ee92SPeng Tao *res = 0; 48302a92ee92SPeng Tao if (bitmap[2] & FATTR4_WORD2_CLONE_BLKSIZE) { 48312a92ee92SPeng Tao p = xdr_inline_decode(xdr, 4); 4832eb72f484SChuck Lever if (unlikely(!p)) 48332a92ee92SPeng Tao return -EIO; 48342a92ee92SPeng Tao *res = be32_to_cpup(p); 48352a92ee92SPeng Tao bitmap[2] &= ~FATTR4_WORD2_CLONE_BLKSIZE; 48362a92ee92SPeng Tao } 48372a92ee92SPeng Tao return 0; 48382a92ee92SPeng Tao } 48392a92ee92SPeng Tao 48401da177e4SLinus Torvalds static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) 48411da177e4SLinus Torvalds { 4842256e48bbSTrond Myklebust unsigned int savep; 4843dae100c2SFred Isaman uint32_t attrlen, bitmap[3]; 48441da177e4SLinus Torvalds int status; 48451da177e4SLinus Torvalds 48461da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 48471da177e4SLinus Torvalds goto xdr_error; 48481da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 48491da177e4SLinus Torvalds goto xdr_error; 48501da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 48511da177e4SLinus Torvalds goto xdr_error; 48521da177e4SLinus Torvalds 48531da177e4SLinus Torvalds fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */ 48541da177e4SLinus Torvalds 48551da177e4SLinus Torvalds if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0) 48561da177e4SLinus Torvalds goto xdr_error; 48571da177e4SLinus Torvalds if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0) 48581da177e4SLinus Torvalds goto xdr_error; 48591da177e4SLinus Torvalds if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0) 48601da177e4SLinus Torvalds goto xdr_error; 48611da177e4SLinus Torvalds fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax; 48621da177e4SLinus Torvalds if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0) 48631da177e4SLinus Torvalds goto xdr_error; 48641da177e4SLinus Torvalds fsinfo->wtpref = fsinfo->wtmax; 48651ca843a2SAndreas Gruenbacher 48661ca843a2SAndreas Gruenbacher status = -EIO; 48671ca843a2SAndreas Gruenbacher if (unlikely(bitmap[0])) 48681ca843a2SAndreas Gruenbacher goto xdr_error; 48691ca843a2SAndreas Gruenbacher 487055b6e774SRicardo Labiaga status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta); 487155b6e774SRicardo Labiaga if (status != 0) 487255b6e774SRicardo Labiaga goto xdr_error; 4873ca440c38SJeff Layton status = decode_attr_pnfstype(xdr, bitmap, fsinfo); 4874504913fbSAndy Adamson if (status != 0) 4875504913fbSAndy Adamson goto xdr_error; 48761ca843a2SAndreas Gruenbacher 48771ca843a2SAndreas Gruenbacher status = -EIO; 48781ca843a2SAndreas Gruenbacher if (unlikely(bitmap[1])) 48791ca843a2SAndreas Gruenbacher goto xdr_error; 48801ca843a2SAndreas Gruenbacher 4881dae100c2SFred Isaman status = decode_attr_layout_blksize(xdr, bitmap, &fsinfo->blksize); 4882dae100c2SFred Isaman if (status) 4883dae100c2SFred Isaman goto xdr_error; 48842a92ee92SPeng Tao status = decode_attr_clone_blksize(xdr, bitmap, &fsinfo->clone_blksize); 48852a92ee92SPeng Tao if (status) 48862a92ee92SPeng Tao goto xdr_error; 48871da177e4SLinus Torvalds 4888b78ef845SFrank van der Linden status = decode_attr_xattrsupport(xdr, bitmap, 4889b78ef845SFrank van der Linden &fsinfo->xattr_support); 4890b78ef845SFrank van der Linden if (status) 4891b78ef845SFrank van der Linden goto xdr_error; 4892b78ef845SFrank van der Linden 48931da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 48941da177e4SLinus Torvalds xdr_error: 48953110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 48961da177e4SLinus Torvalds return status; 48971da177e4SLinus Torvalds } 48981da177e4SLinus Torvalds 48991da177e4SLinus Torvalds static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) 49001da177e4SLinus Torvalds { 49018687b63aSAl Viro __be32 *p; 49021da177e4SLinus Torvalds uint32_t len; 49031da177e4SLinus Torvalds int status; 49041da177e4SLinus Torvalds 49059936781dSTrond Myklebust /* Zero handle first to allow comparisons */ 49069936781dSTrond Myklebust memset(fh, 0, sizeof(*fh)); 49079936781dSTrond Myklebust 49081da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_GETFH); 49091da177e4SLinus Torvalds if (status) 49101da177e4SLinus Torvalds return status; 49111da177e4SLinus Torvalds 4912c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4913c0eae66eSBenny Halevy if (unlikely(!p)) 4914eb72f484SChuck Lever return -EIO; 4915cccddf4fSBenny Halevy len = be32_to_cpup(p); 49161da177e4SLinus Torvalds if (len > NFS4_FHSIZE) 49171da177e4SLinus Torvalds return -EIO; 49181da177e4SLinus Torvalds fh->size = len; 4919c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 4920c0eae66eSBenny Halevy if (unlikely(!p)) 4921eb72f484SChuck Lever return -EIO; 492299398d06SBenny Halevy memcpy(fh->data, p, len); 49231da177e4SLinus Torvalds return 0; 49241da177e4SLinus Torvalds } 49251da177e4SLinus Torvalds 49261da177e4SLinus Torvalds static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 49271da177e4SLinus Torvalds { 49281da177e4SLinus Torvalds int status; 49291da177e4SLinus Torvalds 49301da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LINK); 49311da177e4SLinus Torvalds if (status) 49321da177e4SLinus Torvalds return status; 49331da177e4SLinus Torvalds return decode_change_info(xdr, cinfo); 49341da177e4SLinus Torvalds } 49351da177e4SLinus Torvalds 49361da177e4SLinus Torvalds /* 49371da177e4SLinus Torvalds * We create the owner, so we know a proper owner.id length is 4. 49381da177e4SLinus Torvalds */ 4939911d1aafSTrond Myklebust static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) 49401da177e4SLinus Torvalds { 4941911d1aafSTrond Myklebust uint64_t offset, length, clientid; 49428687b63aSAl Viro __be32 *p; 4943911d1aafSTrond Myklebust uint32_t namelen, type; 49441da177e4SLinus Torvalds 4945babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 32); /* read 32 bytes */ 4946c0eae66eSBenny Halevy if (unlikely(!p)) 4947eb72f484SChuck Lever return -EIO; 4948babddc72SBryan Schumaker p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */ 49493ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &length); 4950babddc72SBryan Schumaker type = be32_to_cpup(p++); /* 4 byte read */ 4951babddc72SBryan Schumaker if (fl != NULL) { /* manipulate file lock */ 4952911d1aafSTrond Myklebust fl->fl_start = (loff_t)offset; 4953911d1aafSTrond Myklebust fl->fl_end = fl->fl_start + (loff_t)length - 1; 4954911d1aafSTrond Myklebust if (length == ~(uint64_t)0) 4955911d1aafSTrond Myklebust fl->fl_end = OFFSET_MAX; 4956911d1aafSTrond Myklebust fl->fl_type = F_WRLCK; 4957911d1aafSTrond Myklebust if (type & 1) 4958911d1aafSTrond Myklebust fl->fl_type = F_RDLCK; 4959911d1aafSTrond Myklebust fl->fl_pid = 0; 4960911d1aafSTrond Myklebust } 4961babddc72SBryan Schumaker p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */ 4962babddc72SBryan Schumaker namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */ 4963babddc72SBryan Schumaker p = xdr_inline_decode(xdr, namelen); /* variable size field */ 4964eb72f484SChuck Lever if (likely(!p)) 4965c0eae66eSBenny Halevy return -EIO; 4966eb72f484SChuck Lever return -NFS4ERR_DENIED; 49671da177e4SLinus Torvalds } 49681da177e4SLinus Torvalds 4969911d1aafSTrond Myklebust static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) 49701da177e4SLinus Torvalds { 49711da177e4SLinus Torvalds int status; 49721da177e4SLinus Torvalds 49731da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCK); 4974c1d51931STrond Myklebust if (status == -EIO) 4975c1d51931STrond Myklebust goto out; 49761da177e4SLinus Torvalds if (status == 0) { 497793b717fdSTrond Myklebust status = decode_lock_stateid(xdr, &res->stateid); 497807d30434SBenny Halevy if (unlikely(status)) 497907d30434SBenny Halevy goto out; 49801da177e4SLinus Torvalds } else if (status == -NFS4ERR_DENIED) 4981c1d51931STrond Myklebust status = decode_lock_denied(xdr, NULL); 4982c1d51931STrond Myklebust if (res->open_seqid != NULL) 4983c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->open_seqid); 4984c1d51931STrond Myklebust nfs_increment_lock_seqid(status, res->lock_seqid); 4985c1d51931STrond Myklebust out: 49861da177e4SLinus Torvalds return status; 49871da177e4SLinus Torvalds } 49881da177e4SLinus Torvalds 4989911d1aafSTrond Myklebust static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res) 49901da177e4SLinus Torvalds { 49911da177e4SLinus Torvalds int status; 49921da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCKT); 49931da177e4SLinus Torvalds if (status == -NFS4ERR_DENIED) 4994911d1aafSTrond Myklebust return decode_lock_denied(xdr, res->denied); 49951da177e4SLinus Torvalds return status; 49961da177e4SLinus Torvalds } 49971da177e4SLinus Torvalds 4998911d1aafSTrond Myklebust static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) 49991da177e4SLinus Torvalds { 50001da177e4SLinus Torvalds int status; 50011da177e4SLinus Torvalds 50021da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCKU); 5003c1d51931STrond Myklebust if (status != -EIO) 5004c1d51931STrond Myklebust nfs_increment_lock_seqid(status, res->seqid); 500507d30434SBenny Halevy if (status == 0) 500693b717fdSTrond Myklebust status = decode_lock_stateid(xdr, &res->stateid); 50071da177e4SLinus Torvalds return status; 50081da177e4SLinus Torvalds } 50091da177e4SLinus Torvalds 5010d3c7b7ccSTrond Myklebust static int decode_release_lockowner(struct xdr_stream *xdr) 5011d3c7b7ccSTrond Myklebust { 5012d3c7b7ccSTrond Myklebust return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER); 5013d3c7b7ccSTrond Myklebust } 5014d3c7b7ccSTrond Myklebust 50151da177e4SLinus Torvalds static int decode_lookup(struct xdr_stream *xdr) 50161da177e4SLinus Torvalds { 50171da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_LOOKUP); 50181da177e4SLinus Torvalds } 50191da177e4SLinus Torvalds 50205b5faaf6SJeff Layton static int decode_lookupp(struct xdr_stream *xdr) 50215b5faaf6SJeff Layton { 50225b5faaf6SJeff Layton return decode_op_hdr(xdr, OP_LOOKUPP); 50235b5faaf6SJeff Layton } 50245b5faaf6SJeff Layton 50251da177e4SLinus Torvalds /* This is too sick! */ 50267d160a6cSTrond Myklebust static int decode_space_limit(struct xdr_stream *xdr, 50277d160a6cSTrond Myklebust unsigned long *pagemod_limit) 50281da177e4SLinus Torvalds { 50298687b63aSAl Viro __be32 *p; 50301da177e4SLinus Torvalds uint32_t limit_type, nblocks, blocksize; 50317d160a6cSTrond Myklebust u64 maxsize = 0; 50321da177e4SLinus Torvalds 5033c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 5034c0eae66eSBenny Halevy if (unlikely(!p)) 5035eb72f484SChuck Lever return -EIO; 50366f723f77SBenny Halevy limit_type = be32_to_cpup(p++); 50371da177e4SLinus Torvalds switch (limit_type) { 50387d160a6cSTrond Myklebust case NFS4_LIMIT_SIZE: 50397d160a6cSTrond Myklebust xdr_decode_hyper(p, &maxsize); 50401da177e4SLinus Torvalds break; 50417d160a6cSTrond Myklebust case NFS4_LIMIT_BLOCKS: 50426f723f77SBenny Halevy nblocks = be32_to_cpup(p++); 5043cccddf4fSBenny Halevy blocksize = be32_to_cpup(p); 50447d160a6cSTrond Myklebust maxsize = (uint64_t)nblocks * (uint64_t)blocksize; 50451da177e4SLinus Torvalds } 504609cbfeafSKirill A. Shutemov maxsize >>= PAGE_SHIFT; 50477d160a6cSTrond Myklebust *pagemod_limit = min_t(u64, maxsize, ULONG_MAX); 50481da177e4SLinus Torvalds return 0; 50491da177e4SLinus Torvalds } 50501da177e4SLinus Torvalds 50516ae37339STrond Myklebust static int decode_rw_delegation(struct xdr_stream *xdr, 50526ae37339STrond Myklebust uint32_t delegation_type, 50536ae37339STrond Myklebust struct nfs_openres *res) 50541da177e4SLinus Torvalds { 50558687b63aSAl Viro __be32 *p; 505607d30434SBenny Halevy int status; 50571da177e4SLinus Torvalds 505893b717fdSTrond Myklebust status = decode_delegation_stateid(xdr, &res->delegation); 505907d30434SBenny Halevy if (unlikely(status)) 506007d30434SBenny Halevy return status; 5061c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 5062c0eae66eSBenny Halevy if (unlikely(!p)) 5063eb72f484SChuck Lever return -EIO; 5064cccddf4fSBenny Halevy res->do_recall = be32_to_cpup(p); 506505d564feSAndy Adamson 50661da177e4SLinus Torvalds switch (delegation_type) { 50671da177e4SLinus Torvalds case NFS4_OPEN_DELEGATE_READ: 50681da177e4SLinus Torvalds res->delegation_type = FMODE_READ; 50691da177e4SLinus Torvalds break; 50701da177e4SLinus Torvalds case NFS4_OPEN_DELEGATE_WRITE: 50711da177e4SLinus Torvalds res->delegation_type = FMODE_WRITE|FMODE_READ; 50727d160a6cSTrond Myklebust if (decode_space_limit(xdr, &res->pagemod_limit) < 0) 50731da177e4SLinus Torvalds return -EIO; 50741da177e4SLinus Torvalds } 50751bbe60ffSTrond Myklebust return decode_ace(xdr, NULL); 50761da177e4SLinus Torvalds } 50771da177e4SLinus Torvalds 50786ae37339STrond Myklebust static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res) 50796ae37339STrond Myklebust { 50806ae37339STrond Myklebust __be32 *p; 50816ae37339STrond Myklebust uint32_t why_no_delegation; 50826ae37339STrond Myklebust 50836ae37339STrond Myklebust p = xdr_inline_decode(xdr, 4); 50846ae37339STrond Myklebust if (unlikely(!p)) 5085eb72f484SChuck Lever return -EIO; 50866ae37339STrond Myklebust why_no_delegation = be32_to_cpup(p); 50876ae37339STrond Myklebust switch (why_no_delegation) { 50886ae37339STrond Myklebust case WND4_CONTENTION: 50896ae37339STrond Myklebust case WND4_RESOURCE: 50906ae37339STrond Myklebust xdr_inline_decode(xdr, 4); 50916ae37339STrond Myklebust /* Ignore for now */ 50926ae37339STrond Myklebust } 50936ae37339STrond Myklebust return 0; 50946ae37339STrond Myklebust } 50956ae37339STrond Myklebust 50966ae37339STrond Myklebust static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) 50976ae37339STrond Myklebust { 50986ae37339STrond Myklebust __be32 *p; 50996ae37339STrond Myklebust uint32_t delegation_type; 51006ae37339STrond Myklebust 51016ae37339STrond Myklebust p = xdr_inline_decode(xdr, 4); 51026ae37339STrond Myklebust if (unlikely(!p)) 5103eb72f484SChuck Lever return -EIO; 51046ae37339STrond Myklebust delegation_type = be32_to_cpup(p); 51056ae37339STrond Myklebust res->delegation_type = 0; 51066ae37339STrond Myklebust switch (delegation_type) { 51076ae37339STrond Myklebust case NFS4_OPEN_DELEGATE_NONE: 51086ae37339STrond Myklebust return 0; 51096ae37339STrond Myklebust case NFS4_OPEN_DELEGATE_READ: 51106ae37339STrond Myklebust case NFS4_OPEN_DELEGATE_WRITE: 51116ae37339STrond Myklebust return decode_rw_delegation(xdr, delegation_type, res); 51126ae37339STrond Myklebust case NFS4_OPEN_DELEGATE_NONE_EXT: 51136ae37339STrond Myklebust return decode_no_delegation(xdr, res); 51146ae37339STrond Myklebust } 51156ae37339STrond Myklebust return -EIO; 51166ae37339STrond Myklebust } 51176ae37339STrond Myklebust 51181da177e4SLinus Torvalds static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) 51191da177e4SLinus Torvalds { 51208687b63aSAl Viro __be32 *p; 5121aa53ed54SJeff Layton uint32_t savewords, bmlen, i; 51221da177e4SLinus Torvalds int status; 51231da177e4SLinus Torvalds 5124c7848f69STrond Myklebust if (!__decode_op_hdr(xdr, OP_OPEN, &status)) 5125c7848f69STrond Myklebust return status; 5126c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 5127c7848f69STrond Myklebust if (status) 5128c7848f69STrond Myklebust return status; 512993b717fdSTrond Myklebust status = decode_open_stateid(xdr, &res->stateid); 513007d30434SBenny Halevy if (unlikely(status)) 51311da177e4SLinus Torvalds return status; 51321da177e4SLinus Torvalds 51331da177e4SLinus Torvalds decode_change_info(xdr, &res->cinfo); 51341da177e4SLinus Torvalds 5135c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5136c0eae66eSBenny Halevy if (unlikely(!p)) 5137eb72f484SChuck Lever return -EIO; 51386f723f77SBenny Halevy res->rflags = be32_to_cpup(p++); 5139cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 51401da177e4SLinus Torvalds if (bmlen > 10) 51411da177e4SLinus Torvalds goto xdr_error; 51421da177e4SLinus Torvalds 5143c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, bmlen << 2); 5144c0eae66eSBenny Halevy if (unlikely(!p)) 5145eb72f484SChuck Lever return -EIO; 5146aa53ed54SJeff Layton savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE); 5147aa53ed54SJeff Layton for (i = 0; i < savewords; ++i) 51486f723f77SBenny Halevy res->attrset[i] = be32_to_cpup(p++); 5149aa53ed54SJeff Layton for (; i < NFS4_BITMAP_SIZE; i++) 5150aa53ed54SJeff Layton res->attrset[i] = 0; 5151aa53ed54SJeff Layton 51521da177e4SLinus Torvalds return decode_delegation(xdr, res); 51531da177e4SLinus Torvalds xdr_error: 51543110ff80SHarvey Harrison dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen); 51551da177e4SLinus Torvalds return -EIO; 51561da177e4SLinus Torvalds } 51571da177e4SLinus Torvalds 51581da177e4SLinus Torvalds static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res) 51591da177e4SLinus Torvalds { 51601da177e4SLinus Torvalds int status; 51611da177e4SLinus Torvalds 51621da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); 5163c1d51931STrond Myklebust if (status != -EIO) 5164c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 516507d30434SBenny Halevy if (!status) 516693b717fdSTrond Myklebust status = decode_open_stateid(xdr, &res->stateid); 51671da177e4SLinus Torvalds return status; 51681da177e4SLinus Torvalds } 51691da177e4SLinus Torvalds 51701da177e4SLinus Torvalds static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res) 51711da177e4SLinus Torvalds { 51721da177e4SLinus Torvalds int status; 51731da177e4SLinus Torvalds 51741da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); 5175c1d51931STrond Myklebust if (status != -EIO) 5176c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 517707d30434SBenny Halevy if (!status) 517893b717fdSTrond Myklebust status = decode_open_stateid(xdr, &res->stateid); 51791da177e4SLinus Torvalds return status; 51801da177e4SLinus Torvalds } 51811da177e4SLinus Torvalds 51821da177e4SLinus Torvalds static int decode_putfh(struct xdr_stream *xdr) 51831da177e4SLinus Torvalds { 51841da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_PUTFH); 51851da177e4SLinus Torvalds } 51861da177e4SLinus Torvalds 51871da177e4SLinus Torvalds static int decode_putrootfh(struct xdr_stream *xdr) 51881da177e4SLinus Torvalds { 51891da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_PUTROOTFH); 51901da177e4SLinus Torvalds } 51911da177e4SLinus Torvalds 51929137bdf3SAnna Schumaker static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, 51939137bdf3SAnna Schumaker struct nfs_pgio_res *res) 51941da177e4SLinus Torvalds { 51958687b63aSAl Viro __be32 *p; 519664bd577eSTrond Myklebust uint32_t count, eof, recvd; 51971da177e4SLinus Torvalds int status; 51981da177e4SLinus Torvalds 51991da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READ); 52001da177e4SLinus Torvalds if (status) 52011da177e4SLinus Torvalds return status; 5202c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5203c0eae66eSBenny Halevy if (unlikely(!p)) 5204eb72f484SChuck Lever return -EIO; 52056f723f77SBenny Halevy eof = be32_to_cpup(p++); 5206cccddf4fSBenny Halevy count = be32_to_cpup(p); 520764bd577eSTrond Myklebust recvd = xdr_read_pages(xdr, count); 52081da177e4SLinus Torvalds if (count > recvd) { 5209fe82a183SChuck Lever dprintk("NFS: server cheating in read reply: " 52101da177e4SLinus Torvalds "count %u > recvd %u\n", count, recvd); 52111da177e4SLinus Torvalds count = recvd; 52121da177e4SLinus Torvalds eof = 0; 52131da177e4SLinus Torvalds } 52141da177e4SLinus Torvalds res->eof = eof; 52151da177e4SLinus Torvalds res->count = count; 52161da177e4SLinus Torvalds return 0; 52171da177e4SLinus Torvalds } 52181da177e4SLinus Torvalds 52191da177e4SLinus Torvalds static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) 52201da177e4SLinus Torvalds { 5221bcecff77SChuck Lever int status; 5222cd93710eSChuck Lever __be32 verf[2]; 52231da177e4SLinus Torvalds 52241da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READDIR); 5225db942bbdSBenny Halevy if (!status) 5226db942bbdSBenny Halevy status = decode_verifier(xdr, readdir->verifier.data); 5227db942bbdSBenny Halevy if (unlikely(status)) 52281da177e4SLinus Torvalds return status; 5229cd93710eSChuck Lever memcpy(verf, readdir->verifier.data, sizeof(verf)); 523044109241SFred Isaman dprintk("%s: verifier = %08x:%08x\n", 5231cd93710eSChuck Lever __func__, verf[0], verf[1]); 523264bd577eSTrond Myklebust return xdr_read_pages(xdr, xdr->buf->page_len); 52331da177e4SLinus Torvalds } 52341da177e4SLinus Torvalds 52351da177e4SLinus Torvalds static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) 52361da177e4SLinus Torvalds { 52371da177e4SLinus Torvalds struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 5238bcecff77SChuck Lever u32 len, recvd; 52398687b63aSAl Viro __be32 *p; 52401da177e4SLinus Torvalds int status; 52411da177e4SLinus Torvalds 52421da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READLINK); 52431da177e4SLinus Torvalds if (status) 52441da177e4SLinus Torvalds return status; 52451da177e4SLinus Torvalds 52461da177e4SLinus Torvalds /* Convert length of symlink */ 5247c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 5248c0eae66eSBenny Halevy if (unlikely(!p)) 5249eb72f484SChuck Lever return -EIO; 5250cccddf4fSBenny Halevy len = be32_to_cpup(p); 52511da177e4SLinus Torvalds if (len >= rcvbuf->page_len || len <= 0) { 5252fe82a183SChuck Lever dprintk("nfs: server returned giant symlink!\n"); 52531da177e4SLinus Torvalds return -ENAMETOOLONG; 52541da177e4SLinus Torvalds } 525564bd577eSTrond Myklebust recvd = xdr_read_pages(xdr, len); 52561da177e4SLinus Torvalds if (recvd < len) { 5257fe82a183SChuck Lever dprintk("NFS: server cheating in readlink reply: " 52581da177e4SLinus Torvalds "count %u > recvd %u\n", len, recvd); 52591da177e4SLinus Torvalds return -EIO; 52601da177e4SLinus Torvalds } 52611da177e4SLinus Torvalds /* 52621da177e4SLinus Torvalds * The XDR encode routine has set things up so that 52631da177e4SLinus Torvalds * the link text will be copied directly into the 52641da177e4SLinus Torvalds * buffer. We just have to do overflow-checking, 5265a5032910SRandy Dunlap * and null-terminate the text (the VFS expects 52661da177e4SLinus Torvalds * null-termination). 52671da177e4SLinus Torvalds */ 5268b4687da7SChuck Lever xdr_terminate_string(rcvbuf, len); 52691da177e4SLinus Torvalds return 0; 52701da177e4SLinus Torvalds } 52711da177e4SLinus Torvalds 52721da177e4SLinus Torvalds static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 52731da177e4SLinus Torvalds { 52741da177e4SLinus Torvalds int status; 52751da177e4SLinus Torvalds 52761da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_REMOVE); 52771da177e4SLinus Torvalds if (status) 52781da177e4SLinus Torvalds goto out; 52791da177e4SLinus Torvalds status = decode_change_info(xdr, cinfo); 52801da177e4SLinus Torvalds out: 52811da177e4SLinus Torvalds return status; 52821da177e4SLinus Torvalds } 52831da177e4SLinus Torvalds 52841da177e4SLinus Torvalds static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo, 52851da177e4SLinus Torvalds struct nfs4_change_info *new_cinfo) 52861da177e4SLinus Torvalds { 52871da177e4SLinus Torvalds int status; 52881da177e4SLinus Torvalds 52891da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_RENAME); 52901da177e4SLinus Torvalds if (status) 52911da177e4SLinus Torvalds goto out; 52921da177e4SLinus Torvalds if ((status = decode_change_info(xdr, old_cinfo))) 52931da177e4SLinus Torvalds goto out; 52941da177e4SLinus Torvalds status = decode_change_info(xdr, new_cinfo); 52951da177e4SLinus Torvalds out: 52961da177e4SLinus Torvalds return status; 52971da177e4SLinus Torvalds } 52981da177e4SLinus Torvalds 52991da177e4SLinus Torvalds static int decode_renew(struct xdr_stream *xdr) 53001da177e4SLinus Torvalds { 53011da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_RENEW); 53021da177e4SLinus Torvalds } 53031da177e4SLinus Torvalds 530456ae19f3STrond Myklebust static int 530556ae19f3STrond Myklebust decode_restorefh(struct xdr_stream *xdr) 530656ae19f3STrond Myklebust { 530756ae19f3STrond Myklebust return decode_op_hdr(xdr, OP_RESTOREFH); 530856ae19f3STrond Myklebust } 530956ae19f3STrond Myklebust 5310029d105eSJ. Bruce Fields static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, 5311bf118a34SAndy Adamson struct nfs_getaclres *res) 5312029d105eSJ. Bruce Fields { 5313256e48bbSTrond Myklebust unsigned int savep; 5314029d105eSJ. Bruce Fields uint32_t attrlen, 5315dae100c2SFred Isaman bitmap[3] = {0}; 5316029d105eSJ. Bruce Fields int status; 5317029d105eSJ. Bruce Fields 5318bf118a34SAndy Adamson res->acl_len = 0; 5319029d105eSJ. Bruce Fields if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 5320029d105eSJ. Bruce Fields goto out; 53215a006899SSachin Prabhu 5322519d3959STrond Myklebust xdr_enter_page(xdr, xdr->buf->page_len); 5323519d3959STrond Myklebust 5324029d105eSJ. Bruce Fields if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 5325029d105eSJ. Bruce Fields goto out; 5326029d105eSJ. Bruce Fields if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 5327029d105eSJ. Bruce Fields goto out; 5328029d105eSJ. Bruce Fields 5329029d105eSJ. Bruce Fields if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) 5330029d105eSJ. Bruce Fields return -EIO; 5331029d105eSJ. Bruce Fields if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { 5332029d105eSJ. Bruce Fields 5333bf118a34SAndy Adamson /* The bitmap (xdr len + bitmaps) and the attr xdr len words 5334bf118a34SAndy Adamson * are stored with the acl data to handle the problem of 5335bf118a34SAndy Adamson * variable length bitmaps.*/ 5336a14a6359SAnna Schumaker res->acl_data_offset = xdr_page_pos(xdr); 5337519d3959STrond Myklebust res->acl_len = attrlen; 53381f1ea6c2STrond Myklebust 53391f1ea6c2STrond Myklebust /* Check for receive buffer overflow */ 5340*17068466STrond Myklebust if (res->acl_len > xdr_stream_remaining(xdr) || 53411f1ea6c2STrond Myklebust res->acl_len + res->acl_data_offset > xdr->buf->page_len) { 53421f1ea6c2STrond Myklebust res->acl_flags |= NFS4_ACL_TRUNC; 5343*17068466STrond Myklebust dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", 5344*17068466STrond Myklebust attrlen, xdr_stream_remaining(xdr)); 5345029d105eSJ. Bruce Fields } 53468c233cf9SJ. Bruce Fields } else 53478c233cf9SJ. Bruce Fields status = -EOPNOTSUPP; 5348029d105eSJ. Bruce Fields 5349029d105eSJ. Bruce Fields out: 5350029d105eSJ. Bruce Fields return status; 5351029d105eSJ. Bruce Fields } 5352029d105eSJ. Bruce Fields 53531da177e4SLinus Torvalds static int 53541da177e4SLinus Torvalds decode_savefh(struct xdr_stream *xdr) 53551da177e4SLinus Torvalds { 53561da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_SAVEFH); 53571da177e4SLinus Torvalds } 53581da177e4SLinus Torvalds 53599e9ecc03SBenny Halevy static int decode_setattr(struct xdr_stream *xdr) 53601da177e4SLinus Torvalds { 53611da177e4SLinus Torvalds int status; 53621da177e4SLinus Torvalds 53631da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_SETATTR); 53641da177e4SLinus Torvalds if (status) 53651da177e4SLinus Torvalds return status; 536637c88763STrond Myklebust if (decode_bitmap4(xdr, NULL, 0) >= 0) 53671da177e4SLinus Torvalds return 0; 5368c0eae66eSBenny Halevy return -EIO; 53691da177e4SLinus Torvalds } 53701da177e4SLinus Torvalds 5371bb8b27e5STrond Myklebust static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res) 53721da177e4SLinus Torvalds { 53738687b63aSAl Viro __be32 *p; 53741da177e4SLinus Torvalds uint32_t opnum; 53751da177e4SLinus Torvalds int32_t nfserr; 53761da177e4SLinus Torvalds 5377c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5378c0eae66eSBenny Halevy if (unlikely(!p)) 5379eb72f484SChuck Lever return -EIO; 53806f723f77SBenny Halevy opnum = be32_to_cpup(p++); 53811da177e4SLinus Torvalds if (opnum != OP_SETCLIENTID) { 5382fe82a183SChuck Lever dprintk("nfs: decode_setclientid: Server returned operation" 53831da177e4SLinus Torvalds " %d\n", opnum); 53841da177e4SLinus Torvalds return -EIO; 53851da177e4SLinus Torvalds } 5386cccddf4fSBenny Halevy nfserr = be32_to_cpup(p); 53871da177e4SLinus Torvalds if (nfserr == NFS_OK) { 5388c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE); 5389c0eae66eSBenny Halevy if (unlikely(!p)) 5390eb72f484SChuck Lever return -EIO; 5391bb8b27e5STrond Myklebust p = xdr_decode_hyper(p, &res->clientid); 5392bb8b27e5STrond Myklebust memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE); 53931da177e4SLinus Torvalds } else if (nfserr == NFSERR_CLID_INUSE) { 53941da177e4SLinus Torvalds uint32_t len; 53951da177e4SLinus Torvalds 53961da177e4SLinus Torvalds /* skip netid string */ 5397c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 5398c0eae66eSBenny Halevy if (unlikely(!p)) 5399eb72f484SChuck Lever return -EIO; 5400cccddf4fSBenny Halevy len = be32_to_cpup(p); 5401c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 5402c0eae66eSBenny Halevy if (unlikely(!p)) 5403eb72f484SChuck Lever return -EIO; 54041da177e4SLinus Torvalds 54051da177e4SLinus Torvalds /* skip uaddr string */ 5406c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 5407c0eae66eSBenny Halevy if (unlikely(!p)) 5408eb72f484SChuck Lever return -EIO; 5409cccddf4fSBenny Halevy len = be32_to_cpup(p); 5410c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 5411c0eae66eSBenny Halevy if (unlikely(!p)) 5412eb72f484SChuck Lever return -EIO; 54131da177e4SLinus Torvalds return -NFSERR_CLID_INUSE; 54141da177e4SLinus Torvalds } else 5415856dff3dSBenny Halevy return nfs4_stat_to_errno(nfserr); 54161da177e4SLinus Torvalds 54171da177e4SLinus Torvalds return 0; 54181da177e4SLinus Torvalds } 54191da177e4SLinus Torvalds 54201da177e4SLinus Torvalds static int decode_setclientid_confirm(struct xdr_stream *xdr) 54211da177e4SLinus Torvalds { 54221da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM); 54231da177e4SLinus Torvalds } 54241da177e4SLinus Torvalds 54259137bdf3SAnna Schumaker static int decode_write(struct xdr_stream *xdr, struct nfs_pgio_res *res) 54261da177e4SLinus Torvalds { 54278687b63aSAl Viro __be32 *p; 54281da177e4SLinus Torvalds int status; 54291da177e4SLinus Torvalds 54301da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_WRITE); 54311da177e4SLinus Torvalds if (status) 54321da177e4SLinus Torvalds return status; 54331da177e4SLinus Torvalds 54342f2c63bcSTrond Myklebust p = xdr_inline_decode(xdr, 8); 5435c0eae66eSBenny Halevy if (unlikely(!p)) 5436eb72f484SChuck Lever return -EIO; 54376f723f77SBenny Halevy res->count = be32_to_cpup(p++); 54386f723f77SBenny Halevy res->verf->committed = be32_to_cpup(p++); 54392f2c63bcSTrond Myklebust return decode_write_verifier(xdr, &res->verf->verifier); 54401da177e4SLinus Torvalds } 54411da177e4SLinus Torvalds 54421da177e4SLinus Torvalds static int decode_delegreturn(struct xdr_stream *xdr) 54431da177e4SLinus Torvalds { 54441da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_DELEGRETURN); 54451da177e4SLinus Torvalds } 54461da177e4SLinus Torvalds 5447fb15b26fSChuck Lever static int decode_secinfo_gss(struct xdr_stream *xdr, 5448fb15b26fSChuck Lever struct nfs4_secinfo4 *flavor) 54495a5ea0d4SBryan Schumaker { 5450fb15b26fSChuck Lever u32 oid_len; 54515a5ea0d4SBryan Schumaker __be32 *p; 54525a5ea0d4SBryan Schumaker 54535a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 4); 54545a5ea0d4SBryan Schumaker if (unlikely(!p)) 5455eb72f484SChuck Lever return -EIO; 5456fb15b26fSChuck Lever oid_len = be32_to_cpup(p); 5457fb15b26fSChuck Lever if (oid_len > GSS_OID_MAX_LEN) 5458eb72f484SChuck Lever return -EINVAL; 54595a5ea0d4SBryan Schumaker 5460fb15b26fSChuck Lever p = xdr_inline_decode(xdr, oid_len); 54615a5ea0d4SBryan Schumaker if (unlikely(!p)) 5462eb72f484SChuck Lever return -EIO; 5463fb15b26fSChuck Lever memcpy(flavor->flavor_info.oid.data, p, oid_len); 5464fb15b26fSChuck Lever flavor->flavor_info.oid.len = oid_len; 54655a5ea0d4SBryan Schumaker 54665a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 8); 54675a5ea0d4SBryan Schumaker if (unlikely(!p)) 5468eb72f484SChuck Lever return -EIO; 5469fb15b26fSChuck Lever flavor->flavor_info.qop = be32_to_cpup(p++); 5470fb15b26fSChuck Lever flavor->flavor_info.service = be32_to_cpup(p); 54715a5ea0d4SBryan Schumaker 54725a5ea0d4SBryan Schumaker return 0; 54735a5ea0d4SBryan Schumaker } 54745a5ea0d4SBryan Schumaker 547531e4dda4SBryan Schumaker static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) 54765a5ea0d4SBryan Schumaker { 5477fb15b26fSChuck Lever struct nfs4_secinfo4 *sec_flavor; 5478fb15b26fSChuck Lever unsigned int i, num_flavors; 54795a5ea0d4SBryan Schumaker int status; 54805a5ea0d4SBryan Schumaker __be32 *p; 54815a5ea0d4SBryan Schumaker 54825a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 4); 54835a5ea0d4SBryan Schumaker if (unlikely(!p)) 5484eb72f484SChuck Lever return -EIO; 54855a5ea0d4SBryan Schumaker 5486c3dfc280SBryan Schumaker res->flavors->num_flavors = 0; 5487c3dfc280SBryan Schumaker num_flavors = be32_to_cpup(p); 5488c3dfc280SBryan Schumaker 5489c3dfc280SBryan Schumaker for (i = 0; i < num_flavors; i++) { 54905a5ea0d4SBryan Schumaker sec_flavor = &res->flavors->flavors[i]; 5491c3dfc280SBryan Schumaker if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE) 54925a5ea0d4SBryan Schumaker break; 54935a5ea0d4SBryan Schumaker 54945a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 4); 54955a5ea0d4SBryan Schumaker if (unlikely(!p)) 5496eb72f484SChuck Lever return -EIO; 54975a5ea0d4SBryan Schumaker sec_flavor->flavor = be32_to_cpup(p); 54985a5ea0d4SBryan Schumaker 54995a5ea0d4SBryan Schumaker if (sec_flavor->flavor == RPC_AUTH_GSS) { 5500613e901eSBryan Schumaker status = decode_secinfo_gss(xdr, sec_flavor); 5501613e901eSBryan Schumaker if (status) 5502613e901eSBryan Schumaker goto out; 55035a5ea0d4SBryan Schumaker } 5504c3dfc280SBryan Schumaker res->flavors->num_flavors++; 55055a5ea0d4SBryan Schumaker } 55065a5ea0d4SBryan Schumaker 550731e4dda4SBryan Schumaker status = 0; 5508613e901eSBryan Schumaker out: 5509613e901eSBryan Schumaker return status; 55105a5ea0d4SBryan Schumaker } 55115a5ea0d4SBryan Schumaker 551231e4dda4SBryan Schumaker static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) 551331e4dda4SBryan Schumaker { 551431e4dda4SBryan Schumaker int status = decode_op_hdr(xdr, OP_SECINFO); 551531e4dda4SBryan Schumaker if (status) 551631e4dda4SBryan Schumaker return status; 551731e4dda4SBryan Schumaker return decode_secinfo_common(xdr, res); 551831e4dda4SBryan Schumaker } 551931e4dda4SBryan Schumaker 552099fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 552131e4dda4SBryan Schumaker static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) 552231e4dda4SBryan Schumaker { 552331e4dda4SBryan Schumaker int status = decode_op_hdr(xdr, OP_SECINFO_NO_NAME); 552431e4dda4SBryan Schumaker if (status) 552531e4dda4SBryan Schumaker return status; 552631e4dda4SBryan Schumaker return decode_secinfo_common(xdr, res); 552731e4dda4SBryan Schumaker } 552831e4dda4SBryan Schumaker 55292031cd1aSWeston Andros Adamson static int decode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map) 55302031cd1aSWeston Andros Adamson { 55312031cd1aSWeston Andros Adamson __be32 *p; 55322031cd1aSWeston Andros Adamson uint32_t bitmap_words; 55332031cd1aSWeston Andros Adamson unsigned int i; 55342031cd1aSWeston Andros Adamson 55352031cd1aSWeston Andros Adamson p = xdr_inline_decode(xdr, 4); 55364edabfd7SPan Bian if (!p) 55374edabfd7SPan Bian return -EIO; 55382031cd1aSWeston Andros Adamson bitmap_words = be32_to_cpup(p++); 55392031cd1aSWeston Andros Adamson if (bitmap_words > NFS4_OP_MAP_NUM_WORDS) 55402031cd1aSWeston Andros Adamson return -EIO; 55412031cd1aSWeston Andros Adamson p = xdr_inline_decode(xdr, 4 * bitmap_words); 55422031cd1aSWeston Andros Adamson for (i = 0; i < bitmap_words; i++) 55432031cd1aSWeston Andros Adamson op_map->u.words[i] = be32_to_cpup(p++); 55442031cd1aSWeston Andros Adamson 55452031cd1aSWeston Andros Adamson return 0; 55462031cd1aSWeston Andros Adamson } 55472031cd1aSWeston Andros Adamson 554899fe60d0SBenny Halevy static int decode_exchange_id(struct xdr_stream *xdr, 554999fe60d0SBenny Halevy struct nfs41_exchange_id_res *res) 555099fe60d0SBenny Halevy { 555199fe60d0SBenny Halevy __be32 *p; 555299fe60d0SBenny Halevy uint32_t dummy; 55532460ba57SBenny Halevy char *dummy_str; 555499fe60d0SBenny Halevy int status; 55557d2ed9acSWeston Andros Adamson uint32_t impl_id_count; 555699fe60d0SBenny Halevy 555799fe60d0SBenny Halevy status = decode_op_hdr(xdr, OP_EXCHANGE_ID); 555899fe60d0SBenny Halevy if (status) 555999fe60d0SBenny Halevy return status; 556099fe60d0SBenny Halevy 5561c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5562c0eae66eSBenny Halevy if (unlikely(!p)) 5563eb72f484SChuck Lever return -EIO; 556432b01310STrond Myklebust xdr_decode_hyper(p, &res->clientid); 5565c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 5566c0eae66eSBenny Halevy if (unlikely(!p)) 5567eb72f484SChuck Lever return -EIO; 556832b01310STrond Myklebust res->seqid = be32_to_cpup(p++); 556932b01310STrond Myklebust res->flags = be32_to_cpup(p++); 557099fe60d0SBenny Halevy 55712031cd1aSWeston Andros Adamson res->state_protect.how = be32_to_cpup(p); 55722031cd1aSWeston Andros Adamson switch (res->state_protect.how) { 55732031cd1aSWeston Andros Adamson case SP4_NONE: 55742031cd1aSWeston Andros Adamson break; 55752031cd1aSWeston Andros Adamson case SP4_MACH_CRED: 55762031cd1aSWeston Andros Adamson status = decode_op_map(xdr, &res->state_protect.enforce); 55772031cd1aSWeston Andros Adamson if (status) 55782031cd1aSWeston Andros Adamson return status; 55792031cd1aSWeston Andros Adamson status = decode_op_map(xdr, &res->state_protect.allow); 55802031cd1aSWeston Andros Adamson if (status) 55812031cd1aSWeston Andros Adamson return status; 55822031cd1aSWeston Andros Adamson break; 55832031cd1aSWeston Andros Adamson default: 55842031cd1aSWeston Andros Adamson WARN_ON_ONCE(1); 558599fe60d0SBenny Halevy return -EIO; 55862031cd1aSWeston Andros Adamson } 558799fe60d0SBenny Halevy 5588acdeb69dSChuck Lever /* server_owner4.so_minor_id */ 5589c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5590c0eae66eSBenny Halevy if (unlikely(!p)) 5591eb72f484SChuck Lever return -EIO; 5592acdeb69dSChuck Lever p = xdr_decode_hyper(p, &res->server_owner->minor_id); 559399fe60d0SBenny Halevy 5594acdeb69dSChuck Lever /* server_owner4.so_major_id */ 55952460ba57SBenny Halevy status = decode_opaque_inline(xdr, &dummy, &dummy_str); 55962460ba57SBenny Halevy if (unlikely(status)) 55972460ba57SBenny Halevy return status; 5598acdeb69dSChuck Lever memcpy(res->server_owner->major_id, dummy_str, dummy); 5599acdeb69dSChuck Lever res->server_owner->major_id_sz = dummy; 560078fe0f41SWeston Andros Adamson 5601acdeb69dSChuck Lever /* server_scope4 */ 5602acdeb69dSChuck Lever status = decode_opaque_inline(xdr, &dummy, &dummy_str); 5603acdeb69dSChuck Lever if (unlikely(status)) 5604acdeb69dSChuck Lever return status; 560578fe0f41SWeston Andros Adamson memcpy(res->server_scope->server_scope, dummy_str, dummy); 560678fe0f41SWeston Andros Adamson res->server_scope->server_scope_sz = dummy; 560778fe0f41SWeston Andros Adamson 56087d2ed9acSWeston Andros Adamson /* Implementation Id */ 56097d2ed9acSWeston Andros Adamson p = xdr_inline_decode(xdr, 4); 56107d2ed9acSWeston Andros Adamson if (unlikely(!p)) 5611eb72f484SChuck Lever return -EIO; 56127d2ed9acSWeston Andros Adamson impl_id_count = be32_to_cpup(p++); 56137d2ed9acSWeston Andros Adamson 56147d2ed9acSWeston Andros Adamson if (impl_id_count) { 56157d2ed9acSWeston Andros Adamson /* nii_domain */ 56162460ba57SBenny Halevy status = decode_opaque_inline(xdr, &dummy, &dummy_str); 56172460ba57SBenny Halevy if (unlikely(status)) 56182460ba57SBenny Halevy return status; 56197d2ed9acSWeston Andros Adamson memcpy(res->impl_id->domain, dummy_str, dummy); 562099fe60d0SBenny Halevy 56217d2ed9acSWeston Andros Adamson /* nii_name */ 56227d2ed9acSWeston Andros Adamson status = decode_opaque_inline(xdr, &dummy, &dummy_str); 56237d2ed9acSWeston Andros Adamson if (unlikely(status)) 56247d2ed9acSWeston Andros Adamson return status; 56257d2ed9acSWeston Andros Adamson memcpy(res->impl_id->name, dummy_str, dummy); 56267d2ed9acSWeston Andros Adamson 56277d2ed9acSWeston Andros Adamson /* nii_date */ 56287d2ed9acSWeston Andros Adamson p = xdr_inline_decode(xdr, 12); 56297d2ed9acSWeston Andros Adamson if (unlikely(!p)) 5630eb72f484SChuck Lever return -EIO; 56317d2ed9acSWeston Andros Adamson p = xdr_decode_hyper(p, &res->impl_id->date.seconds); 56327d2ed9acSWeston Andros Adamson res->impl_id->date.nseconds = be32_to_cpup(p); 56337d2ed9acSWeston Andros Adamson 56347d2ed9acSWeston Andros Adamson /* if there's more than one entry, ignore the rest */ 56357d2ed9acSWeston Andros Adamson } 563699fe60d0SBenny Halevy return 0; 563799fe60d0SBenny Halevy } 5638fc931582SAndy Adamson 5639fc931582SAndy Adamson static int decode_chan_attrs(struct xdr_stream *xdr, 5640fc931582SAndy Adamson struct nfs4_channel_attrs *attrs) 5641fc931582SAndy Adamson { 5642fc931582SAndy Adamson __be32 *p; 5643c9c30dd5SBenny Halevy u32 nr_attrs, val; 5644fc931582SAndy Adamson 5645c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 28); 5646c0eae66eSBenny Halevy if (unlikely(!p)) 5647eb72f484SChuck Lever return -EIO; 5648c9c30dd5SBenny Halevy val = be32_to_cpup(p++); /* headerpadsz */ 5649c9c30dd5SBenny Halevy if (val) 5650c9c30dd5SBenny Halevy return -EINVAL; /* no support for header padding yet */ 56516f723f77SBenny Halevy attrs->max_rqst_sz = be32_to_cpup(p++); 56526f723f77SBenny Halevy attrs->max_resp_sz = be32_to_cpup(p++); 56536f723f77SBenny Halevy attrs->max_resp_sz_cached = be32_to_cpup(p++); 56546f723f77SBenny Halevy attrs->max_ops = be32_to_cpup(p++); 56556f723f77SBenny Halevy attrs->max_reqs = be32_to_cpup(p++); 5656cccddf4fSBenny Halevy nr_attrs = be32_to_cpup(p); 5657fc931582SAndy Adamson if (unlikely(nr_attrs > 1)) { 5658a030889aSWeston Andros Adamson printk(KERN_WARNING "NFS: %s: Invalid rdma channel attrs " 5659a030889aSWeston Andros Adamson "count %u\n", __func__, nr_attrs); 5660fc931582SAndy Adamson return -EINVAL; 5661fc931582SAndy Adamson } 5662c0eae66eSBenny Halevy if (nr_attrs == 1) { 5663c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */ 5664c0eae66eSBenny Halevy if (unlikely(!p)) 5665eb72f484SChuck Lever return -EIO; 5666c0eae66eSBenny Halevy } 5667fc931582SAndy Adamson return 0; 5668fc931582SAndy Adamson } 5669fc931582SAndy Adamson 5670e78291e4SBenny Halevy static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid) 5671e78291e4SBenny Halevy { 5672e78291e4SBenny Halevy return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN); 5673fc931582SAndy Adamson } 5674fc931582SAndy Adamson 56757c44f1aeSWeston Andros Adamson static int decode_bind_conn_to_session(struct xdr_stream *xdr, 56767c44f1aeSWeston Andros Adamson struct nfs41_bind_conn_to_session_res *res) 56777c44f1aeSWeston Andros Adamson { 56787c44f1aeSWeston Andros Adamson __be32 *p; 56797c44f1aeSWeston Andros Adamson int status; 56807c44f1aeSWeston Andros Adamson 56817c44f1aeSWeston Andros Adamson status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION); 56827c44f1aeSWeston Andros Adamson if (!status) 568371a097c6STrond Myklebust status = decode_sessionid(xdr, &res->sessionid); 56847c44f1aeSWeston Andros Adamson if (unlikely(status)) 56857c44f1aeSWeston Andros Adamson return status; 56867c44f1aeSWeston Andros Adamson 56877c44f1aeSWeston Andros Adamson /* dir flags, rdma mode bool */ 56887c44f1aeSWeston Andros Adamson p = xdr_inline_decode(xdr, 8); 56897c44f1aeSWeston Andros Adamson if (unlikely(!p)) 5690eb72f484SChuck Lever return -EIO; 56917c44f1aeSWeston Andros Adamson 56927c44f1aeSWeston Andros Adamson res->dir = be32_to_cpup(p++); 56937c44f1aeSWeston Andros Adamson if (res->dir == 0 || res->dir > NFS4_CDFS4_BOTH) 56947c44f1aeSWeston Andros Adamson return -EIO; 56957c44f1aeSWeston Andros Adamson if (be32_to_cpup(p) == 0) 56967c44f1aeSWeston Andros Adamson res->use_conn_in_rdma_mode = false; 56977c44f1aeSWeston Andros Adamson else 56987c44f1aeSWeston Andros Adamson res->use_conn_in_rdma_mode = true; 56997c44f1aeSWeston Andros Adamson 57007c44f1aeSWeston Andros Adamson return 0; 57017c44f1aeSWeston Andros Adamson } 57027c44f1aeSWeston Andros Adamson 5703fc931582SAndy Adamson static int decode_create_session(struct xdr_stream *xdr, 5704fc931582SAndy Adamson struct nfs41_create_session_res *res) 5705fc931582SAndy Adamson { 5706fc931582SAndy Adamson __be32 *p; 5707fc931582SAndy Adamson int status; 5708fc931582SAndy Adamson 5709fc931582SAndy Adamson status = decode_op_hdr(xdr, OP_CREATE_SESSION); 5710e78291e4SBenny Halevy if (!status) 571179969dd1STrond Myklebust status = decode_sessionid(xdr, &res->sessionid); 5712e78291e4SBenny Halevy if (unlikely(status)) 5713fc931582SAndy Adamson return status; 5714fc931582SAndy Adamson 5715fc931582SAndy Adamson /* seqid, flags */ 5716c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5717c0eae66eSBenny Halevy if (unlikely(!p)) 5718eb72f484SChuck Lever return -EIO; 571979969dd1STrond Myklebust res->seqid = be32_to_cpup(p++); 572079969dd1STrond Myklebust res->flags = be32_to_cpup(p); 5721fc931582SAndy Adamson 5722fc931582SAndy Adamson /* Channel attributes */ 572379969dd1STrond Myklebust status = decode_chan_attrs(xdr, &res->fc_attrs); 5724fc931582SAndy Adamson if (!status) 572579969dd1STrond Myklebust status = decode_chan_attrs(xdr, &res->bc_attrs); 5726fc931582SAndy Adamson return status; 5727fc931582SAndy Adamson } 57280f3e66c6SAndy Adamson 57290f3e66c6SAndy Adamson static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) 57300f3e66c6SAndy Adamson { 57310f3e66c6SAndy Adamson return decode_op_hdr(xdr, OP_DESTROY_SESSION); 57320f3e66c6SAndy Adamson } 573318019753SRicardo Labiaga 573466245539STrond Myklebust static int decode_destroy_clientid(struct xdr_stream *xdr, void *dummy) 573566245539STrond Myklebust { 573666245539STrond Myklebust return decode_op_hdr(xdr, OP_DESTROY_CLIENTID); 573766245539STrond Myklebust } 573866245539STrond Myklebust 573918019753SRicardo Labiaga static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) 574018019753SRicardo Labiaga { 574118019753SRicardo Labiaga return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); 574218019753SRicardo Labiaga } 574399fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 574499fe60d0SBenny Halevy 57459b7b9fccSAndy Adamson static int decode_sequence(struct xdr_stream *xdr, 57469b7b9fccSAndy Adamson struct nfs4_sequence_res *res, 57479b7b9fccSAndy Adamson struct rpc_rqst *rqstp) 57489b7b9fccSAndy Adamson { 57499b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 5750e3725ec0STrond Myklebust struct nfs4_session *session; 5751fc01cea9SAndy Adamson struct nfs4_sessionid id; 5752fc01cea9SAndy Adamson u32 dummy; 5753fc01cea9SAndy Adamson int status; 5754fc01cea9SAndy Adamson __be32 *p; 5755fc01cea9SAndy Adamson 5756e3725ec0STrond Myklebust if (res->sr_slot == NULL) 57579b7b9fccSAndy Adamson return 0; 57583bd2384aSChuck Lever if (!res->sr_slot->table->session) 57593bd2384aSChuck Lever return 0; 57609b7b9fccSAndy Adamson 5761fc01cea9SAndy Adamson status = decode_op_hdr(xdr, OP_SEQUENCE); 5762e78291e4SBenny Halevy if (!status) 5763e78291e4SBenny Halevy status = decode_sessionid(xdr, &id); 5764e78291e4SBenny Halevy if (unlikely(status)) 5765fc01cea9SAndy Adamson goto out_err; 57669b7b9fccSAndy Adamson 5767fc01cea9SAndy Adamson /* 5768fc01cea9SAndy Adamson * If the server returns different values for sessionID, slotID or 5769fc01cea9SAndy Adamson * sequence number, the server is looney tunes. 5770fc01cea9SAndy Adamson */ 5771fdcb4577STrond Myklebust status = -EREMOTEIO; 5772e3725ec0STrond Myklebust session = res->sr_slot->table->session; 5773fc01cea9SAndy Adamson 5774e3725ec0STrond Myklebust if (memcmp(id.data, session->sess_id.data, 5775fc01cea9SAndy Adamson NFS4_MAX_SESSIONID_LEN)) { 5776fc01cea9SAndy Adamson dprintk("%s Invalid session id\n", __func__); 5777fc01cea9SAndy Adamson goto out_err; 5778fc01cea9SAndy Adamson } 5779e78291e4SBenny Halevy 5780c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 20); 5781c0eae66eSBenny Halevy if (unlikely(!p)) 5782c0eae66eSBenny Halevy goto out_overflow; 5783e78291e4SBenny Halevy 5784fc01cea9SAndy Adamson /* seqid */ 57856f723f77SBenny Halevy dummy = be32_to_cpup(p++); 5786dfb4f309SBenny Halevy if (dummy != res->sr_slot->seq_nr) { 5787fc01cea9SAndy Adamson dprintk("%s Invalid sequence number\n", __func__); 5788fc01cea9SAndy Adamson goto out_err; 5789fc01cea9SAndy Adamson } 5790fc01cea9SAndy Adamson /* slot id */ 57916f723f77SBenny Halevy dummy = be32_to_cpup(p++); 5792df2fabffSTrond Myklebust if (dummy != res->sr_slot->slot_nr) { 5793fc01cea9SAndy Adamson dprintk("%s Invalid slot id\n", __func__); 5794fc01cea9SAndy Adamson goto out_err; 5795fc01cea9SAndy Adamson } 5796da0507b7STrond Myklebust /* highest slot id */ 5797da0507b7STrond Myklebust res->sr_highest_slotid = be32_to_cpup(p++); 5798464ee9f9STrond Myklebust /* target highest slot id */ 5799464ee9f9STrond Myklebust res->sr_target_highest_slotid = be32_to_cpup(p++); 58000629e370SAlexandros Batsakis /* result flags */ 58010629e370SAlexandros Batsakis res->sr_status_flags = be32_to_cpup(p); 5802fc01cea9SAndy Adamson status = 0; 5803fc01cea9SAndy Adamson out_err: 5804fc01cea9SAndy Adamson res->sr_status = status; 5805fc01cea9SAndy Adamson return status; 5806c0eae66eSBenny Halevy out_overflow: 5807c0eae66eSBenny Halevy status = -EIO; 5808c0eae66eSBenny Halevy goto out_err; 5809fc01cea9SAndy Adamson #else /* CONFIG_NFS_V4_1 */ 58109b7b9fccSAndy Adamson return 0; 5811fc01cea9SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 58129b7b9fccSAndy Adamson } 58139b7b9fccSAndy Adamson 5814b1f69b75SAndy Adamson #if defined(CONFIG_NFS_V4_1) 581593b717fdSTrond Myklebust static int decode_layout_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 581693b717fdSTrond Myklebust { 581793b717fdSTrond Myklebust stateid->type = NFS4_LAYOUT_STATEID_TYPE; 581893b717fdSTrond Myklebust return decode_stateid(xdr, stateid); 581993b717fdSTrond Myklebust } 582093b717fdSTrond Myklebust 5821b1f69b75SAndy Adamson static int decode_getdeviceinfo(struct xdr_stream *xdr, 58224e590803STrond Myklebust struct nfs4_getdeviceinfo_res *res) 5823b1f69b75SAndy Adamson { 58244e590803STrond Myklebust struct pnfs_device *pdev = res->pdev; 5825b1f69b75SAndy Adamson __be32 *p; 5826b1f69b75SAndy Adamson uint32_t len, type; 5827b1f69b75SAndy Adamson int status; 5828b1f69b75SAndy Adamson 5829b1f69b75SAndy Adamson status = decode_op_hdr(xdr, OP_GETDEVICEINFO); 5830b1f69b75SAndy Adamson if (status) { 5831b1f69b75SAndy Adamson if (status == -ETOOSMALL) { 5832b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4); 5833b1f69b75SAndy Adamson if (unlikely(!p)) 5834eb72f484SChuck Lever return -EIO; 5835b1f69b75SAndy Adamson pdev->mincount = be32_to_cpup(p); 5836b1f69b75SAndy Adamson dprintk("%s: Min count too small. mincnt = %u\n", 5837b1f69b75SAndy Adamson __func__, pdev->mincount); 5838b1f69b75SAndy Adamson } 5839b1f69b75SAndy Adamson return status; 5840b1f69b75SAndy Adamson } 5841b1f69b75SAndy Adamson 5842b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 8); 5843b1f69b75SAndy Adamson if (unlikely(!p)) 5844eb72f484SChuck Lever return -EIO; 5845b1f69b75SAndy Adamson type = be32_to_cpup(p++); 5846b1f69b75SAndy Adamson if (type != pdev->layout_type) { 5847b1f69b75SAndy Adamson dprintk("%s: layout mismatch req: %u pdev: %u\n", 5848b1f69b75SAndy Adamson __func__, pdev->layout_type, type); 5849b1f69b75SAndy Adamson return -EINVAL; 5850b1f69b75SAndy Adamson } 5851b1f69b75SAndy Adamson /* 5852b1f69b75SAndy Adamson * Get the length of the opaque device_addr4. xdr_read_pages places 5853b1f69b75SAndy Adamson * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages) 5854b1f69b75SAndy Adamson * and places the remaining xdr data in xdr_buf->tail 5855b1f69b75SAndy Adamson */ 5856b1f69b75SAndy Adamson pdev->mincount = be32_to_cpup(p); 585713fe4ba1STrond Myklebust if (xdr_read_pages(xdr, pdev->mincount) != pdev->mincount) 5858eb72f484SChuck Lever return -EIO; 5859b1f69b75SAndy Adamson 5860b1f69b75SAndy Adamson /* Parse notification bitmap, verifying that it is zero. */ 5861b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4); 5862b1f69b75SAndy Adamson if (unlikely(!p)) 5863eb72f484SChuck Lever return -EIO; 5864b1f69b75SAndy Adamson len = be32_to_cpup(p); 5865b1f69b75SAndy Adamson if (len) { 5866ead00597SChuck Lever uint32_t i; 5867b1f69b75SAndy Adamson 5868b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4 * len); 5869b1f69b75SAndy Adamson if (unlikely(!p)) 5870eb72f484SChuck Lever return -EIO; 587184c9dee3SChristoph Hellwig 58724e590803STrond Myklebust res->notification = be32_to_cpup(p++); 587384c9dee3SChristoph Hellwig for (i = 1; i < len; i++) { 587484c9dee3SChristoph Hellwig if (be32_to_cpup(p++)) { 587584c9dee3SChristoph Hellwig dprintk("%s: unsupported notification\n", 5876b1f69b75SAndy Adamson __func__); 5877b1f69b75SAndy Adamson return -EIO; 5878b1f69b75SAndy Adamson } 5879b1f69b75SAndy Adamson } 5880b1f69b75SAndy Adamson } 5881b1f69b75SAndy Adamson return 0; 5882b1f69b75SAndy Adamson } 5883b1f69b75SAndy Adamson 5884b1f69b75SAndy Adamson static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, 5885b1f69b75SAndy Adamson struct nfs4_layoutget_res *res) 5886b1f69b75SAndy Adamson { 5887b1f69b75SAndy Adamson __be32 *p; 5888b1f69b75SAndy Adamson int status; 5889b1f69b75SAndy Adamson u32 layout_count; 589064bd577eSTrond Myklebust u32 recvd; 5891b1f69b75SAndy Adamson 5892b1f69b75SAndy Adamson status = decode_op_hdr(xdr, OP_LAYOUTGET); 5893b1f69b75SAndy Adamson if (status) 5894808ba32aSFred Isaman goto out; 5895ea9d23f5STrond Myklebust p = xdr_inline_decode(xdr, 4); 5896b1f69b75SAndy Adamson if (unlikely(!p)) 5897b1f69b75SAndy Adamson goto out_overflow; 5898ea9d23f5STrond Myklebust res->return_on_close = be32_to_cpup(p); 589993b717fdSTrond Myklebust decode_layout_stateid(xdr, &res->stateid); 5900ea9d23f5STrond Myklebust p = xdr_inline_decode(xdr, 4); 5901ea9d23f5STrond Myklebust if (unlikely(!p)) 5902ea9d23f5STrond Myklebust goto out_overflow; 5903b1f69b75SAndy Adamson layout_count = be32_to_cpup(p); 5904b1f69b75SAndy Adamson if (!layout_count) { 5905b1f69b75SAndy Adamson dprintk("%s: server responded with empty layout array\n", 5906b1f69b75SAndy Adamson __func__); 5907808ba32aSFred Isaman status = -EINVAL; 5908808ba32aSFred Isaman goto out; 5909b1f69b75SAndy Adamson } 5910b1f69b75SAndy Adamson 591135124a09SWeston Andros Adamson p = xdr_inline_decode(xdr, 28); 5912b1f69b75SAndy Adamson if (unlikely(!p)) 5913b1f69b75SAndy Adamson goto out_overflow; 5914b1f69b75SAndy Adamson p = xdr_decode_hyper(p, &res->range.offset); 5915b1f69b75SAndy Adamson p = xdr_decode_hyper(p, &res->range.length); 5916b1f69b75SAndy Adamson res->range.iomode = be32_to_cpup(p++); 5917b1f69b75SAndy Adamson res->type = be32_to_cpup(p++); 591835124a09SWeston Andros Adamson res->layoutp->len = be32_to_cpup(p); 5919b1f69b75SAndy Adamson 5920b1f69b75SAndy Adamson dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", 5921b1f69b75SAndy Adamson __func__, 5922b1f69b75SAndy Adamson (unsigned long)res->range.offset, 5923b1f69b75SAndy Adamson (unsigned long)res->range.length, 5924b1f69b75SAndy Adamson res->range.iomode, 5925b1f69b75SAndy Adamson res->type, 592635124a09SWeston Andros Adamson res->layoutp->len); 5927b1f69b75SAndy Adamson 592864bd577eSTrond Myklebust recvd = xdr_read_pages(xdr, res->layoutp->len); 592935124a09SWeston Andros Adamson if (res->layoutp->len > recvd) { 593035124a09SWeston Andros Adamson dprintk("NFS: server cheating in layoutget reply: " 593135124a09SWeston Andros Adamson "layout len %u > recvd %u\n", 593235124a09SWeston Andros Adamson res->layoutp->len, recvd); 5933808ba32aSFred Isaman status = -EINVAL; 5934808ba32aSFred Isaman goto out; 593535124a09SWeston Andros Adamson } 593635124a09SWeston Andros Adamson 5937b1f69b75SAndy Adamson if (layout_count > 1) { 5938b1f69b75SAndy Adamson /* We only handle a length one array at the moment. Any 5939b1f69b75SAndy Adamson * further entries are just ignored. Note that this means 5940b1f69b75SAndy Adamson * the client may see a response that is less than the 5941b1f69b75SAndy Adamson * minimum it requested. 5942b1f69b75SAndy Adamson */ 5943b1f69b75SAndy Adamson dprintk("%s: server responded with %d layouts, dropping tail\n", 5944b1f69b75SAndy Adamson __func__, layout_count); 5945b1f69b75SAndy Adamson } 5946b1f69b75SAndy Adamson 5947808ba32aSFred Isaman out: 5948808ba32aSFred Isaman res->status = status; 5949808ba32aSFred Isaman return status; 5950b1f69b75SAndy Adamson out_overflow: 5951808ba32aSFred Isaman status = -EIO; 5952808ba32aSFred Isaman goto out; 5953b1f69b75SAndy Adamson } 5954863a3c6cSAndy Adamson 5955cbe82603SBenny Halevy static int decode_layoutreturn(struct xdr_stream *xdr, 5956cbe82603SBenny Halevy struct nfs4_layoutreturn_res *res) 5957cbe82603SBenny Halevy { 5958cbe82603SBenny Halevy __be32 *p; 5959cbe82603SBenny Halevy int status; 5960cbe82603SBenny Halevy 5961cbe82603SBenny Halevy status = decode_op_hdr(xdr, OP_LAYOUTRETURN); 5962cbe82603SBenny Halevy if (status) 5963cbe82603SBenny Halevy return status; 5964cbe82603SBenny Halevy p = xdr_inline_decode(xdr, 4); 5965cbe82603SBenny Halevy if (unlikely(!p)) 5966eb72f484SChuck Lever return -EIO; 5967cbe82603SBenny Halevy res->lrs_present = be32_to_cpup(p); 5968cbe82603SBenny Halevy if (res->lrs_present) 596993b717fdSTrond Myklebust status = decode_layout_stateid(xdr, &res->stateid); 5970fcd8843cSTrond Myklebust else 5971fcd8843cSTrond Myklebust nfs4_stateid_copy(&res->stateid, &invalid_stateid); 5972cbe82603SBenny Halevy return status; 5973cbe82603SBenny Halevy } 5974cbe82603SBenny Halevy 5975863a3c6cSAndy Adamson static int decode_layoutcommit(struct xdr_stream *xdr, 5976863a3c6cSAndy Adamson struct rpc_rqst *req, 5977863a3c6cSAndy Adamson struct nfs4_layoutcommit_res *res) 5978863a3c6cSAndy Adamson { 5979863a3c6cSAndy Adamson __be32 *p; 5980863a3c6cSAndy Adamson __u32 sizechanged; 5981863a3c6cSAndy Adamson int status; 5982863a3c6cSAndy Adamson 5983863a3c6cSAndy Adamson status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); 5984db29c089SAndy Adamson res->status = status; 5985863a3c6cSAndy Adamson if (status) 5986863a3c6cSAndy Adamson return status; 5987863a3c6cSAndy Adamson 5988863a3c6cSAndy Adamson p = xdr_inline_decode(xdr, 4); 5989863a3c6cSAndy Adamson if (unlikely(!p)) 5990eb72f484SChuck Lever return -EIO; 5991863a3c6cSAndy Adamson sizechanged = be32_to_cpup(p); 5992863a3c6cSAndy Adamson 5993863a3c6cSAndy Adamson if (sizechanged) { 5994863a3c6cSAndy Adamson /* throw away new size */ 5995863a3c6cSAndy Adamson p = xdr_inline_decode(xdr, 8); 5996863a3c6cSAndy Adamson if (unlikely(!p)) 5997eb72f484SChuck Lever return -EIO; 5998863a3c6cSAndy Adamson } 5999863a3c6cSAndy Adamson return 0; 6000863a3c6cSAndy Adamson } 60017d974794SBryan Schumaker 60027d974794SBryan Schumaker static int decode_test_stateid(struct xdr_stream *xdr, 60037d974794SBryan Schumaker struct nfs41_test_stateid_res *res) 60047d974794SBryan Schumaker { 60057d974794SBryan Schumaker __be32 *p; 60067d974794SBryan Schumaker int status; 60077d974794SBryan Schumaker int num_res; 60087d974794SBryan Schumaker 60097d974794SBryan Schumaker status = decode_op_hdr(xdr, OP_TEST_STATEID); 60107d974794SBryan Schumaker if (status) 60117d974794SBryan Schumaker return status; 60127d974794SBryan Schumaker 60137d974794SBryan Schumaker p = xdr_inline_decode(xdr, 4); 60147d974794SBryan Schumaker if (unlikely(!p)) 6015eb72f484SChuck Lever return -EIO; 60167d974794SBryan Schumaker num_res = be32_to_cpup(p++); 60177d974794SBryan Schumaker if (num_res != 1) 6018eb72f484SChuck Lever return -EIO; 60197d974794SBryan Schumaker 60207d974794SBryan Schumaker p = xdr_inline_decode(xdr, 4); 60217d974794SBryan Schumaker if (unlikely(!p)) 6022eb72f484SChuck Lever return -EIO; 60237d974794SBryan Schumaker res->status = be32_to_cpup(p++); 60241cab0652SBryan Schumaker 60251cab0652SBryan Schumaker return status; 60267d974794SBryan Schumaker } 60279aeda35fSBryan Schumaker 60289aeda35fSBryan Schumaker static int decode_free_stateid(struct xdr_stream *xdr, 60299aeda35fSBryan Schumaker struct nfs41_free_stateid_res *res) 60309aeda35fSBryan Schumaker { 60319f79fb48SAndy Adamson res->status = decode_op_hdr(xdr, OP_FREE_STATEID); 60329aeda35fSBryan Schumaker return res->status; 60339aeda35fSBryan Schumaker } 6034cf805165STrond Myklebust #else 6035cf805165STrond Myklebust static inline 6036cf805165STrond Myklebust int decode_layoutreturn(struct xdr_stream *xdr, 6037cf805165STrond Myklebust struct nfs4_layoutreturn_res *res) 6038cf805165STrond Myklebust { 6039cf805165STrond Myklebust return 0; 6040cf805165STrond Myklebust } 604156f487f8SFred Isaman 604256f487f8SFred Isaman static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, 604356f487f8SFred Isaman struct nfs4_layoutget_res *res) 604456f487f8SFred Isaman { 604556f487f8SFred Isaman return 0; 604656f487f8SFred Isaman } 604756f487f8SFred Isaman 6048b1f69b75SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 6049b1f69b75SAndy Adamson 60501da177e4SLinus Torvalds /* 605149c2559eSBenny Halevy * END OF "GENERIC" DECODE ROUTINES. 605249c2559eSBenny Halevy */ 605349c2559eSBenny Halevy 605449c2559eSBenny Halevy /* 60551da177e4SLinus Torvalds * Decode OPEN_DOWNGRADE response 60561da177e4SLinus Torvalds */ 6057bf269551SChuck Lever static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, 6058bf269551SChuck Lever struct xdr_stream *xdr, 6059fc016483SChristoph Hellwig void *data) 60601da177e4SLinus Torvalds { 6061fc016483SChristoph Hellwig struct nfs_closeres *res = data; 60621da177e4SLinus Torvalds struct compound_hdr hdr; 60631da177e4SLinus Torvalds int status; 60641da177e4SLinus Torvalds 6065bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 60661da177e4SLinus Torvalds if (status) 60671da177e4SLinus Torvalds goto out; 6068bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 60699b7b9fccSAndy Adamson if (status) 60709b7b9fccSAndy Adamson goto out; 6071bf269551SChuck Lever status = decode_putfh(xdr); 60721da177e4SLinus Torvalds if (status) 60731da177e4SLinus Torvalds goto out; 6074b6808145STrond Myklebust if (res->lr_res) { 6075b6808145STrond Myklebust status = decode_layoutreturn(xdr, res->lr_res); 6076b6808145STrond Myklebust res->lr_ret = status; 6077b6808145STrond Myklebust if (status) 6078b6808145STrond Myklebust goto out; 6079b6808145STrond Myklebust } 6080bf269551SChuck Lever status = decode_open_downgrade(xdr, res); 60811da177e4SLinus Torvalds out: 60821da177e4SLinus Torvalds return status; 60831da177e4SLinus Torvalds } 60841da177e4SLinus Torvalds 60851da177e4SLinus Torvalds /* 60861da177e4SLinus Torvalds * Decode ACCESS response 60871da177e4SLinus Torvalds */ 6088bf269551SChuck Lever static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6089fc016483SChristoph Hellwig void *data) 60901da177e4SLinus Torvalds { 6091fc016483SChristoph Hellwig struct nfs4_accessres *res = data; 60921da177e4SLinus Torvalds struct compound_hdr hdr; 60931da177e4SLinus Torvalds int status; 60941da177e4SLinus Torvalds 6095bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 60969b7b9fccSAndy Adamson if (status) 60979b7b9fccSAndy Adamson goto out; 6098bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 60999b7b9fccSAndy Adamson if (status) 61001da177e4SLinus Torvalds goto out; 6101bf269551SChuck Lever status = decode_putfh(xdr); 610276b32999STrond Myklebust if (status != 0) 610376b32999STrond Myklebust goto out; 61046168f62cSWeston Andros Adamson status = decode_access(xdr, &res->supported, &res->access); 610576b32999STrond Myklebust if (status != 0) 610676b32999STrond Myklebust goto out; 61078bcbe7d9STrond Myklebust if (res->fattr) 61086926afd1STrond Myklebust decode_getfattr(xdr, res->fattr, res->server); 61091da177e4SLinus Torvalds out: 61101da177e4SLinus Torvalds return status; 61111da177e4SLinus Torvalds } 61121da177e4SLinus Torvalds 61131da177e4SLinus Torvalds /* 61141da177e4SLinus Torvalds * Decode LOOKUP response 61151da177e4SLinus Torvalds */ 6116bf269551SChuck Lever static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6117fc016483SChristoph Hellwig void *data) 61181da177e4SLinus Torvalds { 6119fc016483SChristoph Hellwig struct nfs4_lookup_res *res = data; 61201da177e4SLinus Torvalds struct compound_hdr hdr; 61211da177e4SLinus Torvalds int status; 61221da177e4SLinus Torvalds 6123bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 61249b7b9fccSAndy Adamson if (status) 61259b7b9fccSAndy Adamson goto out; 6126bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 61279b7b9fccSAndy Adamson if (status) 61281da177e4SLinus Torvalds goto out; 6129bf269551SChuck Lever status = decode_putfh(xdr); 6130bf269551SChuck Lever if (status) 61311da177e4SLinus Torvalds goto out; 6132bf269551SChuck Lever status = decode_lookup(xdr); 6133bf269551SChuck Lever if (status) 61341da177e4SLinus Torvalds goto out; 6135bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 6136bf269551SChuck Lever if (status) 61371da177e4SLinus Torvalds goto out; 6138aa9c2669SDavid Quigley status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); 61391da177e4SLinus Torvalds out: 61401da177e4SLinus Torvalds return status; 61411da177e4SLinus Torvalds } 61421da177e4SLinus Torvalds 61431da177e4SLinus Torvalds /* 61445b5faaf6SJeff Layton * Decode LOOKUPP response 61455b5faaf6SJeff Layton */ 61465b5faaf6SJeff Layton static int nfs4_xdr_dec_lookupp(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 61475b5faaf6SJeff Layton void *data) 61485b5faaf6SJeff Layton { 61495b5faaf6SJeff Layton struct nfs4_lookupp_res *res = data; 61505b5faaf6SJeff Layton struct compound_hdr hdr; 61515b5faaf6SJeff Layton int status; 61525b5faaf6SJeff Layton 61535b5faaf6SJeff Layton status = decode_compound_hdr(xdr, &hdr); 61545b5faaf6SJeff Layton if (status) 61555b5faaf6SJeff Layton goto out; 61565b5faaf6SJeff Layton status = decode_sequence(xdr, &res->seq_res, rqstp); 61575b5faaf6SJeff Layton if (status) 61585b5faaf6SJeff Layton goto out; 61595b5faaf6SJeff Layton status = decode_putfh(xdr); 61605b5faaf6SJeff Layton if (status) 61615b5faaf6SJeff Layton goto out; 61625b5faaf6SJeff Layton status = decode_lookupp(xdr); 61635b5faaf6SJeff Layton if (status) 61645b5faaf6SJeff Layton goto out; 61655b5faaf6SJeff Layton status = decode_getfh(xdr, res->fh); 61665b5faaf6SJeff Layton if (status) 61675b5faaf6SJeff Layton goto out; 61685b5faaf6SJeff Layton status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); 61695b5faaf6SJeff Layton out: 61705b5faaf6SJeff Layton return status; 61715b5faaf6SJeff Layton } 61725b5faaf6SJeff Layton 61735b5faaf6SJeff Layton /* 61741da177e4SLinus Torvalds * Decode LOOKUP_ROOT response 61751da177e4SLinus Torvalds */ 6176bf269551SChuck Lever static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, 6177bf269551SChuck Lever struct xdr_stream *xdr, 6178fc016483SChristoph Hellwig void *data) 61791da177e4SLinus Torvalds { 6180fc016483SChristoph Hellwig struct nfs4_lookup_res *res = data; 61811da177e4SLinus Torvalds struct compound_hdr hdr; 61821da177e4SLinus Torvalds int status; 61831da177e4SLinus Torvalds 6184bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 61859b7b9fccSAndy Adamson if (status) 61869b7b9fccSAndy Adamson goto out; 6187bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 61889b7b9fccSAndy Adamson if (status) 61891da177e4SLinus Torvalds goto out; 6190bf269551SChuck Lever status = decode_putrootfh(xdr); 6191bf269551SChuck Lever if (status) 61921da177e4SLinus Torvalds goto out; 6193bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 6194bf269551SChuck Lever if (status == 0) 6195aa9c2669SDavid Quigley status = decode_getfattr_label(xdr, res->fattr, 6196aa9c2669SDavid Quigley res->label, res->server); 61971da177e4SLinus Torvalds out: 61981da177e4SLinus Torvalds return status; 61991da177e4SLinus Torvalds } 62001da177e4SLinus Torvalds 62011da177e4SLinus Torvalds /* 62021da177e4SLinus Torvalds * Decode REMOVE response 62031da177e4SLinus Torvalds */ 6204bf269551SChuck Lever static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6205fc016483SChristoph Hellwig void *data) 62061da177e4SLinus Torvalds { 6207fc016483SChristoph Hellwig struct nfs_removeres *res = data; 62081da177e4SLinus Torvalds struct compound_hdr hdr; 62091da177e4SLinus Torvalds int status; 62101da177e4SLinus Torvalds 6211bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 62129b7b9fccSAndy Adamson if (status) 62139b7b9fccSAndy Adamson goto out; 6214bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 62159b7b9fccSAndy Adamson if (status) 62161da177e4SLinus Torvalds goto out; 6217bf269551SChuck Lever status = decode_putfh(xdr); 6218bf269551SChuck Lever if (status) 621916e42959STrond Myklebust goto out; 6220bf269551SChuck Lever status = decode_remove(xdr, &res->cinfo); 62211da177e4SLinus Torvalds out: 62221da177e4SLinus Torvalds return status; 62231da177e4SLinus Torvalds } 62241da177e4SLinus Torvalds 62251da177e4SLinus Torvalds /* 62261da177e4SLinus Torvalds * Decode RENAME response 62271da177e4SLinus Torvalds */ 6228bf269551SChuck Lever static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6229fc016483SChristoph Hellwig void *data) 62301da177e4SLinus Torvalds { 6231fc016483SChristoph Hellwig struct nfs_renameres *res = data; 62321da177e4SLinus Torvalds struct compound_hdr hdr; 62331da177e4SLinus Torvalds int status; 62341da177e4SLinus Torvalds 6235bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 62369b7b9fccSAndy Adamson if (status) 62379b7b9fccSAndy Adamson goto out; 6238bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 62399b7b9fccSAndy Adamson if (status) 62401da177e4SLinus Torvalds goto out; 6241bf269551SChuck Lever status = decode_putfh(xdr); 6242bf269551SChuck Lever if (status) 62431da177e4SLinus Torvalds goto out; 6244bf269551SChuck Lever status = decode_savefh(xdr); 6245bf269551SChuck Lever if (status) 62461da177e4SLinus Torvalds goto out; 6247bf269551SChuck Lever status = decode_putfh(xdr); 6248bf269551SChuck Lever if (status) 62491da177e4SLinus Torvalds goto out; 6250bf269551SChuck Lever status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo); 62511da177e4SLinus Torvalds out: 62521da177e4SLinus Torvalds return status; 62531da177e4SLinus Torvalds } 62541da177e4SLinus Torvalds 62551da177e4SLinus Torvalds /* 62561da177e4SLinus Torvalds * Decode LINK response 62571da177e4SLinus Torvalds */ 6258bf269551SChuck Lever static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6259fc016483SChristoph Hellwig void *data) 62601da177e4SLinus Torvalds { 6261fc016483SChristoph Hellwig struct nfs4_link_res *res = data; 62621da177e4SLinus Torvalds struct compound_hdr hdr; 62631da177e4SLinus Torvalds int status; 62641da177e4SLinus Torvalds 6265bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 62669b7b9fccSAndy Adamson if (status) 62679b7b9fccSAndy Adamson goto out; 6268bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 62699b7b9fccSAndy Adamson if (status) 62701da177e4SLinus Torvalds goto out; 6271bf269551SChuck Lever status = decode_putfh(xdr); 6272bf269551SChuck Lever if (status) 62731da177e4SLinus Torvalds goto out; 6274bf269551SChuck Lever status = decode_savefh(xdr); 6275bf269551SChuck Lever if (status) 62761da177e4SLinus Torvalds goto out; 6277bf269551SChuck Lever status = decode_putfh(xdr); 6278bf269551SChuck Lever if (status) 62791da177e4SLinus Torvalds goto out; 6280bf269551SChuck Lever status = decode_link(xdr, &res->cinfo); 6281bf269551SChuck Lever if (status) 628291ba2eeeSTrond Myklebust goto out; 628391ba2eeeSTrond Myklebust /* 628491ba2eeeSTrond Myklebust * Note order: OP_LINK leaves the directory as the current 628591ba2eeeSTrond Myklebust * filehandle. 628691ba2eeeSTrond Myklebust */ 6287bf269551SChuck Lever status = decode_restorefh(xdr); 6288bf269551SChuck Lever if (status) 628991ba2eeeSTrond Myklebust goto out; 6290aa9c2669SDavid Quigley decode_getfattr_label(xdr, res->fattr, res->label, res->server); 62911da177e4SLinus Torvalds out: 62921da177e4SLinus Torvalds return status; 62931da177e4SLinus Torvalds } 62941da177e4SLinus Torvalds 62951da177e4SLinus Torvalds /* 62961da177e4SLinus Torvalds * Decode CREATE response 62971da177e4SLinus Torvalds */ 6298bf269551SChuck Lever static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6299fc016483SChristoph Hellwig void *data) 63001da177e4SLinus Torvalds { 6301fc016483SChristoph Hellwig struct nfs4_create_res *res = data; 63021da177e4SLinus Torvalds struct compound_hdr hdr; 63031da177e4SLinus Torvalds int status; 63041da177e4SLinus Torvalds 6305bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 63069b7b9fccSAndy Adamson if (status) 63079b7b9fccSAndy Adamson goto out; 6308bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 63099b7b9fccSAndy Adamson if (status) 63101da177e4SLinus Torvalds goto out; 6311bf269551SChuck Lever status = decode_putfh(xdr); 6312bf269551SChuck Lever if (status) 63131da177e4SLinus Torvalds goto out; 6314bf269551SChuck Lever status = decode_create(xdr, &res->dir_cinfo); 6315bf269551SChuck Lever if (status) 63161da177e4SLinus Torvalds goto out; 6317bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 6318bf269551SChuck Lever if (status) 63191da177e4SLinus Torvalds goto out; 6320aa9c2669SDavid Quigley decode_getfattr_label(xdr, res->fattr, res->label, res->server); 63211da177e4SLinus Torvalds out: 63221da177e4SLinus Torvalds return status; 63231da177e4SLinus Torvalds } 63241da177e4SLinus Torvalds 63251da177e4SLinus Torvalds /* 63261da177e4SLinus Torvalds * Decode SYMLINK response 63271da177e4SLinus Torvalds */ 6328bf269551SChuck Lever static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6329fc016483SChristoph Hellwig void *res) 63301da177e4SLinus Torvalds { 6331bf269551SChuck Lever return nfs4_xdr_dec_create(rqstp, xdr, res); 63321da177e4SLinus Torvalds } 63331da177e4SLinus Torvalds 63341da177e4SLinus Torvalds /* 63351da177e4SLinus Torvalds * Decode GETATTR response 63361da177e4SLinus Torvalds */ 6337bf269551SChuck Lever static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6338fc016483SChristoph Hellwig void *data) 63391da177e4SLinus Torvalds { 6340fc016483SChristoph Hellwig struct nfs4_getattr_res *res = data; 63411da177e4SLinus Torvalds struct compound_hdr hdr; 63421da177e4SLinus Torvalds int status; 63431da177e4SLinus Torvalds 6344bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 63451da177e4SLinus Torvalds if (status) 63461da177e4SLinus Torvalds goto out; 6347bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 63489b7b9fccSAndy Adamson if (status) 63499b7b9fccSAndy Adamson goto out; 6350bf269551SChuck Lever status = decode_putfh(xdr); 63511da177e4SLinus Torvalds if (status) 63521da177e4SLinus Torvalds goto out; 6353aa9c2669SDavid Quigley status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); 63541da177e4SLinus Torvalds out: 63551da177e4SLinus Torvalds return status; 63561da177e4SLinus Torvalds } 63571da177e4SLinus Torvalds 635823ec6965SJ. Bruce Fields /* 635923ec6965SJ. Bruce Fields * Encode an SETACL request 636023ec6965SJ. Bruce Fields */ 63619f06c719SChuck Lever static void nfs4_xdr_enc_setacl(struct rpc_rqst *req, struct xdr_stream *xdr, 6362fcc85819SChristoph Hellwig const void *data) 636323ec6965SJ. Bruce Fields { 6364fcc85819SChristoph Hellwig const struct nfs_setaclargs *args = data; 636523ec6965SJ. Bruce Fields struct compound_hdr hdr = { 636666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 636723ec6965SJ. Bruce Fields }; 636823ec6965SJ. Bruce Fields 63699f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 63709f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 63719f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 63729f06c719SChuck Lever encode_setacl(xdr, args, &hdr); 6373d017931cSAndy Adamson encode_nops(&hdr); 637423ec6965SJ. Bruce Fields } 637505d564feSAndy Adamson 637623ec6965SJ. Bruce Fields /* 637723ec6965SJ. Bruce Fields * Decode SETACL response 637823ec6965SJ. Bruce Fields */ 637923ec6965SJ. Bruce Fields static int 6380bf269551SChuck Lever nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6381fc016483SChristoph Hellwig void *data) 638223ec6965SJ. Bruce Fields { 6383fc016483SChristoph Hellwig struct nfs_setaclres *res = data; 638423ec6965SJ. Bruce Fields struct compound_hdr hdr; 638523ec6965SJ. Bruce Fields int status; 638623ec6965SJ. Bruce Fields 6387bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 638823ec6965SJ. Bruce Fields if (status) 638923ec6965SJ. Bruce Fields goto out; 6390bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 63919b7b9fccSAndy Adamson if (status) 63929b7b9fccSAndy Adamson goto out; 6393bf269551SChuck Lever status = decode_putfh(xdr); 639423ec6965SJ. Bruce Fields if (status) 639523ec6965SJ. Bruce Fields goto out; 6396bf269551SChuck Lever status = decode_setattr(xdr); 639723ec6965SJ. Bruce Fields out: 639823ec6965SJ. Bruce Fields return status; 639923ec6965SJ. Bruce Fields } 64001da177e4SLinus Torvalds 64011da177e4SLinus Torvalds /* 6402029d105eSJ. Bruce Fields * Decode GETACL response 6403029d105eSJ. Bruce Fields */ 6404029d105eSJ. Bruce Fields static int 6405bf269551SChuck Lever nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6406fc016483SChristoph Hellwig void *data) 6407029d105eSJ. Bruce Fields { 6408fc016483SChristoph Hellwig struct nfs_getaclres *res = data; 6409029d105eSJ. Bruce Fields struct compound_hdr hdr; 6410029d105eSJ. Bruce Fields int status; 6411029d105eSJ. Bruce Fields 6412331818f1STrond Myklebust if (res->acl_scratch != NULL) { 6413331818f1STrond Myklebust void *p = page_address(res->acl_scratch); 6414331818f1STrond Myklebust xdr_set_scratch_buffer(xdr, p, PAGE_SIZE); 6415331818f1STrond Myklebust } 6416bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6417029d105eSJ. Bruce Fields if (status) 6418029d105eSJ. Bruce Fields goto out; 6419bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 64209b7b9fccSAndy Adamson if (status) 64219b7b9fccSAndy Adamson goto out; 6422bf269551SChuck Lever status = decode_putfh(xdr); 6423029d105eSJ. Bruce Fields if (status) 6424029d105eSJ. Bruce Fields goto out; 6425bf118a34SAndy Adamson status = decode_getacl(xdr, rqstp, res); 6426029d105eSJ. Bruce Fields 6427029d105eSJ. Bruce Fields out: 6428029d105eSJ. Bruce Fields return status; 6429029d105eSJ. Bruce Fields } 6430029d105eSJ. Bruce Fields 6431029d105eSJ. Bruce Fields /* 64321da177e4SLinus Torvalds * Decode CLOSE response 64331da177e4SLinus Torvalds */ 6434bf269551SChuck Lever static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6435fc016483SChristoph Hellwig void *data) 64361da177e4SLinus Torvalds { 6437fc016483SChristoph Hellwig struct nfs_closeres *res = data; 64381da177e4SLinus Torvalds struct compound_hdr hdr; 64391da177e4SLinus Torvalds int status; 64401da177e4SLinus Torvalds 6441bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 64421da177e4SLinus Torvalds if (status) 64431da177e4SLinus Torvalds goto out; 6444bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 64459b7b9fccSAndy Adamson if (status) 64469b7b9fccSAndy Adamson goto out; 6447bf269551SChuck Lever status = decode_putfh(xdr); 64481da177e4SLinus Torvalds if (status) 64491da177e4SLinus Torvalds goto out; 6450cf805165STrond Myklebust if (res->lr_res) { 6451cf805165STrond Myklebust status = decode_layoutreturn(xdr, res->lr_res); 6452cf805165STrond Myklebust res->lr_ret = status; 6453cf805165STrond Myklebust if (status) 6454cf805165STrond Myklebust goto out; 6455cf805165STrond Myklebust } 6456d8d84983STrond Myklebust if (res->fattr != NULL) { 6457d8d84983STrond Myklebust status = decode_getfattr(xdr, res->fattr, res->server); 6458516a6af6STrond Myklebust if (status != 0) 6459516a6af6STrond Myklebust goto out; 6460d8d84983STrond Myklebust } 6461d8d84983STrond Myklebust status = decode_close(xdr, res); 64621da177e4SLinus Torvalds out: 64631da177e4SLinus Torvalds return status; 64641da177e4SLinus Torvalds } 64651da177e4SLinus Torvalds 64661da177e4SLinus Torvalds /* 64671da177e4SLinus Torvalds * Decode OPEN response 64681da177e4SLinus Torvalds */ 6469bf269551SChuck Lever static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6470fc016483SChristoph Hellwig void *data) 64711da177e4SLinus Torvalds { 6472fc016483SChristoph Hellwig struct nfs_openres *res = data; 64731da177e4SLinus Torvalds struct compound_hdr hdr; 64741da177e4SLinus Torvalds int status; 64751da177e4SLinus Torvalds 6476bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 64771da177e4SLinus Torvalds if (status) 64781da177e4SLinus Torvalds goto out; 6479bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 64809b7b9fccSAndy Adamson if (status) 64819b7b9fccSAndy Adamson goto out; 6482bf269551SChuck Lever status = decode_putfh(xdr); 64831da177e4SLinus Torvalds if (status) 64841da177e4SLinus Torvalds goto out; 6485bf269551SChuck Lever status = decode_open(xdr, res); 64861da177e4SLinus Torvalds if (status) 64871da177e4SLinus Torvalds goto out; 648801913b49SWeston Andros Adamson status = decode_getfh(xdr, &res->fh); 648901913b49SWeston Andros Adamson if (status) 64901da177e4SLinus Torvalds goto out; 6491ae2bb032SWeston Andros Adamson if (res->access_request) 64926168f62cSWeston Andros Adamson decode_access(xdr, &res->access_supported, &res->access_result); 6493aa9c2669SDavid Quigley decode_getfattr_label(xdr, res->f_attr, res->f_label, res->server); 649456f487f8SFred Isaman if (res->lg_res) 649556f487f8SFred Isaman decode_layoutget(xdr, rqstp, res->lg_res); 64961da177e4SLinus Torvalds out: 64971da177e4SLinus Torvalds return status; 64981da177e4SLinus Torvalds } 64991da177e4SLinus Torvalds 65001da177e4SLinus Torvalds /* 65011da177e4SLinus Torvalds * Decode OPEN_CONFIRM response 65021da177e4SLinus Torvalds */ 6503bf269551SChuck Lever static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, 6504bf269551SChuck Lever struct xdr_stream *xdr, 6505fc016483SChristoph Hellwig void *data) 65061da177e4SLinus Torvalds { 6507fc016483SChristoph Hellwig struct nfs_open_confirmres *res = data; 65081da177e4SLinus Torvalds struct compound_hdr hdr; 65091da177e4SLinus Torvalds int status; 65101da177e4SLinus Torvalds 6511bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 65121da177e4SLinus Torvalds if (status) 65131da177e4SLinus Torvalds goto out; 6514bf269551SChuck Lever status = decode_putfh(xdr); 65151da177e4SLinus Torvalds if (status) 65161da177e4SLinus Torvalds goto out; 6517bf269551SChuck Lever status = decode_open_confirm(xdr, res); 65181da177e4SLinus Torvalds out: 65191da177e4SLinus Torvalds return status; 65201da177e4SLinus Torvalds } 65211da177e4SLinus Torvalds 65221da177e4SLinus Torvalds /* 65231da177e4SLinus Torvalds * Decode OPEN response 65241da177e4SLinus Torvalds */ 6525bf269551SChuck Lever static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, 6526bf269551SChuck Lever struct xdr_stream *xdr, 6527fc016483SChristoph Hellwig void *data) 65281da177e4SLinus Torvalds { 6529fc016483SChristoph Hellwig struct nfs_openres *res = data; 65301da177e4SLinus Torvalds struct compound_hdr hdr; 65311da177e4SLinus Torvalds int status; 65321da177e4SLinus Torvalds 6533bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 65341da177e4SLinus Torvalds if (status) 65351da177e4SLinus Torvalds goto out; 6536bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 65379b7b9fccSAndy Adamson if (status) 65389b7b9fccSAndy Adamson goto out; 6539bf269551SChuck Lever status = decode_putfh(xdr); 65401da177e4SLinus Torvalds if (status) 65411da177e4SLinus Torvalds goto out; 6542bf269551SChuck Lever status = decode_open(xdr, res); 6543864472e9STrond Myklebust if (status) 6544864472e9STrond Myklebust goto out; 6545ae2bb032SWeston Andros Adamson if (res->access_request) 65466168f62cSWeston Andros Adamson decode_access(xdr, &res->access_supported, &res->access_result); 65476926afd1STrond Myklebust decode_getfattr(xdr, res->f_attr, res->server); 654856f487f8SFred Isaman if (res->lg_res) 654956f487f8SFred Isaman decode_layoutget(xdr, rqstp, res->lg_res); 65501da177e4SLinus Torvalds out: 65511da177e4SLinus Torvalds return status; 65521da177e4SLinus Torvalds } 65531da177e4SLinus Torvalds 65541da177e4SLinus Torvalds /* 65551da177e4SLinus Torvalds * Decode SETATTR response 65561da177e4SLinus Torvalds */ 6557bf269551SChuck Lever static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, 6558bf269551SChuck Lever struct xdr_stream *xdr, 6559fc016483SChristoph Hellwig void *data) 65601da177e4SLinus Torvalds { 6561fc016483SChristoph Hellwig struct nfs_setattrres *res = data; 65621da177e4SLinus Torvalds struct compound_hdr hdr; 65631da177e4SLinus Torvalds int status; 65641da177e4SLinus Torvalds 6565bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 65661da177e4SLinus Torvalds if (status) 65671da177e4SLinus Torvalds goto out; 6568bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 65699b7b9fccSAndy Adamson if (status) 65709b7b9fccSAndy Adamson goto out; 6571bf269551SChuck Lever status = decode_putfh(xdr); 65721da177e4SLinus Torvalds if (status) 65731da177e4SLinus Torvalds goto out; 6574bf269551SChuck Lever status = decode_setattr(xdr); 65751da177e4SLinus Torvalds if (status) 65761da177e4SLinus Torvalds goto out; 6577aa9c2669SDavid Quigley decode_getfattr_label(xdr, res->fattr, res->label, res->server); 65781da177e4SLinus Torvalds out: 65791da177e4SLinus Torvalds return status; 65801da177e4SLinus Torvalds } 65811da177e4SLinus Torvalds 65821da177e4SLinus Torvalds /* 65831da177e4SLinus Torvalds * Decode LOCK response 65841da177e4SLinus Torvalds */ 6585bf269551SChuck Lever static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6586fc016483SChristoph Hellwig void *data) 65871da177e4SLinus Torvalds { 6588fc016483SChristoph Hellwig struct nfs_lock_res *res = data; 65891da177e4SLinus Torvalds struct compound_hdr hdr; 65901da177e4SLinus Torvalds int status; 65911da177e4SLinus Torvalds 6592bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 65931da177e4SLinus Torvalds if (status) 65941da177e4SLinus Torvalds goto out; 6595bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 65969b7b9fccSAndy Adamson if (status) 65979b7b9fccSAndy Adamson goto out; 6598bf269551SChuck Lever status = decode_putfh(xdr); 65991da177e4SLinus Torvalds if (status) 66001da177e4SLinus Torvalds goto out; 6601bf269551SChuck Lever status = decode_lock(xdr, res); 66021da177e4SLinus Torvalds out: 66031da177e4SLinus Torvalds return status; 66041da177e4SLinus Torvalds } 66051da177e4SLinus Torvalds 66061da177e4SLinus Torvalds /* 66071da177e4SLinus Torvalds * Decode LOCKT response 66081da177e4SLinus Torvalds */ 6609bf269551SChuck Lever static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6610fc016483SChristoph Hellwig void *data) 66111da177e4SLinus Torvalds { 6612fc016483SChristoph Hellwig struct nfs_lockt_res *res = data; 66131da177e4SLinus Torvalds struct compound_hdr hdr; 66141da177e4SLinus Torvalds int status; 66151da177e4SLinus Torvalds 6616bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 66171da177e4SLinus Torvalds if (status) 66181da177e4SLinus Torvalds goto out; 6619bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 66209b7b9fccSAndy Adamson if (status) 66219b7b9fccSAndy Adamson goto out; 6622bf269551SChuck Lever status = decode_putfh(xdr); 66231da177e4SLinus Torvalds if (status) 66241da177e4SLinus Torvalds goto out; 6625bf269551SChuck Lever status = decode_lockt(xdr, res); 66261da177e4SLinus Torvalds out: 66271da177e4SLinus Torvalds return status; 66281da177e4SLinus Torvalds } 66291da177e4SLinus Torvalds 66301da177e4SLinus Torvalds /* 66311da177e4SLinus Torvalds * Decode LOCKU response 66321da177e4SLinus Torvalds */ 6633bf269551SChuck Lever static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6634fc016483SChristoph Hellwig void *data) 66351da177e4SLinus Torvalds { 6636fc016483SChristoph Hellwig struct nfs_locku_res *res = data; 66371da177e4SLinus Torvalds struct compound_hdr hdr; 66381da177e4SLinus Torvalds int status; 66391da177e4SLinus Torvalds 6640bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 66411da177e4SLinus Torvalds if (status) 66421da177e4SLinus Torvalds goto out; 6643bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 66449b7b9fccSAndy Adamson if (status) 66459b7b9fccSAndy Adamson goto out; 6646bf269551SChuck Lever status = decode_putfh(xdr); 66471da177e4SLinus Torvalds if (status) 66481da177e4SLinus Torvalds goto out; 6649bf269551SChuck Lever status = decode_locku(xdr, res); 66501da177e4SLinus Torvalds out: 66511da177e4SLinus Torvalds return status; 66521da177e4SLinus Torvalds } 66531da177e4SLinus Torvalds 6654bf269551SChuck Lever static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, 6655bf269551SChuck Lever struct xdr_stream *xdr, void *dummy) 6656d3c7b7ccSTrond Myklebust { 6657d3c7b7ccSTrond Myklebust struct compound_hdr hdr; 6658d3c7b7ccSTrond Myklebust int status; 6659d3c7b7ccSTrond Myklebust 6660bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6661d3c7b7ccSTrond Myklebust if (!status) 6662bf269551SChuck Lever status = decode_release_lockowner(xdr); 6663d3c7b7ccSTrond Myklebust return status; 6664d3c7b7ccSTrond Myklebust } 6665d3c7b7ccSTrond Myklebust 66661da177e4SLinus Torvalds /* 66671da177e4SLinus Torvalds * Decode READLINK response 66681da177e4SLinus Torvalds */ 6669bf269551SChuck Lever static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, 6670bf269551SChuck Lever struct xdr_stream *xdr, 6671fc016483SChristoph Hellwig void *data) 66721da177e4SLinus Torvalds { 6673fc016483SChristoph Hellwig struct nfs4_readlink_res *res = data; 66741da177e4SLinus Torvalds struct compound_hdr hdr; 66751da177e4SLinus Torvalds int status; 66761da177e4SLinus Torvalds 6677bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 66781da177e4SLinus Torvalds if (status) 66791da177e4SLinus Torvalds goto out; 6680bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 66819b7b9fccSAndy Adamson if (status) 66829b7b9fccSAndy Adamson goto out; 6683bf269551SChuck Lever status = decode_putfh(xdr); 66841da177e4SLinus Torvalds if (status) 66851da177e4SLinus Torvalds goto out; 6686bf269551SChuck Lever status = decode_readlink(xdr, rqstp); 66871da177e4SLinus Torvalds out: 66881da177e4SLinus Torvalds return status; 66891da177e4SLinus Torvalds } 66901da177e4SLinus Torvalds 66911da177e4SLinus Torvalds /* 66921da177e4SLinus Torvalds * Decode READDIR response 66931da177e4SLinus Torvalds */ 6694bf269551SChuck Lever static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6695fc016483SChristoph Hellwig void *data) 66961da177e4SLinus Torvalds { 6697fc016483SChristoph Hellwig struct nfs4_readdir_res *res = data; 66981da177e4SLinus Torvalds struct compound_hdr hdr; 66991da177e4SLinus Torvalds int status; 67001da177e4SLinus Torvalds 6701bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 67021da177e4SLinus Torvalds if (status) 67031da177e4SLinus Torvalds goto out; 6704bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 67059b7b9fccSAndy Adamson if (status) 67069b7b9fccSAndy Adamson goto out; 6707bf269551SChuck Lever status = decode_putfh(xdr); 67081da177e4SLinus Torvalds if (status) 67091da177e4SLinus Torvalds goto out; 6710bf269551SChuck Lever status = decode_readdir(xdr, rqstp, res); 67111da177e4SLinus Torvalds out: 67121da177e4SLinus Torvalds return status; 67131da177e4SLinus Torvalds } 67141da177e4SLinus Torvalds 67151da177e4SLinus Torvalds /* 67161da177e4SLinus Torvalds * Decode Read response 67171da177e4SLinus Torvalds */ 6718bf269551SChuck Lever static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6719fc016483SChristoph Hellwig void *data) 67201da177e4SLinus Torvalds { 6721fc016483SChristoph Hellwig struct nfs_pgio_res *res = data; 67221da177e4SLinus Torvalds struct compound_hdr hdr; 67231da177e4SLinus Torvalds int status; 67241da177e4SLinus Torvalds 6725bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6726aabff4ddSPeng Tao res->op_status = hdr.status; 67271da177e4SLinus Torvalds if (status) 67281da177e4SLinus Torvalds goto out; 6729bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 67309b7b9fccSAndy Adamson if (status) 67319b7b9fccSAndy Adamson goto out; 6732bf269551SChuck Lever status = decode_putfh(xdr); 67331da177e4SLinus Torvalds if (status) 67341da177e4SLinus Torvalds goto out; 6735bf269551SChuck Lever status = decode_read(xdr, rqstp, res); 67361da177e4SLinus Torvalds if (!status) 67371da177e4SLinus Torvalds status = res->count; 67381da177e4SLinus Torvalds out: 67391da177e4SLinus Torvalds return status; 67401da177e4SLinus Torvalds } 67411da177e4SLinus Torvalds 67421da177e4SLinus Torvalds /* 67431da177e4SLinus Torvalds * Decode WRITE response 67441da177e4SLinus Torvalds */ 6745bf269551SChuck Lever static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6746fc016483SChristoph Hellwig void *data) 67471da177e4SLinus Torvalds { 6748fc016483SChristoph Hellwig struct nfs_pgio_res *res = data; 67491da177e4SLinus Torvalds struct compound_hdr hdr; 67501da177e4SLinus Torvalds int status; 67511da177e4SLinus Torvalds 6752bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6753aabff4ddSPeng Tao res->op_status = hdr.status; 67541da177e4SLinus Torvalds if (status) 67551da177e4SLinus Torvalds goto out; 6756bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 67579b7b9fccSAndy Adamson if (status) 67589b7b9fccSAndy Adamson goto out; 6759bf269551SChuck Lever status = decode_putfh(xdr); 67601da177e4SLinus Torvalds if (status) 67611da177e4SLinus Torvalds goto out; 6762bf269551SChuck Lever status = decode_write(xdr, res); 67634f9838c7STrond Myklebust if (status) 67644f9838c7STrond Myklebust goto out; 67657ffd1064SFred Isaman if (res->fattr) 67666926afd1STrond Myklebust decode_getfattr(xdr, res->fattr, res->server); 67671da177e4SLinus Torvalds if (!status) 67681da177e4SLinus Torvalds status = res->count; 67691da177e4SLinus Torvalds out: 67701da177e4SLinus Torvalds return status; 67711da177e4SLinus Torvalds } 67721da177e4SLinus Torvalds 67731da177e4SLinus Torvalds /* 67741da177e4SLinus Torvalds * Decode COMMIT response 67751da177e4SLinus Torvalds */ 6776bf269551SChuck Lever static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6777fc016483SChristoph Hellwig void *data) 67781da177e4SLinus Torvalds { 6779fc016483SChristoph Hellwig struct nfs_commitres *res = data; 67801da177e4SLinus Torvalds struct compound_hdr hdr; 67811da177e4SLinus Torvalds int status; 67821da177e4SLinus Torvalds 6783bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6784aabff4ddSPeng Tao res->op_status = hdr.status; 67851da177e4SLinus Torvalds if (status) 67861da177e4SLinus Torvalds goto out; 6787bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 67889b7b9fccSAndy Adamson if (status) 67899b7b9fccSAndy Adamson goto out; 6790bf269551SChuck Lever status = decode_putfh(xdr); 67911da177e4SLinus Torvalds if (status) 67921da177e4SLinus Torvalds goto out; 6793bf269551SChuck Lever status = decode_commit(xdr, res); 67941da177e4SLinus Torvalds out: 67951da177e4SLinus Torvalds return status; 67961da177e4SLinus Torvalds } 67971da177e4SLinus Torvalds 67981da177e4SLinus Torvalds /* 67998b173218SRicardo Labiaga * Decode FSINFO response 68001da177e4SLinus Torvalds */ 6801bf269551SChuck Lever static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, 6802fc016483SChristoph Hellwig void *data) 68031da177e4SLinus Torvalds { 6804fc016483SChristoph Hellwig struct nfs4_fsinfo_res *res = data; 68051da177e4SLinus Torvalds struct compound_hdr hdr; 68061da177e4SLinus Torvalds int status; 68071da177e4SLinus Torvalds 6808bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 68091da177e4SLinus Torvalds if (!status) 6810bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 68119b7b9fccSAndy Adamson if (!status) 6812bf269551SChuck Lever status = decode_putfh(xdr); 68131da177e4SLinus Torvalds if (!status) 6814bf269551SChuck Lever status = decode_fsinfo(xdr, res->fsinfo); 68151da177e4SLinus Torvalds return status; 68161da177e4SLinus Torvalds } 68171da177e4SLinus Torvalds 68181da177e4SLinus Torvalds /* 68198b173218SRicardo Labiaga * Decode PATHCONF response 68201da177e4SLinus Torvalds */ 6821bf269551SChuck Lever static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, 6822fc016483SChristoph Hellwig void *data) 68231da177e4SLinus Torvalds { 6824fc016483SChristoph Hellwig struct nfs4_pathconf_res *res = data; 68251da177e4SLinus Torvalds struct compound_hdr hdr; 68261da177e4SLinus Torvalds int status; 68271da177e4SLinus Torvalds 6828bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 68291da177e4SLinus Torvalds if (!status) 6830bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 68319b7b9fccSAndy Adamson if (!status) 6832bf269551SChuck Lever status = decode_putfh(xdr); 68331da177e4SLinus Torvalds if (!status) 6834bf269551SChuck Lever status = decode_pathconf(xdr, res->pathconf); 68351da177e4SLinus Torvalds return status; 68361da177e4SLinus Torvalds } 68371da177e4SLinus Torvalds 68381da177e4SLinus Torvalds /* 68398b173218SRicardo Labiaga * Decode STATFS response 68401da177e4SLinus Torvalds */ 6841bf269551SChuck Lever static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, 6842fc016483SChristoph Hellwig void *data) 68431da177e4SLinus Torvalds { 6844fc016483SChristoph Hellwig struct nfs4_statfs_res *res = data; 68451da177e4SLinus Torvalds struct compound_hdr hdr; 68461da177e4SLinus Torvalds int status; 68471da177e4SLinus Torvalds 6848bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 68491da177e4SLinus Torvalds if (!status) 6850bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 68519b7b9fccSAndy Adamson if (!status) 6852bf269551SChuck Lever status = decode_putfh(xdr); 68531da177e4SLinus Torvalds if (!status) 6854bf269551SChuck Lever status = decode_statfs(xdr, res->fsstat); 68551da177e4SLinus Torvalds return status; 68561da177e4SLinus Torvalds } 68571da177e4SLinus Torvalds 68581da177e4SLinus Torvalds /* 68598b173218SRicardo Labiaga * Decode GETATTR_BITMAP response 68601da177e4SLinus Torvalds */ 6861bf269551SChuck Lever static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, 6862bf269551SChuck Lever struct xdr_stream *xdr, 6863fc016483SChristoph Hellwig void *data) 68641da177e4SLinus Torvalds { 6865fc016483SChristoph Hellwig struct nfs4_server_caps_res *res = data; 68661da177e4SLinus Torvalds struct compound_hdr hdr; 68671da177e4SLinus Torvalds int status; 68681da177e4SLinus Torvalds 6869bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 68709b7b9fccSAndy Adamson if (status) 68719b7b9fccSAndy Adamson goto out; 6872bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 68739b7b9fccSAndy Adamson if (status) 68741da177e4SLinus Torvalds goto out; 6875bf269551SChuck Lever status = decode_putfh(xdr); 6876bf269551SChuck Lever if (status) 68771da177e4SLinus Torvalds goto out; 6878bf269551SChuck Lever status = decode_server_caps(xdr, res); 68791da177e4SLinus Torvalds out: 68801da177e4SLinus Torvalds return status; 68811da177e4SLinus Torvalds } 68821da177e4SLinus Torvalds 68831da177e4SLinus Torvalds /* 68841da177e4SLinus Torvalds * Decode RENEW response 68851da177e4SLinus Torvalds */ 6886bf269551SChuck Lever static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6887bf269551SChuck Lever void *__unused) 68881da177e4SLinus Torvalds { 68891da177e4SLinus Torvalds struct compound_hdr hdr; 68901da177e4SLinus Torvalds int status; 68911da177e4SLinus Torvalds 6892bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 68931da177e4SLinus Torvalds if (!status) 6894bf269551SChuck Lever status = decode_renew(xdr); 68951da177e4SLinus Torvalds return status; 68961da177e4SLinus Torvalds } 68971da177e4SLinus Torvalds 68981da177e4SLinus Torvalds /* 68998b173218SRicardo Labiaga * Decode SETCLIENTID response 69001da177e4SLinus Torvalds */ 6901bf269551SChuck Lever static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, 6902bf269551SChuck Lever struct xdr_stream *xdr, 6903fc016483SChristoph Hellwig void *data) 69041da177e4SLinus Torvalds { 6905fc016483SChristoph Hellwig struct nfs4_setclientid_res *res = data; 69061da177e4SLinus Torvalds struct compound_hdr hdr; 69071da177e4SLinus Torvalds int status; 69081da177e4SLinus Torvalds 6909bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 69101da177e4SLinus Torvalds if (!status) 6911bf269551SChuck Lever status = decode_setclientid(xdr, res); 69121da177e4SLinus Torvalds return status; 69131da177e4SLinus Torvalds } 69141da177e4SLinus Torvalds 69151da177e4SLinus Torvalds /* 69168b173218SRicardo Labiaga * Decode SETCLIENTID_CONFIRM response 69171da177e4SLinus Torvalds */ 6918bf269551SChuck Lever static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, 6919fc016483SChristoph Hellwig struct xdr_stream *xdr, 6920fc016483SChristoph Hellwig void *data) 69211da177e4SLinus Torvalds { 69221da177e4SLinus Torvalds struct compound_hdr hdr; 69231da177e4SLinus Torvalds int status; 69241da177e4SLinus Torvalds 6925bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 69261da177e4SLinus Torvalds if (!status) 6927bf269551SChuck Lever status = decode_setclientid_confirm(xdr); 69281da177e4SLinus Torvalds return status; 69291da177e4SLinus Torvalds } 69301da177e4SLinus Torvalds 69311da177e4SLinus Torvalds /* 69328b173218SRicardo Labiaga * Decode DELEGRETURN response 69331da177e4SLinus Torvalds */ 6934bf269551SChuck Lever static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, 6935bf269551SChuck Lever struct xdr_stream *xdr, 6936fc016483SChristoph Hellwig void *data) 69371da177e4SLinus Torvalds { 6938fc016483SChristoph Hellwig struct nfs4_delegreturnres *res = data; 69391da177e4SLinus Torvalds struct compound_hdr hdr; 69401da177e4SLinus Torvalds int status; 69411da177e4SLinus Torvalds 6942bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 69439b7b9fccSAndy Adamson if (status) 69449b7b9fccSAndy Adamson goto out; 6945bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 69469b7b9fccSAndy Adamson if (status) 6947fa178f29STrond Myklebust goto out; 6948bf269551SChuck Lever status = decode_putfh(xdr); 6949fa178f29STrond Myklebust if (status != 0) 6950fa178f29STrond Myklebust goto out; 6951586f1c39STrond Myklebust if (res->lr_res) { 6952586f1c39STrond Myklebust status = decode_layoutreturn(xdr, res->lr_res); 6953586f1c39STrond Myklebust res->lr_ret = status; 6954586f1c39STrond Myklebust if (status) 6955586f1c39STrond Myklebust goto out; 6956586f1c39STrond Myklebust } 69578ac2b422STrond Myklebust if (res->fattr) { 6958e144cbccSTrond Myklebust status = decode_getfattr(xdr, res->fattr, res->server); 6959556ae3bbSJeff Layton if (status != 0) 6960556ae3bbSJeff Layton goto out; 69618ac2b422STrond Myklebust } 6962e144cbccSTrond Myklebust status = decode_delegreturn(xdr); 6963fa178f29STrond Myklebust out: 69641da177e4SLinus Torvalds return status; 69651da177e4SLinus Torvalds } 69661da177e4SLinus Torvalds 6967683b57b4STrond Myklebust /* 69688b173218SRicardo Labiaga * Decode FS_LOCATIONS response 6969683b57b4STrond Myklebust */ 6970bf269551SChuck Lever static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, 6971bf269551SChuck Lever struct xdr_stream *xdr, 6972fc016483SChristoph Hellwig void *data) 6973683b57b4STrond Myklebust { 6974fc016483SChristoph Hellwig struct nfs4_fs_locations_res *res = data; 6975683b57b4STrond Myklebust struct compound_hdr hdr; 6976683b57b4STrond Myklebust int status; 6977683b57b4STrond Myklebust 6978bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 69799b7b9fccSAndy Adamson if (status) 69809b7b9fccSAndy Adamson goto out; 6981bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 69829b7b9fccSAndy Adamson if (status) 6983683b57b4STrond Myklebust goto out; 6984bf269551SChuck Lever status = decode_putfh(xdr); 6985bf269551SChuck Lever if (status) 6986683b57b4STrond Myklebust goto out; 6987b03d735bSChuck Lever if (res->migration) { 6988b03d735bSChuck Lever xdr_enter_page(xdr, PAGE_SIZE); 6989b03d735bSChuck Lever status = decode_getfattr_generic(xdr, 6990b03d735bSChuck Lever &res->fs_locations->fattr, 6991b03d735bSChuck Lever NULL, res->fs_locations, 6992b03d735bSChuck Lever NULL, res->fs_locations->server); 6993b03d735bSChuck Lever if (status) 6994b03d735bSChuck Lever goto out; 6995b03d735bSChuck Lever if (res->renew) 6996b03d735bSChuck Lever status = decode_renew(xdr); 6997b03d735bSChuck Lever } else { 6998bf269551SChuck Lever status = decode_lookup(xdr); 6999bf269551SChuck Lever if (status) 7000683b57b4STrond Myklebust goto out; 7001bf269551SChuck Lever xdr_enter_page(xdr, PAGE_SIZE); 7002b03d735bSChuck Lever status = decode_getfattr_generic(xdr, 7003b03d735bSChuck Lever &res->fs_locations->fattr, 70048b7e3f49STrond Myklebust NULL, res->fs_locations, 7005aa9c2669SDavid Quigley NULL, res->fs_locations->server); 7006b03d735bSChuck Lever } 7007683b57b4STrond Myklebust out: 7008683b57b4STrond Myklebust return status; 7009683b57b4STrond Myklebust } 7010683b57b4STrond Myklebust 70115a5ea0d4SBryan Schumaker /* 70125a5ea0d4SBryan Schumaker * Decode SECINFO response 70135a5ea0d4SBryan Schumaker */ 70145a5ea0d4SBryan Schumaker static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp, 70155a5ea0d4SBryan Schumaker struct xdr_stream *xdr, 7016fc016483SChristoph Hellwig void *data) 70175a5ea0d4SBryan Schumaker { 7018fc016483SChristoph Hellwig struct nfs4_secinfo_res *res = data; 70195a5ea0d4SBryan Schumaker struct compound_hdr hdr; 70205a5ea0d4SBryan Schumaker int status; 70215a5ea0d4SBryan Schumaker 70225a5ea0d4SBryan Schumaker status = decode_compound_hdr(xdr, &hdr); 70235a5ea0d4SBryan Schumaker if (status) 70245a5ea0d4SBryan Schumaker goto out; 70255a5ea0d4SBryan Schumaker status = decode_sequence(xdr, &res->seq_res, rqstp); 70265a5ea0d4SBryan Schumaker if (status) 70275a5ea0d4SBryan Schumaker goto out; 70285a5ea0d4SBryan Schumaker status = decode_putfh(xdr); 70295a5ea0d4SBryan Schumaker if (status) 70305a5ea0d4SBryan Schumaker goto out; 70315a5ea0d4SBryan Schumaker status = decode_secinfo(xdr, res); 70325a5ea0d4SBryan Schumaker out: 70335a5ea0d4SBryan Schumaker return status; 70345a5ea0d4SBryan Schumaker } 70355a5ea0d4SBryan Schumaker 703644c99933SChuck Lever /* 703744c99933SChuck Lever * Decode FSID_PRESENT response 703844c99933SChuck Lever */ 703944c99933SChuck Lever static int nfs4_xdr_dec_fsid_present(struct rpc_rqst *rqstp, 704044c99933SChuck Lever struct xdr_stream *xdr, 7041fc016483SChristoph Hellwig void *data) 704244c99933SChuck Lever { 7043fc016483SChristoph Hellwig struct nfs4_fsid_present_res *res = data; 704444c99933SChuck Lever struct compound_hdr hdr; 704544c99933SChuck Lever int status; 704644c99933SChuck Lever 704744c99933SChuck Lever status = decode_compound_hdr(xdr, &hdr); 704844c99933SChuck Lever if (status) 704944c99933SChuck Lever goto out; 705044c99933SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 705144c99933SChuck Lever if (status) 705244c99933SChuck Lever goto out; 705344c99933SChuck Lever status = decode_putfh(xdr); 705444c99933SChuck Lever if (status) 705544c99933SChuck Lever goto out; 705644c99933SChuck Lever status = decode_getfh(xdr, res->fh); 705744c99933SChuck Lever if (status) 705844c99933SChuck Lever goto out; 705944c99933SChuck Lever if (res->renew) 706044c99933SChuck Lever status = decode_renew(xdr); 706144c99933SChuck Lever out: 706244c99933SChuck Lever return status; 706344c99933SChuck Lever } 706444c99933SChuck Lever 706599fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 706699fe60d0SBenny Halevy /* 70677c44f1aeSWeston Andros Adamson * Decode BIND_CONN_TO_SESSION response 70687c44f1aeSWeston Andros Adamson */ 70697c44f1aeSWeston Andros Adamson static int nfs4_xdr_dec_bind_conn_to_session(struct rpc_rqst *rqstp, 70707c44f1aeSWeston Andros Adamson struct xdr_stream *xdr, 70717c44f1aeSWeston Andros Adamson void *res) 70727c44f1aeSWeston Andros Adamson { 70737c44f1aeSWeston Andros Adamson struct compound_hdr hdr; 70747c44f1aeSWeston Andros Adamson int status; 70757c44f1aeSWeston Andros Adamson 70767c44f1aeSWeston Andros Adamson status = decode_compound_hdr(xdr, &hdr); 70777c44f1aeSWeston Andros Adamson if (!status) 70787c44f1aeSWeston Andros Adamson status = decode_bind_conn_to_session(xdr, res); 70797c44f1aeSWeston Andros Adamson return status; 70807c44f1aeSWeston Andros Adamson } 70817c44f1aeSWeston Andros Adamson 70827c44f1aeSWeston Andros Adamson /* 70838b173218SRicardo Labiaga * Decode EXCHANGE_ID response 708499fe60d0SBenny Halevy */ 7085bf269551SChuck Lever static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, 7086bf269551SChuck Lever struct xdr_stream *xdr, 708799fe60d0SBenny Halevy void *res) 708899fe60d0SBenny Halevy { 708999fe60d0SBenny Halevy struct compound_hdr hdr; 709099fe60d0SBenny Halevy int status; 709199fe60d0SBenny Halevy 7092bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 709399fe60d0SBenny Halevy if (!status) 7094bf269551SChuck Lever status = decode_exchange_id(xdr, res); 709599fe60d0SBenny Halevy return status; 709699fe60d0SBenny Halevy } 70972050f0ccSAndy Adamson 70982050f0ccSAndy Adamson /* 70998b173218SRicardo Labiaga * Decode CREATE_SESSION response 7100fc931582SAndy Adamson */ 7101bf269551SChuck Lever static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, 7102bf269551SChuck Lever struct xdr_stream *xdr, 7103fc016483SChristoph Hellwig void *res) 7104fc931582SAndy Adamson { 7105fc931582SAndy Adamson struct compound_hdr hdr; 7106fc931582SAndy Adamson int status; 7107fc931582SAndy Adamson 7108bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 7109fc931582SAndy Adamson if (!status) 7110bf269551SChuck Lever status = decode_create_session(xdr, res); 7111fc931582SAndy Adamson return status; 7112fc931582SAndy Adamson } 7113fc931582SAndy Adamson 7114fc931582SAndy Adamson /* 71158b173218SRicardo Labiaga * Decode DESTROY_SESSION response 71160f3e66c6SAndy Adamson */ 7117bf269551SChuck Lever static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, 7118bf269551SChuck Lever struct xdr_stream *xdr, 7119bf269551SChuck Lever void *res) 71200f3e66c6SAndy Adamson { 71210f3e66c6SAndy Adamson struct compound_hdr hdr; 71220f3e66c6SAndy Adamson int status; 71230f3e66c6SAndy Adamson 7124bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 71250f3e66c6SAndy Adamson if (!status) 7126bf269551SChuck Lever status = decode_destroy_session(xdr, res); 71270f3e66c6SAndy Adamson return status; 71280f3e66c6SAndy Adamson } 71290f3e66c6SAndy Adamson 71300f3e66c6SAndy Adamson /* 713166245539STrond Myklebust * Decode DESTROY_CLIENTID response 713266245539STrond Myklebust */ 713366245539STrond Myklebust static int nfs4_xdr_dec_destroy_clientid(struct rpc_rqst *rqstp, 713466245539STrond Myklebust struct xdr_stream *xdr, 713566245539STrond Myklebust void *res) 713666245539STrond Myklebust { 713766245539STrond Myklebust struct compound_hdr hdr; 713866245539STrond Myklebust int status; 713966245539STrond Myklebust 714066245539STrond Myklebust status = decode_compound_hdr(xdr, &hdr); 714166245539STrond Myklebust if (!status) 714266245539STrond Myklebust status = decode_destroy_clientid(xdr, res); 714366245539STrond Myklebust return status; 714466245539STrond Myklebust } 714566245539STrond Myklebust 714666245539STrond Myklebust /* 71478b173218SRicardo Labiaga * Decode SEQUENCE response 7148fc01cea9SAndy Adamson */ 7149bf269551SChuck Lever static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, 7150bf269551SChuck Lever struct xdr_stream *xdr, 7151fc016483SChristoph Hellwig void *res) 7152fc01cea9SAndy Adamson { 7153fc01cea9SAndy Adamson struct compound_hdr hdr; 7154fc01cea9SAndy Adamson int status; 7155fc01cea9SAndy Adamson 7156bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 7157fc01cea9SAndy Adamson if (!status) 7158bf269551SChuck Lever status = decode_sequence(xdr, res, rqstp); 7159fc01cea9SAndy Adamson return status; 7160fc01cea9SAndy Adamson } 7161fc01cea9SAndy Adamson 71620efb01b2SDonald Buczek #endif 71630efb01b2SDonald Buczek 7164fc01cea9SAndy Adamson /* 71658b173218SRicardo Labiaga * Decode GET_LEASE_TIME response 71662050f0ccSAndy Adamson */ 7167bf269551SChuck Lever static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, 7168bf269551SChuck Lever struct xdr_stream *xdr, 7169fc016483SChristoph Hellwig void *data) 71702050f0ccSAndy Adamson { 7171fc016483SChristoph Hellwig struct nfs4_get_lease_time_res *res = data; 71722050f0ccSAndy Adamson struct compound_hdr hdr; 71732050f0ccSAndy Adamson int status; 71742050f0ccSAndy Adamson 7175bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 71762050f0ccSAndy Adamson if (!status) 7177bf269551SChuck Lever status = decode_sequence(xdr, &res->lr_seq_res, rqstp); 71782050f0ccSAndy Adamson if (!status) 7179bf269551SChuck Lever status = decode_putrootfh(xdr); 71802050f0ccSAndy Adamson if (!status) 7181bf269551SChuck Lever status = decode_fsinfo(xdr, res->lr_fsinfo); 71822050f0ccSAndy Adamson return status; 71832050f0ccSAndy Adamson } 718418019753SRicardo Labiaga 71850efb01b2SDonald Buczek #ifdef CONFIG_NFS_V4_1 71860efb01b2SDonald Buczek 718718019753SRicardo Labiaga /* 718818019753SRicardo Labiaga * Decode RECLAIM_COMPLETE response 718918019753SRicardo Labiaga */ 7190bf269551SChuck Lever static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, 7191bf269551SChuck Lever struct xdr_stream *xdr, 7192fc016483SChristoph Hellwig void *data) 719318019753SRicardo Labiaga { 7194fc016483SChristoph Hellwig struct nfs41_reclaim_complete_res *res = data; 719518019753SRicardo Labiaga struct compound_hdr hdr; 719618019753SRicardo Labiaga int status; 719718019753SRicardo Labiaga 7198bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 719918019753SRicardo Labiaga if (!status) 7200bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 720118019753SRicardo Labiaga if (!status) 72028ee2b78aSHimangi Saraogi status = decode_reclaim_complete(xdr, NULL); 720318019753SRicardo Labiaga return status; 720418019753SRicardo Labiaga } 7205b1f69b75SAndy Adamson 7206b1f69b75SAndy Adamson /* 7207b1f69b75SAndy Adamson * Decode GETDEVINFO response 7208b1f69b75SAndy Adamson */ 7209bf269551SChuck Lever static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, 7210bf269551SChuck Lever struct xdr_stream *xdr, 7211fc016483SChristoph Hellwig void *data) 7212b1f69b75SAndy Adamson { 7213fc016483SChristoph Hellwig struct nfs4_getdeviceinfo_res *res = data; 7214b1f69b75SAndy Adamson struct compound_hdr hdr; 7215b1f69b75SAndy Adamson int status; 7216b1f69b75SAndy Adamson 7217bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 7218b1f69b75SAndy Adamson if (status != 0) 7219b1f69b75SAndy Adamson goto out; 7220bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 7221b1f69b75SAndy Adamson if (status != 0) 7222b1f69b75SAndy Adamson goto out; 72234e590803STrond Myklebust status = decode_getdeviceinfo(xdr, res); 7224b1f69b75SAndy Adamson out: 7225b1f69b75SAndy Adamson return status; 7226b1f69b75SAndy Adamson } 7227b1f69b75SAndy Adamson 7228b1f69b75SAndy Adamson /* 7229b1f69b75SAndy Adamson * Decode LAYOUTGET response 7230b1f69b75SAndy Adamson */ 7231bf269551SChuck Lever static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, 7232bf269551SChuck Lever struct xdr_stream *xdr, 7233fc016483SChristoph Hellwig void *data) 7234b1f69b75SAndy Adamson { 7235fc016483SChristoph Hellwig struct nfs4_layoutget_res *res = data; 7236b1f69b75SAndy Adamson struct compound_hdr hdr; 7237b1f69b75SAndy Adamson int status; 7238b1f69b75SAndy Adamson 7239bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 7240b1f69b75SAndy Adamson if (status) 7241b1f69b75SAndy Adamson goto out; 7242bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 7243b1f69b75SAndy Adamson if (status) 7244b1f69b75SAndy Adamson goto out; 7245bf269551SChuck Lever status = decode_putfh(xdr); 7246b1f69b75SAndy Adamson if (status) 7247b1f69b75SAndy Adamson goto out; 7248bf269551SChuck Lever status = decode_layoutget(xdr, rqstp, res); 7249b1f69b75SAndy Adamson out: 7250b1f69b75SAndy Adamson return status; 7251b1f69b75SAndy Adamson } 7252863a3c6cSAndy Adamson 7253863a3c6cSAndy Adamson /* 7254cbe82603SBenny Halevy * Decode LAYOUTRETURN response 7255cbe82603SBenny Halevy */ 7256cbe82603SBenny Halevy static int nfs4_xdr_dec_layoutreturn(struct rpc_rqst *rqstp, 7257cbe82603SBenny Halevy struct xdr_stream *xdr, 7258fc016483SChristoph Hellwig void *data) 7259cbe82603SBenny Halevy { 7260fc016483SChristoph Hellwig struct nfs4_layoutreturn_res *res = data; 7261cbe82603SBenny Halevy struct compound_hdr hdr; 7262cbe82603SBenny Halevy int status; 7263cbe82603SBenny Halevy 7264cbe82603SBenny Halevy status = decode_compound_hdr(xdr, &hdr); 7265cbe82603SBenny Halevy if (status) 7266cbe82603SBenny Halevy goto out; 7267cbe82603SBenny Halevy status = decode_sequence(xdr, &res->seq_res, rqstp); 7268cbe82603SBenny Halevy if (status) 7269cbe82603SBenny Halevy goto out; 7270cbe82603SBenny Halevy status = decode_putfh(xdr); 7271cbe82603SBenny Halevy if (status) 7272cbe82603SBenny Halevy goto out; 7273cbe82603SBenny Halevy status = decode_layoutreturn(xdr, res); 7274cbe82603SBenny Halevy out: 7275cbe82603SBenny Halevy return status; 7276cbe82603SBenny Halevy } 7277cbe82603SBenny Halevy 7278cbe82603SBenny Halevy /* 7279863a3c6cSAndy Adamson * Decode LAYOUTCOMMIT response 7280863a3c6cSAndy Adamson */ 7281863a3c6cSAndy Adamson static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, 7282863a3c6cSAndy Adamson struct xdr_stream *xdr, 7283fc016483SChristoph Hellwig void *data) 7284863a3c6cSAndy Adamson { 7285fc016483SChristoph Hellwig struct nfs4_layoutcommit_res *res = data; 7286863a3c6cSAndy Adamson struct compound_hdr hdr; 7287863a3c6cSAndy Adamson int status; 7288863a3c6cSAndy Adamson 7289863a3c6cSAndy Adamson status = decode_compound_hdr(xdr, &hdr); 7290863a3c6cSAndy Adamson if (status) 7291863a3c6cSAndy Adamson goto out; 7292863a3c6cSAndy Adamson status = decode_sequence(xdr, &res->seq_res, rqstp); 7293863a3c6cSAndy Adamson if (status) 7294863a3c6cSAndy Adamson goto out; 7295863a3c6cSAndy Adamson status = decode_putfh(xdr); 7296863a3c6cSAndy Adamson if (status) 7297863a3c6cSAndy Adamson goto out; 7298863a3c6cSAndy Adamson status = decode_layoutcommit(xdr, rqstp, res); 7299863a3c6cSAndy Adamson if (status) 7300863a3c6cSAndy Adamson goto out; 73016926afd1STrond Myklebust decode_getfattr(xdr, res->fattr, res->server); 7302863a3c6cSAndy Adamson out: 7303863a3c6cSAndy Adamson return status; 7304863a3c6cSAndy Adamson } 7305fca78d6dSBryan Schumaker 7306fca78d6dSBryan Schumaker /* 7307fca78d6dSBryan Schumaker * Decode SECINFO_NO_NAME response 7308fca78d6dSBryan Schumaker */ 7309fca78d6dSBryan Schumaker static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp, 7310fca78d6dSBryan Schumaker struct xdr_stream *xdr, 7311fc016483SChristoph Hellwig void *data) 7312fca78d6dSBryan Schumaker { 7313fc016483SChristoph Hellwig struct nfs4_secinfo_res *res = data; 7314fca78d6dSBryan Schumaker struct compound_hdr hdr; 7315fca78d6dSBryan Schumaker int status; 7316fca78d6dSBryan Schumaker 7317fca78d6dSBryan Schumaker status = decode_compound_hdr(xdr, &hdr); 7318fca78d6dSBryan Schumaker if (status) 7319fca78d6dSBryan Schumaker goto out; 7320fca78d6dSBryan Schumaker status = decode_sequence(xdr, &res->seq_res, rqstp); 7321fca78d6dSBryan Schumaker if (status) 7322fca78d6dSBryan Schumaker goto out; 7323fca78d6dSBryan Schumaker status = decode_putrootfh(xdr); 7324fca78d6dSBryan Schumaker if (status) 7325fca78d6dSBryan Schumaker goto out; 732631e4dda4SBryan Schumaker status = decode_secinfo_no_name(xdr, res); 7327fca78d6dSBryan Schumaker out: 7328fca78d6dSBryan Schumaker return status; 7329fca78d6dSBryan Schumaker } 73307d974794SBryan Schumaker 73317d974794SBryan Schumaker /* 73327d974794SBryan Schumaker * Decode TEST_STATEID response 73337d974794SBryan Schumaker */ 73347d974794SBryan Schumaker static int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp, 73357d974794SBryan Schumaker struct xdr_stream *xdr, 7336fc016483SChristoph Hellwig void *data) 73377d974794SBryan Schumaker { 7338fc016483SChristoph Hellwig struct nfs41_test_stateid_res *res = data; 73397d974794SBryan Schumaker struct compound_hdr hdr; 73407d974794SBryan Schumaker int status; 73417d974794SBryan Schumaker 73427d974794SBryan Schumaker status = decode_compound_hdr(xdr, &hdr); 73437d974794SBryan Schumaker if (status) 73447d974794SBryan Schumaker goto out; 73457d974794SBryan Schumaker status = decode_sequence(xdr, &res->seq_res, rqstp); 73467d974794SBryan Schumaker if (status) 73477d974794SBryan Schumaker goto out; 73487d974794SBryan Schumaker status = decode_test_stateid(xdr, res); 73497d974794SBryan Schumaker out: 73507d974794SBryan Schumaker return status; 73517d974794SBryan Schumaker } 73529aeda35fSBryan Schumaker 73539aeda35fSBryan Schumaker /* 73549aeda35fSBryan Schumaker * Decode FREE_STATEID response 73559aeda35fSBryan Schumaker */ 73569aeda35fSBryan Schumaker static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp, 73579aeda35fSBryan Schumaker struct xdr_stream *xdr, 7358fc016483SChristoph Hellwig void *data) 73599aeda35fSBryan Schumaker { 7360fc016483SChristoph Hellwig struct nfs41_free_stateid_res *res = data; 73619aeda35fSBryan Schumaker struct compound_hdr hdr; 73629aeda35fSBryan Schumaker int status; 73639aeda35fSBryan Schumaker 73649aeda35fSBryan Schumaker status = decode_compound_hdr(xdr, &hdr); 73659aeda35fSBryan Schumaker if (status) 73669aeda35fSBryan Schumaker goto out; 73679aeda35fSBryan Schumaker status = decode_sequence(xdr, &res->seq_res, rqstp); 73689aeda35fSBryan Schumaker if (status) 73699aeda35fSBryan Schumaker goto out; 73709aeda35fSBryan Schumaker status = decode_free_stateid(xdr, res); 73719aeda35fSBryan Schumaker out: 73729aeda35fSBryan Schumaker return status; 73739aeda35fSBryan Schumaker } 737499fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 737599fe60d0SBenny Halevy 7376573c4e1eSChuck Lever /** 7377573c4e1eSChuck Lever * nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in 7378573c4e1eSChuck Lever * the local page cache. 7379573c4e1eSChuck Lever * @xdr: XDR stream where entry resides 7380573c4e1eSChuck Lever * @entry: buffer to fill in with entry data 7381573c4e1eSChuck Lever * @plus: boolean indicating whether this should be a readdirplus entry 7382573c4e1eSChuck Lever * 7383573c4e1eSChuck Lever * Returns zero if successful, otherwise a negative errno value is 7384573c4e1eSChuck Lever * returned. 7385573c4e1eSChuck Lever * 7386573c4e1eSChuck Lever * This function is not invoked during READDIR reply decoding, but 7387573c4e1eSChuck Lever * rather whenever an application invokes the getdents(2) system call 7388573c4e1eSChuck Lever * on a directory already in our cache. 7389573c4e1eSChuck Lever */ 7390573c4e1eSChuck Lever int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, 7391a7a3b1e9SBenjamin Coddington bool plus) 73921da177e4SLinus Torvalds { 7393256e48bbSTrond Myklebust unsigned int savep; 7394dae100c2SFred Isaman uint32_t bitmap[3] = {0}; 73951da177e4SLinus Torvalds uint32_t len; 739698de9ce6SFrank Sorenson uint64_t new_cookie; 7397babddc72SBryan Schumaker __be32 *p = xdr_inline_decode(xdr, 4); 7398babddc72SBryan Schumaker if (unlikely(!p)) 7399eb72f484SChuck Lever return -EAGAIN; 7400c08e76d0SChuck Lever if (*p == xdr_zero) { 7401babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 4); 7402babddc72SBryan Schumaker if (unlikely(!p)) 7403eb72f484SChuck Lever return -EAGAIN; 7404c08e76d0SChuck Lever if (*p == xdr_zero) 7405573c4e1eSChuck Lever return -EAGAIN; 74061da177e4SLinus Torvalds entry->eof = 1; 7407573c4e1eSChuck Lever return -EBADCOOKIE; 74081da177e4SLinus Torvalds } 74091da177e4SLinus Torvalds 7410babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 12); 7411babddc72SBryan Schumaker if (unlikely(!p)) 7412eb72f484SChuck Lever return -EAGAIN; 741398de9ce6SFrank Sorenson p = xdr_decode_hyper(p, &new_cookie); 7414c08e76d0SChuck Lever entry->len = be32_to_cpup(p); 7415babddc72SBryan Schumaker 74169af8c222STrond Myklebust p = xdr_inline_decode(xdr, entry->len); 7417babddc72SBryan Schumaker if (unlikely(!p)) 7418eb72f484SChuck Lever return -EAGAIN; 74191da177e4SLinus Torvalds entry->name = (const char *) p; 74201da177e4SLinus Torvalds 74211da177e4SLinus Torvalds /* 74221da177e4SLinus Torvalds * In case the server doesn't return an inode number, 74231da177e4SLinus Torvalds * we fake one here. (We don't use inode number 0, 74241da177e4SLinus Torvalds * since glibc seems to choke on it...) 74251da177e4SLinus Torvalds */ 74261da177e4SLinus Torvalds entry->ino = 1; 74274f082222STrond Myklebust entry->fattr->valid = 0; 74281da177e4SLinus Torvalds 74299af8c222STrond Myklebust if (decode_attr_bitmap(xdr, bitmap) < 0) 7430eb72f484SChuck Lever return -EAGAIN; 74319af8c222STrond Myklebust 7432256e48bbSTrond Myklebust if (decode_attr_length(xdr, &len, &savep) < 0) 7433eb72f484SChuck Lever return -EAGAIN; 74349af8c222STrond Myklebust 7435573c4e1eSChuck Lever if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, 7436aa9c2669SDavid Quigley NULL, entry->label, entry->server) < 0) 7437eb72f484SChuck Lever return -EAGAIN; 743828331a46STrond Myklebust if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) 743928331a46STrond Myklebust entry->ino = entry->fattr->mounted_on_fileid; 744028331a46STrond Myklebust else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) 744182f2e547SBryan Schumaker entry->ino = entry->fattr->fileid; 74429af8c222STrond Myklebust 74430b26a0bfSTrond Myklebust entry->d_type = DT_UNKNOWN; 74440b26a0bfSTrond Myklebust if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE) 74450b26a0bfSTrond Myklebust entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); 74460b26a0bfSTrond Myklebust 744798de9ce6SFrank Sorenson entry->prev_cookie = entry->cookie; 744898de9ce6SFrank Sorenson entry->cookie = new_cookie; 744998de9ce6SFrank Sorenson 7450573c4e1eSChuck Lever return 0; 74511da177e4SLinus Torvalds } 74521da177e4SLinus Torvalds 74531da177e4SLinus Torvalds /* 74541da177e4SLinus Torvalds * We need to translate between nfs status return values and 74551da177e4SLinus Torvalds * the local errno values which may not be the same. 74561da177e4SLinus Torvalds */ 74571da177e4SLinus Torvalds static struct { 74581da177e4SLinus Torvalds int stat; 74591da177e4SLinus Torvalds int errno; 74601da177e4SLinus Torvalds } nfs_errtbl[] = { 74611da177e4SLinus Torvalds { NFS4_OK, 0 }, 7462856dff3dSBenny Halevy { NFS4ERR_PERM, -EPERM }, 7463856dff3dSBenny Halevy { NFS4ERR_NOENT, -ENOENT }, 7464856dff3dSBenny Halevy { NFS4ERR_IO, -errno_NFSERR_IO}, 7465856dff3dSBenny Halevy { NFS4ERR_NXIO, -ENXIO }, 7466856dff3dSBenny Halevy { NFS4ERR_ACCESS, -EACCES }, 7467856dff3dSBenny Halevy { NFS4ERR_EXIST, -EEXIST }, 7468856dff3dSBenny Halevy { NFS4ERR_XDEV, -EXDEV }, 7469856dff3dSBenny Halevy { NFS4ERR_NOTDIR, -ENOTDIR }, 7470856dff3dSBenny Halevy { NFS4ERR_ISDIR, -EISDIR }, 7471856dff3dSBenny Halevy { NFS4ERR_INVAL, -EINVAL }, 7472856dff3dSBenny Halevy { NFS4ERR_FBIG, -EFBIG }, 7473856dff3dSBenny Halevy { NFS4ERR_NOSPC, -ENOSPC }, 7474856dff3dSBenny Halevy { NFS4ERR_ROFS, -EROFS }, 7475856dff3dSBenny Halevy { NFS4ERR_MLINK, -EMLINK }, 7476856dff3dSBenny Halevy { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG }, 7477856dff3dSBenny Halevy { NFS4ERR_NOTEMPTY, -ENOTEMPTY }, 7478856dff3dSBenny Halevy { NFS4ERR_DQUOT, -EDQUOT }, 7479856dff3dSBenny Halevy { NFS4ERR_STALE, -ESTALE }, 7480856dff3dSBenny Halevy { NFS4ERR_BADHANDLE, -EBADHANDLE }, 7481856dff3dSBenny Halevy { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, 7482856dff3dSBenny Halevy { NFS4ERR_NOTSUPP, -ENOTSUPP }, 7483856dff3dSBenny Halevy { NFS4ERR_TOOSMALL, -ETOOSMALL }, 7484fdcb4577STrond Myklebust { NFS4ERR_SERVERFAULT, -EREMOTEIO }, 7485856dff3dSBenny Halevy { NFS4ERR_BADTYPE, -EBADTYPE }, 7486856dff3dSBenny Halevy { NFS4ERR_LOCKED, -EAGAIN }, 7487856dff3dSBenny Halevy { NFS4ERR_SYMLINK, -ELOOP }, 7488856dff3dSBenny Halevy { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, 7489856dff3dSBenny Halevy { NFS4ERR_DEADLOCK, -EDEADLK }, 74903e1f0212SFrank van der Linden { NFS4ERR_NOXATTR, -ENODATA }, 74913e1f0212SFrank van der Linden { NFS4ERR_XATTR2BIG, -E2BIG }, 7492856dff3dSBenny Halevy { -1, -EIO } 74931da177e4SLinus Torvalds }; 74941da177e4SLinus Torvalds 74951da177e4SLinus Torvalds /* 74961da177e4SLinus Torvalds * Convert an NFS error code to a local one. 74971da177e4SLinus Torvalds * This one is used jointly by NFSv2 and NFSv3. 74981da177e4SLinus Torvalds */ 74991da177e4SLinus Torvalds static int 75000a8ea437SDavid Howells nfs4_stat_to_errno(int stat) 75011da177e4SLinus Torvalds { 75021da177e4SLinus Torvalds int i; 75031da177e4SLinus Torvalds for (i = 0; nfs_errtbl[i].stat != -1; i++) { 75041da177e4SLinus Torvalds if (nfs_errtbl[i].stat == stat) 75051da177e4SLinus Torvalds return nfs_errtbl[i].errno; 75061da177e4SLinus Torvalds } 75071da177e4SLinus Torvalds if (stat <= 10000 || stat > 10100) { 75081da177e4SLinus Torvalds /* The server is looney tunes. */ 7509fdcb4577STrond Myklebust return -EREMOTEIO; 75101da177e4SLinus Torvalds } 75111da177e4SLinus Torvalds /* If we cannot translate the error, the recovery routines should 75121da177e4SLinus Torvalds * handle it. 75131da177e4SLinus Torvalds * Note: remaining NFSv4 error codes have values > 10000, so should 75141da177e4SLinus Torvalds * not conflict with native Linux error codes. 75151da177e4SLinus Torvalds */ 7516856dff3dSBenny Halevy return -stat; 75171da177e4SLinus Torvalds } 75181da177e4SLinus Torvalds 75191c6dcbe5SAnna Schumaker #ifdef CONFIG_NFS_V4_2 75201c6dcbe5SAnna Schumaker #include "nfs42xdr.c" 75211c6dcbe5SAnna Schumaker #endif /* CONFIG_NFS_V4_2 */ 75221c6dcbe5SAnna Schumaker 75231da177e4SLinus Torvalds #define PROC(proc, argtype, restype) \ 75241da177e4SLinus Torvalds [NFSPROC4_CLNT_##proc] = { \ 75251da177e4SLinus Torvalds .p_proc = NFSPROC4_COMPOUND, \ 7526fcc85819SChristoph Hellwig .p_encode = nfs4_xdr_##argtype, \ 7527fc016483SChristoph Hellwig .p_decode = nfs4_xdr_##restype, \ 75282bea90d4SChuck Lever .p_arglen = NFS4_##argtype##_sz, \ 75292bea90d4SChuck Lever .p_replen = NFS4_##restype##_sz, \ 7530cc0175c1SChuck Lever .p_statidx = NFSPROC4_CLNT_##proc, \ 7531cc0175c1SChuck Lever .p_name = #proc, \ 75321da177e4SLinus Torvalds } 75331da177e4SLinus Torvalds 75347c61f0d3SAnna Schumaker #define STUB(proc) \ 75357c61f0d3SAnna Schumaker [NFSPROC4_CLNT_##proc] = { \ 75367c61f0d3SAnna Schumaker .p_name = #proc, \ 75377c61f0d3SAnna Schumaker } 75387c61f0d3SAnna Schumaker 75398634ef5eSTrond Myklebust #if defined(CONFIG_NFS_V4_1) 75408634ef5eSTrond Myklebust #define PROC41(proc, argtype, restype) \ 75418634ef5eSTrond Myklebust PROC(proc, argtype, restype) 75428634ef5eSTrond Myklebust #else 75438634ef5eSTrond Myklebust #define PROC41(proc, argtype, restype) \ 75448634ef5eSTrond Myklebust STUB(proc) 75458634ef5eSTrond Myklebust #endif 75468634ef5eSTrond Myklebust 75478634ef5eSTrond Myklebust #if defined(CONFIG_NFS_V4_2) 75488634ef5eSTrond Myklebust #define PROC42(proc, argtype, restype) \ 75498634ef5eSTrond Myklebust PROC(proc, argtype, restype) 75508634ef5eSTrond Myklebust #else 75518634ef5eSTrond Myklebust #define PROC42(proc, argtype, restype) \ 75528634ef5eSTrond Myklebust STUB(proc) 75538634ef5eSTrond Myklebust #endif 75548634ef5eSTrond Myklebust 7555511e936bSChristoph Hellwig const struct rpc_procinfo nfs4_procedures[] = { 75561da177e4SLinus Torvalds PROC(READ, enc_read, dec_read), 75571da177e4SLinus Torvalds PROC(WRITE, enc_write, dec_write), 75581da177e4SLinus Torvalds PROC(COMMIT, enc_commit, dec_commit), 75591da177e4SLinus Torvalds PROC(OPEN, enc_open, dec_open), 75601da177e4SLinus Torvalds PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm), 75611da177e4SLinus Torvalds PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr), 75621da177e4SLinus Torvalds PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade), 75631da177e4SLinus Torvalds PROC(CLOSE, enc_close, dec_close), 75641da177e4SLinus Torvalds PROC(SETATTR, enc_setattr, dec_setattr), 75651da177e4SLinus Torvalds PROC(FSINFO, enc_fsinfo, dec_fsinfo), 75661da177e4SLinus Torvalds PROC(RENEW, enc_renew, dec_renew), 75671da177e4SLinus Torvalds PROC(SETCLIENTID, enc_setclientid, dec_setclientid), 75681da177e4SLinus Torvalds PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm), 75691da177e4SLinus Torvalds PROC(LOCK, enc_lock, dec_lock), 75701da177e4SLinus Torvalds PROC(LOCKT, enc_lockt, dec_lockt), 75711da177e4SLinus Torvalds PROC(LOCKU, enc_locku, dec_locku), 75721da177e4SLinus Torvalds PROC(ACCESS, enc_access, dec_access), 75731da177e4SLinus Torvalds PROC(GETATTR, enc_getattr, dec_getattr), 75741da177e4SLinus Torvalds PROC(LOOKUP, enc_lookup, dec_lookup), 75751da177e4SLinus Torvalds PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), 75761da177e4SLinus Torvalds PROC(REMOVE, enc_remove, dec_remove), 75771da177e4SLinus Torvalds PROC(RENAME, enc_rename, dec_rename), 75781da177e4SLinus Torvalds PROC(LINK, enc_link, dec_link), 75791da177e4SLinus Torvalds PROC(SYMLINK, enc_symlink, dec_symlink), 75801da177e4SLinus Torvalds PROC(CREATE, enc_create, dec_create), 75811da177e4SLinus Torvalds PROC(PATHCONF, enc_pathconf, dec_pathconf), 75821da177e4SLinus Torvalds PROC(STATFS, enc_statfs, dec_statfs), 75831da177e4SLinus Torvalds PROC(READLINK, enc_readlink, dec_readlink), 75841da177e4SLinus Torvalds PROC(READDIR, enc_readdir, dec_readdir), 75851da177e4SLinus Torvalds PROC(SERVER_CAPS, enc_server_caps, dec_server_caps), 75861da177e4SLinus Torvalds PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), 7587029d105eSJ. Bruce Fields PROC(GETACL, enc_getacl, dec_getacl), 758823ec6965SJ. Bruce Fields PROC(SETACL, enc_setacl, dec_setacl), 7589683b57b4STrond Myklebust PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), 7590d3c7b7ccSTrond Myklebust PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), 75915a5ea0d4SBryan Schumaker PROC(SECINFO, enc_secinfo, dec_secinfo), 759244c99933SChuck Lever PROC(FSID_PRESENT, enc_fsid_present, dec_fsid_present), 75938634ef5eSTrond Myklebust PROC41(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), 75948634ef5eSTrond Myklebust PROC41(CREATE_SESSION, enc_create_session, dec_create_session), 75958634ef5eSTrond Myklebust PROC41(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), 75968634ef5eSTrond Myklebust PROC41(SEQUENCE, enc_sequence, dec_sequence), 75970efb01b2SDonald Buczek PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), 75988634ef5eSTrond Myklebust PROC41(RECLAIM_COMPLETE,enc_reclaim_complete, dec_reclaim_complete), 75998634ef5eSTrond Myklebust PROC41(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), 76008634ef5eSTrond Myklebust PROC41(LAYOUTGET, enc_layoutget, dec_layoutget), 76018634ef5eSTrond Myklebust PROC41(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), 76028634ef5eSTrond Myklebust PROC41(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), 76038634ef5eSTrond Myklebust PROC41(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), 76048634ef5eSTrond Myklebust PROC41(TEST_STATEID, enc_test_stateid, dec_test_stateid), 76058634ef5eSTrond Myklebust PROC41(FREE_STATEID, enc_free_stateid, dec_free_stateid), 76067c61f0d3SAnna Schumaker STUB(GETDEVICELIST), 76078634ef5eSTrond Myklebust PROC41(BIND_CONN_TO_SESSION, 7608ad24ecfbSTrond Myklebust enc_bind_conn_to_session, dec_bind_conn_to_session), 76098634ef5eSTrond Myklebust PROC41(DESTROY_CLIENTID,enc_destroy_clientid, dec_destroy_clientid), 76108634ef5eSTrond Myklebust PROC42(SEEK, enc_seek, dec_seek), 76118634ef5eSTrond Myklebust PROC42(ALLOCATE, enc_allocate, dec_allocate), 76128634ef5eSTrond Myklebust PROC42(DEALLOCATE, enc_deallocate, dec_deallocate), 76138634ef5eSTrond Myklebust PROC42(LAYOUTSTATS, enc_layoutstats, dec_layoutstats), 76148634ef5eSTrond Myklebust PROC42(CLONE, enc_clone, dec_clone), 76158634ef5eSTrond Myklebust PROC42(COPY, enc_copy, dec_copy), 7616cb95deeaSOlga Kornievskaia PROC42(OFFLOAD_CANCEL, enc_offload_cancel, dec_offload_cancel), 76170491567bSOlga Kornievskaia PROC42(COPY_NOTIFY, enc_copy_notify, dec_copy_notify), 76188634ef5eSTrond Myklebust PROC(LOOKUPP, enc_lookupp, dec_lookupp), 76193eb86093STrond Myklebust PROC42(LAYOUTERROR, enc_layouterror, dec_layouterror), 76203e1f0212SFrank van der Linden PROC42(GETXATTR, enc_getxattr, dec_getxattr), 76213e1f0212SFrank van der Linden PROC42(SETXATTR, enc_setxattr, dec_setxattr), 76223e1f0212SFrank van der Linden PROC42(LISTXATTRS, enc_listxattrs, dec_listxattrs), 76233e1f0212SFrank van der Linden PROC42(REMOVEXATTR, enc_removexattr, dec_removexattr), 7624c5675526SAnna Schumaker PROC42(READ_PLUS, enc_read_plus, dec_read_plus), 76251da177e4SLinus Torvalds }; 76261da177e4SLinus Torvalds 7627c551858aSChristoph Hellwig static unsigned int nfs_version4_counts[ARRAY_SIZE(nfs4_procedures)]; 7628a613fa16STrond Myklebust const struct rpc_version nfs_version4 = { 76291da177e4SLinus Torvalds .number = 4, 7630e8c96f8cSTobias Klauser .nrprocs = ARRAY_SIZE(nfs4_procedures), 7631c551858aSChristoph Hellwig .procs = nfs4_procedures, 7632c551858aSChristoph Hellwig .counts = nfs_version4_counts, 76331da177e4SLinus Torvalds }; 76341da177e4SLinus Torvalds 76351da177e4SLinus Torvalds /* 76361da177e4SLinus Torvalds * Local variables: 76371da177e4SLinus Torvalds * c-basic-offset: 8 76381da177e4SLinus Torvalds * End: 76391da177e4SLinus Torvalds */ 7640