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 + \ 14757a789a1STrond Myklebust nfs4_fattr_bitmap_maxsz + 1 + \ 14857a789a1STrond Myklebust 1 /* lease time */ + \ 14957a789a1STrond Myklebust 2 /* max filesize */ + \ 15057a789a1STrond Myklebust 2 /* max read */ + \ 15157a789a1STrond Myklebust 2 /* max write */ + \ 15257a789a1STrond Myklebust nfstime4_maxsz /* time delta */ + \ 15357a789a1STrond Myklebust 5 /* fs layout types */ + \ 15457a789a1STrond Myklebust 1 /* layout blksize */ + \ 15557a789a1STrond Myklebust 1 /* clone blksize */ + \ 1567f08a335STrond Myklebust 1 /* change attr type */ + \ 15757a789a1STrond Myklebust 1 /* xattr support */) 1581da177e4SLinus Torvalds #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) 1591da177e4SLinus Torvalds #define decode_renew_maxsz (op_decode_hdr_maxsz) 1601da177e4SLinus Torvalds #define encode_setclientid_maxsz \ 1611da177e4SLinus Torvalds (op_encode_hdr_maxsz + \ 162cc38bac3SChuck Lever XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ 163b8fb2f59SJeff Layton /* client name */ \ 164b8fb2f59SJeff Layton 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 165cc38bac3SChuck Lever 1 /* sc_prog */ + \ 1666dd3436bSChuck Lever 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ 1676dd3436bSChuck Lever 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ 168cc38bac3SChuck Lever 1) /* sc_cb_ident */ 1691da177e4SLinus Torvalds #define decode_setclientid_maxsz \ 1701da177e4SLinus Torvalds (op_decode_hdr_maxsz + \ 1716dd3436bSChuck Lever 2 /* clientid */ + \ 1726dd3436bSChuck Lever XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ 1736dd3436bSChuck Lever 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ 1746dd3436bSChuck Lever 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN)) 1751da177e4SLinus Torvalds #define encode_setclientid_confirm_maxsz \ 1761da177e4SLinus Torvalds (op_encode_hdr_maxsz + \ 1771da177e4SLinus Torvalds 3 + (NFS4_VERIFIER_SIZE >> 2)) 1781da177e4SLinus Torvalds #define decode_setclientid_confirm_maxsz \ 1791da177e4SLinus Torvalds (op_decode_hdr_maxsz) 180e6889620STrond Myklebust #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) 181e6889620STrond Myklebust #define decode_lookup_maxsz (op_decode_hdr_maxsz) 1825b5faaf6SJeff Layton #define encode_lookupp_maxsz (op_encode_hdr_maxsz) 1835b5faaf6SJeff Layton #define decode_lookupp_maxsz (op_decode_hdr_maxsz) 1842cebf828STrond Myklebust #define encode_share_access_maxsz \ 1852cebf828STrond Myklebust (2) 1864882ef72SAlexandros Batsakis #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) 1872cebf828STrond Myklebust #define encode_opentype_maxsz (1 + encode_createmode_maxsz) 1882cebf828STrond Myklebust #define encode_claim_null_maxsz (1 + nfs4_name_maxsz) 1892cebf828STrond Myklebust #define encode_open_maxsz (op_encode_hdr_maxsz + \ 1902cebf828STrond Myklebust 2 + encode_share_access_maxsz + 2 + \ 1912cebf828STrond Myklebust open_owner_id_maxsz + \ 1922cebf828STrond Myklebust encode_opentype_maxsz + \ 1932cebf828STrond Myklebust encode_claim_null_maxsz) 1945a1f6d9eSTrond Myklebust #define decode_space_limit_maxsz (3) 1952cebf828STrond Myklebust #define decode_ace_maxsz (3 + nfs4_owner_maxsz) 1969104a55dSTrond Myklebust #define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \ 1975a1f6d9eSTrond Myklebust decode_space_limit_maxsz + \ 1982cebf828STrond Myklebust decode_ace_maxsz) 1992cebf828STrond Myklebust #define decode_change_info_maxsz (5) 2002cebf828STrond Myklebust #define decode_open_maxsz (op_decode_hdr_maxsz + \ 2019104a55dSTrond Myklebust decode_stateid_maxsz + \ 2022cebf828STrond Myklebust decode_change_info_maxsz + 1 + \ 2032cebf828STrond Myklebust nfs4_fattr_bitmap_maxsz + \ 2042cebf828STrond Myklebust decode_delegation_maxsz) 2059104a55dSTrond Myklebust #define encode_open_confirm_maxsz \ 2069104a55dSTrond Myklebust (op_encode_hdr_maxsz + \ 2079104a55dSTrond Myklebust encode_stateid_maxsz + 1) 2089104a55dSTrond Myklebust #define decode_open_confirm_maxsz \ 2099104a55dSTrond Myklebust (op_decode_hdr_maxsz + \ 2109104a55dSTrond Myklebust decode_stateid_maxsz) 2119104a55dSTrond Myklebust #define encode_open_downgrade_maxsz \ 2129104a55dSTrond Myklebust (op_encode_hdr_maxsz + \ 2139104a55dSTrond Myklebust encode_stateid_maxsz + 1 + \ 2149104a55dSTrond Myklebust encode_share_access_maxsz) 2159104a55dSTrond Myklebust #define decode_open_downgrade_maxsz \ 2169104a55dSTrond Myklebust (op_decode_hdr_maxsz + \ 2179104a55dSTrond Myklebust decode_stateid_maxsz) 2189104a55dSTrond Myklebust #define encode_close_maxsz (op_encode_hdr_maxsz + \ 2199104a55dSTrond Myklebust 1 + encode_stateid_maxsz) 2209104a55dSTrond Myklebust #define decode_close_maxsz (op_decode_hdr_maxsz + \ 2219104a55dSTrond Myklebust decode_stateid_maxsz) 2229104a55dSTrond Myklebust #define encode_setattr_maxsz (op_encode_hdr_maxsz + \ 2239104a55dSTrond Myklebust encode_stateid_maxsz + \ 2249104a55dSTrond Myklebust encode_attrs_maxsz) 2259104a55dSTrond Myklebust #define decode_setattr_maxsz (op_decode_hdr_maxsz + \ 2269104a55dSTrond Myklebust nfs4_fattr_bitmap_maxsz) 2279104a55dSTrond Myklebust #define encode_read_maxsz (op_encode_hdr_maxsz + \ 2289104a55dSTrond Myklebust encode_stateid_maxsz + 3) 2299ed5af26STrond Myklebust #define decode_read_maxsz (op_decode_hdr_maxsz + 2 + pagepad_maxsz) 2309104a55dSTrond Myklebust #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ 231aa9c2669SDavid Quigley 2 + encode_verifier_maxsz + 5 + \ 232aa9c2669SDavid Quigley nfs4_label_maxsz) 2339104a55dSTrond Myklebust #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ 2349ed5af26STrond Myklebust decode_verifier_maxsz + pagepad_maxsz) 2359104a55dSTrond Myklebust #define encode_readlink_maxsz (op_encode_hdr_maxsz) 2369ed5af26STrond Myklebust #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1 + pagepad_maxsz) 2379104a55dSTrond Myklebust #define encode_write_maxsz (op_encode_hdr_maxsz + \ 2389104a55dSTrond Myklebust encode_stateid_maxsz + 4) 2399104a55dSTrond Myklebust #define decode_write_maxsz (op_decode_hdr_maxsz + \ 2409104a55dSTrond Myklebust 2 + decode_verifier_maxsz) 2419104a55dSTrond Myklebust #define encode_commit_maxsz (op_encode_hdr_maxsz + 3) 2429104a55dSTrond Myklebust #define decode_commit_maxsz (op_decode_hdr_maxsz + \ 2439104a55dSTrond Myklebust decode_verifier_maxsz) 2441da177e4SLinus Torvalds #define encode_remove_maxsz (op_encode_hdr_maxsz + \ 2451da177e4SLinus Torvalds nfs4_name_maxsz) 2466ce18391SBenny Halevy #define decode_remove_maxsz (op_decode_hdr_maxsz + \ 2476ce18391SBenny Halevy decode_change_info_maxsz) 2481da177e4SLinus Torvalds #define encode_rename_maxsz (op_encode_hdr_maxsz + \ 2491da177e4SLinus Torvalds 2 * nfs4_name_maxsz) 2506ce18391SBenny Halevy #define decode_rename_maxsz (op_decode_hdr_maxsz + \ 2516ce18391SBenny Halevy decode_change_info_maxsz + \ 2526ce18391SBenny Halevy decode_change_info_maxsz) 2531da177e4SLinus Torvalds #define encode_link_maxsz (op_encode_hdr_maxsz + \ 2541da177e4SLinus Torvalds nfs4_name_maxsz) 2556ce18391SBenny Halevy #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) 256daccbdedSTrond Myklebust #define encode_lockowner_maxsz (7) 2579104a55dSTrond Myklebust #define encode_lock_maxsz (op_encode_hdr_maxsz + \ 2589104a55dSTrond Myklebust 7 + \ 259daccbdedSTrond Myklebust 1 + encode_stateid_maxsz + 1 + \ 260daccbdedSTrond Myklebust encode_lockowner_maxsz) 2619104a55dSTrond Myklebust #define decode_lock_denied_maxsz \ 2629104a55dSTrond Myklebust (8 + decode_lockowner_maxsz) 2639104a55dSTrond Myklebust #define decode_lock_maxsz (op_decode_hdr_maxsz + \ 2649104a55dSTrond Myklebust decode_lock_denied_maxsz) 265daccbdedSTrond Myklebust #define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \ 266daccbdedSTrond Myklebust encode_lockowner_maxsz) 2679104a55dSTrond Myklebust #define decode_lockt_maxsz (op_decode_hdr_maxsz + \ 2689104a55dSTrond Myklebust decode_lock_denied_maxsz) 2699104a55dSTrond Myklebust #define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \ 2709104a55dSTrond Myklebust encode_stateid_maxsz + \ 2719104a55dSTrond Myklebust 4) 2729104a55dSTrond Myklebust #define decode_locku_maxsz (op_decode_hdr_maxsz + \ 2739104a55dSTrond Myklebust decode_stateid_maxsz) 274d3c7b7ccSTrond Myklebust #define encode_release_lockowner_maxsz \ 275d3c7b7ccSTrond Myklebust (op_encode_hdr_maxsz + \ 276d3c7b7ccSTrond Myklebust encode_lockowner_maxsz) 277d3c7b7ccSTrond Myklebust #define decode_release_lockowner_maxsz \ 278d3c7b7ccSTrond Myklebust (op_decode_hdr_maxsz) 2799104a55dSTrond Myklebust #define encode_access_maxsz (op_encode_hdr_maxsz + 1) 2809104a55dSTrond Myklebust #define decode_access_maxsz (op_decode_hdr_maxsz + 2) 2811da177e4SLinus Torvalds #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ 2821da177e4SLinus Torvalds 1 + nfs4_name_maxsz + \ 28394a6d753SChuck Lever 1 + \ 28496928206SJ. Bruce Fields nfs4_fattr_maxsz) 2851da177e4SLinus Torvalds #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) 2861da177e4SLinus Torvalds #define encode_create_maxsz (op_encode_hdr_maxsz + \ 2879104a55dSTrond Myklebust 1 + 2 + nfs4_name_maxsz + \ 2889104a55dSTrond Myklebust encode_attrs_maxsz) 2892cebf828STrond Myklebust #define decode_create_maxsz (op_decode_hdr_maxsz + \ 2902cebf828STrond Myklebust decode_change_info_maxsz + \ 2912cebf828STrond Myklebust nfs4_fattr_bitmap_maxsz) 2929104a55dSTrond Myklebust #define encode_statfs_maxsz (encode_getattr_maxsz) 2939104a55dSTrond Myklebust #define decode_statfs_maxsz (decode_getattr_maxsz) 2941da177e4SLinus Torvalds #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) 2951da177e4SLinus Torvalds #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) 2969104a55dSTrond Myklebust #define encode_getacl_maxsz (encode_getattr_maxsz) 2979104a55dSTrond Myklebust #define decode_getacl_maxsz (op_decode_hdr_maxsz + \ 2989ed5af26STrond Myklebust nfs4_fattr_bitmap_maxsz + 1 + pagepad_maxsz) 2999104a55dSTrond Myklebust #define encode_setacl_maxsz (op_encode_hdr_maxsz + \ 3009104a55dSTrond Myklebust encode_stateid_maxsz + 3) 3019104a55dSTrond Myklebust #define decode_setacl_maxsz (decode_setattr_maxsz) 302e6889620STrond Myklebust #define encode_fs_locations_maxsz \ 303e6889620STrond Myklebust (encode_getattr_maxsz) 304e6889620STrond Myklebust #define decode_fs_locations_maxsz \ 3059ed5af26STrond Myklebust (pagepad_maxsz) 3065a5ea0d4SBryan Schumaker #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) 3071650add2SBryan Schumaker #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4)) 3089b7b9fccSAndy Adamson 3099b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 310fc931582SAndy Adamson #define NFS4_MAX_MACHINE_NAME_LEN (64) 311d751f748SJim Rees #define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \ 312d751f748SJim Rees sizeof(utsname()->version) + sizeof(utsname()->machine) + 8) 313fc931582SAndy Adamson 31499fe60d0SBenny Halevy #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ 31599fe60d0SBenny Halevy encode_verifier_maxsz + \ 31699fe60d0SBenny Halevy 1 /* co_ownerid.len */ + \ 317b8fb2f59SJeff Layton /* eia_clientowner */ \ 318b8fb2f59SJeff Layton 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 31999fe60d0SBenny Halevy 1 /* flags */ + \ 32099fe60d0SBenny Halevy 1 /* spa_how */ + \ 3212031cd1aSWeston Andros Adamson /* max is SP4_MACH_CRED (for now) */ + \ 3222031cd1aSWeston Andros Adamson 1 + NFS4_OP_MAP_NUM_WORDS + \ 3232031cd1aSWeston Andros Adamson 1 + NFS4_OP_MAP_NUM_WORDS + \ 324db8ac8baSWeston Andros Adamson 1 /* implementation id array of size 1 */ + \ 325db8ac8baSWeston Andros Adamson 1 /* nii_domain */ + \ 326db8ac8baSWeston Andros Adamson XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 327db8ac8baSWeston Andros Adamson 1 /* nii_name */ + \ 328d751f748SJim Rees XDR_QUADLEN(IMPL_NAME_LIMIT) + \ 329db8ac8baSWeston Andros Adamson 3 /* nii_date */) 33099fe60d0SBenny Halevy #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \ 33199fe60d0SBenny Halevy 2 /* eir_clientid */ + \ 33299fe60d0SBenny Halevy 1 /* eir_sequenceid */ + \ 33399fe60d0SBenny Halevy 1 /* eir_flags */ + \ 33499fe60d0SBenny Halevy 1 /* spr_how */ + \ 3352031cd1aSWeston Andros Adamson /* max is SP4_MACH_CRED (for now) */ + \ 3362031cd1aSWeston Andros Adamson 1 + NFS4_OP_MAP_NUM_WORDS + \ 3372031cd1aSWeston Andros Adamson 1 + NFS4_OP_MAP_NUM_WORDS + \ 33899fe60d0SBenny Halevy 2 /* eir_server_owner.so_minor_id */ + \ 33999fe60d0SBenny Halevy /* eir_server_owner.so_major_id<> */ \ 34099fe60d0SBenny Halevy XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ 34199fe60d0SBenny Halevy /* eir_server_scope<> */ \ 34299fe60d0SBenny Halevy XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ 34399fe60d0SBenny Halevy 1 /* eir_server_impl_id array length */ + \ 3447d2ed9acSWeston Andros Adamson 1 /* nii_domain */ + \ 3457d2ed9acSWeston Andros Adamson XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 3467d2ed9acSWeston Andros Adamson 1 /* nii_name */ + \ 3477d2ed9acSWeston Andros Adamson XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 3487d2ed9acSWeston Andros Adamson 3 /* nii_date */) 349fc931582SAndy Adamson #define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */) 350fc931582SAndy Adamson #define decode_channel_attrs_maxsz (6 + \ 351fc931582SAndy Adamson 1 /* ca_rdma_ird.len */ + \ 352fc931582SAndy Adamson 1 /* ca_rdma_ird */) 353fc931582SAndy Adamson #define encode_create_session_maxsz (op_encode_hdr_maxsz + \ 354fc931582SAndy Adamson 2 /* csa_clientid */ + \ 355fc931582SAndy Adamson 1 /* csa_sequence */ + \ 356fc931582SAndy Adamson 1 /* csa_flags */ + \ 357fc931582SAndy Adamson encode_channel_attrs_maxsz + \ 358fc931582SAndy Adamson encode_channel_attrs_maxsz + \ 359fc931582SAndy Adamson 1 /* csa_cb_program */ + \ 360fc931582SAndy Adamson 1 /* csa_sec_parms.len (1) */ + \ 361fc931582SAndy Adamson 1 /* cb_secflavor (AUTH_SYS) */ + \ 362fc931582SAndy Adamson 1 /* stamp */ + \ 363fc931582SAndy Adamson 1 /* machinename.len */ + \ 364fc931582SAndy Adamson XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \ 365fc931582SAndy Adamson 1 /* uid */ + \ 366fc931582SAndy Adamson 1 /* gid */ + \ 367fc931582SAndy Adamson 1 /* gids.len (0) */) 368fc931582SAndy Adamson #define decode_create_session_maxsz (op_decode_hdr_maxsz + \ 369fc931582SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ 370fc931582SAndy Adamson 1 /* csr_sequence */ + \ 371fc931582SAndy Adamson 1 /* csr_flags */ + \ 372fc931582SAndy Adamson decode_channel_attrs_maxsz + \ 373fc931582SAndy Adamson decode_channel_attrs_maxsz) 3747c44f1aeSWeston Andros Adamson #define encode_bind_conn_to_session_maxsz (op_encode_hdr_maxsz + \ 3757c44f1aeSWeston Andros Adamson /* bctsa_sessid */ \ 3767c44f1aeSWeston Andros Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ 3777c44f1aeSWeston Andros Adamson 1 /* bctsa_dir */ + \ 3787c44f1aeSWeston Andros Adamson 1 /* bctsa_use_conn_in_rdma_mode */) 3797c44f1aeSWeston Andros Adamson #define decode_bind_conn_to_session_maxsz (op_decode_hdr_maxsz + \ 3807c44f1aeSWeston Andros Adamson /* bctsr_sessid */ \ 3817c44f1aeSWeston Andros Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ 3827c44f1aeSWeston Andros Adamson 1 /* bctsr_dir */ + \ 3837c44f1aeSWeston Andros Adamson 1 /* bctsr_use_conn_in_rdma_mode */) 3840f3e66c6SAndy Adamson #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) 3850f3e66c6SAndy Adamson #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) 38666245539STrond Myklebust #define encode_destroy_clientid_maxsz (op_encode_hdr_maxsz + 2) 38766245539STrond Myklebust #define decode_destroy_clientid_maxsz (op_decode_hdr_maxsz) 388fc01cea9SAndy Adamson #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ 389fc01cea9SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) 390fc01cea9SAndy Adamson #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ 391fc01cea9SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) 39218019753SRicardo Labiaga #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) 39318019753SRicardo Labiaga #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) 39484c9dee3SChristoph Hellwig #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + \ 39584c9dee3SChristoph Hellwig XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \ 39684c9dee3SChristoph Hellwig 1 /* layout type */ + \ 39784c9dee3SChristoph Hellwig 1 /* maxcount */ + \ 39884c9dee3SChristoph Hellwig 1 /* bitmap size */ + \ 39984c9dee3SChristoph Hellwig 1 /* notification bitmap length */ + \ 40084c9dee3SChristoph Hellwig 1 /* notification bitmap, word 0 */) 401b1f69b75SAndy Adamson #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ 402b1f69b75SAndy Adamson 1 /* layout type */ + \ 403b1f69b75SAndy Adamson 1 /* opaque devaddr4 length */ + \ 404b1f69b75SAndy Adamson /* devaddr4 payload is read into page */ \ 405b1f69b75SAndy Adamson 1 /* notification bitmap length */ + \ 40602ef04e4SChuck Lever 1 /* notification bitmap, word 0 */ + \ 4079ed5af26STrond Myklebust pagepad_maxsz /* possible XDR padding */) 408b1f69b75SAndy Adamson #define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \ 409b1f69b75SAndy Adamson encode_stateid_maxsz) 410b1f69b75SAndy Adamson #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ 411b1f69b75SAndy Adamson decode_stateid_maxsz + \ 4129ed5af26STrond Myklebust XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE) + \ 4139ed5af26STrond Myklebust pagepad_maxsz) 414863a3c6cSAndy Adamson #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ 415863a3c6cSAndy Adamson 2 /* offset */ + \ 416863a3c6cSAndy Adamson 2 /* length */ + \ 417863a3c6cSAndy Adamson 1 /* reclaim */ + \ 418863a3c6cSAndy Adamson encode_stateid_maxsz + \ 419863a3c6cSAndy Adamson 1 /* new offset (true) */ + \ 420863a3c6cSAndy Adamson 2 /* last byte written */ + \ 421863a3c6cSAndy Adamson 1 /* nt_timechanged (false) */ + \ 422863a3c6cSAndy Adamson 1 /* layoutupdate4 layout type */ + \ 4235f919c9fSChristoph Hellwig 1 /* layoutupdate4 opaqueue len */) 4245f919c9fSChristoph Hellwig /* the actual content of layoutupdate4 should 4255f919c9fSChristoph Hellwig be allocated by drivers and spliced in 4265f919c9fSChristoph Hellwig using xdr_write_pages */ 427863a3c6cSAndy Adamson #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) 428cbe82603SBenny Halevy #define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \ 429cbe82603SBenny Halevy encode_stateid_maxsz + \ 4306669cb8bSTrond Myklebust 1 + \ 4316669cb8bSTrond Myklebust XDR_QUADLEN(NFS4_OPAQUE_LIMIT)) 432cbe82603SBenny Halevy #define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \ 433cbe82603SBenny Halevy 1 + decode_stateid_maxsz) 434fca78d6dSBryan Schumaker #define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1) 435fca78d6dSBryan Schumaker #define decode_secinfo_no_name_maxsz decode_secinfo_maxsz 4367d974794SBryan Schumaker #define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \ 4377d974794SBryan Schumaker XDR_QUADLEN(NFS4_STATEID_SIZE)) 4387d974794SBryan Schumaker #define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1) 4399aeda35fSBryan Schumaker #define encode_free_stateid_maxsz (op_encode_hdr_maxsz + 1 + \ 4409aeda35fSBryan Schumaker XDR_QUADLEN(NFS4_STATEID_SIZE)) 4419f79fb48SAndy Adamson #define decode_free_stateid_maxsz (op_decode_hdr_maxsz) 4429b7b9fccSAndy Adamson #else /* CONFIG_NFS_V4_1 */ 4439b7b9fccSAndy Adamson #define encode_sequence_maxsz 0 4449b7b9fccSAndy Adamson #define decode_sequence_maxsz 0 445cf805165STrond Myklebust #define encode_layoutreturn_maxsz 0 446cf805165STrond Myklebust #define decode_layoutreturn_maxsz 0 44756f487f8SFred Isaman #define encode_layoutget_maxsz 0 44856f487f8SFred Isaman #define decode_layoutget_maxsz 0 4499b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 4509b7b9fccSAndy Adamson 4511da177e4SLinus Torvalds #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ 4521da177e4SLinus Torvalds #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ 4531da177e4SLinus Torvalds #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ 4549b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4551da177e4SLinus Torvalds encode_putfh_maxsz + \ 4569104a55dSTrond Myklebust encode_read_maxsz) 4571da177e4SLinus Torvalds #define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \ 4589b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4591da177e4SLinus Torvalds decode_putfh_maxsz + \ 4609104a55dSTrond Myklebust decode_read_maxsz) 4611da177e4SLinus Torvalds #define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \ 4629b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4631da177e4SLinus Torvalds encode_putfh_maxsz + \ 4649104a55dSTrond Myklebust encode_readlink_maxsz) 4651da177e4SLinus Torvalds #define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \ 4669b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4671da177e4SLinus Torvalds decode_putfh_maxsz + \ 4689104a55dSTrond Myklebust decode_readlink_maxsz) 4691da177e4SLinus Torvalds #define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \ 4709b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4711da177e4SLinus Torvalds encode_putfh_maxsz + \ 4729104a55dSTrond Myklebust encode_readdir_maxsz) 4731da177e4SLinus Torvalds #define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \ 4749b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4751da177e4SLinus Torvalds decode_putfh_maxsz + \ 4769104a55dSTrond Myklebust decode_readdir_maxsz) 4771da177e4SLinus Torvalds #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ 4789b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4791da177e4SLinus Torvalds encode_putfh_maxsz + \ 4809104a55dSTrond Myklebust encode_write_maxsz + \ 4814f9838c7STrond Myklebust encode_getattr_maxsz) 4821da177e4SLinus Torvalds #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ 4839b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4841da177e4SLinus Torvalds decode_putfh_maxsz + \ 4859104a55dSTrond Myklebust decode_write_maxsz + \ 4864f9838c7STrond Myklebust decode_getattr_maxsz) 4871da177e4SLinus Torvalds #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ 4889b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4891da177e4SLinus Torvalds encode_putfh_maxsz + \ 4908582715eSTrond Myklebust encode_commit_maxsz) 4911da177e4SLinus Torvalds #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ 4929b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4931da177e4SLinus Torvalds decode_putfh_maxsz + \ 4948582715eSTrond Myklebust decode_commit_maxsz) 4951da177e4SLinus Torvalds #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ 4969b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4971da177e4SLinus Torvalds encode_putfh_maxsz + \ 4982cebf828STrond Myklebust encode_open_maxsz + \ 4996168f62cSWeston Andros Adamson encode_access_maxsz + \ 5002cebf828STrond Myklebust encode_getfh_maxsz + \ 50156f487f8SFred Isaman encode_getattr_maxsz + \ 50256f487f8SFred Isaman encode_layoutget_maxsz) 5031da177e4SLinus Torvalds #define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ 5049b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5051da177e4SLinus Torvalds decode_putfh_maxsz + \ 5062cebf828STrond Myklebust decode_open_maxsz + \ 5076168f62cSWeston Andros Adamson decode_access_maxsz + \ 5082cebf828STrond Myklebust decode_getfh_maxsz + \ 50956f487f8SFred Isaman decode_getattr_maxsz + \ 51056f487f8SFred Isaman decode_layoutget_maxsz) 5111da177e4SLinus Torvalds #define NFS4_enc_open_confirm_sz \ 5121da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 5131da177e4SLinus Torvalds encode_putfh_maxsz + \ 5149104a55dSTrond Myklebust encode_open_confirm_maxsz) 5159104a55dSTrond Myklebust #define NFS4_dec_open_confirm_sz \ 5169104a55dSTrond Myklebust (compound_decode_hdr_maxsz + \ 5171da177e4SLinus Torvalds decode_putfh_maxsz + \ 5189104a55dSTrond Myklebust decode_open_confirm_maxsz) 5191da177e4SLinus Torvalds #define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \ 5209b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5211da177e4SLinus Torvalds encode_putfh_maxsz + \ 5222cebf828STrond Myklebust encode_open_maxsz + \ 5236168f62cSWeston Andros Adamson encode_access_maxsz + \ 52456f487f8SFred Isaman encode_getattr_maxsz + \ 52556f487f8SFred Isaman encode_layoutget_maxsz) 5261da177e4SLinus Torvalds #define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \ 5279b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5281da177e4SLinus Torvalds decode_putfh_maxsz + \ 5292cebf828STrond Myklebust decode_open_maxsz + \ 5306168f62cSWeston Andros Adamson decode_access_maxsz + \ 53156f487f8SFred Isaman decode_getattr_maxsz + \ 53256f487f8SFred Isaman decode_layoutget_maxsz) 5331da177e4SLinus Torvalds #define NFS4_enc_open_downgrade_sz \ 5341da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 5359b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5361da177e4SLinus Torvalds encode_putfh_maxsz + \ 537b6808145STrond Myklebust encode_layoutreturn_maxsz + \ 5383947b74dSTrond Myklebust encode_open_downgrade_maxsz) 5391da177e4SLinus Torvalds #define NFS4_dec_open_downgrade_sz \ 5401da177e4SLinus Torvalds (compound_decode_hdr_maxsz + \ 5419b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5421da177e4SLinus Torvalds decode_putfh_maxsz + \ 543b6808145STrond Myklebust decode_layoutreturn_maxsz + \ 5443947b74dSTrond Myklebust decode_open_downgrade_maxsz) 5451da177e4SLinus Torvalds #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ 5469b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5471da177e4SLinus Torvalds encode_putfh_maxsz + \ 548cf805165STrond Myklebust encode_layoutreturn_maxsz + \ 5499104a55dSTrond Myklebust encode_close_maxsz + \ 550516a6af6STrond Myklebust encode_getattr_maxsz) 5511da177e4SLinus Torvalds #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ 5529b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5531da177e4SLinus Torvalds decode_putfh_maxsz + \ 554cf805165STrond Myklebust decode_layoutreturn_maxsz + \ 5559104a55dSTrond Myklebust decode_close_maxsz + \ 556516a6af6STrond Myklebust decode_getattr_maxsz) 5571da177e4SLinus Torvalds #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ 5589b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5591da177e4SLinus Torvalds encode_putfh_maxsz + \ 5609104a55dSTrond Myklebust encode_setattr_maxsz + \ 5611da177e4SLinus Torvalds encode_getattr_maxsz) 5621da177e4SLinus Torvalds #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ 5639b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5641da177e4SLinus Torvalds decode_putfh_maxsz + \ 5659104a55dSTrond Myklebust decode_setattr_maxsz + \ 5669104a55dSTrond Myklebust decode_getattr_maxsz) 5671da177e4SLinus Torvalds #define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \ 5689b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5691da177e4SLinus Torvalds encode_putfh_maxsz + \ 5701da177e4SLinus Torvalds encode_fsinfo_maxsz) 5711da177e4SLinus Torvalds #define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \ 5729b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5731da177e4SLinus Torvalds decode_putfh_maxsz + \ 5741da177e4SLinus Torvalds decode_fsinfo_maxsz) 5751da177e4SLinus Torvalds #define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \ 5761da177e4SLinus Torvalds encode_renew_maxsz) 5771da177e4SLinus Torvalds #define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \ 5781da177e4SLinus Torvalds decode_renew_maxsz) 5791da177e4SLinus Torvalds #define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \ 5801da177e4SLinus Torvalds encode_setclientid_maxsz) 5811da177e4SLinus Torvalds #define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \ 5821da177e4SLinus Torvalds decode_setclientid_maxsz) 5831da177e4SLinus Torvalds #define NFS4_enc_setclientid_confirm_sz \ 5841da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 58583ca7f5aSChuck Lever encode_setclientid_confirm_maxsz) 5861da177e4SLinus Torvalds #define NFS4_dec_setclientid_confirm_sz \ 5871da177e4SLinus Torvalds (compound_decode_hdr_maxsz + \ 58883ca7f5aSChuck Lever decode_setclientid_confirm_maxsz) 5891da177e4SLinus Torvalds #define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \ 5909b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5911da177e4SLinus Torvalds encode_putfh_maxsz + \ 5929104a55dSTrond Myklebust encode_lock_maxsz) 5931da177e4SLinus Torvalds #define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \ 5949b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5951da177e4SLinus Torvalds decode_putfh_maxsz + \ 5969104a55dSTrond Myklebust decode_lock_maxsz) 5971da177e4SLinus Torvalds #define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \ 5989b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5991da177e4SLinus Torvalds encode_putfh_maxsz + \ 6009104a55dSTrond Myklebust encode_lockt_maxsz) 6019104a55dSTrond Myklebust #define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \ 6029b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6039104a55dSTrond Myklebust decode_putfh_maxsz + \ 6049104a55dSTrond Myklebust decode_lockt_maxsz) 6051da177e4SLinus Torvalds #define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \ 6069b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6071da177e4SLinus Torvalds encode_putfh_maxsz + \ 6089104a55dSTrond Myklebust encode_locku_maxsz) 6091da177e4SLinus Torvalds #define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \ 6109b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6111da177e4SLinus Torvalds decode_putfh_maxsz + \ 6129104a55dSTrond Myklebust decode_locku_maxsz) 613d3c7b7ccSTrond Myklebust #define NFS4_enc_release_lockowner_sz \ 614d3c7b7ccSTrond Myklebust (compound_encode_hdr_maxsz + \ 615d3c7b7ccSTrond Myklebust encode_lockowner_maxsz) 616d3c7b7ccSTrond Myklebust #define NFS4_dec_release_lockowner_sz \ 617d3c7b7ccSTrond Myklebust (compound_decode_hdr_maxsz + \ 618d3c7b7ccSTrond Myklebust decode_lockowner_maxsz) 6191da177e4SLinus Torvalds #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ 6209b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6211da177e4SLinus Torvalds encode_putfh_maxsz + \ 62276b32999STrond Myklebust encode_access_maxsz + \ 62376b32999STrond Myklebust encode_getattr_maxsz) 6241da177e4SLinus Torvalds #define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ 6259b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6261da177e4SLinus Torvalds decode_putfh_maxsz + \ 62776b32999STrond Myklebust decode_access_maxsz + \ 62876b32999STrond Myklebust decode_getattr_maxsz) 6291da177e4SLinus Torvalds #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ 6309b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6311da177e4SLinus Torvalds encode_putfh_maxsz + \ 63244c99933SChuck Lever encode_getattr_maxsz + \ 63344c99933SChuck Lever encode_renew_maxsz) 6341da177e4SLinus Torvalds #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ 6359b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6361da177e4SLinus Torvalds decode_putfh_maxsz + \ 63744c99933SChuck Lever decode_getattr_maxsz + \ 63844c99933SChuck Lever decode_renew_maxsz) 6391da177e4SLinus Torvalds #define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ 6409b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6411da177e4SLinus Torvalds encode_putfh_maxsz + \ 6421da177e4SLinus Torvalds encode_lookup_maxsz + \ 6431da177e4SLinus Torvalds encode_getattr_maxsz + \ 6441da177e4SLinus Torvalds encode_getfh_maxsz) 6451da177e4SLinus Torvalds #define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \ 6469b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6471da177e4SLinus Torvalds decode_putfh_maxsz + \ 648e6889620STrond Myklebust decode_lookup_maxsz + \ 6491da177e4SLinus Torvalds decode_getattr_maxsz + \ 6501da177e4SLinus Torvalds decode_getfh_maxsz) 6515b5faaf6SJeff Layton #define NFS4_enc_lookupp_sz (compound_encode_hdr_maxsz + \ 6525b5faaf6SJeff Layton encode_sequence_maxsz + \ 6535b5faaf6SJeff Layton encode_putfh_maxsz + \ 6545b5faaf6SJeff Layton encode_lookupp_maxsz + \ 6555b5faaf6SJeff Layton encode_getattr_maxsz + \ 6565b5faaf6SJeff Layton encode_getfh_maxsz) 6575b5faaf6SJeff Layton #define NFS4_dec_lookupp_sz (compound_decode_hdr_maxsz + \ 6585b5faaf6SJeff Layton decode_sequence_maxsz + \ 6595b5faaf6SJeff Layton decode_putfh_maxsz + \ 6605b5faaf6SJeff Layton decode_lookupp_maxsz + \ 6615b5faaf6SJeff Layton decode_getattr_maxsz + \ 6625b5faaf6SJeff Layton decode_getfh_maxsz) 6631da177e4SLinus Torvalds #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ 6649b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6651da177e4SLinus Torvalds encode_putrootfh_maxsz + \ 6661da177e4SLinus Torvalds encode_getattr_maxsz + \ 6671da177e4SLinus Torvalds encode_getfh_maxsz) 6681da177e4SLinus Torvalds #define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \ 6699b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6701da177e4SLinus Torvalds decode_putrootfh_maxsz + \ 6711da177e4SLinus Torvalds decode_getattr_maxsz + \ 6721da177e4SLinus Torvalds decode_getfh_maxsz) 6731da177e4SLinus Torvalds #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ 6749b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6751da177e4SLinus Torvalds encode_putfh_maxsz + \ 676778d2817STrond Myklebust encode_remove_maxsz) 6771da177e4SLinus Torvalds #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ 6789b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6791da177e4SLinus Torvalds decode_putfh_maxsz + \ 680778d2817STrond Myklebust decode_remove_maxsz) 6811da177e4SLinus Torvalds #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ 6829b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6831da177e4SLinus Torvalds encode_putfh_maxsz + \ 6841da177e4SLinus Torvalds encode_savefh_maxsz + \ 6851da177e4SLinus Torvalds encode_putfh_maxsz + \ 686778d2817STrond Myklebust encode_rename_maxsz) 6871da177e4SLinus Torvalds #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ 6889b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6891da177e4SLinus Torvalds decode_putfh_maxsz + \ 6901da177e4SLinus Torvalds decode_savefh_maxsz + \ 6911da177e4SLinus Torvalds decode_putfh_maxsz + \ 692778d2817STrond Myklebust decode_rename_maxsz) 6931da177e4SLinus Torvalds #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ 6949b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6951da177e4SLinus Torvalds encode_putfh_maxsz + \ 6961da177e4SLinus Torvalds encode_savefh_maxsz + \ 6971da177e4SLinus Torvalds encode_putfh_maxsz + \ 69891ba2eeeSTrond Myklebust encode_link_maxsz + \ 69991ba2eeeSTrond Myklebust encode_restorefh_maxsz + \ 700a9f6991bSTrond Myklebust encode_getattr_maxsz) 7011da177e4SLinus Torvalds #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ 7029b7b9fccSAndy Adamson decode_sequence_maxsz + \ 7031da177e4SLinus Torvalds decode_putfh_maxsz + \ 7041da177e4SLinus Torvalds decode_savefh_maxsz + \ 7051da177e4SLinus Torvalds decode_putfh_maxsz + \ 70691ba2eeeSTrond Myklebust decode_link_maxsz + \ 70791ba2eeeSTrond Myklebust decode_restorefh_maxsz + \ 70891ba2eeeSTrond Myklebust decode_getattr_maxsz) 7091da177e4SLinus Torvalds #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ 7109b7b9fccSAndy Adamson encode_sequence_maxsz + \ 7111da177e4SLinus Torvalds encode_putfh_maxsz + \ 7121da177e4SLinus Torvalds encode_symlink_maxsz + \ 7131da177e4SLinus Torvalds encode_getattr_maxsz + \ 7141da177e4SLinus Torvalds encode_getfh_maxsz) 7151da177e4SLinus Torvalds #define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \ 7169b7b9fccSAndy Adamson decode_sequence_maxsz + \ 7171da177e4SLinus Torvalds decode_putfh_maxsz + \ 7181da177e4SLinus Torvalds decode_symlink_maxsz + \ 7191da177e4SLinus Torvalds decode_getattr_maxsz + \ 7201da177e4SLinus Torvalds decode_getfh_maxsz) 7211da177e4SLinus Torvalds #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ 7229b7b9fccSAndy Adamson encode_sequence_maxsz + \ 7231da177e4SLinus Torvalds encode_putfh_maxsz + \ 7241da177e4SLinus Torvalds encode_create_maxsz + \ 72556ae19f3STrond Myklebust encode_getfh_maxsz + \ 72656ae19f3STrond Myklebust encode_getattr_maxsz) 7271da177e4SLinus Torvalds #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ 7289b7b9fccSAndy Adamson decode_sequence_maxsz + \ 7291da177e4SLinus Torvalds decode_putfh_maxsz + \ 7301da177e4SLinus Torvalds decode_create_maxsz + \ 73156ae19f3STrond Myklebust decode_getfh_maxsz + \ 73256ae19f3STrond Myklebust decode_getattr_maxsz) 7331da177e4SLinus Torvalds #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ 7349b7b9fccSAndy Adamson encode_sequence_maxsz + \ 7351da177e4SLinus Torvalds encode_putfh_maxsz + \ 7361da177e4SLinus Torvalds encode_getattr_maxsz) 7371da177e4SLinus Torvalds #define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \ 7389b7b9fccSAndy Adamson decode_sequence_maxsz + \ 7391da177e4SLinus Torvalds decode_putfh_maxsz + \ 7401da177e4SLinus Torvalds decode_getattr_maxsz) 7411da177e4SLinus Torvalds #define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \ 7429b7b9fccSAndy Adamson encode_sequence_maxsz + \ 7431da177e4SLinus Torvalds encode_putfh_maxsz + \ 7449104a55dSTrond Myklebust encode_statfs_maxsz) 7451da177e4SLinus Torvalds #define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \ 7469b7b9fccSAndy Adamson decode_sequence_maxsz + \ 7471da177e4SLinus Torvalds decode_putfh_maxsz + \ 7489104a55dSTrond Myklebust decode_statfs_maxsz) 7491da177e4SLinus Torvalds #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ 7509b7b9fccSAndy Adamson encode_sequence_maxsz + \ 751ab91f264STrond Myklebust encode_putfh_maxsz + \ 7521da177e4SLinus Torvalds encode_getattr_maxsz) 7531da177e4SLinus Torvalds #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ 7549b7b9fccSAndy Adamson decode_sequence_maxsz + \ 755ab91f264STrond Myklebust decode_putfh_maxsz + \ 7561da177e4SLinus Torvalds decode_getattr_maxsz) 7571da177e4SLinus Torvalds #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ 7589b7b9fccSAndy Adamson encode_sequence_maxsz + \ 7591da177e4SLinus Torvalds encode_putfh_maxsz + \ 760586f1c39STrond Myklebust encode_layoutreturn_maxsz + \ 761fa178f29STrond Myklebust encode_delegreturn_maxsz + \ 762fa178f29STrond Myklebust encode_getattr_maxsz) 7631da177e4SLinus Torvalds #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ 7649b7b9fccSAndy Adamson decode_sequence_maxsz + \ 765d8434d4cSTrond Myklebust decode_putfh_maxsz + \ 766586f1c39STrond Myklebust decode_layoutreturn_maxsz + \ 767fa178f29STrond Myklebust decode_delegreturn_maxsz + \ 768fa178f29STrond Myklebust decode_getattr_maxsz) 769029d105eSJ. Bruce Fields #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ 7709b7b9fccSAndy Adamson encode_sequence_maxsz + \ 771029d105eSJ. Bruce Fields encode_putfh_maxsz + \ 7729104a55dSTrond Myklebust encode_getacl_maxsz) 773029d105eSJ. Bruce Fields #define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ 7749b7b9fccSAndy Adamson decode_sequence_maxsz + \ 775029d105eSJ. Bruce Fields decode_putfh_maxsz + \ 7769104a55dSTrond Myklebust decode_getacl_maxsz) 77723ec6965SJ. Bruce Fields #define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ 7789b7b9fccSAndy Adamson encode_sequence_maxsz + \ 77923ec6965SJ. Bruce Fields encode_putfh_maxsz + \ 7809104a55dSTrond Myklebust encode_setacl_maxsz) 78123ec6965SJ. Bruce Fields #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ 7829b7b9fccSAndy Adamson decode_sequence_maxsz + \ 78323ec6965SJ. Bruce Fields decode_putfh_maxsz + \ 7849104a55dSTrond Myklebust decode_setacl_maxsz) 785683b57b4STrond Myklebust #define NFS4_enc_fs_locations_sz \ 786683b57b4STrond Myklebust (compound_encode_hdr_maxsz + \ 7879b7b9fccSAndy Adamson encode_sequence_maxsz + \ 788683b57b4STrond Myklebust encode_putfh_maxsz + \ 789e6889620STrond Myklebust encode_lookup_maxsz + \ 790b03d735bSChuck Lever encode_fs_locations_maxsz + \ 791b03d735bSChuck Lever encode_renew_maxsz) 792683b57b4STrond Myklebust #define NFS4_dec_fs_locations_sz \ 793683b57b4STrond Myklebust (compound_decode_hdr_maxsz + \ 7949b7b9fccSAndy Adamson decode_sequence_maxsz + \ 795683b57b4STrond Myklebust decode_putfh_maxsz + \ 796e6889620STrond Myklebust decode_lookup_maxsz + \ 797b03d735bSChuck Lever decode_fs_locations_maxsz + \ 798b03d735bSChuck Lever decode_renew_maxsz) 7995a5ea0d4SBryan Schumaker #define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \ 8005a5ea0d4SBryan Schumaker encode_sequence_maxsz + \ 8015a5ea0d4SBryan Schumaker encode_putfh_maxsz + \ 8025a5ea0d4SBryan Schumaker encode_secinfo_maxsz) 8035a5ea0d4SBryan Schumaker #define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \ 8045a5ea0d4SBryan Schumaker decode_sequence_maxsz + \ 8055a5ea0d4SBryan Schumaker decode_putfh_maxsz + \ 8065a5ea0d4SBryan Schumaker decode_secinfo_maxsz) 80744c99933SChuck Lever #define NFS4_enc_fsid_present_sz \ 80844c99933SChuck Lever (compound_encode_hdr_maxsz + \ 80944c99933SChuck Lever encode_sequence_maxsz + \ 81044c99933SChuck Lever encode_putfh_maxsz + \ 81144c99933SChuck Lever encode_getfh_maxsz + \ 81244c99933SChuck Lever encode_renew_maxsz) 81344c99933SChuck Lever #define NFS4_dec_fsid_present_sz \ 81444c99933SChuck Lever (compound_decode_hdr_maxsz + \ 81544c99933SChuck Lever decode_sequence_maxsz + \ 81644c99933SChuck Lever decode_putfh_maxsz + \ 81744c99933SChuck Lever decode_getfh_maxsz + \ 81844c99933SChuck Lever decode_renew_maxsz) 81999fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 8207c44f1aeSWeston Andros Adamson #define NFS4_enc_bind_conn_to_session_sz \ 8217c44f1aeSWeston Andros Adamson (compound_encode_hdr_maxsz + \ 8227c44f1aeSWeston Andros Adamson encode_bind_conn_to_session_maxsz) 8237c44f1aeSWeston Andros Adamson #define NFS4_dec_bind_conn_to_session_sz \ 8247c44f1aeSWeston Andros Adamson (compound_decode_hdr_maxsz + \ 8257c44f1aeSWeston Andros Adamson decode_bind_conn_to_session_maxsz) 82699fe60d0SBenny Halevy #define NFS4_enc_exchange_id_sz \ 82799fe60d0SBenny Halevy (compound_encode_hdr_maxsz + \ 82899fe60d0SBenny Halevy encode_exchange_id_maxsz) 82999fe60d0SBenny Halevy #define NFS4_dec_exchange_id_sz \ 83099fe60d0SBenny Halevy (compound_decode_hdr_maxsz + \ 83199fe60d0SBenny Halevy decode_exchange_id_maxsz) 832fc931582SAndy Adamson #define NFS4_enc_create_session_sz \ 833fc931582SAndy Adamson (compound_encode_hdr_maxsz + \ 834fc931582SAndy Adamson encode_create_session_maxsz) 835fc931582SAndy Adamson #define NFS4_dec_create_session_sz \ 836fc931582SAndy Adamson (compound_decode_hdr_maxsz + \ 837fc931582SAndy Adamson decode_create_session_maxsz) 8380f3e66c6SAndy Adamson #define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \ 8390f3e66c6SAndy Adamson encode_destroy_session_maxsz) 8400f3e66c6SAndy Adamson #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ 8410f3e66c6SAndy Adamson decode_destroy_session_maxsz) 84266245539STrond Myklebust #define NFS4_enc_destroy_clientid_sz (compound_encode_hdr_maxsz + \ 84366245539STrond Myklebust encode_destroy_clientid_maxsz) 84466245539STrond Myklebust #define NFS4_dec_destroy_clientid_sz (compound_decode_hdr_maxsz + \ 84566245539STrond Myklebust decode_destroy_clientid_maxsz) 846fc01cea9SAndy Adamson #define NFS4_enc_sequence_sz \ 847fc01cea9SAndy Adamson (compound_decode_hdr_maxsz + \ 848fc01cea9SAndy Adamson encode_sequence_maxsz) 849fc01cea9SAndy Adamson #define NFS4_dec_sequence_sz \ 850fc01cea9SAndy Adamson (compound_decode_hdr_maxsz + \ 851fc01cea9SAndy Adamson decode_sequence_maxsz) 8520efb01b2SDonald Buczek #endif 8532050f0ccSAndy Adamson #define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \ 8542050f0ccSAndy Adamson encode_sequence_maxsz + \ 8552050f0ccSAndy Adamson encode_putrootfh_maxsz + \ 8562050f0ccSAndy Adamson encode_fsinfo_maxsz) 8572050f0ccSAndy Adamson #define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \ 8582050f0ccSAndy Adamson decode_sequence_maxsz + \ 8592050f0ccSAndy Adamson decode_putrootfh_maxsz + \ 8602050f0ccSAndy Adamson decode_fsinfo_maxsz) 8610efb01b2SDonald Buczek #if defined(CONFIG_NFS_V4_1) 86218019753SRicardo Labiaga #define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \ 86318019753SRicardo Labiaga encode_sequence_maxsz + \ 86418019753SRicardo Labiaga encode_reclaim_complete_maxsz) 86518019753SRicardo Labiaga #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ 86618019753SRicardo Labiaga decode_sequence_maxsz + \ 86718019753SRicardo Labiaga decode_reclaim_complete_maxsz) 868b1f69b75SAndy Adamson #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ 869b1f69b75SAndy Adamson encode_sequence_maxsz +\ 870b1f69b75SAndy Adamson encode_getdeviceinfo_maxsz) 871b1f69b75SAndy Adamson #define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \ 872b1f69b75SAndy Adamson decode_sequence_maxsz + \ 873b1f69b75SAndy Adamson decode_getdeviceinfo_maxsz) 874b1f69b75SAndy Adamson #define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \ 875b1f69b75SAndy Adamson encode_sequence_maxsz + \ 876b1f69b75SAndy Adamson encode_putfh_maxsz + \ 877b1f69b75SAndy Adamson encode_layoutget_maxsz) 878b1f69b75SAndy Adamson #define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \ 879b1f69b75SAndy Adamson decode_sequence_maxsz + \ 880b1f69b75SAndy Adamson decode_putfh_maxsz + \ 881b1f69b75SAndy Adamson decode_layoutget_maxsz) 882863a3c6cSAndy Adamson #define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ 883863a3c6cSAndy Adamson encode_sequence_maxsz +\ 884863a3c6cSAndy Adamson encode_putfh_maxsz + \ 885863a3c6cSAndy Adamson encode_layoutcommit_maxsz + \ 886863a3c6cSAndy Adamson encode_getattr_maxsz) 887863a3c6cSAndy Adamson #define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ 888863a3c6cSAndy Adamson decode_sequence_maxsz + \ 889863a3c6cSAndy Adamson decode_putfh_maxsz + \ 890863a3c6cSAndy Adamson decode_layoutcommit_maxsz + \ 891863a3c6cSAndy Adamson decode_getattr_maxsz) 892cbe82603SBenny Halevy #define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \ 893cbe82603SBenny Halevy encode_sequence_maxsz + \ 894cbe82603SBenny Halevy encode_putfh_maxsz + \ 895cbe82603SBenny Halevy encode_layoutreturn_maxsz) 896cbe82603SBenny Halevy #define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \ 897cbe82603SBenny Halevy decode_sequence_maxsz + \ 898cbe82603SBenny Halevy decode_putfh_maxsz + \ 899cbe82603SBenny Halevy decode_layoutreturn_maxsz) 900fca78d6dSBryan Schumaker #define NFS4_enc_secinfo_no_name_sz (compound_encode_hdr_maxsz + \ 901fca78d6dSBryan Schumaker encode_sequence_maxsz + \ 902fca78d6dSBryan Schumaker encode_putrootfh_maxsz +\ 903fca78d6dSBryan Schumaker encode_secinfo_no_name_maxsz) 904fca78d6dSBryan Schumaker #define NFS4_dec_secinfo_no_name_sz (compound_decode_hdr_maxsz + \ 905fca78d6dSBryan Schumaker decode_sequence_maxsz + \ 906fca78d6dSBryan Schumaker decode_putrootfh_maxsz + \ 907fca78d6dSBryan Schumaker decode_secinfo_no_name_maxsz) 9087d974794SBryan Schumaker #define NFS4_enc_test_stateid_sz (compound_encode_hdr_maxsz + \ 9097d974794SBryan Schumaker encode_sequence_maxsz + \ 9107d974794SBryan Schumaker encode_test_stateid_maxsz) 9117d974794SBryan Schumaker #define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \ 9127d974794SBryan Schumaker decode_sequence_maxsz + \ 9137d974794SBryan Schumaker decode_test_stateid_maxsz) 9149aeda35fSBryan Schumaker #define NFS4_enc_free_stateid_sz (compound_encode_hdr_maxsz + \ 9159aeda35fSBryan Schumaker encode_sequence_maxsz + \ 9169aeda35fSBryan Schumaker encode_free_stateid_maxsz) 9179aeda35fSBryan Schumaker #define NFS4_dec_free_stateid_sz (compound_decode_hdr_maxsz + \ 9189aeda35fSBryan Schumaker decode_sequence_maxsz + \ 9199aeda35fSBryan Schumaker decode_free_stateid_maxsz) 9202449ea2eSAlexandros Batsakis 9212449ea2eSAlexandros Batsakis const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 9222449ea2eSAlexandros Batsakis compound_encode_hdr_maxsz + 9232449ea2eSAlexandros Batsakis encode_sequence_maxsz + 9242449ea2eSAlexandros Batsakis encode_putfh_maxsz + 9252449ea2eSAlexandros Batsakis encode_getattr_maxsz) * 9262449ea2eSAlexandros Batsakis XDR_UNIT); 9272449ea2eSAlexandros Batsakis 9282449ea2eSAlexandros Batsakis const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 9292449ea2eSAlexandros Batsakis compound_decode_hdr_maxsz + 9302449ea2eSAlexandros Batsakis decode_sequence_maxsz + 9312449ea2eSAlexandros Batsakis decode_putfh_maxsz) * 9322449ea2eSAlexandros Batsakis XDR_UNIT); 933f1c097beSAndy Adamson 934f1c097beSAndy Adamson const u32 nfs41_maxgetdevinfo_overhead = ((RPC_MAX_REPHEADER_WITH_AUTH + 935f1c097beSAndy Adamson compound_decode_hdr_maxsz + 936f1c097beSAndy Adamson decode_sequence_maxsz) * 937f1c097beSAndy Adamson XDR_UNIT); 938f1c097beSAndy Adamson EXPORT_SYMBOL_GPL(nfs41_maxgetdevinfo_overhead); 93999fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 9401da177e4SLinus Torvalds 941bca79478STrond Myklebust static const umode_t nfs_type2fmt[] = { 942bca79478STrond Myklebust [NF4BAD] = 0, 943bca79478STrond Myklebust [NF4REG] = S_IFREG, 944bca79478STrond Myklebust [NF4DIR] = S_IFDIR, 945bca79478STrond Myklebust [NF4BLK] = S_IFBLK, 946bca79478STrond Myklebust [NF4CHR] = S_IFCHR, 947bca79478STrond Myklebust [NF4LNK] = S_IFLNK, 948bca79478STrond Myklebust [NF4SOCK] = S_IFSOCK, 949bca79478STrond Myklebust [NF4FIFO] = S_IFIFO, 950bca79478STrond Myklebust [NF4ATTRDIR] = 0, 951bca79478STrond Myklebust [NF4NAMEDATTR] = 0, 9521da177e4SLinus Torvalds }; 9531da177e4SLinus Torvalds 9541da177e4SLinus Torvalds struct compound_hdr { 9551da177e4SLinus Torvalds int32_t status; 9561da177e4SLinus Torvalds uint32_t nops; 957d017931cSAndy Adamson __be32 * nops_p; 9581da177e4SLinus Torvalds uint32_t taglen; 9591da177e4SLinus Torvalds char * tag; 9600c4e8c18SBenny Halevy uint32_t replen; /* expected reply words */ 96166cc0429SBenny Halevy u32 minorversion; 9621da177e4SLinus Torvalds }; 9631da177e4SLinus Torvalds 96413c65ce9SBenny Halevy static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes) 96513c65ce9SBenny Halevy { 96613c65ce9SBenny Halevy __be32 *p = xdr_reserve_space(xdr, nbytes); 96713c65ce9SBenny Halevy BUG_ON(!p); 96813c65ce9SBenny Halevy return p; 96913c65ce9SBenny Halevy } 9701da177e4SLinus Torvalds 971cb17e556STrond Myklebust static void encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len) 972cb17e556STrond Myklebust { 973ab6e9aafSTrond Myklebust WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, buf, len) < 0); 974cb17e556STrond Myklebust } 975cb17e556STrond Myklebust 9761da177e4SLinus Torvalds static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) 9771da177e4SLinus Torvalds { 978ab6e9aafSTrond Myklebust WARN_ON_ONCE(xdr_stream_encode_opaque(xdr, str, len) < 0); 9791da177e4SLinus Torvalds } 9801da177e4SLinus Torvalds 9814ade9821STrond Myklebust static void encode_uint32(struct xdr_stream *xdr, u32 n) 9824ade9821STrond Myklebust { 983ab6e9aafSTrond Myklebust WARN_ON_ONCE(xdr_stream_encode_u32(xdr, n) < 0); 9844ade9821STrond Myklebust } 9854ade9821STrond Myklebust 986ff2eb681STrond Myklebust static void encode_uint64(struct xdr_stream *xdr, u64 n) 987ff2eb681STrond Myklebust { 988ab6e9aafSTrond Myklebust WARN_ON_ONCE(xdr_stream_encode_u64(xdr, n) < 0); 989ff2eb681STrond Myklebust } 990ff2eb681STrond Myklebust 99137c88763STrond Myklebust static ssize_t xdr_encode_bitmap4(struct xdr_stream *xdr, 99237c88763STrond Myklebust const __u32 *bitmap, size_t len) 99337c88763STrond Myklebust { 99437c88763STrond Myklebust ssize_t ret; 99537c88763STrond Myklebust 99637c88763STrond Myklebust /* Trim empty words */ 99737c88763STrond Myklebust while (len > 0 && bitmap[len-1] == 0) 99837c88763STrond Myklebust len--; 99937c88763STrond Myklebust ret = xdr_stream_encode_uint32_array(xdr, bitmap, len); 100037c88763STrond Myklebust if (WARN_ON_ONCE(ret < 0)) 100137c88763STrond Myklebust return ret; 100237c88763STrond Myklebust return len; 100337c88763STrond Myklebust } 100437c88763STrond Myklebust 100537c88763STrond Myklebust static size_t mask_bitmap4(const __u32 *bitmap, const __u32 *mask, 100637c88763STrond Myklebust __u32 *res, size_t len) 100737c88763STrond Myklebust { 100837c88763STrond Myklebust size_t i; 100937c88763STrond Myklebust __u32 tmp; 101037c88763STrond Myklebust 101137c88763STrond Myklebust while (len > 0 && (bitmap[len-1] == 0 || mask[len-1] == 0)) 101237c88763STrond Myklebust len--; 101337c88763STrond Myklebust for (i = len; i-- > 0;) { 101437c88763STrond Myklebust tmp = bitmap[i] & mask[i]; 101537c88763STrond Myklebust res[i] = tmp; 101637c88763STrond Myklebust } 101737c88763STrond Myklebust return len; 101837c88763STrond Myklebust } 101937c88763STrond Myklebust 10204ade9821STrond Myklebust static void encode_nfs4_seqid(struct xdr_stream *xdr, 10214ade9821STrond Myklebust const struct nfs_seqid *seqid) 10224ade9821STrond Myklebust { 1023a6796419STrond Myklebust if (seqid != NULL) 10244ade9821STrond Myklebust encode_uint32(xdr, seqid->sequence->counter); 1025a6796419STrond Myklebust else 1026a6796419STrond Myklebust encode_uint32(xdr, 0); 10274ade9821STrond Myklebust } 10284ade9821STrond Myklebust 10290c4e8c18SBenny Halevy static void encode_compound_hdr(struct xdr_stream *xdr, 10300c4e8c18SBenny Halevy struct rpc_rqst *req, 10310c4e8c18SBenny Halevy struct compound_hdr *hdr) 10321da177e4SLinus Torvalds { 10338687b63aSAl Viro __be32 *p; 10340c4e8c18SBenny Halevy 10350c4e8c18SBenny Halevy /* initialize running count of expected bytes in reply. 10360c4e8c18SBenny Halevy * NOTE: the replied tag SHOULD be the same is the one sent, 10370c4e8c18SBenny Halevy * but this is not required as a MUST for the server to do so. */ 1038cf500bacSChuck Lever hdr->replen = 3 + hdr->taglen; 10391da177e4SLinus Torvalds 10407fc38846STrond Myklebust WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN); 10416fdfb0bcSTrond Myklebust encode_string(xdr, hdr->taglen, hdr->tag); 10426fdfb0bcSTrond Myklebust p = reserve_space(xdr, 8); 1043e75bc1c8SBenny Halevy *p++ = cpu_to_be32(hdr->minorversion); 1044d017931cSAndy Adamson hdr->nops_p = p; 104534558513SBenny Halevy *p = cpu_to_be32(hdr->nops); 1046d017931cSAndy Adamson } 1047d017931cSAndy Adamson 1048ab19b481STrond Myklebust static void encode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 op, 1049ab19b481STrond Myklebust uint32_t replen, 1050ab19b481STrond Myklebust struct compound_hdr *hdr) 1051ab19b481STrond Myklebust { 1052ab19b481STrond Myklebust encode_uint32(xdr, op); 1053ab19b481STrond Myklebust hdr->nops++; 1054ab19b481STrond Myklebust hdr->replen += replen; 1055ab19b481STrond Myklebust } 1056ab19b481STrond Myklebust 1057d017931cSAndy Adamson static void encode_nops(struct compound_hdr *hdr) 1058d017931cSAndy Adamson { 10597fc38846STrond Myklebust WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS); 1060d017931cSAndy Adamson *hdr->nops_p = htonl(hdr->nops); 10611da177e4SLinus Torvalds } 10621da177e4SLinus Torvalds 1063ea9d23f5STrond Myklebust static void encode_nfs4_stateid(struct xdr_stream *xdr, const nfs4_stateid *stateid) 1064ea9d23f5STrond Myklebust { 10652d2f24adSTrond Myklebust encode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE); 1066ea9d23f5STrond Myklebust } 1067ea9d23f5STrond Myklebust 10681da177e4SLinus Torvalds static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf) 10691da177e4SLinus Torvalds { 1070cb17e556STrond Myklebust encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); 10711da177e4SLinus Torvalds } 10721da177e4SLinus Torvalds 107336b3743fSTrond Myklebust static __be32 * 1074e7d4b05cSTrond Myklebust xdr_encode_nfstime4(__be32 *p, const struct timespec64 *t) 107536b3743fSTrond Myklebust { 1076a3167dacSArnd Bergmann p = xdr_encode_hyper(p, t->tv_sec); 107736b3743fSTrond Myklebust *p++ = cpu_to_be32(t->tv_nsec); 107836b3743fSTrond Myklebust return p; 107936b3743fSTrond Myklebust } 108036b3743fSTrond Myklebust 1081aa9c2669SDavid Quigley static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, 1082aa9c2669SDavid Quigley const struct nfs4_label *label, 108328cf22d0STrond Myklebust const umode_t *umask, 10845334c5bdSKinglong Mee const struct nfs_server *server, 108528cf22d0STrond Myklebust const uint32_t attrmask[]) 10861da177e4SLinus Torvalds { 10871da177e4SLinus Torvalds char owner_name[IDMAP_NAMESZ]; 10881da177e4SLinus Torvalds char owner_group[IDMAP_NAMESZ]; 10891da177e4SLinus Torvalds int owner_namelen = 0; 10901da177e4SLinus Torvalds int owner_grouplen = 0; 10918687b63aSAl Viro __be32 *p; 1092d7067b2dSTrond Myklebust uint32_t len = 0; 1093d7067b2dSTrond Myklebust uint32_t bmval[3] = { 0 }; 10941da177e4SLinus Torvalds 10951da177e4SLinus Torvalds /* 10961da177e4SLinus Torvalds * We reserve enough space to write the entire attribute buffer at once. 10971da177e4SLinus Torvalds */ 109828cf22d0STrond Myklebust if ((iap->ia_valid & ATTR_SIZE) && (attrmask[0] & FATTR4_WORD0_SIZE)) { 1099d7067b2dSTrond Myklebust bmval[0] |= FATTR4_WORD0_SIZE; 11001da177e4SLinus Torvalds len += 8; 1101d7067b2dSTrond Myklebust } 1102d7067b2dSTrond Myklebust if (iap->ia_valid & ATTR_MODE) { 110328cf22d0STrond Myklebust if (umask && (attrmask[2] & FATTR4_WORD2_MODE_UMASK)) { 1104dff25ddbSAndreas Gruenbacher bmval[2] |= FATTR4_WORD2_MODE_UMASK; 1105dff25ddbSAndreas Gruenbacher len += 8; 110628cf22d0STrond Myklebust } else if (attrmask[1] & FATTR4_WORD1_MODE) { 1107d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_MODE; 11081da177e4SLinus Torvalds len += 4; 1109d7067b2dSTrond Myklebust } 1110dff25ddbSAndreas Gruenbacher } 111128cf22d0STrond Myklebust if ((iap->ia_valid & ATTR_UID) && (attrmask[1] & FATTR4_WORD1_OWNER)) { 1112e4fd72a1STrond Myklebust owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); 11131da177e4SLinus Torvalds if (owner_namelen < 0) { 1114fe82a183SChuck Lever dprintk("nfs: couldn't resolve uid %d to string\n", 1115e5782076SEric W. Biederman from_kuid(&init_user_ns, iap->ia_uid)); 11161da177e4SLinus Torvalds /* XXX */ 11171da177e4SLinus Torvalds strcpy(owner_name, "nobody"); 11181da177e4SLinus Torvalds owner_namelen = sizeof("nobody") - 1; 11191da177e4SLinus Torvalds /* goto out; */ 11201da177e4SLinus Torvalds } 1121d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_OWNER; 11221da177e4SLinus Torvalds len += 4 + (XDR_QUADLEN(owner_namelen) << 2); 11231da177e4SLinus Torvalds } 112428cf22d0STrond Myklebust if ((iap->ia_valid & ATTR_GID) && 112528cf22d0STrond Myklebust (attrmask[1] & FATTR4_WORD1_OWNER_GROUP)) { 1126e4fd72a1STrond Myklebust owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ); 11271da177e4SLinus Torvalds if (owner_grouplen < 0) { 1128fe82a183SChuck Lever dprintk("nfs: couldn't resolve gid %d to string\n", 1129e5782076SEric W. Biederman from_kgid(&init_user_ns, iap->ia_gid)); 11301da177e4SLinus Torvalds strcpy(owner_group, "nobody"); 11311da177e4SLinus Torvalds owner_grouplen = sizeof("nobody") - 1; 11321da177e4SLinus Torvalds /* goto out; */ 11331da177e4SLinus Torvalds } 1134d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_OWNER_GROUP; 11351da177e4SLinus Torvalds len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); 11361da177e4SLinus Torvalds } 113728cf22d0STrond Myklebust if (attrmask[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 1138d7067b2dSTrond Myklebust if (iap->ia_valid & ATTR_ATIME_SET) { 1139d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; 114036b3743fSTrond Myklebust len += 4 + (nfstime4_maxsz << 2); 1141d7067b2dSTrond Myklebust } else if (iap->ia_valid & ATTR_ATIME) { 1142d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; 11431da177e4SLinus Torvalds len += 4; 1144d7067b2dSTrond Myklebust } 114528cf22d0STrond Myklebust } 114628cf22d0STrond Myklebust if (attrmask[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 1147d7067b2dSTrond Myklebust if (iap->ia_valid & ATTR_MTIME_SET) { 1148d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; 114936b3743fSTrond Myklebust len += 4 + (nfstime4_maxsz << 2); 1150d7067b2dSTrond Myklebust } else if (iap->ia_valid & ATTR_MTIME) { 1151d7067b2dSTrond Myklebust bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; 11521da177e4SLinus Torvalds len += 4; 1153d7067b2dSTrond Myklebust } 11545334c5bdSKinglong Mee } 11555334c5bdSKinglong Mee 115628cf22d0STrond Myklebust if (label && (attrmask[2] & FATTR4_WORD2_SECURITY_LABEL)) { 1157b4a2cf76STrond Myklebust len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); 1158d7067b2dSTrond Myklebust bmval[2] |= FATTR4_WORD2_SECURITY_LABEL; 1159d7067b2dSTrond Myklebust } 1160d7067b2dSTrond Myklebust 116140a3426cSTrond Myklebust xdr_encode_bitmap4(xdr, bmval, ARRAY_SIZE(bmval)); 116240a3426cSTrond Myklebust xdr_stream_encode_opaque_inline(xdr, (void **)&p, len); 11631da177e4SLinus Torvalds 1164d7067b2dSTrond Myklebust if (bmval[0] & FATTR4_WORD0_SIZE) 1165b95be5a9SBenny Halevy p = xdr_encode_hyper(p, iap->ia_size); 1166d7067b2dSTrond Myklebust if (bmval[1] & FATTR4_WORD1_MODE) 1167e75bc1c8SBenny Halevy *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); 1168d7067b2dSTrond Myklebust if (bmval[1] & FATTR4_WORD1_OWNER) 1169811652bdSBenny Halevy p = xdr_encode_opaque(p, owner_name, owner_namelen); 1170d7067b2dSTrond Myklebust if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) 1171811652bdSBenny Halevy p = xdr_encode_opaque(p, owner_group, owner_grouplen); 1172d7067b2dSTrond Myklebust if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 11731da177e4SLinus Torvalds if (iap->ia_valid & ATTR_ATIME_SET) { 1174e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 1175e7d4b05cSTrond Myklebust p = xdr_encode_nfstime4(p, &iap->ia_atime); 1176d7067b2dSTrond Myklebust } else 1177e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); 11781da177e4SLinus Torvalds } 1179d7067b2dSTrond Myklebust if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 11801da177e4SLinus Torvalds if (iap->ia_valid & ATTR_MTIME_SET) { 1181e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 1182e7d4b05cSTrond Myklebust p = xdr_encode_nfstime4(p, &iap->ia_mtime); 1183d7067b2dSTrond Myklebust } else 1184e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); 11851da177e4SLinus Torvalds } 1186e2751463SJia-Ju Bai if (label && (bmval[2] & FATTR4_WORD2_SECURITY_LABEL)) { 1187aa9c2669SDavid Quigley *p++ = cpu_to_be32(label->lfs); 1188aa9c2669SDavid Quigley *p++ = cpu_to_be32(label->pi); 1189aa9c2669SDavid Quigley *p++ = cpu_to_be32(label->len); 1190aa9c2669SDavid Quigley p = xdr_encode_opaque_fixed(p, label->label, label->len); 1191aa9c2669SDavid Quigley } 1192dff25ddbSAndreas Gruenbacher if (bmval[2] & FATTR4_WORD2_MODE_UMASK) { 1193dff25ddbSAndreas Gruenbacher *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); 1194dff25ddbSAndreas Gruenbacher *p++ = cpu_to_be32(*umask); 1195dff25ddbSAndreas Gruenbacher } 11961da177e4SLinus Torvalds 11971da177e4SLinus Torvalds /* out: */ 11981da177e4SLinus Torvalds } 11991da177e4SLinus Torvalds 1200cf8cdbe5SAndy Adamson static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr) 12011da177e4SLinus Torvalds { 1202475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_ACCESS, decode_access_maxsz, hdr); 1203475d4ba0STrond Myklebust encode_uint32(xdr, access); 12041da177e4SLinus Torvalds } 12051da177e4SLinus Torvalds 1206cf8cdbe5SAndy Adamson static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) 12071da177e4SLinus Torvalds { 1208ab19b481STrond Myklebust encode_op_hdr(xdr, OP_CLOSE, decode_close_maxsz, hdr); 12094ade9821STrond Myklebust encode_nfs4_seqid(xdr, arg->seqid); 1210566fcec6STrond Myklebust encode_nfs4_stateid(xdr, &arg->stateid); 12111da177e4SLinus Torvalds } 12121da177e4SLinus Torvalds 12130b7c0153SFred Isaman static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr) 12141da177e4SLinus Torvalds { 12158687b63aSAl Viro __be32 *p; 12161da177e4SLinus Torvalds 1217475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr); 1218475d4ba0STrond Myklebust p = reserve_space(xdr, 12); 1219b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 122034558513SBenny Halevy *p = cpu_to_be32(args->count); 12211da177e4SLinus Torvalds } 12221da177e4SLinus Torvalds 1223cf8cdbe5SAndy Adamson static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr) 12241da177e4SLinus Torvalds { 12258687b63aSAl Viro __be32 *p; 12261da177e4SLinus Torvalds 1227475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_CREATE, decode_create_maxsz, hdr); 1228475d4ba0STrond Myklebust encode_uint32(xdr, create->ftype); 12291da177e4SLinus Torvalds 12301da177e4SLinus Torvalds switch (create->ftype) { 12311da177e4SLinus Torvalds case NF4LNK: 123213c65ce9SBenny Halevy p = reserve_space(xdr, 4); 123334558513SBenny Halevy *p = cpu_to_be32(create->u.symlink.len); 12342fcc213aSChuck Lever xdr_write_pages(xdr, create->u.symlink.pages, 0, 12352fcc213aSChuck Lever create->u.symlink.len); 12362fcc213aSChuck Lever xdr->buf->flags |= XDRBUF_WRITE; 12371da177e4SLinus Torvalds break; 12381da177e4SLinus Torvalds 12391da177e4SLinus Torvalds case NF4BLK: case NF4CHR: 124013c65ce9SBenny Halevy p = reserve_space(xdr, 8); 1241e75bc1c8SBenny Halevy *p++ = cpu_to_be32(create->u.device.specdata1); 124234558513SBenny Halevy *p = cpu_to_be32(create->u.device.specdata2); 12431da177e4SLinus Torvalds break; 12441da177e4SLinus Torvalds 12451da177e4SLinus Torvalds default: 12461da177e4SLinus Torvalds break; 12471da177e4SLinus Torvalds } 12481da177e4SLinus Torvalds 1249811652bdSBenny Halevy encode_string(xdr, create->name->len, create->name->name); 125028cf22d0STrond Myklebust encode_attrs(xdr, create->attrs, create->label, &create->umask, 125128cf22d0STrond Myklebust create->server, create->server->attr_bitmask); 12521da177e4SLinus Torvalds } 12531da177e4SLinus Torvalds 125437c88763STrond Myklebust static void encode_getattr(struct xdr_stream *xdr, 125537c88763STrond Myklebust const __u32 *bitmap, const __u32 *mask, size_t len, 1256dae100c2SFred Isaman struct compound_hdr *hdr) 1257dae100c2SFred Isaman { 125837c88763STrond Myklebust __u32 masked_bitmap[nfs4_fattr_bitmap_maxsz]; 1259dae100c2SFred Isaman 1260ab19b481STrond Myklebust encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr); 126137c88763STrond Myklebust if (mask) { 126237c88763STrond Myklebust if (WARN_ON_ONCE(len > ARRAY_SIZE(masked_bitmap))) 126337c88763STrond Myklebust len = ARRAY_SIZE(masked_bitmap); 126437c88763STrond Myklebust len = mask_bitmap4(bitmap, mask, masked_bitmap, len); 126537c88763STrond Myklebust bitmap = masked_bitmap; 1266dae100c2SFred Isaman } 126737c88763STrond Myklebust xdr_encode_bitmap4(xdr, bitmap, len); 1268dae100c2SFred Isaman } 1269dae100c2SFred Isaman 1270cf8cdbe5SAndy Adamson static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 12711da177e4SLinus Torvalds { 127237c88763STrond Myklebust encode_getattr(xdr, nfs4_fattr_bitmap, bitmask, 127337c88763STrond Myklebust ARRAY_SIZE(nfs4_fattr_bitmap), hdr); 12741da177e4SLinus Torvalds } 12751da177e4SLinus Torvalds 127688034c3dSAndy Adamson static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, 12771549210fSTrond Myklebust const u32 *open_bitmap, 127888034c3dSAndy Adamson struct compound_hdr *hdr) 127988034c3dSAndy Adamson { 128037c88763STrond Myklebust encode_getattr(xdr, open_bitmap, bitmask, 3, hdr); 128188034c3dSAndy Adamson } 128288034c3dSAndy Adamson 1283cf8cdbe5SAndy Adamson static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 12841da177e4SLinus Torvalds { 128537c88763STrond Myklebust encode_getattr(xdr, nfs4_fsinfo_bitmap, bitmask, 128637c88763STrond Myklebust ARRAY_SIZE(nfs4_fsinfo_bitmap), hdr); 12871da177e4SLinus Torvalds } 12881da177e4SLinus Torvalds 1289cf8cdbe5SAndy Adamson static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 1290830b8e33SManoj Naik { 129137c88763STrond Myklebust encode_getattr(xdr, nfs4_fs_locations_bitmap, bitmask, 129237c88763STrond Myklebust ARRAY_SIZE(nfs4_fs_locations_bitmap), hdr); 1293830b8e33SManoj Naik } 1294830b8e33SManoj Naik 1295cf8cdbe5SAndy Adamson static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr) 12961da177e4SLinus Torvalds { 1297ab19b481STrond Myklebust encode_op_hdr(xdr, OP_GETFH, decode_getfh_maxsz, hdr); 12981da177e4SLinus Torvalds } 12991da177e4SLinus Torvalds 1300cf8cdbe5SAndy Adamson static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 13011da177e4SLinus Torvalds { 1302ab19b481STrond Myklebust encode_op_hdr(xdr, OP_LINK, decode_link_maxsz, hdr); 13036fdfb0bcSTrond Myklebust encode_string(xdr, name->len, name->name); 13041da177e4SLinus Torvalds } 13051da177e4SLinus Torvalds 1306911d1aafSTrond Myklebust static inline int nfs4_lock_type(struct file_lock *fl, int block) 1307911d1aafSTrond Myklebust { 1308f44106e2SJeff Layton if (fl->fl_type == F_RDLCK) 1309911d1aafSTrond Myklebust return block ? NFS4_READW_LT : NFS4_READ_LT; 1310911d1aafSTrond Myklebust return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; 1311911d1aafSTrond Myklebust } 1312911d1aafSTrond Myklebust 1313911d1aafSTrond Myklebust static inline uint64_t nfs4_lock_length(struct file_lock *fl) 1314911d1aafSTrond Myklebust { 1315911d1aafSTrond Myklebust if (fl->fl_end == OFFSET_MAX) 1316911d1aafSTrond Myklebust return ~(uint64_t)0; 1317911d1aafSTrond Myklebust return fl->fl_end - fl->fl_start + 1; 1318911d1aafSTrond Myklebust } 1319911d1aafSTrond Myklebust 1320daccbdedSTrond Myklebust static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner) 1321daccbdedSTrond Myklebust { 1322daccbdedSTrond Myklebust __be32 *p; 1323daccbdedSTrond Myklebust 1324d035c36cSTrond Myklebust p = reserve_space(xdr, 32); 1325daccbdedSTrond Myklebust p = xdr_encode_hyper(p, lowner->clientid); 1326d035c36cSTrond Myklebust *p++ = cpu_to_be32(20); 1327daccbdedSTrond Myklebust p = xdr_encode_opaque_fixed(p, "lock id:", 8); 1328d035c36cSTrond Myklebust *p++ = cpu_to_be32(lowner->s_dev); 1329daccbdedSTrond Myklebust xdr_encode_hyper(p, lowner->id); 1330daccbdedSTrond Myklebust } 1331daccbdedSTrond Myklebust 13321da177e4SLinus Torvalds /* 13331da177e4SLinus Torvalds * opcode,type,reclaim,offset,length,new_lock_owner = 32 13341da177e4SLinus Torvalds * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 13351da177e4SLinus Torvalds */ 1336cf8cdbe5SAndy Adamson static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr) 13371da177e4SLinus Torvalds { 13388687b63aSAl Viro __be32 *p; 13391da177e4SLinus Torvalds 1340475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LOCK, decode_lock_maxsz, hdr); 1341475d4ba0STrond Myklebust p = reserve_space(xdr, 28); 1342e75bc1c8SBenny Halevy *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block)); 1343e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->reclaim); 1344b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 1345b95be5a9SBenny Halevy p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 134634558513SBenny Halevy *p = cpu_to_be32(args->new_lock_owner); 1347911d1aafSTrond Myklebust if (args->new_lock_owner){ 13484ade9821STrond Myklebust encode_nfs4_seqid(xdr, args->open_seqid); 1349425c1d4eSTrond Myklebust encode_nfs4_stateid(xdr, &args->open_stateid); 13504ade9821STrond Myklebust encode_nfs4_seqid(xdr, args->lock_seqid); 1351daccbdedSTrond Myklebust encode_lockowner(xdr, &args->lock_owner); 13521da177e4SLinus Torvalds } 13531da177e4SLinus Torvalds else { 1354425c1d4eSTrond Myklebust encode_nfs4_stateid(xdr, &args->lock_stateid); 13554ade9821STrond Myklebust encode_nfs4_seqid(xdr, args->lock_seqid); 13561da177e4SLinus Torvalds } 13571da177e4SLinus Torvalds } 13581da177e4SLinus Torvalds 1359cf8cdbe5SAndy Adamson static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr) 13601da177e4SLinus Torvalds { 13618687b63aSAl Viro __be32 *p; 13621da177e4SLinus Torvalds 1363475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LOCKT, decode_lockt_maxsz, hdr); 1364475d4ba0STrond Myklebust p = reserve_space(xdr, 20); 1365e75bc1c8SBenny Halevy *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); 1366b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 1367b95be5a9SBenny Halevy p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 1368daccbdedSTrond Myklebust encode_lockowner(xdr, &args->lock_owner); 13691da177e4SLinus Torvalds } 13701da177e4SLinus Torvalds 1371cf8cdbe5SAndy Adamson static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr) 13721da177e4SLinus Torvalds { 13738687b63aSAl Viro __be32 *p; 13741da177e4SLinus Torvalds 1375475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LOCKU, decode_locku_maxsz, hdr); 1376475d4ba0STrond Myklebust encode_uint32(xdr, nfs4_lock_type(args->fl, 0)); 13774ade9821STrond Myklebust encode_nfs4_seqid(xdr, args->seqid); 1378425c1d4eSTrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 1379ea9d23f5STrond Myklebust p = reserve_space(xdr, 16); 1380b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 138134558513SBenny Halevy xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 13821da177e4SLinus Torvalds } 13831da177e4SLinus Torvalds 1384d3c7b7ccSTrond Myklebust static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr) 1385d3c7b7ccSTrond Myklebust { 1386ab19b481STrond Myklebust encode_op_hdr(xdr, OP_RELEASE_LOCKOWNER, decode_release_lockowner_maxsz, hdr); 1387d3c7b7ccSTrond Myklebust encode_lockowner(xdr, lowner); 1388d3c7b7ccSTrond Myklebust } 1389d3c7b7ccSTrond Myklebust 1390cf8cdbe5SAndy Adamson static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 13911da177e4SLinus Torvalds { 1392ab19b481STrond Myklebust encode_op_hdr(xdr, OP_LOOKUP, decode_lookup_maxsz, hdr); 13936fdfb0bcSTrond Myklebust encode_string(xdr, name->len, name->name); 13941da177e4SLinus Torvalds } 13951da177e4SLinus Torvalds 13965b5faaf6SJeff Layton static void encode_lookupp(struct xdr_stream *xdr, struct compound_hdr *hdr) 13975b5faaf6SJeff Layton { 13985b5faaf6SJeff Layton encode_op_hdr(xdr, OP_LOOKUPP, decode_lookupp_maxsz, hdr); 13995b5faaf6SJeff Layton } 14005b5faaf6SJeff Layton 14016ae37339STrond Myklebust static void encode_share_access(struct xdr_stream *xdr, u32 share_access) 14021da177e4SLinus Torvalds { 14038687b63aSAl Viro __be32 *p; 14041da177e4SLinus Torvalds 140513c65ce9SBenny Halevy p = reserve_space(xdr, 8); 14066ae37339STrond Myklebust *p++ = cpu_to_be32(share_access); 140734558513SBenny Halevy *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */ 14081da177e4SLinus Torvalds } 14091da177e4SLinus Torvalds 14101da177e4SLinus Torvalds static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg) 14111da177e4SLinus Torvalds { 14128687b63aSAl Viro __be32 *p; 14131da177e4SLinus Torvalds /* 14141da177e4SLinus Torvalds * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, 14151da177e4SLinus Torvalds * owner 4 = 32 14161da177e4SLinus Torvalds */ 14174ade9821STrond Myklebust encode_nfs4_seqid(xdr, arg->seqid); 14186ae37339STrond Myklebust encode_share_access(xdr, arg->share_access); 141995b72eb0STrond Myklebust p = reserve_space(xdr, 36); 1420b95be5a9SBenny Halevy p = xdr_encode_hyper(p, arg->clientid); 142195b72eb0STrond Myklebust *p++ = cpu_to_be32(24); 142293f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, "open id:", 8); 1423d035c36cSTrond Myklebust *p++ = cpu_to_be32(arg->server->s_dev); 142495b72eb0STrond Myklebust *p++ = cpu_to_be32(arg->id.uniquifier); 142595b72eb0STrond Myklebust xdr_encode_hyper(p, arg->id.create_time); 14261da177e4SLinus Torvalds } 14271da177e4SLinus Torvalds 14281da177e4SLinus Torvalds static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) 14291da177e4SLinus Torvalds { 14308687b63aSAl Viro __be32 *p; 14311da177e4SLinus Torvalds 143213c65ce9SBenny Halevy p = reserve_space(xdr, 4); 1433549b19ccSTrond Myklebust switch(arg->createmode) { 1434549b19ccSTrond Myklebust case NFS4_CREATE_UNCHECKED: 143534558513SBenny Halevy *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); 143628cf22d0STrond Myklebust encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask, 143728cf22d0STrond Myklebust arg->server, arg->server->attr_bitmask); 14381da177e4SLinus Torvalds break; 1439549b19ccSTrond Myklebust case NFS4_CREATE_GUARDED: 14404882ef72SAlexandros Batsakis *p = cpu_to_be32(NFS4_CREATE_GUARDED); 144128cf22d0STrond Myklebust encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask, 144228cf22d0STrond Myklebust arg->server, arg->server->attr_bitmask); 1443549b19ccSTrond Myklebust break; 1444549b19ccSTrond Myklebust case NFS4_CREATE_EXCLUSIVE: 1445549b19ccSTrond Myklebust *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); 1446549b19ccSTrond Myklebust encode_nfs4_verifier(xdr, &arg->u.verifier); 1447549b19ccSTrond Myklebust break; 1448549b19ccSTrond Myklebust case NFS4_CREATE_EXCLUSIVE4_1: 14494882ef72SAlexandros Batsakis *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); 14504882ef72SAlexandros Batsakis encode_nfs4_verifier(xdr, &arg->u.verifier); 145128cf22d0STrond Myklebust encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask, 145228cf22d0STrond Myklebust arg->server, arg->server->exclcreat_bitmask); 14534882ef72SAlexandros Batsakis } 14544882ef72SAlexandros Batsakis } 14551da177e4SLinus Torvalds 14561da177e4SLinus Torvalds static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg) 14571da177e4SLinus Torvalds { 14588687b63aSAl Viro __be32 *p; 14591da177e4SLinus Torvalds 146013c65ce9SBenny Halevy p = reserve_space(xdr, 4); 14611da177e4SLinus Torvalds switch (arg->open_flags & O_CREAT) { 14621da177e4SLinus Torvalds case 0: 146334558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_NOCREATE); 14641da177e4SLinus Torvalds break; 14651da177e4SLinus Torvalds default: 146634558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CREATE); 14671da177e4SLinus Torvalds encode_createmode(xdr, arg); 14681da177e4SLinus Torvalds } 14691da177e4SLinus Torvalds } 14701da177e4SLinus Torvalds 1471bd7bf9d5STrond Myklebust static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type) 14721da177e4SLinus Torvalds { 14738687b63aSAl Viro __be32 *p; 14741da177e4SLinus Torvalds 147513c65ce9SBenny Halevy p = reserve_space(xdr, 4); 14761da177e4SLinus Torvalds switch (delegation_type) { 14771da177e4SLinus Torvalds case 0: 147834558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE); 14791da177e4SLinus Torvalds break; 14801da177e4SLinus Torvalds case FMODE_READ: 148134558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ); 14821da177e4SLinus Torvalds break; 14831da177e4SLinus Torvalds case FMODE_WRITE|FMODE_READ: 148434558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE); 14851da177e4SLinus Torvalds break; 14861da177e4SLinus Torvalds default: 14871da177e4SLinus Torvalds BUG(); 14881da177e4SLinus Torvalds } 14891da177e4SLinus Torvalds } 14901da177e4SLinus Torvalds 14911da177e4SLinus Torvalds static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name) 14921da177e4SLinus Torvalds { 14938687b63aSAl Viro __be32 *p; 14941da177e4SLinus Torvalds 149513c65ce9SBenny Halevy p = reserve_space(xdr, 4); 149634558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL); 14971da177e4SLinus Torvalds encode_string(xdr, name->len, name->name); 14981da177e4SLinus Torvalds } 14991da177e4SLinus Torvalds 1500bd7bf9d5STrond Myklebust static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type) 15011da177e4SLinus Torvalds { 15028687b63aSAl Viro __be32 *p; 15031da177e4SLinus Torvalds 150413c65ce9SBenny Halevy p = reserve_space(xdr, 4); 150534558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS); 15061da177e4SLinus Torvalds encode_delegation_type(xdr, type); 15071da177e4SLinus Torvalds } 15081da177e4SLinus Torvalds 15091da177e4SLinus Torvalds static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid) 15101da177e4SLinus Torvalds { 15118687b63aSAl Viro __be32 *p; 15121da177e4SLinus Torvalds 1513ea9d23f5STrond Myklebust p = reserve_space(xdr, 4); 1514ea9d23f5STrond Myklebust *p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR); 1515ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, stateid); 15161da177e4SLinus Torvalds encode_string(xdr, name->len, name->name); 15171da177e4SLinus Torvalds } 15181da177e4SLinus Torvalds 1519d9fc6619STrond Myklebust static inline void encode_claim_fh(struct xdr_stream *xdr) 1520d9fc6619STrond Myklebust { 1521d9fc6619STrond Myklebust __be32 *p; 1522d9fc6619STrond Myklebust 1523d9fc6619STrond Myklebust p = reserve_space(xdr, 4); 1524d9fc6619STrond Myklebust *p = cpu_to_be32(NFS4_OPEN_CLAIM_FH); 1525d9fc6619STrond Myklebust } 1526d9fc6619STrond Myklebust 1527d9fc6619STrond Myklebust static inline void encode_claim_delegate_cur_fh(struct xdr_stream *xdr, const nfs4_stateid *stateid) 1528d9fc6619STrond Myklebust { 1529d9fc6619STrond Myklebust __be32 *p; 1530d9fc6619STrond Myklebust 1531d9fc6619STrond Myklebust p = reserve_space(xdr, 4); 1532d9fc6619STrond Myklebust *p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEG_CUR_FH); 1533d9fc6619STrond Myklebust encode_nfs4_stateid(xdr, stateid); 1534d9fc6619STrond Myklebust } 1535d9fc6619STrond Myklebust 1536cf8cdbe5SAndy Adamson static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr) 15371da177e4SLinus Torvalds { 1538ab19b481STrond Myklebust encode_op_hdr(xdr, OP_OPEN, decode_open_maxsz, hdr); 15391da177e4SLinus Torvalds encode_openhdr(xdr, arg); 15401da177e4SLinus Torvalds encode_opentype(xdr, arg); 15411da177e4SLinus Torvalds switch (arg->claim) { 15421da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_NULL: 15431da177e4SLinus Torvalds encode_claim_null(xdr, arg->name); 15441da177e4SLinus Torvalds break; 15451da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_PREVIOUS: 15461da177e4SLinus Torvalds encode_claim_previous(xdr, arg->u.delegation_type); 15471da177e4SLinus Torvalds break; 15481da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_DELEGATE_CUR: 15491da177e4SLinus Torvalds encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation); 15501da177e4SLinus Torvalds break; 1551d9fc6619STrond Myklebust case NFS4_OPEN_CLAIM_FH: 1552d9fc6619STrond Myklebust encode_claim_fh(xdr); 1553d9fc6619STrond Myklebust break; 1554d9fc6619STrond Myklebust case NFS4_OPEN_CLAIM_DELEG_CUR_FH: 1555d9fc6619STrond Myklebust encode_claim_delegate_cur_fh(xdr, &arg->u.delegation); 1556d9fc6619STrond Myklebust break; 15571da177e4SLinus Torvalds default: 15581da177e4SLinus Torvalds BUG(); 15591da177e4SLinus Torvalds } 15601da177e4SLinus Torvalds } 15611da177e4SLinus Torvalds 1562cf8cdbe5SAndy Adamson static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr) 15631da177e4SLinus Torvalds { 1564ab19b481STrond Myklebust encode_op_hdr(xdr, OP_OPEN_CONFIRM, decode_open_confirm_maxsz, hdr); 1565ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, arg->stateid); 15664ade9821STrond Myklebust encode_nfs4_seqid(xdr, arg->seqid); 15671da177e4SLinus Torvalds } 15681da177e4SLinus Torvalds 1569cf8cdbe5SAndy Adamson static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) 15701da177e4SLinus Torvalds { 1571ab19b481STrond Myklebust encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr); 1572566fcec6STrond Myklebust encode_nfs4_stateid(xdr, &arg->stateid); 15734ade9821STrond Myklebust encode_nfs4_seqid(xdr, arg->seqid); 15746ae37339STrond Myklebust encode_share_access(xdr, arg->share_access); 15751da177e4SLinus Torvalds } 15761da177e4SLinus Torvalds 1577cf8cdbe5SAndy Adamson static void 1578d017931cSAndy Adamson encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr) 15791da177e4SLinus Torvalds { 1580ab19b481STrond Myklebust encode_op_hdr(xdr, OP_PUTFH, decode_putfh_maxsz, hdr); 15816fdfb0bcSTrond Myklebust encode_string(xdr, fh->size, fh->data); 15821da177e4SLinus Torvalds } 15831da177e4SLinus Torvalds 1584cf8cdbe5SAndy Adamson static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr) 15851da177e4SLinus Torvalds { 1586ab19b481STrond Myklebust encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr); 15871da177e4SLinus Torvalds } 15881da177e4SLinus Torvalds 15893c6b899cSAnna Schumaker static void encode_read(struct xdr_stream *xdr, const struct nfs_pgio_args *args, 15903c6b899cSAnna Schumaker struct compound_hdr *hdr) 15911da177e4SLinus Torvalds { 15928687b63aSAl Viro __be32 *p; 15931da177e4SLinus Torvalds 1594ab19b481STrond Myklebust encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr); 15959b206149STrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 15961da177e4SLinus Torvalds 159713c65ce9SBenny Halevy p = reserve_space(xdr, 12); 1598b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 159934558513SBenny Halevy *p = cpu_to_be32(args->count); 16001da177e4SLinus Torvalds } 16011da177e4SLinus Torvalds 1602cf8cdbe5SAndy Adamson static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) 16031da177e4SLinus Torvalds { 1604aa9c2669SDavid Quigley uint32_t attrs[3] = { 160528331a46STrond Myklebust FATTR4_WORD0_RDATTR_ERROR, 160628331a46STrond Myklebust FATTR4_WORD1_MOUNTED_ON_FILEID, 160728331a46STrond Myklebust }; 16086f7a35bdSTrond Myklebust uint32_t dircount = readdir->count >> 1; 1609cd93710eSChuck Lever __be32 *p, verf[2]; 1610d204c5d2STrond Myklebust uint32_t attrlen = 0; 1611d204c5d2STrond Myklebust unsigned int i; 16121da177e4SLinus Torvalds 161382f2e547SBryan Schumaker if (readdir->plus) { 161482f2e547SBryan Schumaker attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| 161528331a46STrond Myklebust FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID; 161682f2e547SBryan Schumaker attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER| 161782f2e547SBryan Schumaker FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| 161882f2e547SBryan Schumaker FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| 161982f2e547SBryan Schumaker FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; 1620d204c5d2STrond Myklebust attrs[2] |= FATTR4_WORD2_SECURITY_LABEL; 16216f7a35bdSTrond Myklebust dircount >>= 1; 162282f2e547SBryan Schumaker } 162328331a46STrond Myklebust /* Use mounted_on_fileid only if the server supports it */ 162428331a46STrond Myklebust if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) 162528331a46STrond Myklebust attrs[0] |= FATTR4_WORD0_FILEID; 1626d204c5d2STrond Myklebust for (i = 0; i < ARRAY_SIZE(attrs); i++) { 1627d204c5d2STrond Myklebust attrs[i] &= readdir->bitmask[i]; 1628d204c5d2STrond Myklebust if (attrs[i] != 0) 1629d204c5d2STrond Myklebust attrlen = i+1; 1630d204c5d2STrond Myklebust } 16316f7a35bdSTrond Myklebust 1632475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); 1633ff2eb681STrond Myklebust encode_uint64(xdr, readdir->cookie); 1634cd93710eSChuck Lever encode_nfs4_verifier(xdr, &readdir->verifier); 1635d204c5d2STrond Myklebust p = reserve_space(xdr, 12 + (attrlen << 2)); 16366f7a35bdSTrond Myklebust *p++ = cpu_to_be32(dircount); 16376f7a35bdSTrond Myklebust *p++ = cpu_to_be32(readdir->count); 1638d204c5d2STrond Myklebust *p++ = cpu_to_be32(attrlen); 1639d204c5d2STrond Myklebust for (i = 0; i < attrlen; i++) 1640d204c5d2STrond Myklebust *p++ = cpu_to_be32(attrs[i]); 1641cd93710eSChuck Lever memcpy(verf, readdir->verifier.data, sizeof(verf)); 1642aa9c2669SDavid Quigley 1643aa9c2669SDavid Quigley dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n", 164444109241SFred Isaman __func__, 1645eadf4598STrond Myklebust (unsigned long long)readdir->cookie, 1646cd93710eSChuck Lever verf[0], verf[1], 1647eadf4598STrond Myklebust attrs[0] & readdir->bitmask[0], 1648aa9c2669SDavid Quigley attrs[1] & readdir->bitmask[1], 1649aa9c2669SDavid Quigley attrs[2] & readdir->bitmask[2]); 16501da177e4SLinus Torvalds } 16511da177e4SLinus Torvalds 1652cf8cdbe5SAndy Adamson static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) 16531da177e4SLinus Torvalds { 1654ab19b481STrond Myklebust encode_op_hdr(xdr, OP_READLINK, decode_readlink_maxsz, hdr); 16551da177e4SLinus Torvalds } 16561da177e4SLinus Torvalds 1657cf8cdbe5SAndy Adamson static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 16581da177e4SLinus Torvalds { 1659ab19b481STrond Myklebust encode_op_hdr(xdr, OP_REMOVE, decode_remove_maxsz, hdr); 16606fdfb0bcSTrond Myklebust encode_string(xdr, name->len, name->name); 16611da177e4SLinus Torvalds } 16621da177e4SLinus Torvalds 1663cf8cdbe5SAndy Adamson static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr) 16641da177e4SLinus Torvalds { 1665ab19b481STrond Myklebust encode_op_hdr(xdr, OP_RENAME, decode_rename_maxsz, hdr); 1666811652bdSBenny Halevy encode_string(xdr, oldname->len, oldname->name); 1667811652bdSBenny Halevy encode_string(xdr, newname->len, newname->name); 16681da177e4SLinus Torvalds } 16691da177e4SLinus Torvalds 1670bb4dae5eSChuck Lever static void encode_renew(struct xdr_stream *xdr, clientid4 clid, 1671bb4dae5eSChuck Lever struct compound_hdr *hdr) 16721da177e4SLinus Torvalds { 1673475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_RENEW, decode_renew_maxsz, hdr); 1674ff2eb681STrond Myklebust encode_uint64(xdr, clid); 16751da177e4SLinus Torvalds } 16761da177e4SLinus Torvalds 1677cf8cdbe5SAndy Adamson static void 1678d017931cSAndy Adamson encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr) 167956ae19f3STrond Myklebust { 1680ab19b481STrond Myklebust encode_op_hdr(xdr, OP_RESTOREFH, decode_restorefh_maxsz, hdr); 168156ae19f3STrond Myklebust } 168256ae19f3STrond Myklebust 16839f06c719SChuck Lever static void 1684fcc85819SChristoph Hellwig encode_setacl(struct xdr_stream *xdr, const struct nfs_setaclargs *arg, 1685fcc85819SChristoph Hellwig struct compound_hdr *hdr) 168623ec6965SJ. Bruce Fields { 16878687b63aSAl Viro __be32 *p; 168823ec6965SJ. Bruce Fields 1689ab19b481STrond Myklebust encode_op_hdr(xdr, OP_SETATTR, decode_setacl_maxsz, hdr); 1690ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, &zero_stateid); 169113c65ce9SBenny Halevy p = reserve_space(xdr, 2*4); 1692e75bc1c8SBenny Halevy *p++ = cpu_to_be32(1); 169334558513SBenny Halevy *p = cpu_to_be32(FATTR4_WORD0_ACL); 169413c65ce9SBenny Halevy p = reserve_space(xdr, 4); 169534558513SBenny Halevy *p = cpu_to_be32(arg->acl_len); 16968fbcf237SAndreas Gruenbacher xdr_write_pages(xdr, arg->acl_pages, 0, arg->acl_len); 169723ec6965SJ. Bruce Fields } 169823ec6965SJ. Bruce Fields 1699cf8cdbe5SAndy Adamson static void 1700d017931cSAndy Adamson encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr) 17011da177e4SLinus Torvalds { 1702ab19b481STrond Myklebust encode_op_hdr(xdr, OP_SAVEFH, decode_savefh_maxsz, hdr); 17031da177e4SLinus Torvalds } 17041da177e4SLinus Torvalds 1705cf8cdbe5SAndy Adamson static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr) 17061da177e4SLinus Torvalds { 1707ab19b481STrond Myklebust encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); 1708ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, &arg->stateid); 170928cf22d0STrond Myklebust encode_attrs(xdr, arg->iap, arg->label, NULL, server, 171028cf22d0STrond Myklebust server->attr_bitmask); 17111da177e4SLinus Torvalds } 17121da177e4SLinus Torvalds 1713cf8cdbe5SAndy Adamson static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) 17141da177e4SLinus Torvalds { 17158687b63aSAl Viro __be32 *p; 17161da177e4SLinus Torvalds 171770019514STrond Myklebust encode_op_hdr(xdr, OP_SETCLIENTID, decode_setclientid_maxsz, hdr); 1718cd93710eSChuck Lever encode_nfs4_verifier(xdr, setclientid->sc_verifier); 17191da177e4SLinus Torvalds 17203a6bb738SJeff Layton encode_string(xdr, strlen(setclientid->sc_clnt->cl_owner_id), 17213a6bb738SJeff Layton setclientid->sc_clnt->cl_owner_id); 172213c65ce9SBenny Halevy p = reserve_space(xdr, 4); 172334558513SBenny Halevy *p = cpu_to_be32(setclientid->sc_prog); 17241da177e4SLinus Torvalds encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid); 17251da177e4SLinus Torvalds encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr); 172613c65ce9SBenny Halevy p = reserve_space(xdr, 4); 17273a6bb738SJeff Layton *p = cpu_to_be32(setclientid->sc_clnt->cl_cb_ident); 17281da177e4SLinus Torvalds } 17291da177e4SLinus Torvalds 1730bb8b27e5STrond Myklebust static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr) 17311da177e4SLinus Torvalds { 1732475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM, 1733475d4ba0STrond Myklebust decode_setclientid_confirm_maxsz, hdr); 1734ff2eb681STrond Myklebust encode_uint64(xdr, arg->clientid); 1735cd93710eSChuck Lever encode_nfs4_verifier(xdr, &arg->confirm); 17361da177e4SLinus Torvalds } 17371da177e4SLinus Torvalds 17383c6b899cSAnna Schumaker static void encode_write(struct xdr_stream *xdr, const struct nfs_pgio_args *args, 17393c6b899cSAnna Schumaker struct compound_hdr *hdr) 17401da177e4SLinus Torvalds { 17418687b63aSAl Viro __be32 *p; 17421da177e4SLinus Torvalds 1743ab19b481STrond Myklebust encode_op_hdr(xdr, OP_WRITE, decode_write_maxsz, hdr); 17449b206149STrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 17451da177e4SLinus Torvalds 174613c65ce9SBenny Halevy p = reserve_space(xdr, 16); 1747b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 1748e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->stable); 174934558513SBenny Halevy *p = cpu_to_be32(args->count); 17501da177e4SLinus Torvalds 17511da177e4SLinus Torvalds xdr_write_pages(xdr, args->pages, args->pgbase, args->count); 17521da177e4SLinus Torvalds } 17531da177e4SLinus Torvalds 1754cf8cdbe5SAndy Adamson static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr) 17551da177e4SLinus Torvalds { 1756ab19b481STrond Myklebust encode_op_hdr(xdr, OP_DELEGRETURN, decode_delegreturn_maxsz, hdr); 1757ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, stateid); 17581da177e4SLinus Torvalds } 17599b7b9fccSAndy Adamson 17605a5ea0d4SBryan Schumaker static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 17615a5ea0d4SBryan Schumaker { 1762ab19b481STrond Myklebust encode_op_hdr(xdr, OP_SECINFO, decode_secinfo_maxsz, hdr); 17636fdfb0bcSTrond Myklebust encode_string(xdr, name->len, name->name); 17645a5ea0d4SBryan Schumaker } 17655a5ea0d4SBryan Schumaker 176699fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 17679b7b9fccSAndy Adamson /* NFSv4.1 operations */ 17687c44f1aeSWeston Andros Adamson static void encode_bind_conn_to_session(struct xdr_stream *xdr, 1769fcc85819SChristoph Hellwig const struct nfs41_bind_conn_to_session_args *args, 17707c44f1aeSWeston Andros Adamson struct compound_hdr *hdr) 17717c44f1aeSWeston Andros Adamson { 17727c44f1aeSWeston Andros Adamson __be32 *p; 17737c44f1aeSWeston Andros Adamson 17747c44f1aeSWeston Andros Adamson encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION, 17757c44f1aeSWeston Andros Adamson decode_bind_conn_to_session_maxsz, hdr); 177671a097c6STrond Myklebust encode_opaque_fixed(xdr, args->sessionid.data, NFS4_MAX_SESSIONID_LEN); 17777c44f1aeSWeston Andros Adamson p = xdr_reserve_space(xdr, 8); 177871a097c6STrond Myklebust *p++ = cpu_to_be32(args->dir); 177971a097c6STrond Myklebust *p = (args->use_conn_in_rdma_mode) ? cpu_to_be32(1) : cpu_to_be32(0); 17807c44f1aeSWeston Andros Adamson } 17817c44f1aeSWeston Andros Adamson 1782fcc85819SChristoph Hellwig static void encode_op_map(struct xdr_stream *xdr, const struct nfs4_op_map *op_map) 17832031cd1aSWeston Andros Adamson { 17842031cd1aSWeston Andros Adamson unsigned int i; 17852031cd1aSWeston Andros Adamson encode_uint32(xdr, NFS4_OP_MAP_NUM_WORDS); 17862031cd1aSWeston Andros Adamson for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++) 17872031cd1aSWeston Andros Adamson encode_uint32(xdr, op_map->u.words[i]); 17882031cd1aSWeston Andros Adamson } 17892031cd1aSWeston Andros Adamson 179099fe60d0SBenny Halevy static void encode_exchange_id(struct xdr_stream *xdr, 1791fcc85819SChristoph Hellwig const struct nfs41_exchange_id_args *args, 179299fe60d0SBenny Halevy struct compound_hdr *hdr) 179399fe60d0SBenny Halevy { 179499fe60d0SBenny Halevy __be32 *p; 1795d751f748SJim Rees char impl_name[IMPL_NAME_LIMIT]; 1796db8ac8baSWeston Andros Adamson int len = 0; 179799fe60d0SBenny Halevy 179870019514STrond Myklebust encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr); 1799fd40559cSTrond Myklebust encode_nfs4_verifier(xdr, &args->verifier); 180099fe60d0SBenny Halevy 18013a6bb738SJeff Layton encode_string(xdr, strlen(args->client->cl_owner_id), 18023a6bb738SJeff Layton args->client->cl_owner_id); 180399fe60d0SBenny Halevy 18042031cd1aSWeston Andros Adamson encode_uint32(xdr, args->flags); 18052031cd1aSWeston Andros Adamson encode_uint32(xdr, args->state_protect.how); 18062031cd1aSWeston Andros Adamson 18072031cd1aSWeston Andros Adamson switch (args->state_protect.how) { 18082031cd1aSWeston Andros Adamson case SP4_NONE: 18092031cd1aSWeston Andros Adamson break; 18102031cd1aSWeston Andros Adamson case SP4_MACH_CRED: 18112031cd1aSWeston Andros Adamson encode_op_map(xdr, &args->state_protect.enforce); 18122031cd1aSWeston Andros Adamson encode_op_map(xdr, &args->state_protect.allow); 18132031cd1aSWeston Andros Adamson break; 18142031cd1aSWeston Andros Adamson default: 18152031cd1aSWeston Andros Adamson WARN_ON_ONCE(1); 18162031cd1aSWeston Andros Adamson break; 18172031cd1aSWeston Andros Adamson } 1818db8ac8baSWeston Andros Adamson 1819db8ac8baSWeston Andros Adamson if (send_implementation_id && 1820db8ac8baSWeston Andros Adamson sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 && 1821db8ac8baSWeston Andros Adamson sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) 1822d751f748SJim Rees <= sizeof(impl_name) + 1) 1823db8ac8baSWeston Andros Adamson len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s", 1824db8ac8baSWeston Andros Adamson utsname()->sysname, utsname()->release, 1825db8ac8baSWeston Andros Adamson utsname()->version, utsname()->machine); 1826db8ac8baSWeston Andros Adamson 1827db8ac8baSWeston Andros Adamson if (len > 0) { 18282031cd1aSWeston Andros Adamson encode_uint32(xdr, 1); /* implementation id array length=1 */ 1829db8ac8baSWeston Andros Adamson 1830db8ac8baSWeston Andros Adamson encode_string(xdr, 1831db8ac8baSWeston Andros Adamson sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1, 1832db8ac8baSWeston Andros Adamson CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN); 1833db8ac8baSWeston Andros Adamson encode_string(xdr, len, impl_name); 1834db8ac8baSWeston Andros Adamson /* just send zeros for nii_date - the date is in nii_name */ 1835db8ac8baSWeston Andros Adamson p = reserve_space(xdr, 12); 1836db8ac8baSWeston Andros Adamson p = xdr_encode_hyper(p, 0); 1837db8ac8baSWeston Andros Adamson *p = cpu_to_be32(0); 1838db8ac8baSWeston Andros Adamson } else 18392031cd1aSWeston Andros Adamson encode_uint32(xdr, 0); /* implementation id array length=0 */ 184099fe60d0SBenny Halevy } 1841fc931582SAndy Adamson 1842fc931582SAndy Adamson static void encode_create_session(struct xdr_stream *xdr, 1843fcc85819SChristoph Hellwig const struct nfs41_create_session_args *args, 1844fc931582SAndy Adamson struct compound_hdr *hdr) 1845fc931582SAndy Adamson { 1846fc931582SAndy Adamson __be32 *p; 1847fc931582SAndy Adamson struct nfs_client *clp = args->client; 184889f0ff38STrond Myklebust struct rpc_clnt *clnt = clp->cl_rpcclient; 1849f092075dSChuck Lever struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); 18508e0d46e1SMike Sager u32 max_resp_sz_cached; 18518e0d46e1SMike Sager 18528e0d46e1SMike Sager /* 18538e0d46e1SMike Sager * Assumes OPEN is the biggest non-idempotent compound. 18548e0d46e1SMike Sager * 2 is the verifier. 18558e0d46e1SMike Sager */ 185635c036efSJ. Bruce Fields max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + 2) 185735c036efSJ. Bruce Fields * XDR_UNIT + RPC_MAX_AUTH_SIZE; 1858fc931582SAndy Adamson 1859475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr); 186089f0ff38STrond Myklebust p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12); 186179969dd1STrond Myklebust p = xdr_encode_hyper(p, args->clientid); 186279969dd1STrond Myklebust *p++ = cpu_to_be32(args->seqid); /*Sequence id */ 1863e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->flags); /*flags */ 1864fc931582SAndy Adamson 1865fc931582SAndy Adamson /* Fore Channel */ 1866c9c30dd5SBenny Halevy *p++ = cpu_to_be32(0); /* header padding size */ 1867e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ 1868e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ 18698e0d46e1SMike Sager *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ 1870e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */ 1871e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */ 1872e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ 1873fc931582SAndy Adamson 1874fc931582SAndy Adamson /* Back Channel */ 1875c9c30dd5SBenny Halevy *p++ = cpu_to_be32(0); /* header padding size */ 1876e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ 1877e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ 1878e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ 1879e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */ 1880e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */ 1881e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ 1882fc931582SAndy Adamson 1883e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->cb_program); /* cb_program */ 1884e75bc1c8SBenny Halevy *p++ = cpu_to_be32(1); 1885e75bc1c8SBenny Halevy *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ 1886fc931582SAndy Adamson 1887fc931582SAndy Adamson /* authsys_parms rfc1831 */ 18882f86e091SDeepa Dinamani *p++ = cpu_to_be32(ktime_to_ns(nn->boot_time)); /* stamp */ 188989f0ff38STrond Myklebust p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen); 1890e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* UID */ 1891e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* GID */ 189234558513SBenny Halevy *p = cpu_to_be32(0); /* No more gids */ 1893fc931582SAndy Adamson } 18940f3e66c6SAndy Adamson 18950f3e66c6SAndy Adamson static void encode_destroy_session(struct xdr_stream *xdr, 1896fcc85819SChristoph Hellwig const struct nfs4_session *session, 18970f3e66c6SAndy Adamson struct compound_hdr *hdr) 18980f3e66c6SAndy Adamson { 1899475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_DESTROY_SESSION, decode_destroy_session_maxsz, hdr); 1900475d4ba0STrond Myklebust encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); 19010f3e66c6SAndy Adamson } 190218019753SRicardo Labiaga 190366245539STrond Myklebust static void encode_destroy_clientid(struct xdr_stream *xdr, 190466245539STrond Myklebust uint64_t clientid, 190566245539STrond Myklebust struct compound_hdr *hdr) 190666245539STrond Myklebust { 190766245539STrond Myklebust encode_op_hdr(xdr, OP_DESTROY_CLIENTID, decode_destroy_clientid_maxsz, hdr); 190866245539STrond Myklebust encode_uint64(xdr, clientid); 190966245539STrond Myklebust } 191066245539STrond Myklebust 191118019753SRicardo Labiaga static void encode_reclaim_complete(struct xdr_stream *xdr, 1912fcc85819SChristoph Hellwig const struct nfs41_reclaim_complete_args *args, 191318019753SRicardo Labiaga struct compound_hdr *hdr) 191418019753SRicardo Labiaga { 1915475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_RECLAIM_COMPLETE, decode_reclaim_complete_maxsz, hdr); 1916475d4ba0STrond Myklebust encode_uint32(xdr, args->one_fs); 191718019753SRicardo Labiaga } 191899fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 191999fe60d0SBenny Halevy 19209b7b9fccSAndy Adamson static void encode_sequence(struct xdr_stream *xdr, 19219b7b9fccSAndy Adamson const struct nfs4_sequence_args *args, 19229b7b9fccSAndy Adamson struct compound_hdr *hdr) 19239b7b9fccSAndy Adamson { 19249b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 19252b2fa717STrond Myklebust struct nfs4_session *session; 1926fc01cea9SAndy Adamson struct nfs4_slot_table *tp; 19272b2fa717STrond Myklebust struct nfs4_slot *slot = args->sa_slot; 1928fc01cea9SAndy Adamson __be32 *p; 19299b7b9fccSAndy Adamson 19302b2fa717STrond Myklebust tp = slot->table; 19312b2fa717STrond Myklebust session = tp->session; 19323bd2384aSChuck Lever if (!session) 19333bd2384aSChuck Lever return; 1934fc01cea9SAndy Adamson 1935475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr); 1936fc01cea9SAndy Adamson 1937fc01cea9SAndy Adamson /* 1938fc01cea9SAndy Adamson * Sessionid + seqid + slotid + max slotid + cache_this 1939fc01cea9SAndy Adamson */ 1940fc01cea9SAndy Adamson dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d " 1941fc01cea9SAndy Adamson "max_slotid=%d cache_this=%d\n", 1942fc01cea9SAndy Adamson __func__, 1943fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[0], 1944fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[1], 1945fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[2], 1946fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[3], 19472b2fa717STrond Myklebust slot->seq_nr, slot->slot_nr, 1948fc01cea9SAndy Adamson tp->highest_used_slotid, args->sa_cache_this); 1949475d4ba0STrond Myklebust p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16); 195093f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); 1951e75bc1c8SBenny Halevy *p++ = cpu_to_be32(slot->seq_nr); 19522b2fa717STrond Myklebust *p++ = cpu_to_be32(slot->slot_nr); 1953e75bc1c8SBenny Halevy *p++ = cpu_to_be32(tp->highest_used_slotid); 195434558513SBenny Halevy *p = cpu_to_be32(args->sa_cache_this); 19559b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 19569b7b9fccSAndy Adamson } 19579b7b9fccSAndy Adamson 1958b1f69b75SAndy Adamson #ifdef CONFIG_NFS_V4_1 1959b1f69b75SAndy Adamson static void 1960b1f69b75SAndy Adamson encode_getdeviceinfo(struct xdr_stream *xdr, 1961b1f69b75SAndy Adamson const struct nfs4_getdeviceinfo_args *args, 1962b1f69b75SAndy Adamson struct compound_hdr *hdr) 1963b1f69b75SAndy Adamson { 1964b1f69b75SAndy Adamson __be32 *p; 1965b1f69b75SAndy Adamson 1966475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_GETDEVICEINFO, decode_getdeviceinfo_maxsz, hdr); 196784c9dee3SChristoph Hellwig p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 4 + 4); 1968b1f69b75SAndy Adamson p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, 1969b1f69b75SAndy Adamson NFS4_DEVICEID4_SIZE); 1970b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->pdev->layout_type); 1971f1c097beSAndy Adamson *p++ = cpu_to_be32(args->pdev->maxcount); /* gdia_maxcount */ 197284c9dee3SChristoph Hellwig 197384c9dee3SChristoph Hellwig p = reserve_space(xdr, 4 + 4); 197484c9dee3SChristoph Hellwig *p++ = cpu_to_be32(1); /* bitmap length */ 19754e590803STrond Myklebust *p++ = cpu_to_be32(args->notify_types); 1976b1f69b75SAndy Adamson } 1977b1f69b75SAndy Adamson 1978b1f69b75SAndy Adamson static void 1979b1f69b75SAndy Adamson encode_layoutget(struct xdr_stream *xdr, 1980b1f69b75SAndy Adamson const struct nfs4_layoutget_args *args, 1981b1f69b75SAndy Adamson struct compound_hdr *hdr) 1982b1f69b75SAndy Adamson { 1983b1f69b75SAndy Adamson __be32 *p; 1984b1f69b75SAndy Adamson 1985475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LAYOUTGET, decode_layoutget_maxsz, hdr); 1986475d4ba0STrond Myklebust p = reserve_space(xdr, 36); 1987b1f69b75SAndy Adamson *p++ = cpu_to_be32(0); /* Signal layout available */ 1988b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->type); 1989b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->range.iomode); 1990b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->range.offset); 1991b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->range.length); 1992b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->minlength); 1993ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 1994475d4ba0STrond Myklebust encode_uint32(xdr, args->maxcount); 1995b1f69b75SAndy Adamson 1996b1f69b75SAndy Adamson dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", 1997b1f69b75SAndy Adamson __func__, 1998b1f69b75SAndy Adamson args->type, 1999b1f69b75SAndy Adamson args->range.iomode, 2000b1f69b75SAndy Adamson (unsigned long)args->range.offset, 2001b1f69b75SAndy Adamson (unsigned long)args->range.length, 2002b1f69b75SAndy Adamson args->maxcount); 2003b1f69b75SAndy Adamson } 2004863a3c6cSAndy Adamson 2005863a3c6cSAndy Adamson static int 2006863a3c6cSAndy Adamson encode_layoutcommit(struct xdr_stream *xdr, 2007ac7db726SBenny Halevy struct inode *inode, 2008fcc85819SChristoph Hellwig const struct nfs4_layoutcommit_args *args, 2009863a3c6cSAndy Adamson struct compound_hdr *hdr) 2010863a3c6cSAndy Adamson { 2011863a3c6cSAndy Adamson __be32 *p; 2012863a3c6cSAndy Adamson 2013863a3c6cSAndy Adamson dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, 2014863a3c6cSAndy Adamson NFS_SERVER(args->inode)->pnfs_curr_ld->id); 2015863a3c6cSAndy Adamson 2016475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LAYOUTCOMMIT, decode_layoutcommit_maxsz, hdr); 2017475d4ba0STrond Myklebust p = reserve_space(xdr, 20); 2018863a3c6cSAndy Adamson /* Only whole file layouts */ 2019863a3c6cSAndy Adamson p = xdr_encode_hyper(p, 0); /* offset */ 20203557c6c3SPeng Tao p = xdr_encode_hyper(p, args->lastbytewritten + 1); /* length */ 2021ea9d23f5STrond Myklebust *p = cpu_to_be32(0); /* reclaim */ 2022ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 20232e18d4d8STrond Myklebust if (args->lastbytewritten != U64_MAX) { 2024ea9d23f5STrond Myklebust p = reserve_space(xdr, 20); 2025863a3c6cSAndy Adamson *p++ = cpu_to_be32(1); /* newoffset = TRUE */ 2026863a3c6cSAndy Adamson p = xdr_encode_hyper(p, args->lastbytewritten); 20272e18d4d8STrond Myklebust } else { 20282e18d4d8STrond Myklebust p = reserve_space(xdr, 12); 20292e18d4d8STrond Myklebust *p++ = cpu_to_be32(0); /* newoffset = FALSE */ 20302e18d4d8STrond Myklebust } 2031863a3c6cSAndy Adamson *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ 2032863a3c6cSAndy Adamson *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ 2033ac7db726SBenny Halevy 20345f919c9fSChristoph Hellwig encode_uint32(xdr, args->layoutupdate_len); 203573504740STrond Myklebust if (args->layoutupdate_pages) 20365f919c9fSChristoph Hellwig xdr_write_pages(xdr, args->layoutupdate_pages, 0, 20375f919c9fSChristoph Hellwig args->layoutupdate_len); 2038863a3c6cSAndy Adamson 2039863a3c6cSAndy Adamson return 0; 2040863a3c6cSAndy Adamson } 2041cbe82603SBenny Halevy 2042cbe82603SBenny Halevy static void 2043cbe82603SBenny Halevy encode_layoutreturn(struct xdr_stream *xdr, 2044cbe82603SBenny Halevy const struct nfs4_layoutreturn_args *args, 2045cbe82603SBenny Halevy struct compound_hdr *hdr) 2046cbe82603SBenny Halevy { 2047cbe82603SBenny Halevy __be32 *p; 2048cbe82603SBenny Halevy 2049475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_LAYOUTRETURN, decode_layoutreturn_maxsz, hdr); 2050475d4ba0STrond Myklebust p = reserve_space(xdr, 16); 2051cbe82603SBenny Halevy *p++ = cpu_to_be32(0); /* reclaim. always 0 for now */ 2052cbe82603SBenny Halevy *p++ = cpu_to_be32(args->layout_type); 205315eb67c1SPeng Tao *p++ = cpu_to_be32(args->range.iomode); 2054cbe82603SBenny Halevy *p = cpu_to_be32(RETURN_FILE); 2055ea9d23f5STrond Myklebust p = reserve_space(xdr, 16); 205615eb67c1SPeng Tao p = xdr_encode_hyper(p, args->range.offset); 205715eb67c1SPeng Tao p = xdr_encode_hyper(p, args->range.length); 2058cbe82603SBenny Halevy spin_lock(&args->inode->i_lock); 2059ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 2060cbe82603SBenny Halevy spin_unlock(&args->inode->i_lock); 20614d796d75STrond Myklebust if (args->ld_private->ops && args->ld_private->ops->encode) 20624d796d75STrond Myklebust args->ld_private->ops->encode(xdr, args, args->ld_private); 206394e5c571STrond Myklebust else 2064475d4ba0STrond Myklebust encode_uint32(xdr, 0); 2065cbe82603SBenny Halevy } 2066fca78d6dSBryan Schumaker 2067fca78d6dSBryan Schumaker static int 2068fca78d6dSBryan Schumaker encode_secinfo_no_name(struct xdr_stream *xdr, 2069fca78d6dSBryan Schumaker const struct nfs41_secinfo_no_name_args *args, 2070fca78d6dSBryan Schumaker struct compound_hdr *hdr) 2071fca78d6dSBryan Schumaker { 2072475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_SECINFO_NO_NAME, decode_secinfo_no_name_maxsz, hdr); 2073475d4ba0STrond Myklebust encode_uint32(xdr, args->style); 2074fca78d6dSBryan Schumaker return 0; 2075fca78d6dSBryan Schumaker } 20767d974794SBryan Schumaker 20777d974794SBryan Schumaker static void encode_test_stateid(struct xdr_stream *xdr, 2078fcc85819SChristoph Hellwig const struct nfs41_test_stateid_args *args, 20797d974794SBryan Schumaker struct compound_hdr *hdr) 20807d974794SBryan Schumaker { 2081475d4ba0STrond Myklebust encode_op_hdr(xdr, OP_TEST_STATEID, decode_test_stateid_maxsz, hdr); 2082475d4ba0STrond Myklebust encode_uint32(xdr, 1); 2083ea9d23f5STrond Myklebust encode_nfs4_stateid(xdr, args->stateid); 20847d974794SBryan Schumaker } 20859aeda35fSBryan Schumaker 20869aeda35fSBryan Schumaker static void encode_free_stateid(struct xdr_stream *xdr, 2087fcc85819SChristoph Hellwig const struct nfs41_free_stateid_args *args, 20889aeda35fSBryan Schumaker struct compound_hdr *hdr) 20899aeda35fSBryan Schumaker { 2090ab19b481STrond Myklebust encode_op_hdr(xdr, OP_FREE_STATEID, decode_free_stateid_maxsz, hdr); 20917c1d5faeSTrond Myklebust encode_nfs4_stateid(xdr, &args->stateid); 20929aeda35fSBryan Schumaker } 2093cf805165STrond Myklebust #else 2094cf805165STrond Myklebust static inline void 2095cf805165STrond Myklebust encode_layoutreturn(struct xdr_stream *xdr, 2096cf805165STrond Myklebust const struct nfs4_layoutreturn_args *args, 2097cf805165STrond Myklebust struct compound_hdr *hdr) 2098cf805165STrond Myklebust { 2099cf805165STrond Myklebust } 210056f487f8SFred Isaman 210156f487f8SFred Isaman static void 210256f487f8SFred Isaman encode_layoutget(struct xdr_stream *xdr, 210356f487f8SFred Isaman const struct nfs4_layoutget_args *args, 210456f487f8SFred Isaman struct compound_hdr *hdr) 210556f487f8SFred Isaman { 210656f487f8SFred Isaman } 2107b1f69b75SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 2108b1f69b75SAndy Adamson 21091da177e4SLinus Torvalds /* 21101da177e4SLinus Torvalds * END OF "GENERIC" ENCODE ROUTINES. 21111da177e4SLinus Torvalds */ 21121da177e4SLinus Torvalds 211366cc0429SBenny Halevy static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) 211466cc0429SBenny Halevy { 211566cc0429SBenny Halevy #if defined(CONFIG_NFS_V4_1) 21163bd2384aSChuck Lever struct nfs4_session *session = args->sa_slot->table->session; 21173bd2384aSChuck Lever if (session) 21183bd2384aSChuck Lever return session->clp->cl_mvops->minor_version; 211966cc0429SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 212066cc0429SBenny Halevy return 0; 212166cc0429SBenny Halevy } 212266cc0429SBenny Halevy 21231da177e4SLinus Torvalds /* 21241da177e4SLinus Torvalds * Encode an ACCESS request 21251da177e4SLinus Torvalds */ 21269f06c719SChuck Lever static void nfs4_xdr_enc_access(struct rpc_rqst *req, struct xdr_stream *xdr, 2127fcc85819SChristoph Hellwig const void *data) 21281da177e4SLinus Torvalds { 2129fcc85819SChristoph Hellwig const struct nfs4_accessargs *args = data; 21301da177e4SLinus Torvalds struct compound_hdr hdr = { 213166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21321da177e4SLinus Torvalds }; 21331da177e4SLinus Torvalds 21349f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21359f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21369f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21379f06c719SChuck Lever encode_access(xdr, args->access, &hdr); 21388bcbe7d9STrond Myklebust if (args->bitmask) 21399f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2140d017931cSAndy Adamson encode_nops(&hdr); 21411da177e4SLinus Torvalds } 21421da177e4SLinus Torvalds 21431da177e4SLinus Torvalds /* 21441da177e4SLinus Torvalds * Encode LOOKUP request 21451da177e4SLinus Torvalds */ 21469f06c719SChuck Lever static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr, 2147fcc85819SChristoph Hellwig const void *data) 21481da177e4SLinus Torvalds { 2149fcc85819SChristoph Hellwig const struct nfs4_lookup_arg *args = data; 21501da177e4SLinus Torvalds struct compound_hdr hdr = { 215166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21521da177e4SLinus Torvalds }; 21531da177e4SLinus Torvalds 21549f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21559f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21569f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 21579f06c719SChuck Lever encode_lookup(xdr, args->name, &hdr); 21589f06c719SChuck Lever encode_getfh(xdr, &hdr); 21599f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2160d017931cSAndy Adamson encode_nops(&hdr); 21611da177e4SLinus Torvalds } 21621da177e4SLinus Torvalds 21631da177e4SLinus Torvalds /* 21645b5faaf6SJeff Layton * Encode LOOKUPP request 21655b5faaf6SJeff Layton */ 21665b5faaf6SJeff Layton static void nfs4_xdr_enc_lookupp(struct rpc_rqst *req, struct xdr_stream *xdr, 21675b5faaf6SJeff Layton const void *data) 21685b5faaf6SJeff Layton { 21695b5faaf6SJeff Layton const struct nfs4_lookupp_arg *args = data; 21705b5faaf6SJeff Layton struct compound_hdr hdr = { 21715b5faaf6SJeff Layton .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21725b5faaf6SJeff Layton }; 21735b5faaf6SJeff Layton 21745b5faaf6SJeff Layton encode_compound_hdr(xdr, req, &hdr); 21755b5faaf6SJeff Layton encode_sequence(xdr, &args->seq_args, &hdr); 21765b5faaf6SJeff Layton encode_putfh(xdr, args->fh, &hdr); 21775b5faaf6SJeff Layton encode_lookupp(xdr, &hdr); 21785b5faaf6SJeff Layton encode_getfh(xdr, &hdr); 21795b5faaf6SJeff Layton encode_getfattr(xdr, args->bitmask, &hdr); 21805b5faaf6SJeff Layton encode_nops(&hdr); 21815b5faaf6SJeff Layton } 21825b5faaf6SJeff Layton 21835b5faaf6SJeff Layton /* 21841da177e4SLinus Torvalds * Encode LOOKUP_ROOT request 21851da177e4SLinus Torvalds */ 21869f06c719SChuck Lever static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, 21879f06c719SChuck Lever struct xdr_stream *xdr, 2188fcc85819SChristoph Hellwig const void *data) 21891da177e4SLinus Torvalds { 2190fcc85819SChristoph Hellwig const struct nfs4_lookup_root_arg *args = data; 21911da177e4SLinus Torvalds struct compound_hdr hdr = { 219266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21931da177e4SLinus Torvalds }; 21941da177e4SLinus Torvalds 21959f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21969f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21979f06c719SChuck Lever encode_putrootfh(xdr, &hdr); 21989f06c719SChuck Lever encode_getfh(xdr, &hdr); 21999f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2200d017931cSAndy Adamson encode_nops(&hdr); 22011da177e4SLinus Torvalds } 22021da177e4SLinus Torvalds 22031da177e4SLinus Torvalds /* 22041da177e4SLinus Torvalds * Encode REMOVE request 22051da177e4SLinus Torvalds */ 22069f06c719SChuck Lever static void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr, 2207fcc85819SChristoph Hellwig const void *data) 22081da177e4SLinus Torvalds { 2209fcc85819SChristoph Hellwig const struct nfs_removeargs *args = data; 22101da177e4SLinus Torvalds struct compound_hdr hdr = { 221166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22121da177e4SLinus Torvalds }; 22131da177e4SLinus Torvalds 22149f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22159f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22169f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22179f06c719SChuck Lever encode_remove(xdr, &args->name, &hdr); 2218d017931cSAndy Adamson encode_nops(&hdr); 22191da177e4SLinus Torvalds } 22201da177e4SLinus Torvalds 22211da177e4SLinus Torvalds /* 22221da177e4SLinus Torvalds * Encode RENAME request 22231da177e4SLinus Torvalds */ 22249f06c719SChuck Lever static void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr, 2225fcc85819SChristoph Hellwig const void *data) 22261da177e4SLinus Torvalds { 2227fcc85819SChristoph Hellwig const struct nfs_renameargs *args = data; 22281da177e4SLinus Torvalds struct compound_hdr hdr = { 222966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22301da177e4SLinus Torvalds }; 22311da177e4SLinus Torvalds 22329f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22339f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22349f06c719SChuck Lever encode_putfh(xdr, args->old_dir, &hdr); 22359f06c719SChuck Lever encode_savefh(xdr, &hdr); 22369f06c719SChuck Lever encode_putfh(xdr, args->new_dir, &hdr); 22379f06c719SChuck Lever encode_rename(xdr, args->old_name, args->new_name, &hdr); 2238d017931cSAndy Adamson encode_nops(&hdr); 22391da177e4SLinus Torvalds } 22401da177e4SLinus Torvalds 22411da177e4SLinus Torvalds /* 22421da177e4SLinus Torvalds * Encode LINK request 22431da177e4SLinus Torvalds */ 22449f06c719SChuck Lever static void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr, 2245fcc85819SChristoph Hellwig const void *data) 22461da177e4SLinus Torvalds { 2247fcc85819SChristoph Hellwig const struct nfs4_link_arg *args = data; 22481da177e4SLinus Torvalds struct compound_hdr hdr = { 224966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22501da177e4SLinus Torvalds }; 22511da177e4SLinus Torvalds 22529f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22539f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22549f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22559f06c719SChuck Lever encode_savefh(xdr, &hdr); 22569f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 22579f06c719SChuck Lever encode_link(xdr, args->name, &hdr); 22589f06c719SChuck Lever encode_restorefh(xdr, &hdr); 22599f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2260d017931cSAndy Adamson encode_nops(&hdr); 22611da177e4SLinus Torvalds } 22621da177e4SLinus Torvalds 22631da177e4SLinus Torvalds /* 22641da177e4SLinus Torvalds * Encode CREATE request 22651da177e4SLinus Torvalds */ 22669f06c719SChuck Lever static void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr, 2267fcc85819SChristoph Hellwig const void *data) 22681da177e4SLinus Torvalds { 2269fcc85819SChristoph Hellwig const struct nfs4_create_arg *args = data; 22701da177e4SLinus Torvalds struct compound_hdr hdr = { 227166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22721da177e4SLinus Torvalds }; 22731da177e4SLinus Torvalds 22749f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22759f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22769f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 22779f06c719SChuck Lever encode_create(xdr, args, &hdr); 22789f06c719SChuck Lever encode_getfh(xdr, &hdr); 22799f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2280d017931cSAndy Adamson encode_nops(&hdr); 22811da177e4SLinus Torvalds } 22821da177e4SLinus Torvalds 22831da177e4SLinus Torvalds /* 22841da177e4SLinus Torvalds * Encode SYMLINK request 22851da177e4SLinus Torvalds */ 22869f06c719SChuck Lever static void nfs4_xdr_enc_symlink(struct rpc_rqst *req, struct xdr_stream *xdr, 2287fcc85819SChristoph Hellwig const void *data) 22881da177e4SLinus Torvalds { 2289fcc85819SChristoph Hellwig const struct nfs4_create_arg *args = data; 2290fcc85819SChristoph Hellwig 22919f06c719SChuck Lever nfs4_xdr_enc_create(req, xdr, args); 22921da177e4SLinus Torvalds } 22931da177e4SLinus Torvalds 22941da177e4SLinus Torvalds /* 22951da177e4SLinus Torvalds * Encode GETATTR request 22961da177e4SLinus Torvalds */ 22979f06c719SChuck Lever static void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr, 2298fcc85819SChristoph Hellwig const void *data) 22991da177e4SLinus Torvalds { 2300fcc85819SChristoph Hellwig const struct nfs4_getattr_arg *args = data; 23011da177e4SLinus Torvalds struct compound_hdr hdr = { 230266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23031da177e4SLinus Torvalds }; 23041da177e4SLinus Torvalds 23059f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23069f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23079f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23089f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2309d017931cSAndy Adamson encode_nops(&hdr); 23101da177e4SLinus Torvalds } 23111da177e4SLinus Torvalds 23121da177e4SLinus Torvalds /* 23131da177e4SLinus Torvalds * Encode a CLOSE request 23141da177e4SLinus Torvalds */ 23159f06c719SChuck Lever static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr, 2316fcc85819SChristoph Hellwig const void *data) 23171da177e4SLinus Torvalds { 2318fcc85819SChristoph Hellwig const struct nfs_closeargs *args = data; 23191da177e4SLinus Torvalds struct compound_hdr hdr = { 232066cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23211da177e4SLinus Torvalds }; 23221da177e4SLinus Torvalds 23239f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23249f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23259f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 2326cf805165STrond Myklebust if (args->lr_args) 2327cf805165STrond Myklebust encode_layoutreturn(xdr, args->lr_args, &hdr); 23283ecefc92STrond Myklebust if (args->bitmask != NULL) 23299f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2330d8d84983STrond Myklebust encode_close(xdr, args, &hdr); 2331d017931cSAndy Adamson encode_nops(&hdr); 23321da177e4SLinus Torvalds } 23331da177e4SLinus Torvalds 23341da177e4SLinus Torvalds /* 23351da177e4SLinus Torvalds * Encode an OPEN request 23361da177e4SLinus Torvalds */ 23379f06c719SChuck Lever static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, 2338fcc85819SChristoph Hellwig const void *data) 23391da177e4SLinus Torvalds { 2340fcc85819SChristoph Hellwig const struct nfs_openargs *args = data; 23411da177e4SLinus Torvalds struct compound_hdr hdr = { 234266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23431da177e4SLinus Torvalds }; 23441da177e4SLinus Torvalds 23459f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23469f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23479f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23489f06c719SChuck Lever encode_open(xdr, args, &hdr); 23499f06c719SChuck Lever encode_getfh(xdr, &hdr); 2350ae2bb032SWeston Andros Adamson if (args->access) 23516168f62cSWeston Andros Adamson encode_access(xdr, args->access, &hdr); 23521549210fSTrond Myklebust encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); 235356f487f8SFred Isaman if (args->lg_args) { 235456f487f8SFred Isaman encode_layoutget(xdr, args->lg_args, &hdr); 2355cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0, 2356cf500bacSChuck Lever args->lg_args->layout.pglen, 23579ed5af26STrond Myklebust hdr.replen - pagepad_maxsz); 235856f487f8SFred Isaman } 2359d017931cSAndy Adamson encode_nops(&hdr); 23601da177e4SLinus Torvalds } 23611da177e4SLinus Torvalds 23621da177e4SLinus Torvalds /* 23631da177e4SLinus Torvalds * Encode an OPEN_CONFIRM request 23641da177e4SLinus Torvalds */ 23659f06c719SChuck Lever static void nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, 23669f06c719SChuck Lever struct xdr_stream *xdr, 2367fcc85819SChristoph Hellwig const void *data) 23681da177e4SLinus Torvalds { 2369fcc85819SChristoph Hellwig const struct nfs_open_confirmargs *args = data; 23701da177e4SLinus Torvalds struct compound_hdr hdr = { 2371d017931cSAndy Adamson .nops = 0, 23721da177e4SLinus Torvalds }; 23731da177e4SLinus Torvalds 23749f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23759f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23769f06c719SChuck Lever encode_open_confirm(xdr, args, &hdr); 2377d017931cSAndy Adamson encode_nops(&hdr); 23781da177e4SLinus Torvalds } 23791da177e4SLinus Torvalds 23801da177e4SLinus Torvalds /* 23811da177e4SLinus Torvalds * Encode an OPEN request with no attributes. 23821da177e4SLinus Torvalds */ 23839f06c719SChuck Lever static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, 23849f06c719SChuck Lever struct xdr_stream *xdr, 2385fcc85819SChristoph Hellwig const void *data) 23861da177e4SLinus Torvalds { 2387fcc85819SChristoph Hellwig const struct nfs_openargs *args = data; 23881da177e4SLinus Torvalds struct compound_hdr hdr = { 238966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23901da177e4SLinus Torvalds }; 23911da177e4SLinus Torvalds 23929f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23939f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23949f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23959f06c719SChuck Lever encode_open(xdr, args, &hdr); 2396ae2bb032SWeston Andros Adamson if (args->access) 23976168f62cSWeston Andros Adamson encode_access(xdr, args->access, &hdr); 2398e23008ecSAndy Adamson encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); 239956f487f8SFred Isaman if (args->lg_args) { 240056f487f8SFred Isaman encode_layoutget(xdr, args->lg_args, &hdr); 2401cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0, 2402cf500bacSChuck Lever args->lg_args->layout.pglen, 24039ed5af26STrond Myklebust hdr.replen - pagepad_maxsz); 240456f487f8SFred Isaman } 2405d017931cSAndy Adamson encode_nops(&hdr); 24061da177e4SLinus Torvalds } 24071da177e4SLinus Torvalds 24081da177e4SLinus Torvalds /* 24091da177e4SLinus Torvalds * Encode an OPEN_DOWNGRADE request 24101da177e4SLinus Torvalds */ 24119f06c719SChuck Lever static void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, 24129f06c719SChuck Lever struct xdr_stream *xdr, 2413fcc85819SChristoph Hellwig const void *data) 24141da177e4SLinus Torvalds { 2415fcc85819SChristoph Hellwig const struct nfs_closeargs *args = data; 24161da177e4SLinus Torvalds struct compound_hdr hdr = { 241766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24181da177e4SLinus Torvalds }; 24191da177e4SLinus Torvalds 24209f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24219f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24229f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 2423b6808145STrond Myklebust if (args->lr_args) 2424b6808145STrond Myklebust encode_layoutreturn(xdr, args->lr_args, &hdr); 24259f06c719SChuck Lever encode_open_downgrade(xdr, args, &hdr); 2426d017931cSAndy Adamson encode_nops(&hdr); 24271da177e4SLinus Torvalds } 24281da177e4SLinus Torvalds 24291da177e4SLinus Torvalds /* 24301da177e4SLinus Torvalds * Encode a LOCK request 24311da177e4SLinus Torvalds */ 24329f06c719SChuck Lever static void nfs4_xdr_enc_lock(struct rpc_rqst *req, struct xdr_stream *xdr, 2433fcc85819SChristoph Hellwig const void *data) 24341da177e4SLinus Torvalds { 2435fcc85819SChristoph Hellwig const struct nfs_lock_args *args = data; 24361da177e4SLinus Torvalds struct compound_hdr hdr = { 243766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24381da177e4SLinus Torvalds }; 24391da177e4SLinus Torvalds 24409f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24419f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24429f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24439f06c719SChuck Lever encode_lock(xdr, args, &hdr); 2444d017931cSAndy Adamson encode_nops(&hdr); 24451da177e4SLinus Torvalds } 24461da177e4SLinus Torvalds 24471da177e4SLinus Torvalds /* 24481da177e4SLinus Torvalds * Encode a LOCKT request 24491da177e4SLinus Torvalds */ 24509f06c719SChuck Lever static void nfs4_xdr_enc_lockt(struct rpc_rqst *req, struct xdr_stream *xdr, 2451fcc85819SChristoph Hellwig const void *data) 24521da177e4SLinus Torvalds { 2453fcc85819SChristoph Hellwig const struct nfs_lockt_args *args = data; 24541da177e4SLinus Torvalds struct compound_hdr hdr = { 245566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24561da177e4SLinus Torvalds }; 24571da177e4SLinus Torvalds 24589f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24599f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24609f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24619f06c719SChuck Lever encode_lockt(xdr, args, &hdr); 2462d017931cSAndy Adamson encode_nops(&hdr); 24631da177e4SLinus Torvalds } 24641da177e4SLinus Torvalds 24651da177e4SLinus Torvalds /* 24661da177e4SLinus Torvalds * Encode a LOCKU request 24671da177e4SLinus Torvalds */ 24689f06c719SChuck Lever static void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr, 2469fcc85819SChristoph Hellwig const void *data) 24701da177e4SLinus Torvalds { 2471fcc85819SChristoph Hellwig const struct nfs_locku_args *args = data; 24721da177e4SLinus Torvalds struct compound_hdr hdr = { 247366cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24741da177e4SLinus Torvalds }; 24751da177e4SLinus Torvalds 24769f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24779f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24789f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24799f06c719SChuck Lever encode_locku(xdr, args, &hdr); 2480d017931cSAndy Adamson encode_nops(&hdr); 24811da177e4SLinus Torvalds } 24821da177e4SLinus Torvalds 24839f06c719SChuck Lever static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, 24849f06c719SChuck Lever struct xdr_stream *xdr, 2485fcc85819SChristoph Hellwig const void *data) 2486d3c7b7ccSTrond Myklebust { 2487fcc85819SChristoph Hellwig const struct nfs_release_lockowner_args *args = data; 2488d3c7b7ccSTrond Myklebust struct compound_hdr hdr = { 2489d3c7b7ccSTrond Myklebust .minorversion = 0, 2490d3c7b7ccSTrond Myklebust }; 2491d3c7b7ccSTrond Myklebust 24929f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24939f06c719SChuck Lever encode_release_lockowner(xdr, &args->lock_owner, &hdr); 2494d3c7b7ccSTrond Myklebust encode_nops(&hdr); 2495d3c7b7ccSTrond Myklebust } 2496d3c7b7ccSTrond Myklebust 24971da177e4SLinus Torvalds /* 24981da177e4SLinus Torvalds * Encode a READLINK request 24991da177e4SLinus Torvalds */ 25009f06c719SChuck Lever static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr, 2501fcc85819SChristoph Hellwig const void *data) 25021da177e4SLinus Torvalds { 2503fcc85819SChristoph Hellwig const struct nfs4_readlink *args = data; 25041da177e4SLinus Torvalds struct compound_hdr hdr = { 250566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 25061da177e4SLinus Torvalds }; 25071da177e4SLinus Torvalds 25089f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25099f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25109f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 25119f06c719SChuck Lever encode_readlink(xdr, args, req, &hdr); 2512e3a535e1STrond Myklebust 2513cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->pages, args->pgbase, 25149ed5af26STrond Myklebust args->pglen, hdr.replen - pagepad_maxsz); 2515d017931cSAndy Adamson encode_nops(&hdr); 25161da177e4SLinus Torvalds } 25171da177e4SLinus Torvalds 25181da177e4SLinus Torvalds /* 25191da177e4SLinus Torvalds * Encode a READDIR request 25201da177e4SLinus Torvalds */ 25219f06c719SChuck Lever static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr, 2522fcc85819SChristoph Hellwig const void *data) 25231da177e4SLinus Torvalds { 2524fcc85819SChristoph Hellwig const struct nfs4_readdir_arg *args = data; 25251da177e4SLinus Torvalds struct compound_hdr hdr = { 252666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 25271da177e4SLinus Torvalds }; 25281da177e4SLinus Torvalds 25299f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25309f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25319f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 25329f06c719SChuck Lever encode_readdir(xdr, args, req, &hdr); 2533d6ac02dfSTrond Myklebust 2534cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->pages, args->pgbase, 25359ed5af26STrond Myklebust args->count, hdr.replen - pagepad_maxsz); 2536d017931cSAndy Adamson encode_nops(&hdr); 25371da177e4SLinus Torvalds } 25381da177e4SLinus Torvalds 25391da177e4SLinus Torvalds /* 25401da177e4SLinus Torvalds * Encode a READ request 25411da177e4SLinus Torvalds */ 25429f06c719SChuck Lever static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr, 2543fcc85819SChristoph Hellwig const void *data) 25441da177e4SLinus Torvalds { 2545fcc85819SChristoph Hellwig const struct nfs_pgio_args *args = data; 25461da177e4SLinus Torvalds struct compound_hdr hdr = { 254766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 25481da177e4SLinus Torvalds }; 25491da177e4SLinus Torvalds 25509f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25519f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25529f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 25539f06c719SChuck Lever encode_read(xdr, args, &hdr); 25541da177e4SLinus Torvalds 2555cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->pages, args->pgbase, 25569ed5af26STrond Myklebust args->count, hdr.replen - pagepad_maxsz); 25574f22ccc3S\"Talpey, Thomas\ req->rq_rcv_buf.flags |= XDRBUF_READ; 2558d017931cSAndy Adamson encode_nops(&hdr); 25591da177e4SLinus Torvalds } 25601da177e4SLinus Torvalds 25611da177e4SLinus Torvalds /* 25621da177e4SLinus Torvalds * Encode an SETATTR request 25631da177e4SLinus Torvalds */ 25649f06c719SChuck Lever static void nfs4_xdr_enc_setattr(struct rpc_rqst *req, struct xdr_stream *xdr, 2565fcc85819SChristoph Hellwig const void *data) 25661da177e4SLinus Torvalds { 2567fcc85819SChristoph Hellwig const struct nfs_setattrargs *args = data; 25681da177e4SLinus Torvalds struct compound_hdr hdr = { 256966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 25701da177e4SLinus Torvalds }; 25711da177e4SLinus Torvalds 25729f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25739f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25749f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 25759f06c719SChuck Lever encode_setattr(xdr, args, args->server, &hdr); 25769f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2577d017931cSAndy Adamson encode_nops(&hdr); 25781da177e4SLinus Torvalds } 25791da177e4SLinus Torvalds 25801da177e4SLinus Torvalds /* 2581029d105eSJ. Bruce Fields * Encode a GETACL request 2582029d105eSJ. Bruce Fields */ 25839f06c719SChuck Lever static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, 2584fcc85819SChristoph Hellwig const void *data) 2585029d105eSJ. Bruce Fields { 2586fcc85819SChristoph Hellwig const struct nfs_getaclargs *args = data; 2587029d105eSJ. Bruce Fields struct compound_hdr hdr = { 258866cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2589029d105eSJ. Bruce Fields }; 259037c88763STrond Myklebust const __u32 nfs4_acl_bitmap[1] = { 259137c88763STrond Myklebust [0] = FATTR4_WORD0_ACL, 259237c88763STrond Myklebust }; 259328f56694SBenny Halevy uint32_t replen; 2594029d105eSJ. Bruce Fields 25959f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25969f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25979f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 25986682c14bSJ. Bruce Fields replen = hdr.replen + op_decode_hdr_maxsz; 259937c88763STrond Myklebust encode_getattr(xdr, nfs4_acl_bitmap, NULL, 260037c88763STrond Myklebust ARRAY_SIZE(nfs4_acl_bitmap), &hdr); 2601cf8cdbe5SAndy Adamson 2602cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->acl_pages, 0, 26039ed5af26STrond Myklebust args->acl_len, replen); 2604d017931cSAndy Adamson encode_nops(&hdr); 2605029d105eSJ. Bruce Fields } 2606029d105eSJ. Bruce Fields 2607029d105eSJ. Bruce Fields /* 26081da177e4SLinus Torvalds * Encode a WRITE request 26091da177e4SLinus Torvalds */ 26109f06c719SChuck Lever static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr, 2611fcc85819SChristoph Hellwig const void *data) 26121da177e4SLinus Torvalds { 2613fcc85819SChristoph Hellwig const struct nfs_pgio_args *args = data; 26141da177e4SLinus Torvalds struct compound_hdr hdr = { 261566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26161da177e4SLinus Torvalds }; 26171da177e4SLinus Torvalds 26189f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26199f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26209f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 26219f06c719SChuck Lever encode_write(xdr, args, &hdr); 26224f22ccc3S\"Talpey, Thomas\ req->rq_snd_buf.flags |= XDRBUF_WRITE; 26237ffd1064SFred Isaman if (args->bitmask) 26249f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2625d017931cSAndy Adamson encode_nops(&hdr); 26261da177e4SLinus Torvalds } 26271da177e4SLinus Torvalds 26281da177e4SLinus Torvalds /* 26291da177e4SLinus Torvalds * a COMMIT request 26301da177e4SLinus Torvalds */ 26319f06c719SChuck Lever static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, 2632fcc85819SChristoph Hellwig const void *data) 26331da177e4SLinus Torvalds { 2634fcc85819SChristoph Hellwig const struct nfs_commitargs *args = data; 26351da177e4SLinus Torvalds struct compound_hdr hdr = { 263666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26371da177e4SLinus Torvalds }; 26381da177e4SLinus Torvalds 26399f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26409f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26419f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 26429f06c719SChuck Lever encode_commit(xdr, args, &hdr); 2643d017931cSAndy Adamson encode_nops(&hdr); 26441da177e4SLinus Torvalds } 26451da177e4SLinus Torvalds 26461da177e4SLinus Torvalds /* 26471da177e4SLinus Torvalds * FSINFO request 26481da177e4SLinus Torvalds */ 26499f06c719SChuck Lever static void nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, 2650fcc85819SChristoph Hellwig const void *data) 26511da177e4SLinus Torvalds { 2652fcc85819SChristoph Hellwig const struct nfs4_fsinfo_arg *args = data; 26531da177e4SLinus Torvalds struct compound_hdr hdr = { 265466cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26551da177e4SLinus Torvalds }; 26561da177e4SLinus Torvalds 26579f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26589f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26599f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 26609f06c719SChuck Lever encode_fsinfo(xdr, args->bitmask, &hdr); 2661d017931cSAndy Adamson encode_nops(&hdr); 26621da177e4SLinus Torvalds } 26631da177e4SLinus Torvalds 26641da177e4SLinus Torvalds /* 26651da177e4SLinus Torvalds * a PATHCONF request 26661da177e4SLinus Torvalds */ 26679f06c719SChuck Lever static void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, 2668fcc85819SChristoph Hellwig const void *data) 26691da177e4SLinus Torvalds { 2670fcc85819SChristoph Hellwig const struct nfs4_pathconf_arg *args = data; 26711da177e4SLinus Torvalds struct compound_hdr hdr = { 267266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26731da177e4SLinus Torvalds }; 26741da177e4SLinus Torvalds 26759f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26769f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26779f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 267837c88763STrond Myklebust encode_getattr(xdr, nfs4_pathconf_bitmap, args->bitmask, 267937c88763STrond Myklebust ARRAY_SIZE(nfs4_pathconf_bitmap), &hdr); 2680d017931cSAndy Adamson encode_nops(&hdr); 26811da177e4SLinus Torvalds } 26821da177e4SLinus Torvalds 26831da177e4SLinus Torvalds /* 26841da177e4SLinus Torvalds * a STATFS request 26851da177e4SLinus Torvalds */ 26869f06c719SChuck Lever static void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, 2687fcc85819SChristoph Hellwig const void *data) 26881da177e4SLinus Torvalds { 2689fcc85819SChristoph Hellwig const struct nfs4_statfs_arg *args = data; 26901da177e4SLinus Torvalds struct compound_hdr hdr = { 269166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26921da177e4SLinus Torvalds }; 26931da177e4SLinus Torvalds 26949f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26959f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26969f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 269737c88763STrond Myklebust encode_getattr(xdr, nfs4_statfs_bitmap, args->bitmask, 269837c88763STrond Myklebust ARRAY_SIZE(nfs4_statfs_bitmap), &hdr); 2699d017931cSAndy Adamson encode_nops(&hdr); 27001da177e4SLinus Torvalds } 27011da177e4SLinus Torvalds 27021da177e4SLinus Torvalds /* 27031da177e4SLinus Torvalds * GETATTR_BITMAP request 27041da177e4SLinus Torvalds */ 27059f06c719SChuck Lever static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req, 27069f06c719SChuck Lever struct xdr_stream *xdr, 2707fcc85819SChristoph Hellwig const void *data) 27081da177e4SLinus Torvalds { 2709fcc85819SChristoph Hellwig const struct nfs4_server_caps_arg *args = data; 27108c61282fSKinglong Mee const u32 *bitmask = args->bitmask; 27111da177e4SLinus Torvalds struct compound_hdr hdr = { 271266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 27131da177e4SLinus Torvalds }; 27141da177e4SLinus Torvalds 27159f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27169f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 27179f06c719SChuck Lever encode_putfh(xdr, args->fhandle, &hdr); 271837c88763STrond Myklebust encode_getattr(xdr, bitmask, NULL, 3, &hdr); 2719d017931cSAndy Adamson encode_nops(&hdr); 27201da177e4SLinus Torvalds } 27211da177e4SLinus Torvalds 27221da177e4SLinus Torvalds /* 27231da177e4SLinus Torvalds * a RENEW request 27241da177e4SLinus Torvalds */ 27259f06c719SChuck Lever static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr, 2726fcc85819SChristoph Hellwig const void *data) 2727fcc85819SChristoph Hellwig 27281da177e4SLinus Torvalds { 2729fcc85819SChristoph Hellwig const struct nfs_client *clp = data; 27301da177e4SLinus Torvalds struct compound_hdr hdr = { 2731d017931cSAndy Adamson .nops = 0, 27321da177e4SLinus Torvalds }; 27331da177e4SLinus Torvalds 27349f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 2735bb4dae5eSChuck Lever encode_renew(xdr, clp->cl_clientid, &hdr); 2736d017931cSAndy Adamson encode_nops(&hdr); 27371da177e4SLinus Torvalds } 27381da177e4SLinus Torvalds 27391da177e4SLinus Torvalds /* 27401da177e4SLinus Torvalds * a SETCLIENTID request 27411da177e4SLinus Torvalds */ 27429f06c719SChuck Lever static void nfs4_xdr_enc_setclientid(struct rpc_rqst *req, 27439f06c719SChuck Lever struct xdr_stream *xdr, 2744fcc85819SChristoph Hellwig const void *data) 27451da177e4SLinus Torvalds { 2746fcc85819SChristoph Hellwig const struct nfs4_setclientid *sc = data; 27471da177e4SLinus Torvalds struct compound_hdr hdr = { 2748d017931cSAndy Adamson .nops = 0, 27491da177e4SLinus Torvalds }; 27501da177e4SLinus Torvalds 27519f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27529f06c719SChuck Lever encode_setclientid(xdr, sc, &hdr); 2753d017931cSAndy Adamson encode_nops(&hdr); 27541da177e4SLinus Torvalds } 27551da177e4SLinus Torvalds 27561da177e4SLinus Torvalds /* 27571da177e4SLinus Torvalds * a SETCLIENTID_CONFIRM request 27581da177e4SLinus Torvalds */ 27599f06c719SChuck Lever static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, 27609f06c719SChuck Lever struct xdr_stream *xdr, 2761fcc85819SChristoph Hellwig const void *data) 27621da177e4SLinus Torvalds { 2763fcc85819SChristoph Hellwig const struct nfs4_setclientid_res *arg = data; 27641da177e4SLinus Torvalds struct compound_hdr hdr = { 2765d017931cSAndy Adamson .nops = 0, 27661da177e4SLinus Torvalds }; 27671da177e4SLinus Torvalds 27689f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27699f06c719SChuck Lever encode_setclientid_confirm(xdr, arg, &hdr); 2770d017931cSAndy Adamson encode_nops(&hdr); 27711da177e4SLinus Torvalds } 27721da177e4SLinus Torvalds 27731da177e4SLinus Torvalds /* 27741da177e4SLinus Torvalds * DELEGRETURN request 27751da177e4SLinus Torvalds */ 27769f06c719SChuck Lever static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, 27779f06c719SChuck Lever struct xdr_stream *xdr, 2778fcc85819SChristoph Hellwig const void *data) 27791da177e4SLinus Torvalds { 2780fcc85819SChristoph Hellwig const struct nfs4_delegreturnargs *args = data; 27811da177e4SLinus Torvalds struct compound_hdr hdr = { 278266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 27831da177e4SLinus Torvalds }; 27841da177e4SLinus Torvalds 27859f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27869f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 27879f06c719SChuck Lever encode_putfh(xdr, args->fhandle, &hdr); 2788586f1c39STrond Myklebust if (args->lr_args) 2789586f1c39STrond Myklebust encode_layoutreturn(xdr, args->lr_args, &hdr); 27908ac2b422STrond Myklebust if (args->bitmask) 27919f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2792e144cbccSTrond Myklebust encode_delegreturn(xdr, args->stateid, &hdr); 2793d017931cSAndy Adamson encode_nops(&hdr); 27941da177e4SLinus Torvalds } 27951da177e4SLinus Torvalds 27961da177e4SLinus Torvalds /* 2797683b57b4STrond Myklebust * Encode FS_LOCATIONS request 2798683b57b4STrond Myklebust */ 27999f06c719SChuck Lever static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, 28009f06c719SChuck Lever struct xdr_stream *xdr, 2801fcc85819SChristoph Hellwig const void *data) 2802683b57b4STrond Myklebust { 2803fcc85819SChristoph Hellwig const struct nfs4_fs_locations_arg *args = data; 2804683b57b4STrond Myklebust struct compound_hdr hdr = { 280566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2806683b57b4STrond Myklebust }; 280728f56694SBenny Halevy uint32_t replen; 2808683b57b4STrond Myklebust 28099f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 28109f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 2811b03d735bSChuck Lever if (args->migration) { 2812b03d735bSChuck Lever encode_putfh(xdr, args->fh, &hdr); 2813b03d735bSChuck Lever replen = hdr.replen; 2814b03d735bSChuck Lever encode_fs_locations(xdr, args->bitmask, &hdr); 2815b03d735bSChuck Lever if (args->renew) 2816b03d735bSChuck Lever encode_renew(xdr, args->clientid, &hdr); 2817b03d735bSChuck Lever } else { 28189f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 28199f06c719SChuck Lever encode_lookup(xdr, args->name, &hdr); 2820b03d735bSChuck Lever replen = hdr.replen; 28219f06c719SChuck Lever encode_fs_locations(xdr, args->bitmask, &hdr); 2822b03d735bSChuck Lever } 2823cf8cdbe5SAndy Adamson 2824cf500bacSChuck Lever rpc_prepare_reply_pages(req, (struct page **)&args->page, 0, 28259ed5af26STrond Myklebust PAGE_SIZE, replen); 2826d017931cSAndy Adamson encode_nops(&hdr); 2827683b57b4STrond Myklebust } 2828683b57b4STrond Myklebust 28295a5ea0d4SBryan Schumaker /* 28305a5ea0d4SBryan Schumaker * Encode SECINFO request 28315a5ea0d4SBryan Schumaker */ 28325a5ea0d4SBryan Schumaker static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req, 28335a5ea0d4SBryan Schumaker struct xdr_stream *xdr, 2834fcc85819SChristoph Hellwig const void *data) 28355a5ea0d4SBryan Schumaker { 2836fcc85819SChristoph Hellwig const struct nfs4_secinfo_arg *args = data; 28375a5ea0d4SBryan Schumaker struct compound_hdr hdr = { 28385a5ea0d4SBryan Schumaker .minorversion = nfs4_xdr_minorversion(&args->seq_args), 28395a5ea0d4SBryan Schumaker }; 28405a5ea0d4SBryan Schumaker 28415a5ea0d4SBryan Schumaker encode_compound_hdr(xdr, req, &hdr); 28425a5ea0d4SBryan Schumaker encode_sequence(xdr, &args->seq_args, &hdr); 28435a5ea0d4SBryan Schumaker encode_putfh(xdr, args->dir_fh, &hdr); 28445a5ea0d4SBryan Schumaker encode_secinfo(xdr, args->name, &hdr); 28455a5ea0d4SBryan Schumaker encode_nops(&hdr); 28465a5ea0d4SBryan Schumaker } 28475a5ea0d4SBryan Schumaker 284844c99933SChuck Lever /* 284944c99933SChuck Lever * Encode FSID_PRESENT request 285044c99933SChuck Lever */ 285144c99933SChuck Lever static void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req, 285244c99933SChuck Lever struct xdr_stream *xdr, 2853fcc85819SChristoph Hellwig const void *data) 285444c99933SChuck Lever { 2855fcc85819SChristoph Hellwig const struct nfs4_fsid_present_arg *args = data; 285644c99933SChuck Lever struct compound_hdr hdr = { 285744c99933SChuck Lever .minorversion = nfs4_xdr_minorversion(&args->seq_args), 285844c99933SChuck Lever }; 285944c99933SChuck Lever 286044c99933SChuck Lever encode_compound_hdr(xdr, req, &hdr); 286144c99933SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 286244c99933SChuck Lever encode_putfh(xdr, args->fh, &hdr); 286344c99933SChuck Lever encode_getfh(xdr, &hdr); 286444c99933SChuck Lever if (args->renew) 286544c99933SChuck Lever encode_renew(xdr, args->clientid, &hdr); 286644c99933SChuck Lever encode_nops(&hdr); 286744c99933SChuck Lever } 286844c99933SChuck Lever 286999fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 287099fe60d0SBenny Halevy /* 28717c44f1aeSWeston Andros Adamson * BIND_CONN_TO_SESSION request 28727c44f1aeSWeston Andros Adamson */ 28737c44f1aeSWeston Andros Adamson static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req, 28747c44f1aeSWeston Andros Adamson struct xdr_stream *xdr, 2875fcc85819SChristoph Hellwig const void *data) 28767c44f1aeSWeston Andros Adamson { 2877fcc85819SChristoph Hellwig const struct nfs41_bind_conn_to_session_args *args = data; 28787c44f1aeSWeston Andros Adamson struct compound_hdr hdr = { 287971a097c6STrond Myklebust .minorversion = args->client->cl_mvops->minor_version, 28807c44f1aeSWeston Andros Adamson }; 28817c44f1aeSWeston Andros Adamson 28827c44f1aeSWeston Andros Adamson encode_compound_hdr(xdr, req, &hdr); 288371a097c6STrond Myklebust encode_bind_conn_to_session(xdr, args, &hdr); 28847c44f1aeSWeston Andros Adamson encode_nops(&hdr); 28857c44f1aeSWeston Andros Adamson } 28867c44f1aeSWeston Andros Adamson 28877c44f1aeSWeston Andros Adamson /* 288899fe60d0SBenny Halevy * EXCHANGE_ID request 288999fe60d0SBenny Halevy */ 28909f06c719SChuck Lever static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, 28919f06c719SChuck Lever struct xdr_stream *xdr, 2892fcc85819SChristoph Hellwig const void *data) 289399fe60d0SBenny Halevy { 2894fcc85819SChristoph Hellwig const struct nfs41_exchange_id_args *args = data; 289599fe60d0SBenny Halevy struct compound_hdr hdr = { 2896a4432345STrond Myklebust .minorversion = args->client->cl_mvops->minor_version, 289799fe60d0SBenny Halevy }; 289899fe60d0SBenny Halevy 28999f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 29009f06c719SChuck Lever encode_exchange_id(xdr, args, &hdr); 290199fe60d0SBenny Halevy encode_nops(&hdr); 290299fe60d0SBenny Halevy } 29032050f0ccSAndy Adamson 29042050f0ccSAndy Adamson /* 2905fc931582SAndy Adamson * a CREATE_SESSION request 2906fc931582SAndy Adamson */ 29079f06c719SChuck Lever static void nfs4_xdr_enc_create_session(struct rpc_rqst *req, 29089f06c719SChuck Lever struct xdr_stream *xdr, 2909fcc85819SChristoph Hellwig const void *data) 2910fc931582SAndy Adamson { 2911fcc85819SChristoph Hellwig const struct nfs41_create_session_args *args = data; 2912fc931582SAndy Adamson struct compound_hdr hdr = { 2913a4432345STrond Myklebust .minorversion = args->client->cl_mvops->minor_version, 2914fc931582SAndy Adamson }; 2915fc931582SAndy Adamson 29169f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 29179f06c719SChuck Lever encode_create_session(xdr, args, &hdr); 2918fc931582SAndy Adamson encode_nops(&hdr); 2919fc931582SAndy Adamson } 2920fc931582SAndy Adamson 2921fc931582SAndy Adamson /* 29220f3e66c6SAndy Adamson * a DESTROY_SESSION request 29230f3e66c6SAndy Adamson */ 29249f06c719SChuck Lever static void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, 29259f06c719SChuck Lever struct xdr_stream *xdr, 2926fcc85819SChristoph Hellwig const void *data) 29270f3e66c6SAndy Adamson { 2928fcc85819SChristoph Hellwig const struct nfs4_session *session = data; 29290f3e66c6SAndy Adamson struct compound_hdr hdr = { 2930a4432345STrond Myklebust .minorversion = session->clp->cl_mvops->minor_version, 29310f3e66c6SAndy Adamson }; 29320f3e66c6SAndy Adamson 29339f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 29349f06c719SChuck Lever encode_destroy_session(xdr, session, &hdr); 29350f3e66c6SAndy Adamson encode_nops(&hdr); 29360f3e66c6SAndy Adamson } 29370f3e66c6SAndy Adamson 29380f3e66c6SAndy Adamson /* 293966245539STrond Myklebust * a DESTROY_CLIENTID request 294066245539STrond Myklebust */ 294166245539STrond Myklebust static void nfs4_xdr_enc_destroy_clientid(struct rpc_rqst *req, 294266245539STrond Myklebust struct xdr_stream *xdr, 2943fcc85819SChristoph Hellwig const void *data) 294466245539STrond Myklebust { 2945fcc85819SChristoph Hellwig const struct nfs_client *clp = data; 294666245539STrond Myklebust struct compound_hdr hdr = { 294766245539STrond Myklebust .minorversion = clp->cl_mvops->minor_version, 294866245539STrond Myklebust }; 294966245539STrond Myklebust 295066245539STrond Myklebust encode_compound_hdr(xdr, req, &hdr); 295166245539STrond Myklebust encode_destroy_clientid(xdr, clp->cl_clientid, &hdr); 295266245539STrond Myklebust encode_nops(&hdr); 295366245539STrond Myklebust } 295466245539STrond Myklebust 295566245539STrond Myklebust /* 2956fc01cea9SAndy Adamson * a SEQUENCE request 2957fc01cea9SAndy Adamson */ 29589f06c719SChuck Lever static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr, 2959fcc85819SChristoph Hellwig const void *data) 2960fc01cea9SAndy Adamson { 2961fcc85819SChristoph Hellwig const struct nfs4_sequence_args *args = data; 2962fc01cea9SAndy Adamson struct compound_hdr hdr = { 2963fc01cea9SAndy Adamson .minorversion = nfs4_xdr_minorversion(args), 2964fc01cea9SAndy Adamson }; 2965fc01cea9SAndy Adamson 29669f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 29679f06c719SChuck Lever encode_sequence(xdr, args, &hdr); 2968fc01cea9SAndy Adamson encode_nops(&hdr); 2969fc01cea9SAndy Adamson } 2970fc01cea9SAndy Adamson 29710efb01b2SDonald Buczek #endif 29720efb01b2SDonald Buczek 2973fc01cea9SAndy Adamson /* 29742050f0ccSAndy Adamson * a GET_LEASE_TIME request 29752050f0ccSAndy Adamson */ 29769f06c719SChuck Lever static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, 29779f06c719SChuck Lever struct xdr_stream *xdr, 2978fcc85819SChristoph Hellwig const void *data) 29792050f0ccSAndy Adamson { 2980fcc85819SChristoph Hellwig const struct nfs4_get_lease_time_args *args = data; 29812050f0ccSAndy Adamson struct compound_hdr hdr = { 29822050f0ccSAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->la_seq_args), 29832050f0ccSAndy Adamson }; 2984dae100c2SFred Isaman const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME }; 29852050f0ccSAndy Adamson 29869f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 29879f06c719SChuck Lever encode_sequence(xdr, &args->la_seq_args, &hdr); 29889f06c719SChuck Lever encode_putrootfh(xdr, &hdr); 29899f06c719SChuck Lever encode_fsinfo(xdr, lease_bitmap, &hdr); 29902050f0ccSAndy Adamson encode_nops(&hdr); 29912050f0ccSAndy Adamson } 299218019753SRicardo Labiaga 29930efb01b2SDonald Buczek #ifdef CONFIG_NFS_V4_1 29940efb01b2SDonald Buczek 299518019753SRicardo Labiaga /* 299618019753SRicardo Labiaga * a RECLAIM_COMPLETE request 299718019753SRicardo Labiaga */ 29989f06c719SChuck Lever static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, 29999f06c719SChuck Lever struct xdr_stream *xdr, 3000fcc85819SChristoph Hellwig const void *data) 300118019753SRicardo Labiaga { 3002fcc85819SChristoph Hellwig const struct nfs41_reclaim_complete_args *args = data; 300318019753SRicardo Labiaga struct compound_hdr hdr = { 300418019753SRicardo Labiaga .minorversion = nfs4_xdr_minorversion(&args->seq_args) 300518019753SRicardo Labiaga }; 300618019753SRicardo Labiaga 30079f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 30089f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 30099f06c719SChuck Lever encode_reclaim_complete(xdr, args, &hdr); 301018019753SRicardo Labiaga encode_nops(&hdr); 301118019753SRicardo Labiaga } 301218019753SRicardo Labiaga 3013b1f69b75SAndy Adamson /* 3014b1f69b75SAndy Adamson * Encode GETDEVICEINFO request 3015b1f69b75SAndy Adamson */ 30169f06c719SChuck Lever static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, 30179f06c719SChuck Lever struct xdr_stream *xdr, 3018fcc85819SChristoph Hellwig const void *data) 3019b1f69b75SAndy Adamson { 3020fcc85819SChristoph Hellwig const struct nfs4_getdeviceinfo_args *args = data; 3021b1f69b75SAndy Adamson struct compound_hdr hdr = { 3022b1f69b75SAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 3023b1f69b75SAndy Adamson }; 3024046e5ccbSTrond Myklebust uint32_t replen; 3025b1f69b75SAndy Adamson 30269f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 30279f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 3028046e5ccbSTrond Myklebust 30299ed5af26STrond Myklebust replen = hdr.replen + op_decode_hdr_maxsz + 2; 3030046e5ccbSTrond Myklebust 30319f06c719SChuck Lever encode_getdeviceinfo(xdr, args, &hdr); 3032b1f69b75SAndy Adamson 3033046e5ccbSTrond Myklebust /* set up reply kvec. device_addr4 opaque data is read into the 3034046e5ccbSTrond Myklebust * pages */ 3035cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->pdev->pages, args->pdev->pgbase, 30369ed5af26STrond Myklebust args->pdev->pglen, replen); 3037b1f69b75SAndy Adamson encode_nops(&hdr); 3038b1f69b75SAndy Adamson } 3039b1f69b75SAndy Adamson 3040b1f69b75SAndy Adamson /* 3041b1f69b75SAndy Adamson * Encode LAYOUTGET request 3042b1f69b75SAndy Adamson */ 30439f06c719SChuck Lever static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, 30449f06c719SChuck Lever struct xdr_stream *xdr, 3045fcc85819SChristoph Hellwig const void *data) 3046b1f69b75SAndy Adamson { 3047fcc85819SChristoph Hellwig const struct nfs4_layoutget_args *args = data; 3048b1f69b75SAndy Adamson struct compound_hdr hdr = { 3049b1f69b75SAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 3050b1f69b75SAndy Adamson }; 3051b1f69b75SAndy Adamson 30529f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 30539f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 30549f06c719SChuck Lever encode_putfh(xdr, NFS_FH(args->inode), &hdr); 30559f06c719SChuck Lever encode_layoutget(xdr, args, &hdr); 305635124a09SWeston Andros Adamson 3057cf500bacSChuck Lever rpc_prepare_reply_pages(req, args->layout.pages, 0, 30589ed5af26STrond Myklebust args->layout.pglen, hdr.replen - pagepad_maxsz); 3059b1f69b75SAndy Adamson encode_nops(&hdr); 3060b1f69b75SAndy Adamson } 3061863a3c6cSAndy Adamson 3062863a3c6cSAndy Adamson /* 3063863a3c6cSAndy Adamson * Encode LAYOUTCOMMIT request 3064863a3c6cSAndy Adamson */ 3065cbe82603SBenny Halevy static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, 3066863a3c6cSAndy Adamson struct xdr_stream *xdr, 3067fcc85819SChristoph Hellwig const void *priv) 3068863a3c6cSAndy Adamson { 3069fcc85819SChristoph Hellwig const struct nfs4_layoutcommit_args *args = priv; 3070ac7db726SBenny Halevy struct nfs4_layoutcommit_data *data = 3071ac7db726SBenny Halevy container_of(args, struct nfs4_layoutcommit_data, args); 3072863a3c6cSAndy Adamson struct compound_hdr hdr = { 3073863a3c6cSAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 3074863a3c6cSAndy Adamson }; 3075863a3c6cSAndy Adamson 3076863a3c6cSAndy Adamson encode_compound_hdr(xdr, req, &hdr); 3077863a3c6cSAndy Adamson encode_sequence(xdr, &args->seq_args, &hdr); 3078863a3c6cSAndy Adamson encode_putfh(xdr, NFS_FH(args->inode), &hdr); 3079ac7db726SBenny Halevy encode_layoutcommit(xdr, data->args.inode, args, &hdr); 3080863a3c6cSAndy Adamson encode_getfattr(xdr, args->bitmask, &hdr); 3081863a3c6cSAndy Adamson encode_nops(&hdr); 3082cbe82603SBenny Halevy } 3083cbe82603SBenny Halevy 3084cbe82603SBenny Halevy /* 3085cbe82603SBenny Halevy * Encode LAYOUTRETURN request 3086cbe82603SBenny Halevy */ 3087cbe82603SBenny Halevy static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req, 3088cbe82603SBenny Halevy struct xdr_stream *xdr, 3089fcc85819SChristoph Hellwig const void *data) 3090cbe82603SBenny Halevy { 3091fcc85819SChristoph Hellwig const struct nfs4_layoutreturn_args *args = data; 3092cbe82603SBenny Halevy struct compound_hdr hdr = { 3093cbe82603SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 3094cbe82603SBenny Halevy }; 3095cbe82603SBenny Halevy 3096cbe82603SBenny Halevy encode_compound_hdr(xdr, req, &hdr); 3097cbe82603SBenny Halevy encode_sequence(xdr, &args->seq_args, &hdr); 3098cbe82603SBenny Halevy encode_putfh(xdr, NFS_FH(args->inode), &hdr); 3099cbe82603SBenny Halevy encode_layoutreturn(xdr, args, &hdr); 3100cbe82603SBenny Halevy encode_nops(&hdr); 3101863a3c6cSAndy Adamson } 3102fca78d6dSBryan Schumaker 3103fca78d6dSBryan Schumaker /* 3104fca78d6dSBryan Schumaker * Encode SECINFO_NO_NAME request 3105fca78d6dSBryan Schumaker */ 3106fcc85819SChristoph Hellwig static void nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req, 3107fca78d6dSBryan Schumaker struct xdr_stream *xdr, 3108fcc85819SChristoph Hellwig const void *data) 3109fca78d6dSBryan Schumaker { 3110fcc85819SChristoph Hellwig const struct nfs41_secinfo_no_name_args *args = data; 3111fca78d6dSBryan Schumaker struct compound_hdr hdr = { 3112fca78d6dSBryan Schumaker .minorversion = nfs4_xdr_minorversion(&args->seq_args), 3113fca78d6dSBryan Schumaker }; 3114fca78d6dSBryan Schumaker 3115fca78d6dSBryan Schumaker encode_compound_hdr(xdr, req, &hdr); 3116fca78d6dSBryan Schumaker encode_sequence(xdr, &args->seq_args, &hdr); 3117fca78d6dSBryan Schumaker encode_putrootfh(xdr, &hdr); 3118fca78d6dSBryan Schumaker encode_secinfo_no_name(xdr, args, &hdr); 3119fca78d6dSBryan Schumaker encode_nops(&hdr); 3120fca78d6dSBryan Schumaker } 31217d974794SBryan Schumaker 31227d974794SBryan Schumaker /* 31237d974794SBryan Schumaker * Encode TEST_STATEID request 31247d974794SBryan Schumaker */ 31257d974794SBryan Schumaker static void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req, 31267d974794SBryan Schumaker struct xdr_stream *xdr, 3127fcc85819SChristoph Hellwig const void *data) 31287d974794SBryan Schumaker { 3129fcc85819SChristoph Hellwig const struct nfs41_test_stateid_args *args = data; 31307d974794SBryan Schumaker struct compound_hdr hdr = { 31317d974794SBryan Schumaker .minorversion = nfs4_xdr_minorversion(&args->seq_args), 31327d974794SBryan Schumaker }; 31337d974794SBryan Schumaker 31347d974794SBryan Schumaker encode_compound_hdr(xdr, req, &hdr); 31357d974794SBryan Schumaker encode_sequence(xdr, &args->seq_args, &hdr); 31367d974794SBryan Schumaker encode_test_stateid(xdr, args, &hdr); 31377d974794SBryan Schumaker encode_nops(&hdr); 31387d974794SBryan Schumaker } 31399aeda35fSBryan Schumaker 31409aeda35fSBryan Schumaker /* 31419aeda35fSBryan Schumaker * Encode FREE_STATEID request 31429aeda35fSBryan Schumaker */ 31439aeda35fSBryan Schumaker static void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req, 31449aeda35fSBryan Schumaker struct xdr_stream *xdr, 3145fcc85819SChristoph Hellwig const void *data) 31469aeda35fSBryan Schumaker { 3147fcc85819SChristoph Hellwig const struct nfs41_free_stateid_args *args = data; 31489aeda35fSBryan Schumaker struct compound_hdr hdr = { 31499aeda35fSBryan Schumaker .minorversion = nfs4_xdr_minorversion(&args->seq_args), 31509aeda35fSBryan Schumaker }; 31519aeda35fSBryan Schumaker 31529aeda35fSBryan Schumaker encode_compound_hdr(xdr, req, &hdr); 31539aeda35fSBryan Schumaker encode_sequence(xdr, &args->seq_args, &hdr); 31549aeda35fSBryan Schumaker encode_free_stateid(xdr, args, &hdr); 31559aeda35fSBryan Schumaker encode_nops(&hdr); 31569aeda35fSBryan Schumaker } 315799fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 315899fe60d0SBenny Halevy 3159683b57b4STrond Myklebust static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) 31601da177e4SLinus Torvalds { 31616da59ce2STrond Myklebust ssize_t ret = xdr_stream_decode_opaque_inline(xdr, (void **)string, 31626da59ce2STrond Myklebust NFS4_OPAQUE_LIMIT); 3163eb72f484SChuck Lever if (unlikely(ret < 0)) 3164c0eae66eSBenny Halevy return -EIO; 31656da59ce2STrond Myklebust *len = ret; 31666da59ce2STrond Myklebust return 0; 31676da59ce2STrond Myklebust } 31681da177e4SLinus Torvalds 31691da177e4SLinus Torvalds static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) 31701da177e4SLinus Torvalds { 31716659db4cSTrond Myklebust ssize_t ret; 31726659db4cSTrond Myklebust void *ptr; 31736659db4cSTrond Myklebust u32 tmp; 31741da177e4SLinus Torvalds 31756659db4cSTrond Myklebust if (xdr_stream_decode_u32(xdr, &tmp) < 0) 3176eb72f484SChuck Lever return -EIO; 31776659db4cSTrond Myklebust hdr->status = tmp; 31781da177e4SLinus Torvalds 31796659db4cSTrond Myklebust ret = xdr_stream_decode_opaque_inline(xdr, &ptr, NFS4_OPAQUE_LIMIT); 31806659db4cSTrond Myklebust if (ret < 0) 3181eb72f484SChuck Lever return -EIO; 31826659db4cSTrond Myklebust hdr->taglen = ret; 31836659db4cSTrond Myklebust hdr->tag = ptr; 31846659db4cSTrond Myklebust 31856659db4cSTrond Myklebust if (xdr_stream_decode_u32(xdr, &tmp) < 0) 31866659db4cSTrond Myklebust return -EIO; 31876659db4cSTrond Myklebust hdr->nops = tmp; 3188aadf6152SBenny Halevy if (unlikely(hdr->nops < 1)) 3189aadf6152SBenny Halevy return nfs4_stat_to_errno(hdr->status); 31901da177e4SLinus Torvalds return 0; 31911da177e4SLinus Torvalds } 31921da177e4SLinus Torvalds 3193c7848f69STrond Myklebust static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected, 3194c7848f69STrond Myklebust int *nfs_retval) 31951da177e4SLinus Torvalds { 31968687b63aSAl Viro __be32 *p; 31971da177e4SLinus Torvalds uint32_t opnum; 31981da177e4SLinus Torvalds int32_t nfserr; 31991da177e4SLinus Torvalds 3200c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3201c0eae66eSBenny Halevy if (unlikely(!p)) 3202c0eae66eSBenny Halevy goto out_overflow; 32036f723f77SBenny Halevy opnum = be32_to_cpup(p++); 3204c7848f69STrond Myklebust if (unlikely(opnum != expected)) 3205c7848f69STrond Myklebust goto out_bad_operation; 3206f23f6584SChuck Lever if (unlikely(*p != cpu_to_be32(NFS_OK))) 3207f23f6584SChuck Lever goto out_status; 3208c7848f69STrond Myklebust *nfs_retval = 0; 3209f23f6584SChuck Lever return true; 3210f23f6584SChuck Lever out_status: 3211f23f6584SChuck Lever nfserr = be32_to_cpup(p); 321262a92ba9SChuck Lever trace_nfs4_xdr_status(xdr, opnum, nfserr); 3213c7848f69STrond Myklebust *nfs_retval = nfs4_stat_to_errno(nfserr); 3214c7848f69STrond Myklebust return true; 3215c7848f69STrond Myklebust out_bad_operation: 3216da934ae0STrond Myklebust trace_nfs4_xdr_bad_operation(xdr, opnum, expected); 3217c7848f69STrond Myklebust *nfs_retval = -EREMOTEIO; 3218c7848f69STrond Myklebust return false; 3219c0eae66eSBenny Halevy out_overflow: 3220c7848f69STrond Myklebust *nfs_retval = -EIO; 3221c7848f69STrond Myklebust return false; 3222c7848f69STrond Myklebust } 3223c7848f69STrond Myklebust 3224c7848f69STrond Myklebust static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) 3225c7848f69STrond Myklebust { 3226c7848f69STrond Myklebust int retval; 3227c7848f69STrond Myklebust 3228c7848f69STrond Myklebust __decode_op_hdr(xdr, expected, &retval); 3229c7848f69STrond Myklebust return retval; 32301da177e4SLinus Torvalds } 32311da177e4SLinus Torvalds 32321da177e4SLinus Torvalds /* Dummy routine */ 32331bbe60ffSTrond Myklebust static int decode_ace(struct xdr_stream *xdr, void *ace) 32341da177e4SLinus Torvalds { 32358687b63aSAl Viro __be32 *p; 3236683b57b4STrond Myklebust unsigned int strlen; 32371da177e4SLinus Torvalds char *str; 32381da177e4SLinus Torvalds 3239c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 3240eb72f484SChuck Lever if (unlikely(!p)) 3241c0eae66eSBenny Halevy return -EIO; 3242eb72f484SChuck Lever return decode_opaque_inline(xdr, &strlen, &str); 32431da177e4SLinus Torvalds } 32441da177e4SLinus Torvalds 324537c88763STrond Myklebust static ssize_t 324637c88763STrond Myklebust decode_bitmap4(struct xdr_stream *xdr, uint32_t *bitmap, size_t sz) 32471da177e4SLinus Torvalds { 324837c88763STrond Myklebust ssize_t ret; 32491da177e4SLinus Torvalds 325037c88763STrond Myklebust ret = xdr_stream_decode_uint32_array(xdr, bitmap, sz); 325137c88763STrond Myklebust if (likely(ret >= 0)) 325237c88763STrond Myklebust return ret; 3253eb72f484SChuck Lever if (ret != -EMSGSIZE) 3254c0eae66eSBenny Halevy return -EIO; 3255eb72f484SChuck Lever return sz; 32561da177e4SLinus Torvalds } 32571da177e4SLinus Torvalds 325837c88763STrond Myklebust static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) 325937c88763STrond Myklebust { 326037c88763STrond Myklebust ssize_t ret; 326137c88763STrond Myklebust ret = decode_bitmap4(xdr, bitmap, 3); 326237c88763STrond Myklebust return ret < 0 ? ret : 0; 326337c88763STrond Myklebust } 326437c88763STrond Myklebust 3265256e48bbSTrond Myklebust static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigned int *savep) 32661da177e4SLinus Torvalds { 32678687b63aSAl Viro __be32 *p; 32681da177e4SLinus Torvalds 3269c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3270c0eae66eSBenny Halevy if (unlikely(!p)) 3271eb72f484SChuck Lever return -EIO; 3272cccddf4fSBenny Halevy *attrlen = be32_to_cpup(p); 3273256e48bbSTrond Myklebust *savep = xdr_stream_pos(xdr); 32741da177e4SLinus Torvalds return 0; 32751da177e4SLinus Torvalds } 32761da177e4SLinus Torvalds 32771da177e4SLinus Torvalds static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask) 32781da177e4SLinus Torvalds { 32791da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) { 32803388bff5SRoman Borisov int ret; 32813388bff5SRoman Borisov ret = decode_attr_bitmap(xdr, bitmask); 32823388bff5SRoman Borisov if (unlikely(ret < 0)) 32833388bff5SRoman Borisov return ret; 32841da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS; 32851da177e4SLinus Torvalds } else 3286dae100c2SFred Isaman bitmask[0] = bitmask[1] = bitmask[2] = 0; 3287dae100c2SFred Isaman dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__, 3288dae100c2SFred Isaman bitmask[0], bitmask[1], bitmask[2]); 32891da177e4SLinus Torvalds return 0; 32901da177e4SLinus Torvalds } 32911da177e4SLinus Torvalds 32921da177e4SLinus Torvalds static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type) 32931da177e4SLinus Torvalds { 32948687b63aSAl Viro __be32 *p; 3295409924e4STrond Myklebust int ret = 0; 32961da177e4SLinus Torvalds 32971da177e4SLinus Torvalds *type = 0; 32981da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U))) 32991da177e4SLinus Torvalds return -EIO; 33001da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) { 3301c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3302c0eae66eSBenny Halevy if (unlikely(!p)) 3303eb72f484SChuck Lever return -EIO; 3304cccddf4fSBenny Halevy *type = be32_to_cpup(p); 33051da177e4SLinus Torvalds if (*type < NF4REG || *type > NF4NAMEDATTR) { 33063110ff80SHarvey Harrison dprintk("%s: bad type %d\n", __func__, *type); 33071da177e4SLinus Torvalds return -EIO; 33081da177e4SLinus Torvalds } 33091da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_TYPE; 3310409924e4STrond Myklebust ret = NFS_ATTR_FATTR_TYPE; 33111da177e4SLinus Torvalds } 3312bca79478STrond Myklebust dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]); 3313409924e4STrond Myklebust return ret; 33141da177e4SLinus Torvalds } 33151da177e4SLinus Torvalds 3316264e6351SChuck Lever static int decode_attr_fh_expire_type(struct xdr_stream *xdr, 3317264e6351SChuck Lever uint32_t *bitmap, uint32_t *type) 3318264e6351SChuck Lever { 3319264e6351SChuck Lever __be32 *p; 3320264e6351SChuck Lever 3321264e6351SChuck Lever *type = 0; 3322264e6351SChuck Lever if (unlikely(bitmap[0] & (FATTR4_WORD0_FH_EXPIRE_TYPE - 1U))) 3323264e6351SChuck Lever return -EIO; 3324264e6351SChuck Lever if (likely(bitmap[0] & FATTR4_WORD0_FH_EXPIRE_TYPE)) { 3325264e6351SChuck Lever p = xdr_inline_decode(xdr, 4); 3326264e6351SChuck Lever if (unlikely(!p)) 3327eb72f484SChuck Lever return -EIO; 3328264e6351SChuck Lever *type = be32_to_cpup(p); 3329264e6351SChuck Lever bitmap[0] &= ~FATTR4_WORD0_FH_EXPIRE_TYPE; 3330264e6351SChuck Lever } 3331264e6351SChuck Lever dprintk("%s: expire type=0x%x\n", __func__, *type); 3332264e6351SChuck Lever return 0; 3333264e6351SChuck Lever } 3334264e6351SChuck Lever 33351da177e4SLinus Torvalds static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) 33361da177e4SLinus Torvalds { 33378687b63aSAl Viro __be32 *p; 3338409924e4STrond Myklebust int ret = 0; 33391da177e4SLinus Torvalds 33401da177e4SLinus Torvalds *change = 0; 33411da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U))) 33421da177e4SLinus Torvalds return -EIO; 33431da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) { 3344c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3345c0eae66eSBenny Halevy if (unlikely(!p)) 3346eb72f484SChuck Lever return -EIO; 3347cccddf4fSBenny Halevy xdr_decode_hyper(p, change); 33481da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_CHANGE; 3349409924e4STrond Myklebust ret = NFS_ATTR_FATTR_CHANGE; 33501da177e4SLinus Torvalds } 33513110ff80SHarvey Harrison dprintk("%s: change attribute=%Lu\n", __func__, 33521da177e4SLinus Torvalds (unsigned long long)*change); 3353409924e4STrond Myklebust return ret; 33541da177e4SLinus Torvalds } 33551da177e4SLinus Torvalds 33561da177e4SLinus Torvalds static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) 33571da177e4SLinus Torvalds { 33588687b63aSAl Viro __be32 *p; 3359409924e4STrond Myklebust int ret = 0; 33601da177e4SLinus Torvalds 33611da177e4SLinus Torvalds *size = 0; 33621da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U))) 33631da177e4SLinus Torvalds return -EIO; 33641da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) { 3365c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3366c0eae66eSBenny Halevy if (unlikely(!p)) 3367eb72f484SChuck Lever return -EIO; 3368cccddf4fSBenny Halevy xdr_decode_hyper(p, size); 33691da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SIZE; 3370409924e4STrond Myklebust ret = NFS_ATTR_FATTR_SIZE; 33711da177e4SLinus Torvalds } 33723110ff80SHarvey Harrison dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size); 3373409924e4STrond Myklebust return ret; 33741da177e4SLinus Torvalds } 33751da177e4SLinus Torvalds 33761da177e4SLinus Torvalds static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 33771da177e4SLinus Torvalds { 33788687b63aSAl Viro __be32 *p; 33791da177e4SLinus Torvalds 33801da177e4SLinus Torvalds *res = 0; 33811da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U))) 33821da177e4SLinus Torvalds return -EIO; 33831da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) { 3384c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3385c0eae66eSBenny Halevy if (unlikely(!p)) 3386eb72f484SChuck Lever return -EIO; 3387cccddf4fSBenny Halevy *res = be32_to_cpup(p); 33881da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT; 33891da177e4SLinus Torvalds } 33903110ff80SHarvey Harrison dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true"); 33911da177e4SLinus Torvalds return 0; 33921da177e4SLinus Torvalds } 33931da177e4SLinus Torvalds 33941da177e4SLinus Torvalds static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 33951da177e4SLinus Torvalds { 33968687b63aSAl Viro __be32 *p; 33971da177e4SLinus Torvalds 33981da177e4SLinus Torvalds *res = 0; 33991da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U))) 34001da177e4SLinus Torvalds return -EIO; 34011da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) { 3402c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3403c0eae66eSBenny Halevy if (unlikely(!p)) 3404eb72f484SChuck Lever return -EIO; 3405cccddf4fSBenny Halevy *res = be32_to_cpup(p); 34061da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT; 34071da177e4SLinus Torvalds } 34083110ff80SHarvey Harrison dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true"); 34091da177e4SLinus Torvalds return 0; 34101da177e4SLinus Torvalds } 34111da177e4SLinus Torvalds 34128b4bdcf8STrond Myklebust static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) 34131da177e4SLinus Torvalds { 34148687b63aSAl Viro __be32 *p; 3415409924e4STrond Myklebust int ret = 0; 34161da177e4SLinus Torvalds 34171da177e4SLinus Torvalds fsid->major = 0; 34181da177e4SLinus Torvalds fsid->minor = 0; 34191da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U))) 34201da177e4SLinus Torvalds return -EIO; 34211da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FSID)) { 3422c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 16); 3423c0eae66eSBenny Halevy if (unlikely(!p)) 3424eb72f484SChuck Lever return -EIO; 34253ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &fsid->major); 3426cccddf4fSBenny Halevy xdr_decode_hyper(p, &fsid->minor); 34271da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FSID; 3428409924e4STrond Myklebust ret = NFS_ATTR_FATTR_FSID; 34291da177e4SLinus Torvalds } 34303110ff80SHarvey Harrison dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__, 34311da177e4SLinus Torvalds (unsigned long long)fsid->major, 34321da177e4SLinus Torvalds (unsigned long long)fsid->minor); 3433409924e4STrond Myklebust return ret; 34341da177e4SLinus Torvalds } 34351da177e4SLinus Torvalds 34361da177e4SLinus Torvalds static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 34371da177e4SLinus Torvalds { 34388687b63aSAl Viro __be32 *p; 34391da177e4SLinus Torvalds 34401da177e4SLinus Torvalds *res = 60; 34411da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U))) 34421da177e4SLinus Torvalds return -EIO; 34431da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) { 3444c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3445c0eae66eSBenny Halevy if (unlikely(!p)) 3446eb72f484SChuck Lever return -EIO; 3447cccddf4fSBenny Halevy *res = be32_to_cpup(p); 34481da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME; 34491da177e4SLinus Torvalds } 34502eaf426dSDonald Buczek dprintk("%s: lease time=%u\n", __func__, (unsigned int)*res); 34511da177e4SLinus Torvalds return 0; 34521da177e4SLinus Torvalds } 34531da177e4SLinus Torvalds 3454ee7b75fcSTrond Myklebust static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res) 3455ae42c70aSBryan Schumaker { 3456ae42c70aSBryan Schumaker __be32 *p; 3457ae42c70aSBryan Schumaker 3458ae42c70aSBryan Schumaker if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U))) 3459ae42c70aSBryan Schumaker return -EIO; 3460ae42c70aSBryan Schumaker if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) { 3461ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, 4); 3462ae42c70aSBryan Schumaker if (unlikely(!p)) 3463eb72f484SChuck Lever return -EIO; 3464ae42c70aSBryan Schumaker bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; 3465ee7b75fcSTrond Myklebust *res = -be32_to_cpup(p); 3466ae42c70aSBryan Schumaker } 3467ae42c70aSBryan Schumaker return 0; 3468ae42c70aSBryan Schumaker } 3469ae42c70aSBryan Schumaker 34708c61282fSKinglong Mee static int decode_attr_exclcreat_supported(struct xdr_stream *xdr, 34718c61282fSKinglong Mee uint32_t *bitmap, uint32_t *bitmask) 34728c61282fSKinglong Mee { 34738c61282fSKinglong Mee if (likely(bitmap[2] & FATTR4_WORD2_SUPPATTR_EXCLCREAT)) { 34748c61282fSKinglong Mee int ret; 34758c61282fSKinglong Mee ret = decode_attr_bitmap(xdr, bitmask); 34768c61282fSKinglong Mee if (unlikely(ret < 0)) 34778c61282fSKinglong Mee return ret; 34788c61282fSKinglong Mee bitmap[2] &= ~FATTR4_WORD2_SUPPATTR_EXCLCREAT; 34798c61282fSKinglong Mee } else 34808c61282fSKinglong Mee bitmask[0] = bitmask[1] = bitmask[2] = 0; 34818c61282fSKinglong Mee dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__, 34828c61282fSKinglong Mee bitmask[0], bitmask[1], bitmask[2]); 34838c61282fSKinglong Mee return 0; 34848c61282fSKinglong Mee } 34858c61282fSKinglong Mee 3486ae42c70aSBryan Schumaker static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh) 3487ae42c70aSBryan Schumaker { 3488ae42c70aSBryan Schumaker __be32 *p; 348986bbd742SFrank Sorenson u32 len; 3490ae42c70aSBryan Schumaker 34917ad07353STrond Myklebust if (fh != NULL) 3492ae42c70aSBryan Schumaker memset(fh, 0, sizeof(*fh)); 3493ae42c70aSBryan Schumaker 3494ae42c70aSBryan Schumaker if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U))) 3495ae42c70aSBryan Schumaker return -EIO; 3496ae42c70aSBryan Schumaker if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) { 3497ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, 4); 3498ae42c70aSBryan Schumaker if (unlikely(!p)) 3499eb72f484SChuck Lever return -EIO; 3500ae42c70aSBryan Schumaker len = be32_to_cpup(p); 3501eb3d58c6STrond Myklebust if (len > NFS4_FHSIZE || len == 0) { 3502eb3d58c6STrond Myklebust trace_nfs4_xdr_bad_filehandle(xdr, OP_READDIR, 3503eb3d58c6STrond Myklebust NFS4ERR_BADHANDLE); 3504eb3d58c6STrond Myklebust return -EREMOTEIO; 3505eb3d58c6STrond Myklebust } 3506ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, len); 3507ae42c70aSBryan Schumaker if (unlikely(!p)) 3508eb72f484SChuck Lever return -EIO; 35097ad07353STrond Myklebust if (fh != NULL) { 3510ae42c70aSBryan Schumaker memcpy(fh->data, p, len); 35117ad07353STrond Myklebust fh->size = len; 35127ad07353STrond Myklebust } 3513ae42c70aSBryan Schumaker bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE; 3514ae42c70aSBryan Schumaker } 3515ae42c70aSBryan Schumaker return 0; 3516ae42c70aSBryan Schumaker } 3517ae42c70aSBryan Schumaker 35181da177e4SLinus Torvalds static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 35191da177e4SLinus Torvalds { 35208687b63aSAl Viro __be32 *p; 35211da177e4SLinus Torvalds 3522a1800acaSMalahal Naineni *res = 0; 35231da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U))) 35241da177e4SLinus Torvalds return -EIO; 35251da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { 3526c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3527c0eae66eSBenny Halevy if (unlikely(!p)) 3528eb72f484SChuck Lever return -EIO; 3529cccddf4fSBenny Halevy *res = be32_to_cpup(p); 35301da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT; 35311da177e4SLinus Torvalds } 35323110ff80SHarvey Harrison dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res); 35331da177e4SLinus Torvalds return 0; 35341da177e4SLinus Torvalds } 35351da177e4SLinus Torvalds 35361da177e4SLinus Torvalds static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) 35371da177e4SLinus Torvalds { 35388687b63aSAl Viro __be32 *p; 3539409924e4STrond Myklebust int ret = 0; 35401da177e4SLinus Torvalds 35411da177e4SLinus Torvalds *fileid = 0; 35421da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U))) 35431da177e4SLinus Torvalds return -EIO; 35441da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) { 3545c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3546c0eae66eSBenny Halevy if (unlikely(!p)) 3547eb72f484SChuck Lever return -EIO; 3548cccddf4fSBenny Halevy xdr_decode_hyper(p, fileid); 35491da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILEID; 3550409924e4STrond Myklebust ret = NFS_ATTR_FATTR_FILEID; 35511da177e4SLinus Torvalds } 35523110ff80SHarvey Harrison dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); 3553409924e4STrond Myklebust return ret; 35541da177e4SLinus Torvalds } 35551da177e4SLinus Torvalds 355699baf625SManoj Naik static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) 355799baf625SManoj Naik { 35588687b63aSAl Viro __be32 *p; 3559409924e4STrond Myklebust int ret = 0; 356099baf625SManoj Naik 356199baf625SManoj Naik *fileid = 0; 356299baf625SManoj Naik if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U))) 356399baf625SManoj Naik return -EIO; 356499baf625SManoj Naik if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) { 3565c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3566c0eae66eSBenny Halevy if (unlikely(!p)) 3567eb72f484SChuck Lever return -EIO; 3568cccddf4fSBenny Halevy xdr_decode_hyper(p, fileid); 356999baf625SManoj Naik bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; 357028331a46STrond Myklebust ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID; 357199baf625SManoj Naik } 35723110ff80SHarvey Harrison dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); 3573409924e4STrond Myklebust return ret; 357499baf625SManoj Naik } 357599baf625SManoj Naik 35761da177e4SLinus Torvalds static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 35771da177e4SLinus Torvalds { 35788687b63aSAl Viro __be32 *p; 35791da177e4SLinus Torvalds int status = 0; 35801da177e4SLinus Torvalds 35811da177e4SLinus Torvalds *res = 0; 35821da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U))) 35831da177e4SLinus Torvalds return -EIO; 35841da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) { 3585c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3586c0eae66eSBenny Halevy if (unlikely(!p)) 3587eb72f484SChuck Lever return -EIO; 3588cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 35891da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL; 35901da177e4SLinus Torvalds } 35913110ff80SHarvey Harrison dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res); 35921da177e4SLinus Torvalds return status; 35931da177e4SLinus Torvalds } 35941da177e4SLinus Torvalds 35951da177e4SLinus Torvalds static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 35961da177e4SLinus Torvalds { 35978687b63aSAl Viro __be32 *p; 35981da177e4SLinus Torvalds int status = 0; 35991da177e4SLinus Torvalds 36001da177e4SLinus Torvalds *res = 0; 36011da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U))) 36021da177e4SLinus Torvalds return -EIO; 36031da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) { 3604c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3605c0eae66eSBenny Halevy if (unlikely(!p)) 3606eb72f484SChuck Lever return -EIO; 3607cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 36081da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_FREE; 36091da177e4SLinus Torvalds } 36103110ff80SHarvey Harrison dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res); 36111da177e4SLinus Torvalds return status; 36121da177e4SLinus Torvalds } 36131da177e4SLinus Torvalds 36141da177e4SLinus Torvalds static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 36151da177e4SLinus Torvalds { 36168687b63aSAl Viro __be32 *p; 36171da177e4SLinus Torvalds int status = 0; 36181da177e4SLinus Torvalds 36191da177e4SLinus Torvalds *res = 0; 36201da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U))) 36211da177e4SLinus Torvalds return -EIO; 36221da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) { 3623c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3624c0eae66eSBenny Halevy if (unlikely(!p)) 3625eb72f484SChuck Lever return -EIO; 3626cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 36271da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL; 36281da177e4SLinus Torvalds } 36293110ff80SHarvey Harrison dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res); 36301da177e4SLinus Torvalds return status; 36311da177e4SLinus Torvalds } 36321da177e4SLinus Torvalds 36337aaa0b3bSManoj Naik static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) 36347aaa0b3bSManoj Naik { 3635464ad6b1SChuck Lever u32 n; 36368687b63aSAl Viro __be32 *p; 36377aaa0b3bSManoj Naik int status = 0; 36387aaa0b3bSManoj Naik 3639c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3640c0eae66eSBenny Halevy if (unlikely(!p)) 3641eb72f484SChuck Lever return -EIO; 3642cccddf4fSBenny Halevy n = be32_to_cpup(p); 364333a43f28SAndy Adamson if (n == 0) 364433a43f28SAndy Adamson goto root_path; 364502a2976cSChuck Lever dprintk("pathname4: "); 3646809b426cSTrond Myklebust if (n > NFS4_PATHNAME_MAXCOMPONENTS) { 3647809b426cSTrond Myklebust dprintk("cannot parse %d components in path\n", n); 3648809b426cSTrond Myklebust goto out_eio; 3649809b426cSTrond Myklebust } 3650809b426cSTrond Myklebust for (path->ncomponents = 0; path->ncomponents < n; path->ncomponents++) { 36517aaa0b3bSManoj Naik struct nfs4_string *component = &path->components[path->ncomponents]; 36527aaa0b3bSManoj Naik status = decode_opaque_inline(xdr, &component->len, &component->data); 36537aaa0b3bSManoj Naik if (unlikely(status != 0)) 36547aaa0b3bSManoj Naik goto out_eio; 365595a13f7bSTrond Myklebust ifdebug (XDR) 365602a2976cSChuck Lever pr_cont("%s%.*s ", 365702a2976cSChuck Lever (path->ncomponents != n ? "/ " : ""), 365802a2976cSChuck Lever component->len, component->data); 36597aaa0b3bSManoj Naik } 36607aaa0b3bSManoj Naik out: 36617aaa0b3bSManoj Naik return status; 366233a43f28SAndy Adamson root_path: 366333a43f28SAndy Adamson /* a root pathname is sent as a zero component4 */ 366433a43f28SAndy Adamson path->ncomponents = 1; 366533a43f28SAndy Adamson path->components[0].len=0; 366633a43f28SAndy Adamson path->components[0].data=NULL; 366702a2976cSChuck Lever dprintk("pathname4: /\n"); 366833a43f28SAndy Adamson goto out; 36697aaa0b3bSManoj Naik out_eio: 36707aaa0b3bSManoj Naik dprintk(" status %d", status); 36717aaa0b3bSManoj Naik status = -EIO; 36727aaa0b3bSManoj Naik goto out; 36737aaa0b3bSManoj Naik } 36747aaa0b3bSManoj Naik 36757aaa0b3bSManoj Naik static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) 3676683b57b4STrond Myklebust { 3677683b57b4STrond Myklebust int n; 36788687b63aSAl Viro __be32 *p; 3679683b57b4STrond Myklebust int status = -EIO; 3680683b57b4STrond Myklebust 3681683b57b4STrond Myklebust if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U))) 3682683b57b4STrond Myklebust goto out; 3683683b57b4STrond Myklebust status = 0; 3684683b57b4STrond Myklebust if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) 3685683b57b4STrond Myklebust goto out; 3686f54423a1SKinglong Mee bitmap[0] &= ~FATTR4_WORD0_FS_LOCATIONS; 36878b7e3f49STrond Myklebust status = -EIO; 36888b7e3f49STrond Myklebust /* Ignore borken servers that return unrequested attrs */ 36898b7e3f49STrond Myklebust if (unlikely(res == NULL)) 36908b7e3f49STrond Myklebust goto out; 369102a2976cSChuck Lever dprintk("%s: fsroot:\n", __func__); 36927aaa0b3bSManoj Naik status = decode_pathname(xdr, &res->fs_path); 3693683b57b4STrond Myklebust if (unlikely(status != 0)) 3694683b57b4STrond Myklebust goto out; 3695c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3696c0eae66eSBenny Halevy if (unlikely(!p)) 3697eb72f484SChuck Lever goto out_eio; 3698cccddf4fSBenny Halevy n = be32_to_cpup(p); 3699683b57b4STrond Myklebust if (n <= 0) 3700683b57b4STrond Myklebust goto out_eio; 3701809b426cSTrond Myklebust for (res->nlocations = 0; res->nlocations < n; res->nlocations++) { 3702464ad6b1SChuck Lever u32 m; 3703809b426cSTrond Myklebust struct nfs4_fs_location *loc; 3704683b57b4STrond Myklebust 3705809b426cSTrond Myklebust if (res->nlocations == NFS4_FS_LOCATIONS_MAXENTRIES) 3706809b426cSTrond Myklebust break; 3707809b426cSTrond Myklebust loc = &res->locations[res->nlocations]; 3708c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3709c0eae66eSBenny Halevy if (unlikely(!p)) 3710eb72f484SChuck Lever goto out_eio; 3711cccddf4fSBenny Halevy m = be32_to_cpup(p); 37127aaa0b3bSManoj Naik 371302a2976cSChuck Lever dprintk("%s: servers:\n", __func__); 3714809b426cSTrond Myklebust for (loc->nservers = 0; loc->nservers < m; loc->nservers++) { 3715809b426cSTrond Myklebust struct nfs4_string *server; 3716809b426cSTrond Myklebust 3717809b426cSTrond Myklebust if (loc->nservers == NFS4_FS_LOCATION_MAXSERVERS) { 3718464ad6b1SChuck Lever unsigned int i; 3719464ad6b1SChuck Lever dprintk("%s: using first %u of %u servers " 3720464ad6b1SChuck Lever "returned for location %u\n", 37213110ff80SHarvey Harrison __func__, 3722464ad6b1SChuck Lever NFS4_FS_LOCATION_MAXSERVERS, 3723464ad6b1SChuck Lever m, res->nlocations); 37247aaa0b3bSManoj Naik for (i = loc->nservers; i < m; i++) { 37252e42c3e2STrond Myklebust unsigned int len; 37267aaa0b3bSManoj Naik char *data; 37277aaa0b3bSManoj Naik status = decode_opaque_inline(xdr, &len, &data); 3728683b57b4STrond Myklebust if (unlikely(status != 0)) 3729683b57b4STrond Myklebust goto out_eio; 37307aaa0b3bSManoj Naik } 3731809b426cSTrond Myklebust break; 37327aaa0b3bSManoj Naik } 3733809b426cSTrond Myklebust server = &loc->servers[loc->nservers]; 3734809b426cSTrond Myklebust status = decode_opaque_inline(xdr, &server->len, &server->data); 3735809b426cSTrond Myklebust if (unlikely(status != 0)) 3736809b426cSTrond Myklebust goto out_eio; 3737809b426cSTrond Myklebust dprintk("%s ", server->data); 37387aaa0b3bSManoj Naik } 37397aaa0b3bSManoj Naik status = decode_pathname(xdr, &loc->rootpath); 37407aaa0b3bSManoj Naik if (unlikely(status != 0)) 37417aaa0b3bSManoj Naik goto out_eio; 3742683b57b4STrond Myklebust } 3743409924e4STrond Myklebust if (res->nlocations != 0) 374481934ddbSChuck Lever status = NFS_ATTR_FATTR_V4_LOCATIONS; 3745683b57b4STrond Myklebust out: 37463110ff80SHarvey Harrison dprintk("%s: fs_locations done, error = %d\n", __func__, status); 3747683b57b4STrond Myklebust return status; 3748683b57b4STrond Myklebust out_eio: 3749683b57b4STrond Myklebust status = -EIO; 3750683b57b4STrond Myklebust goto out; 3751683b57b4STrond Myklebust } 3752683b57b4STrond Myklebust 37531da177e4SLinus Torvalds static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 37541da177e4SLinus Torvalds { 37558687b63aSAl Viro __be32 *p; 37561da177e4SLinus Torvalds int status = 0; 37571da177e4SLinus Torvalds 37581da177e4SLinus Torvalds *res = 0; 37591da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U))) 37601da177e4SLinus Torvalds return -EIO; 37611da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) { 3762c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3763c0eae66eSBenny Halevy if (unlikely(!p)) 3764eb72f484SChuck Lever return -EIO; 3765cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 37661da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE; 37671da177e4SLinus Torvalds } 37683110ff80SHarvey Harrison dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res); 37691da177e4SLinus Torvalds return status; 37701da177e4SLinus Torvalds } 37711da177e4SLinus Torvalds 37721da177e4SLinus Torvalds static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink) 37731da177e4SLinus Torvalds { 37748687b63aSAl Viro __be32 *p; 37751da177e4SLinus Torvalds int status = 0; 37761da177e4SLinus Torvalds 37771da177e4SLinus Torvalds *maxlink = 1; 37781da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U))) 37791da177e4SLinus Torvalds return -EIO; 37801da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) { 3781c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3782c0eae66eSBenny Halevy if (unlikely(!p)) 3783eb72f484SChuck Lever return -EIO; 3784cccddf4fSBenny Halevy *maxlink = be32_to_cpup(p); 37851da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXLINK; 37861da177e4SLinus Torvalds } 37873110ff80SHarvey Harrison dprintk("%s: maxlink=%u\n", __func__, *maxlink); 37881da177e4SLinus Torvalds return status; 37891da177e4SLinus Torvalds } 37901da177e4SLinus Torvalds 37911da177e4SLinus Torvalds static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname) 37921da177e4SLinus Torvalds { 37938687b63aSAl Viro __be32 *p; 37941da177e4SLinus Torvalds int status = 0; 37951da177e4SLinus Torvalds 37961da177e4SLinus Torvalds *maxname = 1024; 37971da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U))) 37981da177e4SLinus Torvalds return -EIO; 37991da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) { 3800c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3801c0eae66eSBenny Halevy if (unlikely(!p)) 3802eb72f484SChuck Lever return -EIO; 3803cccddf4fSBenny Halevy *maxname = be32_to_cpup(p); 38041da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXNAME; 38051da177e4SLinus Torvalds } 38063110ff80SHarvey Harrison dprintk("%s: maxname=%u\n", __func__, *maxname); 38071da177e4SLinus Torvalds return status; 38081da177e4SLinus Torvalds } 38091da177e4SLinus Torvalds 38101da177e4SLinus Torvalds static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 38111da177e4SLinus Torvalds { 38128687b63aSAl Viro __be32 *p; 38131da177e4SLinus Torvalds int status = 0; 38141da177e4SLinus Torvalds 38151da177e4SLinus Torvalds *res = 1024; 38161da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U))) 38171da177e4SLinus Torvalds return -EIO; 38181da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) { 38191da177e4SLinus Torvalds uint64_t maxread; 3820c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3821c0eae66eSBenny Halevy if (unlikely(!p)) 3822eb72f484SChuck Lever return -EIO; 3823cccddf4fSBenny Halevy xdr_decode_hyper(p, &maxread); 38241da177e4SLinus Torvalds if (maxread > 0x7FFFFFFF) 38251da177e4SLinus Torvalds maxread = 0x7FFFFFFF; 38261da177e4SLinus Torvalds *res = (uint32_t)maxread; 38271da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXREAD; 38281da177e4SLinus Torvalds } 38293110ff80SHarvey Harrison dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res); 38301da177e4SLinus Torvalds return status; 38311da177e4SLinus Torvalds } 38321da177e4SLinus Torvalds 38331da177e4SLinus Torvalds static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 38341da177e4SLinus Torvalds { 38358687b63aSAl Viro __be32 *p; 38361da177e4SLinus Torvalds int status = 0; 38371da177e4SLinus Torvalds 38381da177e4SLinus Torvalds *res = 1024; 38391da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U))) 38401da177e4SLinus Torvalds return -EIO; 38411da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) { 38421da177e4SLinus Torvalds uint64_t maxwrite; 3843c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3844c0eae66eSBenny Halevy if (unlikely(!p)) 3845eb72f484SChuck Lever return -EIO; 3846cccddf4fSBenny Halevy xdr_decode_hyper(p, &maxwrite); 38471da177e4SLinus Torvalds if (maxwrite > 0x7FFFFFFF) 38481da177e4SLinus Torvalds maxwrite = 0x7FFFFFFF; 38491da177e4SLinus Torvalds *res = (uint32_t)maxwrite; 38501da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXWRITE; 38511da177e4SLinus Torvalds } 38523110ff80SHarvey Harrison dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res); 38531da177e4SLinus Torvalds return status; 38541da177e4SLinus Torvalds } 38551da177e4SLinus Torvalds 3856bca79478STrond Myklebust static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode) 38571da177e4SLinus Torvalds { 3858bca79478STrond Myklebust uint32_t tmp; 38598687b63aSAl Viro __be32 *p; 3860409924e4STrond Myklebust int ret = 0; 38611da177e4SLinus Torvalds 38621da177e4SLinus Torvalds *mode = 0; 38631da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U))) 38641da177e4SLinus Torvalds return -EIO; 38651da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_MODE)) { 3866c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3867c0eae66eSBenny Halevy if (unlikely(!p)) 3868eb72f484SChuck Lever return -EIO; 3869cccddf4fSBenny Halevy tmp = be32_to_cpup(p); 3870bca79478STrond Myklebust *mode = tmp & ~S_IFMT; 38711da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_MODE; 3872409924e4STrond Myklebust ret = NFS_ATTR_FATTR_MODE; 38731da177e4SLinus Torvalds } 38743110ff80SHarvey Harrison dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode); 3875409924e4STrond Myklebust return ret; 38761da177e4SLinus Torvalds } 38771da177e4SLinus Torvalds 38781da177e4SLinus Torvalds static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) 38791da177e4SLinus Torvalds { 38808687b63aSAl Viro __be32 *p; 3881409924e4STrond Myklebust int ret = 0; 38821da177e4SLinus Torvalds 38831da177e4SLinus Torvalds *nlink = 1; 38841da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U))) 38851da177e4SLinus Torvalds return -EIO; 38861da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) { 3887c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3888c0eae66eSBenny Halevy if (unlikely(!p)) 3889eb72f484SChuck Lever return -EIO; 3890cccddf4fSBenny Halevy *nlink = be32_to_cpup(p); 38911da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_NUMLINKS; 3892409924e4STrond Myklebust ret = NFS_ATTR_FATTR_NLINK; 38931da177e4SLinus Torvalds } 38943110ff80SHarvey Harrison dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink); 3895409924e4STrond Myklebust return ret; 38961da177e4SLinus Torvalds } 38971da177e4SLinus Torvalds 3898686a816aSTrond Myklebust static ssize_t decode_nfs4_string(struct xdr_stream *xdr, 3899686a816aSTrond Myklebust struct nfs4_string *name, gfp_t gfp_flags) 3900686a816aSTrond Myklebust { 3901686a816aSTrond Myklebust ssize_t ret; 3902686a816aSTrond Myklebust 3903686a816aSTrond Myklebust ret = xdr_stream_decode_string_dup(xdr, &name->data, 3904686a816aSTrond Myklebust XDR_MAX_NETOBJ, gfp_flags); 3905686a816aSTrond Myklebust name->len = 0; 3906686a816aSTrond Myklebust if (ret > 0) 3907686a816aSTrond Myklebust name->len = ret; 3908686a816aSTrond Myklebust return ret; 3909686a816aSTrond Myklebust } 3910686a816aSTrond Myklebust 391180e52aceSTrond Myklebust static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, 3912e5782076SEric W. Biederman const struct nfs_server *server, kuid_t *uid, 39136926afd1STrond Myklebust struct nfs4_string *owner_name) 39141da177e4SLinus Torvalds { 3915686a816aSTrond Myklebust ssize_t len; 3916686a816aSTrond Myklebust char *p; 39171da177e4SLinus Torvalds 3918e5782076SEric W. Biederman *uid = make_kuid(&init_user_ns, -2); 39191da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U))) 39201da177e4SLinus Torvalds return -EIO; 3921686a816aSTrond Myklebust if (!(bitmap[1] & FATTR4_WORD1_OWNER)) 3922686a816aSTrond Myklebust return 0; 39231da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_OWNER; 3924686a816aSTrond Myklebust 3925686a816aSTrond Myklebust if (owner_name != NULL) { 3926e8d8aa46STrond Myklebust len = decode_nfs4_string(xdr, owner_name, GFP_NOIO); 3927686a816aSTrond Myklebust if (len <= 0) 3928686a816aSTrond Myklebust goto out; 3929686a816aSTrond Myklebust dprintk("%s: name=%s\n", __func__, owner_name->data); 3930686a816aSTrond Myklebust return NFS_ATTR_FATTR_OWNER_NAME; 3931686a816aSTrond Myklebust } else { 3932686a816aSTrond Myklebust len = xdr_stream_decode_opaque_inline(xdr, (void **)&p, 3933686a816aSTrond Myklebust XDR_MAX_NETOBJ); 3934686a816aSTrond Myklebust if (len <= 0 || nfs_map_name_to_uid(server, p, len, uid) != 0) 3935686a816aSTrond Myklebust goto out; 3936e5782076SEric W. Biederman dprintk("%s: uid=%d\n", __func__, (int)from_kuid(&init_user_ns, *uid)); 3937686a816aSTrond Myklebust return NFS_ATTR_FATTR_OWNER; 3938686a816aSTrond Myklebust } 3939686a816aSTrond Myklebust out: 3940eb72f484SChuck Lever if (len == -EBADMSG) 3941c0eae66eSBenny Halevy return -EIO; 3942eb72f484SChuck Lever return 0; 39431da177e4SLinus Torvalds } 39441da177e4SLinus Torvalds 394580e52aceSTrond Myklebust static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, 3946e5782076SEric W. Biederman const struct nfs_server *server, kgid_t *gid, 39476926afd1STrond Myklebust struct nfs4_string *group_name) 39481da177e4SLinus Torvalds { 3949686a816aSTrond Myklebust ssize_t len; 3950686a816aSTrond Myklebust char *p; 39511da177e4SLinus Torvalds 3952e5782076SEric W. Biederman *gid = make_kgid(&init_user_ns, -2); 39531da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U))) 39541da177e4SLinus Torvalds return -EIO; 3955686a816aSTrond Myklebust if (!(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) 3956686a816aSTrond Myklebust return 0; 39571da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP; 3958686a816aSTrond Myklebust 3959686a816aSTrond Myklebust if (group_name != NULL) { 3960e8d8aa46STrond Myklebust len = decode_nfs4_string(xdr, group_name, GFP_NOIO); 3961686a816aSTrond Myklebust if (len <= 0) 3962686a816aSTrond Myklebust goto out; 3963686a816aSTrond Myklebust dprintk("%s: name=%s\n", __func__, group_name->data); 39646f1f6220SKinglong Mee return NFS_ATTR_FATTR_GROUP_NAME; 3965686a816aSTrond Myklebust } else { 3966686a816aSTrond Myklebust len = xdr_stream_decode_opaque_inline(xdr, (void **)&p, 3967686a816aSTrond Myklebust XDR_MAX_NETOBJ); 3968686a816aSTrond Myklebust if (len <= 0 || nfs_map_group_to_gid(server, p, len, gid) != 0) 3969686a816aSTrond Myklebust goto out; 3970e5782076SEric W. Biederman dprintk("%s: gid=%d\n", __func__, (int)from_kgid(&init_user_ns, *gid)); 3971686a816aSTrond Myklebust return NFS_ATTR_FATTR_GROUP; 3972686a816aSTrond Myklebust } 3973686a816aSTrond Myklebust out: 3974eb72f484SChuck Lever if (len == -EBADMSG) 3975c0eae66eSBenny Halevy return -EIO; 3976eb72f484SChuck Lever return 0; 39771da177e4SLinus Torvalds } 39781da177e4SLinus Torvalds 39791da177e4SLinus Torvalds static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) 39801da177e4SLinus Torvalds { 39818687b63aSAl Viro uint32_t major = 0, minor = 0; 39828687b63aSAl Viro __be32 *p; 3983409924e4STrond Myklebust int ret = 0; 39841da177e4SLinus Torvalds 39851da177e4SLinus Torvalds *rdev = MKDEV(0,0); 39861da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U))) 39871da177e4SLinus Torvalds return -EIO; 39881da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) { 39891da177e4SLinus Torvalds dev_t tmp; 39901da177e4SLinus Torvalds 3991c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3992c0eae66eSBenny Halevy if (unlikely(!p)) 3993eb72f484SChuck Lever return -EIO; 39946f723f77SBenny Halevy major = be32_to_cpup(p++); 3995cccddf4fSBenny Halevy minor = be32_to_cpup(p); 39961da177e4SLinus Torvalds tmp = MKDEV(major, minor); 39971da177e4SLinus Torvalds if (MAJOR(tmp) == major && MINOR(tmp) == minor) 39981da177e4SLinus Torvalds *rdev = tmp; 39991da177e4SLinus Torvalds bitmap[1] &= ~ FATTR4_WORD1_RAWDEV; 4000409924e4STrond Myklebust ret = NFS_ATTR_FATTR_RDEV; 40011da177e4SLinus Torvalds } 40023110ff80SHarvey Harrison dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor); 4003409924e4STrond Myklebust return ret; 40041da177e4SLinus Torvalds } 40051da177e4SLinus Torvalds 40061da177e4SLinus Torvalds static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 40071da177e4SLinus Torvalds { 40088687b63aSAl Viro __be32 *p; 40091da177e4SLinus Torvalds int status = 0; 40101da177e4SLinus Torvalds 40111da177e4SLinus Torvalds *res = 0; 40121da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U))) 40131da177e4SLinus Torvalds return -EIO; 40141da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) { 4015c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4016c0eae66eSBenny Halevy if (unlikely(!p)) 4017eb72f484SChuck Lever return -EIO; 4018cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 40191da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL; 40201da177e4SLinus Torvalds } 40213110ff80SHarvey Harrison dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res); 40221da177e4SLinus Torvalds return status; 40231da177e4SLinus Torvalds } 40241da177e4SLinus Torvalds 40251da177e4SLinus Torvalds static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 40261da177e4SLinus Torvalds { 40278687b63aSAl Viro __be32 *p; 40281da177e4SLinus Torvalds int status = 0; 40291da177e4SLinus Torvalds 40301da177e4SLinus Torvalds *res = 0; 40311da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U))) 40321da177e4SLinus Torvalds return -EIO; 40331da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) { 4034c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4035c0eae66eSBenny Halevy if (unlikely(!p)) 4036eb72f484SChuck Lever return -EIO; 4037cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 40381da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE; 40391da177e4SLinus Torvalds } 40403110ff80SHarvey Harrison dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res); 40411da177e4SLinus Torvalds return status; 40421da177e4SLinus Torvalds } 40431da177e4SLinus Torvalds 40441da177e4SLinus Torvalds static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 40451da177e4SLinus Torvalds { 40468687b63aSAl Viro __be32 *p; 40471da177e4SLinus Torvalds int status = 0; 40481da177e4SLinus Torvalds 40491da177e4SLinus Torvalds *res = 0; 40501da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U))) 40511da177e4SLinus Torvalds return -EIO; 40521da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) { 4053c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4054c0eae66eSBenny Halevy if (unlikely(!p)) 4055eb72f484SChuck Lever return -EIO; 4056cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 40571da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL; 40581da177e4SLinus Torvalds } 40593110ff80SHarvey Harrison dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res); 40601da177e4SLinus Torvalds return status; 40611da177e4SLinus Torvalds } 40621da177e4SLinus Torvalds 40631da177e4SLinus Torvalds static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) 40641da177e4SLinus Torvalds { 40658687b63aSAl Viro __be32 *p; 4066409924e4STrond Myklebust int ret = 0; 40671da177e4SLinus Torvalds 40681da177e4SLinus Torvalds *used = 0; 40691da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U))) 40701da177e4SLinus Torvalds return -EIO; 40711da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) { 4072c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4073c0eae66eSBenny Halevy if (unlikely(!p)) 4074eb72f484SChuck Lever return -EIO; 4075cccddf4fSBenny Halevy xdr_decode_hyper(p, used); 40761da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_USED; 4077409924e4STrond Myklebust ret = NFS_ATTR_FATTR_SPACE_USED; 40781da177e4SLinus Torvalds } 40793110ff80SHarvey Harrison dprintk("%s: space used=%Lu\n", __func__, 40801da177e4SLinus Torvalds (unsigned long long)*used); 4081409924e4STrond Myklebust return ret; 40821da177e4SLinus Torvalds } 40831da177e4SLinus Torvalds 408436b3743fSTrond Myklebust static __be32 * 4085e86d5a02STrond Myklebust xdr_decode_nfstime4(__be32 *p, struct timespec64 *t) 408636b3743fSTrond Myklebust { 408736b3743fSTrond Myklebust __u64 sec; 408836b3743fSTrond Myklebust 408936b3743fSTrond Myklebust p = xdr_decode_hyper(p, &sec); 4090e86d5a02STrond Myklebust t-> tv_sec = sec; 409136b3743fSTrond Myklebust t->tv_nsec = be32_to_cpup(p++); 409236b3743fSTrond Myklebust return p; 409336b3743fSTrond Myklebust } 409436b3743fSTrond Myklebust 4095e86d5a02STrond Myklebust static int decode_attr_time(struct xdr_stream *xdr, struct timespec64 *time) 40961da177e4SLinus Torvalds { 40978687b63aSAl Viro __be32 *p; 40981da177e4SLinus Torvalds 409936b3743fSTrond Myklebust p = xdr_inline_decode(xdr, nfstime4_maxsz << 2); 4100c0eae66eSBenny Halevy if (unlikely(!p)) 4101eb72f484SChuck Lever return -EIO; 410236b3743fSTrond Myklebust xdr_decode_nfstime4(p, time); 41031da177e4SLinus Torvalds return 0; 41041da177e4SLinus Torvalds } 41051da177e4SLinus Torvalds 4106e86d5a02STrond Myklebust static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time) 41071da177e4SLinus Torvalds { 41081da177e4SLinus Torvalds int status = 0; 41091da177e4SLinus Torvalds 41101da177e4SLinus Torvalds time->tv_sec = 0; 41111da177e4SLinus Torvalds time->tv_nsec = 0; 41121da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U))) 41131da177e4SLinus Torvalds return -EIO; 41141da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) { 41151da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 4116409924e4STrond Myklebust if (status == 0) 4117409924e4STrond Myklebust status = NFS_ATTR_FATTR_ATIME; 41181da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS; 41191da177e4SLinus Torvalds } 4120ae08483cSArnd Bergmann dprintk("%s: atime=%lld\n", __func__, time->tv_sec); 41211da177e4SLinus Torvalds return status; 41221da177e4SLinus Torvalds } 41231da177e4SLinus Torvalds 4124e86d5a02STrond Myklebust static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time) 41251da177e4SLinus Torvalds { 41261da177e4SLinus Torvalds int status = 0; 41271da177e4SLinus Torvalds 41281da177e4SLinus Torvalds time->tv_sec = 0; 41291da177e4SLinus Torvalds time->tv_nsec = 0; 41301da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U))) 41311da177e4SLinus Torvalds return -EIO; 41321da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) { 41331da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 4134409924e4STrond Myklebust if (status == 0) 4135409924e4STrond Myklebust status = NFS_ATTR_FATTR_CTIME; 41361da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA; 41371da177e4SLinus Torvalds } 4138ae08483cSArnd Bergmann dprintk("%s: ctime=%lld\n", __func__, time->tv_sec); 41391da177e4SLinus Torvalds return status; 41401da177e4SLinus Torvalds } 41411da177e4SLinus Torvalds 414255b6e774SRicardo Labiaga static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, 4143e86d5a02STrond Myklebust struct timespec64 *time) 414455b6e774SRicardo Labiaga { 414555b6e774SRicardo Labiaga int status = 0; 414655b6e774SRicardo Labiaga 414755b6e774SRicardo Labiaga time->tv_sec = 0; 414855b6e774SRicardo Labiaga time->tv_nsec = 0; 414955b6e774SRicardo Labiaga if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U))) 415055b6e774SRicardo Labiaga return -EIO; 415155b6e774SRicardo Labiaga if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) { 415255b6e774SRicardo Labiaga status = decode_attr_time(xdr, time); 415355b6e774SRicardo Labiaga bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA; 415455b6e774SRicardo Labiaga } 4155ae08483cSArnd Bergmann dprintk("%s: time_delta=%lld %ld\n", __func__, time->tv_sec, 4156ae08483cSArnd Bergmann time->tv_nsec); 415755b6e774SRicardo Labiaga return status; 415855b6e774SRicardo Labiaga } 415955b6e774SRicardo Labiaga 4160aa9c2669SDavid Quigley static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, 4161aa9c2669SDavid Quigley struct nfs4_label *label) 4162aa9c2669SDavid Quigley { 4163aa9c2669SDavid Quigley uint32_t pi = 0; 4164aa9c2669SDavid Quigley uint32_t lfs = 0; 4165aa9c2669SDavid Quigley __u32 len; 4166aa9c2669SDavid Quigley __be32 *p; 4167aa9c2669SDavid Quigley int status = 0; 4168aa9c2669SDavid Quigley 4169aa9c2669SDavid Quigley if (unlikely(bitmap[2] & (FATTR4_WORD2_SECURITY_LABEL - 1U))) 4170aa9c2669SDavid Quigley return -EIO; 4171aa9c2669SDavid Quigley if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) { 4172aa9c2669SDavid Quigley p = xdr_inline_decode(xdr, 4); 4173aa9c2669SDavid Quigley if (unlikely(!p)) 4174eb72f484SChuck Lever return -EIO; 4175aa9c2669SDavid Quigley lfs = be32_to_cpup(p++); 4176aa9c2669SDavid Quigley p = xdr_inline_decode(xdr, 4); 4177aa9c2669SDavid Quigley if (unlikely(!p)) 4178eb72f484SChuck Lever return -EIO; 4179aa9c2669SDavid Quigley pi = be32_to_cpup(p++); 4180aa9c2669SDavid Quigley p = xdr_inline_decode(xdr, 4); 4181aa9c2669SDavid Quigley if (unlikely(!p)) 4182eb72f484SChuck Lever return -EIO; 4183aa9c2669SDavid Quigley len = be32_to_cpup(p++); 4184aa9c2669SDavid Quigley p = xdr_inline_decode(xdr, len); 4185aa9c2669SDavid Quigley if (unlikely(!p)) 4186eb72f484SChuck Lever return -EIO; 4187aa9c2669SDavid Quigley if (len < NFS4_MAXLABELLEN) { 4188aa9c2669SDavid Quigley if (label) { 4189b4487b93SJeffrey Mitchell if (label->len) { 4190b4487b93SJeffrey Mitchell if (label->len < len) 4191b4487b93SJeffrey Mitchell return -ERANGE; 4192aa9c2669SDavid Quigley memcpy(label->label, p, len); 4193b4487b93SJeffrey Mitchell } 4194aa9c2669SDavid Quigley label->len = len; 4195aa9c2669SDavid Quigley label->pi = pi; 4196aa9c2669SDavid Quigley label->lfs = lfs; 4197aa9c2669SDavid Quigley status = NFS_ATTR_FATTR_V4_SECURITY_LABEL; 4198aa9c2669SDavid Quigley } 4199aa9c2669SDavid Quigley bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; 4200aa9c2669SDavid Quigley } else 4201aa9c2669SDavid Quigley printk(KERN_WARNING "%s: label too long (%u)!\n", 4202aa9c2669SDavid Quigley __func__, len); 4203aa9c2669SDavid Quigley if (label && label->label) 4204*2c52c837SOlga Kornievskaia dprintk("%s: label=%.*s, len=%d, PI=%d, LFS=%d\n", 4205*2c52c837SOlga Kornievskaia __func__, label->len, (char *)label->label, 4206*2c52c837SOlga Kornievskaia label->len, label->pi, label->lfs); 4207*2c52c837SOlga Kornievskaia } 4208aa9c2669SDavid Quigley return status; 4209aa9c2669SDavid Quigley } 4210aa9c2669SDavid Quigley 4211e86d5a02STrond Myklebust static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time) 42121da177e4SLinus Torvalds { 42131da177e4SLinus Torvalds int status = 0; 42141da177e4SLinus Torvalds 42151da177e4SLinus Torvalds time->tv_sec = 0; 42161da177e4SLinus Torvalds time->tv_nsec = 0; 42171da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U))) 42181da177e4SLinus Torvalds return -EIO; 42191da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) { 42201da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 4221409924e4STrond Myklebust if (status == 0) 4222409924e4STrond Myklebust status = NFS_ATTR_FATTR_MTIME; 42231da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY; 42241da177e4SLinus Torvalds } 4225ae08483cSArnd Bergmann dprintk("%s: mtime=%lld\n", __func__, time->tv_sec); 42261da177e4SLinus Torvalds return status; 42271da177e4SLinus Torvalds } 42281da177e4SLinus Torvalds 4229b78ef845SFrank van der Linden static int decode_attr_xattrsupport(struct xdr_stream *xdr, uint32_t *bitmap, 4230b78ef845SFrank van der Linden uint32_t *res) 4231b78ef845SFrank van der Linden { 4232b78ef845SFrank van der Linden __be32 *p; 4233b78ef845SFrank van der Linden 4234b78ef845SFrank van der Linden *res = 0; 4235b78ef845SFrank van der Linden if (unlikely(bitmap[2] & (FATTR4_WORD2_XATTR_SUPPORT - 1U))) 4236b78ef845SFrank van der Linden return -EIO; 4237b78ef845SFrank van der Linden if (likely(bitmap[2] & FATTR4_WORD2_XATTR_SUPPORT)) { 4238b78ef845SFrank van der Linden p = xdr_inline_decode(xdr, 4); 4239b78ef845SFrank van der Linden if (unlikely(!p)) 4240b78ef845SFrank van der Linden return -EIO; 4241b78ef845SFrank van der Linden *res = be32_to_cpup(p); 4242b78ef845SFrank van der Linden bitmap[2] &= ~FATTR4_WORD2_XATTR_SUPPORT; 4243b78ef845SFrank van der Linden } 4244b78ef845SFrank van der Linden dprintk("%s: XATTR support=%s\n", __func__, 4245b78ef845SFrank van der Linden *res == 0 ? "false" : "true"); 4246b78ef845SFrank van der Linden return 0; 4247b78ef845SFrank van der Linden } 4248b78ef845SFrank van der Linden 4249256e48bbSTrond Myklebust static int verify_attr_len(struct xdr_stream *xdr, unsigned int savep, uint32_t attrlen) 42501da177e4SLinus Torvalds { 42511da177e4SLinus Torvalds unsigned int attrwords = XDR_QUADLEN(attrlen); 4252256e48bbSTrond Myklebust unsigned int nwords = (xdr_stream_pos(xdr) - savep) >> 2; 42531da177e4SLinus Torvalds 42541da177e4SLinus Torvalds if (unlikely(attrwords != nwords)) { 4255fe82a183SChuck Lever dprintk("%s: server returned incorrect attribute length: " 4256fe82a183SChuck Lever "%u %c %u\n", 42573110ff80SHarvey Harrison __func__, 42581da177e4SLinus Torvalds attrwords << 2, 42591da177e4SLinus Torvalds (attrwords < nwords) ? '<' : '>', 42601da177e4SLinus Torvalds nwords << 2); 42611da177e4SLinus Torvalds return -EIO; 42621da177e4SLinus Torvalds } 42631da177e4SLinus Torvalds return 0; 42641da177e4SLinus Torvalds } 42651da177e4SLinus Torvalds 42661da177e4SLinus Torvalds static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 42671da177e4SLinus Torvalds { 42688687b63aSAl Viro __be32 *p; 42691da177e4SLinus Torvalds 4270c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 20); 4271c0eae66eSBenny Halevy if (unlikely(!p)) 4272eb72f484SChuck Lever return -EIO; 42736f723f77SBenny Halevy cinfo->atomic = be32_to_cpup(p++); 42743ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &cinfo->before); 4275cccddf4fSBenny Halevy xdr_decode_hyper(p, &cinfo->after); 42761da177e4SLinus Torvalds return 0; 42771da177e4SLinus Torvalds } 42781da177e4SLinus Torvalds 42796168f62cSWeston Andros Adamson static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access) 42801da177e4SLinus Torvalds { 42818687b63aSAl Viro __be32 *p; 42821da177e4SLinus Torvalds uint32_t supp, acc; 42831da177e4SLinus Torvalds int status; 42841da177e4SLinus Torvalds 42851da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_ACCESS); 42861da177e4SLinus Torvalds if (status) 42871da177e4SLinus Torvalds return status; 4288c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4289c0eae66eSBenny Halevy if (unlikely(!p)) 4290eb72f484SChuck Lever return -EIO; 42916f723f77SBenny Halevy supp = be32_to_cpup(p++); 4292cccddf4fSBenny Halevy acc = be32_to_cpup(p); 42936168f62cSWeston Andros Adamson *supported = supp; 42946168f62cSWeston Andros Adamson *access = acc; 42951da177e4SLinus Torvalds return 0; 42961da177e4SLinus Torvalds } 42971da177e4SLinus Torvalds 429807d30434SBenny Halevy static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len) 42991da177e4SLinus Torvalds { 4300ab6e9aafSTrond Myklebust ssize_t ret = xdr_stream_decode_opaque_fixed(xdr, buf, len); 4301eb72f484SChuck Lever if (unlikely(ret < 0)) 430207d30434SBenny Halevy return -EIO; 4303ab6e9aafSTrond Myklebust return 0; 4304ab6e9aafSTrond Myklebust } 430507d30434SBenny Halevy 430607d30434SBenny Halevy static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 430707d30434SBenny Halevy { 43082d2f24adSTrond Myklebust return decode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE); 43091da177e4SLinus Torvalds } 43101da177e4SLinus Torvalds 431193b717fdSTrond Myklebust static int decode_open_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 431293b717fdSTrond Myklebust { 431393b717fdSTrond Myklebust stateid->type = NFS4_OPEN_STATEID_TYPE; 431493b717fdSTrond Myklebust return decode_stateid(xdr, stateid); 431593b717fdSTrond Myklebust } 431693b717fdSTrond Myklebust 431793b717fdSTrond Myklebust static int decode_lock_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 431893b717fdSTrond Myklebust { 431993b717fdSTrond Myklebust stateid->type = NFS4_LOCK_STATEID_TYPE; 432093b717fdSTrond Myklebust return decode_stateid(xdr, stateid); 432193b717fdSTrond Myklebust } 432293b717fdSTrond Myklebust 432393b717fdSTrond Myklebust static int decode_delegation_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 432493b717fdSTrond Myklebust { 432593b717fdSTrond Myklebust stateid->type = NFS4_DELEGATION_STATEID_TYPE; 432693b717fdSTrond Myklebust return decode_stateid(xdr, stateid); 432793b717fdSTrond Myklebust } 432893b717fdSTrond Myklebust 4329fcd8843cSTrond Myklebust static int decode_invalid_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 4330fcd8843cSTrond Myklebust { 4331fcd8843cSTrond Myklebust nfs4_stateid dummy; 4332fcd8843cSTrond Myklebust 4333fcd8843cSTrond Myklebust nfs4_stateid_copy(stateid, &invalid_stateid); 4334fcd8843cSTrond Myklebust return decode_stateid(xdr, &dummy); 4335fcd8843cSTrond Myklebust } 4336fcd8843cSTrond Myklebust 43371da177e4SLinus Torvalds static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) 43381da177e4SLinus Torvalds { 43391da177e4SLinus Torvalds int status; 43401da177e4SLinus Torvalds 43411da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_CLOSE); 4342c1d51931STrond Myklebust if (status != -EIO) 4343c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 434407d30434SBenny Halevy if (!status) 4345fcd8843cSTrond Myklebust status = decode_invalid_stateid(xdr, &res->stateid); 43461da177e4SLinus Torvalds return status; 43471da177e4SLinus Torvalds } 43481da177e4SLinus Torvalds 4349db942bbdSBenny Halevy static int decode_verifier(struct xdr_stream *xdr, void *verifier) 4350db942bbdSBenny Halevy { 4351cd93710eSChuck Lever return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE); 43521da177e4SLinus Torvalds } 43531da177e4SLinus Torvalds 43542f2c63bcSTrond Myklebust static int decode_write_verifier(struct xdr_stream *xdr, struct nfs_write_verifier *verifier) 43552f2c63bcSTrond Myklebust { 43562f2c63bcSTrond Myklebust return decode_opaque_fixed(xdr, verifier->data, NFS4_VERIFIER_SIZE); 43572f2c63bcSTrond Myklebust } 43582f2c63bcSTrond Myklebust 43590b7c0153SFred Isaman static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res) 43601da177e4SLinus Torvalds { 4361221203ceSTrond Myklebust struct nfs_writeverf *verf = res->verf; 43621da177e4SLinus Torvalds int status; 43631da177e4SLinus Torvalds 43641da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_COMMIT); 4365db942bbdSBenny Halevy if (!status) 4366221203ceSTrond Myklebust status = decode_write_verifier(xdr, &verf->verifier); 4367221203ceSTrond Myklebust if (!status) 4368221203ceSTrond Myklebust verf->committed = NFS_FILE_SYNC; 43691da177e4SLinus Torvalds return status; 43701da177e4SLinus Torvalds } 43711da177e4SLinus Torvalds 43721da177e4SLinus Torvalds static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 43731da177e4SLinus Torvalds { 43748687b63aSAl Viro __be32 *p; 43751da177e4SLinus Torvalds uint32_t bmlen; 43761da177e4SLinus Torvalds int status; 43771da177e4SLinus Torvalds 43781da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_CREATE); 43791da177e4SLinus Torvalds if (status) 43801da177e4SLinus Torvalds return status; 43811da177e4SLinus Torvalds if ((status = decode_change_info(xdr, cinfo))) 43821da177e4SLinus Torvalds return status; 4383c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4384c0eae66eSBenny Halevy if (unlikely(!p)) 4385eb72f484SChuck Lever return -EIO; 4386cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 4387c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, bmlen << 2); 4388c0eae66eSBenny Halevy if (likely(p)) 43891da177e4SLinus Torvalds return 0; 4390c0eae66eSBenny Halevy return -EIO; 43911da177e4SLinus Torvalds } 43921da177e4SLinus Torvalds 43931da177e4SLinus Torvalds static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) 43941da177e4SLinus Torvalds { 4395256e48bbSTrond Myklebust unsigned int savep; 4396dae100c2SFred Isaman uint32_t attrlen, bitmap[3] = {0}; 43971da177e4SLinus Torvalds int status; 43981da177e4SLinus Torvalds 43991da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 44001da177e4SLinus Torvalds goto xdr_error; 44011da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 44021da177e4SLinus Torvalds goto xdr_error; 44031da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 44041da177e4SLinus Torvalds goto xdr_error; 44051da177e4SLinus Torvalds if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0) 44061da177e4SLinus Torvalds goto xdr_error; 4407264e6351SChuck Lever if ((status = decode_attr_fh_expire_type(xdr, bitmap, 4408264e6351SChuck Lever &res->fh_expire_type)) != 0) 4409264e6351SChuck Lever goto xdr_error; 44101da177e4SLinus Torvalds if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0) 44111da177e4SLinus Torvalds goto xdr_error; 44121da177e4SLinus Torvalds if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0) 44131da177e4SLinus Torvalds goto xdr_error; 44141da177e4SLinus Torvalds if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0) 44151da177e4SLinus Torvalds goto xdr_error; 44168c61282fSKinglong Mee if ((status = decode_attr_exclcreat_supported(xdr, bitmap, 44178c61282fSKinglong Mee res->exclcreat_bitmask)) != 0) 44188c61282fSKinglong Mee goto xdr_error; 44191da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 44201da177e4SLinus Torvalds xdr_error: 44213110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 44221da177e4SLinus Torvalds return status; 44231da177e4SLinus Torvalds } 44241da177e4SLinus Torvalds 44251da177e4SLinus Torvalds static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) 44261da177e4SLinus Torvalds { 4427256e48bbSTrond Myklebust unsigned int savep; 4428dae100c2SFred Isaman uint32_t attrlen, bitmap[3] = {0}; 44291da177e4SLinus Torvalds int status; 44301da177e4SLinus Torvalds 44311da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 44321da177e4SLinus Torvalds goto xdr_error; 44331da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 44341da177e4SLinus Torvalds goto xdr_error; 44351da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 44361da177e4SLinus Torvalds goto xdr_error; 44371da177e4SLinus Torvalds 44381da177e4SLinus Torvalds if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0) 44391da177e4SLinus Torvalds goto xdr_error; 44401da177e4SLinus Torvalds if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0) 44411da177e4SLinus Torvalds goto xdr_error; 44421da177e4SLinus Torvalds if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0) 44431da177e4SLinus Torvalds goto xdr_error; 44441ca843a2SAndreas Gruenbacher 44451ca843a2SAndreas Gruenbacher status = -EIO; 44461ca843a2SAndreas Gruenbacher if (unlikely(bitmap[0])) 44471ca843a2SAndreas Gruenbacher goto xdr_error; 44481ca843a2SAndreas Gruenbacher 44491da177e4SLinus Torvalds if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0) 44501da177e4SLinus Torvalds goto xdr_error; 44511da177e4SLinus Torvalds if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0) 44521da177e4SLinus Torvalds goto xdr_error; 44531da177e4SLinus Torvalds if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0) 44541da177e4SLinus Torvalds goto xdr_error; 44551da177e4SLinus Torvalds 44561da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 44571da177e4SLinus Torvalds xdr_error: 44583110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 44591da177e4SLinus Torvalds return status; 44601da177e4SLinus Torvalds } 44611da177e4SLinus Torvalds 44621da177e4SLinus Torvalds static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) 44631da177e4SLinus Torvalds { 4464256e48bbSTrond Myklebust unsigned int savep; 4465dae100c2SFred Isaman uint32_t attrlen, bitmap[3] = {0}; 44661da177e4SLinus Torvalds int status; 44671da177e4SLinus Torvalds 44681da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 44691da177e4SLinus Torvalds goto xdr_error; 44701da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 44711da177e4SLinus Torvalds goto xdr_error; 44721da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 44731da177e4SLinus Torvalds goto xdr_error; 44741da177e4SLinus Torvalds 44751da177e4SLinus Torvalds if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0) 44761da177e4SLinus Torvalds goto xdr_error; 44771da177e4SLinus Torvalds if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0) 44781da177e4SLinus Torvalds goto xdr_error; 44791da177e4SLinus Torvalds 44801da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 44811da177e4SLinus Torvalds xdr_error: 44823110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 44831da177e4SLinus Torvalds return status; 44841da177e4SLinus Torvalds } 44851da177e4SLinus Torvalds 448688034c3dSAndy Adamson static int decode_threshold_hint(struct xdr_stream *xdr, 448788034c3dSAndy Adamson uint32_t *bitmap, 448888034c3dSAndy Adamson uint64_t *res, 448988034c3dSAndy Adamson uint32_t hint_bit) 449088034c3dSAndy Adamson { 449188034c3dSAndy Adamson __be32 *p; 449288034c3dSAndy Adamson 449388034c3dSAndy Adamson *res = 0; 449488034c3dSAndy Adamson if (likely(bitmap[0] & hint_bit)) { 449588034c3dSAndy Adamson p = xdr_inline_decode(xdr, 8); 449688034c3dSAndy Adamson if (unlikely(!p)) 4497eb72f484SChuck Lever return -EIO; 449888034c3dSAndy Adamson xdr_decode_hyper(p, res); 449988034c3dSAndy Adamson } 450088034c3dSAndy Adamson return 0; 450188034c3dSAndy Adamson } 450288034c3dSAndy Adamson 450388034c3dSAndy Adamson static int decode_first_threshold_item4(struct xdr_stream *xdr, 450488034c3dSAndy Adamson struct nfs4_threshold *res) 450588034c3dSAndy Adamson { 4506256e48bbSTrond Myklebust __be32 *p; 4507256e48bbSTrond Myklebust unsigned int savep; 450888034c3dSAndy Adamson uint32_t bitmap[3] = {0,}, attrlen; 450988034c3dSAndy Adamson int status; 451088034c3dSAndy Adamson 451188034c3dSAndy Adamson /* layout type */ 451288034c3dSAndy Adamson p = xdr_inline_decode(xdr, 4); 4513eb72f484SChuck Lever if (unlikely(!p)) 451488034c3dSAndy Adamson return -EIO; 451588034c3dSAndy Adamson res->l_type = be32_to_cpup(p); 451688034c3dSAndy Adamson 451788034c3dSAndy Adamson /* thi_hintset bitmap */ 451888034c3dSAndy Adamson status = decode_attr_bitmap(xdr, bitmap); 451988034c3dSAndy Adamson if (status < 0) 452088034c3dSAndy Adamson goto xdr_error; 452188034c3dSAndy Adamson 452288034c3dSAndy Adamson /* thi_hintlist length */ 452388034c3dSAndy Adamson status = decode_attr_length(xdr, &attrlen, &savep); 452488034c3dSAndy Adamson if (status < 0) 452588034c3dSAndy Adamson goto xdr_error; 452688034c3dSAndy Adamson /* thi_hintlist */ 452788034c3dSAndy Adamson status = decode_threshold_hint(xdr, bitmap, &res->rd_sz, THRESHOLD_RD); 452888034c3dSAndy Adamson if (status < 0) 452988034c3dSAndy Adamson goto xdr_error; 453088034c3dSAndy Adamson status = decode_threshold_hint(xdr, bitmap, &res->wr_sz, THRESHOLD_WR); 453188034c3dSAndy Adamson if (status < 0) 453288034c3dSAndy Adamson goto xdr_error; 453388034c3dSAndy Adamson status = decode_threshold_hint(xdr, bitmap, &res->rd_io_sz, 453488034c3dSAndy Adamson THRESHOLD_RD_IO); 453588034c3dSAndy Adamson if (status < 0) 453688034c3dSAndy Adamson goto xdr_error; 453788034c3dSAndy Adamson status = decode_threshold_hint(xdr, bitmap, &res->wr_io_sz, 453888034c3dSAndy Adamson THRESHOLD_WR_IO); 453988034c3dSAndy Adamson if (status < 0) 454088034c3dSAndy Adamson goto xdr_error; 454188034c3dSAndy Adamson 454288034c3dSAndy Adamson status = verify_attr_len(xdr, savep, attrlen); 454388034c3dSAndy Adamson res->bm = bitmap[0]; 454488034c3dSAndy Adamson 454588034c3dSAndy Adamson dprintk("%s bm=0x%x rd_sz=%llu wr_sz=%llu rd_io=%llu wr_io=%llu\n", 454688034c3dSAndy Adamson __func__, res->bm, res->rd_sz, res->wr_sz, res->rd_io_sz, 454788034c3dSAndy Adamson res->wr_io_sz); 454888034c3dSAndy Adamson xdr_error: 454988034c3dSAndy Adamson dprintk("%s ret=%d!\n", __func__, status); 455088034c3dSAndy Adamson return status; 455188034c3dSAndy Adamson } 455288034c3dSAndy Adamson 455388034c3dSAndy Adamson /* 455488034c3dSAndy Adamson * Thresholds on pNFS direct I/O vrs MDS I/O 455588034c3dSAndy Adamson */ 455688034c3dSAndy Adamson static int decode_attr_mdsthreshold(struct xdr_stream *xdr, 455788034c3dSAndy Adamson uint32_t *bitmap, 455888034c3dSAndy Adamson struct nfs4_threshold *res) 455988034c3dSAndy Adamson { 456088034c3dSAndy Adamson __be32 *p; 456188034c3dSAndy Adamson int status = 0; 456288034c3dSAndy Adamson uint32_t num; 456388034c3dSAndy Adamson 456488034c3dSAndy Adamson if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U))) 456588034c3dSAndy Adamson return -EIO; 4566029c5347STrond Myklebust if (bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD) { 45671549210fSTrond Myklebust /* Did the server return an unrequested attribute? */ 45681549210fSTrond Myklebust if (unlikely(res == NULL)) 45691549210fSTrond Myklebust return -EREMOTEIO; 457088034c3dSAndy Adamson p = xdr_inline_decode(xdr, 4); 457188034c3dSAndy Adamson if (unlikely(!p)) 4572eb72f484SChuck Lever return -EIO; 457388034c3dSAndy Adamson num = be32_to_cpup(p); 457488034c3dSAndy Adamson if (num == 0) 457588034c3dSAndy Adamson return 0; 457688034c3dSAndy Adamson if (num > 1) 457788034c3dSAndy Adamson printk(KERN_INFO "%s: Warning: Multiple pNFS layout " 457888034c3dSAndy Adamson "drivers per filesystem not supported\n", 457988034c3dSAndy Adamson __func__); 458088034c3dSAndy Adamson 458188034c3dSAndy Adamson status = decode_first_threshold_item4(xdr, res); 4582029c5347STrond Myklebust bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD; 458388034c3dSAndy Adamson } 458488034c3dSAndy Adamson return status; 458588034c3dSAndy Adamson } 458688034c3dSAndy Adamson 4587ae42c70aSBryan Schumaker static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, 4588ae42c70aSBryan Schumaker struct nfs_fattr *fattr, struct nfs_fh *fh, 45891e2f67daSAnna Schumaker struct nfs4_fs_locations *fs_loc, const struct nfs_server *server) 45901da177e4SLinus Torvalds { 4591bca79478STrond Myklebust int status; 4592bca79478STrond Myklebust umode_t fmode = 0; 4593ae42c70aSBryan Schumaker uint32_t type; 4594ee7b75fcSTrond Myklebust int32_t err; 45951da177e4SLinus Torvalds 4596f26c7a78STrond Myklebust status = decode_attr_type(xdr, bitmap, &type); 4597f26c7a78STrond Myklebust if (status < 0) 45981da177e4SLinus Torvalds goto xdr_error; 4599409924e4STrond Myklebust fattr->mode = 0; 4600409924e4STrond Myklebust if (status != 0) { 4601409924e4STrond Myklebust fattr->mode |= nfs_type2fmt[type]; 4602409924e4STrond Myklebust fattr->valid |= status; 4603409924e4STrond Myklebust } 46041da177e4SLinus Torvalds 4605f26c7a78STrond Myklebust status = decode_attr_change(xdr, bitmap, &fattr->change_attr); 4606f26c7a78STrond Myklebust if (status < 0) 46071da177e4SLinus Torvalds goto xdr_error; 4608409924e4STrond Myklebust fattr->valid |= status; 4609f26c7a78STrond Myklebust 4610f26c7a78STrond Myklebust status = decode_attr_size(xdr, bitmap, &fattr->size); 4611f26c7a78STrond Myklebust if (status < 0) 46121da177e4SLinus Torvalds goto xdr_error; 4613409924e4STrond Myklebust fattr->valid |= status; 4614f26c7a78STrond Myklebust 4615f26c7a78STrond Myklebust status = decode_attr_fsid(xdr, bitmap, &fattr->fsid); 4616f26c7a78STrond Myklebust if (status < 0) 46171da177e4SLinus Torvalds goto xdr_error; 4618409924e4STrond Myklebust fattr->valid |= status; 4619f26c7a78STrond Myklebust 4620ee7b75fcSTrond Myklebust err = 0; 4621ee7b75fcSTrond Myklebust status = decode_attr_error(xdr, bitmap, &err); 4622ae42c70aSBryan Schumaker if (status < 0) 4623ae42c70aSBryan Schumaker goto xdr_error; 4624ae42c70aSBryan Schumaker 4625ae42c70aSBryan Schumaker status = decode_attr_filehandle(xdr, bitmap, fh); 4626ae42c70aSBryan Schumaker if (status < 0) 4627ae42c70aSBryan Schumaker goto xdr_error; 4628ae42c70aSBryan Schumaker 4629f26c7a78STrond Myklebust status = decode_attr_fileid(xdr, bitmap, &fattr->fileid); 4630f26c7a78STrond Myklebust if (status < 0) 46311da177e4SLinus Torvalds goto xdr_error; 4632409924e4STrond Myklebust fattr->valid |= status; 4633f26c7a78STrond Myklebust 46348b7e3f49STrond Myklebust status = decode_attr_fs_locations(xdr, bitmap, fs_loc); 4635f26c7a78STrond Myklebust if (status < 0) 4636683b57b4STrond Myklebust goto xdr_error; 4637409924e4STrond Myklebust fattr->valid |= status; 4638f26c7a78STrond Myklebust 46391ca843a2SAndreas Gruenbacher status = -EIO; 46401ca843a2SAndreas Gruenbacher if (unlikely(bitmap[0])) 46411ca843a2SAndreas Gruenbacher goto xdr_error; 46421ca843a2SAndreas Gruenbacher 4643f26c7a78STrond Myklebust status = decode_attr_mode(xdr, bitmap, &fmode); 4644f26c7a78STrond Myklebust if (status < 0) 46451da177e4SLinus Torvalds goto xdr_error; 4646409924e4STrond Myklebust if (status != 0) { 46471da177e4SLinus Torvalds fattr->mode |= fmode; 4648409924e4STrond Myklebust fattr->valid |= status; 4649409924e4STrond Myklebust } 4650f26c7a78STrond Myklebust 4651f26c7a78STrond Myklebust status = decode_attr_nlink(xdr, bitmap, &fattr->nlink); 4652f26c7a78STrond Myklebust if (status < 0) 46531da177e4SLinus Torvalds goto xdr_error; 4654409924e4STrond Myklebust fattr->valid |= status; 4655f26c7a78STrond Myklebust 46566926afd1STrond Myklebust status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name); 4657f26c7a78STrond Myklebust if (status < 0) 46581da177e4SLinus Torvalds goto xdr_error; 4659409924e4STrond Myklebust fattr->valid |= status; 4660f26c7a78STrond Myklebust 46616926afd1STrond Myklebust status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name); 4662f26c7a78STrond Myklebust if (status < 0) 46631da177e4SLinus Torvalds goto xdr_error; 4664409924e4STrond Myklebust fattr->valid |= status; 4665f26c7a78STrond Myklebust 4666f26c7a78STrond Myklebust status = decode_attr_rdev(xdr, bitmap, &fattr->rdev); 4667f26c7a78STrond Myklebust if (status < 0) 46681da177e4SLinus Torvalds goto xdr_error; 4669409924e4STrond Myklebust fattr->valid |= status; 4670f26c7a78STrond Myklebust 4671f26c7a78STrond Myklebust status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used); 4672f26c7a78STrond Myklebust if (status < 0) 46731da177e4SLinus Torvalds goto xdr_error; 4674409924e4STrond Myklebust fattr->valid |= status; 4675f26c7a78STrond Myklebust 4676f26c7a78STrond Myklebust status = decode_attr_time_access(xdr, bitmap, &fattr->atime); 4677f26c7a78STrond Myklebust if (status < 0) 46781da177e4SLinus Torvalds goto xdr_error; 4679409924e4STrond Myklebust fattr->valid |= status; 4680f26c7a78STrond Myklebust 4681f26c7a78STrond Myklebust status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime); 4682f26c7a78STrond Myklebust if (status < 0) 46831da177e4SLinus Torvalds goto xdr_error; 4684409924e4STrond Myklebust fattr->valid |= status; 4685f26c7a78STrond Myklebust 4686f26c7a78STrond Myklebust status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime); 4687f26c7a78STrond Myklebust if (status < 0) 46881da177e4SLinus Torvalds goto xdr_error; 4689409924e4STrond Myklebust fattr->valid |= status; 4690f26c7a78STrond Myklebust 469128331a46STrond Myklebust status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid); 4692f26c7a78STrond Myklebust if (status < 0) 469399baf625SManoj Naik goto xdr_error; 4694409924e4STrond Myklebust fattr->valid |= status; 4695f26c7a78STrond Myklebust 46961ca843a2SAndreas Gruenbacher status = -EIO; 46971ca843a2SAndreas Gruenbacher if (unlikely(bitmap[1])) 46981ca843a2SAndreas Gruenbacher goto xdr_error; 46991ca843a2SAndreas Gruenbacher 470088034c3dSAndy Adamson status = decode_attr_mdsthreshold(xdr, bitmap, fattr->mdsthreshold); 470188034c3dSAndy Adamson if (status < 0) 470288034c3dSAndy Adamson goto xdr_error; 470388034c3dSAndy Adamson 47041e2f67daSAnna Schumaker if (fattr->label) { 47051e2f67daSAnna Schumaker status = decode_attr_security_label(xdr, bitmap, fattr->label); 4706aa9c2669SDavid Quigley if (status < 0) 4707aa9c2669SDavid Quigley goto xdr_error; 4708aa9c2669SDavid Quigley fattr->valid |= status; 4709aa9c2669SDavid Quigley } 4710aa9c2669SDavid Quigley 4711ae42c70aSBryan Schumaker xdr_error: 4712ae42c70aSBryan Schumaker dprintk("%s: xdr returned %d\n", __func__, -status); 4713ae42c70aSBryan Schumaker return status; 4714ae42c70aSBryan Schumaker } 4715ae42c70aSBryan Schumaker 4716ae42c70aSBryan Schumaker static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, 47178b7e3f49STrond Myklebust struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, 47181e2f67daSAnna Schumaker const struct nfs_server *server) 4719ae42c70aSBryan Schumaker { 4720256e48bbSTrond Myklebust unsigned int savep; 4721ae42c70aSBryan Schumaker uint32_t attrlen, 4722dae100c2SFred Isaman bitmap[3] = {0}; 4723ae42c70aSBryan Schumaker int status; 4724ae42c70aSBryan Schumaker 4725ae42c70aSBryan Schumaker status = decode_op_hdr(xdr, OP_GETATTR); 4726ae42c70aSBryan Schumaker if (status < 0) 4727ae42c70aSBryan Schumaker goto xdr_error; 4728ae42c70aSBryan Schumaker 4729ae42c70aSBryan Schumaker status = decode_attr_bitmap(xdr, bitmap); 4730ae42c70aSBryan Schumaker if (status < 0) 4731ae42c70aSBryan Schumaker goto xdr_error; 4732ae42c70aSBryan Schumaker 4733ae42c70aSBryan Schumaker status = decode_attr_length(xdr, &attrlen, &savep); 4734ae42c70aSBryan Schumaker if (status < 0) 4735ae42c70aSBryan Schumaker goto xdr_error; 4736ae42c70aSBryan Schumaker 47371e2f67daSAnna Schumaker status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, server); 4738ae42c70aSBryan Schumaker if (status < 0) 4739ae42c70aSBryan Schumaker goto xdr_error; 4740ae42c70aSBryan Schumaker 4741f26c7a78STrond Myklebust status = verify_attr_len(xdr, savep, attrlen); 47421da177e4SLinus Torvalds xdr_error: 47433110ff80SHarvey Harrison dprintk("%s: xdr returned %d\n", __func__, -status); 47441da177e4SLinus Torvalds return status; 47451da177e4SLinus Torvalds } 47461da177e4SLinus Torvalds 4747ae42c70aSBryan Schumaker static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, 47486926afd1STrond Myklebust const struct nfs_server *server) 4749ae42c70aSBryan Schumaker { 47501e2f67daSAnna Schumaker return decode_getfattr_generic(xdr, fattr, NULL, NULL, server); 4751ae42c70aSBryan Schumaker } 47521da177e4SLinus Torvalds 4753504913fbSAndy Adamson /* 47543132e49eSJeff Layton * Decode potentially multiple layout types. 4755504913fbSAndy Adamson */ 47563132e49eSJeff Layton static int decode_pnfs_layout_types(struct xdr_stream *xdr, 4757ca440c38SJeff Layton struct nfs_fsinfo *fsinfo) 4758504913fbSAndy Adamson { 4759b8a8a0ddSTrond Myklebust __be32 *p; 4760ca440c38SJeff Layton uint32_t i; 4761504913fbSAndy Adamson 4762504913fbSAndy Adamson p = xdr_inline_decode(xdr, 4); 4763504913fbSAndy Adamson if (unlikely(!p)) 4764eb72f484SChuck Lever return -EIO; 4765ca440c38SJeff Layton fsinfo->nlayouttypes = be32_to_cpup(p); 4766504913fbSAndy Adamson 4767504913fbSAndy Adamson /* pNFS is not supported by the underlying file system */ 4768ca440c38SJeff Layton if (fsinfo->nlayouttypes == 0) 4769504913fbSAndy Adamson return 0; 4770504913fbSAndy Adamson 4771504913fbSAndy Adamson /* Decode and set first layout type, move xdr->p past unused types */ 4772ca440c38SJeff Layton p = xdr_inline_decode(xdr, fsinfo->nlayouttypes * 4); 4773504913fbSAndy Adamson if (unlikely(!p)) 4774eb72f484SChuck Lever return -EIO; 4775ca440c38SJeff Layton 4776ca440c38SJeff Layton /* If we get too many, then just cap it at the max */ 4777ca440c38SJeff Layton if (fsinfo->nlayouttypes > NFS_MAX_LAYOUT_TYPES) { 4778ca440c38SJeff Layton printk(KERN_INFO "NFS: %s: Warning: Too many (%u) pNFS layout types\n", 4779ca440c38SJeff Layton __func__, fsinfo->nlayouttypes); 4780ca440c38SJeff Layton fsinfo->nlayouttypes = NFS_MAX_LAYOUT_TYPES; 4781ca440c38SJeff Layton } 4782ca440c38SJeff Layton 4783ca440c38SJeff Layton for(i = 0; i < fsinfo->nlayouttypes; ++i) 4784ca440c38SJeff Layton fsinfo->layouttype[i] = be32_to_cpup(p++); 4785504913fbSAndy Adamson return 0; 4786504913fbSAndy Adamson } 4787504913fbSAndy Adamson 4788504913fbSAndy Adamson /* 4789504913fbSAndy Adamson * The type of file system exported. 4790504913fbSAndy Adamson * Note we must ensure that layouttype is set in any non-error case. 4791504913fbSAndy Adamson */ 4792504913fbSAndy Adamson static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap, 4793ca440c38SJeff Layton struct nfs_fsinfo *fsinfo) 4794504913fbSAndy Adamson { 4795504913fbSAndy Adamson int status = 0; 4796504913fbSAndy Adamson 4797504913fbSAndy Adamson dprintk("%s: bitmap is %x\n", __func__, bitmap[1]); 4798504913fbSAndy Adamson if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U))) 4799504913fbSAndy Adamson return -EIO; 4800504913fbSAndy Adamson if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) { 4801ca440c38SJeff Layton status = decode_pnfs_layout_types(xdr, fsinfo); 4802504913fbSAndy Adamson bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES; 48033132e49eSJeff Layton } 4804504913fbSAndy Adamson return status; 4805504913fbSAndy Adamson } 4806504913fbSAndy Adamson 4807dae100c2SFred Isaman /* 4808dae100c2SFred Isaman * The prefered block size for layout directed io 4809dae100c2SFred Isaman */ 4810dae100c2SFred Isaman static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap, 4811dae100c2SFred Isaman uint32_t *res) 4812dae100c2SFred Isaman { 4813dae100c2SFred Isaman __be32 *p; 4814dae100c2SFred Isaman 4815dae100c2SFred Isaman dprintk("%s: bitmap is %x\n", __func__, bitmap[2]); 4816dae100c2SFred Isaman *res = 0; 4817dae100c2SFred Isaman if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) { 4818dae100c2SFred Isaman p = xdr_inline_decode(xdr, 4); 4819eb72f484SChuck Lever if (unlikely(!p)) 4820dae100c2SFred Isaman return -EIO; 4821dae100c2SFred Isaman *res = be32_to_cpup(p); 4822dae100c2SFred Isaman bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE; 4823dae100c2SFred Isaman } 4824dae100c2SFred Isaman return 0; 4825dae100c2SFred Isaman } 4826dae100c2SFred Isaman 48272a92ee92SPeng Tao /* 48282a92ee92SPeng Tao * The granularity of a CLONE operation. 48292a92ee92SPeng Tao */ 48302a92ee92SPeng Tao static int decode_attr_clone_blksize(struct xdr_stream *xdr, uint32_t *bitmap, 48312a92ee92SPeng Tao uint32_t *res) 48322a92ee92SPeng Tao { 48332a92ee92SPeng Tao __be32 *p; 48342a92ee92SPeng Tao 48352a92ee92SPeng Tao dprintk("%s: bitmap is %x\n", __func__, bitmap[2]); 48362a92ee92SPeng Tao *res = 0; 48372a92ee92SPeng Tao if (bitmap[2] & FATTR4_WORD2_CLONE_BLKSIZE) { 48382a92ee92SPeng Tao p = xdr_inline_decode(xdr, 4); 4839eb72f484SChuck Lever if (unlikely(!p)) 48402a92ee92SPeng Tao return -EIO; 48412a92ee92SPeng Tao *res = be32_to_cpup(p); 48422a92ee92SPeng Tao bitmap[2] &= ~FATTR4_WORD2_CLONE_BLKSIZE; 48432a92ee92SPeng Tao } 48442a92ee92SPeng Tao return 0; 48452a92ee92SPeng Tao } 48462a92ee92SPeng Tao 48477f08a335STrond Myklebust static int decode_attr_change_attr_type(struct xdr_stream *xdr, 48487f08a335STrond Myklebust uint32_t *bitmap, 48497f08a335STrond Myklebust enum nfs4_change_attr_type *res) 48507f08a335STrond Myklebust { 48517f08a335STrond Myklebust u32 tmp = NFS4_CHANGE_TYPE_IS_UNDEFINED; 48527f08a335STrond Myklebust 48537f08a335STrond Myklebust dprintk("%s: bitmap is %x\n", __func__, bitmap[2]); 48547f08a335STrond Myklebust if (bitmap[2] & FATTR4_WORD2_CHANGE_ATTR_TYPE) { 48557f08a335STrond Myklebust if (xdr_stream_decode_u32(xdr, &tmp)) 48567f08a335STrond Myklebust return -EIO; 48577f08a335STrond Myklebust bitmap[2] &= ~FATTR4_WORD2_CHANGE_ATTR_TYPE; 48587f08a335STrond Myklebust } 48597f08a335STrond Myklebust 48607f08a335STrond Myklebust switch(tmp) { 48617f08a335STrond Myklebust case NFS4_CHANGE_TYPE_IS_MONOTONIC_INCR: 48627f08a335STrond Myklebust case NFS4_CHANGE_TYPE_IS_VERSION_COUNTER: 48637f08a335STrond Myklebust case NFS4_CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS: 48647f08a335STrond Myklebust case NFS4_CHANGE_TYPE_IS_TIME_METADATA: 48657f08a335STrond Myklebust *res = tmp; 48667f08a335STrond Myklebust break; 48677f08a335STrond Myklebust default: 48687f08a335STrond Myklebust *res = NFS4_CHANGE_TYPE_IS_UNDEFINED; 48697f08a335STrond Myklebust } 48707f08a335STrond Myklebust return 0; 48717f08a335STrond Myklebust } 48727f08a335STrond Myklebust 48731da177e4SLinus Torvalds static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) 48741da177e4SLinus Torvalds { 4875256e48bbSTrond Myklebust unsigned int savep; 4876dae100c2SFred Isaman uint32_t attrlen, bitmap[3]; 48771da177e4SLinus Torvalds int status; 48781da177e4SLinus Torvalds 48791da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 48801da177e4SLinus Torvalds goto xdr_error; 48811da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 48821da177e4SLinus Torvalds goto xdr_error; 48831da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 48841da177e4SLinus Torvalds goto xdr_error; 48851da177e4SLinus Torvalds 48861da177e4SLinus Torvalds fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */ 48871da177e4SLinus Torvalds 48881da177e4SLinus Torvalds if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0) 48891da177e4SLinus Torvalds goto xdr_error; 48901da177e4SLinus Torvalds if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0) 48911da177e4SLinus Torvalds goto xdr_error; 48921da177e4SLinus Torvalds if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0) 48931da177e4SLinus Torvalds goto xdr_error; 48941da177e4SLinus Torvalds fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax; 48951da177e4SLinus Torvalds if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0) 48961da177e4SLinus Torvalds goto xdr_error; 48971da177e4SLinus Torvalds fsinfo->wtpref = fsinfo->wtmax; 48981ca843a2SAndreas Gruenbacher 48991ca843a2SAndreas Gruenbacher status = -EIO; 49001ca843a2SAndreas Gruenbacher if (unlikely(bitmap[0])) 49011ca843a2SAndreas Gruenbacher goto xdr_error; 49021ca843a2SAndreas Gruenbacher 490355b6e774SRicardo Labiaga status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta); 490455b6e774SRicardo Labiaga if (status != 0) 490555b6e774SRicardo Labiaga goto xdr_error; 4906ca440c38SJeff Layton status = decode_attr_pnfstype(xdr, bitmap, fsinfo); 4907504913fbSAndy Adamson if (status != 0) 4908504913fbSAndy Adamson goto xdr_error; 49091ca843a2SAndreas Gruenbacher 49101ca843a2SAndreas Gruenbacher status = -EIO; 49111ca843a2SAndreas Gruenbacher if (unlikely(bitmap[1])) 49121ca843a2SAndreas Gruenbacher goto xdr_error; 49131ca843a2SAndreas Gruenbacher 4914dae100c2SFred Isaman status = decode_attr_layout_blksize(xdr, bitmap, &fsinfo->blksize); 4915dae100c2SFred Isaman if (status) 4916dae100c2SFred Isaman goto xdr_error; 49172a92ee92SPeng Tao status = decode_attr_clone_blksize(xdr, bitmap, &fsinfo->clone_blksize); 49182a92ee92SPeng Tao if (status) 49192a92ee92SPeng Tao goto xdr_error; 49201da177e4SLinus Torvalds 49217f08a335STrond Myklebust status = decode_attr_change_attr_type(xdr, bitmap, 49227f08a335STrond Myklebust &fsinfo->change_attr_type); 49237f08a335STrond Myklebust if (status) 49247f08a335STrond Myklebust goto xdr_error; 49257f08a335STrond Myklebust 4926b78ef845SFrank van der Linden status = decode_attr_xattrsupport(xdr, bitmap, 4927b78ef845SFrank van der Linden &fsinfo->xattr_support); 4928b78ef845SFrank van der Linden if (status) 4929b78ef845SFrank van der Linden goto xdr_error; 4930b78ef845SFrank van der Linden 49311da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 49321da177e4SLinus Torvalds xdr_error: 49333110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 49341da177e4SLinus Torvalds return status; 49351da177e4SLinus Torvalds } 49361da177e4SLinus Torvalds 49371da177e4SLinus Torvalds static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) 49381da177e4SLinus Torvalds { 49398687b63aSAl Viro __be32 *p; 49401da177e4SLinus Torvalds uint32_t len; 49411da177e4SLinus Torvalds int status; 49421da177e4SLinus Torvalds 49439936781dSTrond Myklebust /* Zero handle first to allow comparisons */ 49449936781dSTrond Myklebust memset(fh, 0, sizeof(*fh)); 49459936781dSTrond Myklebust 49461da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_GETFH); 49471da177e4SLinus Torvalds if (status) 49481da177e4SLinus Torvalds return status; 49491da177e4SLinus Torvalds 4950c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4951c0eae66eSBenny Halevy if (unlikely(!p)) 4952eb72f484SChuck Lever return -EIO; 4953cccddf4fSBenny Halevy len = be32_to_cpup(p); 4954eb3d58c6STrond Myklebust if (len > NFS4_FHSIZE || len == 0) { 4955eb3d58c6STrond Myklebust trace_nfs4_xdr_bad_filehandle(xdr, OP_GETFH, NFS4ERR_BADHANDLE); 4956eb3d58c6STrond Myklebust return -EREMOTEIO; 4957eb3d58c6STrond Myklebust } 49581da177e4SLinus Torvalds fh->size = len; 4959c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 4960c0eae66eSBenny Halevy if (unlikely(!p)) 4961eb72f484SChuck Lever return -EIO; 496299398d06SBenny Halevy memcpy(fh->data, p, len); 49631da177e4SLinus Torvalds return 0; 49641da177e4SLinus Torvalds } 49651da177e4SLinus Torvalds 49661da177e4SLinus Torvalds static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 49671da177e4SLinus Torvalds { 49681da177e4SLinus Torvalds int status; 49691da177e4SLinus Torvalds 49701da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LINK); 49711da177e4SLinus Torvalds if (status) 49721da177e4SLinus Torvalds return status; 49731da177e4SLinus Torvalds return decode_change_info(xdr, cinfo); 49741da177e4SLinus Torvalds } 49751da177e4SLinus Torvalds 49761da177e4SLinus Torvalds /* 49771da177e4SLinus Torvalds * We create the owner, so we know a proper owner.id length is 4. 49781da177e4SLinus Torvalds */ 4979911d1aafSTrond Myklebust static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) 49801da177e4SLinus Torvalds { 4981911d1aafSTrond Myklebust uint64_t offset, length, clientid; 49828687b63aSAl Viro __be32 *p; 4983911d1aafSTrond Myklebust uint32_t namelen, type; 49841da177e4SLinus Torvalds 4985babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 32); /* read 32 bytes */ 4986c0eae66eSBenny Halevy if (unlikely(!p)) 4987eb72f484SChuck Lever return -EIO; 4988babddc72SBryan Schumaker p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */ 49893ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &length); 4990babddc72SBryan Schumaker type = be32_to_cpup(p++); /* 4 byte read */ 4991babddc72SBryan Schumaker if (fl != NULL) { /* manipulate file lock */ 4992911d1aafSTrond Myklebust fl->fl_start = (loff_t)offset; 4993911d1aafSTrond Myklebust fl->fl_end = fl->fl_start + (loff_t)length - 1; 4994911d1aafSTrond Myklebust if (length == ~(uint64_t)0) 4995911d1aafSTrond Myklebust fl->fl_end = OFFSET_MAX; 4996911d1aafSTrond Myklebust fl->fl_type = F_WRLCK; 4997911d1aafSTrond Myklebust if (type & 1) 4998911d1aafSTrond Myklebust fl->fl_type = F_RDLCK; 4999911d1aafSTrond Myklebust fl->fl_pid = 0; 5000911d1aafSTrond Myklebust } 5001babddc72SBryan Schumaker p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */ 5002babddc72SBryan Schumaker namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */ 5003babddc72SBryan Schumaker p = xdr_inline_decode(xdr, namelen); /* variable size field */ 5004eb72f484SChuck Lever if (likely(!p)) 5005c0eae66eSBenny Halevy return -EIO; 5006eb72f484SChuck Lever return -NFS4ERR_DENIED; 50071da177e4SLinus Torvalds } 50081da177e4SLinus Torvalds 5009911d1aafSTrond Myklebust static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) 50101da177e4SLinus Torvalds { 50111da177e4SLinus Torvalds int status; 50121da177e4SLinus Torvalds 50131da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCK); 5014c1d51931STrond Myklebust if (status == -EIO) 5015c1d51931STrond Myklebust goto out; 50161da177e4SLinus Torvalds if (status == 0) { 501793b717fdSTrond Myklebust status = decode_lock_stateid(xdr, &res->stateid); 501807d30434SBenny Halevy if (unlikely(status)) 501907d30434SBenny Halevy goto out; 50201da177e4SLinus Torvalds } else if (status == -NFS4ERR_DENIED) 5021c1d51931STrond Myklebust status = decode_lock_denied(xdr, NULL); 5022c1d51931STrond Myklebust if (res->open_seqid != NULL) 5023c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->open_seqid); 5024c1d51931STrond Myklebust nfs_increment_lock_seqid(status, res->lock_seqid); 5025c1d51931STrond Myklebust out: 50261da177e4SLinus Torvalds return status; 50271da177e4SLinus Torvalds } 50281da177e4SLinus Torvalds 5029911d1aafSTrond Myklebust static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res) 50301da177e4SLinus Torvalds { 50311da177e4SLinus Torvalds int status; 50321da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCKT); 50331da177e4SLinus Torvalds if (status == -NFS4ERR_DENIED) 5034911d1aafSTrond Myklebust return decode_lock_denied(xdr, res->denied); 50351da177e4SLinus Torvalds return status; 50361da177e4SLinus Torvalds } 50371da177e4SLinus Torvalds 5038911d1aafSTrond Myklebust static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) 50391da177e4SLinus Torvalds { 50401da177e4SLinus Torvalds int status; 50411da177e4SLinus Torvalds 50421da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCKU); 5043c1d51931STrond Myklebust if (status != -EIO) 5044c1d51931STrond Myklebust nfs_increment_lock_seqid(status, res->seqid); 504507d30434SBenny Halevy if (status == 0) 504693b717fdSTrond Myklebust status = decode_lock_stateid(xdr, &res->stateid); 50471da177e4SLinus Torvalds return status; 50481da177e4SLinus Torvalds } 50491da177e4SLinus Torvalds 5050d3c7b7ccSTrond Myklebust static int decode_release_lockowner(struct xdr_stream *xdr) 5051d3c7b7ccSTrond Myklebust { 5052d3c7b7ccSTrond Myklebust return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER); 5053d3c7b7ccSTrond Myklebust } 5054d3c7b7ccSTrond Myklebust 50551da177e4SLinus Torvalds static int decode_lookup(struct xdr_stream *xdr) 50561da177e4SLinus Torvalds { 50571da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_LOOKUP); 50581da177e4SLinus Torvalds } 50591da177e4SLinus Torvalds 50605b5faaf6SJeff Layton static int decode_lookupp(struct xdr_stream *xdr) 50615b5faaf6SJeff Layton { 50625b5faaf6SJeff Layton return decode_op_hdr(xdr, OP_LOOKUPP); 50635b5faaf6SJeff Layton } 50645b5faaf6SJeff Layton 50651da177e4SLinus Torvalds /* This is too sick! */ 50667d160a6cSTrond Myklebust static int decode_space_limit(struct xdr_stream *xdr, 50677d160a6cSTrond Myklebust unsigned long *pagemod_limit) 50681da177e4SLinus Torvalds { 50698687b63aSAl Viro __be32 *p; 50701da177e4SLinus Torvalds uint32_t limit_type, nblocks, blocksize; 50717d160a6cSTrond Myklebust u64 maxsize = 0; 50721da177e4SLinus Torvalds 5073c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 5074c0eae66eSBenny Halevy if (unlikely(!p)) 5075eb72f484SChuck Lever return -EIO; 50766f723f77SBenny Halevy limit_type = be32_to_cpup(p++); 50771da177e4SLinus Torvalds switch (limit_type) { 50787d160a6cSTrond Myklebust case NFS4_LIMIT_SIZE: 50797d160a6cSTrond Myklebust xdr_decode_hyper(p, &maxsize); 50801da177e4SLinus Torvalds break; 50817d160a6cSTrond Myklebust case NFS4_LIMIT_BLOCKS: 50826f723f77SBenny Halevy nblocks = be32_to_cpup(p++); 5083cccddf4fSBenny Halevy blocksize = be32_to_cpup(p); 50847d160a6cSTrond Myklebust maxsize = (uint64_t)nblocks * (uint64_t)blocksize; 50851da177e4SLinus Torvalds } 508609cbfeafSKirill A. Shutemov maxsize >>= PAGE_SHIFT; 50877d160a6cSTrond Myklebust *pagemod_limit = min_t(u64, maxsize, ULONG_MAX); 50881da177e4SLinus Torvalds return 0; 50891da177e4SLinus Torvalds } 50901da177e4SLinus Torvalds 50916ae37339STrond Myklebust static int decode_rw_delegation(struct xdr_stream *xdr, 50926ae37339STrond Myklebust uint32_t delegation_type, 50936ae37339STrond Myklebust struct nfs_openres *res) 50941da177e4SLinus Torvalds { 50958687b63aSAl Viro __be32 *p; 509607d30434SBenny Halevy int status; 50971da177e4SLinus Torvalds 509893b717fdSTrond Myklebust status = decode_delegation_stateid(xdr, &res->delegation); 509907d30434SBenny Halevy if (unlikely(status)) 510007d30434SBenny Halevy return status; 5101c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 5102c0eae66eSBenny Halevy if (unlikely(!p)) 5103eb72f484SChuck Lever return -EIO; 5104cccddf4fSBenny Halevy res->do_recall = be32_to_cpup(p); 510505d564feSAndy Adamson 51061da177e4SLinus Torvalds switch (delegation_type) { 51071da177e4SLinus Torvalds case NFS4_OPEN_DELEGATE_READ: 51081da177e4SLinus Torvalds res->delegation_type = FMODE_READ; 51091da177e4SLinus Torvalds break; 51101da177e4SLinus Torvalds case NFS4_OPEN_DELEGATE_WRITE: 51111da177e4SLinus Torvalds res->delegation_type = FMODE_WRITE|FMODE_READ; 51127d160a6cSTrond Myklebust if (decode_space_limit(xdr, &res->pagemod_limit) < 0) 51131da177e4SLinus Torvalds return -EIO; 51141da177e4SLinus Torvalds } 51151bbe60ffSTrond Myklebust return decode_ace(xdr, NULL); 51161da177e4SLinus Torvalds } 51171da177e4SLinus Torvalds 51186ae37339STrond Myklebust static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res) 51196ae37339STrond Myklebust { 51206ae37339STrond Myklebust __be32 *p; 51216ae37339STrond Myklebust uint32_t why_no_delegation; 51226ae37339STrond Myklebust 51236ae37339STrond Myklebust p = xdr_inline_decode(xdr, 4); 51246ae37339STrond Myklebust if (unlikely(!p)) 5125eb72f484SChuck Lever return -EIO; 51266ae37339STrond Myklebust why_no_delegation = be32_to_cpup(p); 51276ae37339STrond Myklebust switch (why_no_delegation) { 51286ae37339STrond Myklebust case WND4_CONTENTION: 51296ae37339STrond Myklebust case WND4_RESOURCE: 51306ae37339STrond Myklebust xdr_inline_decode(xdr, 4); 51316ae37339STrond Myklebust /* Ignore for now */ 51326ae37339STrond Myklebust } 51336ae37339STrond Myklebust return 0; 51346ae37339STrond Myklebust } 51356ae37339STrond Myklebust 51366ae37339STrond Myklebust static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) 51376ae37339STrond Myklebust { 51386ae37339STrond Myklebust __be32 *p; 51396ae37339STrond Myklebust uint32_t delegation_type; 51406ae37339STrond Myklebust 51416ae37339STrond Myklebust p = xdr_inline_decode(xdr, 4); 51426ae37339STrond Myklebust if (unlikely(!p)) 5143eb72f484SChuck Lever return -EIO; 51446ae37339STrond Myklebust delegation_type = be32_to_cpup(p); 51456ae37339STrond Myklebust res->delegation_type = 0; 51466ae37339STrond Myklebust switch (delegation_type) { 51476ae37339STrond Myklebust case NFS4_OPEN_DELEGATE_NONE: 51486ae37339STrond Myklebust return 0; 51496ae37339STrond Myklebust case NFS4_OPEN_DELEGATE_READ: 51506ae37339STrond Myklebust case NFS4_OPEN_DELEGATE_WRITE: 51516ae37339STrond Myklebust return decode_rw_delegation(xdr, delegation_type, res); 51526ae37339STrond Myklebust case NFS4_OPEN_DELEGATE_NONE_EXT: 51536ae37339STrond Myklebust return decode_no_delegation(xdr, res); 51546ae37339STrond Myklebust } 51556ae37339STrond Myklebust return -EIO; 51566ae37339STrond Myklebust } 51576ae37339STrond Myklebust 51581da177e4SLinus Torvalds static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) 51591da177e4SLinus Torvalds { 51608687b63aSAl Viro __be32 *p; 5161aa53ed54SJeff Layton uint32_t savewords, bmlen, i; 51621da177e4SLinus Torvalds int status; 51631da177e4SLinus Torvalds 5164c7848f69STrond Myklebust if (!__decode_op_hdr(xdr, OP_OPEN, &status)) 5165c7848f69STrond Myklebust return status; 5166c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 5167c7848f69STrond Myklebust if (status) 5168c7848f69STrond Myklebust return status; 516993b717fdSTrond Myklebust status = decode_open_stateid(xdr, &res->stateid); 517007d30434SBenny Halevy if (unlikely(status)) 51711da177e4SLinus Torvalds return status; 51721da177e4SLinus Torvalds 51731da177e4SLinus Torvalds decode_change_info(xdr, &res->cinfo); 51741da177e4SLinus Torvalds 5175c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5176c0eae66eSBenny Halevy if (unlikely(!p)) 5177eb72f484SChuck Lever return -EIO; 51786f723f77SBenny Halevy res->rflags = be32_to_cpup(p++); 5179cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 51801da177e4SLinus Torvalds if (bmlen > 10) 51811da177e4SLinus Torvalds goto xdr_error; 51821da177e4SLinus Torvalds 5183c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, bmlen << 2); 5184c0eae66eSBenny Halevy if (unlikely(!p)) 5185eb72f484SChuck Lever return -EIO; 5186aa53ed54SJeff Layton savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE); 5187aa53ed54SJeff Layton for (i = 0; i < savewords; ++i) 51886f723f77SBenny Halevy res->attrset[i] = be32_to_cpup(p++); 5189aa53ed54SJeff Layton for (; i < NFS4_BITMAP_SIZE; i++) 5190aa53ed54SJeff Layton res->attrset[i] = 0; 5191aa53ed54SJeff Layton 51921da177e4SLinus Torvalds return decode_delegation(xdr, res); 51931da177e4SLinus Torvalds xdr_error: 51943110ff80SHarvey Harrison dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen); 51951da177e4SLinus Torvalds return -EIO; 51961da177e4SLinus Torvalds } 51971da177e4SLinus Torvalds 51981da177e4SLinus Torvalds static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res) 51991da177e4SLinus Torvalds { 52001da177e4SLinus Torvalds int status; 52011da177e4SLinus Torvalds 52021da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); 5203c1d51931STrond Myklebust if (status != -EIO) 5204c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 520507d30434SBenny Halevy if (!status) 520693b717fdSTrond Myklebust status = decode_open_stateid(xdr, &res->stateid); 52071da177e4SLinus Torvalds return status; 52081da177e4SLinus Torvalds } 52091da177e4SLinus Torvalds 52101da177e4SLinus Torvalds static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res) 52111da177e4SLinus Torvalds { 52121da177e4SLinus Torvalds int status; 52131da177e4SLinus Torvalds 52141da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); 5215c1d51931STrond Myklebust if (status != -EIO) 5216c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 521707d30434SBenny Halevy if (!status) 521893b717fdSTrond Myklebust status = decode_open_stateid(xdr, &res->stateid); 52191da177e4SLinus Torvalds return status; 52201da177e4SLinus Torvalds } 52211da177e4SLinus Torvalds 52221da177e4SLinus Torvalds static int decode_putfh(struct xdr_stream *xdr) 52231da177e4SLinus Torvalds { 52241da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_PUTFH); 52251da177e4SLinus Torvalds } 52261da177e4SLinus Torvalds 52271da177e4SLinus Torvalds static int decode_putrootfh(struct xdr_stream *xdr) 52281da177e4SLinus Torvalds { 52291da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_PUTROOTFH); 52301da177e4SLinus Torvalds } 52311da177e4SLinus Torvalds 52329137bdf3SAnna Schumaker static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, 52339137bdf3SAnna Schumaker struct nfs_pgio_res *res) 52341da177e4SLinus Torvalds { 52358687b63aSAl Viro __be32 *p; 523664bd577eSTrond Myklebust uint32_t count, eof, recvd; 52371da177e4SLinus Torvalds int status; 52381da177e4SLinus Torvalds 52391da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READ); 52401da177e4SLinus Torvalds if (status) 52411da177e4SLinus Torvalds return status; 5242c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5243c0eae66eSBenny Halevy if (unlikely(!p)) 5244eb72f484SChuck Lever return -EIO; 52456f723f77SBenny Halevy eof = be32_to_cpup(p++); 5246cccddf4fSBenny Halevy count = be32_to_cpup(p); 524764bd577eSTrond Myklebust recvd = xdr_read_pages(xdr, count); 52481da177e4SLinus Torvalds if (count > recvd) { 5249fe82a183SChuck Lever dprintk("NFS: server cheating in read reply: " 52501da177e4SLinus Torvalds "count %u > recvd %u\n", count, recvd); 52511da177e4SLinus Torvalds count = recvd; 52521da177e4SLinus Torvalds eof = 0; 52531da177e4SLinus Torvalds } 52541da177e4SLinus Torvalds res->eof = eof; 52551da177e4SLinus Torvalds res->count = count; 52561da177e4SLinus Torvalds return 0; 52571da177e4SLinus Torvalds } 52581da177e4SLinus Torvalds 52591da177e4SLinus Torvalds static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) 52601da177e4SLinus Torvalds { 5261bcecff77SChuck Lever int status; 5262cd93710eSChuck Lever __be32 verf[2]; 52631da177e4SLinus Torvalds 52641da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READDIR); 5265db942bbdSBenny Halevy if (!status) 5266db942bbdSBenny Halevy status = decode_verifier(xdr, readdir->verifier.data); 5267db942bbdSBenny Halevy if (unlikely(status)) 52681da177e4SLinus Torvalds return status; 5269cd93710eSChuck Lever memcpy(verf, readdir->verifier.data, sizeof(verf)); 527044109241SFred Isaman dprintk("%s: verifier = %08x:%08x\n", 5271cd93710eSChuck Lever __func__, verf[0], verf[1]); 527264bd577eSTrond Myklebust return xdr_read_pages(xdr, xdr->buf->page_len); 52731da177e4SLinus Torvalds } 52741da177e4SLinus Torvalds 52751da177e4SLinus Torvalds static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) 52761da177e4SLinus Torvalds { 52771da177e4SLinus Torvalds struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 5278bcecff77SChuck Lever u32 len, recvd; 52798687b63aSAl Viro __be32 *p; 52801da177e4SLinus Torvalds int status; 52811da177e4SLinus Torvalds 52821da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READLINK); 52831da177e4SLinus Torvalds if (status) 52841da177e4SLinus Torvalds return status; 52851da177e4SLinus Torvalds 52861da177e4SLinus Torvalds /* Convert length of symlink */ 5287c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 5288c0eae66eSBenny Halevy if (unlikely(!p)) 5289eb72f484SChuck Lever return -EIO; 5290cccddf4fSBenny Halevy len = be32_to_cpup(p); 52911da177e4SLinus Torvalds if (len >= rcvbuf->page_len || len <= 0) { 5292fe82a183SChuck Lever dprintk("nfs: server returned giant symlink!\n"); 52931da177e4SLinus Torvalds return -ENAMETOOLONG; 52941da177e4SLinus Torvalds } 529564bd577eSTrond Myklebust recvd = xdr_read_pages(xdr, len); 52961da177e4SLinus Torvalds if (recvd < len) { 5297fe82a183SChuck Lever dprintk("NFS: server cheating in readlink reply: " 52981da177e4SLinus Torvalds "count %u > recvd %u\n", len, recvd); 52991da177e4SLinus Torvalds return -EIO; 53001da177e4SLinus Torvalds } 53011da177e4SLinus Torvalds /* 53021da177e4SLinus Torvalds * The XDR encode routine has set things up so that 53031da177e4SLinus Torvalds * the link text will be copied directly into the 53041da177e4SLinus Torvalds * buffer. We just have to do overflow-checking, 5305a5032910SRandy Dunlap * and null-terminate the text (the VFS expects 53061da177e4SLinus Torvalds * null-termination). 53071da177e4SLinus Torvalds */ 5308b4687da7SChuck Lever xdr_terminate_string(rcvbuf, len); 53091da177e4SLinus Torvalds return 0; 53101da177e4SLinus Torvalds } 53111da177e4SLinus Torvalds 53121da177e4SLinus Torvalds static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 53131da177e4SLinus Torvalds { 53141da177e4SLinus Torvalds int status; 53151da177e4SLinus Torvalds 53161da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_REMOVE); 53171da177e4SLinus Torvalds if (status) 53181da177e4SLinus Torvalds goto out; 53191da177e4SLinus Torvalds status = decode_change_info(xdr, cinfo); 53201da177e4SLinus Torvalds out: 53211da177e4SLinus Torvalds return status; 53221da177e4SLinus Torvalds } 53231da177e4SLinus Torvalds 53241da177e4SLinus Torvalds static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo, 53251da177e4SLinus Torvalds struct nfs4_change_info *new_cinfo) 53261da177e4SLinus Torvalds { 53271da177e4SLinus Torvalds int status; 53281da177e4SLinus Torvalds 53291da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_RENAME); 53301da177e4SLinus Torvalds if (status) 53311da177e4SLinus Torvalds goto out; 53321da177e4SLinus Torvalds if ((status = decode_change_info(xdr, old_cinfo))) 53331da177e4SLinus Torvalds goto out; 53341da177e4SLinus Torvalds status = decode_change_info(xdr, new_cinfo); 53351da177e4SLinus Torvalds out: 53361da177e4SLinus Torvalds return status; 53371da177e4SLinus Torvalds } 53381da177e4SLinus Torvalds 53391da177e4SLinus Torvalds static int decode_renew(struct xdr_stream *xdr) 53401da177e4SLinus Torvalds { 53411da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_RENEW); 53421da177e4SLinus Torvalds } 53431da177e4SLinus Torvalds 534456ae19f3STrond Myklebust static int 534556ae19f3STrond Myklebust decode_restorefh(struct xdr_stream *xdr) 534656ae19f3STrond Myklebust { 534756ae19f3STrond Myklebust return decode_op_hdr(xdr, OP_RESTOREFH); 534856ae19f3STrond Myklebust } 534956ae19f3STrond Myklebust 5350029d105eSJ. Bruce Fields static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, 5351bf118a34SAndy Adamson struct nfs_getaclres *res) 5352029d105eSJ. Bruce Fields { 5353256e48bbSTrond Myklebust unsigned int savep; 5354029d105eSJ. Bruce Fields uint32_t attrlen, 5355dae100c2SFred Isaman bitmap[3] = {0}; 5356029d105eSJ. Bruce Fields int status; 5357029d105eSJ. Bruce Fields 5358bf118a34SAndy Adamson res->acl_len = 0; 5359029d105eSJ. Bruce Fields if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 5360029d105eSJ. Bruce Fields goto out; 53615a006899SSachin Prabhu 5362519d3959STrond Myklebust xdr_enter_page(xdr, xdr->buf->page_len); 5363519d3959STrond Myklebust 5364029d105eSJ. Bruce Fields if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 5365029d105eSJ. Bruce Fields goto out; 5366029d105eSJ. Bruce Fields if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 5367029d105eSJ. Bruce Fields goto out; 5368029d105eSJ. Bruce Fields 5369029d105eSJ. Bruce Fields if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) 5370029d105eSJ. Bruce Fields return -EIO; 5371029d105eSJ. Bruce Fields if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { 5372029d105eSJ. Bruce Fields 5373bf118a34SAndy Adamson /* The bitmap (xdr len + bitmaps) and the attr xdr len words 5374bf118a34SAndy Adamson * are stored with the acl data to handle the problem of 5375bf118a34SAndy Adamson * variable length bitmaps.*/ 5376a14a6359SAnna Schumaker res->acl_data_offset = xdr_page_pos(xdr); 5377519d3959STrond Myklebust res->acl_len = attrlen; 53781f1ea6c2STrond Myklebust 53791f1ea6c2STrond Myklebust /* Check for receive buffer overflow */ 538017068466STrond Myklebust if (res->acl_len > xdr_stream_remaining(xdr) || 53811f1ea6c2STrond Myklebust res->acl_len + res->acl_data_offset > xdr->buf->page_len) { 53821f1ea6c2STrond Myklebust res->acl_flags |= NFS4_ACL_TRUNC; 538317068466STrond Myklebust dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", 538417068466STrond Myklebust attrlen, xdr_stream_remaining(xdr)); 5385029d105eSJ. Bruce Fields } 53868c233cf9SJ. Bruce Fields } else 53878c233cf9SJ. Bruce Fields status = -EOPNOTSUPP; 5388029d105eSJ. Bruce Fields 5389029d105eSJ. Bruce Fields out: 5390029d105eSJ. Bruce Fields return status; 5391029d105eSJ. Bruce Fields } 5392029d105eSJ. Bruce Fields 53931da177e4SLinus Torvalds static int 53941da177e4SLinus Torvalds decode_savefh(struct xdr_stream *xdr) 53951da177e4SLinus Torvalds { 53961da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_SAVEFH); 53971da177e4SLinus Torvalds } 53981da177e4SLinus Torvalds 53999e9ecc03SBenny Halevy static int decode_setattr(struct xdr_stream *xdr) 54001da177e4SLinus Torvalds { 54011da177e4SLinus Torvalds int status; 54021da177e4SLinus Torvalds 54031da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_SETATTR); 54041da177e4SLinus Torvalds if (status) 54051da177e4SLinus Torvalds return status; 540637c88763STrond Myklebust if (decode_bitmap4(xdr, NULL, 0) >= 0) 54071da177e4SLinus Torvalds return 0; 5408c0eae66eSBenny Halevy return -EIO; 54091da177e4SLinus Torvalds } 54101da177e4SLinus Torvalds 5411bb8b27e5STrond Myklebust static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res) 54121da177e4SLinus Torvalds { 54138687b63aSAl Viro __be32 *p; 54141da177e4SLinus Torvalds uint32_t opnum; 54151da177e4SLinus Torvalds int32_t nfserr; 54161da177e4SLinus Torvalds 5417c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5418c0eae66eSBenny Halevy if (unlikely(!p)) 5419eb72f484SChuck Lever return -EIO; 54206f723f77SBenny Halevy opnum = be32_to_cpup(p++); 54211da177e4SLinus Torvalds if (opnum != OP_SETCLIENTID) { 5422fe82a183SChuck Lever dprintk("nfs: decode_setclientid: Server returned operation" 54231da177e4SLinus Torvalds " %d\n", opnum); 54241da177e4SLinus Torvalds return -EIO; 54251da177e4SLinus Torvalds } 5426cccddf4fSBenny Halevy nfserr = be32_to_cpup(p); 54271da177e4SLinus Torvalds if (nfserr == NFS_OK) { 5428c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE); 5429c0eae66eSBenny Halevy if (unlikely(!p)) 5430eb72f484SChuck Lever return -EIO; 5431bb8b27e5STrond Myklebust p = xdr_decode_hyper(p, &res->clientid); 5432bb8b27e5STrond Myklebust memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE); 54331da177e4SLinus Torvalds } else if (nfserr == NFSERR_CLID_INUSE) { 54341da177e4SLinus Torvalds uint32_t len; 54351da177e4SLinus Torvalds 54361da177e4SLinus Torvalds /* skip netid string */ 5437c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 5438c0eae66eSBenny Halevy if (unlikely(!p)) 5439eb72f484SChuck Lever return -EIO; 5440cccddf4fSBenny Halevy len = be32_to_cpup(p); 5441c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 5442c0eae66eSBenny Halevy if (unlikely(!p)) 5443eb72f484SChuck Lever return -EIO; 54441da177e4SLinus Torvalds 54451da177e4SLinus Torvalds /* skip uaddr string */ 5446c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 5447c0eae66eSBenny Halevy if (unlikely(!p)) 5448eb72f484SChuck Lever return -EIO; 5449cccddf4fSBenny Halevy len = be32_to_cpup(p); 5450c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 5451c0eae66eSBenny Halevy if (unlikely(!p)) 5452eb72f484SChuck Lever return -EIO; 54531da177e4SLinus Torvalds return -NFSERR_CLID_INUSE; 54541da177e4SLinus Torvalds } else 5455856dff3dSBenny Halevy return nfs4_stat_to_errno(nfserr); 54561da177e4SLinus Torvalds 54571da177e4SLinus Torvalds return 0; 54581da177e4SLinus Torvalds } 54591da177e4SLinus Torvalds 54601da177e4SLinus Torvalds static int decode_setclientid_confirm(struct xdr_stream *xdr) 54611da177e4SLinus Torvalds { 54621da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM); 54631da177e4SLinus Torvalds } 54641da177e4SLinus Torvalds 54659137bdf3SAnna Schumaker static int decode_write(struct xdr_stream *xdr, struct nfs_pgio_res *res) 54661da177e4SLinus Torvalds { 54678687b63aSAl Viro __be32 *p; 54681da177e4SLinus Torvalds int status; 54691da177e4SLinus Torvalds 54701da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_WRITE); 54711da177e4SLinus Torvalds if (status) 54721da177e4SLinus Torvalds return status; 54731da177e4SLinus Torvalds 54742f2c63bcSTrond Myklebust p = xdr_inline_decode(xdr, 8); 5475c0eae66eSBenny Halevy if (unlikely(!p)) 5476eb72f484SChuck Lever return -EIO; 54776f723f77SBenny Halevy res->count = be32_to_cpup(p++); 54786f723f77SBenny Halevy res->verf->committed = be32_to_cpup(p++); 54792f2c63bcSTrond Myklebust return decode_write_verifier(xdr, &res->verf->verifier); 54801da177e4SLinus Torvalds } 54811da177e4SLinus Torvalds 54821da177e4SLinus Torvalds static int decode_delegreturn(struct xdr_stream *xdr) 54831da177e4SLinus Torvalds { 54841da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_DELEGRETURN); 54851da177e4SLinus Torvalds } 54861da177e4SLinus Torvalds 5487fb15b26fSChuck Lever static int decode_secinfo_gss(struct xdr_stream *xdr, 5488fb15b26fSChuck Lever struct nfs4_secinfo4 *flavor) 54895a5ea0d4SBryan Schumaker { 5490fb15b26fSChuck Lever u32 oid_len; 54915a5ea0d4SBryan Schumaker __be32 *p; 54925a5ea0d4SBryan Schumaker 54935a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 4); 54945a5ea0d4SBryan Schumaker if (unlikely(!p)) 5495eb72f484SChuck Lever return -EIO; 5496fb15b26fSChuck Lever oid_len = be32_to_cpup(p); 5497fb15b26fSChuck Lever if (oid_len > GSS_OID_MAX_LEN) 5498eb72f484SChuck Lever return -EINVAL; 54995a5ea0d4SBryan Schumaker 5500fb15b26fSChuck Lever p = xdr_inline_decode(xdr, oid_len); 55015a5ea0d4SBryan Schumaker if (unlikely(!p)) 5502eb72f484SChuck Lever return -EIO; 5503fb15b26fSChuck Lever memcpy(flavor->flavor_info.oid.data, p, oid_len); 5504fb15b26fSChuck Lever flavor->flavor_info.oid.len = oid_len; 55055a5ea0d4SBryan Schumaker 55065a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 8); 55075a5ea0d4SBryan Schumaker if (unlikely(!p)) 5508eb72f484SChuck Lever return -EIO; 5509fb15b26fSChuck Lever flavor->flavor_info.qop = be32_to_cpup(p++); 5510fb15b26fSChuck Lever flavor->flavor_info.service = be32_to_cpup(p); 55115a5ea0d4SBryan Schumaker 55125a5ea0d4SBryan Schumaker return 0; 55135a5ea0d4SBryan Schumaker } 55145a5ea0d4SBryan Schumaker 551531e4dda4SBryan Schumaker static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) 55165a5ea0d4SBryan Schumaker { 5517fb15b26fSChuck Lever struct nfs4_secinfo4 *sec_flavor; 5518fb15b26fSChuck Lever unsigned int i, num_flavors; 55195a5ea0d4SBryan Schumaker int status; 55205a5ea0d4SBryan Schumaker __be32 *p; 55215a5ea0d4SBryan Schumaker 55225a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 4); 55235a5ea0d4SBryan Schumaker if (unlikely(!p)) 5524eb72f484SChuck Lever return -EIO; 55255a5ea0d4SBryan Schumaker 5526c3dfc280SBryan Schumaker res->flavors->num_flavors = 0; 5527c3dfc280SBryan Schumaker num_flavors = be32_to_cpup(p); 5528c3dfc280SBryan Schumaker 5529c3dfc280SBryan Schumaker for (i = 0; i < num_flavors; i++) { 55305a5ea0d4SBryan Schumaker sec_flavor = &res->flavors->flavors[i]; 5531c3dfc280SBryan Schumaker if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE) 55325a5ea0d4SBryan Schumaker break; 55335a5ea0d4SBryan Schumaker 55345a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 4); 55355a5ea0d4SBryan Schumaker if (unlikely(!p)) 5536eb72f484SChuck Lever return -EIO; 55375a5ea0d4SBryan Schumaker sec_flavor->flavor = be32_to_cpup(p); 55385a5ea0d4SBryan Schumaker 55395a5ea0d4SBryan Schumaker if (sec_flavor->flavor == RPC_AUTH_GSS) { 5540613e901eSBryan Schumaker status = decode_secinfo_gss(xdr, sec_flavor); 5541613e901eSBryan Schumaker if (status) 5542613e901eSBryan Schumaker goto out; 55435a5ea0d4SBryan Schumaker } 5544c3dfc280SBryan Schumaker res->flavors->num_flavors++; 55455a5ea0d4SBryan Schumaker } 55465a5ea0d4SBryan Schumaker 554731e4dda4SBryan Schumaker status = 0; 5548613e901eSBryan Schumaker out: 5549613e901eSBryan Schumaker return status; 55505a5ea0d4SBryan Schumaker } 55515a5ea0d4SBryan Schumaker 555231e4dda4SBryan Schumaker static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) 555331e4dda4SBryan Schumaker { 555431e4dda4SBryan Schumaker int status = decode_op_hdr(xdr, OP_SECINFO); 555531e4dda4SBryan Schumaker if (status) 555631e4dda4SBryan Schumaker return status; 555731e4dda4SBryan Schumaker return decode_secinfo_common(xdr, res); 555831e4dda4SBryan Schumaker } 555931e4dda4SBryan Schumaker 556099fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 556131e4dda4SBryan Schumaker static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) 556231e4dda4SBryan Schumaker { 556331e4dda4SBryan Schumaker int status = decode_op_hdr(xdr, OP_SECINFO_NO_NAME); 556431e4dda4SBryan Schumaker if (status) 556531e4dda4SBryan Schumaker return status; 556631e4dda4SBryan Schumaker return decode_secinfo_common(xdr, res); 556731e4dda4SBryan Schumaker } 556831e4dda4SBryan Schumaker 55692031cd1aSWeston Andros Adamson static int decode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map) 55702031cd1aSWeston Andros Adamson { 5571f114759cSTrond Myklebust if (xdr_stream_decode_uint32_array(xdr, op_map->u.words, 5572f114759cSTrond Myklebust ARRAY_SIZE(op_map->u.words)) < 0) 55734edabfd7SPan Bian return -EIO; 55742031cd1aSWeston Andros Adamson return 0; 55752031cd1aSWeston Andros Adamson } 55762031cd1aSWeston Andros Adamson 557799fe60d0SBenny Halevy static int decode_exchange_id(struct xdr_stream *xdr, 557899fe60d0SBenny Halevy struct nfs41_exchange_id_res *res) 557999fe60d0SBenny Halevy { 558099fe60d0SBenny Halevy __be32 *p; 558199fe60d0SBenny Halevy uint32_t dummy; 55822460ba57SBenny Halevy char *dummy_str; 558399fe60d0SBenny Halevy int status; 55847d2ed9acSWeston Andros Adamson uint32_t impl_id_count; 558599fe60d0SBenny Halevy 558699fe60d0SBenny Halevy status = decode_op_hdr(xdr, OP_EXCHANGE_ID); 558799fe60d0SBenny Halevy if (status) 558899fe60d0SBenny Halevy return status; 558999fe60d0SBenny Halevy 5590c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5591c0eae66eSBenny Halevy if (unlikely(!p)) 5592eb72f484SChuck Lever return -EIO; 559332b01310STrond Myklebust xdr_decode_hyper(p, &res->clientid); 5594c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 5595c0eae66eSBenny Halevy if (unlikely(!p)) 5596eb72f484SChuck Lever return -EIO; 559732b01310STrond Myklebust res->seqid = be32_to_cpup(p++); 559832b01310STrond Myklebust res->flags = be32_to_cpup(p++); 559999fe60d0SBenny Halevy 56002031cd1aSWeston Andros Adamson res->state_protect.how = be32_to_cpup(p); 56012031cd1aSWeston Andros Adamson switch (res->state_protect.how) { 56022031cd1aSWeston Andros Adamson case SP4_NONE: 56032031cd1aSWeston Andros Adamson break; 56042031cd1aSWeston Andros Adamson case SP4_MACH_CRED: 56052031cd1aSWeston Andros Adamson status = decode_op_map(xdr, &res->state_protect.enforce); 56062031cd1aSWeston Andros Adamson if (status) 56072031cd1aSWeston Andros Adamson return status; 56082031cd1aSWeston Andros Adamson status = decode_op_map(xdr, &res->state_protect.allow); 56092031cd1aSWeston Andros Adamson if (status) 56102031cd1aSWeston Andros Adamson return status; 56112031cd1aSWeston Andros Adamson break; 56122031cd1aSWeston Andros Adamson default: 56132031cd1aSWeston Andros Adamson WARN_ON_ONCE(1); 561499fe60d0SBenny Halevy return -EIO; 56152031cd1aSWeston Andros Adamson } 561699fe60d0SBenny Halevy 5617acdeb69dSChuck Lever /* server_owner4.so_minor_id */ 5618c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5619c0eae66eSBenny Halevy if (unlikely(!p)) 5620eb72f484SChuck Lever return -EIO; 5621acdeb69dSChuck Lever p = xdr_decode_hyper(p, &res->server_owner->minor_id); 562299fe60d0SBenny Halevy 5623acdeb69dSChuck Lever /* server_owner4.so_major_id */ 56242460ba57SBenny Halevy status = decode_opaque_inline(xdr, &dummy, &dummy_str); 56252460ba57SBenny Halevy if (unlikely(status)) 56262460ba57SBenny Halevy return status; 5627acdeb69dSChuck Lever memcpy(res->server_owner->major_id, dummy_str, dummy); 5628acdeb69dSChuck Lever res->server_owner->major_id_sz = dummy; 562978fe0f41SWeston Andros Adamson 5630acdeb69dSChuck Lever /* server_scope4 */ 5631acdeb69dSChuck Lever status = decode_opaque_inline(xdr, &dummy, &dummy_str); 5632acdeb69dSChuck Lever if (unlikely(status)) 5633acdeb69dSChuck Lever return status; 563478fe0f41SWeston Andros Adamson memcpy(res->server_scope->server_scope, dummy_str, dummy); 563578fe0f41SWeston Andros Adamson res->server_scope->server_scope_sz = dummy; 563678fe0f41SWeston Andros Adamson 56377d2ed9acSWeston Andros Adamson /* Implementation Id */ 56387d2ed9acSWeston Andros Adamson p = xdr_inline_decode(xdr, 4); 56397d2ed9acSWeston Andros Adamson if (unlikely(!p)) 5640eb72f484SChuck Lever return -EIO; 56417d2ed9acSWeston Andros Adamson impl_id_count = be32_to_cpup(p++); 56427d2ed9acSWeston Andros Adamson 56437d2ed9acSWeston Andros Adamson if (impl_id_count) { 56447d2ed9acSWeston Andros Adamson /* nii_domain */ 56452460ba57SBenny Halevy status = decode_opaque_inline(xdr, &dummy, &dummy_str); 56462460ba57SBenny Halevy if (unlikely(status)) 56472460ba57SBenny Halevy return status; 56487d2ed9acSWeston Andros Adamson memcpy(res->impl_id->domain, dummy_str, dummy); 564999fe60d0SBenny Halevy 56507d2ed9acSWeston Andros Adamson /* nii_name */ 56517d2ed9acSWeston Andros Adamson status = decode_opaque_inline(xdr, &dummy, &dummy_str); 56527d2ed9acSWeston Andros Adamson if (unlikely(status)) 56537d2ed9acSWeston Andros Adamson return status; 56547d2ed9acSWeston Andros Adamson memcpy(res->impl_id->name, dummy_str, dummy); 56557d2ed9acSWeston Andros Adamson 56567d2ed9acSWeston Andros Adamson /* nii_date */ 56577d2ed9acSWeston Andros Adamson p = xdr_inline_decode(xdr, 12); 56587d2ed9acSWeston Andros Adamson if (unlikely(!p)) 5659eb72f484SChuck Lever return -EIO; 56607d2ed9acSWeston Andros Adamson p = xdr_decode_hyper(p, &res->impl_id->date.seconds); 56617d2ed9acSWeston Andros Adamson res->impl_id->date.nseconds = be32_to_cpup(p); 56627d2ed9acSWeston Andros Adamson 56637d2ed9acSWeston Andros Adamson /* if there's more than one entry, ignore the rest */ 56647d2ed9acSWeston Andros Adamson } 566599fe60d0SBenny Halevy return 0; 566699fe60d0SBenny Halevy } 5667fc931582SAndy Adamson 5668fc931582SAndy Adamson static int decode_chan_attrs(struct xdr_stream *xdr, 5669fc931582SAndy Adamson struct nfs4_channel_attrs *attrs) 5670fc931582SAndy Adamson { 5671fc931582SAndy Adamson __be32 *p; 5672c9c30dd5SBenny Halevy u32 nr_attrs, val; 5673fc931582SAndy Adamson 5674c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 28); 5675c0eae66eSBenny Halevy if (unlikely(!p)) 5676eb72f484SChuck Lever return -EIO; 5677c9c30dd5SBenny Halevy val = be32_to_cpup(p++); /* headerpadsz */ 5678c9c30dd5SBenny Halevy if (val) 5679c9c30dd5SBenny Halevy return -EINVAL; /* no support for header padding yet */ 56806f723f77SBenny Halevy attrs->max_rqst_sz = be32_to_cpup(p++); 56816f723f77SBenny Halevy attrs->max_resp_sz = be32_to_cpup(p++); 56826f723f77SBenny Halevy attrs->max_resp_sz_cached = be32_to_cpup(p++); 56836f723f77SBenny Halevy attrs->max_ops = be32_to_cpup(p++); 56846f723f77SBenny Halevy attrs->max_reqs = be32_to_cpup(p++); 5685cccddf4fSBenny Halevy nr_attrs = be32_to_cpup(p); 5686fc931582SAndy Adamson if (unlikely(nr_attrs > 1)) { 5687a030889aSWeston Andros Adamson printk(KERN_WARNING "NFS: %s: Invalid rdma channel attrs " 5688a030889aSWeston Andros Adamson "count %u\n", __func__, nr_attrs); 5689fc931582SAndy Adamson return -EINVAL; 5690fc931582SAndy Adamson } 5691c0eae66eSBenny Halevy if (nr_attrs == 1) { 5692c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */ 5693c0eae66eSBenny Halevy if (unlikely(!p)) 5694eb72f484SChuck Lever return -EIO; 5695c0eae66eSBenny Halevy } 5696fc931582SAndy Adamson return 0; 5697fc931582SAndy Adamson } 5698fc931582SAndy Adamson 5699e78291e4SBenny Halevy static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid) 5700e78291e4SBenny Halevy { 5701e78291e4SBenny Halevy return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN); 5702fc931582SAndy Adamson } 5703fc931582SAndy Adamson 57047c44f1aeSWeston Andros Adamson static int decode_bind_conn_to_session(struct xdr_stream *xdr, 57057c44f1aeSWeston Andros Adamson struct nfs41_bind_conn_to_session_res *res) 57067c44f1aeSWeston Andros Adamson { 57077c44f1aeSWeston Andros Adamson __be32 *p; 57087c44f1aeSWeston Andros Adamson int status; 57097c44f1aeSWeston Andros Adamson 57107c44f1aeSWeston Andros Adamson status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION); 57117c44f1aeSWeston Andros Adamson if (!status) 571271a097c6STrond Myklebust status = decode_sessionid(xdr, &res->sessionid); 57137c44f1aeSWeston Andros Adamson if (unlikely(status)) 57147c44f1aeSWeston Andros Adamson return status; 57157c44f1aeSWeston Andros Adamson 57167c44f1aeSWeston Andros Adamson /* dir flags, rdma mode bool */ 57177c44f1aeSWeston Andros Adamson p = xdr_inline_decode(xdr, 8); 57187c44f1aeSWeston Andros Adamson if (unlikely(!p)) 5719eb72f484SChuck Lever return -EIO; 57207c44f1aeSWeston Andros Adamson 57217c44f1aeSWeston Andros Adamson res->dir = be32_to_cpup(p++); 57227c44f1aeSWeston Andros Adamson if (res->dir == 0 || res->dir > NFS4_CDFS4_BOTH) 57237c44f1aeSWeston Andros Adamson return -EIO; 57247c44f1aeSWeston Andros Adamson if (be32_to_cpup(p) == 0) 57257c44f1aeSWeston Andros Adamson res->use_conn_in_rdma_mode = false; 57267c44f1aeSWeston Andros Adamson else 57277c44f1aeSWeston Andros Adamson res->use_conn_in_rdma_mode = true; 57287c44f1aeSWeston Andros Adamson 57297c44f1aeSWeston Andros Adamson return 0; 57307c44f1aeSWeston Andros Adamson } 57317c44f1aeSWeston Andros Adamson 5732fc931582SAndy Adamson static int decode_create_session(struct xdr_stream *xdr, 5733fc931582SAndy Adamson struct nfs41_create_session_res *res) 5734fc931582SAndy Adamson { 5735fc931582SAndy Adamson __be32 *p; 5736fc931582SAndy Adamson int status; 5737fc931582SAndy Adamson 5738fc931582SAndy Adamson status = decode_op_hdr(xdr, OP_CREATE_SESSION); 5739e78291e4SBenny Halevy if (!status) 574079969dd1STrond Myklebust status = decode_sessionid(xdr, &res->sessionid); 5741e78291e4SBenny Halevy if (unlikely(status)) 5742fc931582SAndy Adamson return status; 5743fc931582SAndy Adamson 5744fc931582SAndy Adamson /* seqid, flags */ 5745c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5746c0eae66eSBenny Halevy if (unlikely(!p)) 5747eb72f484SChuck Lever return -EIO; 574879969dd1STrond Myklebust res->seqid = be32_to_cpup(p++); 574979969dd1STrond Myklebust res->flags = be32_to_cpup(p); 5750fc931582SAndy Adamson 5751fc931582SAndy Adamson /* Channel attributes */ 575279969dd1STrond Myklebust status = decode_chan_attrs(xdr, &res->fc_attrs); 5753fc931582SAndy Adamson if (!status) 575479969dd1STrond Myklebust status = decode_chan_attrs(xdr, &res->bc_attrs); 5755fc931582SAndy Adamson return status; 5756fc931582SAndy Adamson } 57570f3e66c6SAndy Adamson 57580f3e66c6SAndy Adamson static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) 57590f3e66c6SAndy Adamson { 57600f3e66c6SAndy Adamson return decode_op_hdr(xdr, OP_DESTROY_SESSION); 57610f3e66c6SAndy Adamson } 576218019753SRicardo Labiaga 576366245539STrond Myklebust static int decode_destroy_clientid(struct xdr_stream *xdr, void *dummy) 576466245539STrond Myklebust { 576566245539STrond Myklebust return decode_op_hdr(xdr, OP_DESTROY_CLIENTID); 576666245539STrond Myklebust } 576766245539STrond Myklebust 576818019753SRicardo Labiaga static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) 576918019753SRicardo Labiaga { 577018019753SRicardo Labiaga return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); 577118019753SRicardo Labiaga } 577299fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 577399fe60d0SBenny Halevy 57749b7b9fccSAndy Adamson static int decode_sequence(struct xdr_stream *xdr, 57759b7b9fccSAndy Adamson struct nfs4_sequence_res *res, 57769b7b9fccSAndy Adamson struct rpc_rqst *rqstp) 57779b7b9fccSAndy Adamson { 57789b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 5779e3725ec0STrond Myklebust struct nfs4_session *session; 5780fc01cea9SAndy Adamson struct nfs4_sessionid id; 5781fc01cea9SAndy Adamson u32 dummy; 5782fc01cea9SAndy Adamson int status; 5783fc01cea9SAndy Adamson __be32 *p; 5784fc01cea9SAndy Adamson 5785e3725ec0STrond Myklebust if (res->sr_slot == NULL) 57869b7b9fccSAndy Adamson return 0; 57873bd2384aSChuck Lever if (!res->sr_slot->table->session) 57883bd2384aSChuck Lever return 0; 57899b7b9fccSAndy Adamson 5790fc01cea9SAndy Adamson status = decode_op_hdr(xdr, OP_SEQUENCE); 5791e78291e4SBenny Halevy if (!status) 5792e78291e4SBenny Halevy status = decode_sessionid(xdr, &id); 5793e78291e4SBenny Halevy if (unlikely(status)) 5794fc01cea9SAndy Adamson goto out_err; 57959b7b9fccSAndy Adamson 5796fc01cea9SAndy Adamson /* 5797fc01cea9SAndy Adamson * If the server returns different values for sessionID, slotID or 5798fc01cea9SAndy Adamson * sequence number, the server is looney tunes. 5799fc01cea9SAndy Adamson */ 5800fdcb4577STrond Myklebust status = -EREMOTEIO; 5801e3725ec0STrond Myklebust session = res->sr_slot->table->session; 5802fc01cea9SAndy Adamson 5803e3725ec0STrond Myklebust if (memcmp(id.data, session->sess_id.data, 5804fc01cea9SAndy Adamson NFS4_MAX_SESSIONID_LEN)) { 5805fc01cea9SAndy Adamson dprintk("%s Invalid session id\n", __func__); 5806fc01cea9SAndy Adamson goto out_err; 5807fc01cea9SAndy Adamson } 5808e78291e4SBenny Halevy 5809c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 20); 5810c0eae66eSBenny Halevy if (unlikely(!p)) 5811c0eae66eSBenny Halevy goto out_overflow; 5812e78291e4SBenny Halevy 5813fc01cea9SAndy Adamson /* seqid */ 58146f723f77SBenny Halevy dummy = be32_to_cpup(p++); 5815dfb4f309SBenny Halevy if (dummy != res->sr_slot->seq_nr) { 5816fc01cea9SAndy Adamson dprintk("%s Invalid sequence number\n", __func__); 5817fc01cea9SAndy Adamson goto out_err; 5818fc01cea9SAndy Adamson } 5819fc01cea9SAndy Adamson /* slot id */ 58206f723f77SBenny Halevy dummy = be32_to_cpup(p++); 5821df2fabffSTrond Myklebust if (dummy != res->sr_slot->slot_nr) { 5822fc01cea9SAndy Adamson dprintk("%s Invalid slot id\n", __func__); 5823fc01cea9SAndy Adamson goto out_err; 5824fc01cea9SAndy Adamson } 5825da0507b7STrond Myklebust /* highest slot id */ 5826da0507b7STrond Myklebust res->sr_highest_slotid = be32_to_cpup(p++); 5827464ee9f9STrond Myklebust /* target highest slot id */ 5828464ee9f9STrond Myklebust res->sr_target_highest_slotid = be32_to_cpup(p++); 58290629e370SAlexandros Batsakis /* result flags */ 58300629e370SAlexandros Batsakis res->sr_status_flags = be32_to_cpup(p); 5831fc01cea9SAndy Adamson status = 0; 5832fc01cea9SAndy Adamson out_err: 5833fc01cea9SAndy Adamson res->sr_status = status; 5834fc01cea9SAndy Adamson return status; 5835c0eae66eSBenny Halevy out_overflow: 5836c0eae66eSBenny Halevy status = -EIO; 5837c0eae66eSBenny Halevy goto out_err; 5838fc01cea9SAndy Adamson #else /* CONFIG_NFS_V4_1 */ 58399b7b9fccSAndy Adamson return 0; 5840fc01cea9SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 58419b7b9fccSAndy Adamson } 58429b7b9fccSAndy Adamson 5843b1f69b75SAndy Adamson #if defined(CONFIG_NFS_V4_1) 584493b717fdSTrond Myklebust static int decode_layout_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 584593b717fdSTrond Myklebust { 584693b717fdSTrond Myklebust stateid->type = NFS4_LAYOUT_STATEID_TYPE; 584793b717fdSTrond Myklebust return decode_stateid(xdr, stateid); 584893b717fdSTrond Myklebust } 584993b717fdSTrond Myklebust 5850b1f69b75SAndy Adamson static int decode_getdeviceinfo(struct xdr_stream *xdr, 58514e590803STrond Myklebust struct nfs4_getdeviceinfo_res *res) 5852b1f69b75SAndy Adamson { 58534e590803STrond Myklebust struct pnfs_device *pdev = res->pdev; 5854b1f69b75SAndy Adamson __be32 *p; 5855b1f69b75SAndy Adamson uint32_t len, type; 5856b1f69b75SAndy Adamson int status; 5857b1f69b75SAndy Adamson 5858b1f69b75SAndy Adamson status = decode_op_hdr(xdr, OP_GETDEVICEINFO); 5859b1f69b75SAndy Adamson if (status) { 5860b1f69b75SAndy Adamson if (status == -ETOOSMALL) { 5861b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4); 5862b1f69b75SAndy Adamson if (unlikely(!p)) 5863eb72f484SChuck Lever return -EIO; 5864b1f69b75SAndy Adamson pdev->mincount = be32_to_cpup(p); 5865b1f69b75SAndy Adamson dprintk("%s: Min count too small. mincnt = %u\n", 5866b1f69b75SAndy Adamson __func__, pdev->mincount); 5867b1f69b75SAndy Adamson } 5868b1f69b75SAndy Adamson return status; 5869b1f69b75SAndy Adamson } 5870b1f69b75SAndy Adamson 5871b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 8); 5872b1f69b75SAndy Adamson if (unlikely(!p)) 5873eb72f484SChuck Lever return -EIO; 5874b1f69b75SAndy Adamson type = be32_to_cpup(p++); 5875b1f69b75SAndy Adamson if (type != pdev->layout_type) { 5876b1f69b75SAndy Adamson dprintk("%s: layout mismatch req: %u pdev: %u\n", 5877b1f69b75SAndy Adamson __func__, pdev->layout_type, type); 5878b1f69b75SAndy Adamson return -EINVAL; 5879b1f69b75SAndy Adamson } 5880b1f69b75SAndy Adamson /* 5881b1f69b75SAndy Adamson * Get the length of the opaque device_addr4. xdr_read_pages places 5882b1f69b75SAndy Adamson * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages) 5883b1f69b75SAndy Adamson * and places the remaining xdr data in xdr_buf->tail 5884b1f69b75SAndy Adamson */ 5885b1f69b75SAndy Adamson pdev->mincount = be32_to_cpup(p); 588613fe4ba1STrond Myklebust if (xdr_read_pages(xdr, pdev->mincount) != pdev->mincount) 5887eb72f484SChuck Lever return -EIO; 5888b1f69b75SAndy Adamson 5889b1f69b75SAndy Adamson /* Parse notification bitmap, verifying that it is zero. */ 5890b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4); 5891b1f69b75SAndy Adamson if (unlikely(!p)) 5892eb72f484SChuck Lever return -EIO; 5893b1f69b75SAndy Adamson len = be32_to_cpup(p); 5894b1f69b75SAndy Adamson if (len) { 5895ead00597SChuck Lever uint32_t i; 5896b1f69b75SAndy Adamson 5897b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4 * len); 5898b1f69b75SAndy Adamson if (unlikely(!p)) 5899eb72f484SChuck Lever return -EIO; 590084c9dee3SChristoph Hellwig 59014e590803STrond Myklebust res->notification = be32_to_cpup(p++); 590284c9dee3SChristoph Hellwig for (i = 1; i < len; i++) { 590384c9dee3SChristoph Hellwig if (be32_to_cpup(p++)) { 590484c9dee3SChristoph Hellwig dprintk("%s: unsupported notification\n", 5905b1f69b75SAndy Adamson __func__); 5906b1f69b75SAndy Adamson return -EIO; 5907b1f69b75SAndy Adamson } 5908b1f69b75SAndy Adamson } 5909b1f69b75SAndy Adamson } 5910b1f69b75SAndy Adamson return 0; 5911b1f69b75SAndy Adamson } 5912b1f69b75SAndy Adamson 5913b1f69b75SAndy Adamson static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, 5914b1f69b75SAndy Adamson struct nfs4_layoutget_res *res) 5915b1f69b75SAndy Adamson { 5916b1f69b75SAndy Adamson __be32 *p; 5917b1f69b75SAndy Adamson int status; 5918b1f69b75SAndy Adamson u32 layout_count; 591964bd577eSTrond Myklebust u32 recvd; 5920b1f69b75SAndy Adamson 5921b1f69b75SAndy Adamson status = decode_op_hdr(xdr, OP_LAYOUTGET); 5922b1f69b75SAndy Adamson if (status) 5923808ba32aSFred Isaman goto out; 5924ea9d23f5STrond Myklebust p = xdr_inline_decode(xdr, 4); 5925b1f69b75SAndy Adamson if (unlikely(!p)) 5926b1f69b75SAndy Adamson goto out_overflow; 5927ea9d23f5STrond Myklebust res->return_on_close = be32_to_cpup(p); 592893b717fdSTrond Myklebust decode_layout_stateid(xdr, &res->stateid); 5929ea9d23f5STrond Myklebust p = xdr_inline_decode(xdr, 4); 5930ea9d23f5STrond Myklebust if (unlikely(!p)) 5931ea9d23f5STrond Myklebust goto out_overflow; 5932b1f69b75SAndy Adamson layout_count = be32_to_cpup(p); 5933b1f69b75SAndy Adamson if (!layout_count) { 5934b1f69b75SAndy Adamson dprintk("%s: server responded with empty layout array\n", 5935b1f69b75SAndy Adamson __func__); 5936808ba32aSFred Isaman status = -EINVAL; 5937808ba32aSFred Isaman goto out; 5938b1f69b75SAndy Adamson } 5939b1f69b75SAndy Adamson 594035124a09SWeston Andros Adamson p = xdr_inline_decode(xdr, 28); 5941b1f69b75SAndy Adamson if (unlikely(!p)) 5942b1f69b75SAndy Adamson goto out_overflow; 5943b1f69b75SAndy Adamson p = xdr_decode_hyper(p, &res->range.offset); 5944b1f69b75SAndy Adamson p = xdr_decode_hyper(p, &res->range.length); 5945b1f69b75SAndy Adamson res->range.iomode = be32_to_cpup(p++); 5946b1f69b75SAndy Adamson res->type = be32_to_cpup(p++); 594735124a09SWeston Andros Adamson res->layoutp->len = be32_to_cpup(p); 5948b1f69b75SAndy Adamson 5949b1f69b75SAndy Adamson dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", 5950b1f69b75SAndy Adamson __func__, 5951b1f69b75SAndy Adamson (unsigned long)res->range.offset, 5952b1f69b75SAndy Adamson (unsigned long)res->range.length, 5953b1f69b75SAndy Adamson res->range.iomode, 5954b1f69b75SAndy Adamson res->type, 595535124a09SWeston Andros Adamson res->layoutp->len); 5956b1f69b75SAndy Adamson 595764bd577eSTrond Myklebust recvd = xdr_read_pages(xdr, res->layoutp->len); 595835124a09SWeston Andros Adamson if (res->layoutp->len > recvd) { 595935124a09SWeston Andros Adamson dprintk("NFS: server cheating in layoutget reply: " 596035124a09SWeston Andros Adamson "layout len %u > recvd %u\n", 596135124a09SWeston Andros Adamson res->layoutp->len, recvd); 5962808ba32aSFred Isaman status = -EINVAL; 5963808ba32aSFred Isaman goto out; 596435124a09SWeston Andros Adamson } 596535124a09SWeston Andros Adamson 5966b1f69b75SAndy Adamson if (layout_count > 1) { 5967b1f69b75SAndy Adamson /* We only handle a length one array at the moment. Any 5968b1f69b75SAndy Adamson * further entries are just ignored. Note that this means 5969b1f69b75SAndy Adamson * the client may see a response that is less than the 5970b1f69b75SAndy Adamson * minimum it requested. 5971b1f69b75SAndy Adamson */ 5972b1f69b75SAndy Adamson dprintk("%s: server responded with %d layouts, dropping tail\n", 5973b1f69b75SAndy Adamson __func__, layout_count); 5974b1f69b75SAndy Adamson } 5975b1f69b75SAndy Adamson 5976808ba32aSFred Isaman out: 5977808ba32aSFred Isaman res->status = status; 5978808ba32aSFred Isaman return status; 5979b1f69b75SAndy Adamson out_overflow: 5980808ba32aSFred Isaman status = -EIO; 5981808ba32aSFred Isaman goto out; 5982b1f69b75SAndy Adamson } 5983863a3c6cSAndy Adamson 5984cbe82603SBenny Halevy static int decode_layoutreturn(struct xdr_stream *xdr, 5985cbe82603SBenny Halevy struct nfs4_layoutreturn_res *res) 5986cbe82603SBenny Halevy { 5987cbe82603SBenny Halevy __be32 *p; 5988cbe82603SBenny Halevy int status; 5989cbe82603SBenny Halevy 5990cbe82603SBenny Halevy status = decode_op_hdr(xdr, OP_LAYOUTRETURN); 5991cbe82603SBenny Halevy if (status) 5992cbe82603SBenny Halevy return status; 5993cbe82603SBenny Halevy p = xdr_inline_decode(xdr, 4); 5994cbe82603SBenny Halevy if (unlikely(!p)) 5995eb72f484SChuck Lever return -EIO; 5996cbe82603SBenny Halevy res->lrs_present = be32_to_cpup(p); 5997cbe82603SBenny Halevy if (res->lrs_present) 599893b717fdSTrond Myklebust status = decode_layout_stateid(xdr, &res->stateid); 5999fcd8843cSTrond Myklebust else 6000fcd8843cSTrond Myklebust nfs4_stateid_copy(&res->stateid, &invalid_stateid); 6001cbe82603SBenny Halevy return status; 6002cbe82603SBenny Halevy } 6003cbe82603SBenny Halevy 6004863a3c6cSAndy Adamson static int decode_layoutcommit(struct xdr_stream *xdr, 6005863a3c6cSAndy Adamson struct rpc_rqst *req, 6006863a3c6cSAndy Adamson struct nfs4_layoutcommit_res *res) 6007863a3c6cSAndy Adamson { 6008863a3c6cSAndy Adamson __be32 *p; 6009863a3c6cSAndy Adamson __u32 sizechanged; 6010863a3c6cSAndy Adamson int status; 6011863a3c6cSAndy Adamson 6012863a3c6cSAndy Adamson status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); 6013db29c089SAndy Adamson res->status = status; 6014863a3c6cSAndy Adamson if (status) 6015863a3c6cSAndy Adamson return status; 6016863a3c6cSAndy Adamson 6017863a3c6cSAndy Adamson p = xdr_inline_decode(xdr, 4); 6018863a3c6cSAndy Adamson if (unlikely(!p)) 6019eb72f484SChuck Lever return -EIO; 6020863a3c6cSAndy Adamson sizechanged = be32_to_cpup(p); 6021863a3c6cSAndy Adamson 6022863a3c6cSAndy Adamson if (sizechanged) { 6023863a3c6cSAndy Adamson /* throw away new size */ 6024863a3c6cSAndy Adamson p = xdr_inline_decode(xdr, 8); 6025863a3c6cSAndy Adamson if (unlikely(!p)) 6026eb72f484SChuck Lever return -EIO; 6027863a3c6cSAndy Adamson } 6028863a3c6cSAndy Adamson return 0; 6029863a3c6cSAndy Adamson } 60307d974794SBryan Schumaker 60317d974794SBryan Schumaker static int decode_test_stateid(struct xdr_stream *xdr, 60327d974794SBryan Schumaker struct nfs41_test_stateid_res *res) 60337d974794SBryan Schumaker { 60347d974794SBryan Schumaker __be32 *p; 60357d974794SBryan Schumaker int status; 60367d974794SBryan Schumaker int num_res; 60377d974794SBryan Schumaker 60387d974794SBryan Schumaker status = decode_op_hdr(xdr, OP_TEST_STATEID); 60397d974794SBryan Schumaker if (status) 60407d974794SBryan Schumaker return status; 60417d974794SBryan Schumaker 60427d974794SBryan Schumaker p = xdr_inline_decode(xdr, 4); 60437d974794SBryan Schumaker if (unlikely(!p)) 6044eb72f484SChuck Lever return -EIO; 60457d974794SBryan Schumaker num_res = be32_to_cpup(p++); 60467d974794SBryan Schumaker if (num_res != 1) 6047eb72f484SChuck Lever return -EIO; 60487d974794SBryan Schumaker 60497d974794SBryan Schumaker p = xdr_inline_decode(xdr, 4); 60507d974794SBryan Schumaker if (unlikely(!p)) 6051eb72f484SChuck Lever return -EIO; 60527d974794SBryan Schumaker res->status = be32_to_cpup(p++); 60531cab0652SBryan Schumaker 60541cab0652SBryan Schumaker return status; 60557d974794SBryan Schumaker } 60569aeda35fSBryan Schumaker 60579aeda35fSBryan Schumaker static int decode_free_stateid(struct xdr_stream *xdr, 60589aeda35fSBryan Schumaker struct nfs41_free_stateid_res *res) 60599aeda35fSBryan Schumaker { 60609f79fb48SAndy Adamson res->status = decode_op_hdr(xdr, OP_FREE_STATEID); 60619aeda35fSBryan Schumaker return res->status; 60629aeda35fSBryan Schumaker } 6063cf805165STrond Myklebust #else 6064cf805165STrond Myklebust static inline 6065cf805165STrond Myklebust int decode_layoutreturn(struct xdr_stream *xdr, 6066cf805165STrond Myklebust struct nfs4_layoutreturn_res *res) 6067cf805165STrond Myklebust { 6068cf805165STrond Myklebust return 0; 6069cf805165STrond Myklebust } 607056f487f8SFred Isaman 607156f487f8SFred Isaman static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, 607256f487f8SFred Isaman struct nfs4_layoutget_res *res) 607356f487f8SFred Isaman { 607456f487f8SFred Isaman return 0; 607556f487f8SFred Isaman } 607656f487f8SFred Isaman 6077b1f69b75SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 6078b1f69b75SAndy Adamson 60791da177e4SLinus Torvalds /* 608049c2559eSBenny Halevy * END OF "GENERIC" DECODE ROUTINES. 608149c2559eSBenny Halevy */ 608249c2559eSBenny Halevy 608349c2559eSBenny Halevy /* 60841da177e4SLinus Torvalds * Decode OPEN_DOWNGRADE response 60851da177e4SLinus Torvalds */ 6086bf269551SChuck Lever static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, 6087bf269551SChuck Lever struct xdr_stream *xdr, 6088fc016483SChristoph Hellwig void *data) 60891da177e4SLinus Torvalds { 6090fc016483SChristoph Hellwig struct nfs_closeres *res = data; 60911da177e4SLinus Torvalds struct compound_hdr hdr; 60921da177e4SLinus Torvalds int status; 60931da177e4SLinus Torvalds 6094bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 60951da177e4SLinus Torvalds if (status) 60961da177e4SLinus Torvalds goto out; 6097bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 60989b7b9fccSAndy Adamson if (status) 60999b7b9fccSAndy Adamson goto out; 6100bf269551SChuck Lever status = decode_putfh(xdr); 61011da177e4SLinus Torvalds if (status) 61021da177e4SLinus Torvalds goto out; 6103b6808145STrond Myklebust if (res->lr_res) { 6104b6808145STrond Myklebust status = decode_layoutreturn(xdr, res->lr_res); 6105b6808145STrond Myklebust res->lr_ret = status; 6106b6808145STrond Myklebust if (status) 6107b6808145STrond Myklebust goto out; 6108b6808145STrond Myklebust } 6109bf269551SChuck Lever status = decode_open_downgrade(xdr, res); 61101da177e4SLinus Torvalds out: 61111da177e4SLinus Torvalds return status; 61121da177e4SLinus Torvalds } 61131da177e4SLinus Torvalds 61141da177e4SLinus Torvalds /* 61151da177e4SLinus Torvalds * Decode ACCESS response 61161da177e4SLinus Torvalds */ 6117bf269551SChuck Lever static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6118fc016483SChristoph Hellwig void *data) 61191da177e4SLinus Torvalds { 6120fc016483SChristoph Hellwig struct nfs4_accessres *res = data; 61211da177e4SLinus Torvalds struct compound_hdr hdr; 61221da177e4SLinus Torvalds int status; 61231da177e4SLinus Torvalds 6124bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 61259b7b9fccSAndy Adamson if (status) 61269b7b9fccSAndy Adamson goto out; 6127bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 61289b7b9fccSAndy Adamson if (status) 61291da177e4SLinus Torvalds goto out; 6130bf269551SChuck Lever status = decode_putfh(xdr); 613176b32999STrond Myklebust if (status != 0) 613276b32999STrond Myklebust goto out; 61336168f62cSWeston Andros Adamson status = decode_access(xdr, &res->supported, &res->access); 613476b32999STrond Myklebust if (status != 0) 613576b32999STrond Myklebust goto out; 61368bcbe7d9STrond Myklebust if (res->fattr) 61376926afd1STrond Myklebust decode_getfattr(xdr, res->fattr, res->server); 61381da177e4SLinus Torvalds out: 61391da177e4SLinus Torvalds return status; 61401da177e4SLinus Torvalds } 61411da177e4SLinus Torvalds 61421da177e4SLinus Torvalds /* 61431da177e4SLinus Torvalds * Decode LOOKUP response 61441da177e4SLinus Torvalds */ 6145bf269551SChuck Lever static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6146fc016483SChristoph Hellwig void *data) 61471da177e4SLinus Torvalds { 6148fc016483SChristoph Hellwig struct nfs4_lookup_res *res = data; 61491da177e4SLinus Torvalds struct compound_hdr hdr; 61501da177e4SLinus Torvalds int status; 61511da177e4SLinus Torvalds 6152bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 61539b7b9fccSAndy Adamson if (status) 61549b7b9fccSAndy Adamson goto out; 6155bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 61569b7b9fccSAndy Adamson if (status) 61571da177e4SLinus Torvalds goto out; 6158bf269551SChuck Lever status = decode_putfh(xdr); 6159bf269551SChuck Lever if (status) 61601da177e4SLinus Torvalds goto out; 6161bf269551SChuck Lever status = decode_lookup(xdr); 6162bf269551SChuck Lever if (status) 61631da177e4SLinus Torvalds goto out; 6164bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 6165bf269551SChuck Lever if (status) 61661da177e4SLinus Torvalds goto out; 61671e2f67daSAnna Schumaker status = decode_getfattr(xdr, res->fattr, res->server); 61681da177e4SLinus Torvalds out: 61691da177e4SLinus Torvalds return status; 61701da177e4SLinus Torvalds } 61711da177e4SLinus Torvalds 61721da177e4SLinus Torvalds /* 61735b5faaf6SJeff Layton * Decode LOOKUPP response 61745b5faaf6SJeff Layton */ 61755b5faaf6SJeff Layton static int nfs4_xdr_dec_lookupp(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 61765b5faaf6SJeff Layton void *data) 61775b5faaf6SJeff Layton { 61785b5faaf6SJeff Layton struct nfs4_lookupp_res *res = data; 61795b5faaf6SJeff Layton struct compound_hdr hdr; 61805b5faaf6SJeff Layton int status; 61815b5faaf6SJeff Layton 61825b5faaf6SJeff Layton status = decode_compound_hdr(xdr, &hdr); 61835b5faaf6SJeff Layton if (status) 61845b5faaf6SJeff Layton goto out; 61855b5faaf6SJeff Layton status = decode_sequence(xdr, &res->seq_res, rqstp); 61865b5faaf6SJeff Layton if (status) 61875b5faaf6SJeff Layton goto out; 61885b5faaf6SJeff Layton status = decode_putfh(xdr); 61895b5faaf6SJeff Layton if (status) 61905b5faaf6SJeff Layton goto out; 61915b5faaf6SJeff Layton status = decode_lookupp(xdr); 61925b5faaf6SJeff Layton if (status) 61935b5faaf6SJeff Layton goto out; 61945b5faaf6SJeff Layton status = decode_getfh(xdr, res->fh); 61955b5faaf6SJeff Layton if (status) 61965b5faaf6SJeff Layton goto out; 61971e2f67daSAnna Schumaker status = decode_getfattr(xdr, res->fattr, res->server); 61985b5faaf6SJeff Layton out: 61995b5faaf6SJeff Layton return status; 62005b5faaf6SJeff Layton } 62015b5faaf6SJeff Layton 62025b5faaf6SJeff Layton /* 62031da177e4SLinus Torvalds * Decode LOOKUP_ROOT response 62041da177e4SLinus Torvalds */ 6205bf269551SChuck Lever static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, 6206bf269551SChuck Lever struct xdr_stream *xdr, 6207fc016483SChristoph Hellwig void *data) 62081da177e4SLinus Torvalds { 6209fc016483SChristoph Hellwig struct nfs4_lookup_res *res = data; 62101da177e4SLinus Torvalds struct compound_hdr hdr; 62111da177e4SLinus Torvalds int status; 62121da177e4SLinus Torvalds 6213bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 62149b7b9fccSAndy Adamson if (status) 62159b7b9fccSAndy Adamson goto out; 6216bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 62179b7b9fccSAndy Adamson if (status) 62181da177e4SLinus Torvalds goto out; 6219bf269551SChuck Lever status = decode_putrootfh(xdr); 6220bf269551SChuck Lever if (status) 62211da177e4SLinus Torvalds goto out; 6222bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 6223bf269551SChuck Lever if (status == 0) 62241e2f67daSAnna Schumaker status = decode_getfattr(xdr, res->fattr, res->server); 62251da177e4SLinus Torvalds out: 62261da177e4SLinus Torvalds return status; 62271da177e4SLinus Torvalds } 62281da177e4SLinus Torvalds 62291da177e4SLinus Torvalds /* 62301da177e4SLinus Torvalds * Decode REMOVE response 62311da177e4SLinus Torvalds */ 6232bf269551SChuck Lever static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6233fc016483SChristoph Hellwig void *data) 62341da177e4SLinus Torvalds { 6235fc016483SChristoph Hellwig struct nfs_removeres *res = data; 62361da177e4SLinus Torvalds struct compound_hdr hdr; 62371da177e4SLinus Torvalds int status; 62381da177e4SLinus Torvalds 6239bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 62409b7b9fccSAndy Adamson if (status) 62419b7b9fccSAndy Adamson goto out; 6242bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 62439b7b9fccSAndy Adamson if (status) 62441da177e4SLinus Torvalds goto out; 6245bf269551SChuck Lever status = decode_putfh(xdr); 6246bf269551SChuck Lever if (status) 624716e42959STrond Myklebust goto out; 6248bf269551SChuck Lever status = decode_remove(xdr, &res->cinfo); 62491da177e4SLinus Torvalds out: 62501da177e4SLinus Torvalds return status; 62511da177e4SLinus Torvalds } 62521da177e4SLinus Torvalds 62531da177e4SLinus Torvalds /* 62541da177e4SLinus Torvalds * Decode RENAME response 62551da177e4SLinus Torvalds */ 6256bf269551SChuck Lever static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6257fc016483SChristoph Hellwig void *data) 62581da177e4SLinus Torvalds { 6259fc016483SChristoph Hellwig struct nfs_renameres *res = data; 62601da177e4SLinus Torvalds struct compound_hdr hdr; 62611da177e4SLinus Torvalds int status; 62621da177e4SLinus Torvalds 6263bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 62649b7b9fccSAndy Adamson if (status) 62659b7b9fccSAndy Adamson goto out; 6266bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 62679b7b9fccSAndy Adamson if (status) 62681da177e4SLinus Torvalds goto out; 6269bf269551SChuck Lever status = decode_putfh(xdr); 6270bf269551SChuck Lever if (status) 62711da177e4SLinus Torvalds goto out; 6272bf269551SChuck Lever status = decode_savefh(xdr); 6273bf269551SChuck Lever if (status) 62741da177e4SLinus Torvalds goto out; 6275bf269551SChuck Lever status = decode_putfh(xdr); 6276bf269551SChuck Lever if (status) 62771da177e4SLinus Torvalds goto out; 6278bf269551SChuck Lever status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo); 62791da177e4SLinus Torvalds out: 62801da177e4SLinus Torvalds return status; 62811da177e4SLinus Torvalds } 62821da177e4SLinus Torvalds 62831da177e4SLinus Torvalds /* 62841da177e4SLinus Torvalds * Decode LINK response 62851da177e4SLinus Torvalds */ 6286bf269551SChuck Lever static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6287fc016483SChristoph Hellwig void *data) 62881da177e4SLinus Torvalds { 6289fc016483SChristoph Hellwig struct nfs4_link_res *res = data; 62901da177e4SLinus Torvalds struct compound_hdr hdr; 62911da177e4SLinus Torvalds int status; 62921da177e4SLinus Torvalds 6293bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 62949b7b9fccSAndy Adamson if (status) 62959b7b9fccSAndy Adamson goto out; 6296bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 62979b7b9fccSAndy Adamson if (status) 62981da177e4SLinus Torvalds goto out; 6299bf269551SChuck Lever status = decode_putfh(xdr); 6300bf269551SChuck Lever if (status) 63011da177e4SLinus Torvalds goto out; 6302bf269551SChuck Lever status = decode_savefh(xdr); 6303bf269551SChuck Lever if (status) 63041da177e4SLinus Torvalds goto out; 6305bf269551SChuck Lever status = decode_putfh(xdr); 6306bf269551SChuck Lever if (status) 63071da177e4SLinus Torvalds goto out; 6308bf269551SChuck Lever status = decode_link(xdr, &res->cinfo); 6309bf269551SChuck Lever if (status) 631091ba2eeeSTrond Myklebust goto out; 631191ba2eeeSTrond Myklebust /* 631291ba2eeeSTrond Myklebust * Note order: OP_LINK leaves the directory as the current 631391ba2eeeSTrond Myklebust * filehandle. 631491ba2eeeSTrond Myklebust */ 6315bf269551SChuck Lever status = decode_restorefh(xdr); 6316bf269551SChuck Lever if (status) 631791ba2eeeSTrond Myklebust goto out; 63181e2f67daSAnna Schumaker decode_getfattr(xdr, res->fattr, res->server); 63191da177e4SLinus Torvalds out: 63201da177e4SLinus Torvalds return status; 63211da177e4SLinus Torvalds } 63221da177e4SLinus Torvalds 63231da177e4SLinus Torvalds /* 63241da177e4SLinus Torvalds * Decode CREATE response 63251da177e4SLinus Torvalds */ 6326bf269551SChuck Lever static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6327fc016483SChristoph Hellwig void *data) 63281da177e4SLinus Torvalds { 6329fc016483SChristoph Hellwig struct nfs4_create_res *res = data; 63301da177e4SLinus Torvalds struct compound_hdr hdr; 63311da177e4SLinus Torvalds int status; 63321da177e4SLinus Torvalds 6333bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 63349b7b9fccSAndy Adamson if (status) 63359b7b9fccSAndy Adamson goto out; 6336bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 63379b7b9fccSAndy Adamson if (status) 63381da177e4SLinus Torvalds goto out; 6339bf269551SChuck Lever status = decode_putfh(xdr); 6340bf269551SChuck Lever if (status) 63411da177e4SLinus Torvalds goto out; 6342bf269551SChuck Lever status = decode_create(xdr, &res->dir_cinfo); 6343bf269551SChuck Lever if (status) 63441da177e4SLinus Torvalds goto out; 6345bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 6346bf269551SChuck Lever if (status) 63471da177e4SLinus Torvalds goto out; 63481e2f67daSAnna Schumaker decode_getfattr(xdr, res->fattr, res->server); 63491da177e4SLinus Torvalds out: 63501da177e4SLinus Torvalds return status; 63511da177e4SLinus Torvalds } 63521da177e4SLinus Torvalds 63531da177e4SLinus Torvalds /* 63541da177e4SLinus Torvalds * Decode SYMLINK response 63551da177e4SLinus Torvalds */ 6356bf269551SChuck Lever static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6357fc016483SChristoph Hellwig void *res) 63581da177e4SLinus Torvalds { 6359bf269551SChuck Lever return nfs4_xdr_dec_create(rqstp, xdr, res); 63601da177e4SLinus Torvalds } 63611da177e4SLinus Torvalds 63621da177e4SLinus Torvalds /* 63631da177e4SLinus Torvalds * Decode GETATTR response 63641da177e4SLinus Torvalds */ 6365bf269551SChuck Lever static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6366fc016483SChristoph Hellwig void *data) 63671da177e4SLinus Torvalds { 6368fc016483SChristoph Hellwig struct nfs4_getattr_res *res = data; 63691da177e4SLinus Torvalds struct compound_hdr hdr; 63701da177e4SLinus Torvalds int status; 63711da177e4SLinus Torvalds 6372bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 63731da177e4SLinus Torvalds if (status) 63741da177e4SLinus Torvalds goto out; 6375bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 63769b7b9fccSAndy Adamson if (status) 63779b7b9fccSAndy Adamson goto out; 6378bf269551SChuck Lever status = decode_putfh(xdr); 63791da177e4SLinus Torvalds if (status) 63801da177e4SLinus Torvalds goto out; 63811e2f67daSAnna Schumaker status = decode_getfattr(xdr, res->fattr, res->server); 63821da177e4SLinus Torvalds out: 63831da177e4SLinus Torvalds return status; 63841da177e4SLinus Torvalds } 63851da177e4SLinus Torvalds 638623ec6965SJ. Bruce Fields /* 638723ec6965SJ. Bruce Fields * Encode an SETACL request 638823ec6965SJ. Bruce Fields */ 63899f06c719SChuck Lever static void nfs4_xdr_enc_setacl(struct rpc_rqst *req, struct xdr_stream *xdr, 6390fcc85819SChristoph Hellwig const void *data) 639123ec6965SJ. Bruce Fields { 6392fcc85819SChristoph Hellwig const struct nfs_setaclargs *args = data; 639323ec6965SJ. Bruce Fields struct compound_hdr hdr = { 639466cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 639523ec6965SJ. Bruce Fields }; 639623ec6965SJ. Bruce Fields 63979f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 63989f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 63999f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 64009f06c719SChuck Lever encode_setacl(xdr, args, &hdr); 6401d017931cSAndy Adamson encode_nops(&hdr); 640223ec6965SJ. Bruce Fields } 640305d564feSAndy Adamson 640423ec6965SJ. Bruce Fields /* 640523ec6965SJ. Bruce Fields * Decode SETACL response 640623ec6965SJ. Bruce Fields */ 640723ec6965SJ. Bruce Fields static int 6408bf269551SChuck Lever nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6409fc016483SChristoph Hellwig void *data) 641023ec6965SJ. Bruce Fields { 6411fc016483SChristoph Hellwig struct nfs_setaclres *res = data; 641223ec6965SJ. Bruce Fields struct compound_hdr hdr; 641323ec6965SJ. Bruce Fields int status; 641423ec6965SJ. Bruce Fields 6415bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 641623ec6965SJ. Bruce Fields if (status) 641723ec6965SJ. Bruce Fields goto out; 6418bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 64199b7b9fccSAndy Adamson if (status) 64209b7b9fccSAndy Adamson goto out; 6421bf269551SChuck Lever status = decode_putfh(xdr); 642223ec6965SJ. Bruce Fields if (status) 642323ec6965SJ. Bruce Fields goto out; 6424bf269551SChuck Lever status = decode_setattr(xdr); 642523ec6965SJ. Bruce Fields out: 642623ec6965SJ. Bruce Fields return status; 642723ec6965SJ. Bruce Fields } 64281da177e4SLinus Torvalds 64291da177e4SLinus Torvalds /* 6430029d105eSJ. Bruce Fields * Decode GETACL response 6431029d105eSJ. Bruce Fields */ 6432029d105eSJ. Bruce Fields static int 6433bf269551SChuck Lever nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6434fc016483SChristoph Hellwig void *data) 6435029d105eSJ. Bruce Fields { 6436fc016483SChristoph Hellwig struct nfs_getaclres *res = data; 6437029d105eSJ. Bruce Fields struct compound_hdr hdr; 6438029d105eSJ. Bruce Fields int status; 6439029d105eSJ. Bruce Fields 64400ae4c3e8SChuck Lever if (res->acl_scratch != NULL) 64410ae4c3e8SChuck Lever xdr_set_scratch_page(xdr, res->acl_scratch); 6442bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6443029d105eSJ. Bruce Fields if (status) 6444029d105eSJ. Bruce Fields goto out; 6445bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 64469b7b9fccSAndy Adamson if (status) 64479b7b9fccSAndy Adamson goto out; 6448bf269551SChuck Lever status = decode_putfh(xdr); 6449029d105eSJ. Bruce Fields if (status) 6450029d105eSJ. Bruce Fields goto out; 6451bf118a34SAndy Adamson status = decode_getacl(xdr, rqstp, res); 6452029d105eSJ. Bruce Fields 6453029d105eSJ. Bruce Fields out: 6454029d105eSJ. Bruce Fields return status; 6455029d105eSJ. Bruce Fields } 6456029d105eSJ. Bruce Fields 6457029d105eSJ. Bruce Fields /* 64581da177e4SLinus Torvalds * Decode CLOSE response 64591da177e4SLinus Torvalds */ 6460bf269551SChuck Lever static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6461fc016483SChristoph Hellwig void *data) 64621da177e4SLinus Torvalds { 6463fc016483SChristoph Hellwig struct nfs_closeres *res = data; 64641da177e4SLinus Torvalds struct compound_hdr hdr; 64651da177e4SLinus Torvalds int status; 64661da177e4SLinus Torvalds 6467bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 64681da177e4SLinus Torvalds if (status) 64691da177e4SLinus Torvalds goto out; 6470bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 64719b7b9fccSAndy Adamson if (status) 64729b7b9fccSAndy Adamson goto out; 6473bf269551SChuck Lever status = decode_putfh(xdr); 64741da177e4SLinus Torvalds if (status) 64751da177e4SLinus Torvalds goto out; 6476cf805165STrond Myklebust if (res->lr_res) { 6477cf805165STrond Myklebust status = decode_layoutreturn(xdr, res->lr_res); 6478cf805165STrond Myklebust res->lr_ret = status; 6479cf805165STrond Myklebust if (status) 6480cf805165STrond Myklebust goto out; 6481cf805165STrond Myklebust } 6482d8d84983STrond Myklebust if (res->fattr != NULL) { 6483d8d84983STrond Myklebust status = decode_getfattr(xdr, res->fattr, res->server); 6484516a6af6STrond Myklebust if (status != 0) 6485516a6af6STrond Myklebust goto out; 6486d8d84983STrond Myklebust } 6487d8d84983STrond Myklebust status = decode_close(xdr, res); 64881da177e4SLinus Torvalds out: 64891da177e4SLinus Torvalds return status; 64901da177e4SLinus Torvalds } 64911da177e4SLinus Torvalds 64921da177e4SLinus Torvalds /* 64931da177e4SLinus Torvalds * Decode OPEN response 64941da177e4SLinus Torvalds */ 6495bf269551SChuck Lever static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6496fc016483SChristoph Hellwig void *data) 64971da177e4SLinus Torvalds { 6498fc016483SChristoph Hellwig struct nfs_openres *res = data; 64991da177e4SLinus Torvalds struct compound_hdr hdr; 65001da177e4SLinus Torvalds int status; 65011da177e4SLinus Torvalds 6502bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 65031da177e4SLinus Torvalds if (status) 65041da177e4SLinus Torvalds goto out; 6505bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 65069b7b9fccSAndy Adamson if (status) 65079b7b9fccSAndy Adamson goto out; 6508bf269551SChuck Lever status = decode_putfh(xdr); 65091da177e4SLinus Torvalds if (status) 65101da177e4SLinus Torvalds goto out; 6511bf269551SChuck Lever status = decode_open(xdr, res); 65121da177e4SLinus Torvalds if (status) 65131da177e4SLinus Torvalds goto out; 651401913b49SWeston Andros Adamson status = decode_getfh(xdr, &res->fh); 651501913b49SWeston Andros Adamson if (status) 65161da177e4SLinus Torvalds goto out; 6517ae2bb032SWeston Andros Adamson if (res->access_request) 65186168f62cSWeston Andros Adamson decode_access(xdr, &res->access_supported, &res->access_result); 65191e2f67daSAnna Schumaker decode_getfattr(xdr, res->f_attr, res->server); 652056f487f8SFred Isaman if (res->lg_res) 652156f487f8SFred Isaman decode_layoutget(xdr, rqstp, res->lg_res); 65221da177e4SLinus Torvalds out: 65231da177e4SLinus Torvalds return status; 65241da177e4SLinus Torvalds } 65251da177e4SLinus Torvalds 65261da177e4SLinus Torvalds /* 65271da177e4SLinus Torvalds * Decode OPEN_CONFIRM response 65281da177e4SLinus Torvalds */ 6529bf269551SChuck Lever static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, 6530bf269551SChuck Lever struct xdr_stream *xdr, 6531fc016483SChristoph Hellwig void *data) 65321da177e4SLinus Torvalds { 6533fc016483SChristoph Hellwig struct nfs_open_confirmres *res = data; 65341da177e4SLinus Torvalds struct compound_hdr hdr; 65351da177e4SLinus Torvalds int status; 65361da177e4SLinus Torvalds 6537bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 65381da177e4SLinus Torvalds if (status) 65391da177e4SLinus Torvalds goto out; 6540bf269551SChuck Lever status = decode_putfh(xdr); 65411da177e4SLinus Torvalds if (status) 65421da177e4SLinus Torvalds goto out; 6543bf269551SChuck Lever status = decode_open_confirm(xdr, res); 65441da177e4SLinus Torvalds out: 65451da177e4SLinus Torvalds return status; 65461da177e4SLinus Torvalds } 65471da177e4SLinus Torvalds 65481da177e4SLinus Torvalds /* 65491da177e4SLinus Torvalds * Decode OPEN response 65501da177e4SLinus Torvalds */ 6551bf269551SChuck Lever static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, 6552bf269551SChuck Lever struct xdr_stream *xdr, 6553fc016483SChristoph Hellwig void *data) 65541da177e4SLinus Torvalds { 6555fc016483SChristoph Hellwig struct nfs_openres *res = data; 65561da177e4SLinus Torvalds struct compound_hdr hdr; 65571da177e4SLinus Torvalds int status; 65581da177e4SLinus Torvalds 6559bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 65601da177e4SLinus Torvalds if (status) 65611da177e4SLinus Torvalds goto out; 6562bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 65639b7b9fccSAndy Adamson if (status) 65649b7b9fccSAndy Adamson goto out; 6565bf269551SChuck Lever status = decode_putfh(xdr); 65661da177e4SLinus Torvalds if (status) 65671da177e4SLinus Torvalds goto out; 6568bf269551SChuck Lever status = decode_open(xdr, res); 6569864472e9STrond Myklebust if (status) 6570864472e9STrond Myklebust goto out; 6571ae2bb032SWeston Andros Adamson if (res->access_request) 65726168f62cSWeston Andros Adamson decode_access(xdr, &res->access_supported, &res->access_result); 65736926afd1STrond Myklebust decode_getfattr(xdr, res->f_attr, res->server); 657456f487f8SFred Isaman if (res->lg_res) 657556f487f8SFred Isaman decode_layoutget(xdr, rqstp, res->lg_res); 65761da177e4SLinus Torvalds out: 65771da177e4SLinus Torvalds return status; 65781da177e4SLinus Torvalds } 65791da177e4SLinus Torvalds 65801da177e4SLinus Torvalds /* 65811da177e4SLinus Torvalds * Decode SETATTR response 65821da177e4SLinus Torvalds */ 6583bf269551SChuck Lever static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, 6584bf269551SChuck Lever struct xdr_stream *xdr, 6585fc016483SChristoph Hellwig void *data) 65861da177e4SLinus Torvalds { 6587fc016483SChristoph Hellwig struct nfs_setattrres *res = data; 65881da177e4SLinus Torvalds struct compound_hdr hdr; 65891da177e4SLinus Torvalds int status; 65901da177e4SLinus Torvalds 6591bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 65921da177e4SLinus Torvalds if (status) 65931da177e4SLinus Torvalds goto out; 6594bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 65959b7b9fccSAndy Adamson if (status) 65969b7b9fccSAndy Adamson goto out; 6597bf269551SChuck Lever status = decode_putfh(xdr); 65981da177e4SLinus Torvalds if (status) 65991da177e4SLinus Torvalds goto out; 6600bf269551SChuck Lever status = decode_setattr(xdr); 66011da177e4SLinus Torvalds if (status) 66021da177e4SLinus Torvalds goto out; 66031e2f67daSAnna Schumaker decode_getfattr(xdr, res->fattr, res->server); 66041da177e4SLinus Torvalds out: 66051da177e4SLinus Torvalds return status; 66061da177e4SLinus Torvalds } 66071da177e4SLinus Torvalds 66081da177e4SLinus Torvalds /* 66091da177e4SLinus Torvalds * Decode LOCK response 66101da177e4SLinus Torvalds */ 6611bf269551SChuck Lever static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6612fc016483SChristoph Hellwig void *data) 66131da177e4SLinus Torvalds { 6614fc016483SChristoph Hellwig struct nfs_lock_res *res = data; 66151da177e4SLinus Torvalds struct compound_hdr hdr; 66161da177e4SLinus Torvalds int status; 66171da177e4SLinus Torvalds 6618bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 66191da177e4SLinus Torvalds if (status) 66201da177e4SLinus Torvalds goto out; 6621bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 66229b7b9fccSAndy Adamson if (status) 66239b7b9fccSAndy Adamson goto out; 6624bf269551SChuck Lever status = decode_putfh(xdr); 66251da177e4SLinus Torvalds if (status) 66261da177e4SLinus Torvalds goto out; 6627bf269551SChuck Lever status = decode_lock(xdr, res); 66281da177e4SLinus Torvalds out: 66291da177e4SLinus Torvalds return status; 66301da177e4SLinus Torvalds } 66311da177e4SLinus Torvalds 66321da177e4SLinus Torvalds /* 66331da177e4SLinus Torvalds * Decode LOCKT response 66341da177e4SLinus Torvalds */ 6635bf269551SChuck Lever static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6636fc016483SChristoph Hellwig void *data) 66371da177e4SLinus Torvalds { 6638fc016483SChristoph Hellwig struct nfs_lockt_res *res = data; 66391da177e4SLinus Torvalds struct compound_hdr hdr; 66401da177e4SLinus Torvalds int status; 66411da177e4SLinus Torvalds 6642bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 66431da177e4SLinus Torvalds if (status) 66441da177e4SLinus Torvalds goto out; 6645bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 66469b7b9fccSAndy Adamson if (status) 66479b7b9fccSAndy Adamson goto out; 6648bf269551SChuck Lever status = decode_putfh(xdr); 66491da177e4SLinus Torvalds if (status) 66501da177e4SLinus Torvalds goto out; 6651bf269551SChuck Lever status = decode_lockt(xdr, res); 66521da177e4SLinus Torvalds out: 66531da177e4SLinus Torvalds return status; 66541da177e4SLinus Torvalds } 66551da177e4SLinus Torvalds 66561da177e4SLinus Torvalds /* 66571da177e4SLinus Torvalds * Decode LOCKU response 66581da177e4SLinus Torvalds */ 6659bf269551SChuck Lever static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6660fc016483SChristoph Hellwig void *data) 66611da177e4SLinus Torvalds { 6662fc016483SChristoph Hellwig struct nfs_locku_res *res = data; 66631da177e4SLinus Torvalds struct compound_hdr hdr; 66641da177e4SLinus Torvalds int status; 66651da177e4SLinus Torvalds 6666bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 66671da177e4SLinus Torvalds if (status) 66681da177e4SLinus Torvalds goto out; 6669bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 66709b7b9fccSAndy Adamson if (status) 66719b7b9fccSAndy Adamson goto out; 6672bf269551SChuck Lever status = decode_putfh(xdr); 66731da177e4SLinus Torvalds if (status) 66741da177e4SLinus Torvalds goto out; 6675bf269551SChuck Lever status = decode_locku(xdr, res); 66761da177e4SLinus Torvalds out: 66771da177e4SLinus Torvalds return status; 66781da177e4SLinus Torvalds } 66791da177e4SLinus Torvalds 6680bf269551SChuck Lever static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, 6681bf269551SChuck Lever struct xdr_stream *xdr, void *dummy) 6682d3c7b7ccSTrond Myklebust { 6683d3c7b7ccSTrond Myklebust struct compound_hdr hdr; 6684d3c7b7ccSTrond Myklebust int status; 6685d3c7b7ccSTrond Myklebust 6686bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6687d3c7b7ccSTrond Myklebust if (!status) 6688bf269551SChuck Lever status = decode_release_lockowner(xdr); 6689d3c7b7ccSTrond Myklebust return status; 6690d3c7b7ccSTrond Myklebust } 6691d3c7b7ccSTrond Myklebust 66921da177e4SLinus Torvalds /* 66931da177e4SLinus Torvalds * Decode READLINK response 66941da177e4SLinus Torvalds */ 6695bf269551SChuck Lever static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, 6696bf269551SChuck Lever struct xdr_stream *xdr, 6697fc016483SChristoph Hellwig void *data) 66981da177e4SLinus Torvalds { 6699fc016483SChristoph Hellwig struct nfs4_readlink_res *res = data; 67001da177e4SLinus Torvalds struct compound_hdr hdr; 67011da177e4SLinus Torvalds int status; 67021da177e4SLinus Torvalds 6703bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 67041da177e4SLinus Torvalds if (status) 67051da177e4SLinus Torvalds goto out; 6706bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 67079b7b9fccSAndy Adamson if (status) 67089b7b9fccSAndy Adamson goto out; 6709bf269551SChuck Lever status = decode_putfh(xdr); 67101da177e4SLinus Torvalds if (status) 67111da177e4SLinus Torvalds goto out; 6712bf269551SChuck Lever status = decode_readlink(xdr, rqstp); 67131da177e4SLinus Torvalds out: 67141da177e4SLinus Torvalds return status; 67151da177e4SLinus Torvalds } 67161da177e4SLinus Torvalds 67171da177e4SLinus Torvalds /* 67181da177e4SLinus Torvalds * Decode READDIR response 67191da177e4SLinus Torvalds */ 6720bf269551SChuck Lever static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6721fc016483SChristoph Hellwig void *data) 67221da177e4SLinus Torvalds { 6723fc016483SChristoph Hellwig struct nfs4_readdir_res *res = data; 67241da177e4SLinus Torvalds struct compound_hdr hdr; 67251da177e4SLinus Torvalds int status; 67261da177e4SLinus Torvalds 6727bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 67281da177e4SLinus Torvalds if (status) 67291da177e4SLinus Torvalds goto out; 6730bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 67319b7b9fccSAndy Adamson if (status) 67329b7b9fccSAndy Adamson goto out; 6733bf269551SChuck Lever status = decode_putfh(xdr); 67341da177e4SLinus Torvalds if (status) 67351da177e4SLinus Torvalds goto out; 6736bf269551SChuck Lever status = decode_readdir(xdr, rqstp, res); 67371da177e4SLinus Torvalds out: 67381da177e4SLinus Torvalds return status; 67391da177e4SLinus Torvalds } 67401da177e4SLinus Torvalds 67411da177e4SLinus Torvalds /* 67421da177e4SLinus Torvalds * Decode Read response 67431da177e4SLinus Torvalds */ 6744bf269551SChuck Lever static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6745fc016483SChristoph Hellwig void *data) 67461da177e4SLinus Torvalds { 6747fc016483SChristoph Hellwig struct nfs_pgio_res *res = data; 67481da177e4SLinus Torvalds struct compound_hdr hdr; 67491da177e4SLinus Torvalds int status; 67501da177e4SLinus Torvalds 6751bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6752aabff4ddSPeng Tao res->op_status = hdr.status; 67531da177e4SLinus Torvalds if (status) 67541da177e4SLinus Torvalds goto out; 6755bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 67569b7b9fccSAndy Adamson if (status) 67579b7b9fccSAndy Adamson goto out; 6758bf269551SChuck Lever status = decode_putfh(xdr); 67591da177e4SLinus Torvalds if (status) 67601da177e4SLinus Torvalds goto out; 6761bf269551SChuck Lever status = decode_read(xdr, rqstp, res); 67621da177e4SLinus Torvalds if (!status) 67631da177e4SLinus Torvalds status = res->count; 67641da177e4SLinus Torvalds out: 67651da177e4SLinus Torvalds return status; 67661da177e4SLinus Torvalds } 67671da177e4SLinus Torvalds 67681da177e4SLinus Torvalds /* 67691da177e4SLinus Torvalds * Decode WRITE response 67701da177e4SLinus Torvalds */ 6771bf269551SChuck Lever static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6772fc016483SChristoph Hellwig void *data) 67731da177e4SLinus Torvalds { 6774fc016483SChristoph Hellwig struct nfs_pgio_res *res = data; 67751da177e4SLinus Torvalds struct compound_hdr hdr; 67761da177e4SLinus Torvalds int status; 67771da177e4SLinus Torvalds 6778bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6779aabff4ddSPeng Tao res->op_status = hdr.status; 67801da177e4SLinus Torvalds if (status) 67811da177e4SLinus Torvalds goto out; 6782bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 67839b7b9fccSAndy Adamson if (status) 67849b7b9fccSAndy Adamson goto out; 6785bf269551SChuck Lever status = decode_putfh(xdr); 67861da177e4SLinus Torvalds if (status) 67871da177e4SLinus Torvalds goto out; 6788bf269551SChuck Lever status = decode_write(xdr, res); 67894f9838c7STrond Myklebust if (status) 67904f9838c7STrond Myklebust goto out; 67917ffd1064SFred Isaman if (res->fattr) 67926926afd1STrond Myklebust decode_getfattr(xdr, res->fattr, res->server); 67931da177e4SLinus Torvalds if (!status) 67941da177e4SLinus Torvalds status = res->count; 67951da177e4SLinus Torvalds out: 67961da177e4SLinus Torvalds return status; 67971da177e4SLinus Torvalds } 67981da177e4SLinus Torvalds 67991da177e4SLinus Torvalds /* 68001da177e4SLinus Torvalds * Decode COMMIT response 68011da177e4SLinus Torvalds */ 6802bf269551SChuck Lever static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6803fc016483SChristoph Hellwig void *data) 68041da177e4SLinus Torvalds { 6805fc016483SChristoph Hellwig struct nfs_commitres *res = data; 68061da177e4SLinus Torvalds struct compound_hdr hdr; 68071da177e4SLinus Torvalds int status; 68081da177e4SLinus Torvalds 6809bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6810aabff4ddSPeng Tao res->op_status = hdr.status; 68111da177e4SLinus Torvalds if (status) 68121da177e4SLinus Torvalds goto out; 6813bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 68149b7b9fccSAndy Adamson if (status) 68159b7b9fccSAndy Adamson goto out; 6816bf269551SChuck Lever status = decode_putfh(xdr); 68171da177e4SLinus Torvalds if (status) 68181da177e4SLinus Torvalds goto out; 6819bf269551SChuck Lever status = decode_commit(xdr, res); 68201da177e4SLinus Torvalds out: 68211da177e4SLinus Torvalds return status; 68221da177e4SLinus Torvalds } 68231da177e4SLinus Torvalds 68241da177e4SLinus Torvalds /* 68258b173218SRicardo Labiaga * Decode FSINFO response 68261da177e4SLinus Torvalds */ 6827bf269551SChuck Lever static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, 6828fc016483SChristoph Hellwig void *data) 68291da177e4SLinus Torvalds { 6830fc016483SChristoph Hellwig struct nfs4_fsinfo_res *res = data; 68311da177e4SLinus Torvalds struct compound_hdr hdr; 68321da177e4SLinus Torvalds int status; 68331da177e4SLinus Torvalds 6834bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 68351da177e4SLinus Torvalds if (!status) 6836bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 68379b7b9fccSAndy Adamson if (!status) 6838bf269551SChuck Lever status = decode_putfh(xdr); 68391da177e4SLinus Torvalds if (!status) 6840bf269551SChuck Lever status = decode_fsinfo(xdr, res->fsinfo); 68411da177e4SLinus Torvalds return status; 68421da177e4SLinus Torvalds } 68431da177e4SLinus Torvalds 68441da177e4SLinus Torvalds /* 68458b173218SRicardo Labiaga * Decode PATHCONF response 68461da177e4SLinus Torvalds */ 6847bf269551SChuck Lever static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, 6848fc016483SChristoph Hellwig void *data) 68491da177e4SLinus Torvalds { 6850fc016483SChristoph Hellwig struct nfs4_pathconf_res *res = data; 68511da177e4SLinus Torvalds struct compound_hdr hdr; 68521da177e4SLinus Torvalds int status; 68531da177e4SLinus Torvalds 6854bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 68551da177e4SLinus Torvalds if (!status) 6856bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 68579b7b9fccSAndy Adamson if (!status) 6858bf269551SChuck Lever status = decode_putfh(xdr); 68591da177e4SLinus Torvalds if (!status) 6860bf269551SChuck Lever status = decode_pathconf(xdr, res->pathconf); 68611da177e4SLinus Torvalds return status; 68621da177e4SLinus Torvalds } 68631da177e4SLinus Torvalds 68641da177e4SLinus Torvalds /* 68658b173218SRicardo Labiaga * Decode STATFS response 68661da177e4SLinus Torvalds */ 6867bf269551SChuck Lever static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, 6868fc016483SChristoph Hellwig void *data) 68691da177e4SLinus Torvalds { 6870fc016483SChristoph Hellwig struct nfs4_statfs_res *res = data; 68711da177e4SLinus Torvalds struct compound_hdr hdr; 68721da177e4SLinus Torvalds int status; 68731da177e4SLinus Torvalds 6874bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 68751da177e4SLinus Torvalds if (!status) 6876bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 68779b7b9fccSAndy Adamson if (!status) 6878bf269551SChuck Lever status = decode_putfh(xdr); 68791da177e4SLinus Torvalds if (!status) 6880bf269551SChuck Lever status = decode_statfs(xdr, res->fsstat); 68811da177e4SLinus Torvalds return status; 68821da177e4SLinus Torvalds } 68831da177e4SLinus Torvalds 68841da177e4SLinus Torvalds /* 68858b173218SRicardo Labiaga * Decode GETATTR_BITMAP response 68861da177e4SLinus Torvalds */ 6887bf269551SChuck Lever static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, 6888bf269551SChuck Lever struct xdr_stream *xdr, 6889fc016483SChristoph Hellwig void *data) 68901da177e4SLinus Torvalds { 6891fc016483SChristoph Hellwig struct nfs4_server_caps_res *res = data; 68921da177e4SLinus Torvalds struct compound_hdr hdr; 68931da177e4SLinus Torvalds int status; 68941da177e4SLinus Torvalds 6895bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 68969b7b9fccSAndy Adamson if (status) 68979b7b9fccSAndy Adamson goto out; 6898bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 68999b7b9fccSAndy Adamson if (status) 69001da177e4SLinus Torvalds goto out; 6901bf269551SChuck Lever status = decode_putfh(xdr); 6902bf269551SChuck Lever if (status) 69031da177e4SLinus Torvalds goto out; 6904bf269551SChuck Lever status = decode_server_caps(xdr, res); 69051da177e4SLinus Torvalds out: 69061da177e4SLinus Torvalds return status; 69071da177e4SLinus Torvalds } 69081da177e4SLinus Torvalds 69091da177e4SLinus Torvalds /* 69101da177e4SLinus Torvalds * Decode RENEW response 69111da177e4SLinus Torvalds */ 6912bf269551SChuck Lever static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6913bf269551SChuck Lever void *__unused) 69141da177e4SLinus Torvalds { 69151da177e4SLinus Torvalds struct compound_hdr hdr; 69161da177e4SLinus Torvalds int status; 69171da177e4SLinus Torvalds 6918bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 69191da177e4SLinus Torvalds if (!status) 6920bf269551SChuck Lever status = decode_renew(xdr); 69211da177e4SLinus Torvalds return status; 69221da177e4SLinus Torvalds } 69231da177e4SLinus Torvalds 69241da177e4SLinus Torvalds /* 69258b173218SRicardo Labiaga * Decode SETCLIENTID response 69261da177e4SLinus Torvalds */ 6927bf269551SChuck Lever static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, 6928bf269551SChuck Lever struct xdr_stream *xdr, 6929fc016483SChristoph Hellwig void *data) 69301da177e4SLinus Torvalds { 6931fc016483SChristoph Hellwig struct nfs4_setclientid_res *res = data; 69321da177e4SLinus Torvalds struct compound_hdr hdr; 69331da177e4SLinus Torvalds int status; 69341da177e4SLinus Torvalds 6935bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 69361da177e4SLinus Torvalds if (!status) 6937bf269551SChuck Lever status = decode_setclientid(xdr, res); 69381da177e4SLinus Torvalds return status; 69391da177e4SLinus Torvalds } 69401da177e4SLinus Torvalds 69411da177e4SLinus Torvalds /* 69428b173218SRicardo Labiaga * Decode SETCLIENTID_CONFIRM response 69431da177e4SLinus Torvalds */ 6944bf269551SChuck Lever static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, 6945fc016483SChristoph Hellwig struct xdr_stream *xdr, 6946fc016483SChristoph Hellwig void *data) 69471da177e4SLinus Torvalds { 69481da177e4SLinus Torvalds struct compound_hdr hdr; 69491da177e4SLinus Torvalds int status; 69501da177e4SLinus Torvalds 6951bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 69521da177e4SLinus Torvalds if (!status) 6953bf269551SChuck Lever status = decode_setclientid_confirm(xdr); 69541da177e4SLinus Torvalds return status; 69551da177e4SLinus Torvalds } 69561da177e4SLinus Torvalds 69571da177e4SLinus Torvalds /* 69588b173218SRicardo Labiaga * Decode DELEGRETURN response 69591da177e4SLinus Torvalds */ 6960bf269551SChuck Lever static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, 6961bf269551SChuck Lever struct xdr_stream *xdr, 6962fc016483SChristoph Hellwig void *data) 69631da177e4SLinus Torvalds { 6964fc016483SChristoph Hellwig struct nfs4_delegreturnres *res = data; 69651da177e4SLinus Torvalds struct compound_hdr hdr; 69661da177e4SLinus Torvalds int status; 69671da177e4SLinus Torvalds 6968bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 69699b7b9fccSAndy Adamson if (status) 69709b7b9fccSAndy Adamson goto out; 6971bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 69729b7b9fccSAndy Adamson if (status) 6973fa178f29STrond Myklebust goto out; 6974bf269551SChuck Lever status = decode_putfh(xdr); 6975fa178f29STrond Myklebust if (status != 0) 6976fa178f29STrond Myklebust goto out; 6977586f1c39STrond Myklebust if (res->lr_res) { 6978586f1c39STrond Myklebust status = decode_layoutreturn(xdr, res->lr_res); 6979586f1c39STrond Myklebust res->lr_ret = status; 6980586f1c39STrond Myklebust if (status) 6981586f1c39STrond Myklebust goto out; 6982586f1c39STrond Myklebust } 69838ac2b422STrond Myklebust if (res->fattr) { 6984e144cbccSTrond Myklebust status = decode_getfattr(xdr, res->fattr, res->server); 6985556ae3bbSJeff Layton if (status != 0) 6986556ae3bbSJeff Layton goto out; 69878ac2b422STrond Myklebust } 6988e144cbccSTrond Myklebust status = decode_delegreturn(xdr); 6989fa178f29STrond Myklebust out: 69901da177e4SLinus Torvalds return status; 69911da177e4SLinus Torvalds } 69921da177e4SLinus Torvalds 6993683b57b4STrond Myklebust /* 69948b173218SRicardo Labiaga * Decode FS_LOCATIONS response 6995683b57b4STrond Myklebust */ 6996bf269551SChuck Lever static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, 6997bf269551SChuck Lever struct xdr_stream *xdr, 6998fc016483SChristoph Hellwig void *data) 6999683b57b4STrond Myklebust { 7000fc016483SChristoph Hellwig struct nfs4_fs_locations_res *res = data; 7001683b57b4STrond Myklebust struct compound_hdr hdr; 7002683b57b4STrond Myklebust int status; 7003683b57b4STrond Myklebust 7004bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 70059b7b9fccSAndy Adamson if (status) 70069b7b9fccSAndy Adamson goto out; 7007bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 70089b7b9fccSAndy Adamson if (status) 7009683b57b4STrond Myklebust goto out; 7010bf269551SChuck Lever status = decode_putfh(xdr); 7011bf269551SChuck Lever if (status) 7012683b57b4STrond Myklebust goto out; 7013b03d735bSChuck Lever if (res->migration) { 7014b03d735bSChuck Lever xdr_enter_page(xdr, PAGE_SIZE); 7015b03d735bSChuck Lever status = decode_getfattr_generic(xdr, 7016b03d735bSChuck Lever &res->fs_locations->fattr, 7017b03d735bSChuck Lever NULL, res->fs_locations, 70181e2f67daSAnna Schumaker res->fs_locations->server); 7019b03d735bSChuck Lever if (status) 7020b03d735bSChuck Lever goto out; 7021b03d735bSChuck Lever if (res->renew) 7022b03d735bSChuck Lever status = decode_renew(xdr); 7023b03d735bSChuck Lever } else { 7024bf269551SChuck Lever status = decode_lookup(xdr); 7025bf269551SChuck Lever if (status) 7026683b57b4STrond Myklebust goto out; 7027bf269551SChuck Lever xdr_enter_page(xdr, PAGE_SIZE); 7028b03d735bSChuck Lever status = decode_getfattr_generic(xdr, 7029b03d735bSChuck Lever &res->fs_locations->fattr, 70308b7e3f49STrond Myklebust NULL, res->fs_locations, 70311e2f67daSAnna Schumaker res->fs_locations->server); 7032b03d735bSChuck Lever } 7033683b57b4STrond Myklebust out: 7034683b57b4STrond Myklebust return status; 7035683b57b4STrond Myklebust } 7036683b57b4STrond Myklebust 70375a5ea0d4SBryan Schumaker /* 70385a5ea0d4SBryan Schumaker * Decode SECINFO response 70395a5ea0d4SBryan Schumaker */ 70405a5ea0d4SBryan Schumaker static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp, 70415a5ea0d4SBryan Schumaker struct xdr_stream *xdr, 7042fc016483SChristoph Hellwig void *data) 70435a5ea0d4SBryan Schumaker { 7044fc016483SChristoph Hellwig struct nfs4_secinfo_res *res = data; 70455a5ea0d4SBryan Schumaker struct compound_hdr hdr; 70465a5ea0d4SBryan Schumaker int status; 70475a5ea0d4SBryan Schumaker 70485a5ea0d4SBryan Schumaker status = decode_compound_hdr(xdr, &hdr); 70495a5ea0d4SBryan Schumaker if (status) 70505a5ea0d4SBryan Schumaker goto out; 70515a5ea0d4SBryan Schumaker status = decode_sequence(xdr, &res->seq_res, rqstp); 70525a5ea0d4SBryan Schumaker if (status) 70535a5ea0d4SBryan Schumaker goto out; 70545a5ea0d4SBryan Schumaker status = decode_putfh(xdr); 70555a5ea0d4SBryan Schumaker if (status) 70565a5ea0d4SBryan Schumaker goto out; 70575a5ea0d4SBryan Schumaker status = decode_secinfo(xdr, res); 70585a5ea0d4SBryan Schumaker out: 70595a5ea0d4SBryan Schumaker return status; 70605a5ea0d4SBryan Schumaker } 70615a5ea0d4SBryan Schumaker 706244c99933SChuck Lever /* 706344c99933SChuck Lever * Decode FSID_PRESENT response 706444c99933SChuck Lever */ 706544c99933SChuck Lever static int nfs4_xdr_dec_fsid_present(struct rpc_rqst *rqstp, 706644c99933SChuck Lever struct xdr_stream *xdr, 7067fc016483SChristoph Hellwig void *data) 706844c99933SChuck Lever { 7069fc016483SChristoph Hellwig struct nfs4_fsid_present_res *res = data; 707044c99933SChuck Lever struct compound_hdr hdr; 707144c99933SChuck Lever int status; 707244c99933SChuck Lever 707344c99933SChuck Lever status = decode_compound_hdr(xdr, &hdr); 707444c99933SChuck Lever if (status) 707544c99933SChuck Lever goto out; 707644c99933SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 707744c99933SChuck Lever if (status) 707844c99933SChuck Lever goto out; 707944c99933SChuck Lever status = decode_putfh(xdr); 708044c99933SChuck Lever if (status) 708144c99933SChuck Lever goto out; 708244c99933SChuck Lever status = decode_getfh(xdr, res->fh); 708344c99933SChuck Lever if (status) 708444c99933SChuck Lever goto out; 708544c99933SChuck Lever if (res->renew) 708644c99933SChuck Lever status = decode_renew(xdr); 708744c99933SChuck Lever out: 708844c99933SChuck Lever return status; 708944c99933SChuck Lever } 709044c99933SChuck Lever 709199fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 709299fe60d0SBenny Halevy /* 70937c44f1aeSWeston Andros Adamson * Decode BIND_CONN_TO_SESSION response 70947c44f1aeSWeston Andros Adamson */ 70957c44f1aeSWeston Andros Adamson static int nfs4_xdr_dec_bind_conn_to_session(struct rpc_rqst *rqstp, 70967c44f1aeSWeston Andros Adamson struct xdr_stream *xdr, 70977c44f1aeSWeston Andros Adamson void *res) 70987c44f1aeSWeston Andros Adamson { 70997c44f1aeSWeston Andros Adamson struct compound_hdr hdr; 71007c44f1aeSWeston Andros Adamson int status; 71017c44f1aeSWeston Andros Adamson 71027c44f1aeSWeston Andros Adamson status = decode_compound_hdr(xdr, &hdr); 71037c44f1aeSWeston Andros Adamson if (!status) 71047c44f1aeSWeston Andros Adamson status = decode_bind_conn_to_session(xdr, res); 71057c44f1aeSWeston Andros Adamson return status; 71067c44f1aeSWeston Andros Adamson } 71077c44f1aeSWeston Andros Adamson 71087c44f1aeSWeston Andros Adamson /* 71098b173218SRicardo Labiaga * Decode EXCHANGE_ID response 711099fe60d0SBenny Halevy */ 7111bf269551SChuck Lever static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, 7112bf269551SChuck Lever struct xdr_stream *xdr, 711399fe60d0SBenny Halevy void *res) 711499fe60d0SBenny Halevy { 711599fe60d0SBenny Halevy struct compound_hdr hdr; 711699fe60d0SBenny Halevy int status; 711799fe60d0SBenny Halevy 7118bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 711999fe60d0SBenny Halevy if (!status) 7120bf269551SChuck Lever status = decode_exchange_id(xdr, res); 712199fe60d0SBenny Halevy return status; 712299fe60d0SBenny Halevy } 71232050f0ccSAndy Adamson 71242050f0ccSAndy Adamson /* 71258b173218SRicardo Labiaga * Decode CREATE_SESSION response 7126fc931582SAndy Adamson */ 7127bf269551SChuck Lever static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, 7128bf269551SChuck Lever struct xdr_stream *xdr, 7129fc016483SChristoph Hellwig void *res) 7130fc931582SAndy Adamson { 7131fc931582SAndy Adamson struct compound_hdr hdr; 7132fc931582SAndy Adamson int status; 7133fc931582SAndy Adamson 7134bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 7135fc931582SAndy Adamson if (!status) 7136bf269551SChuck Lever status = decode_create_session(xdr, res); 7137fc931582SAndy Adamson return status; 7138fc931582SAndy Adamson } 7139fc931582SAndy Adamson 7140fc931582SAndy Adamson /* 71418b173218SRicardo Labiaga * Decode DESTROY_SESSION response 71420f3e66c6SAndy Adamson */ 7143bf269551SChuck Lever static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, 7144bf269551SChuck Lever struct xdr_stream *xdr, 7145bf269551SChuck Lever void *res) 71460f3e66c6SAndy Adamson { 71470f3e66c6SAndy Adamson struct compound_hdr hdr; 71480f3e66c6SAndy Adamson int status; 71490f3e66c6SAndy Adamson 7150bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 71510f3e66c6SAndy Adamson if (!status) 7152bf269551SChuck Lever status = decode_destroy_session(xdr, res); 71530f3e66c6SAndy Adamson return status; 71540f3e66c6SAndy Adamson } 71550f3e66c6SAndy Adamson 71560f3e66c6SAndy Adamson /* 715766245539STrond Myklebust * Decode DESTROY_CLIENTID response 715866245539STrond Myklebust */ 715966245539STrond Myklebust static int nfs4_xdr_dec_destroy_clientid(struct rpc_rqst *rqstp, 716066245539STrond Myklebust struct xdr_stream *xdr, 716166245539STrond Myklebust void *res) 716266245539STrond Myklebust { 716366245539STrond Myklebust struct compound_hdr hdr; 716466245539STrond Myklebust int status; 716566245539STrond Myklebust 716666245539STrond Myklebust status = decode_compound_hdr(xdr, &hdr); 716766245539STrond Myklebust if (!status) 716866245539STrond Myklebust status = decode_destroy_clientid(xdr, res); 716966245539STrond Myklebust return status; 717066245539STrond Myklebust } 717166245539STrond Myklebust 717266245539STrond Myklebust /* 71738b173218SRicardo Labiaga * Decode SEQUENCE response 7174fc01cea9SAndy Adamson */ 7175bf269551SChuck Lever static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, 7176bf269551SChuck Lever struct xdr_stream *xdr, 7177fc016483SChristoph Hellwig void *res) 7178fc01cea9SAndy Adamson { 7179fc01cea9SAndy Adamson struct compound_hdr hdr; 7180fc01cea9SAndy Adamson int status; 7181fc01cea9SAndy Adamson 7182bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 7183fc01cea9SAndy Adamson if (!status) 7184bf269551SChuck Lever status = decode_sequence(xdr, res, rqstp); 7185fc01cea9SAndy Adamson return status; 7186fc01cea9SAndy Adamson } 7187fc01cea9SAndy Adamson 71880efb01b2SDonald Buczek #endif 71890efb01b2SDonald Buczek 7190fc01cea9SAndy Adamson /* 71918b173218SRicardo Labiaga * Decode GET_LEASE_TIME response 71922050f0ccSAndy Adamson */ 7193bf269551SChuck Lever static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, 7194bf269551SChuck Lever struct xdr_stream *xdr, 7195fc016483SChristoph Hellwig void *data) 71962050f0ccSAndy Adamson { 7197fc016483SChristoph Hellwig struct nfs4_get_lease_time_res *res = data; 71982050f0ccSAndy Adamson struct compound_hdr hdr; 71992050f0ccSAndy Adamson int status; 72002050f0ccSAndy Adamson 7201bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 72022050f0ccSAndy Adamson if (!status) 7203bf269551SChuck Lever status = decode_sequence(xdr, &res->lr_seq_res, rqstp); 72042050f0ccSAndy Adamson if (!status) 7205bf269551SChuck Lever status = decode_putrootfh(xdr); 72062050f0ccSAndy Adamson if (!status) 7207bf269551SChuck Lever status = decode_fsinfo(xdr, res->lr_fsinfo); 72082050f0ccSAndy Adamson return status; 72092050f0ccSAndy Adamson } 721018019753SRicardo Labiaga 72110efb01b2SDonald Buczek #ifdef CONFIG_NFS_V4_1 72120efb01b2SDonald Buczek 721318019753SRicardo Labiaga /* 721418019753SRicardo Labiaga * Decode RECLAIM_COMPLETE response 721518019753SRicardo Labiaga */ 7216bf269551SChuck Lever static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, 7217bf269551SChuck Lever struct xdr_stream *xdr, 7218fc016483SChristoph Hellwig void *data) 721918019753SRicardo Labiaga { 7220fc016483SChristoph Hellwig struct nfs41_reclaim_complete_res *res = data; 722118019753SRicardo Labiaga struct compound_hdr hdr; 722218019753SRicardo Labiaga int status; 722318019753SRicardo Labiaga 7224bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 722518019753SRicardo Labiaga if (!status) 7226bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 722718019753SRicardo Labiaga if (!status) 72288ee2b78aSHimangi Saraogi status = decode_reclaim_complete(xdr, NULL); 722918019753SRicardo Labiaga return status; 723018019753SRicardo Labiaga } 7231b1f69b75SAndy Adamson 7232b1f69b75SAndy Adamson /* 7233b1f69b75SAndy Adamson * Decode GETDEVINFO response 7234b1f69b75SAndy Adamson */ 7235bf269551SChuck Lever static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, 7236bf269551SChuck Lever struct xdr_stream *xdr, 7237fc016483SChristoph Hellwig void *data) 7238b1f69b75SAndy Adamson { 7239fc016483SChristoph Hellwig struct nfs4_getdeviceinfo_res *res = data; 7240b1f69b75SAndy Adamson struct compound_hdr hdr; 7241b1f69b75SAndy Adamson int status; 7242b1f69b75SAndy Adamson 7243bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 7244b1f69b75SAndy Adamson if (status != 0) 7245b1f69b75SAndy Adamson goto out; 7246bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 7247b1f69b75SAndy Adamson if (status != 0) 7248b1f69b75SAndy Adamson goto out; 72494e590803STrond Myklebust status = decode_getdeviceinfo(xdr, res); 7250b1f69b75SAndy Adamson out: 7251b1f69b75SAndy Adamson return status; 7252b1f69b75SAndy Adamson } 7253b1f69b75SAndy Adamson 7254b1f69b75SAndy Adamson /* 7255b1f69b75SAndy Adamson * Decode LAYOUTGET response 7256b1f69b75SAndy Adamson */ 7257bf269551SChuck Lever static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, 7258bf269551SChuck Lever struct xdr_stream *xdr, 7259fc016483SChristoph Hellwig void *data) 7260b1f69b75SAndy Adamson { 7261fc016483SChristoph Hellwig struct nfs4_layoutget_res *res = data; 7262b1f69b75SAndy Adamson struct compound_hdr hdr; 7263b1f69b75SAndy Adamson int status; 7264b1f69b75SAndy Adamson 7265bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 7266b1f69b75SAndy Adamson if (status) 7267b1f69b75SAndy Adamson goto out; 7268bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 7269b1f69b75SAndy Adamson if (status) 7270b1f69b75SAndy Adamson goto out; 7271bf269551SChuck Lever status = decode_putfh(xdr); 7272b1f69b75SAndy Adamson if (status) 7273b1f69b75SAndy Adamson goto out; 7274bf269551SChuck Lever status = decode_layoutget(xdr, rqstp, res); 7275b1f69b75SAndy Adamson out: 7276b1f69b75SAndy Adamson return status; 7277b1f69b75SAndy Adamson } 7278863a3c6cSAndy Adamson 7279863a3c6cSAndy Adamson /* 7280cbe82603SBenny Halevy * Decode LAYOUTRETURN response 7281cbe82603SBenny Halevy */ 7282cbe82603SBenny Halevy static int nfs4_xdr_dec_layoutreturn(struct rpc_rqst *rqstp, 7283cbe82603SBenny Halevy struct xdr_stream *xdr, 7284fc016483SChristoph Hellwig void *data) 7285cbe82603SBenny Halevy { 7286fc016483SChristoph Hellwig struct nfs4_layoutreturn_res *res = data; 7287cbe82603SBenny Halevy struct compound_hdr hdr; 7288cbe82603SBenny Halevy int status; 7289cbe82603SBenny Halevy 7290cbe82603SBenny Halevy status = decode_compound_hdr(xdr, &hdr); 7291cbe82603SBenny Halevy if (status) 7292cbe82603SBenny Halevy goto out; 7293cbe82603SBenny Halevy status = decode_sequence(xdr, &res->seq_res, rqstp); 7294cbe82603SBenny Halevy if (status) 7295cbe82603SBenny Halevy goto out; 7296cbe82603SBenny Halevy status = decode_putfh(xdr); 7297cbe82603SBenny Halevy if (status) 7298cbe82603SBenny Halevy goto out; 7299cbe82603SBenny Halevy status = decode_layoutreturn(xdr, res); 7300cbe82603SBenny Halevy out: 7301cbe82603SBenny Halevy return status; 7302cbe82603SBenny Halevy } 7303cbe82603SBenny Halevy 7304cbe82603SBenny Halevy /* 7305863a3c6cSAndy Adamson * Decode LAYOUTCOMMIT response 7306863a3c6cSAndy Adamson */ 7307863a3c6cSAndy Adamson static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, 7308863a3c6cSAndy Adamson struct xdr_stream *xdr, 7309fc016483SChristoph Hellwig void *data) 7310863a3c6cSAndy Adamson { 7311fc016483SChristoph Hellwig struct nfs4_layoutcommit_res *res = data; 7312863a3c6cSAndy Adamson struct compound_hdr hdr; 7313863a3c6cSAndy Adamson int status; 7314863a3c6cSAndy Adamson 7315863a3c6cSAndy Adamson status = decode_compound_hdr(xdr, &hdr); 7316863a3c6cSAndy Adamson if (status) 7317863a3c6cSAndy Adamson goto out; 7318863a3c6cSAndy Adamson status = decode_sequence(xdr, &res->seq_res, rqstp); 7319863a3c6cSAndy Adamson if (status) 7320863a3c6cSAndy Adamson goto out; 7321863a3c6cSAndy Adamson status = decode_putfh(xdr); 7322863a3c6cSAndy Adamson if (status) 7323863a3c6cSAndy Adamson goto out; 7324863a3c6cSAndy Adamson status = decode_layoutcommit(xdr, rqstp, res); 7325863a3c6cSAndy Adamson if (status) 7326863a3c6cSAndy Adamson goto out; 73276926afd1STrond Myklebust decode_getfattr(xdr, res->fattr, res->server); 7328863a3c6cSAndy Adamson out: 7329863a3c6cSAndy Adamson return status; 7330863a3c6cSAndy Adamson } 7331fca78d6dSBryan Schumaker 7332fca78d6dSBryan Schumaker /* 7333fca78d6dSBryan Schumaker * Decode SECINFO_NO_NAME response 7334fca78d6dSBryan Schumaker */ 7335fca78d6dSBryan Schumaker static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp, 7336fca78d6dSBryan Schumaker struct xdr_stream *xdr, 7337fc016483SChristoph Hellwig void *data) 7338fca78d6dSBryan Schumaker { 7339fc016483SChristoph Hellwig struct nfs4_secinfo_res *res = data; 7340fca78d6dSBryan Schumaker struct compound_hdr hdr; 7341fca78d6dSBryan Schumaker int status; 7342fca78d6dSBryan Schumaker 7343fca78d6dSBryan Schumaker status = decode_compound_hdr(xdr, &hdr); 7344fca78d6dSBryan Schumaker if (status) 7345fca78d6dSBryan Schumaker goto out; 7346fca78d6dSBryan Schumaker status = decode_sequence(xdr, &res->seq_res, rqstp); 7347fca78d6dSBryan Schumaker if (status) 7348fca78d6dSBryan Schumaker goto out; 7349fca78d6dSBryan Schumaker status = decode_putrootfh(xdr); 7350fca78d6dSBryan Schumaker if (status) 7351fca78d6dSBryan Schumaker goto out; 735231e4dda4SBryan Schumaker status = decode_secinfo_no_name(xdr, res); 7353fca78d6dSBryan Schumaker out: 7354fca78d6dSBryan Schumaker return status; 7355fca78d6dSBryan Schumaker } 73567d974794SBryan Schumaker 73577d974794SBryan Schumaker /* 73587d974794SBryan Schumaker * Decode TEST_STATEID response 73597d974794SBryan Schumaker */ 73607d974794SBryan Schumaker static int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp, 73617d974794SBryan Schumaker struct xdr_stream *xdr, 7362fc016483SChristoph Hellwig void *data) 73637d974794SBryan Schumaker { 7364fc016483SChristoph Hellwig struct nfs41_test_stateid_res *res = data; 73657d974794SBryan Schumaker struct compound_hdr hdr; 73667d974794SBryan Schumaker int status; 73677d974794SBryan Schumaker 73687d974794SBryan Schumaker status = decode_compound_hdr(xdr, &hdr); 73697d974794SBryan Schumaker if (status) 73707d974794SBryan Schumaker goto out; 73717d974794SBryan Schumaker status = decode_sequence(xdr, &res->seq_res, rqstp); 73727d974794SBryan Schumaker if (status) 73737d974794SBryan Schumaker goto out; 73747d974794SBryan Schumaker status = decode_test_stateid(xdr, res); 73757d974794SBryan Schumaker out: 73767d974794SBryan Schumaker return status; 73777d974794SBryan Schumaker } 73789aeda35fSBryan Schumaker 73799aeda35fSBryan Schumaker /* 73809aeda35fSBryan Schumaker * Decode FREE_STATEID response 73819aeda35fSBryan Schumaker */ 73829aeda35fSBryan Schumaker static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp, 73839aeda35fSBryan Schumaker struct xdr_stream *xdr, 7384fc016483SChristoph Hellwig void *data) 73859aeda35fSBryan Schumaker { 7386fc016483SChristoph Hellwig struct nfs41_free_stateid_res *res = data; 73879aeda35fSBryan Schumaker struct compound_hdr hdr; 73889aeda35fSBryan Schumaker int status; 73899aeda35fSBryan Schumaker 73909aeda35fSBryan Schumaker status = decode_compound_hdr(xdr, &hdr); 73919aeda35fSBryan Schumaker if (status) 73929aeda35fSBryan Schumaker goto out; 73939aeda35fSBryan Schumaker status = decode_sequence(xdr, &res->seq_res, rqstp); 73949aeda35fSBryan Schumaker if (status) 73959aeda35fSBryan Schumaker goto out; 73969aeda35fSBryan Schumaker status = decode_free_stateid(xdr, res); 73979aeda35fSBryan Schumaker out: 73989aeda35fSBryan Schumaker return status; 73999aeda35fSBryan Schumaker } 740099fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 740199fe60d0SBenny Halevy 7402573c4e1eSChuck Lever /** 7403573c4e1eSChuck Lever * nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in 7404573c4e1eSChuck Lever * the local page cache. 7405573c4e1eSChuck Lever * @xdr: XDR stream where entry resides 7406573c4e1eSChuck Lever * @entry: buffer to fill in with entry data 7407573c4e1eSChuck Lever * @plus: boolean indicating whether this should be a readdirplus entry 7408573c4e1eSChuck Lever * 7409573c4e1eSChuck Lever * Returns zero if successful, otherwise a negative errno value is 7410573c4e1eSChuck Lever * returned. 7411573c4e1eSChuck Lever * 7412573c4e1eSChuck Lever * This function is not invoked during READDIR reply decoding, but 7413573c4e1eSChuck Lever * rather whenever an application invokes the getdents(2) system call 7414573c4e1eSChuck Lever * on a directory already in our cache. 7415573c4e1eSChuck Lever */ 7416573c4e1eSChuck Lever int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, 7417a7a3b1e9SBenjamin Coddington bool plus) 74181da177e4SLinus Torvalds { 7419256e48bbSTrond Myklebust unsigned int savep; 7420dae100c2SFred Isaman uint32_t bitmap[3] = {0}; 74211da177e4SLinus Torvalds uint32_t len; 742298de9ce6SFrank Sorenson uint64_t new_cookie; 7423babddc72SBryan Schumaker __be32 *p = xdr_inline_decode(xdr, 4); 7424babddc72SBryan Schumaker if (unlikely(!p)) 7425eb72f484SChuck Lever return -EAGAIN; 7426c08e76d0SChuck Lever if (*p == xdr_zero) { 7427babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 4); 7428babddc72SBryan Schumaker if (unlikely(!p)) 7429eb72f484SChuck Lever return -EAGAIN; 7430c08e76d0SChuck Lever if (*p == xdr_zero) 7431573c4e1eSChuck Lever return -EAGAIN; 74321da177e4SLinus Torvalds entry->eof = 1; 7433573c4e1eSChuck Lever return -EBADCOOKIE; 74341da177e4SLinus Torvalds } 74351da177e4SLinus Torvalds 7436babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 12); 7437babddc72SBryan Schumaker if (unlikely(!p)) 7438eb72f484SChuck Lever return -EAGAIN; 743998de9ce6SFrank Sorenson p = xdr_decode_hyper(p, &new_cookie); 7440c08e76d0SChuck Lever entry->len = be32_to_cpup(p); 7441babddc72SBryan Schumaker 74429af8c222STrond Myklebust p = xdr_inline_decode(xdr, entry->len); 7443babddc72SBryan Schumaker if (unlikely(!p)) 7444eb72f484SChuck Lever return -EAGAIN; 74451da177e4SLinus Torvalds entry->name = (const char *) p; 74461da177e4SLinus Torvalds 74471da177e4SLinus Torvalds /* 74481da177e4SLinus Torvalds * In case the server doesn't return an inode number, 74491da177e4SLinus Torvalds * we fake one here. (We don't use inode number 0, 74501da177e4SLinus Torvalds * since glibc seems to choke on it...) 74511da177e4SLinus Torvalds */ 74521da177e4SLinus Torvalds entry->ino = 1; 74534f082222STrond Myklebust entry->fattr->valid = 0; 74541da177e4SLinus Torvalds 74559af8c222STrond Myklebust if (decode_attr_bitmap(xdr, bitmap) < 0) 7456eb72f484SChuck Lever return -EAGAIN; 74579af8c222STrond Myklebust 7458256e48bbSTrond Myklebust if (decode_attr_length(xdr, &len, &savep) < 0) 7459eb72f484SChuck Lever return -EAGAIN; 74609af8c222STrond Myklebust 7461573c4e1eSChuck Lever if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, 74621e2f67daSAnna Schumaker NULL, entry->server) < 0) 7463eb72f484SChuck Lever return -EAGAIN; 746428331a46STrond Myklebust if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) 746528331a46STrond Myklebust entry->ino = entry->fattr->mounted_on_fileid; 746628331a46STrond Myklebust else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) 746782f2e547SBryan Schumaker entry->ino = entry->fattr->fileid; 74689af8c222STrond Myklebust 74690b26a0bfSTrond Myklebust entry->d_type = DT_UNKNOWN; 74700b26a0bfSTrond Myklebust if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE) 74710b26a0bfSTrond Myklebust entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); 74720b26a0bfSTrond Myklebust 747398de9ce6SFrank Sorenson entry->prev_cookie = entry->cookie; 747498de9ce6SFrank Sorenson entry->cookie = new_cookie; 747598de9ce6SFrank Sorenson 7476573c4e1eSChuck Lever return 0; 74771da177e4SLinus Torvalds } 74781da177e4SLinus Torvalds 74791da177e4SLinus Torvalds /* 74801da177e4SLinus Torvalds * We need to translate between nfs status return values and 74811da177e4SLinus Torvalds * the local errno values which may not be the same. 74821da177e4SLinus Torvalds */ 74831da177e4SLinus Torvalds static struct { 74841da177e4SLinus Torvalds int stat; 74851da177e4SLinus Torvalds int errno; 74861da177e4SLinus Torvalds } nfs_errtbl[] = { 74871da177e4SLinus Torvalds { NFS4_OK, 0 }, 7488856dff3dSBenny Halevy { NFS4ERR_PERM, -EPERM }, 7489856dff3dSBenny Halevy { NFS4ERR_NOENT, -ENOENT }, 7490856dff3dSBenny Halevy { NFS4ERR_IO, -errno_NFSERR_IO}, 7491856dff3dSBenny Halevy { NFS4ERR_NXIO, -ENXIO }, 7492856dff3dSBenny Halevy { NFS4ERR_ACCESS, -EACCES }, 7493856dff3dSBenny Halevy { NFS4ERR_EXIST, -EEXIST }, 7494856dff3dSBenny Halevy { NFS4ERR_XDEV, -EXDEV }, 7495856dff3dSBenny Halevy { NFS4ERR_NOTDIR, -ENOTDIR }, 7496856dff3dSBenny Halevy { NFS4ERR_ISDIR, -EISDIR }, 7497856dff3dSBenny Halevy { NFS4ERR_INVAL, -EINVAL }, 7498856dff3dSBenny Halevy { NFS4ERR_FBIG, -EFBIG }, 7499856dff3dSBenny Halevy { NFS4ERR_NOSPC, -ENOSPC }, 7500856dff3dSBenny Halevy { NFS4ERR_ROFS, -EROFS }, 7501856dff3dSBenny Halevy { NFS4ERR_MLINK, -EMLINK }, 7502856dff3dSBenny Halevy { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG }, 7503856dff3dSBenny Halevy { NFS4ERR_NOTEMPTY, -ENOTEMPTY }, 7504856dff3dSBenny Halevy { NFS4ERR_DQUOT, -EDQUOT }, 7505856dff3dSBenny Halevy { NFS4ERR_STALE, -ESTALE }, 7506856dff3dSBenny Halevy { NFS4ERR_BADHANDLE, -EBADHANDLE }, 7507856dff3dSBenny Halevy { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, 7508856dff3dSBenny Halevy { NFS4ERR_NOTSUPP, -ENOTSUPP }, 7509856dff3dSBenny Halevy { NFS4ERR_TOOSMALL, -ETOOSMALL }, 7510fdcb4577STrond Myklebust { NFS4ERR_SERVERFAULT, -EREMOTEIO }, 7511856dff3dSBenny Halevy { NFS4ERR_BADTYPE, -EBADTYPE }, 7512856dff3dSBenny Halevy { NFS4ERR_LOCKED, -EAGAIN }, 7513856dff3dSBenny Halevy { NFS4ERR_SYMLINK, -ELOOP }, 7514856dff3dSBenny Halevy { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, 7515856dff3dSBenny Halevy { NFS4ERR_DEADLOCK, -EDEADLK }, 75163e1f0212SFrank van der Linden { NFS4ERR_NOXATTR, -ENODATA }, 75173e1f0212SFrank van der Linden { NFS4ERR_XATTR2BIG, -E2BIG }, 7518856dff3dSBenny Halevy { -1, -EIO } 75191da177e4SLinus Torvalds }; 75201da177e4SLinus Torvalds 75211da177e4SLinus Torvalds /* 75221da177e4SLinus Torvalds * Convert an NFS error code to a local one. 75231da177e4SLinus Torvalds * This one is used jointly by NFSv2 and NFSv3. 75241da177e4SLinus Torvalds */ 75251da177e4SLinus Torvalds static int 75260a8ea437SDavid Howells nfs4_stat_to_errno(int stat) 75271da177e4SLinus Torvalds { 75281da177e4SLinus Torvalds int i; 75291da177e4SLinus Torvalds for (i = 0; nfs_errtbl[i].stat != -1; i++) { 75301da177e4SLinus Torvalds if (nfs_errtbl[i].stat == stat) 75311da177e4SLinus Torvalds return nfs_errtbl[i].errno; 75321da177e4SLinus Torvalds } 75331da177e4SLinus Torvalds if (stat <= 10000 || stat > 10100) { 75341da177e4SLinus Torvalds /* The server is looney tunes. */ 7535fdcb4577STrond Myklebust return -EREMOTEIO; 75361da177e4SLinus Torvalds } 75371da177e4SLinus Torvalds /* If we cannot translate the error, the recovery routines should 75381da177e4SLinus Torvalds * handle it. 75391da177e4SLinus Torvalds * Note: remaining NFSv4 error codes have values > 10000, so should 75401da177e4SLinus Torvalds * not conflict with native Linux error codes. 75411da177e4SLinus Torvalds */ 7542856dff3dSBenny Halevy return -stat; 75431da177e4SLinus Torvalds } 75441da177e4SLinus Torvalds 75451c6dcbe5SAnna Schumaker #ifdef CONFIG_NFS_V4_2 75461c6dcbe5SAnna Schumaker #include "nfs42xdr.c" 75471c6dcbe5SAnna Schumaker #endif /* CONFIG_NFS_V4_2 */ 75481c6dcbe5SAnna Schumaker 75491da177e4SLinus Torvalds #define PROC(proc, argtype, restype) \ 75501da177e4SLinus Torvalds [NFSPROC4_CLNT_##proc] = { \ 75511da177e4SLinus Torvalds .p_proc = NFSPROC4_COMPOUND, \ 7552fcc85819SChristoph Hellwig .p_encode = nfs4_xdr_##argtype, \ 7553fc016483SChristoph Hellwig .p_decode = nfs4_xdr_##restype, \ 75542bea90d4SChuck Lever .p_arglen = NFS4_##argtype##_sz, \ 75552bea90d4SChuck Lever .p_replen = NFS4_##restype##_sz, \ 7556cc0175c1SChuck Lever .p_statidx = NFSPROC4_CLNT_##proc, \ 7557cc0175c1SChuck Lever .p_name = #proc, \ 75581da177e4SLinus Torvalds } 75591da177e4SLinus Torvalds 75607c61f0d3SAnna Schumaker #define STUB(proc) \ 75617c61f0d3SAnna Schumaker [NFSPROC4_CLNT_##proc] = { \ 75627c61f0d3SAnna Schumaker .p_name = #proc, \ 75637c61f0d3SAnna Schumaker } 75647c61f0d3SAnna Schumaker 75658634ef5eSTrond Myklebust #if defined(CONFIG_NFS_V4_1) 75668634ef5eSTrond Myklebust #define PROC41(proc, argtype, restype) \ 75678634ef5eSTrond Myklebust PROC(proc, argtype, restype) 75688634ef5eSTrond Myklebust #else 75698634ef5eSTrond Myklebust #define PROC41(proc, argtype, restype) \ 75708634ef5eSTrond Myklebust STUB(proc) 75718634ef5eSTrond Myklebust #endif 75728634ef5eSTrond Myklebust 75738634ef5eSTrond Myklebust #if defined(CONFIG_NFS_V4_2) 75748634ef5eSTrond Myklebust #define PROC42(proc, argtype, restype) \ 75758634ef5eSTrond Myklebust PROC(proc, argtype, restype) 75768634ef5eSTrond Myklebust #else 75778634ef5eSTrond Myklebust #define PROC42(proc, argtype, restype) \ 75788634ef5eSTrond Myklebust STUB(proc) 75798634ef5eSTrond Myklebust #endif 75808634ef5eSTrond Myklebust 7581511e936bSChristoph Hellwig const struct rpc_procinfo nfs4_procedures[] = { 75821da177e4SLinus Torvalds PROC(READ, enc_read, dec_read), 75831da177e4SLinus Torvalds PROC(WRITE, enc_write, dec_write), 75841da177e4SLinus Torvalds PROC(COMMIT, enc_commit, dec_commit), 75851da177e4SLinus Torvalds PROC(OPEN, enc_open, dec_open), 75861da177e4SLinus Torvalds PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm), 75871da177e4SLinus Torvalds PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr), 75881da177e4SLinus Torvalds PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade), 75891da177e4SLinus Torvalds PROC(CLOSE, enc_close, dec_close), 75901da177e4SLinus Torvalds PROC(SETATTR, enc_setattr, dec_setattr), 75911da177e4SLinus Torvalds PROC(FSINFO, enc_fsinfo, dec_fsinfo), 75921da177e4SLinus Torvalds PROC(RENEW, enc_renew, dec_renew), 75931da177e4SLinus Torvalds PROC(SETCLIENTID, enc_setclientid, dec_setclientid), 75941da177e4SLinus Torvalds PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm), 75951da177e4SLinus Torvalds PROC(LOCK, enc_lock, dec_lock), 75961da177e4SLinus Torvalds PROC(LOCKT, enc_lockt, dec_lockt), 75971da177e4SLinus Torvalds PROC(LOCKU, enc_locku, dec_locku), 75981da177e4SLinus Torvalds PROC(ACCESS, enc_access, dec_access), 75991da177e4SLinus Torvalds PROC(GETATTR, enc_getattr, dec_getattr), 76001da177e4SLinus Torvalds PROC(LOOKUP, enc_lookup, dec_lookup), 76011da177e4SLinus Torvalds PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), 76021da177e4SLinus Torvalds PROC(REMOVE, enc_remove, dec_remove), 76031da177e4SLinus Torvalds PROC(RENAME, enc_rename, dec_rename), 76041da177e4SLinus Torvalds PROC(LINK, enc_link, dec_link), 76051da177e4SLinus Torvalds PROC(SYMLINK, enc_symlink, dec_symlink), 76061da177e4SLinus Torvalds PROC(CREATE, enc_create, dec_create), 76071da177e4SLinus Torvalds PROC(PATHCONF, enc_pathconf, dec_pathconf), 76081da177e4SLinus Torvalds PROC(STATFS, enc_statfs, dec_statfs), 76091da177e4SLinus Torvalds PROC(READLINK, enc_readlink, dec_readlink), 76101da177e4SLinus Torvalds PROC(READDIR, enc_readdir, dec_readdir), 76111da177e4SLinus Torvalds PROC(SERVER_CAPS, enc_server_caps, dec_server_caps), 76121da177e4SLinus Torvalds PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), 7613029d105eSJ. Bruce Fields PROC(GETACL, enc_getacl, dec_getacl), 761423ec6965SJ. Bruce Fields PROC(SETACL, enc_setacl, dec_setacl), 7615683b57b4STrond Myklebust PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), 7616d3c7b7ccSTrond Myklebust PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), 76175a5ea0d4SBryan Schumaker PROC(SECINFO, enc_secinfo, dec_secinfo), 761844c99933SChuck Lever PROC(FSID_PRESENT, enc_fsid_present, dec_fsid_present), 76198634ef5eSTrond Myklebust PROC41(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), 76208634ef5eSTrond Myklebust PROC41(CREATE_SESSION, enc_create_session, dec_create_session), 76218634ef5eSTrond Myklebust PROC41(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), 76228634ef5eSTrond Myklebust PROC41(SEQUENCE, enc_sequence, dec_sequence), 76230efb01b2SDonald Buczek PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), 76248634ef5eSTrond Myklebust PROC41(RECLAIM_COMPLETE,enc_reclaim_complete, dec_reclaim_complete), 76258634ef5eSTrond Myklebust PROC41(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), 76268634ef5eSTrond Myklebust PROC41(LAYOUTGET, enc_layoutget, dec_layoutget), 76278634ef5eSTrond Myklebust PROC41(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), 76288634ef5eSTrond Myklebust PROC41(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), 76298634ef5eSTrond Myklebust PROC41(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), 76308634ef5eSTrond Myklebust PROC41(TEST_STATEID, enc_test_stateid, dec_test_stateid), 76318634ef5eSTrond Myklebust PROC41(FREE_STATEID, enc_free_stateid, dec_free_stateid), 76327c61f0d3SAnna Schumaker STUB(GETDEVICELIST), 76338634ef5eSTrond Myklebust PROC41(BIND_CONN_TO_SESSION, 7634ad24ecfbSTrond Myklebust enc_bind_conn_to_session, dec_bind_conn_to_session), 76358634ef5eSTrond Myklebust PROC41(DESTROY_CLIENTID,enc_destroy_clientid, dec_destroy_clientid), 76368634ef5eSTrond Myklebust PROC42(SEEK, enc_seek, dec_seek), 76378634ef5eSTrond Myklebust PROC42(ALLOCATE, enc_allocate, dec_allocate), 76388634ef5eSTrond Myklebust PROC42(DEALLOCATE, enc_deallocate, dec_deallocate), 76398634ef5eSTrond Myklebust PROC42(LAYOUTSTATS, enc_layoutstats, dec_layoutstats), 76408634ef5eSTrond Myklebust PROC42(CLONE, enc_clone, dec_clone), 76418634ef5eSTrond Myklebust PROC42(COPY, enc_copy, dec_copy), 7642cb95deeaSOlga Kornievskaia PROC42(OFFLOAD_CANCEL, enc_offload_cancel, dec_offload_cancel), 76430491567bSOlga Kornievskaia PROC42(COPY_NOTIFY, enc_copy_notify, dec_copy_notify), 76448634ef5eSTrond Myklebust PROC(LOOKUPP, enc_lookupp, dec_lookupp), 76453eb86093STrond Myklebust PROC42(LAYOUTERROR, enc_layouterror, dec_layouterror), 76463e1f0212SFrank van der Linden PROC42(GETXATTR, enc_getxattr, dec_getxattr), 76473e1f0212SFrank van der Linden PROC42(SETXATTR, enc_setxattr, dec_setxattr), 76483e1f0212SFrank van der Linden PROC42(LISTXATTRS, enc_listxattrs, dec_listxattrs), 76493e1f0212SFrank van der Linden PROC42(REMOVEXATTR, enc_removexattr, dec_removexattr), 7650c5675526SAnna Schumaker PROC42(READ_PLUS, enc_read_plus, dec_read_plus), 76511da177e4SLinus Torvalds }; 76521da177e4SLinus Torvalds 7653c551858aSChristoph Hellwig static unsigned int nfs_version4_counts[ARRAY_SIZE(nfs4_procedures)]; 7654a613fa16STrond Myklebust const struct rpc_version nfs_version4 = { 76551da177e4SLinus Torvalds .number = 4, 7656e8c96f8cSTobias Klauser .nrprocs = ARRAY_SIZE(nfs4_procedures), 7657c551858aSChristoph Hellwig .procs = nfs4_procedures, 7658c551858aSChristoph Hellwig .counts = nfs_version4_counts, 76591da177e4SLinus Torvalds }; 7660