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> 471da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h> 482449ea2eSAlexandros Batsakis #include <linux/sunrpc/msg_prot.h> 495a5ea0d4SBryan Schumaker #include <linux/sunrpc/gss_api.h> 501da177e4SLinus Torvalds #include <linux/nfs.h> 511da177e4SLinus Torvalds #include <linux/nfs4.h> 521da177e4SLinus Torvalds #include <linux/nfs_fs.h> 531da177e4SLinus Torvalds #include <linux/nfs_idmap.h> 544ce79717STrond Myklebust #include "nfs4_fs.h" 554882ef72SAlexandros Batsakis #include "internal.h" 56b1f69b75SAndy Adamson #include "pnfs.h" 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds #define NFSDBG_FACILITY NFSDBG_XDR 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds /* Mapping from NFS error code to "errno" error code. */ 611da177e4SLinus Torvalds #define errno_NFSERR_IO EIO 621da177e4SLinus Torvalds 630a8ea437SDavid Howells static int nfs4_stat_to_errno(int); 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds /* NFSv4 COMPOUND tags are only wanted for debugging purposes */ 661da177e4SLinus Torvalds #ifdef DEBUG 671da177e4SLinus Torvalds #define NFS4_MAXTAGLEN 20 681da177e4SLinus Torvalds #else 691da177e4SLinus Torvalds #define NFS4_MAXTAGLEN 0 701da177e4SLinus Torvalds #endif 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds /* lock,open owner id: 739f958ab8STrond Myklebust * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) 741da177e4SLinus Torvalds */ 75d035c36cSTrond Myklebust #define open_owner_id_maxsz (1 + 1 + 4) 76d035c36cSTrond Myklebust #define lock_owner_id_maxsz (1 + 1 + 4) 779104a55dSTrond Myklebust #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 781da177e4SLinus Torvalds #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) 791da177e4SLinus Torvalds #define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) 801da177e4SLinus Torvalds #define op_encode_hdr_maxsz (1) 811da177e4SLinus Torvalds #define op_decode_hdr_maxsz (2) 829104a55dSTrond Myklebust #define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) 839104a55dSTrond Myklebust #define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) 849104a55dSTrond Myklebust #define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) 859104a55dSTrond Myklebust #define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) 861da177e4SLinus Torvalds #define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \ 871da177e4SLinus Torvalds (NFS4_FHSIZE >> 2)) 881da177e4SLinus Torvalds #define decode_putfh_maxsz (op_decode_hdr_maxsz) 891da177e4SLinus Torvalds #define encode_putrootfh_maxsz (op_encode_hdr_maxsz) 901da177e4SLinus Torvalds #define decode_putrootfh_maxsz (op_decode_hdr_maxsz) 911da177e4SLinus Torvalds #define encode_getfh_maxsz (op_encode_hdr_maxsz) 921da177e4SLinus Torvalds #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ 931da177e4SLinus Torvalds ((3+NFS4_FHSIZE) >> 2)) 9496928206SJ. Bruce Fields #define nfs4_fattr_bitmap_maxsz 3 9596928206SJ. Bruce Fields #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) 961da177e4SLinus Torvalds #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) 971da177e4SLinus Torvalds #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) 98bd625ba8STrond Myklebust #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 99bd625ba8STrond Myklebust #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 10096928206SJ. Bruce Fields /* This is based on getfattr, which uses the most attributes: */ 10196928206SJ. Bruce Fields #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ 102bd625ba8STrond Myklebust 3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz)) 10396928206SJ. Bruce Fields #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ 10496928206SJ. Bruce Fields nfs4_fattr_value_maxsz) 10596928206SJ. Bruce Fields #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) 1069104a55dSTrond Myklebust #define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \ 1079104a55dSTrond Myklebust 1 + 2 + 1 + \ 1089104a55dSTrond Myklebust nfs4_owner_maxsz + \ 1099104a55dSTrond Myklebust nfs4_group_maxsz + \ 1109104a55dSTrond Myklebust 4 + 4) 1111da177e4SLinus Torvalds #define encode_savefh_maxsz (op_encode_hdr_maxsz) 1121da177e4SLinus Torvalds #define decode_savefh_maxsz (op_decode_hdr_maxsz) 11356ae19f3STrond Myklebust #define encode_restorefh_maxsz (op_encode_hdr_maxsz) 11456ae19f3STrond Myklebust #define decode_restorefh_maxsz (op_decode_hdr_maxsz) 1152f42b5d0SFred Isaman #define encode_fsinfo_maxsz (encode_getattr_maxsz) 1167ebb9315SBryan Schumaker #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 15) 1171da177e4SLinus Torvalds #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) 1181da177e4SLinus Torvalds #define decode_renew_maxsz (op_decode_hdr_maxsz) 1191da177e4SLinus Torvalds #define encode_setclientid_maxsz \ 1201da177e4SLinus Torvalds (op_encode_hdr_maxsz + \ 121cc38bac3SChuck Lever XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ 122cc38bac3SChuck Lever XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \ 123cc38bac3SChuck Lever 1 /* sc_prog */ + \ 124cc38bac3SChuck Lever XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ 125cc38bac3SChuck Lever XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ 126cc38bac3SChuck Lever 1) /* sc_cb_ident */ 1271da177e4SLinus Torvalds #define decode_setclientid_maxsz \ 1281da177e4SLinus Torvalds (op_decode_hdr_maxsz + \ 1291da177e4SLinus Torvalds 2 + \ 1301da177e4SLinus Torvalds 1024) /* large value for CLID_INUSE */ 1311da177e4SLinus Torvalds #define encode_setclientid_confirm_maxsz \ 1321da177e4SLinus Torvalds (op_encode_hdr_maxsz + \ 1331da177e4SLinus Torvalds 3 + (NFS4_VERIFIER_SIZE >> 2)) 1341da177e4SLinus Torvalds #define decode_setclientid_confirm_maxsz \ 1351da177e4SLinus Torvalds (op_decode_hdr_maxsz) 136e6889620STrond Myklebust #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) 137e6889620STrond Myklebust #define decode_lookup_maxsz (op_decode_hdr_maxsz) 1382cebf828STrond Myklebust #define encode_share_access_maxsz \ 1392cebf828STrond Myklebust (2) 1404882ef72SAlexandros Batsakis #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) 1412cebf828STrond Myklebust #define encode_opentype_maxsz (1 + encode_createmode_maxsz) 1422cebf828STrond Myklebust #define encode_claim_null_maxsz (1 + nfs4_name_maxsz) 1432cebf828STrond Myklebust #define encode_open_maxsz (op_encode_hdr_maxsz + \ 1442cebf828STrond Myklebust 2 + encode_share_access_maxsz + 2 + \ 1452cebf828STrond Myklebust open_owner_id_maxsz + \ 1462cebf828STrond Myklebust encode_opentype_maxsz + \ 1472cebf828STrond Myklebust encode_claim_null_maxsz) 1482cebf828STrond Myklebust #define decode_ace_maxsz (3 + nfs4_owner_maxsz) 1499104a55dSTrond Myklebust #define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \ 1502cebf828STrond Myklebust decode_ace_maxsz) 1512cebf828STrond Myklebust #define decode_change_info_maxsz (5) 1522cebf828STrond Myklebust #define decode_open_maxsz (op_decode_hdr_maxsz + \ 1539104a55dSTrond Myklebust decode_stateid_maxsz + \ 1542cebf828STrond Myklebust decode_change_info_maxsz + 1 + \ 1552cebf828STrond Myklebust nfs4_fattr_bitmap_maxsz + \ 1562cebf828STrond Myklebust decode_delegation_maxsz) 1579104a55dSTrond Myklebust #define encode_open_confirm_maxsz \ 1589104a55dSTrond Myklebust (op_encode_hdr_maxsz + \ 1599104a55dSTrond Myklebust encode_stateid_maxsz + 1) 1609104a55dSTrond Myklebust #define decode_open_confirm_maxsz \ 1619104a55dSTrond Myklebust (op_decode_hdr_maxsz + \ 1629104a55dSTrond Myklebust decode_stateid_maxsz) 1639104a55dSTrond Myklebust #define encode_open_downgrade_maxsz \ 1649104a55dSTrond Myklebust (op_encode_hdr_maxsz + \ 1659104a55dSTrond Myklebust encode_stateid_maxsz + 1 + \ 1669104a55dSTrond Myklebust encode_share_access_maxsz) 1679104a55dSTrond Myklebust #define decode_open_downgrade_maxsz \ 1689104a55dSTrond Myklebust (op_decode_hdr_maxsz + \ 1699104a55dSTrond Myklebust decode_stateid_maxsz) 1709104a55dSTrond Myklebust #define encode_close_maxsz (op_encode_hdr_maxsz + \ 1719104a55dSTrond Myklebust 1 + encode_stateid_maxsz) 1729104a55dSTrond Myklebust #define decode_close_maxsz (op_decode_hdr_maxsz + \ 1739104a55dSTrond Myklebust decode_stateid_maxsz) 1749104a55dSTrond Myklebust #define encode_setattr_maxsz (op_encode_hdr_maxsz + \ 1759104a55dSTrond Myklebust encode_stateid_maxsz + \ 1769104a55dSTrond Myklebust encode_attrs_maxsz) 1779104a55dSTrond Myklebust #define decode_setattr_maxsz (op_decode_hdr_maxsz + \ 1789104a55dSTrond Myklebust nfs4_fattr_bitmap_maxsz) 1799104a55dSTrond Myklebust #define encode_read_maxsz (op_encode_hdr_maxsz + \ 1809104a55dSTrond Myklebust encode_stateid_maxsz + 3) 1819104a55dSTrond Myklebust #define decode_read_maxsz (op_decode_hdr_maxsz + 2) 1829104a55dSTrond Myklebust #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ 1839104a55dSTrond Myklebust 2 + encode_verifier_maxsz + 5) 1849104a55dSTrond Myklebust #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ 1859104a55dSTrond Myklebust decode_verifier_maxsz) 1869104a55dSTrond Myklebust #define encode_readlink_maxsz (op_encode_hdr_maxsz) 1879104a55dSTrond Myklebust #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) 1889104a55dSTrond Myklebust #define encode_write_maxsz (op_encode_hdr_maxsz + \ 1899104a55dSTrond Myklebust encode_stateid_maxsz + 4) 1909104a55dSTrond Myklebust #define decode_write_maxsz (op_decode_hdr_maxsz + \ 1919104a55dSTrond Myklebust 2 + decode_verifier_maxsz) 1929104a55dSTrond Myklebust #define encode_commit_maxsz (op_encode_hdr_maxsz + 3) 1939104a55dSTrond Myklebust #define decode_commit_maxsz (op_decode_hdr_maxsz + \ 1949104a55dSTrond Myklebust decode_verifier_maxsz) 1951da177e4SLinus Torvalds #define encode_remove_maxsz (op_encode_hdr_maxsz + \ 1961da177e4SLinus Torvalds nfs4_name_maxsz) 1976ce18391SBenny Halevy #define decode_remove_maxsz (op_decode_hdr_maxsz + \ 1986ce18391SBenny Halevy decode_change_info_maxsz) 1991da177e4SLinus Torvalds #define encode_rename_maxsz (op_encode_hdr_maxsz + \ 2001da177e4SLinus Torvalds 2 * nfs4_name_maxsz) 2016ce18391SBenny Halevy #define decode_rename_maxsz (op_decode_hdr_maxsz + \ 2026ce18391SBenny Halevy decode_change_info_maxsz + \ 2036ce18391SBenny Halevy decode_change_info_maxsz) 2041da177e4SLinus Torvalds #define encode_link_maxsz (op_encode_hdr_maxsz + \ 2051da177e4SLinus Torvalds nfs4_name_maxsz) 2066ce18391SBenny Halevy #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) 207daccbdedSTrond Myklebust #define encode_lockowner_maxsz (7) 2089104a55dSTrond Myklebust #define encode_lock_maxsz (op_encode_hdr_maxsz + \ 2099104a55dSTrond Myklebust 7 + \ 210daccbdedSTrond Myklebust 1 + encode_stateid_maxsz + 1 + \ 211daccbdedSTrond Myklebust encode_lockowner_maxsz) 2129104a55dSTrond Myklebust #define decode_lock_denied_maxsz \ 2139104a55dSTrond Myklebust (8 + decode_lockowner_maxsz) 2149104a55dSTrond Myklebust #define decode_lock_maxsz (op_decode_hdr_maxsz + \ 2159104a55dSTrond Myklebust decode_lock_denied_maxsz) 216daccbdedSTrond Myklebust #define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \ 217daccbdedSTrond Myklebust encode_lockowner_maxsz) 2189104a55dSTrond Myklebust #define decode_lockt_maxsz (op_decode_hdr_maxsz + \ 2199104a55dSTrond Myklebust decode_lock_denied_maxsz) 2209104a55dSTrond Myklebust #define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \ 2219104a55dSTrond Myklebust encode_stateid_maxsz + \ 2229104a55dSTrond Myklebust 4) 2239104a55dSTrond Myklebust #define decode_locku_maxsz (op_decode_hdr_maxsz + \ 2249104a55dSTrond Myklebust decode_stateid_maxsz) 225d3c7b7ccSTrond Myklebust #define encode_release_lockowner_maxsz \ 226d3c7b7ccSTrond Myklebust (op_encode_hdr_maxsz + \ 227d3c7b7ccSTrond Myklebust encode_lockowner_maxsz) 228d3c7b7ccSTrond Myklebust #define decode_release_lockowner_maxsz \ 229d3c7b7ccSTrond Myklebust (op_decode_hdr_maxsz) 2309104a55dSTrond Myklebust #define encode_access_maxsz (op_encode_hdr_maxsz + 1) 2319104a55dSTrond Myklebust #define decode_access_maxsz (op_decode_hdr_maxsz + 2) 2321da177e4SLinus Torvalds #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ 2331da177e4SLinus Torvalds 1 + nfs4_name_maxsz + \ 23494a6d753SChuck Lever 1 + \ 23596928206SJ. Bruce Fields nfs4_fattr_maxsz) 2361da177e4SLinus Torvalds #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) 2371da177e4SLinus Torvalds #define encode_create_maxsz (op_encode_hdr_maxsz + \ 2389104a55dSTrond Myklebust 1 + 2 + nfs4_name_maxsz + \ 2399104a55dSTrond Myklebust encode_attrs_maxsz) 2402cebf828STrond Myklebust #define decode_create_maxsz (op_decode_hdr_maxsz + \ 2412cebf828STrond Myklebust decode_change_info_maxsz + \ 2422cebf828STrond Myklebust nfs4_fattr_bitmap_maxsz) 2439104a55dSTrond Myklebust #define encode_statfs_maxsz (encode_getattr_maxsz) 2449104a55dSTrond Myklebust #define decode_statfs_maxsz (decode_getattr_maxsz) 2451da177e4SLinus Torvalds #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) 2461da177e4SLinus Torvalds #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) 2479104a55dSTrond Myklebust #define encode_getacl_maxsz (encode_getattr_maxsz) 2489104a55dSTrond Myklebust #define decode_getacl_maxsz (op_decode_hdr_maxsz + \ 2499104a55dSTrond Myklebust nfs4_fattr_bitmap_maxsz + 1) 2509104a55dSTrond Myklebust #define encode_setacl_maxsz (op_encode_hdr_maxsz + \ 2519104a55dSTrond Myklebust encode_stateid_maxsz + 3) 2529104a55dSTrond Myklebust #define decode_setacl_maxsz (decode_setattr_maxsz) 253e6889620STrond Myklebust #define encode_fs_locations_maxsz \ 254e6889620STrond Myklebust (encode_getattr_maxsz) 255e6889620STrond Myklebust #define decode_fs_locations_maxsz \ 256e6889620STrond Myklebust (0) 2575a5ea0d4SBryan Schumaker #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) 2585a5ea0d4SBryan Schumaker #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 4 + (NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN))) 2599b7b9fccSAndy Adamson 2609b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 261fc931582SAndy Adamson #define NFS4_MAX_MACHINE_NAME_LEN (64) 262fc931582SAndy Adamson 26399fe60d0SBenny Halevy #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ 26499fe60d0SBenny Halevy encode_verifier_maxsz + \ 26599fe60d0SBenny Halevy 1 /* co_ownerid.len */ + \ 26699fe60d0SBenny Halevy XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \ 26799fe60d0SBenny Halevy 1 /* flags */ + \ 26899fe60d0SBenny Halevy 1 /* spa_how */ + \ 26999fe60d0SBenny Halevy 0 /* SP4_NONE (for now) */ + \ 27099fe60d0SBenny Halevy 1 /* zero implemetation id array */) 27199fe60d0SBenny Halevy #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \ 27299fe60d0SBenny Halevy 2 /* eir_clientid */ + \ 27399fe60d0SBenny Halevy 1 /* eir_sequenceid */ + \ 27499fe60d0SBenny Halevy 1 /* eir_flags */ + \ 27599fe60d0SBenny Halevy 1 /* spr_how */ + \ 27699fe60d0SBenny Halevy 0 /* SP4_NONE (for now) */ + \ 27799fe60d0SBenny Halevy 2 /* eir_server_owner.so_minor_id */ + \ 27899fe60d0SBenny Halevy /* eir_server_owner.so_major_id<> */ \ 27999fe60d0SBenny Halevy XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ 28099fe60d0SBenny Halevy /* eir_server_scope<> */ \ 28199fe60d0SBenny Halevy XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ 28299fe60d0SBenny Halevy 1 /* eir_server_impl_id array length */ + \ 28399fe60d0SBenny Halevy 0 /* ignored eir_server_impl_id contents */) 284fc931582SAndy Adamson #define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */) 285fc931582SAndy Adamson #define decode_channel_attrs_maxsz (6 + \ 286fc931582SAndy Adamson 1 /* ca_rdma_ird.len */ + \ 287fc931582SAndy Adamson 1 /* ca_rdma_ird */) 288fc931582SAndy Adamson #define encode_create_session_maxsz (op_encode_hdr_maxsz + \ 289fc931582SAndy Adamson 2 /* csa_clientid */ + \ 290fc931582SAndy Adamson 1 /* csa_sequence */ + \ 291fc931582SAndy Adamson 1 /* csa_flags */ + \ 292fc931582SAndy Adamson encode_channel_attrs_maxsz + \ 293fc931582SAndy Adamson encode_channel_attrs_maxsz + \ 294fc931582SAndy Adamson 1 /* csa_cb_program */ + \ 295fc931582SAndy Adamson 1 /* csa_sec_parms.len (1) */ + \ 296fc931582SAndy Adamson 1 /* cb_secflavor (AUTH_SYS) */ + \ 297fc931582SAndy Adamson 1 /* stamp */ + \ 298fc931582SAndy Adamson 1 /* machinename.len */ + \ 299fc931582SAndy Adamson XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \ 300fc931582SAndy Adamson 1 /* uid */ + \ 301fc931582SAndy Adamson 1 /* gid */ + \ 302fc931582SAndy Adamson 1 /* gids.len (0) */) 303fc931582SAndy Adamson #define decode_create_session_maxsz (op_decode_hdr_maxsz + \ 304fc931582SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ 305fc931582SAndy Adamson 1 /* csr_sequence */ + \ 306fc931582SAndy Adamson 1 /* csr_flags */ + \ 307fc931582SAndy Adamson decode_channel_attrs_maxsz + \ 308fc931582SAndy Adamson decode_channel_attrs_maxsz) 3090f3e66c6SAndy Adamson #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) 3100f3e66c6SAndy Adamson #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) 311fc01cea9SAndy Adamson #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ 312fc01cea9SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) 313fc01cea9SAndy Adamson #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ 314fc01cea9SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) 31518019753SRicardo Labiaga #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) 31618019753SRicardo Labiaga #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) 317b1f69b75SAndy Adamson #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \ 318b1f69b75SAndy Adamson XDR_QUADLEN(NFS4_DEVICEID4_SIZE)) 319b1f69b75SAndy Adamson #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ 320b1f69b75SAndy Adamson 1 /* layout type */ + \ 321b1f69b75SAndy Adamson 1 /* opaque devaddr4 length */ + \ 322b1f69b75SAndy Adamson /* devaddr4 payload is read into page */ \ 323b1f69b75SAndy Adamson 1 /* notification bitmap length */ + \ 324b1f69b75SAndy Adamson 1 /* notification bitmap */) 325b1f69b75SAndy Adamson #define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \ 326b1f69b75SAndy Adamson encode_stateid_maxsz) 327b1f69b75SAndy Adamson #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ 328b1f69b75SAndy Adamson decode_stateid_maxsz + \ 329b1f69b75SAndy Adamson XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) 330863a3c6cSAndy Adamson #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ 331863a3c6cSAndy Adamson 2 /* offset */ + \ 332863a3c6cSAndy Adamson 2 /* length */ + \ 333863a3c6cSAndy Adamson 1 /* reclaim */ + \ 334863a3c6cSAndy Adamson encode_stateid_maxsz + \ 335863a3c6cSAndy Adamson 1 /* new offset (true) */ + \ 336863a3c6cSAndy Adamson 2 /* last byte written */ + \ 337863a3c6cSAndy Adamson 1 /* nt_timechanged (false) */ + \ 338863a3c6cSAndy Adamson 1 /* layoutupdate4 layout type */ + \ 339863a3c6cSAndy Adamson 1 /* NULL filelayout layoutupdate4 payload */) 340863a3c6cSAndy Adamson #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) 341cbe82603SBenny Halevy #define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \ 342cbe82603SBenny Halevy encode_stateid_maxsz + \ 343cbe82603SBenny Halevy 1 /* FIXME: opaque lrf_body always empty at the moment */) 344cbe82603SBenny Halevy #define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \ 345cbe82603SBenny Halevy 1 + decode_stateid_maxsz) 3469b7b9fccSAndy Adamson #else /* CONFIG_NFS_V4_1 */ 3479b7b9fccSAndy Adamson #define encode_sequence_maxsz 0 3489b7b9fccSAndy Adamson #define decode_sequence_maxsz 0 3499b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 3509b7b9fccSAndy Adamson 3511da177e4SLinus Torvalds #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ 3521da177e4SLinus Torvalds #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ 3531da177e4SLinus Torvalds #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ 3549b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3551da177e4SLinus Torvalds encode_putfh_maxsz + \ 3569104a55dSTrond Myklebust encode_read_maxsz) 3571da177e4SLinus Torvalds #define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \ 3589b7b9fccSAndy Adamson decode_sequence_maxsz + \ 3591da177e4SLinus Torvalds decode_putfh_maxsz + \ 3609104a55dSTrond Myklebust decode_read_maxsz) 3611da177e4SLinus Torvalds #define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \ 3629b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3631da177e4SLinus Torvalds encode_putfh_maxsz + \ 3649104a55dSTrond Myklebust encode_readlink_maxsz) 3651da177e4SLinus Torvalds #define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \ 3669b7b9fccSAndy Adamson decode_sequence_maxsz + \ 3671da177e4SLinus Torvalds decode_putfh_maxsz + \ 3689104a55dSTrond Myklebust decode_readlink_maxsz) 3691da177e4SLinus Torvalds #define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \ 3709b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3711da177e4SLinus Torvalds encode_putfh_maxsz + \ 3729104a55dSTrond Myklebust encode_readdir_maxsz) 3731da177e4SLinus Torvalds #define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \ 3749b7b9fccSAndy Adamson decode_sequence_maxsz + \ 3751da177e4SLinus Torvalds decode_putfh_maxsz + \ 3769104a55dSTrond Myklebust decode_readdir_maxsz) 3771da177e4SLinus Torvalds #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ 3789b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3791da177e4SLinus Torvalds encode_putfh_maxsz + \ 3809104a55dSTrond Myklebust encode_write_maxsz + \ 3814f9838c7STrond Myklebust encode_getattr_maxsz) 3821da177e4SLinus Torvalds #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ 3839b7b9fccSAndy Adamson decode_sequence_maxsz + \ 3841da177e4SLinus Torvalds decode_putfh_maxsz + \ 3859104a55dSTrond Myklebust decode_write_maxsz + \ 3864f9838c7STrond Myklebust decode_getattr_maxsz) 3871da177e4SLinus Torvalds #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ 3889b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3891da177e4SLinus Torvalds encode_putfh_maxsz + \ 3909104a55dSTrond Myklebust encode_commit_maxsz + \ 3914f9838c7STrond Myklebust encode_getattr_maxsz) 3921da177e4SLinus Torvalds #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ 3939b7b9fccSAndy Adamson decode_sequence_maxsz + \ 3941da177e4SLinus Torvalds decode_putfh_maxsz + \ 3959104a55dSTrond Myklebust decode_commit_maxsz + \ 3964f9838c7STrond Myklebust decode_getattr_maxsz) 3971da177e4SLinus Torvalds #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ 3989b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3991da177e4SLinus Torvalds encode_putfh_maxsz + \ 4002cebf828STrond Myklebust encode_savefh_maxsz + \ 4012cebf828STrond Myklebust encode_open_maxsz + \ 4022cebf828STrond Myklebust encode_getfh_maxsz + \ 4031da177e4SLinus Torvalds encode_getattr_maxsz + \ 4042cebf828STrond Myklebust encode_restorefh_maxsz + \ 4052cebf828STrond Myklebust encode_getattr_maxsz) 4061da177e4SLinus Torvalds #define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ 4079b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4081da177e4SLinus Torvalds decode_putfh_maxsz + \ 4092cebf828STrond Myklebust decode_savefh_maxsz + \ 4102cebf828STrond Myklebust decode_open_maxsz + \ 4112cebf828STrond Myklebust decode_getfh_maxsz + \ 4121da177e4SLinus Torvalds decode_getattr_maxsz + \ 4132cebf828STrond Myklebust decode_restorefh_maxsz + \ 4142cebf828STrond Myklebust decode_getattr_maxsz) 4151da177e4SLinus Torvalds #define NFS4_enc_open_confirm_sz \ 4161da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 4171da177e4SLinus Torvalds encode_putfh_maxsz + \ 4189104a55dSTrond Myklebust encode_open_confirm_maxsz) 4199104a55dSTrond Myklebust #define NFS4_dec_open_confirm_sz \ 4209104a55dSTrond Myklebust (compound_decode_hdr_maxsz + \ 4211da177e4SLinus Torvalds decode_putfh_maxsz + \ 4229104a55dSTrond Myklebust decode_open_confirm_maxsz) 4231da177e4SLinus Torvalds #define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \ 4249b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4251da177e4SLinus Torvalds encode_putfh_maxsz + \ 4262cebf828STrond Myklebust encode_open_maxsz + \ 4272cebf828STrond Myklebust encode_getattr_maxsz) 4281da177e4SLinus Torvalds #define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \ 4299b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4301da177e4SLinus Torvalds decode_putfh_maxsz + \ 4312cebf828STrond Myklebust decode_open_maxsz + \ 4322cebf828STrond Myklebust decode_getattr_maxsz) 4331da177e4SLinus Torvalds #define NFS4_enc_open_downgrade_sz \ 4341da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 4359b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4361da177e4SLinus Torvalds encode_putfh_maxsz + \ 4379104a55dSTrond Myklebust encode_open_downgrade_maxsz + \ 438516a6af6STrond Myklebust encode_getattr_maxsz) 4391da177e4SLinus Torvalds #define NFS4_dec_open_downgrade_sz \ 4401da177e4SLinus Torvalds (compound_decode_hdr_maxsz + \ 4419b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4421da177e4SLinus Torvalds decode_putfh_maxsz + \ 4439104a55dSTrond Myklebust decode_open_downgrade_maxsz + \ 444516a6af6STrond Myklebust decode_getattr_maxsz) 4451da177e4SLinus Torvalds #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ 4469b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4471da177e4SLinus Torvalds encode_putfh_maxsz + \ 4489104a55dSTrond Myklebust encode_close_maxsz + \ 449516a6af6STrond Myklebust encode_getattr_maxsz) 4501da177e4SLinus Torvalds #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ 4519b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4521da177e4SLinus Torvalds decode_putfh_maxsz + \ 4539104a55dSTrond Myklebust decode_close_maxsz + \ 454516a6af6STrond Myklebust decode_getattr_maxsz) 4551da177e4SLinus Torvalds #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ 4569b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4571da177e4SLinus Torvalds encode_putfh_maxsz + \ 4589104a55dSTrond Myklebust encode_setattr_maxsz + \ 4591da177e4SLinus Torvalds encode_getattr_maxsz) 4601da177e4SLinus Torvalds #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ 4619b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4621da177e4SLinus Torvalds decode_putfh_maxsz + \ 4639104a55dSTrond Myklebust decode_setattr_maxsz + \ 4649104a55dSTrond Myklebust decode_getattr_maxsz) 4651da177e4SLinus Torvalds #define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \ 4669b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4671da177e4SLinus Torvalds encode_putfh_maxsz + \ 4681da177e4SLinus Torvalds encode_fsinfo_maxsz) 4691da177e4SLinus Torvalds #define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \ 4709b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4711da177e4SLinus Torvalds decode_putfh_maxsz + \ 4721da177e4SLinus Torvalds decode_fsinfo_maxsz) 4731da177e4SLinus Torvalds #define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \ 4741da177e4SLinus Torvalds encode_renew_maxsz) 4751da177e4SLinus Torvalds #define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \ 4761da177e4SLinus Torvalds decode_renew_maxsz) 4771da177e4SLinus Torvalds #define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \ 4781da177e4SLinus Torvalds encode_setclientid_maxsz) 4791da177e4SLinus Torvalds #define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \ 4801da177e4SLinus Torvalds decode_setclientid_maxsz) 4811da177e4SLinus Torvalds #define NFS4_enc_setclientid_confirm_sz \ 4821da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 4831da177e4SLinus Torvalds encode_setclientid_confirm_maxsz + \ 4841da177e4SLinus Torvalds encode_putrootfh_maxsz + \ 4851da177e4SLinus Torvalds encode_fsinfo_maxsz) 4861da177e4SLinus Torvalds #define NFS4_dec_setclientid_confirm_sz \ 4871da177e4SLinus Torvalds (compound_decode_hdr_maxsz + \ 4881da177e4SLinus Torvalds decode_setclientid_confirm_maxsz + \ 4891da177e4SLinus Torvalds decode_putrootfh_maxsz + \ 4901da177e4SLinus Torvalds decode_fsinfo_maxsz) 4911da177e4SLinus Torvalds #define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \ 4929b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4931da177e4SLinus Torvalds encode_putfh_maxsz + \ 4949104a55dSTrond Myklebust encode_lock_maxsz) 4951da177e4SLinus Torvalds #define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \ 4969b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4971da177e4SLinus Torvalds decode_putfh_maxsz + \ 4989104a55dSTrond Myklebust decode_lock_maxsz) 4991da177e4SLinus Torvalds #define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \ 5009b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5011da177e4SLinus Torvalds encode_putfh_maxsz + \ 5029104a55dSTrond Myklebust encode_lockt_maxsz) 5039104a55dSTrond Myklebust #define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \ 5049b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5059104a55dSTrond Myklebust decode_putfh_maxsz + \ 5069104a55dSTrond Myklebust decode_lockt_maxsz) 5071da177e4SLinus Torvalds #define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \ 5089b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5091da177e4SLinus Torvalds encode_putfh_maxsz + \ 5109104a55dSTrond Myklebust encode_locku_maxsz) 5111da177e4SLinus Torvalds #define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \ 5129b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5131da177e4SLinus Torvalds decode_putfh_maxsz + \ 5149104a55dSTrond Myklebust decode_locku_maxsz) 515d3c7b7ccSTrond Myklebust #define NFS4_enc_release_lockowner_sz \ 516d3c7b7ccSTrond Myklebust (compound_encode_hdr_maxsz + \ 517d3c7b7ccSTrond Myklebust encode_lockowner_maxsz) 518d3c7b7ccSTrond Myklebust #define NFS4_dec_release_lockowner_sz \ 519d3c7b7ccSTrond Myklebust (compound_decode_hdr_maxsz + \ 520d3c7b7ccSTrond Myklebust decode_lockowner_maxsz) 5211da177e4SLinus Torvalds #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ 5229b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5231da177e4SLinus Torvalds encode_putfh_maxsz + \ 52476b32999STrond Myklebust encode_access_maxsz + \ 52576b32999STrond Myklebust encode_getattr_maxsz) 5261da177e4SLinus Torvalds #define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ 5279b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5281da177e4SLinus Torvalds decode_putfh_maxsz + \ 52976b32999STrond Myklebust decode_access_maxsz + \ 53076b32999STrond Myklebust decode_getattr_maxsz) 5311da177e4SLinus Torvalds #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ 5329b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5331da177e4SLinus Torvalds encode_putfh_maxsz + \ 5341da177e4SLinus Torvalds encode_getattr_maxsz) 5351da177e4SLinus Torvalds #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ 5369b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5371da177e4SLinus Torvalds decode_putfh_maxsz + \ 5381da177e4SLinus Torvalds decode_getattr_maxsz) 5391da177e4SLinus Torvalds #define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ 5409b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5411da177e4SLinus Torvalds encode_putfh_maxsz + \ 5421da177e4SLinus Torvalds encode_lookup_maxsz + \ 5431da177e4SLinus Torvalds encode_getattr_maxsz + \ 5441da177e4SLinus Torvalds encode_getfh_maxsz) 5451da177e4SLinus Torvalds #define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \ 5469b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5471da177e4SLinus Torvalds decode_putfh_maxsz + \ 548e6889620STrond Myklebust decode_lookup_maxsz + \ 5491da177e4SLinus Torvalds decode_getattr_maxsz + \ 5501da177e4SLinus Torvalds decode_getfh_maxsz) 5511da177e4SLinus Torvalds #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ 5529b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5531da177e4SLinus Torvalds encode_putrootfh_maxsz + \ 5541da177e4SLinus Torvalds encode_getattr_maxsz + \ 5551da177e4SLinus Torvalds encode_getfh_maxsz) 5561da177e4SLinus Torvalds #define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \ 5579b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5581da177e4SLinus Torvalds decode_putrootfh_maxsz + \ 5591da177e4SLinus Torvalds decode_getattr_maxsz + \ 5601da177e4SLinus Torvalds decode_getfh_maxsz) 5611da177e4SLinus Torvalds #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ 5629b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5631da177e4SLinus Torvalds encode_putfh_maxsz + \ 56416e42959STrond Myklebust encode_remove_maxsz + \ 56516e42959STrond Myklebust encode_getattr_maxsz) 5661da177e4SLinus Torvalds #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ 5679b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5681da177e4SLinus Torvalds decode_putfh_maxsz + \ 5696ce18391SBenny Halevy decode_remove_maxsz + \ 57016e42959STrond Myklebust decode_getattr_maxsz) 5711da177e4SLinus Torvalds #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ 5729b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5731da177e4SLinus Torvalds encode_putfh_maxsz + \ 5741da177e4SLinus Torvalds encode_savefh_maxsz + \ 5751da177e4SLinus Torvalds encode_putfh_maxsz + \ 5766caf2c82STrond Myklebust encode_rename_maxsz + \ 5776caf2c82STrond Myklebust encode_getattr_maxsz + \ 5786caf2c82STrond Myklebust encode_restorefh_maxsz + \ 5796caf2c82STrond Myklebust encode_getattr_maxsz) 5801da177e4SLinus Torvalds #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ 5819b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5821da177e4SLinus Torvalds decode_putfh_maxsz + \ 5831da177e4SLinus Torvalds decode_savefh_maxsz + \ 5841da177e4SLinus Torvalds decode_putfh_maxsz + \ 5856caf2c82STrond Myklebust decode_rename_maxsz + \ 5866caf2c82STrond Myklebust decode_getattr_maxsz + \ 5876caf2c82STrond Myklebust decode_restorefh_maxsz + \ 5886caf2c82STrond Myklebust decode_getattr_maxsz) 5891da177e4SLinus Torvalds #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ 5909b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5911da177e4SLinus Torvalds encode_putfh_maxsz + \ 5921da177e4SLinus Torvalds encode_savefh_maxsz + \ 5931da177e4SLinus Torvalds encode_putfh_maxsz + \ 59491ba2eeeSTrond Myklebust encode_link_maxsz + \ 59591ba2eeeSTrond Myklebust decode_getattr_maxsz + \ 59691ba2eeeSTrond Myklebust encode_restorefh_maxsz + \ 59791ba2eeeSTrond Myklebust decode_getattr_maxsz) 5981da177e4SLinus Torvalds #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ 5999b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6001da177e4SLinus Torvalds decode_putfh_maxsz + \ 6011da177e4SLinus Torvalds decode_savefh_maxsz + \ 6021da177e4SLinus Torvalds decode_putfh_maxsz + \ 60391ba2eeeSTrond Myklebust decode_link_maxsz + \ 60491ba2eeeSTrond Myklebust decode_getattr_maxsz + \ 60591ba2eeeSTrond Myklebust decode_restorefh_maxsz + \ 60691ba2eeeSTrond Myklebust decode_getattr_maxsz) 6071da177e4SLinus Torvalds #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ 6089b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6091da177e4SLinus Torvalds encode_putfh_maxsz + \ 6101da177e4SLinus Torvalds encode_symlink_maxsz + \ 6111da177e4SLinus Torvalds encode_getattr_maxsz + \ 6121da177e4SLinus Torvalds encode_getfh_maxsz) 6131da177e4SLinus Torvalds #define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \ 6149b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6151da177e4SLinus Torvalds decode_putfh_maxsz + \ 6161da177e4SLinus Torvalds decode_symlink_maxsz + \ 6171da177e4SLinus Torvalds decode_getattr_maxsz + \ 6181da177e4SLinus Torvalds decode_getfh_maxsz) 6191da177e4SLinus Torvalds #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ 6209b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6211da177e4SLinus Torvalds encode_putfh_maxsz + \ 62256ae19f3STrond Myklebust encode_savefh_maxsz + \ 6231da177e4SLinus Torvalds encode_create_maxsz + \ 62456ae19f3STrond Myklebust encode_getfh_maxsz + \ 6251da177e4SLinus Torvalds encode_getattr_maxsz + \ 62656ae19f3STrond Myklebust encode_restorefh_maxsz + \ 62756ae19f3STrond Myklebust encode_getattr_maxsz) 6281da177e4SLinus Torvalds #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ 6299b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6301da177e4SLinus Torvalds decode_putfh_maxsz + \ 63156ae19f3STrond Myklebust decode_savefh_maxsz + \ 6321da177e4SLinus Torvalds decode_create_maxsz + \ 63356ae19f3STrond Myklebust decode_getfh_maxsz + \ 6341da177e4SLinus Torvalds decode_getattr_maxsz + \ 63556ae19f3STrond Myklebust decode_restorefh_maxsz + \ 63656ae19f3STrond Myklebust decode_getattr_maxsz) 6371da177e4SLinus Torvalds #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ 6389b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6391da177e4SLinus Torvalds encode_putfh_maxsz + \ 6401da177e4SLinus Torvalds encode_getattr_maxsz) 6411da177e4SLinus Torvalds #define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \ 6429b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6431da177e4SLinus Torvalds decode_putfh_maxsz + \ 6441da177e4SLinus Torvalds decode_getattr_maxsz) 6451da177e4SLinus Torvalds #define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \ 6469b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6471da177e4SLinus Torvalds encode_putfh_maxsz + \ 6489104a55dSTrond Myklebust encode_statfs_maxsz) 6491da177e4SLinus Torvalds #define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \ 6509b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6511da177e4SLinus Torvalds decode_putfh_maxsz + \ 6529104a55dSTrond Myklebust decode_statfs_maxsz) 6531da177e4SLinus Torvalds #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ 6549b7b9fccSAndy Adamson encode_sequence_maxsz + \ 655ab91f264STrond Myklebust encode_putfh_maxsz + \ 6561da177e4SLinus Torvalds encode_getattr_maxsz) 6571da177e4SLinus Torvalds #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ 6589b7b9fccSAndy Adamson decode_sequence_maxsz + \ 659ab91f264STrond Myklebust decode_putfh_maxsz + \ 6601da177e4SLinus Torvalds decode_getattr_maxsz) 6611da177e4SLinus Torvalds #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ 6629b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6631da177e4SLinus Torvalds encode_putfh_maxsz + \ 664fa178f29STrond Myklebust encode_delegreturn_maxsz + \ 665fa178f29STrond Myklebust encode_getattr_maxsz) 6661da177e4SLinus Torvalds #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ 6679b7b9fccSAndy Adamson decode_sequence_maxsz + \ 668fa178f29STrond Myklebust decode_delegreturn_maxsz + \ 669fa178f29STrond Myklebust decode_getattr_maxsz) 670029d105eSJ. Bruce Fields #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ 6719b7b9fccSAndy Adamson encode_sequence_maxsz + \ 672029d105eSJ. Bruce Fields encode_putfh_maxsz + \ 6739104a55dSTrond Myklebust encode_getacl_maxsz) 674029d105eSJ. Bruce Fields #define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ 6759b7b9fccSAndy Adamson decode_sequence_maxsz + \ 676029d105eSJ. Bruce Fields decode_putfh_maxsz + \ 6779104a55dSTrond Myklebust decode_getacl_maxsz) 67823ec6965SJ. Bruce Fields #define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ 6799b7b9fccSAndy Adamson encode_sequence_maxsz + \ 68023ec6965SJ. Bruce Fields encode_putfh_maxsz + \ 6819104a55dSTrond Myklebust encode_setacl_maxsz) 68223ec6965SJ. Bruce Fields #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ 6839b7b9fccSAndy Adamson decode_sequence_maxsz + \ 68423ec6965SJ. Bruce Fields decode_putfh_maxsz + \ 6859104a55dSTrond Myklebust decode_setacl_maxsz) 686683b57b4STrond Myklebust #define NFS4_enc_fs_locations_sz \ 687683b57b4STrond Myklebust (compound_encode_hdr_maxsz + \ 6889b7b9fccSAndy Adamson encode_sequence_maxsz + \ 689683b57b4STrond Myklebust encode_putfh_maxsz + \ 690e6889620STrond Myklebust encode_lookup_maxsz + \ 691e6889620STrond Myklebust encode_fs_locations_maxsz) 692683b57b4STrond Myklebust #define NFS4_dec_fs_locations_sz \ 693683b57b4STrond Myklebust (compound_decode_hdr_maxsz + \ 6949b7b9fccSAndy Adamson decode_sequence_maxsz + \ 695683b57b4STrond Myklebust decode_putfh_maxsz + \ 696e6889620STrond Myklebust decode_lookup_maxsz + \ 697e6889620STrond Myklebust decode_fs_locations_maxsz) 6985a5ea0d4SBryan Schumaker #define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \ 6995a5ea0d4SBryan Schumaker encode_sequence_maxsz + \ 7005a5ea0d4SBryan Schumaker encode_putfh_maxsz + \ 7015a5ea0d4SBryan Schumaker encode_secinfo_maxsz) 7025a5ea0d4SBryan Schumaker #define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \ 7035a5ea0d4SBryan Schumaker decode_sequence_maxsz + \ 7045a5ea0d4SBryan Schumaker decode_putfh_maxsz + \ 7055a5ea0d4SBryan Schumaker decode_secinfo_maxsz) 70699fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 70799fe60d0SBenny Halevy #define NFS4_enc_exchange_id_sz \ 70899fe60d0SBenny Halevy (compound_encode_hdr_maxsz + \ 70999fe60d0SBenny Halevy encode_exchange_id_maxsz) 71099fe60d0SBenny Halevy #define NFS4_dec_exchange_id_sz \ 71199fe60d0SBenny Halevy (compound_decode_hdr_maxsz + \ 71299fe60d0SBenny Halevy decode_exchange_id_maxsz) 713fc931582SAndy Adamson #define NFS4_enc_create_session_sz \ 714fc931582SAndy Adamson (compound_encode_hdr_maxsz + \ 715fc931582SAndy Adamson encode_create_session_maxsz) 716fc931582SAndy Adamson #define NFS4_dec_create_session_sz \ 717fc931582SAndy Adamson (compound_decode_hdr_maxsz + \ 718fc931582SAndy Adamson decode_create_session_maxsz) 7190f3e66c6SAndy Adamson #define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \ 7200f3e66c6SAndy Adamson encode_destroy_session_maxsz) 7210f3e66c6SAndy Adamson #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ 7220f3e66c6SAndy Adamson decode_destroy_session_maxsz) 723fc01cea9SAndy Adamson #define NFS4_enc_sequence_sz \ 724fc01cea9SAndy Adamson (compound_decode_hdr_maxsz + \ 725fc01cea9SAndy Adamson encode_sequence_maxsz) 726fc01cea9SAndy Adamson #define NFS4_dec_sequence_sz \ 727fc01cea9SAndy Adamson (compound_decode_hdr_maxsz + \ 728fc01cea9SAndy Adamson decode_sequence_maxsz) 7292050f0ccSAndy Adamson #define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \ 7302050f0ccSAndy Adamson encode_sequence_maxsz + \ 7312050f0ccSAndy Adamson encode_putrootfh_maxsz + \ 7322050f0ccSAndy Adamson encode_fsinfo_maxsz) 7332050f0ccSAndy Adamson #define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \ 7342050f0ccSAndy Adamson decode_sequence_maxsz + \ 7352050f0ccSAndy Adamson decode_putrootfh_maxsz + \ 7362050f0ccSAndy Adamson decode_fsinfo_maxsz) 73718019753SRicardo Labiaga #define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \ 73818019753SRicardo Labiaga encode_sequence_maxsz + \ 73918019753SRicardo Labiaga encode_reclaim_complete_maxsz) 74018019753SRicardo Labiaga #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ 74118019753SRicardo Labiaga decode_sequence_maxsz + \ 74218019753SRicardo Labiaga decode_reclaim_complete_maxsz) 743b1f69b75SAndy Adamson #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ 744b1f69b75SAndy Adamson encode_sequence_maxsz +\ 745b1f69b75SAndy Adamson encode_getdeviceinfo_maxsz) 746b1f69b75SAndy Adamson #define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \ 747b1f69b75SAndy Adamson decode_sequence_maxsz + \ 748b1f69b75SAndy Adamson decode_getdeviceinfo_maxsz) 749b1f69b75SAndy Adamson #define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \ 750b1f69b75SAndy Adamson encode_sequence_maxsz + \ 751b1f69b75SAndy Adamson encode_putfh_maxsz + \ 752b1f69b75SAndy Adamson encode_layoutget_maxsz) 753b1f69b75SAndy Adamson #define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \ 754b1f69b75SAndy Adamson decode_sequence_maxsz + \ 755b1f69b75SAndy Adamson decode_putfh_maxsz + \ 756b1f69b75SAndy Adamson decode_layoutget_maxsz) 757863a3c6cSAndy Adamson #define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ 758863a3c6cSAndy Adamson encode_sequence_maxsz +\ 759863a3c6cSAndy Adamson encode_putfh_maxsz + \ 760863a3c6cSAndy Adamson encode_layoutcommit_maxsz + \ 761863a3c6cSAndy Adamson encode_getattr_maxsz) 762863a3c6cSAndy Adamson #define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ 763863a3c6cSAndy Adamson decode_sequence_maxsz + \ 764863a3c6cSAndy Adamson decode_putfh_maxsz + \ 765863a3c6cSAndy Adamson decode_layoutcommit_maxsz + \ 766863a3c6cSAndy Adamson decode_getattr_maxsz) 767cbe82603SBenny Halevy #define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \ 768cbe82603SBenny Halevy encode_sequence_maxsz + \ 769cbe82603SBenny Halevy encode_putfh_maxsz + \ 770cbe82603SBenny Halevy encode_layoutreturn_maxsz) 771cbe82603SBenny Halevy #define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \ 772cbe82603SBenny Halevy decode_sequence_maxsz + \ 773cbe82603SBenny Halevy decode_putfh_maxsz + \ 774cbe82603SBenny Halevy decode_layoutreturn_maxsz) 7752449ea2eSAlexandros Batsakis 7762449ea2eSAlexandros Batsakis const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 7772449ea2eSAlexandros Batsakis compound_encode_hdr_maxsz + 7782449ea2eSAlexandros Batsakis encode_sequence_maxsz + 7792449ea2eSAlexandros Batsakis encode_putfh_maxsz + 7802449ea2eSAlexandros Batsakis encode_getattr_maxsz) * 7812449ea2eSAlexandros Batsakis XDR_UNIT); 7822449ea2eSAlexandros Batsakis 7832449ea2eSAlexandros Batsakis const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 7842449ea2eSAlexandros Batsakis compound_decode_hdr_maxsz + 7852449ea2eSAlexandros Batsakis decode_sequence_maxsz + 7862449ea2eSAlexandros Batsakis decode_putfh_maxsz) * 7872449ea2eSAlexandros Batsakis XDR_UNIT); 78899fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 7891da177e4SLinus Torvalds 790bca79478STrond Myklebust static const umode_t nfs_type2fmt[] = { 791bca79478STrond Myklebust [NF4BAD] = 0, 792bca79478STrond Myklebust [NF4REG] = S_IFREG, 793bca79478STrond Myklebust [NF4DIR] = S_IFDIR, 794bca79478STrond Myklebust [NF4BLK] = S_IFBLK, 795bca79478STrond Myklebust [NF4CHR] = S_IFCHR, 796bca79478STrond Myklebust [NF4LNK] = S_IFLNK, 797bca79478STrond Myklebust [NF4SOCK] = S_IFSOCK, 798bca79478STrond Myklebust [NF4FIFO] = S_IFIFO, 799bca79478STrond Myklebust [NF4ATTRDIR] = 0, 800bca79478STrond Myklebust [NF4NAMEDATTR] = 0, 8011da177e4SLinus Torvalds }; 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds struct compound_hdr { 8041da177e4SLinus Torvalds int32_t status; 8051da177e4SLinus Torvalds uint32_t nops; 806d017931cSAndy Adamson __be32 * nops_p; 8071da177e4SLinus Torvalds uint32_t taglen; 8081da177e4SLinus Torvalds char * tag; 8090c4e8c18SBenny Halevy uint32_t replen; /* expected reply words */ 81066cc0429SBenny Halevy u32 minorversion; 8111da177e4SLinus Torvalds }; 8121da177e4SLinus Torvalds 81313c65ce9SBenny Halevy static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes) 81413c65ce9SBenny Halevy { 81513c65ce9SBenny Halevy __be32 *p = xdr_reserve_space(xdr, nbytes); 81613c65ce9SBenny Halevy BUG_ON(!p); 81713c65ce9SBenny Halevy return p; 81813c65ce9SBenny Halevy } 8191da177e4SLinus Torvalds 8201da177e4SLinus Torvalds static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) 8211da177e4SLinus Torvalds { 8228687b63aSAl Viro __be32 *p; 8231da177e4SLinus Torvalds 8241da177e4SLinus Torvalds p = xdr_reserve_space(xdr, 4 + len); 8251da177e4SLinus Torvalds BUG_ON(p == NULL); 8261da177e4SLinus Torvalds xdr_encode_opaque(p, str, len); 8271da177e4SLinus Torvalds } 8281da177e4SLinus Torvalds 8290c4e8c18SBenny Halevy static void encode_compound_hdr(struct xdr_stream *xdr, 8300c4e8c18SBenny Halevy struct rpc_rqst *req, 8310c4e8c18SBenny Halevy struct compound_hdr *hdr) 8321da177e4SLinus Torvalds { 8338687b63aSAl Viro __be32 *p; 834a17c2153STrond Myklebust struct rpc_auth *auth = req->rq_cred->cr_auth; 8350c4e8c18SBenny Halevy 8360c4e8c18SBenny Halevy /* initialize running count of expected bytes in reply. 8370c4e8c18SBenny Halevy * NOTE: the replied tag SHOULD be the same is the one sent, 8380c4e8c18SBenny Halevy * but this is not required as a MUST for the server to do so. */ 8390c4e8c18SBenny Halevy hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen; 8401da177e4SLinus Torvalds 8411da177e4SLinus Torvalds dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag); 8421da177e4SLinus Torvalds BUG_ON(hdr->taglen > NFS4_MAXTAGLEN); 843811652bdSBenny Halevy p = reserve_space(xdr, 4 + hdr->taglen + 8); 844811652bdSBenny Halevy p = xdr_encode_opaque(p, hdr->tag, hdr->taglen); 845e75bc1c8SBenny Halevy *p++ = cpu_to_be32(hdr->minorversion); 846d017931cSAndy Adamson hdr->nops_p = p; 84734558513SBenny Halevy *p = cpu_to_be32(hdr->nops); 848d017931cSAndy Adamson } 849d017931cSAndy Adamson 850d017931cSAndy Adamson static void encode_nops(struct compound_hdr *hdr) 851d017931cSAndy Adamson { 852fc931582SAndy Adamson BUG_ON(hdr->nops > NFS4_MAX_OPS); 853d017931cSAndy Adamson *hdr->nops_p = htonl(hdr->nops); 8541da177e4SLinus Torvalds } 8551da177e4SLinus Torvalds 8561da177e4SLinus Torvalds static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf) 8571da177e4SLinus Torvalds { 8588687b63aSAl Viro __be32 *p; 8591da177e4SLinus Torvalds 8601da177e4SLinus Torvalds p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE); 8611da177e4SLinus Torvalds BUG_ON(p == NULL); 8621da177e4SLinus Torvalds xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE); 8631da177e4SLinus Torvalds } 8641da177e4SLinus Torvalds 865cf8cdbe5SAndy Adamson static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server) 8661da177e4SLinus Torvalds { 8671da177e4SLinus Torvalds char owner_name[IDMAP_NAMESZ]; 8681da177e4SLinus Torvalds char owner_group[IDMAP_NAMESZ]; 8691da177e4SLinus Torvalds int owner_namelen = 0; 8701da177e4SLinus Torvalds int owner_grouplen = 0; 8718687b63aSAl Viro __be32 *p; 8728687b63aSAl Viro __be32 *q; 8731da177e4SLinus Torvalds int len; 8741da177e4SLinus Torvalds uint32_t bmval0 = 0; 8751da177e4SLinus Torvalds uint32_t bmval1 = 0; 8761da177e4SLinus Torvalds 8771da177e4SLinus Torvalds /* 8781da177e4SLinus Torvalds * We reserve enough space to write the entire attribute buffer at once. 8791da177e4SLinus Torvalds * In the worst-case, this would be 8801da177e4SLinus Torvalds * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) 8811da177e4SLinus Torvalds * = 36 bytes, plus any contribution from variable-length fields 88223ec6965SJ. Bruce Fields * such as owner/group. 8831da177e4SLinus Torvalds */ 8841da177e4SLinus Torvalds len = 16; 8851da177e4SLinus Torvalds 8861da177e4SLinus Torvalds /* Sigh */ 8871da177e4SLinus Torvalds if (iap->ia_valid & ATTR_SIZE) 8881da177e4SLinus Torvalds len += 8; 8891da177e4SLinus Torvalds if (iap->ia_valid & ATTR_MODE) 8901da177e4SLinus Torvalds len += 4; 8911da177e4SLinus Torvalds if (iap->ia_valid & ATTR_UID) { 892e4fd72a1STrond Myklebust owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); 8931da177e4SLinus Torvalds if (owner_namelen < 0) { 894fe82a183SChuck Lever dprintk("nfs: couldn't resolve uid %d to string\n", 8951da177e4SLinus Torvalds iap->ia_uid); 8961da177e4SLinus Torvalds /* XXX */ 8971da177e4SLinus Torvalds strcpy(owner_name, "nobody"); 8981da177e4SLinus Torvalds owner_namelen = sizeof("nobody") - 1; 8991da177e4SLinus Torvalds /* goto out; */ 9001da177e4SLinus Torvalds } 9011da177e4SLinus Torvalds len += 4 + (XDR_QUADLEN(owner_namelen) << 2); 9021da177e4SLinus Torvalds } 9031da177e4SLinus Torvalds if (iap->ia_valid & ATTR_GID) { 904e4fd72a1STrond Myklebust owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ); 9051da177e4SLinus Torvalds if (owner_grouplen < 0) { 906fe82a183SChuck Lever dprintk("nfs: couldn't resolve gid %d to string\n", 9071da177e4SLinus Torvalds iap->ia_gid); 9081da177e4SLinus Torvalds strcpy(owner_group, "nobody"); 9091da177e4SLinus Torvalds owner_grouplen = sizeof("nobody") - 1; 9101da177e4SLinus Torvalds /* goto out; */ 9111da177e4SLinus Torvalds } 9121da177e4SLinus Torvalds len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); 9131da177e4SLinus Torvalds } 9141da177e4SLinus Torvalds if (iap->ia_valid & ATTR_ATIME_SET) 9151da177e4SLinus Torvalds len += 16; 9161da177e4SLinus Torvalds else if (iap->ia_valid & ATTR_ATIME) 9171da177e4SLinus Torvalds len += 4; 9181da177e4SLinus Torvalds if (iap->ia_valid & ATTR_MTIME_SET) 9191da177e4SLinus Torvalds len += 16; 9201da177e4SLinus Torvalds else if (iap->ia_valid & ATTR_MTIME) 9211da177e4SLinus Torvalds len += 4; 92213c65ce9SBenny Halevy p = reserve_space(xdr, len); 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds /* 9251da177e4SLinus Torvalds * We write the bitmap length now, but leave the bitmap and the attribute 9261da177e4SLinus Torvalds * buffer length to be backfilled at the end of this routine. 9271da177e4SLinus Torvalds */ 928e75bc1c8SBenny Halevy *p++ = cpu_to_be32(2); 9291da177e4SLinus Torvalds q = p; 9301da177e4SLinus Torvalds p += 3; 9311da177e4SLinus Torvalds 9321da177e4SLinus Torvalds if (iap->ia_valid & ATTR_SIZE) { 9331da177e4SLinus Torvalds bmval0 |= FATTR4_WORD0_SIZE; 934b95be5a9SBenny Halevy p = xdr_encode_hyper(p, iap->ia_size); 9351da177e4SLinus Torvalds } 9361da177e4SLinus Torvalds if (iap->ia_valid & ATTR_MODE) { 9371da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_MODE; 938e75bc1c8SBenny Halevy *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); 9391da177e4SLinus Torvalds } 9401da177e4SLinus Torvalds if (iap->ia_valid & ATTR_UID) { 9411da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_OWNER; 942811652bdSBenny Halevy p = xdr_encode_opaque(p, owner_name, owner_namelen); 9431da177e4SLinus Torvalds } 9441da177e4SLinus Torvalds if (iap->ia_valid & ATTR_GID) { 9451da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_OWNER_GROUP; 946811652bdSBenny Halevy p = xdr_encode_opaque(p, owner_group, owner_grouplen); 9471da177e4SLinus Torvalds } 9481da177e4SLinus Torvalds if (iap->ia_valid & ATTR_ATIME_SET) { 9491da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; 950e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 951e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); 952d3f6baaaSTrond Myklebust *p++ = cpu_to_be32(iap->ia_atime.tv_sec); 953d3f6baaaSTrond Myklebust *p++ = cpu_to_be32(iap->ia_atime.tv_nsec); 9541da177e4SLinus Torvalds } 9551da177e4SLinus Torvalds else if (iap->ia_valid & ATTR_ATIME) { 9561da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; 957e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); 9581da177e4SLinus Torvalds } 9591da177e4SLinus Torvalds if (iap->ia_valid & ATTR_MTIME_SET) { 9601da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; 961e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 962e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); 963e75bc1c8SBenny Halevy *p++ = cpu_to_be32(iap->ia_mtime.tv_sec); 964e75bc1c8SBenny Halevy *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec); 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds else if (iap->ia_valid & ATTR_MTIME) { 9671da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; 968e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); 9691da177e4SLinus Torvalds } 9701da177e4SLinus Torvalds 9711da177e4SLinus Torvalds /* 9721da177e4SLinus Torvalds * Now we backfill the bitmap and the attribute buffer length. 9731da177e4SLinus Torvalds */ 9741da177e4SLinus Torvalds if (len != ((char *)p - (char *)q) + 4) { 975fe82a183SChuck Lever printk(KERN_ERR "nfs: Attr length error, %u != %Zu\n", 9761da177e4SLinus Torvalds len, ((char *)p - (char *)q) + 4); 9771da177e4SLinus Torvalds BUG(); 9781da177e4SLinus Torvalds } 9791da177e4SLinus Torvalds len = (char *)p - (char *)q - 12; 9801da177e4SLinus Torvalds *q++ = htonl(bmval0); 9811da177e4SLinus Torvalds *q++ = htonl(bmval1); 98234558513SBenny Halevy *q = htonl(len); 9831da177e4SLinus Torvalds 9841da177e4SLinus Torvalds /* out: */ 9851da177e4SLinus Torvalds } 9861da177e4SLinus Torvalds 987cf8cdbe5SAndy Adamson static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr) 9881da177e4SLinus Torvalds { 9898687b63aSAl Viro __be32 *p; 9901da177e4SLinus Torvalds 99113c65ce9SBenny Halevy p = reserve_space(xdr, 8); 992e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_ACCESS); 99334558513SBenny Halevy *p = cpu_to_be32(access); 994d017931cSAndy Adamson hdr->nops++; 995dadf0c27SBenny Halevy hdr->replen += decode_access_maxsz; 9961da177e4SLinus Torvalds } 9971da177e4SLinus Torvalds 998cf8cdbe5SAndy Adamson static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) 9991da177e4SLinus Torvalds { 10008687b63aSAl Viro __be32 *p; 10011da177e4SLinus Torvalds 100213c65ce9SBenny Halevy p = reserve_space(xdr, 8+NFS4_STATEID_SIZE); 1003e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_CLOSE); 1004e75bc1c8SBenny Halevy *p++ = cpu_to_be32(arg->seqid->sequence->counter); 100534558513SBenny Halevy xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); 1006d017931cSAndy Adamson hdr->nops++; 1007dadf0c27SBenny Halevy hdr->replen += decode_close_maxsz; 10081da177e4SLinus Torvalds } 10091da177e4SLinus Torvalds 1010cf8cdbe5SAndy Adamson static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) 10111da177e4SLinus Torvalds { 10128687b63aSAl Viro __be32 *p; 10131da177e4SLinus Torvalds 101413c65ce9SBenny Halevy p = reserve_space(xdr, 16); 1015e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_COMMIT); 1016b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 101734558513SBenny Halevy *p = cpu_to_be32(args->count); 1018d017931cSAndy Adamson hdr->nops++; 1019dadf0c27SBenny Halevy hdr->replen += decode_commit_maxsz; 10201da177e4SLinus Torvalds } 10211da177e4SLinus Torvalds 1022cf8cdbe5SAndy Adamson static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr) 10231da177e4SLinus Torvalds { 10248687b63aSAl Viro __be32 *p; 10251da177e4SLinus Torvalds 102613c65ce9SBenny Halevy p = reserve_space(xdr, 8); 1027e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_CREATE); 102834558513SBenny Halevy *p = cpu_to_be32(create->ftype); 10291da177e4SLinus Torvalds 10301da177e4SLinus Torvalds switch (create->ftype) { 10311da177e4SLinus Torvalds case NF4LNK: 103213c65ce9SBenny Halevy p = reserve_space(xdr, 4); 103334558513SBenny Halevy *p = cpu_to_be32(create->u.symlink.len); 103494a6d753SChuck Lever xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len); 10351da177e4SLinus Torvalds break; 10361da177e4SLinus Torvalds 10371da177e4SLinus Torvalds case NF4BLK: case NF4CHR: 103813c65ce9SBenny Halevy p = reserve_space(xdr, 8); 1039e75bc1c8SBenny Halevy *p++ = cpu_to_be32(create->u.device.specdata1); 104034558513SBenny Halevy *p = cpu_to_be32(create->u.device.specdata2); 10411da177e4SLinus Torvalds break; 10421da177e4SLinus Torvalds 10431da177e4SLinus Torvalds default: 10441da177e4SLinus Torvalds break; 10451da177e4SLinus Torvalds } 10461da177e4SLinus Torvalds 1047811652bdSBenny Halevy encode_string(xdr, create->name->len, create->name->name); 1048d017931cSAndy Adamson hdr->nops++; 1049dadf0c27SBenny Halevy hdr->replen += decode_create_maxsz; 10501da177e4SLinus Torvalds 1051cf8cdbe5SAndy Adamson encode_attrs(xdr, create->attrs, create->server); 10521da177e4SLinus Torvalds } 10531da177e4SLinus Torvalds 1054cf8cdbe5SAndy Adamson static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) 10551da177e4SLinus Torvalds { 10568687b63aSAl Viro __be32 *p; 10571da177e4SLinus Torvalds 105813c65ce9SBenny Halevy p = reserve_space(xdr, 12); 1059e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_GETATTR); 1060e75bc1c8SBenny Halevy *p++ = cpu_to_be32(1); 106134558513SBenny Halevy *p = cpu_to_be32(bitmap); 1062d017931cSAndy Adamson hdr->nops++; 1063dadf0c27SBenny Halevy hdr->replen += decode_getattr_maxsz; 10641da177e4SLinus Torvalds } 10651da177e4SLinus Torvalds 1066cf8cdbe5SAndy Adamson static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr) 10671da177e4SLinus Torvalds { 10688687b63aSAl Viro __be32 *p; 10691da177e4SLinus Torvalds 107013c65ce9SBenny Halevy p = reserve_space(xdr, 16); 1071e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_GETATTR); 1072e75bc1c8SBenny Halevy *p++ = cpu_to_be32(2); 1073e75bc1c8SBenny Halevy *p++ = cpu_to_be32(bm0); 107434558513SBenny Halevy *p = cpu_to_be32(bm1); 1075d017931cSAndy Adamson hdr->nops++; 1076dadf0c27SBenny Halevy hdr->replen += decode_getattr_maxsz; 10771da177e4SLinus Torvalds } 10781da177e4SLinus Torvalds 1079cf8cdbe5SAndy Adamson static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 10801da177e4SLinus Torvalds { 1081cf8cdbe5SAndy Adamson encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], 1082d017931cSAndy Adamson bitmask[1] & nfs4_fattr_bitmap[1], hdr); 10831da177e4SLinus Torvalds } 10841da177e4SLinus Torvalds 1085cf8cdbe5SAndy Adamson static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 10861da177e4SLinus Torvalds { 1087cf8cdbe5SAndy Adamson encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0], 1088d017931cSAndy Adamson bitmask[1] & nfs4_fsinfo_bitmap[1], hdr); 10891da177e4SLinus Torvalds } 10901da177e4SLinus Torvalds 1091cf8cdbe5SAndy Adamson static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 1092830b8e33SManoj Naik { 1093cf8cdbe5SAndy Adamson encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0], 1094cf8cdbe5SAndy Adamson bitmask[1] & nfs4_fs_locations_bitmap[1], hdr); 1095830b8e33SManoj Naik } 1096830b8e33SManoj Naik 1097cf8cdbe5SAndy Adamson static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr) 10981da177e4SLinus Torvalds { 10998687b63aSAl Viro __be32 *p; 11001da177e4SLinus Torvalds 110113c65ce9SBenny Halevy p = reserve_space(xdr, 4); 110234558513SBenny Halevy *p = cpu_to_be32(OP_GETFH); 1103d017931cSAndy Adamson hdr->nops++; 1104dadf0c27SBenny Halevy hdr->replen += decode_getfh_maxsz; 11051da177e4SLinus Torvalds } 11061da177e4SLinus Torvalds 1107cf8cdbe5SAndy Adamson static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 11081da177e4SLinus Torvalds { 11098687b63aSAl Viro __be32 *p; 11101da177e4SLinus Torvalds 111113c65ce9SBenny Halevy p = reserve_space(xdr, 8 + name->len); 1112e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_LINK); 1113811652bdSBenny Halevy xdr_encode_opaque(p, name->name, name->len); 1114d017931cSAndy Adamson hdr->nops++; 1115dadf0c27SBenny Halevy hdr->replen += decode_link_maxsz; 11161da177e4SLinus Torvalds } 11171da177e4SLinus Torvalds 1118911d1aafSTrond Myklebust static inline int nfs4_lock_type(struct file_lock *fl, int block) 1119911d1aafSTrond Myklebust { 1120911d1aafSTrond Myklebust if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK) 1121911d1aafSTrond Myklebust return block ? NFS4_READW_LT : NFS4_READ_LT; 1122911d1aafSTrond Myklebust return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; 1123911d1aafSTrond Myklebust } 1124911d1aafSTrond Myklebust 1125911d1aafSTrond Myklebust static inline uint64_t nfs4_lock_length(struct file_lock *fl) 1126911d1aafSTrond Myklebust { 1127911d1aafSTrond Myklebust if (fl->fl_end == OFFSET_MAX) 1128911d1aafSTrond Myklebust return ~(uint64_t)0; 1129911d1aafSTrond Myklebust return fl->fl_end - fl->fl_start + 1; 1130911d1aafSTrond Myklebust } 1131911d1aafSTrond Myklebust 1132daccbdedSTrond Myklebust static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner) 1133daccbdedSTrond Myklebust { 1134daccbdedSTrond Myklebust __be32 *p; 1135daccbdedSTrond Myklebust 1136d035c36cSTrond Myklebust p = reserve_space(xdr, 32); 1137daccbdedSTrond Myklebust p = xdr_encode_hyper(p, lowner->clientid); 1138d035c36cSTrond Myklebust *p++ = cpu_to_be32(20); 1139daccbdedSTrond Myklebust p = xdr_encode_opaque_fixed(p, "lock id:", 8); 1140d035c36cSTrond Myklebust *p++ = cpu_to_be32(lowner->s_dev); 1141daccbdedSTrond Myklebust xdr_encode_hyper(p, lowner->id); 1142daccbdedSTrond Myklebust } 1143daccbdedSTrond Myklebust 11441da177e4SLinus Torvalds /* 11451da177e4SLinus Torvalds * opcode,type,reclaim,offset,length,new_lock_owner = 32 11461da177e4SLinus Torvalds * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 11471da177e4SLinus Torvalds */ 1148cf8cdbe5SAndy Adamson static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr) 11491da177e4SLinus Torvalds { 11508687b63aSAl Viro __be32 *p; 11511da177e4SLinus Torvalds 115213c65ce9SBenny Halevy p = reserve_space(xdr, 32); 1153e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_LOCK); 1154e75bc1c8SBenny Halevy *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block)); 1155e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->reclaim); 1156b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 1157b95be5a9SBenny Halevy p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 115834558513SBenny Halevy *p = cpu_to_be32(args->new_lock_owner); 1159911d1aafSTrond Myklebust if (args->new_lock_owner){ 1160daccbdedSTrond Myklebust p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); 1161e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->open_seqid->sequence->counter); 116293f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, args->open_stateid->data, NFS4_STATEID_SIZE); 1163e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->lock_seqid->sequence->counter); 1164daccbdedSTrond Myklebust encode_lockowner(xdr, &args->lock_owner); 11651da177e4SLinus Torvalds } 11661da177e4SLinus Torvalds else { 116713c65ce9SBenny Halevy p = reserve_space(xdr, NFS4_STATEID_SIZE+4); 116893f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, args->lock_stateid->data, NFS4_STATEID_SIZE); 116934558513SBenny Halevy *p = cpu_to_be32(args->lock_seqid->sequence->counter); 11701da177e4SLinus Torvalds } 1171d017931cSAndy Adamson hdr->nops++; 1172dadf0c27SBenny Halevy hdr->replen += decode_lock_maxsz; 11731da177e4SLinus Torvalds } 11741da177e4SLinus Torvalds 1175cf8cdbe5SAndy Adamson static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr) 11761da177e4SLinus Torvalds { 11778687b63aSAl Viro __be32 *p; 11781da177e4SLinus Torvalds 1179daccbdedSTrond Myklebust p = reserve_space(xdr, 24); 1180e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_LOCKT); 1181e75bc1c8SBenny Halevy *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); 1182b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 1183b95be5a9SBenny Halevy p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 1184daccbdedSTrond Myklebust encode_lockowner(xdr, &args->lock_owner); 1185d017931cSAndy Adamson hdr->nops++; 1186dadf0c27SBenny Halevy hdr->replen += decode_lockt_maxsz; 11871da177e4SLinus Torvalds } 11881da177e4SLinus Torvalds 1189cf8cdbe5SAndy Adamson static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr) 11901da177e4SLinus Torvalds { 11918687b63aSAl Viro __be32 *p; 11921da177e4SLinus Torvalds 119313c65ce9SBenny Halevy p = reserve_space(xdr, 12+NFS4_STATEID_SIZE+16); 1194e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_LOCKU); 1195e75bc1c8SBenny Halevy *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); 1196e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->seqid->sequence->counter); 119793f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); 1198b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 119934558513SBenny Halevy xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 1200d017931cSAndy Adamson hdr->nops++; 1201dadf0c27SBenny Halevy hdr->replen += decode_locku_maxsz; 12021da177e4SLinus Torvalds } 12031da177e4SLinus Torvalds 1204d3c7b7ccSTrond Myklebust static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr) 1205d3c7b7ccSTrond Myklebust { 1206d3c7b7ccSTrond Myklebust __be32 *p; 1207d3c7b7ccSTrond Myklebust 1208d3c7b7ccSTrond Myklebust p = reserve_space(xdr, 4); 1209d3c7b7ccSTrond Myklebust *p = cpu_to_be32(OP_RELEASE_LOCKOWNER); 1210d3c7b7ccSTrond Myklebust encode_lockowner(xdr, lowner); 1211d3c7b7ccSTrond Myklebust hdr->nops++; 1212d3c7b7ccSTrond Myklebust hdr->replen += decode_release_lockowner_maxsz; 1213d3c7b7ccSTrond Myklebust } 1214d3c7b7ccSTrond Myklebust 1215cf8cdbe5SAndy Adamson static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 12161da177e4SLinus Torvalds { 12171da177e4SLinus Torvalds int len = name->len; 12188687b63aSAl Viro __be32 *p; 12191da177e4SLinus Torvalds 122013c65ce9SBenny Halevy p = reserve_space(xdr, 8 + len); 1221e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_LOOKUP); 1222811652bdSBenny Halevy xdr_encode_opaque(p, name->name, len); 1223d017931cSAndy Adamson hdr->nops++; 1224dadf0c27SBenny Halevy hdr->replen += decode_lookup_maxsz; 12251da177e4SLinus Torvalds } 12261da177e4SLinus Torvalds 1227dc0b027dSTrond Myklebust static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode) 12281da177e4SLinus Torvalds { 12298687b63aSAl Viro __be32 *p; 12301da177e4SLinus Torvalds 123113c65ce9SBenny Halevy p = reserve_space(xdr, 8); 1232dc0b027dSTrond Myklebust switch (fmode & (FMODE_READ|FMODE_WRITE)) { 12331da177e4SLinus Torvalds case FMODE_READ: 1234e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ); 12351da177e4SLinus Torvalds break; 12361da177e4SLinus Torvalds case FMODE_WRITE: 1237e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE); 12381da177e4SLinus Torvalds break; 12391da177e4SLinus Torvalds case FMODE_READ|FMODE_WRITE: 1240e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH); 12411da177e4SLinus Torvalds break; 12421da177e4SLinus Torvalds default: 1243e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); 12441da177e4SLinus Torvalds } 124534558513SBenny Halevy *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */ 12461da177e4SLinus Torvalds } 12471da177e4SLinus Torvalds 12481da177e4SLinus Torvalds static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg) 12491da177e4SLinus Torvalds { 12508687b63aSAl Viro __be32 *p; 12511da177e4SLinus Torvalds /* 12521da177e4SLinus Torvalds * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, 12531da177e4SLinus Torvalds * owner 4 = 32 12541da177e4SLinus Torvalds */ 125513c65ce9SBenny Halevy p = reserve_space(xdr, 8); 1256e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_OPEN); 125734558513SBenny Halevy *p = cpu_to_be32(arg->seqid->sequence->counter); 1258dc0b027dSTrond Myklebust encode_share_access(xdr, arg->fmode); 1259d035c36cSTrond Myklebust p = reserve_space(xdr, 32); 1260b95be5a9SBenny Halevy p = xdr_encode_hyper(p, arg->clientid); 1261d035c36cSTrond Myklebust *p++ = cpu_to_be32(20); 126293f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, "open id:", 8); 1263d035c36cSTrond Myklebust *p++ = cpu_to_be32(arg->server->s_dev); 126434558513SBenny Halevy xdr_encode_hyper(p, arg->id); 12651da177e4SLinus Torvalds } 12661da177e4SLinus Torvalds 12671da177e4SLinus Torvalds static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) 12681da177e4SLinus Torvalds { 12698687b63aSAl Viro __be32 *p; 12704882ef72SAlexandros Batsakis struct nfs_client *clp; 12711da177e4SLinus Torvalds 127213c65ce9SBenny Halevy p = reserve_space(xdr, 4); 12731da177e4SLinus Torvalds switch(arg->open_flags & O_EXCL) { 12741da177e4SLinus Torvalds case 0: 127534558513SBenny Halevy *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); 12761da177e4SLinus Torvalds encode_attrs(xdr, arg->u.attrs, arg->server); 12771da177e4SLinus Torvalds break; 12781da177e4SLinus Torvalds default: 12794882ef72SAlexandros Batsakis clp = arg->server->nfs_client; 1280a4432345STrond Myklebust if (clp->cl_mvops->minor_version > 0) { 12814882ef72SAlexandros Batsakis if (nfs4_has_persistent_session(clp)) { 12824882ef72SAlexandros Batsakis *p = cpu_to_be32(NFS4_CREATE_GUARDED); 12834882ef72SAlexandros Batsakis encode_attrs(xdr, arg->u.attrs, arg->server); 12844882ef72SAlexandros Batsakis } else { 12854882ef72SAlexandros Batsakis struct iattr dummy; 12864882ef72SAlexandros Batsakis 12874882ef72SAlexandros Batsakis *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); 12884882ef72SAlexandros Batsakis encode_nfs4_verifier(xdr, &arg->u.verifier); 12894882ef72SAlexandros Batsakis dummy.ia_valid = 0; 12904882ef72SAlexandros Batsakis encode_attrs(xdr, &dummy, arg->server); 12914882ef72SAlexandros Batsakis } 12924882ef72SAlexandros Batsakis } else { 129334558513SBenny Halevy *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); 12941da177e4SLinus Torvalds encode_nfs4_verifier(xdr, &arg->u.verifier); 12951da177e4SLinus Torvalds } 12961da177e4SLinus Torvalds } 12974882ef72SAlexandros Batsakis } 12981da177e4SLinus Torvalds 12991da177e4SLinus Torvalds static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg) 13001da177e4SLinus Torvalds { 13018687b63aSAl Viro __be32 *p; 13021da177e4SLinus Torvalds 130313c65ce9SBenny Halevy p = reserve_space(xdr, 4); 13041da177e4SLinus Torvalds switch (arg->open_flags & O_CREAT) { 13051da177e4SLinus Torvalds case 0: 130634558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_NOCREATE); 13071da177e4SLinus Torvalds break; 13081da177e4SLinus Torvalds default: 13091da177e4SLinus Torvalds BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL); 131034558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CREATE); 13111da177e4SLinus Torvalds encode_createmode(xdr, arg); 13121da177e4SLinus Torvalds } 13131da177e4SLinus Torvalds } 13141da177e4SLinus Torvalds 1315bd7bf9d5STrond Myklebust static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type) 13161da177e4SLinus Torvalds { 13178687b63aSAl Viro __be32 *p; 13181da177e4SLinus Torvalds 131913c65ce9SBenny Halevy p = reserve_space(xdr, 4); 13201da177e4SLinus Torvalds switch (delegation_type) { 13211da177e4SLinus Torvalds case 0: 132234558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE); 13231da177e4SLinus Torvalds break; 13241da177e4SLinus Torvalds case FMODE_READ: 132534558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ); 13261da177e4SLinus Torvalds break; 13271da177e4SLinus Torvalds case FMODE_WRITE|FMODE_READ: 132834558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE); 13291da177e4SLinus Torvalds break; 13301da177e4SLinus Torvalds default: 13311da177e4SLinus Torvalds BUG(); 13321da177e4SLinus Torvalds } 13331da177e4SLinus Torvalds } 13341da177e4SLinus Torvalds 13351da177e4SLinus Torvalds static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name) 13361da177e4SLinus Torvalds { 13378687b63aSAl Viro __be32 *p; 13381da177e4SLinus Torvalds 133913c65ce9SBenny Halevy p = reserve_space(xdr, 4); 134034558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL); 13411da177e4SLinus Torvalds encode_string(xdr, name->len, name->name); 13421da177e4SLinus Torvalds } 13431da177e4SLinus Torvalds 1344bd7bf9d5STrond Myklebust static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type) 13451da177e4SLinus Torvalds { 13468687b63aSAl Viro __be32 *p; 13471da177e4SLinus Torvalds 134813c65ce9SBenny Halevy p = reserve_space(xdr, 4); 134934558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS); 13501da177e4SLinus Torvalds encode_delegation_type(xdr, type); 13511da177e4SLinus Torvalds } 13521da177e4SLinus Torvalds 13531da177e4SLinus Torvalds static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid) 13541da177e4SLinus Torvalds { 13558687b63aSAl Viro __be32 *p; 13561da177e4SLinus Torvalds 135713c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); 1358e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR); 135934558513SBenny Halevy xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE); 13601da177e4SLinus Torvalds encode_string(xdr, name->len, name->name); 13611da177e4SLinus Torvalds } 13621da177e4SLinus Torvalds 1363cf8cdbe5SAndy Adamson static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr) 13641da177e4SLinus Torvalds { 13651da177e4SLinus Torvalds encode_openhdr(xdr, arg); 13661da177e4SLinus Torvalds encode_opentype(xdr, arg); 13671da177e4SLinus Torvalds switch (arg->claim) { 13681da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_NULL: 13691da177e4SLinus Torvalds encode_claim_null(xdr, arg->name); 13701da177e4SLinus Torvalds break; 13711da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_PREVIOUS: 13721da177e4SLinus Torvalds encode_claim_previous(xdr, arg->u.delegation_type); 13731da177e4SLinus Torvalds break; 13741da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_DELEGATE_CUR: 13751da177e4SLinus Torvalds encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation); 13761da177e4SLinus Torvalds break; 13771da177e4SLinus Torvalds default: 13781da177e4SLinus Torvalds BUG(); 13791da177e4SLinus Torvalds } 1380d017931cSAndy Adamson hdr->nops++; 1381dadf0c27SBenny Halevy hdr->replen += decode_open_maxsz; 13821da177e4SLinus Torvalds } 13831da177e4SLinus Torvalds 1384cf8cdbe5SAndy Adamson static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr) 13851da177e4SLinus Torvalds { 13868687b63aSAl Viro __be32 *p; 13871da177e4SLinus Torvalds 138813c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); 1389e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_OPEN_CONFIRM); 139093f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); 139134558513SBenny Halevy *p = cpu_to_be32(arg->seqid->sequence->counter); 1392d017931cSAndy Adamson hdr->nops++; 1393dadf0c27SBenny Halevy hdr->replen += decode_open_confirm_maxsz; 13941da177e4SLinus Torvalds } 13951da177e4SLinus Torvalds 1396cf8cdbe5SAndy Adamson static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) 13971da177e4SLinus Torvalds { 13988687b63aSAl Viro __be32 *p; 13991da177e4SLinus Torvalds 140013c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); 1401e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_OPEN_DOWNGRADE); 140293f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); 140334558513SBenny Halevy *p = cpu_to_be32(arg->seqid->sequence->counter); 1404dc0b027dSTrond Myklebust encode_share_access(xdr, arg->fmode); 1405d017931cSAndy Adamson hdr->nops++; 1406dadf0c27SBenny Halevy hdr->replen += decode_open_downgrade_maxsz; 14071da177e4SLinus Torvalds } 14081da177e4SLinus Torvalds 1409cf8cdbe5SAndy Adamson static void 1410d017931cSAndy Adamson encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr) 14111da177e4SLinus Torvalds { 14121da177e4SLinus Torvalds int len = fh->size; 14138687b63aSAl Viro __be32 *p; 14141da177e4SLinus Torvalds 141513c65ce9SBenny Halevy p = reserve_space(xdr, 8 + len); 1416e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_PUTFH); 1417811652bdSBenny Halevy xdr_encode_opaque(p, fh->data, len); 1418d017931cSAndy Adamson hdr->nops++; 1419dadf0c27SBenny Halevy hdr->replen += decode_putfh_maxsz; 14201da177e4SLinus Torvalds } 14211da177e4SLinus Torvalds 1422cf8cdbe5SAndy Adamson static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr) 14231da177e4SLinus Torvalds { 14248687b63aSAl Viro __be32 *p; 14251da177e4SLinus Torvalds 142613c65ce9SBenny Halevy p = reserve_space(xdr, 4); 142734558513SBenny Halevy *p = cpu_to_be32(OP_PUTROOTFH); 1428d017931cSAndy Adamson hdr->nops++; 1429dadf0c27SBenny Halevy hdr->replen += decode_putrootfh_maxsz; 14301da177e4SLinus Torvalds } 14311da177e4SLinus Torvalds 143289d1ea65SAndy Adamson static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx, int zero_seqid) 14331da177e4SLinus Torvalds { 14341da177e4SLinus Torvalds nfs4_stateid stateid; 14358687b63aSAl Viro __be32 *p; 14361da177e4SLinus Torvalds 143713c65ce9SBenny Halevy p = reserve_space(xdr, NFS4_STATEID_SIZE); 14381da177e4SLinus Torvalds if (ctx->state != NULL) { 143977041ed9STrond Myklebust nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid); 144089d1ea65SAndy Adamson if (zero_seqid) 144189d1ea65SAndy Adamson stateid.stateid.seqid = 0; 144234558513SBenny Halevy xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE); 14431da177e4SLinus Torvalds } else 144434558513SBenny Halevy xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); 14451da177e4SLinus Torvalds } 14461da177e4SLinus Torvalds 1447cf8cdbe5SAndy Adamson static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, struct compound_hdr *hdr) 14481da177e4SLinus Torvalds { 14498687b63aSAl Viro __be32 *p; 14501da177e4SLinus Torvalds 145113c65ce9SBenny Halevy p = reserve_space(xdr, 4); 145234558513SBenny Halevy *p = cpu_to_be32(OP_READ); 14531da177e4SLinus Torvalds 145489d1ea65SAndy Adamson encode_stateid(xdr, args->context, args->lock_context, 145589d1ea65SAndy Adamson hdr->minorversion); 14561da177e4SLinus Torvalds 145713c65ce9SBenny Halevy p = reserve_space(xdr, 12); 1458b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 145934558513SBenny Halevy *p = cpu_to_be32(args->count); 1460d017931cSAndy Adamson hdr->nops++; 1461dadf0c27SBenny Halevy hdr->replen += decode_read_maxsz; 14621da177e4SLinus Torvalds } 14631da177e4SLinus Torvalds 1464cf8cdbe5SAndy Adamson static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) 14651da177e4SLinus Torvalds { 146628331a46STrond Myklebust uint32_t attrs[2] = { 146728331a46STrond Myklebust FATTR4_WORD0_RDATTR_ERROR, 146828331a46STrond Myklebust FATTR4_WORD1_MOUNTED_ON_FILEID, 146928331a46STrond Myklebust }; 14706f7a35bdSTrond Myklebust uint32_t dircount = readdir->count >> 1; 14718687b63aSAl Viro __be32 *p; 14721da177e4SLinus Torvalds 147382f2e547SBryan Schumaker if (readdir->plus) { 147482f2e547SBryan Schumaker attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| 147528331a46STrond Myklebust FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID; 147682f2e547SBryan Schumaker attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER| 147782f2e547SBryan Schumaker FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| 147882f2e547SBryan Schumaker FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| 147982f2e547SBryan Schumaker FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; 14806f7a35bdSTrond Myklebust dircount >>= 1; 148182f2e547SBryan Schumaker } 148228331a46STrond Myklebust /* Use mounted_on_fileid only if the server supports it */ 148328331a46STrond Myklebust if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) 148428331a46STrond Myklebust attrs[0] |= FATTR4_WORD0_FILEID; 14856f7a35bdSTrond Myklebust 14866f7a35bdSTrond Myklebust p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20); 14876f7a35bdSTrond Myklebust *p++ = cpu_to_be32(OP_READDIR); 14886f7a35bdSTrond Myklebust p = xdr_encode_hyper(p, readdir->cookie); 14896f7a35bdSTrond Myklebust p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE); 14906f7a35bdSTrond Myklebust *p++ = cpu_to_be32(dircount); 14916f7a35bdSTrond Myklebust *p++ = cpu_to_be32(readdir->count); 14926f7a35bdSTrond Myklebust *p++ = cpu_to_be32(2); 149382f2e547SBryan Schumaker 1494e75bc1c8SBenny Halevy *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); 149534558513SBenny Halevy *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); 1496d017931cSAndy Adamson hdr->nops++; 1497dadf0c27SBenny Halevy hdr->replen += decode_readdir_maxsz; 149844109241SFred Isaman dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", 149944109241SFred Isaman __func__, 1500eadf4598STrond Myklebust (unsigned long long)readdir->cookie, 1501eadf4598STrond Myklebust ((u32 *)readdir->verifier.data)[0], 1502eadf4598STrond Myklebust ((u32 *)readdir->verifier.data)[1], 1503eadf4598STrond Myklebust attrs[0] & readdir->bitmask[0], 1504eadf4598STrond Myklebust attrs[1] & readdir->bitmask[1]); 15051da177e4SLinus Torvalds } 15061da177e4SLinus Torvalds 1507cf8cdbe5SAndy Adamson static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) 15081da177e4SLinus Torvalds { 15098687b63aSAl Viro __be32 *p; 15101da177e4SLinus Torvalds 151113c65ce9SBenny Halevy p = reserve_space(xdr, 4); 151234558513SBenny Halevy *p = cpu_to_be32(OP_READLINK); 1513d017931cSAndy Adamson hdr->nops++; 1514dadf0c27SBenny Halevy hdr->replen += decode_readlink_maxsz; 15151da177e4SLinus Torvalds } 15161da177e4SLinus Torvalds 1517cf8cdbe5SAndy Adamson static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 15181da177e4SLinus Torvalds { 15198687b63aSAl Viro __be32 *p; 15201da177e4SLinus Torvalds 152113c65ce9SBenny Halevy p = reserve_space(xdr, 8 + name->len); 1522e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_REMOVE); 1523811652bdSBenny Halevy xdr_encode_opaque(p, name->name, name->len); 1524d017931cSAndy Adamson hdr->nops++; 1525dadf0c27SBenny Halevy hdr->replen += decode_remove_maxsz; 15261da177e4SLinus Torvalds } 15271da177e4SLinus Torvalds 1528cf8cdbe5SAndy Adamson static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr) 15291da177e4SLinus Torvalds { 15308687b63aSAl Viro __be32 *p; 15311da177e4SLinus Torvalds 1532811652bdSBenny Halevy p = reserve_space(xdr, 4); 1533811652bdSBenny Halevy *p = cpu_to_be32(OP_RENAME); 1534811652bdSBenny Halevy encode_string(xdr, oldname->len, oldname->name); 1535811652bdSBenny Halevy encode_string(xdr, newname->len, newname->name); 1536d017931cSAndy Adamson hdr->nops++; 1537dadf0c27SBenny Halevy hdr->replen += decode_rename_maxsz; 15381da177e4SLinus Torvalds } 15391da177e4SLinus Torvalds 1540cf8cdbe5SAndy Adamson static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid, struct compound_hdr *hdr) 15411da177e4SLinus Torvalds { 15428687b63aSAl Viro __be32 *p; 15431da177e4SLinus Torvalds 154413c65ce9SBenny Halevy p = reserve_space(xdr, 12); 1545e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_RENEW); 154634558513SBenny Halevy xdr_encode_hyper(p, client_stateid->cl_clientid); 1547d017931cSAndy Adamson hdr->nops++; 1548dadf0c27SBenny Halevy hdr->replen += decode_renew_maxsz; 15491da177e4SLinus Torvalds } 15501da177e4SLinus Torvalds 1551cf8cdbe5SAndy Adamson static void 1552d017931cSAndy Adamson encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr) 155356ae19f3STrond Myklebust { 15548687b63aSAl Viro __be32 *p; 155556ae19f3STrond Myklebust 155613c65ce9SBenny Halevy p = reserve_space(xdr, 4); 155734558513SBenny Halevy *p = cpu_to_be32(OP_RESTOREFH); 1558d017931cSAndy Adamson hdr->nops++; 1559dadf0c27SBenny Halevy hdr->replen += decode_restorefh_maxsz; 156056ae19f3STrond Myklebust } 156156ae19f3STrond Myklebust 15629f06c719SChuck Lever static void 1563d017931cSAndy Adamson encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compound_hdr *hdr) 156423ec6965SJ. Bruce Fields { 15658687b63aSAl Viro __be32 *p; 156623ec6965SJ. Bruce Fields 156713c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); 1568e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_SETATTR); 156934558513SBenny Halevy xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); 157013c65ce9SBenny Halevy p = reserve_space(xdr, 2*4); 1571e75bc1c8SBenny Halevy *p++ = cpu_to_be32(1); 157234558513SBenny Halevy *p = cpu_to_be32(FATTR4_WORD0_ACL); 15739f06c719SChuck Lever BUG_ON(arg->acl_len % 4); 157413c65ce9SBenny Halevy p = reserve_space(xdr, 4); 157534558513SBenny Halevy *p = cpu_to_be32(arg->acl_len); 157623ec6965SJ. Bruce Fields xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); 1577d017931cSAndy Adamson hdr->nops++; 1578dadf0c27SBenny Halevy hdr->replen += decode_setacl_maxsz; 157923ec6965SJ. Bruce Fields } 158023ec6965SJ. Bruce Fields 1581cf8cdbe5SAndy Adamson static void 1582d017931cSAndy Adamson encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr) 15831da177e4SLinus Torvalds { 15848687b63aSAl Viro __be32 *p; 15851da177e4SLinus Torvalds 158613c65ce9SBenny Halevy p = reserve_space(xdr, 4); 158734558513SBenny Halevy *p = cpu_to_be32(OP_SAVEFH); 1588d017931cSAndy Adamson hdr->nops++; 1589dadf0c27SBenny Halevy hdr->replen += decode_savefh_maxsz; 15901da177e4SLinus Torvalds } 15911da177e4SLinus Torvalds 1592cf8cdbe5SAndy Adamson static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr) 15931da177e4SLinus Torvalds { 15948687b63aSAl Viro __be32 *p; 15951da177e4SLinus Torvalds 159613c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); 1597e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_SETATTR); 159834558513SBenny Halevy xdr_encode_opaque_fixed(p, arg->stateid.data, NFS4_STATEID_SIZE); 1599d017931cSAndy Adamson hdr->nops++; 1600dadf0c27SBenny Halevy hdr->replen += decode_setattr_maxsz; 1601cf8cdbe5SAndy Adamson encode_attrs(xdr, arg->iap, server); 16021da177e4SLinus Torvalds } 16031da177e4SLinus Torvalds 1604cf8cdbe5SAndy Adamson static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) 16051da177e4SLinus Torvalds { 16068687b63aSAl Viro __be32 *p; 16071da177e4SLinus Torvalds 160813c65ce9SBenny Halevy p = reserve_space(xdr, 4 + NFS4_VERIFIER_SIZE); 1609e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_SETCLIENTID); 161034558513SBenny Halevy xdr_encode_opaque_fixed(p, setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE); 16111da177e4SLinus Torvalds 16121da177e4SLinus Torvalds encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name); 161313c65ce9SBenny Halevy p = reserve_space(xdr, 4); 161434558513SBenny Halevy *p = cpu_to_be32(setclientid->sc_prog); 16151da177e4SLinus Torvalds encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid); 16161da177e4SLinus Torvalds encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr); 161713c65ce9SBenny Halevy p = reserve_space(xdr, 4); 161834558513SBenny Halevy *p = cpu_to_be32(setclientid->sc_cb_ident); 1619d017931cSAndy Adamson hdr->nops++; 1620dadf0c27SBenny Halevy hdr->replen += decode_setclientid_maxsz; 16211da177e4SLinus Torvalds } 16221da177e4SLinus Torvalds 1623bb8b27e5STrond Myklebust static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr) 16241da177e4SLinus Torvalds { 16258687b63aSAl Viro __be32 *p; 16261da177e4SLinus Torvalds 162713c65ce9SBenny Halevy p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE); 1628e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM); 1629bb8b27e5STrond Myklebust p = xdr_encode_hyper(p, arg->clientid); 1630bb8b27e5STrond Myklebust xdr_encode_opaque_fixed(p, arg->confirm.data, NFS4_VERIFIER_SIZE); 1631d017931cSAndy Adamson hdr->nops++; 1632dadf0c27SBenny Halevy hdr->replen += decode_setclientid_confirm_maxsz; 16331da177e4SLinus Torvalds } 16341da177e4SLinus Torvalds 1635cf8cdbe5SAndy Adamson static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) 16361da177e4SLinus Torvalds { 16378687b63aSAl Viro __be32 *p; 16381da177e4SLinus Torvalds 163913c65ce9SBenny Halevy p = reserve_space(xdr, 4); 164034558513SBenny Halevy *p = cpu_to_be32(OP_WRITE); 16411da177e4SLinus Torvalds 164289d1ea65SAndy Adamson encode_stateid(xdr, args->context, args->lock_context, 164389d1ea65SAndy Adamson hdr->minorversion); 16441da177e4SLinus Torvalds 164513c65ce9SBenny Halevy p = reserve_space(xdr, 16); 1646b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 1647e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->stable); 164834558513SBenny Halevy *p = cpu_to_be32(args->count); 16491da177e4SLinus Torvalds 16501da177e4SLinus Torvalds xdr_write_pages(xdr, args->pages, args->pgbase, args->count); 1651d017931cSAndy Adamson hdr->nops++; 1652dadf0c27SBenny Halevy hdr->replen += decode_write_maxsz; 16531da177e4SLinus Torvalds } 16541da177e4SLinus Torvalds 1655cf8cdbe5SAndy Adamson static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr) 16561da177e4SLinus Torvalds { 16578687b63aSAl Viro __be32 *p; 16581da177e4SLinus Torvalds 165913c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); 16601da177e4SLinus Torvalds 1661e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_DELEGRETURN); 166234558513SBenny Halevy xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE); 1663d017931cSAndy Adamson hdr->nops++; 1664dadf0c27SBenny Halevy hdr->replen += decode_delegreturn_maxsz; 16651da177e4SLinus Torvalds } 16669b7b9fccSAndy Adamson 16675a5ea0d4SBryan Schumaker static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 16685a5ea0d4SBryan Schumaker { 16695a5ea0d4SBryan Schumaker int len = name->len; 16705a5ea0d4SBryan Schumaker __be32 *p; 16715a5ea0d4SBryan Schumaker 16725a5ea0d4SBryan Schumaker p = reserve_space(xdr, 8 + len); 16735a5ea0d4SBryan Schumaker *p++ = cpu_to_be32(OP_SECINFO); 16745a5ea0d4SBryan Schumaker xdr_encode_opaque(p, name->name, len); 16755a5ea0d4SBryan Schumaker hdr->nops++; 16765a5ea0d4SBryan Schumaker hdr->replen += decode_secinfo_maxsz; 16775a5ea0d4SBryan Schumaker } 16785a5ea0d4SBryan Schumaker 167999fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 16809b7b9fccSAndy Adamson /* NFSv4.1 operations */ 168199fe60d0SBenny Halevy static void encode_exchange_id(struct xdr_stream *xdr, 168299fe60d0SBenny Halevy struct nfs41_exchange_id_args *args, 168399fe60d0SBenny Halevy struct compound_hdr *hdr) 168499fe60d0SBenny Halevy { 168599fe60d0SBenny Halevy __be32 *p; 168699fe60d0SBenny Halevy 168713c65ce9SBenny Halevy p = reserve_space(xdr, 4 + sizeof(args->verifier->data)); 1688e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_EXCHANGE_ID); 168934558513SBenny Halevy xdr_encode_opaque_fixed(p, args->verifier->data, sizeof(args->verifier->data)); 169099fe60d0SBenny Halevy 169199fe60d0SBenny Halevy encode_string(xdr, args->id_len, args->id); 169299fe60d0SBenny Halevy 169313c65ce9SBenny Halevy p = reserve_space(xdr, 12); 1694e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->flags); 1695e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* zero length state_protect4_a */ 169634558513SBenny Halevy *p = cpu_to_be32(0); /* zero length implementation id array */ 169799fe60d0SBenny Halevy hdr->nops++; 169899fe60d0SBenny Halevy hdr->replen += decode_exchange_id_maxsz; 169999fe60d0SBenny Halevy } 1700fc931582SAndy Adamson 1701fc931582SAndy Adamson static void encode_create_session(struct xdr_stream *xdr, 1702fc931582SAndy Adamson struct nfs41_create_session_args *args, 1703fc931582SAndy Adamson struct compound_hdr *hdr) 1704fc931582SAndy Adamson { 1705fc931582SAndy Adamson __be32 *p; 1706fc931582SAndy Adamson char machine_name[NFS4_MAX_MACHINE_NAME_LEN]; 1707fc931582SAndy Adamson uint32_t len; 1708fc931582SAndy Adamson struct nfs_client *clp = args->client; 17098e0d46e1SMike Sager u32 max_resp_sz_cached; 17108e0d46e1SMike Sager 17118e0d46e1SMike Sager /* 17128e0d46e1SMike Sager * Assumes OPEN is the biggest non-idempotent compound. 17138e0d46e1SMike Sager * 2 is the verifier. 17148e0d46e1SMike Sager */ 17158e0d46e1SMike Sager max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + 17168e0d46e1SMike Sager RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT; 1717fc931582SAndy Adamson 1718fc931582SAndy Adamson len = scnprintf(machine_name, sizeof(machine_name), "%s", 1719fc931582SAndy Adamson clp->cl_ipaddr); 172042edd698SBenny Halevy 172113c65ce9SBenny Halevy p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12); 1722e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_CREATE_SESSION); 1723114f64b5SAndy Adamson p = xdr_encode_hyper(p, clp->cl_clientid); 1724e75bc1c8SBenny Halevy *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ 1725e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->flags); /*flags */ 1726fc931582SAndy Adamson 1727fc931582SAndy Adamson /* Fore Channel */ 1728e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ 1729e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ 1730e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ 17318e0d46e1SMike Sager *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ 1732e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */ 1733e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */ 1734e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ 1735fc931582SAndy Adamson 1736fc931582SAndy Adamson /* Back Channel */ 1737e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ 1738e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ 1739e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ 1740e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ 1741e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */ 1742e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */ 1743e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ 1744fc931582SAndy Adamson 1745e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->cb_program); /* cb_program */ 1746e75bc1c8SBenny Halevy *p++ = cpu_to_be32(1); 1747e75bc1c8SBenny Halevy *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ 1748fc931582SAndy Adamson 1749fc931582SAndy Adamson /* authsys_parms rfc1831 */ 1750e75bc1c8SBenny Halevy *p++ = cpu_to_be32((u32)clp->cl_boot_time.tv_nsec); /* stamp */ 1751811652bdSBenny Halevy p = xdr_encode_opaque(p, machine_name, len); 1752e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* UID */ 1753e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* GID */ 175434558513SBenny Halevy *p = cpu_to_be32(0); /* No more gids */ 1755fc931582SAndy Adamson hdr->nops++; 1756fc931582SAndy Adamson hdr->replen += decode_create_session_maxsz; 1757fc931582SAndy Adamson } 17580f3e66c6SAndy Adamson 17590f3e66c6SAndy Adamson static void encode_destroy_session(struct xdr_stream *xdr, 17600f3e66c6SAndy Adamson struct nfs4_session *session, 17610f3e66c6SAndy Adamson struct compound_hdr *hdr) 17620f3e66c6SAndy Adamson { 17630f3e66c6SAndy Adamson __be32 *p; 176413c65ce9SBenny Halevy p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN); 1765e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_DESTROY_SESSION); 176634558513SBenny Halevy xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); 17670f3e66c6SAndy Adamson hdr->nops++; 17680f3e66c6SAndy Adamson hdr->replen += decode_destroy_session_maxsz; 17690f3e66c6SAndy Adamson } 177018019753SRicardo Labiaga 177118019753SRicardo Labiaga static void encode_reclaim_complete(struct xdr_stream *xdr, 177218019753SRicardo Labiaga struct nfs41_reclaim_complete_args *args, 177318019753SRicardo Labiaga struct compound_hdr *hdr) 177418019753SRicardo Labiaga { 177518019753SRicardo Labiaga __be32 *p; 177618019753SRicardo Labiaga 177718019753SRicardo Labiaga p = reserve_space(xdr, 8); 177818019753SRicardo Labiaga *p++ = cpu_to_be32(OP_RECLAIM_COMPLETE); 177918019753SRicardo Labiaga *p++ = cpu_to_be32(args->one_fs); 178018019753SRicardo Labiaga hdr->nops++; 178118019753SRicardo Labiaga hdr->replen += decode_reclaim_complete_maxsz; 178218019753SRicardo Labiaga } 178399fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 178499fe60d0SBenny Halevy 17859b7b9fccSAndy Adamson static void encode_sequence(struct xdr_stream *xdr, 17869b7b9fccSAndy Adamson const struct nfs4_sequence_args *args, 17879b7b9fccSAndy Adamson struct compound_hdr *hdr) 17889b7b9fccSAndy Adamson { 17899b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 17909b7b9fccSAndy Adamson struct nfs4_session *session = args->sa_session; 1791fc01cea9SAndy Adamson struct nfs4_slot_table *tp; 1792fc01cea9SAndy Adamson struct nfs4_slot *slot; 1793fc01cea9SAndy Adamson __be32 *p; 17949b7b9fccSAndy Adamson 17959b7b9fccSAndy Adamson if (!session) 17969b7b9fccSAndy Adamson return; 17979b7b9fccSAndy Adamson 1798fc01cea9SAndy Adamson tp = &session->fc_slot_table; 1799fc01cea9SAndy Adamson 1800fc01cea9SAndy Adamson WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE); 1801fc01cea9SAndy Adamson slot = tp->slots + args->sa_slotid; 1802fc01cea9SAndy Adamson 180313c65ce9SBenny Halevy p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN + 16); 1804e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_SEQUENCE); 1805fc01cea9SAndy Adamson 1806fc01cea9SAndy Adamson /* 1807fc01cea9SAndy Adamson * Sessionid + seqid + slotid + max slotid + cache_this 1808fc01cea9SAndy Adamson */ 1809fc01cea9SAndy Adamson dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d " 1810fc01cea9SAndy Adamson "max_slotid=%d cache_this=%d\n", 1811fc01cea9SAndy Adamson __func__, 1812fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[0], 1813fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[1], 1814fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[2], 1815fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[3], 1816fc01cea9SAndy Adamson slot->seq_nr, args->sa_slotid, 1817fc01cea9SAndy Adamson tp->highest_used_slotid, args->sa_cache_this); 181893f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); 1819e75bc1c8SBenny Halevy *p++ = cpu_to_be32(slot->seq_nr); 1820e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->sa_slotid); 1821e75bc1c8SBenny Halevy *p++ = cpu_to_be32(tp->highest_used_slotid); 182234558513SBenny Halevy *p = cpu_to_be32(args->sa_cache_this); 18239b7b9fccSAndy Adamson hdr->nops++; 18249b7b9fccSAndy Adamson hdr->replen += decode_sequence_maxsz; 18259b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 18269b7b9fccSAndy Adamson } 18279b7b9fccSAndy Adamson 1828b1f69b75SAndy Adamson #ifdef CONFIG_NFS_V4_1 1829b1f69b75SAndy Adamson static void 1830b1f69b75SAndy Adamson encode_getdeviceinfo(struct xdr_stream *xdr, 1831b1f69b75SAndy Adamson const struct nfs4_getdeviceinfo_args *args, 1832b1f69b75SAndy Adamson struct compound_hdr *hdr) 1833b1f69b75SAndy Adamson { 1834b1f69b75SAndy Adamson __be32 *p; 1835b1f69b75SAndy Adamson 1836b1f69b75SAndy Adamson p = reserve_space(xdr, 16 + NFS4_DEVICEID4_SIZE); 1837b1f69b75SAndy Adamson *p++ = cpu_to_be32(OP_GETDEVICEINFO); 1838b1f69b75SAndy Adamson p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, 1839b1f69b75SAndy Adamson NFS4_DEVICEID4_SIZE); 1840b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->pdev->layout_type); 1841b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->pdev->pglen); /* gdia_maxcount */ 1842b1f69b75SAndy Adamson *p++ = cpu_to_be32(0); /* bitmap length 0 */ 1843b1f69b75SAndy Adamson hdr->nops++; 1844b1f69b75SAndy Adamson hdr->replen += decode_getdeviceinfo_maxsz; 1845b1f69b75SAndy Adamson } 1846b1f69b75SAndy Adamson 1847b1f69b75SAndy Adamson static void 1848b1f69b75SAndy Adamson encode_layoutget(struct xdr_stream *xdr, 1849b1f69b75SAndy Adamson const struct nfs4_layoutget_args *args, 1850b1f69b75SAndy Adamson struct compound_hdr *hdr) 1851b1f69b75SAndy Adamson { 1852b1f69b75SAndy Adamson __be32 *p; 1853b1f69b75SAndy Adamson 1854b1f69b75SAndy Adamson p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); 1855b1f69b75SAndy Adamson *p++ = cpu_to_be32(OP_LAYOUTGET); 1856b1f69b75SAndy Adamson *p++ = cpu_to_be32(0); /* Signal layout available */ 1857b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->type); 1858b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->range.iomode); 1859b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->range.offset); 1860b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->range.length); 1861b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->minlength); 1862cf7d63f1SFred Isaman p = xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE); 1863b1f69b75SAndy Adamson *p = cpu_to_be32(args->maxcount); 1864b1f69b75SAndy Adamson 1865b1f69b75SAndy Adamson dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", 1866b1f69b75SAndy Adamson __func__, 1867b1f69b75SAndy Adamson args->type, 1868b1f69b75SAndy Adamson args->range.iomode, 1869b1f69b75SAndy Adamson (unsigned long)args->range.offset, 1870b1f69b75SAndy Adamson (unsigned long)args->range.length, 1871b1f69b75SAndy Adamson args->maxcount); 1872b1f69b75SAndy Adamson hdr->nops++; 1873b1f69b75SAndy Adamson hdr->replen += decode_layoutget_maxsz; 1874b1f69b75SAndy Adamson } 1875863a3c6cSAndy Adamson 1876863a3c6cSAndy Adamson static int 1877863a3c6cSAndy Adamson encode_layoutcommit(struct xdr_stream *xdr, 1878ac7db726SBenny Halevy struct inode *inode, 1879863a3c6cSAndy Adamson const struct nfs4_layoutcommit_args *args, 1880863a3c6cSAndy Adamson struct compound_hdr *hdr) 1881863a3c6cSAndy Adamson { 1882863a3c6cSAndy Adamson __be32 *p; 1883863a3c6cSAndy Adamson 1884863a3c6cSAndy Adamson dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, 1885863a3c6cSAndy Adamson NFS_SERVER(args->inode)->pnfs_curr_ld->id); 1886863a3c6cSAndy Adamson 1887ac7db726SBenny Halevy p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); 1888863a3c6cSAndy Adamson *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); 1889863a3c6cSAndy Adamson /* Only whole file layouts */ 1890863a3c6cSAndy Adamson p = xdr_encode_hyper(p, 0); /* offset */ 1891863a3c6cSAndy Adamson p = xdr_encode_hyper(p, NFS4_MAX_UINT64); /* length */ 1892863a3c6cSAndy Adamson *p++ = cpu_to_be32(0); /* reclaim */ 1893863a3c6cSAndy Adamson p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); 1894863a3c6cSAndy Adamson *p++ = cpu_to_be32(1); /* newoffset = TRUE */ 1895863a3c6cSAndy Adamson p = xdr_encode_hyper(p, args->lastbytewritten); 1896863a3c6cSAndy Adamson *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ 1897863a3c6cSAndy Adamson *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ 1898ac7db726SBenny Halevy 1899ac7db726SBenny Halevy if (NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit) 1900ac7db726SBenny Halevy NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit( 1901ac7db726SBenny Halevy NFS_I(inode)->layout, xdr, args); 1902ac7db726SBenny Halevy else { 1903ac7db726SBenny Halevy p = reserve_space(xdr, 4); 1904ac7db726SBenny Halevy *p = cpu_to_be32(0); /* no layout-type payload */ 1905ac7db726SBenny Halevy } 1906863a3c6cSAndy Adamson 1907863a3c6cSAndy Adamson hdr->nops++; 1908863a3c6cSAndy Adamson hdr->replen += decode_layoutcommit_maxsz; 1909863a3c6cSAndy Adamson return 0; 1910863a3c6cSAndy Adamson } 1911cbe82603SBenny Halevy 1912cbe82603SBenny Halevy static void 1913cbe82603SBenny Halevy encode_layoutreturn(struct xdr_stream *xdr, 1914cbe82603SBenny Halevy const struct nfs4_layoutreturn_args *args, 1915cbe82603SBenny Halevy struct compound_hdr *hdr) 1916cbe82603SBenny Halevy { 1917cbe82603SBenny Halevy __be32 *p; 1918cbe82603SBenny Halevy 1919cbe82603SBenny Halevy p = reserve_space(xdr, 20); 1920cbe82603SBenny Halevy *p++ = cpu_to_be32(OP_LAYOUTRETURN); 1921cbe82603SBenny Halevy *p++ = cpu_to_be32(0); /* reclaim. always 0 for now */ 1922cbe82603SBenny Halevy *p++ = cpu_to_be32(args->layout_type); 1923cbe82603SBenny Halevy *p++ = cpu_to_be32(IOMODE_ANY); 1924cbe82603SBenny Halevy *p = cpu_to_be32(RETURN_FILE); 1925cbe82603SBenny Halevy p = reserve_space(xdr, 16 + NFS4_STATEID_SIZE); 1926cbe82603SBenny Halevy p = xdr_encode_hyper(p, 0); 1927cbe82603SBenny Halevy p = xdr_encode_hyper(p, NFS4_MAX_UINT64); 1928cbe82603SBenny Halevy spin_lock(&args->inode->i_lock); 1929cbe82603SBenny Halevy xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE); 1930cbe82603SBenny Halevy spin_unlock(&args->inode->i_lock); 193104a55549SAndy Adamson if (NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn) { 193204a55549SAndy Adamson NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn( 193304a55549SAndy Adamson NFS_I(args->inode)->layout, xdr, args); 193404a55549SAndy Adamson } else { 1935cbe82603SBenny Halevy p = reserve_space(xdr, 4); 1936cbe82603SBenny Halevy *p = cpu_to_be32(0); 193704a55549SAndy Adamson } 1938cbe82603SBenny Halevy hdr->nops++; 1939cbe82603SBenny Halevy hdr->replen += decode_layoutreturn_maxsz; 1940cbe82603SBenny Halevy } 1941b1f69b75SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 1942b1f69b75SAndy Adamson 19431da177e4SLinus Torvalds /* 19441da177e4SLinus Torvalds * END OF "GENERIC" ENCODE ROUTINES. 19451da177e4SLinus Torvalds */ 19461da177e4SLinus Torvalds 194766cc0429SBenny Halevy static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) 194866cc0429SBenny Halevy { 194966cc0429SBenny Halevy #if defined(CONFIG_NFS_V4_1) 195066cc0429SBenny Halevy if (args->sa_session) 1951a4432345STrond Myklebust return args->sa_session->clp->cl_mvops->minor_version; 195266cc0429SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 195366cc0429SBenny Halevy return 0; 195466cc0429SBenny Halevy } 195566cc0429SBenny Halevy 19561da177e4SLinus Torvalds /* 19571da177e4SLinus Torvalds * Encode an ACCESS request 19581da177e4SLinus Torvalds */ 19599f06c719SChuck Lever static void nfs4_xdr_enc_access(struct rpc_rqst *req, struct xdr_stream *xdr, 19609f06c719SChuck Lever const struct nfs4_accessargs *args) 19611da177e4SLinus Torvalds { 19621da177e4SLinus Torvalds struct compound_hdr hdr = { 196366cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 19641da177e4SLinus Torvalds }; 19651da177e4SLinus Torvalds 19669f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 19679f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 19689f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 19699f06c719SChuck Lever encode_access(xdr, args->access, &hdr); 19709f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 1971d017931cSAndy Adamson encode_nops(&hdr); 19721da177e4SLinus Torvalds } 19731da177e4SLinus Torvalds 19741da177e4SLinus Torvalds /* 19751da177e4SLinus Torvalds * Encode LOOKUP request 19761da177e4SLinus Torvalds */ 19779f06c719SChuck Lever static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr, 19789f06c719SChuck Lever const struct nfs4_lookup_arg *args) 19791da177e4SLinus Torvalds { 19801da177e4SLinus Torvalds struct compound_hdr hdr = { 198166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 19821da177e4SLinus Torvalds }; 19831da177e4SLinus Torvalds 19849f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 19859f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 19869f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 19879f06c719SChuck Lever encode_lookup(xdr, args->name, &hdr); 19889f06c719SChuck Lever encode_getfh(xdr, &hdr); 19899f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 1990d017931cSAndy Adamson encode_nops(&hdr); 19911da177e4SLinus Torvalds } 19921da177e4SLinus Torvalds 19931da177e4SLinus Torvalds /* 19941da177e4SLinus Torvalds * Encode LOOKUP_ROOT request 19951da177e4SLinus Torvalds */ 19969f06c719SChuck Lever static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, 19979f06c719SChuck Lever struct xdr_stream *xdr, 19989f06c719SChuck Lever const struct nfs4_lookup_root_arg *args) 19991da177e4SLinus Torvalds { 20001da177e4SLinus Torvalds struct compound_hdr hdr = { 200166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 20021da177e4SLinus Torvalds }; 20031da177e4SLinus Torvalds 20049f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 20059f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 20069f06c719SChuck Lever encode_putrootfh(xdr, &hdr); 20079f06c719SChuck Lever encode_getfh(xdr, &hdr); 20089f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2009d017931cSAndy Adamson encode_nops(&hdr); 20101da177e4SLinus Torvalds } 20111da177e4SLinus Torvalds 20121da177e4SLinus Torvalds /* 20131da177e4SLinus Torvalds * Encode REMOVE request 20141da177e4SLinus Torvalds */ 20159f06c719SChuck Lever static void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr, 20169f06c719SChuck Lever const struct nfs_removeargs *args) 20171da177e4SLinus Torvalds { 20181da177e4SLinus Torvalds struct compound_hdr hdr = { 201966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 20201da177e4SLinus Torvalds }; 20211da177e4SLinus Torvalds 20229f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 20239f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 20249f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 20259f06c719SChuck Lever encode_remove(xdr, &args->name, &hdr); 20269f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2027d017931cSAndy Adamson encode_nops(&hdr); 20281da177e4SLinus Torvalds } 20291da177e4SLinus Torvalds 20301da177e4SLinus Torvalds /* 20311da177e4SLinus Torvalds * Encode RENAME request 20321da177e4SLinus Torvalds */ 20339f06c719SChuck Lever static void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr, 20349f06c719SChuck Lever const struct nfs_renameargs *args) 20351da177e4SLinus Torvalds { 20361da177e4SLinus Torvalds struct compound_hdr hdr = { 203766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 20381da177e4SLinus Torvalds }; 20391da177e4SLinus Torvalds 20409f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 20419f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 20429f06c719SChuck Lever encode_putfh(xdr, args->old_dir, &hdr); 20439f06c719SChuck Lever encode_savefh(xdr, &hdr); 20449f06c719SChuck Lever encode_putfh(xdr, args->new_dir, &hdr); 20459f06c719SChuck Lever encode_rename(xdr, args->old_name, args->new_name, &hdr); 20469f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 20479f06c719SChuck Lever encode_restorefh(xdr, &hdr); 20489f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2049d017931cSAndy Adamson encode_nops(&hdr); 20501da177e4SLinus Torvalds } 20511da177e4SLinus Torvalds 20521da177e4SLinus Torvalds /* 20531da177e4SLinus Torvalds * Encode LINK request 20541da177e4SLinus Torvalds */ 20559f06c719SChuck Lever static void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr, 20569f06c719SChuck Lever const struct nfs4_link_arg *args) 20571da177e4SLinus Torvalds { 20581da177e4SLinus Torvalds struct compound_hdr hdr = { 205966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 20601da177e4SLinus Torvalds }; 20611da177e4SLinus Torvalds 20629f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 20639f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 20649f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 20659f06c719SChuck Lever encode_savefh(xdr, &hdr); 20669f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 20679f06c719SChuck Lever encode_link(xdr, args->name, &hdr); 20689f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 20699f06c719SChuck Lever encode_restorefh(xdr, &hdr); 20709f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2071d017931cSAndy Adamson encode_nops(&hdr); 20721da177e4SLinus Torvalds } 20731da177e4SLinus Torvalds 20741da177e4SLinus Torvalds /* 20751da177e4SLinus Torvalds * Encode CREATE request 20761da177e4SLinus Torvalds */ 20779f06c719SChuck Lever static void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr, 20789f06c719SChuck Lever const struct nfs4_create_arg *args) 20791da177e4SLinus Torvalds { 20801da177e4SLinus Torvalds struct compound_hdr hdr = { 208166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 20821da177e4SLinus Torvalds }; 20831da177e4SLinus Torvalds 20849f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 20859f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 20869f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 20879f06c719SChuck Lever encode_savefh(xdr, &hdr); 20889f06c719SChuck Lever encode_create(xdr, args, &hdr); 20899f06c719SChuck Lever encode_getfh(xdr, &hdr); 20909f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 20919f06c719SChuck Lever encode_restorefh(xdr, &hdr); 20929f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2093d017931cSAndy Adamson encode_nops(&hdr); 20941da177e4SLinus Torvalds } 20951da177e4SLinus Torvalds 20961da177e4SLinus Torvalds /* 20971da177e4SLinus Torvalds * Encode SYMLINK request 20981da177e4SLinus Torvalds */ 20999f06c719SChuck Lever static void nfs4_xdr_enc_symlink(struct rpc_rqst *req, struct xdr_stream *xdr, 21009f06c719SChuck Lever const struct nfs4_create_arg *args) 21011da177e4SLinus Torvalds { 21029f06c719SChuck Lever nfs4_xdr_enc_create(req, xdr, args); 21031da177e4SLinus Torvalds } 21041da177e4SLinus Torvalds 21051da177e4SLinus Torvalds /* 21061da177e4SLinus Torvalds * Encode GETATTR request 21071da177e4SLinus Torvalds */ 21089f06c719SChuck Lever static void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr, 21099f06c719SChuck Lever const struct nfs4_getattr_arg *args) 21101da177e4SLinus Torvalds { 21111da177e4SLinus Torvalds struct compound_hdr hdr = { 211266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21131da177e4SLinus Torvalds }; 21141da177e4SLinus Torvalds 21159f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21169f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21179f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21189f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2119d017931cSAndy Adamson encode_nops(&hdr); 21201da177e4SLinus Torvalds } 21211da177e4SLinus Torvalds 21221da177e4SLinus Torvalds /* 21231da177e4SLinus Torvalds * Encode a CLOSE request 21241da177e4SLinus Torvalds */ 21259f06c719SChuck Lever static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr, 21269f06c719SChuck Lever struct nfs_closeargs *args) 21271da177e4SLinus Torvalds { 21281da177e4SLinus Torvalds struct compound_hdr hdr = { 212966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21301da177e4SLinus Torvalds }; 21311da177e4SLinus Torvalds 21329f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21339f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21349f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21359f06c719SChuck Lever encode_close(xdr, args, &hdr); 21369f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2137d017931cSAndy Adamson encode_nops(&hdr); 21381da177e4SLinus Torvalds } 21391da177e4SLinus Torvalds 21401da177e4SLinus Torvalds /* 21411da177e4SLinus Torvalds * Encode an OPEN request 21421da177e4SLinus Torvalds */ 21439f06c719SChuck Lever static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, 21449f06c719SChuck Lever struct nfs_openargs *args) 21451da177e4SLinus Torvalds { 21461da177e4SLinus Torvalds struct compound_hdr hdr = { 214766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21481da177e4SLinus Torvalds }; 21491da177e4SLinus Torvalds 21509f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21519f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21529f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21539f06c719SChuck Lever encode_savefh(xdr, &hdr); 21549f06c719SChuck Lever encode_open(xdr, args, &hdr); 21559f06c719SChuck Lever encode_getfh(xdr, &hdr); 21569f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 21579f06c719SChuck Lever encode_restorefh(xdr, &hdr); 21589f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2159d017931cSAndy Adamson encode_nops(&hdr); 21601da177e4SLinus Torvalds } 21611da177e4SLinus Torvalds 21621da177e4SLinus Torvalds /* 21631da177e4SLinus Torvalds * Encode an OPEN_CONFIRM request 21641da177e4SLinus Torvalds */ 21659f06c719SChuck Lever static void nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, 21669f06c719SChuck Lever struct xdr_stream *xdr, 21679f06c719SChuck Lever struct nfs_open_confirmargs *args) 21681da177e4SLinus Torvalds { 21691da177e4SLinus Torvalds struct compound_hdr hdr = { 2170d017931cSAndy Adamson .nops = 0, 21711da177e4SLinus Torvalds }; 21721da177e4SLinus Torvalds 21739f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21749f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21759f06c719SChuck Lever encode_open_confirm(xdr, args, &hdr); 2176d017931cSAndy Adamson encode_nops(&hdr); 21771da177e4SLinus Torvalds } 21781da177e4SLinus Torvalds 21791da177e4SLinus Torvalds /* 21801da177e4SLinus Torvalds * Encode an OPEN request with no attributes. 21811da177e4SLinus Torvalds */ 21829f06c719SChuck Lever static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, 21839f06c719SChuck Lever struct xdr_stream *xdr, 21849f06c719SChuck Lever struct nfs_openargs *args) 21851da177e4SLinus Torvalds { 21861da177e4SLinus Torvalds struct compound_hdr hdr = { 218766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21881da177e4SLinus Torvalds }; 21891da177e4SLinus Torvalds 21909f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21919f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21929f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21939f06c719SChuck Lever encode_open(xdr, args, &hdr); 21949f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2195d017931cSAndy Adamson encode_nops(&hdr); 21961da177e4SLinus Torvalds } 21971da177e4SLinus Torvalds 21981da177e4SLinus Torvalds /* 21991da177e4SLinus Torvalds * Encode an OPEN_DOWNGRADE request 22001da177e4SLinus Torvalds */ 22019f06c719SChuck Lever static void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, 22029f06c719SChuck Lever struct xdr_stream *xdr, 22039f06c719SChuck Lever struct nfs_closeargs *args) 22041da177e4SLinus Torvalds { 22051da177e4SLinus Torvalds struct compound_hdr hdr = { 220666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22071da177e4SLinus Torvalds }; 22081da177e4SLinus Torvalds 22099f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22109f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22119f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22129f06c719SChuck Lever encode_open_downgrade(xdr, args, &hdr); 22139f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2214d017931cSAndy Adamson encode_nops(&hdr); 22151da177e4SLinus Torvalds } 22161da177e4SLinus Torvalds 22171da177e4SLinus Torvalds /* 22181da177e4SLinus Torvalds * Encode a LOCK request 22191da177e4SLinus Torvalds */ 22209f06c719SChuck Lever static void nfs4_xdr_enc_lock(struct rpc_rqst *req, struct xdr_stream *xdr, 22219f06c719SChuck Lever struct nfs_lock_args *args) 22221da177e4SLinus Torvalds { 22231da177e4SLinus Torvalds struct compound_hdr hdr = { 222466cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22251da177e4SLinus Torvalds }; 22261da177e4SLinus Torvalds 22279f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22289f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22299f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22309f06c719SChuck Lever encode_lock(xdr, args, &hdr); 2231d017931cSAndy Adamson encode_nops(&hdr); 22321da177e4SLinus Torvalds } 22331da177e4SLinus Torvalds 22341da177e4SLinus Torvalds /* 22351da177e4SLinus Torvalds * Encode a LOCKT request 22361da177e4SLinus Torvalds */ 22379f06c719SChuck Lever static void nfs4_xdr_enc_lockt(struct rpc_rqst *req, struct xdr_stream *xdr, 22389f06c719SChuck Lever struct nfs_lockt_args *args) 22391da177e4SLinus Torvalds { 22401da177e4SLinus Torvalds struct compound_hdr hdr = { 224166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22421da177e4SLinus Torvalds }; 22431da177e4SLinus Torvalds 22449f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22459f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22469f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22479f06c719SChuck Lever encode_lockt(xdr, args, &hdr); 2248d017931cSAndy Adamson encode_nops(&hdr); 22491da177e4SLinus Torvalds } 22501da177e4SLinus Torvalds 22511da177e4SLinus Torvalds /* 22521da177e4SLinus Torvalds * Encode a LOCKU request 22531da177e4SLinus Torvalds */ 22549f06c719SChuck Lever static void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr, 22559f06c719SChuck Lever struct nfs_locku_args *args) 22561da177e4SLinus Torvalds { 22571da177e4SLinus Torvalds struct compound_hdr hdr = { 225866cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22591da177e4SLinus Torvalds }; 22601da177e4SLinus Torvalds 22619f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22629f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22639f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22649f06c719SChuck Lever encode_locku(xdr, args, &hdr); 2265d017931cSAndy Adamson encode_nops(&hdr); 22661da177e4SLinus Torvalds } 22671da177e4SLinus Torvalds 22689f06c719SChuck Lever static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, 22699f06c719SChuck Lever struct xdr_stream *xdr, 22709f06c719SChuck Lever struct nfs_release_lockowner_args *args) 2271d3c7b7ccSTrond Myklebust { 2272d3c7b7ccSTrond Myklebust struct compound_hdr hdr = { 2273d3c7b7ccSTrond Myklebust .minorversion = 0, 2274d3c7b7ccSTrond Myklebust }; 2275d3c7b7ccSTrond Myklebust 22769f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22779f06c719SChuck Lever encode_release_lockowner(xdr, &args->lock_owner, &hdr); 2278d3c7b7ccSTrond Myklebust encode_nops(&hdr); 2279d3c7b7ccSTrond Myklebust } 2280d3c7b7ccSTrond Myklebust 22811da177e4SLinus Torvalds /* 22821da177e4SLinus Torvalds * Encode a READLINK request 22831da177e4SLinus Torvalds */ 22849f06c719SChuck Lever static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr, 22859f06c719SChuck Lever const struct nfs4_readlink *args) 22861da177e4SLinus Torvalds { 22871da177e4SLinus Torvalds struct compound_hdr hdr = { 228866cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22891da177e4SLinus Torvalds }; 22901da177e4SLinus Torvalds 22919f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22929f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22939f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22949f06c719SChuck Lever encode_readlink(xdr, args, req, &hdr); 2295e3a535e1STrond Myklebust 229628f56694SBenny Halevy xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages, 2297e3a535e1STrond Myklebust args->pgbase, args->pglen); 2298d017931cSAndy Adamson encode_nops(&hdr); 22991da177e4SLinus Torvalds } 23001da177e4SLinus Torvalds 23011da177e4SLinus Torvalds /* 23021da177e4SLinus Torvalds * Encode a READDIR request 23031da177e4SLinus Torvalds */ 23049f06c719SChuck Lever static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr, 23059f06c719SChuck Lever const struct nfs4_readdir_arg *args) 23061da177e4SLinus Torvalds { 23071da177e4SLinus Torvalds struct compound_hdr hdr = { 230866cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23091da177e4SLinus Torvalds }; 23101da177e4SLinus Torvalds 23119f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23129f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23139f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23149f06c719SChuck Lever encode_readdir(xdr, args, req, &hdr); 2315d6ac02dfSTrond Myklebust 231628f56694SBenny Halevy xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages, 2317d6ac02dfSTrond Myklebust args->pgbase, args->count); 2318d6ac02dfSTrond Myklebust dprintk("%s: inlined page args = (%u, %p, %u, %u)\n", 231928f56694SBenny Halevy __func__, hdr.replen << 2, args->pages, 2320d6ac02dfSTrond Myklebust args->pgbase, args->count); 2321d017931cSAndy Adamson encode_nops(&hdr); 23221da177e4SLinus Torvalds } 23231da177e4SLinus Torvalds 23241da177e4SLinus Torvalds /* 23251da177e4SLinus Torvalds * Encode a READ request 23261da177e4SLinus Torvalds */ 23279f06c719SChuck Lever static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr, 23289f06c719SChuck Lever struct nfs_readargs *args) 23291da177e4SLinus Torvalds { 23301da177e4SLinus Torvalds struct compound_hdr hdr = { 233166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23321da177e4SLinus Torvalds }; 23331da177e4SLinus Torvalds 23349f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23359f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23369f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23379f06c719SChuck Lever encode_read(xdr, args, &hdr); 23381da177e4SLinus Torvalds 233928f56694SBenny Halevy xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, 23401da177e4SLinus Torvalds args->pages, args->pgbase, args->count); 23414f22ccc3S\"Talpey, Thomas\ req->rq_rcv_buf.flags |= XDRBUF_READ; 2342d017931cSAndy Adamson encode_nops(&hdr); 23431da177e4SLinus Torvalds } 23441da177e4SLinus Torvalds 23451da177e4SLinus Torvalds /* 23461da177e4SLinus Torvalds * Encode an SETATTR request 23471da177e4SLinus Torvalds */ 23489f06c719SChuck Lever static void nfs4_xdr_enc_setattr(struct rpc_rqst *req, struct xdr_stream *xdr, 23499f06c719SChuck Lever struct nfs_setattrargs *args) 23501da177e4SLinus Torvalds { 23511da177e4SLinus Torvalds struct compound_hdr hdr = { 235266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23531da177e4SLinus Torvalds }; 23541da177e4SLinus Torvalds 23559f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23569f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23579f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23589f06c719SChuck Lever encode_setattr(xdr, args, args->server, &hdr); 23599f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2360d017931cSAndy Adamson encode_nops(&hdr); 23611da177e4SLinus Torvalds } 23621da177e4SLinus Torvalds 23631da177e4SLinus Torvalds /* 2364029d105eSJ. Bruce Fields * Encode a GETACL request 2365029d105eSJ. Bruce Fields */ 23669f06c719SChuck Lever static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, 2367029d105eSJ. Bruce Fields struct nfs_getaclargs *args) 2368029d105eSJ. Bruce Fields { 2369029d105eSJ. Bruce Fields struct compound_hdr hdr = { 237066cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2371029d105eSJ. Bruce Fields }; 237228f56694SBenny Halevy uint32_t replen; 2373029d105eSJ. Bruce Fields 23749f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23759f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23769f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 2377d327cf74SJ. Bruce Fields replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1; 23789f06c719SChuck Lever encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); 2379cf8cdbe5SAndy Adamson 238028f56694SBenny Halevy xdr_inline_pages(&req->rq_rcv_buf, replen << 2, 2381029d105eSJ. Bruce Fields args->acl_pages, args->acl_pgbase, args->acl_len); 2382d017931cSAndy Adamson encode_nops(&hdr); 2383029d105eSJ. Bruce Fields } 2384029d105eSJ. Bruce Fields 2385029d105eSJ. Bruce Fields /* 23861da177e4SLinus Torvalds * Encode a WRITE request 23871da177e4SLinus Torvalds */ 23889f06c719SChuck Lever static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr, 23899f06c719SChuck Lever struct nfs_writeargs *args) 23901da177e4SLinus Torvalds { 23911da177e4SLinus Torvalds struct compound_hdr hdr = { 239266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23931da177e4SLinus Torvalds }; 23941da177e4SLinus Torvalds 23959f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23969f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23979f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23989f06c719SChuck Lever encode_write(xdr, args, &hdr); 23994f22ccc3S\"Talpey, Thomas\ req->rq_snd_buf.flags |= XDRBUF_WRITE; 24007ffd1064SFred Isaman if (args->bitmask) 24019f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2402d017931cSAndy Adamson encode_nops(&hdr); 24031da177e4SLinus Torvalds } 24041da177e4SLinus Torvalds 24051da177e4SLinus Torvalds /* 24061da177e4SLinus Torvalds * a COMMIT request 24071da177e4SLinus Torvalds */ 24089f06c719SChuck Lever static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, 24099f06c719SChuck Lever struct nfs_writeargs *args) 24101da177e4SLinus Torvalds { 24111da177e4SLinus Torvalds struct compound_hdr hdr = { 241266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24131da177e4SLinus Torvalds }; 24141da177e4SLinus Torvalds 24159f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24169f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24179f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24189f06c719SChuck Lever encode_commit(xdr, args, &hdr); 2419988b6dceSFred Isaman if (args->bitmask) 24209f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2421d017931cSAndy Adamson encode_nops(&hdr); 24221da177e4SLinus Torvalds } 24231da177e4SLinus Torvalds 24241da177e4SLinus Torvalds /* 24251da177e4SLinus Torvalds * FSINFO request 24261da177e4SLinus Torvalds */ 24279f06c719SChuck Lever static void nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, 24289f06c719SChuck Lever struct nfs4_fsinfo_arg *args) 24291da177e4SLinus Torvalds { 24301da177e4SLinus Torvalds struct compound_hdr hdr = { 243166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24321da177e4SLinus Torvalds }; 24331da177e4SLinus Torvalds 24349f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24359f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24369f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24379f06c719SChuck Lever encode_fsinfo(xdr, args->bitmask, &hdr); 2438d017931cSAndy Adamson encode_nops(&hdr); 24391da177e4SLinus Torvalds } 24401da177e4SLinus Torvalds 24411da177e4SLinus Torvalds /* 24421da177e4SLinus Torvalds * a PATHCONF request 24431da177e4SLinus Torvalds */ 24449f06c719SChuck Lever static void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, 24459f06c719SChuck Lever const struct nfs4_pathconf_arg *args) 24461da177e4SLinus Torvalds { 24471da177e4SLinus Torvalds struct compound_hdr hdr = { 244866cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24491da177e4SLinus Torvalds }; 24501da177e4SLinus Torvalds 24519f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24529f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24539f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24549f06c719SChuck Lever encode_getattr_one(xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0], 2455d017931cSAndy Adamson &hdr); 2456d017931cSAndy Adamson encode_nops(&hdr); 24571da177e4SLinus Torvalds } 24581da177e4SLinus Torvalds 24591da177e4SLinus Torvalds /* 24601da177e4SLinus Torvalds * a STATFS request 24611da177e4SLinus Torvalds */ 24629f06c719SChuck Lever static void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, 24639f06c719SChuck Lever const struct nfs4_statfs_arg *args) 24641da177e4SLinus Torvalds { 24651da177e4SLinus Torvalds struct compound_hdr hdr = { 246666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24671da177e4SLinus Torvalds }; 24681da177e4SLinus Torvalds 24699f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24709f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24719f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24729f06c719SChuck Lever encode_getattr_two(xdr, args->bitmask[0] & nfs4_statfs_bitmap[0], 2473d017931cSAndy Adamson args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr); 2474d017931cSAndy Adamson encode_nops(&hdr); 24751da177e4SLinus Torvalds } 24761da177e4SLinus Torvalds 24771da177e4SLinus Torvalds /* 24781da177e4SLinus Torvalds * GETATTR_BITMAP request 24791da177e4SLinus Torvalds */ 24809f06c719SChuck Lever static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req, 24819f06c719SChuck Lever struct xdr_stream *xdr, 248243652ad5SBenny Halevy struct nfs4_server_caps_arg *args) 24831da177e4SLinus Torvalds { 24841da177e4SLinus Torvalds struct compound_hdr hdr = { 248566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24861da177e4SLinus Torvalds }; 24871da177e4SLinus Torvalds 24889f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24899f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24909f06c719SChuck Lever encode_putfh(xdr, args->fhandle, &hdr); 24919f06c719SChuck Lever encode_getattr_one(xdr, FATTR4_WORD0_SUPPORTED_ATTRS| 24921da177e4SLinus Torvalds FATTR4_WORD0_LINK_SUPPORT| 24931da177e4SLinus Torvalds FATTR4_WORD0_SYMLINK_SUPPORT| 2494d017931cSAndy Adamson FATTR4_WORD0_ACLSUPPORT, &hdr); 2495d017931cSAndy Adamson encode_nops(&hdr); 24961da177e4SLinus Torvalds } 24971da177e4SLinus Torvalds 24981da177e4SLinus Torvalds /* 24991da177e4SLinus Torvalds * a RENEW request 25001da177e4SLinus Torvalds */ 25019f06c719SChuck Lever static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr, 25029f06c719SChuck Lever struct nfs_client *clp) 25031da177e4SLinus Torvalds { 25041da177e4SLinus Torvalds struct compound_hdr hdr = { 2505d017931cSAndy Adamson .nops = 0, 25061da177e4SLinus Torvalds }; 25071da177e4SLinus Torvalds 25089f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25099f06c719SChuck Lever encode_renew(xdr, clp, &hdr); 2510d017931cSAndy Adamson encode_nops(&hdr); 25111da177e4SLinus Torvalds } 25121da177e4SLinus Torvalds 25131da177e4SLinus Torvalds /* 25141da177e4SLinus Torvalds * a SETCLIENTID request 25151da177e4SLinus Torvalds */ 25169f06c719SChuck Lever static void nfs4_xdr_enc_setclientid(struct rpc_rqst *req, 25179f06c719SChuck Lever struct xdr_stream *xdr, 25189f06c719SChuck Lever struct nfs4_setclientid *sc) 25191da177e4SLinus Torvalds { 25201da177e4SLinus Torvalds struct compound_hdr hdr = { 2521d017931cSAndy Adamson .nops = 0, 25221da177e4SLinus Torvalds }; 25231da177e4SLinus Torvalds 25249f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25259f06c719SChuck Lever encode_setclientid(xdr, sc, &hdr); 2526d017931cSAndy Adamson encode_nops(&hdr); 25271da177e4SLinus Torvalds } 25281da177e4SLinus Torvalds 25291da177e4SLinus Torvalds /* 25301da177e4SLinus Torvalds * a SETCLIENTID_CONFIRM request 25311da177e4SLinus Torvalds */ 25329f06c719SChuck Lever static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, 25339f06c719SChuck Lever struct xdr_stream *xdr, 25349f06c719SChuck Lever struct nfs4_setclientid_res *arg) 25351da177e4SLinus Torvalds { 25361da177e4SLinus Torvalds struct compound_hdr hdr = { 2537d017931cSAndy Adamson .nops = 0, 25381da177e4SLinus Torvalds }; 25391da177e4SLinus Torvalds const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 }; 25401da177e4SLinus Torvalds 25419f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25429f06c719SChuck Lever encode_setclientid_confirm(xdr, arg, &hdr); 25439f06c719SChuck Lever encode_putrootfh(xdr, &hdr); 25449f06c719SChuck Lever encode_fsinfo(xdr, lease_bitmap, &hdr); 2545d017931cSAndy Adamson encode_nops(&hdr); 25461da177e4SLinus Torvalds } 25471da177e4SLinus Torvalds 25481da177e4SLinus Torvalds /* 25491da177e4SLinus Torvalds * DELEGRETURN request 25501da177e4SLinus Torvalds */ 25519f06c719SChuck Lever static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, 25529f06c719SChuck Lever struct xdr_stream *xdr, 25539f06c719SChuck Lever const struct nfs4_delegreturnargs *args) 25541da177e4SLinus Torvalds { 25551da177e4SLinus Torvalds struct compound_hdr hdr = { 255666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 25571da177e4SLinus Torvalds }; 25581da177e4SLinus Torvalds 25599f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25609f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25619f06c719SChuck Lever encode_putfh(xdr, args->fhandle, &hdr); 25629f06c719SChuck Lever encode_delegreturn(xdr, args->stateid, &hdr); 25639f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2564d017931cSAndy Adamson encode_nops(&hdr); 25651da177e4SLinus Torvalds } 25661da177e4SLinus Torvalds 25671da177e4SLinus Torvalds /* 2568683b57b4STrond Myklebust * Encode FS_LOCATIONS request 2569683b57b4STrond Myklebust */ 25709f06c719SChuck Lever static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, 25719f06c719SChuck Lever struct xdr_stream *xdr, 25729f06c719SChuck Lever struct nfs4_fs_locations_arg *args) 2573683b57b4STrond Myklebust { 2574683b57b4STrond Myklebust struct compound_hdr hdr = { 257566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2576683b57b4STrond Myklebust }; 257728f56694SBenny Halevy uint32_t replen; 2578683b57b4STrond Myklebust 25799f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25809f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25819f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 25829f06c719SChuck Lever encode_lookup(xdr, args->name, &hdr); 258328f56694SBenny Halevy replen = hdr.replen; /* get the attribute into args->page */ 25849f06c719SChuck Lever encode_fs_locations(xdr, args->bitmask, &hdr); 2585cf8cdbe5SAndy Adamson 258628f56694SBenny Halevy xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page, 2587683b57b4STrond Myklebust 0, PAGE_SIZE); 2588d017931cSAndy Adamson encode_nops(&hdr); 2589683b57b4STrond Myklebust } 2590683b57b4STrond Myklebust 25915a5ea0d4SBryan Schumaker /* 25925a5ea0d4SBryan Schumaker * Encode SECINFO request 25935a5ea0d4SBryan Schumaker */ 25945a5ea0d4SBryan Schumaker static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req, 25955a5ea0d4SBryan Schumaker struct xdr_stream *xdr, 25965a5ea0d4SBryan Schumaker struct nfs4_secinfo_arg *args) 25975a5ea0d4SBryan Schumaker { 25985a5ea0d4SBryan Schumaker struct compound_hdr hdr = { 25995a5ea0d4SBryan Schumaker .minorversion = nfs4_xdr_minorversion(&args->seq_args), 26005a5ea0d4SBryan Schumaker }; 26015a5ea0d4SBryan Schumaker 26025a5ea0d4SBryan Schumaker encode_compound_hdr(xdr, req, &hdr); 26035a5ea0d4SBryan Schumaker encode_sequence(xdr, &args->seq_args, &hdr); 26045a5ea0d4SBryan Schumaker encode_putfh(xdr, args->dir_fh, &hdr); 26055a5ea0d4SBryan Schumaker encode_secinfo(xdr, args->name, &hdr); 26065a5ea0d4SBryan Schumaker encode_nops(&hdr); 26075a5ea0d4SBryan Schumaker } 26085a5ea0d4SBryan Schumaker 260999fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 261099fe60d0SBenny Halevy /* 261199fe60d0SBenny Halevy * EXCHANGE_ID request 261299fe60d0SBenny Halevy */ 26139f06c719SChuck Lever static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, 26149f06c719SChuck Lever struct xdr_stream *xdr, 261599fe60d0SBenny Halevy struct nfs41_exchange_id_args *args) 261699fe60d0SBenny Halevy { 261799fe60d0SBenny Halevy struct compound_hdr hdr = { 2618a4432345STrond Myklebust .minorversion = args->client->cl_mvops->minor_version, 261999fe60d0SBenny Halevy }; 262099fe60d0SBenny Halevy 26219f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26229f06c719SChuck Lever encode_exchange_id(xdr, args, &hdr); 262399fe60d0SBenny Halevy encode_nops(&hdr); 262499fe60d0SBenny Halevy } 26252050f0ccSAndy Adamson 26262050f0ccSAndy Adamson /* 2627fc931582SAndy Adamson * a CREATE_SESSION request 2628fc931582SAndy Adamson */ 26299f06c719SChuck Lever static void nfs4_xdr_enc_create_session(struct rpc_rqst *req, 26309f06c719SChuck Lever struct xdr_stream *xdr, 2631fc931582SAndy Adamson struct nfs41_create_session_args *args) 2632fc931582SAndy Adamson { 2633fc931582SAndy Adamson struct compound_hdr hdr = { 2634a4432345STrond Myklebust .minorversion = args->client->cl_mvops->minor_version, 2635fc931582SAndy Adamson }; 2636fc931582SAndy Adamson 26379f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26389f06c719SChuck Lever encode_create_session(xdr, args, &hdr); 2639fc931582SAndy Adamson encode_nops(&hdr); 2640fc931582SAndy Adamson } 2641fc931582SAndy Adamson 2642fc931582SAndy Adamson /* 26430f3e66c6SAndy Adamson * a DESTROY_SESSION request 26440f3e66c6SAndy Adamson */ 26459f06c719SChuck Lever static void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, 26469f06c719SChuck Lever struct xdr_stream *xdr, 26470f3e66c6SAndy Adamson struct nfs4_session *session) 26480f3e66c6SAndy Adamson { 26490f3e66c6SAndy Adamson struct compound_hdr hdr = { 2650a4432345STrond Myklebust .minorversion = session->clp->cl_mvops->minor_version, 26510f3e66c6SAndy Adamson }; 26520f3e66c6SAndy Adamson 26539f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26549f06c719SChuck Lever encode_destroy_session(xdr, session, &hdr); 26550f3e66c6SAndy Adamson encode_nops(&hdr); 26560f3e66c6SAndy Adamson } 26570f3e66c6SAndy Adamson 26580f3e66c6SAndy Adamson /* 2659fc01cea9SAndy Adamson * a SEQUENCE request 2660fc01cea9SAndy Adamson */ 26619f06c719SChuck Lever static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr, 2662fc01cea9SAndy Adamson struct nfs4_sequence_args *args) 2663fc01cea9SAndy Adamson { 2664fc01cea9SAndy Adamson struct compound_hdr hdr = { 2665fc01cea9SAndy Adamson .minorversion = nfs4_xdr_minorversion(args), 2666fc01cea9SAndy Adamson }; 2667fc01cea9SAndy Adamson 26689f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26699f06c719SChuck Lever encode_sequence(xdr, args, &hdr); 2670fc01cea9SAndy Adamson encode_nops(&hdr); 2671fc01cea9SAndy Adamson } 2672fc01cea9SAndy Adamson 2673fc01cea9SAndy Adamson /* 26742050f0ccSAndy Adamson * a GET_LEASE_TIME request 26752050f0ccSAndy Adamson */ 26769f06c719SChuck Lever static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, 26779f06c719SChuck Lever struct xdr_stream *xdr, 26782050f0ccSAndy Adamson struct nfs4_get_lease_time_args *args) 26792050f0ccSAndy Adamson { 26802050f0ccSAndy Adamson struct compound_hdr hdr = { 26812050f0ccSAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->la_seq_args), 26822050f0ccSAndy Adamson }; 26832050f0ccSAndy Adamson const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 }; 26842050f0ccSAndy Adamson 26859f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26869f06c719SChuck Lever encode_sequence(xdr, &args->la_seq_args, &hdr); 26879f06c719SChuck Lever encode_putrootfh(xdr, &hdr); 26889f06c719SChuck Lever encode_fsinfo(xdr, lease_bitmap, &hdr); 26892050f0ccSAndy Adamson encode_nops(&hdr); 26902050f0ccSAndy Adamson } 269118019753SRicardo Labiaga 269218019753SRicardo Labiaga /* 269318019753SRicardo Labiaga * a RECLAIM_COMPLETE request 269418019753SRicardo Labiaga */ 26959f06c719SChuck Lever static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, 26969f06c719SChuck Lever struct xdr_stream *xdr, 269718019753SRicardo Labiaga struct nfs41_reclaim_complete_args *args) 269818019753SRicardo Labiaga { 269918019753SRicardo Labiaga struct compound_hdr hdr = { 270018019753SRicardo Labiaga .minorversion = nfs4_xdr_minorversion(&args->seq_args) 270118019753SRicardo Labiaga }; 270218019753SRicardo Labiaga 27039f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27049f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 27059f06c719SChuck Lever encode_reclaim_complete(xdr, args, &hdr); 270618019753SRicardo Labiaga encode_nops(&hdr); 270718019753SRicardo Labiaga } 270818019753SRicardo Labiaga 2709b1f69b75SAndy Adamson /* 2710b1f69b75SAndy Adamson * Encode GETDEVICEINFO request 2711b1f69b75SAndy Adamson */ 27129f06c719SChuck Lever static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, 27139f06c719SChuck Lever struct xdr_stream *xdr, 2714b1f69b75SAndy Adamson struct nfs4_getdeviceinfo_args *args) 2715b1f69b75SAndy Adamson { 2716b1f69b75SAndy Adamson struct compound_hdr hdr = { 2717b1f69b75SAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2718b1f69b75SAndy Adamson }; 2719b1f69b75SAndy Adamson 27209f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27219f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 27229f06c719SChuck Lever encode_getdeviceinfo(xdr, args, &hdr); 2723b1f69b75SAndy Adamson 2724b1f69b75SAndy Adamson /* set up reply kvec. Subtract notification bitmap max size (2) 2725b1f69b75SAndy Adamson * so that notification bitmap is put in xdr_buf tail */ 2726b1f69b75SAndy Adamson xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2, 2727b1f69b75SAndy Adamson args->pdev->pages, args->pdev->pgbase, 2728b1f69b75SAndy Adamson args->pdev->pglen); 2729b1f69b75SAndy Adamson 2730b1f69b75SAndy Adamson encode_nops(&hdr); 2731b1f69b75SAndy Adamson } 2732b1f69b75SAndy Adamson 2733b1f69b75SAndy Adamson /* 2734b1f69b75SAndy Adamson * Encode LAYOUTGET request 2735b1f69b75SAndy Adamson */ 27369f06c719SChuck Lever static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, 27379f06c719SChuck Lever struct xdr_stream *xdr, 2738b1f69b75SAndy Adamson struct nfs4_layoutget_args *args) 2739b1f69b75SAndy Adamson { 2740b1f69b75SAndy Adamson struct compound_hdr hdr = { 2741b1f69b75SAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2742b1f69b75SAndy Adamson }; 2743b1f69b75SAndy Adamson 27449f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 27459f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 27469f06c719SChuck Lever encode_putfh(xdr, NFS_FH(args->inode), &hdr); 27479f06c719SChuck Lever encode_layoutget(xdr, args, &hdr); 274835124a09SWeston Andros Adamson 274935124a09SWeston Andros Adamson xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, 275035124a09SWeston Andros Adamson args->layout.pages, 0, args->layout.pglen); 275135124a09SWeston Andros Adamson 2752b1f69b75SAndy Adamson encode_nops(&hdr); 2753b1f69b75SAndy Adamson } 2754863a3c6cSAndy Adamson 2755863a3c6cSAndy Adamson /* 2756863a3c6cSAndy Adamson * Encode LAYOUTCOMMIT request 2757863a3c6cSAndy Adamson */ 2758cbe82603SBenny Halevy static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, 2759863a3c6cSAndy Adamson struct xdr_stream *xdr, 2760863a3c6cSAndy Adamson struct nfs4_layoutcommit_args *args) 2761863a3c6cSAndy Adamson { 2762ac7db726SBenny Halevy struct nfs4_layoutcommit_data *data = 2763ac7db726SBenny Halevy container_of(args, struct nfs4_layoutcommit_data, args); 2764863a3c6cSAndy Adamson struct compound_hdr hdr = { 2765863a3c6cSAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2766863a3c6cSAndy Adamson }; 2767863a3c6cSAndy Adamson 2768863a3c6cSAndy Adamson encode_compound_hdr(xdr, req, &hdr); 2769863a3c6cSAndy Adamson encode_sequence(xdr, &args->seq_args, &hdr); 2770863a3c6cSAndy Adamson encode_putfh(xdr, NFS_FH(args->inode), &hdr); 2771ac7db726SBenny Halevy encode_layoutcommit(xdr, data->args.inode, args, &hdr); 2772863a3c6cSAndy Adamson encode_getfattr(xdr, args->bitmask, &hdr); 2773863a3c6cSAndy Adamson encode_nops(&hdr); 2774cbe82603SBenny Halevy } 2775cbe82603SBenny Halevy 2776cbe82603SBenny Halevy /* 2777cbe82603SBenny Halevy * Encode LAYOUTRETURN request 2778cbe82603SBenny Halevy */ 2779cbe82603SBenny Halevy static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req, 2780cbe82603SBenny Halevy struct xdr_stream *xdr, 2781cbe82603SBenny Halevy struct nfs4_layoutreturn_args *args) 2782cbe82603SBenny Halevy { 2783cbe82603SBenny Halevy struct compound_hdr hdr = { 2784cbe82603SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2785cbe82603SBenny Halevy }; 2786cbe82603SBenny Halevy 2787cbe82603SBenny Halevy encode_compound_hdr(xdr, req, &hdr); 2788cbe82603SBenny Halevy encode_sequence(xdr, &args->seq_args, &hdr); 2789cbe82603SBenny Halevy encode_putfh(xdr, NFS_FH(args->inode), &hdr); 2790cbe82603SBenny Halevy encode_layoutreturn(xdr, args, &hdr); 2791cbe82603SBenny Halevy encode_nops(&hdr); 2792863a3c6cSAndy Adamson } 279399fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 279499fe60d0SBenny Halevy 2795686841b3SBenny Halevy static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) 2796686841b3SBenny Halevy { 2797686841b3SBenny Halevy dprintk("nfs: %s: prematurely hit end of receive buffer. " 2798686841b3SBenny Halevy "Remaining buffer length is %tu words.\n", 2799686841b3SBenny Halevy func, xdr->end - xdr->p); 2800686841b3SBenny Halevy } 28011da177e4SLinus Torvalds 2802683b57b4STrond Myklebust static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) 28031da177e4SLinus Torvalds { 28048687b63aSAl Viro __be32 *p; 28051da177e4SLinus Torvalds 2806c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2807c0eae66eSBenny Halevy if (unlikely(!p)) 2808c0eae66eSBenny Halevy goto out_overflow; 2809cccddf4fSBenny Halevy *len = be32_to_cpup(p); 2810c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, *len); 2811c0eae66eSBenny Halevy if (unlikely(!p)) 2812c0eae66eSBenny Halevy goto out_overflow; 28131da177e4SLinus Torvalds *string = (char *)p; 28141da177e4SLinus Torvalds return 0; 2815c0eae66eSBenny Halevy out_overflow: 2816c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2817c0eae66eSBenny Halevy return -EIO; 28181da177e4SLinus Torvalds } 28191da177e4SLinus Torvalds 28201da177e4SLinus Torvalds static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) 28211da177e4SLinus Torvalds { 28228687b63aSAl Viro __be32 *p; 28231da177e4SLinus Torvalds 2824c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 2825c0eae66eSBenny Halevy if (unlikely(!p)) 2826c0eae66eSBenny Halevy goto out_overflow; 28276f723f77SBenny Halevy hdr->status = be32_to_cpup(p++); 2828cccddf4fSBenny Halevy hdr->taglen = be32_to_cpup(p); 28291da177e4SLinus Torvalds 2830c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, hdr->taglen + 4); 2831c0eae66eSBenny Halevy if (unlikely(!p)) 2832c0eae66eSBenny Halevy goto out_overflow; 28331da177e4SLinus Torvalds hdr->tag = (char *)p; 28341da177e4SLinus Torvalds p += XDR_QUADLEN(hdr->taglen); 2835cccddf4fSBenny Halevy hdr->nops = be32_to_cpup(p); 2836aadf6152SBenny Halevy if (unlikely(hdr->nops < 1)) 2837aadf6152SBenny Halevy return nfs4_stat_to_errno(hdr->status); 28381da177e4SLinus Torvalds return 0; 2839c0eae66eSBenny Halevy out_overflow: 2840c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2841c0eae66eSBenny Halevy return -EIO; 28421da177e4SLinus Torvalds } 28431da177e4SLinus Torvalds 28441da177e4SLinus Torvalds static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) 28451da177e4SLinus Torvalds { 28468687b63aSAl Viro __be32 *p; 28471da177e4SLinus Torvalds uint32_t opnum; 28481da177e4SLinus Torvalds int32_t nfserr; 28491da177e4SLinus Torvalds 2850c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 2851c0eae66eSBenny Halevy if (unlikely(!p)) 2852c0eae66eSBenny Halevy goto out_overflow; 28536f723f77SBenny Halevy opnum = be32_to_cpup(p++); 28541da177e4SLinus Torvalds if (opnum != expected) { 2855fe82a183SChuck Lever dprintk("nfs: Server returned operation" 28561da177e4SLinus Torvalds " %d but we issued a request for %d\n", 28571da177e4SLinus Torvalds opnum, expected); 28581da177e4SLinus Torvalds return -EIO; 28591da177e4SLinus Torvalds } 2860cccddf4fSBenny Halevy nfserr = be32_to_cpup(p); 28611da177e4SLinus Torvalds if (nfserr != NFS_OK) 2862856dff3dSBenny Halevy return nfs4_stat_to_errno(nfserr); 28631da177e4SLinus Torvalds return 0; 2864c0eae66eSBenny Halevy out_overflow: 2865c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2866c0eae66eSBenny Halevy return -EIO; 28671da177e4SLinus Torvalds } 28681da177e4SLinus Torvalds 28691da177e4SLinus Torvalds /* Dummy routine */ 2870adfa6f98SDavid Howells static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp) 28711da177e4SLinus Torvalds { 28728687b63aSAl Viro __be32 *p; 2873683b57b4STrond Myklebust unsigned int strlen; 28741da177e4SLinus Torvalds char *str; 28751da177e4SLinus Torvalds 2876c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 2877c0eae66eSBenny Halevy if (likely(p)) 28781da177e4SLinus Torvalds return decode_opaque_inline(xdr, &strlen, &str); 2879c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2880c0eae66eSBenny Halevy return -EIO; 28811da177e4SLinus Torvalds } 28821da177e4SLinus Torvalds 28831da177e4SLinus Torvalds static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) 28841da177e4SLinus Torvalds { 28858687b63aSAl Viro uint32_t bmlen; 28868687b63aSAl Viro __be32 *p; 28871da177e4SLinus Torvalds 2888c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2889c0eae66eSBenny Halevy if (unlikely(!p)) 2890c0eae66eSBenny Halevy goto out_overflow; 2891cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 28921da177e4SLinus Torvalds 28931da177e4SLinus Torvalds bitmap[0] = bitmap[1] = 0; 2894c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, (bmlen << 2)); 2895c0eae66eSBenny Halevy if (unlikely(!p)) 2896c0eae66eSBenny Halevy goto out_overflow; 28971da177e4SLinus Torvalds if (bmlen > 0) { 28986f723f77SBenny Halevy bitmap[0] = be32_to_cpup(p++); 28991da177e4SLinus Torvalds if (bmlen > 1) 2900cccddf4fSBenny Halevy bitmap[1] = be32_to_cpup(p); 29011da177e4SLinus Torvalds } 29021da177e4SLinus Torvalds return 0; 2903c0eae66eSBenny Halevy out_overflow: 2904c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2905c0eae66eSBenny Halevy return -EIO; 29061da177e4SLinus Torvalds } 29071da177e4SLinus Torvalds 29088687b63aSAl Viro static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep) 29091da177e4SLinus Torvalds { 29108687b63aSAl Viro __be32 *p; 29111da177e4SLinus Torvalds 2912c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2913c0eae66eSBenny Halevy if (unlikely(!p)) 2914c0eae66eSBenny Halevy goto out_overflow; 2915cccddf4fSBenny Halevy *attrlen = be32_to_cpup(p); 29161da177e4SLinus Torvalds *savep = xdr->p; 29171da177e4SLinus Torvalds return 0; 2918c0eae66eSBenny Halevy out_overflow: 2919c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2920c0eae66eSBenny Halevy return -EIO; 29211da177e4SLinus Torvalds } 29221da177e4SLinus Torvalds 29231da177e4SLinus Torvalds static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask) 29241da177e4SLinus Torvalds { 29251da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) { 29263388bff5SRoman Borisov int ret; 29273388bff5SRoman Borisov ret = decode_attr_bitmap(xdr, bitmask); 29283388bff5SRoman Borisov if (unlikely(ret < 0)) 29293388bff5SRoman Borisov return ret; 29301da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS; 29311da177e4SLinus Torvalds } else 29321da177e4SLinus Torvalds bitmask[0] = bitmask[1] = 0; 293344109241SFred Isaman dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]); 29341da177e4SLinus Torvalds return 0; 29351da177e4SLinus Torvalds } 29361da177e4SLinus Torvalds 29371da177e4SLinus Torvalds static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type) 29381da177e4SLinus Torvalds { 29398687b63aSAl Viro __be32 *p; 2940409924e4STrond Myklebust int ret = 0; 29411da177e4SLinus Torvalds 29421da177e4SLinus Torvalds *type = 0; 29431da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U))) 29441da177e4SLinus Torvalds return -EIO; 29451da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) { 2946c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2947c0eae66eSBenny Halevy if (unlikely(!p)) 2948c0eae66eSBenny Halevy goto out_overflow; 2949cccddf4fSBenny Halevy *type = be32_to_cpup(p); 29501da177e4SLinus Torvalds if (*type < NF4REG || *type > NF4NAMEDATTR) { 29513110ff80SHarvey Harrison dprintk("%s: bad type %d\n", __func__, *type); 29521da177e4SLinus Torvalds return -EIO; 29531da177e4SLinus Torvalds } 29541da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_TYPE; 2955409924e4STrond Myklebust ret = NFS_ATTR_FATTR_TYPE; 29561da177e4SLinus Torvalds } 2957bca79478STrond Myklebust dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]); 2958409924e4STrond Myklebust return ret; 2959c0eae66eSBenny Halevy out_overflow: 2960c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2961c0eae66eSBenny Halevy return -EIO; 29621da177e4SLinus Torvalds } 29631da177e4SLinus Torvalds 29641da177e4SLinus Torvalds static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) 29651da177e4SLinus Torvalds { 29668687b63aSAl Viro __be32 *p; 2967409924e4STrond Myklebust int ret = 0; 29681da177e4SLinus Torvalds 29691da177e4SLinus Torvalds *change = 0; 29701da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U))) 29711da177e4SLinus Torvalds return -EIO; 29721da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) { 2973c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 2974c0eae66eSBenny Halevy if (unlikely(!p)) 2975c0eae66eSBenny Halevy goto out_overflow; 2976cccddf4fSBenny Halevy xdr_decode_hyper(p, change); 29771da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_CHANGE; 2978409924e4STrond Myklebust ret = NFS_ATTR_FATTR_CHANGE; 29791da177e4SLinus Torvalds } 29803110ff80SHarvey Harrison dprintk("%s: change attribute=%Lu\n", __func__, 29811da177e4SLinus Torvalds (unsigned long long)*change); 2982409924e4STrond Myklebust return ret; 2983c0eae66eSBenny Halevy out_overflow: 2984c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2985c0eae66eSBenny Halevy return -EIO; 29861da177e4SLinus Torvalds } 29871da177e4SLinus Torvalds 29881da177e4SLinus Torvalds static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) 29891da177e4SLinus Torvalds { 29908687b63aSAl Viro __be32 *p; 2991409924e4STrond Myklebust int ret = 0; 29921da177e4SLinus Torvalds 29931da177e4SLinus Torvalds *size = 0; 29941da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U))) 29951da177e4SLinus Torvalds return -EIO; 29961da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) { 2997c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 2998c0eae66eSBenny Halevy if (unlikely(!p)) 2999c0eae66eSBenny Halevy goto out_overflow; 3000cccddf4fSBenny Halevy xdr_decode_hyper(p, size); 30011da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SIZE; 3002409924e4STrond Myklebust ret = NFS_ATTR_FATTR_SIZE; 30031da177e4SLinus Torvalds } 30043110ff80SHarvey Harrison dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size); 3005409924e4STrond Myklebust return ret; 3006c0eae66eSBenny Halevy out_overflow: 3007c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3008c0eae66eSBenny Halevy return -EIO; 30091da177e4SLinus Torvalds } 30101da177e4SLinus Torvalds 30111da177e4SLinus Torvalds static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 30121da177e4SLinus Torvalds { 30138687b63aSAl Viro __be32 *p; 30141da177e4SLinus Torvalds 30151da177e4SLinus Torvalds *res = 0; 30161da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U))) 30171da177e4SLinus Torvalds return -EIO; 30181da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) { 3019c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3020c0eae66eSBenny Halevy if (unlikely(!p)) 3021c0eae66eSBenny Halevy goto out_overflow; 3022cccddf4fSBenny Halevy *res = be32_to_cpup(p); 30231da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT; 30241da177e4SLinus Torvalds } 30253110ff80SHarvey Harrison dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true"); 30261da177e4SLinus Torvalds return 0; 3027c0eae66eSBenny Halevy out_overflow: 3028c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3029c0eae66eSBenny Halevy return -EIO; 30301da177e4SLinus Torvalds } 30311da177e4SLinus Torvalds 30321da177e4SLinus Torvalds static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 30331da177e4SLinus Torvalds { 30348687b63aSAl Viro __be32 *p; 30351da177e4SLinus Torvalds 30361da177e4SLinus Torvalds *res = 0; 30371da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U))) 30381da177e4SLinus Torvalds return -EIO; 30391da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) { 3040c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3041c0eae66eSBenny Halevy if (unlikely(!p)) 3042c0eae66eSBenny Halevy goto out_overflow; 3043cccddf4fSBenny Halevy *res = be32_to_cpup(p); 30441da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT; 30451da177e4SLinus Torvalds } 30463110ff80SHarvey Harrison dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true"); 30471da177e4SLinus Torvalds return 0; 3048c0eae66eSBenny Halevy out_overflow: 3049c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3050c0eae66eSBenny Halevy return -EIO; 30511da177e4SLinus Torvalds } 30521da177e4SLinus Torvalds 30538b4bdcf8STrond Myklebust static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) 30541da177e4SLinus Torvalds { 30558687b63aSAl Viro __be32 *p; 3056409924e4STrond Myklebust int ret = 0; 30571da177e4SLinus Torvalds 30581da177e4SLinus Torvalds fsid->major = 0; 30591da177e4SLinus Torvalds fsid->minor = 0; 30601da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U))) 30611da177e4SLinus Torvalds return -EIO; 30621da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FSID)) { 3063c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 16); 3064c0eae66eSBenny Halevy if (unlikely(!p)) 3065c0eae66eSBenny Halevy goto out_overflow; 30663ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &fsid->major); 3067cccddf4fSBenny Halevy xdr_decode_hyper(p, &fsid->minor); 30681da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FSID; 3069409924e4STrond Myklebust ret = NFS_ATTR_FATTR_FSID; 30701da177e4SLinus Torvalds } 30713110ff80SHarvey Harrison dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__, 30721da177e4SLinus Torvalds (unsigned long long)fsid->major, 30731da177e4SLinus Torvalds (unsigned long long)fsid->minor); 3074409924e4STrond Myklebust return ret; 3075c0eae66eSBenny Halevy out_overflow: 3076c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3077c0eae66eSBenny Halevy return -EIO; 30781da177e4SLinus Torvalds } 30791da177e4SLinus Torvalds 30801da177e4SLinus Torvalds static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 30811da177e4SLinus Torvalds { 30828687b63aSAl Viro __be32 *p; 30831da177e4SLinus Torvalds 30841da177e4SLinus Torvalds *res = 60; 30851da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U))) 30861da177e4SLinus Torvalds return -EIO; 30871da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) { 3088c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3089c0eae66eSBenny Halevy if (unlikely(!p)) 3090c0eae66eSBenny Halevy goto out_overflow; 3091cccddf4fSBenny Halevy *res = be32_to_cpup(p); 30921da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME; 30931da177e4SLinus Torvalds } 30943110ff80SHarvey Harrison dprintk("%s: file size=%u\n", __func__, (unsigned int)*res); 30951da177e4SLinus Torvalds return 0; 3096c0eae66eSBenny Halevy out_overflow: 3097c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3098c0eae66eSBenny Halevy return -EIO; 30991da177e4SLinus Torvalds } 31001da177e4SLinus Torvalds 3101ae42c70aSBryan Schumaker static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) 3102ae42c70aSBryan Schumaker { 3103ae42c70aSBryan Schumaker __be32 *p; 3104ae42c70aSBryan Schumaker 3105ae42c70aSBryan Schumaker if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U))) 3106ae42c70aSBryan Schumaker return -EIO; 3107ae42c70aSBryan Schumaker if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) { 3108ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, 4); 3109ae42c70aSBryan Schumaker if (unlikely(!p)) 3110ae42c70aSBryan Schumaker goto out_overflow; 3111ae42c70aSBryan Schumaker bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; 31127ebb9315SBryan Schumaker return -be32_to_cpup(p); 3113ae42c70aSBryan Schumaker } 3114ae42c70aSBryan Schumaker return 0; 3115ae42c70aSBryan Schumaker out_overflow: 3116ae42c70aSBryan Schumaker print_overflow_msg(__func__, xdr); 3117ae42c70aSBryan Schumaker return -EIO; 3118ae42c70aSBryan Schumaker } 3119ae42c70aSBryan Schumaker 3120ae42c70aSBryan Schumaker static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh) 3121ae42c70aSBryan Schumaker { 3122ae42c70aSBryan Schumaker __be32 *p; 3123ae42c70aSBryan Schumaker int len; 3124ae42c70aSBryan Schumaker 31257ad07353STrond Myklebust if (fh != NULL) 3126ae42c70aSBryan Schumaker memset(fh, 0, sizeof(*fh)); 3127ae42c70aSBryan Schumaker 3128ae42c70aSBryan Schumaker if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U))) 3129ae42c70aSBryan Schumaker return -EIO; 3130ae42c70aSBryan Schumaker if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) { 3131ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, 4); 3132ae42c70aSBryan Schumaker if (unlikely(!p)) 3133ae42c70aSBryan Schumaker goto out_overflow; 3134ae42c70aSBryan Schumaker len = be32_to_cpup(p); 3135ae42c70aSBryan Schumaker if (len > NFS4_FHSIZE) 3136ae42c70aSBryan Schumaker return -EIO; 3137ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, len); 3138ae42c70aSBryan Schumaker if (unlikely(!p)) 3139ae42c70aSBryan Schumaker goto out_overflow; 31407ad07353STrond Myklebust if (fh != NULL) { 3141ae42c70aSBryan Schumaker memcpy(fh->data, p, len); 31427ad07353STrond Myklebust fh->size = len; 31437ad07353STrond Myklebust } 3144ae42c70aSBryan Schumaker bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE; 3145ae42c70aSBryan Schumaker } 3146ae42c70aSBryan Schumaker return 0; 3147ae42c70aSBryan Schumaker out_overflow: 3148ae42c70aSBryan Schumaker print_overflow_msg(__func__, xdr); 3149ae42c70aSBryan Schumaker return -EIO; 3150ae42c70aSBryan Schumaker } 3151ae42c70aSBryan Schumaker 31521da177e4SLinus Torvalds static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 31531da177e4SLinus Torvalds { 31548687b63aSAl Viro __be32 *p; 31551da177e4SLinus Torvalds 31561da177e4SLinus Torvalds *res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL; 31571da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U))) 31581da177e4SLinus Torvalds return -EIO; 31591da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { 3160c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3161c0eae66eSBenny Halevy if (unlikely(!p)) 3162c0eae66eSBenny Halevy goto out_overflow; 3163cccddf4fSBenny Halevy *res = be32_to_cpup(p); 31641da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT; 31651da177e4SLinus Torvalds } 31663110ff80SHarvey Harrison dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res); 31671da177e4SLinus Torvalds return 0; 3168c0eae66eSBenny Halevy out_overflow: 3169c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3170c0eae66eSBenny Halevy return -EIO; 31711da177e4SLinus Torvalds } 31721da177e4SLinus Torvalds 31731da177e4SLinus Torvalds static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) 31741da177e4SLinus Torvalds { 31758687b63aSAl Viro __be32 *p; 3176409924e4STrond Myklebust int ret = 0; 31771da177e4SLinus Torvalds 31781da177e4SLinus Torvalds *fileid = 0; 31791da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U))) 31801da177e4SLinus Torvalds return -EIO; 31811da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) { 3182c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3183c0eae66eSBenny Halevy if (unlikely(!p)) 3184c0eae66eSBenny Halevy goto out_overflow; 3185cccddf4fSBenny Halevy xdr_decode_hyper(p, fileid); 31861da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILEID; 3187409924e4STrond Myklebust ret = NFS_ATTR_FATTR_FILEID; 31881da177e4SLinus Torvalds } 31893110ff80SHarvey Harrison dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); 3190409924e4STrond Myklebust return ret; 3191c0eae66eSBenny Halevy out_overflow: 3192c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3193c0eae66eSBenny Halevy return -EIO; 31941da177e4SLinus Torvalds } 31951da177e4SLinus Torvalds 319699baf625SManoj Naik static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) 319799baf625SManoj Naik { 31988687b63aSAl Viro __be32 *p; 3199409924e4STrond Myklebust int ret = 0; 320099baf625SManoj Naik 320199baf625SManoj Naik *fileid = 0; 320299baf625SManoj Naik if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U))) 320399baf625SManoj Naik return -EIO; 320499baf625SManoj Naik if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) { 3205c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3206c0eae66eSBenny Halevy if (unlikely(!p)) 3207c0eae66eSBenny Halevy goto out_overflow; 3208cccddf4fSBenny Halevy xdr_decode_hyper(p, fileid); 320999baf625SManoj Naik bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; 321028331a46STrond Myklebust ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID; 321199baf625SManoj Naik } 32123110ff80SHarvey Harrison dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); 3213409924e4STrond Myklebust return ret; 3214c0eae66eSBenny Halevy out_overflow: 3215c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3216c0eae66eSBenny Halevy return -EIO; 321799baf625SManoj Naik } 321899baf625SManoj Naik 32191da177e4SLinus Torvalds static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 32201da177e4SLinus Torvalds { 32218687b63aSAl Viro __be32 *p; 32221da177e4SLinus Torvalds int status = 0; 32231da177e4SLinus Torvalds 32241da177e4SLinus Torvalds *res = 0; 32251da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U))) 32261da177e4SLinus Torvalds return -EIO; 32271da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) { 3228c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3229c0eae66eSBenny Halevy if (unlikely(!p)) 3230c0eae66eSBenny Halevy goto out_overflow; 3231cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 32321da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL; 32331da177e4SLinus Torvalds } 32343110ff80SHarvey Harrison dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res); 32351da177e4SLinus Torvalds return status; 3236c0eae66eSBenny Halevy out_overflow: 3237c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3238c0eae66eSBenny Halevy return -EIO; 32391da177e4SLinus Torvalds } 32401da177e4SLinus Torvalds 32411da177e4SLinus Torvalds static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 32421da177e4SLinus Torvalds { 32438687b63aSAl Viro __be32 *p; 32441da177e4SLinus Torvalds int status = 0; 32451da177e4SLinus Torvalds 32461da177e4SLinus Torvalds *res = 0; 32471da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U))) 32481da177e4SLinus Torvalds return -EIO; 32491da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) { 3250c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3251c0eae66eSBenny Halevy if (unlikely(!p)) 3252c0eae66eSBenny Halevy goto out_overflow; 3253cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 32541da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_FREE; 32551da177e4SLinus Torvalds } 32563110ff80SHarvey Harrison dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res); 32571da177e4SLinus Torvalds return status; 3258c0eae66eSBenny Halevy out_overflow: 3259c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3260c0eae66eSBenny Halevy return -EIO; 32611da177e4SLinus Torvalds } 32621da177e4SLinus Torvalds 32631da177e4SLinus Torvalds static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 32641da177e4SLinus Torvalds { 32658687b63aSAl Viro __be32 *p; 32661da177e4SLinus Torvalds int status = 0; 32671da177e4SLinus Torvalds 32681da177e4SLinus Torvalds *res = 0; 32691da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U))) 32701da177e4SLinus Torvalds return -EIO; 32711da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) { 3272c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3273c0eae66eSBenny Halevy if (unlikely(!p)) 3274c0eae66eSBenny Halevy goto out_overflow; 3275cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 32761da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL; 32771da177e4SLinus Torvalds } 32783110ff80SHarvey Harrison dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res); 32791da177e4SLinus Torvalds return status; 3280c0eae66eSBenny Halevy out_overflow: 3281c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3282c0eae66eSBenny Halevy return -EIO; 32831da177e4SLinus Torvalds } 32841da177e4SLinus Torvalds 32857aaa0b3bSManoj Naik static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) 32867aaa0b3bSManoj Naik { 3287464ad6b1SChuck Lever u32 n; 32888687b63aSAl Viro __be32 *p; 32897aaa0b3bSManoj Naik int status = 0; 32907aaa0b3bSManoj Naik 3291c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3292c0eae66eSBenny Halevy if (unlikely(!p)) 3293c0eae66eSBenny Halevy goto out_overflow; 3294cccddf4fSBenny Halevy n = be32_to_cpup(p); 329533a43f28SAndy Adamson if (n == 0) 329633a43f28SAndy Adamson goto root_path; 32977aaa0b3bSManoj Naik dprintk("path "); 32987aaa0b3bSManoj Naik path->ncomponents = 0; 32997aaa0b3bSManoj Naik while (path->ncomponents < n) { 33007aaa0b3bSManoj Naik struct nfs4_string *component = &path->components[path->ncomponents]; 33017aaa0b3bSManoj Naik status = decode_opaque_inline(xdr, &component->len, &component->data); 33027aaa0b3bSManoj Naik if (unlikely(status != 0)) 33037aaa0b3bSManoj Naik goto out_eio; 33047aaa0b3bSManoj Naik if (path->ncomponents != n) 33057aaa0b3bSManoj Naik dprintk("/"); 33067aaa0b3bSManoj Naik dprintk("%s", component->data); 33077aaa0b3bSManoj Naik if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS) 33087aaa0b3bSManoj Naik path->ncomponents++; 33097aaa0b3bSManoj Naik else { 33107aaa0b3bSManoj Naik dprintk("cannot parse %d components in path\n", n); 33117aaa0b3bSManoj Naik goto out_eio; 33127aaa0b3bSManoj Naik } 33137aaa0b3bSManoj Naik } 33147aaa0b3bSManoj Naik out: 33157aaa0b3bSManoj Naik dprintk("\n"); 33167aaa0b3bSManoj Naik return status; 331733a43f28SAndy Adamson root_path: 331833a43f28SAndy Adamson /* a root pathname is sent as a zero component4 */ 331933a43f28SAndy Adamson path->ncomponents = 1; 332033a43f28SAndy Adamson path->components[0].len=0; 332133a43f28SAndy Adamson path->components[0].data=NULL; 332233a43f28SAndy Adamson dprintk("path /\n"); 332333a43f28SAndy Adamson goto out; 33247aaa0b3bSManoj Naik out_eio: 33257aaa0b3bSManoj Naik dprintk(" status %d", status); 33267aaa0b3bSManoj Naik status = -EIO; 33277aaa0b3bSManoj Naik goto out; 3328c0eae66eSBenny Halevy out_overflow: 3329c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3330c0eae66eSBenny Halevy return -EIO; 33317aaa0b3bSManoj Naik } 33327aaa0b3bSManoj Naik 33337aaa0b3bSManoj Naik static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) 3334683b57b4STrond Myklebust { 3335683b57b4STrond Myklebust int n; 33368687b63aSAl Viro __be32 *p; 3337683b57b4STrond Myklebust int status = -EIO; 3338683b57b4STrond Myklebust 3339683b57b4STrond Myklebust if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U))) 3340683b57b4STrond Myklebust goto out; 3341683b57b4STrond Myklebust status = 0; 3342683b57b4STrond Myklebust if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) 3343683b57b4STrond Myklebust goto out; 33443110ff80SHarvey Harrison dprintk("%s: fsroot ", __func__); 33457aaa0b3bSManoj Naik status = decode_pathname(xdr, &res->fs_path); 3346683b57b4STrond Myklebust if (unlikely(status != 0)) 3347683b57b4STrond Myklebust goto out; 3348c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3349c0eae66eSBenny Halevy if (unlikely(!p)) 3350c0eae66eSBenny Halevy goto out_overflow; 3351cccddf4fSBenny Halevy n = be32_to_cpup(p); 3352683b57b4STrond Myklebust if (n <= 0) 3353683b57b4STrond Myklebust goto out_eio; 3354683b57b4STrond Myklebust res->nlocations = 0; 3355683b57b4STrond Myklebust while (res->nlocations < n) { 3356464ad6b1SChuck Lever u32 m; 33577aaa0b3bSManoj Naik struct nfs4_fs_location *loc = &res->locations[res->nlocations]; 3358683b57b4STrond Myklebust 3359c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3360c0eae66eSBenny Halevy if (unlikely(!p)) 3361c0eae66eSBenny Halevy goto out_overflow; 3362cccddf4fSBenny Halevy m = be32_to_cpup(p); 33637aaa0b3bSManoj Naik 33647aaa0b3bSManoj Naik loc->nservers = 0; 33653110ff80SHarvey Harrison dprintk("%s: servers ", __func__); 33667aaa0b3bSManoj Naik while (loc->nservers < m) { 33677aaa0b3bSManoj Naik struct nfs4_string *server = &loc->servers[loc->nservers]; 33687aaa0b3bSManoj Naik status = decode_opaque_inline(xdr, &server->len, &server->data); 3369683b57b4STrond Myklebust if (unlikely(status != 0)) 3370683b57b4STrond Myklebust goto out_eio; 33717aaa0b3bSManoj Naik dprintk("%s ", server->data); 33727aaa0b3bSManoj Naik if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS) 33737aaa0b3bSManoj Naik loc->nservers++; 33747aaa0b3bSManoj Naik else { 3375464ad6b1SChuck Lever unsigned int i; 3376464ad6b1SChuck Lever dprintk("%s: using first %u of %u servers " 3377464ad6b1SChuck Lever "returned for location %u\n", 33783110ff80SHarvey Harrison __func__, 3379464ad6b1SChuck Lever NFS4_FS_LOCATION_MAXSERVERS, 3380464ad6b1SChuck Lever m, res->nlocations); 33817aaa0b3bSManoj Naik for (i = loc->nservers; i < m; i++) { 33822e42c3e2STrond Myklebust unsigned int len; 33837aaa0b3bSManoj Naik char *data; 33847aaa0b3bSManoj Naik status = decode_opaque_inline(xdr, &len, &data); 3385683b57b4STrond Myklebust if (unlikely(status != 0)) 3386683b57b4STrond Myklebust goto out_eio; 33877aaa0b3bSManoj Naik } 33887aaa0b3bSManoj Naik } 33897aaa0b3bSManoj Naik } 33907aaa0b3bSManoj Naik status = decode_pathname(xdr, &loc->rootpath); 33917aaa0b3bSManoj Naik if (unlikely(status != 0)) 33927aaa0b3bSManoj Naik goto out_eio; 33937aaa0b3bSManoj Naik if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES) 3394683b57b4STrond Myklebust res->nlocations++; 3395683b57b4STrond Myklebust } 3396409924e4STrond Myklebust if (res->nlocations != 0) 3397409924e4STrond Myklebust status = NFS_ATTR_FATTR_V4_REFERRAL; 3398683b57b4STrond Myklebust out: 33993110ff80SHarvey Harrison dprintk("%s: fs_locations done, error = %d\n", __func__, status); 3400683b57b4STrond Myklebust return status; 3401c0eae66eSBenny Halevy out_overflow: 3402c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3403683b57b4STrond Myklebust out_eio: 3404683b57b4STrond Myklebust status = -EIO; 3405683b57b4STrond Myklebust goto out; 3406683b57b4STrond Myklebust } 3407683b57b4STrond Myklebust 34081da177e4SLinus Torvalds static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 34091da177e4SLinus Torvalds { 34108687b63aSAl Viro __be32 *p; 34111da177e4SLinus Torvalds int status = 0; 34121da177e4SLinus Torvalds 34131da177e4SLinus Torvalds *res = 0; 34141da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U))) 34151da177e4SLinus Torvalds return -EIO; 34161da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) { 3417c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3418c0eae66eSBenny Halevy if (unlikely(!p)) 3419c0eae66eSBenny Halevy goto out_overflow; 3420cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 34211da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE; 34221da177e4SLinus Torvalds } 34233110ff80SHarvey Harrison dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res); 34241da177e4SLinus Torvalds return status; 3425c0eae66eSBenny Halevy out_overflow: 3426c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3427c0eae66eSBenny Halevy return -EIO; 34281da177e4SLinus Torvalds } 34291da177e4SLinus Torvalds 34301da177e4SLinus Torvalds static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink) 34311da177e4SLinus Torvalds { 34328687b63aSAl Viro __be32 *p; 34331da177e4SLinus Torvalds int status = 0; 34341da177e4SLinus Torvalds 34351da177e4SLinus Torvalds *maxlink = 1; 34361da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U))) 34371da177e4SLinus Torvalds return -EIO; 34381da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) { 3439c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3440c0eae66eSBenny Halevy if (unlikely(!p)) 3441c0eae66eSBenny Halevy goto out_overflow; 3442cccddf4fSBenny Halevy *maxlink = be32_to_cpup(p); 34431da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXLINK; 34441da177e4SLinus Torvalds } 34453110ff80SHarvey Harrison dprintk("%s: maxlink=%u\n", __func__, *maxlink); 34461da177e4SLinus Torvalds return status; 3447c0eae66eSBenny Halevy out_overflow: 3448c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3449c0eae66eSBenny Halevy return -EIO; 34501da177e4SLinus Torvalds } 34511da177e4SLinus Torvalds 34521da177e4SLinus Torvalds static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname) 34531da177e4SLinus Torvalds { 34548687b63aSAl Viro __be32 *p; 34551da177e4SLinus Torvalds int status = 0; 34561da177e4SLinus Torvalds 34571da177e4SLinus Torvalds *maxname = 1024; 34581da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U))) 34591da177e4SLinus Torvalds return -EIO; 34601da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) { 3461c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3462c0eae66eSBenny Halevy if (unlikely(!p)) 3463c0eae66eSBenny Halevy goto out_overflow; 3464cccddf4fSBenny Halevy *maxname = be32_to_cpup(p); 34651da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXNAME; 34661da177e4SLinus Torvalds } 34673110ff80SHarvey Harrison dprintk("%s: maxname=%u\n", __func__, *maxname); 34681da177e4SLinus Torvalds return status; 3469c0eae66eSBenny Halevy out_overflow: 3470c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3471c0eae66eSBenny Halevy return -EIO; 34721da177e4SLinus Torvalds } 34731da177e4SLinus Torvalds 34741da177e4SLinus Torvalds static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 34751da177e4SLinus Torvalds { 34768687b63aSAl Viro __be32 *p; 34771da177e4SLinus Torvalds int status = 0; 34781da177e4SLinus Torvalds 34791da177e4SLinus Torvalds *res = 1024; 34801da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U))) 34811da177e4SLinus Torvalds return -EIO; 34821da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) { 34831da177e4SLinus Torvalds uint64_t maxread; 3484c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3485c0eae66eSBenny Halevy if (unlikely(!p)) 3486c0eae66eSBenny Halevy goto out_overflow; 3487cccddf4fSBenny Halevy xdr_decode_hyper(p, &maxread); 34881da177e4SLinus Torvalds if (maxread > 0x7FFFFFFF) 34891da177e4SLinus Torvalds maxread = 0x7FFFFFFF; 34901da177e4SLinus Torvalds *res = (uint32_t)maxread; 34911da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXREAD; 34921da177e4SLinus Torvalds } 34933110ff80SHarvey Harrison dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res); 34941da177e4SLinus Torvalds return status; 3495c0eae66eSBenny Halevy out_overflow: 3496c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3497c0eae66eSBenny Halevy return -EIO; 34981da177e4SLinus Torvalds } 34991da177e4SLinus Torvalds 35001da177e4SLinus Torvalds static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 35011da177e4SLinus Torvalds { 35028687b63aSAl Viro __be32 *p; 35031da177e4SLinus Torvalds int status = 0; 35041da177e4SLinus Torvalds 35051da177e4SLinus Torvalds *res = 1024; 35061da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U))) 35071da177e4SLinus Torvalds return -EIO; 35081da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) { 35091da177e4SLinus Torvalds uint64_t maxwrite; 3510c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3511c0eae66eSBenny Halevy if (unlikely(!p)) 3512c0eae66eSBenny Halevy goto out_overflow; 3513cccddf4fSBenny Halevy xdr_decode_hyper(p, &maxwrite); 35141da177e4SLinus Torvalds if (maxwrite > 0x7FFFFFFF) 35151da177e4SLinus Torvalds maxwrite = 0x7FFFFFFF; 35161da177e4SLinus Torvalds *res = (uint32_t)maxwrite; 35171da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXWRITE; 35181da177e4SLinus Torvalds } 35193110ff80SHarvey Harrison dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res); 35201da177e4SLinus Torvalds return status; 3521c0eae66eSBenny Halevy out_overflow: 3522c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3523c0eae66eSBenny Halevy return -EIO; 35241da177e4SLinus Torvalds } 35251da177e4SLinus Torvalds 3526bca79478STrond Myklebust static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode) 35271da177e4SLinus Torvalds { 3528bca79478STrond Myklebust uint32_t tmp; 35298687b63aSAl Viro __be32 *p; 3530409924e4STrond Myklebust int ret = 0; 35311da177e4SLinus Torvalds 35321da177e4SLinus Torvalds *mode = 0; 35331da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U))) 35341da177e4SLinus Torvalds return -EIO; 35351da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_MODE)) { 3536c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3537c0eae66eSBenny Halevy if (unlikely(!p)) 3538c0eae66eSBenny Halevy goto out_overflow; 3539cccddf4fSBenny Halevy tmp = be32_to_cpup(p); 3540bca79478STrond Myklebust *mode = tmp & ~S_IFMT; 35411da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_MODE; 3542409924e4STrond Myklebust ret = NFS_ATTR_FATTR_MODE; 35431da177e4SLinus Torvalds } 35443110ff80SHarvey Harrison dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode); 3545409924e4STrond Myklebust return ret; 3546c0eae66eSBenny Halevy out_overflow: 3547c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3548c0eae66eSBenny Halevy return -EIO; 35491da177e4SLinus Torvalds } 35501da177e4SLinus Torvalds 35511da177e4SLinus Torvalds static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) 35521da177e4SLinus Torvalds { 35538687b63aSAl Viro __be32 *p; 3554409924e4STrond Myklebust int ret = 0; 35551da177e4SLinus Torvalds 35561da177e4SLinus Torvalds *nlink = 1; 35571da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U))) 35581da177e4SLinus Torvalds return -EIO; 35591da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) { 3560c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3561c0eae66eSBenny Halevy if (unlikely(!p)) 3562c0eae66eSBenny Halevy goto out_overflow; 3563cccddf4fSBenny Halevy *nlink = be32_to_cpup(p); 35641da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_NUMLINKS; 3565409924e4STrond Myklebust ret = NFS_ATTR_FATTR_NLINK; 35661da177e4SLinus Torvalds } 35673110ff80SHarvey Harrison dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink); 3568409924e4STrond Myklebust return ret; 3569c0eae66eSBenny Halevy out_overflow: 3570c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3571c0eae66eSBenny Halevy return -EIO; 35721da177e4SLinus Torvalds } 35731da177e4SLinus Torvalds 357480e52aceSTrond Myklebust static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, 3575e4fd72a1STrond Myklebust const struct nfs_server *server, uint32_t *uid, int may_sleep) 35761da177e4SLinus Torvalds { 35778687b63aSAl Viro uint32_t len; 35788687b63aSAl Viro __be32 *p; 3579409924e4STrond Myklebust int ret = 0; 35801da177e4SLinus Torvalds 35811da177e4SLinus Torvalds *uid = -2; 35821da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U))) 35831da177e4SLinus Torvalds return -EIO; 35841da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) { 3585c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3586c0eae66eSBenny Halevy if (unlikely(!p)) 3587c0eae66eSBenny Halevy goto out_overflow; 3588cccddf4fSBenny Halevy len = be32_to_cpup(p); 3589c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 3590c0eae66eSBenny Halevy if (unlikely(!p)) 3591c0eae66eSBenny Halevy goto out_overflow; 359280e52aceSTrond Myklebust if (!may_sleep) { 359380e52aceSTrond Myklebust /* do nothing */ 359480e52aceSTrond Myklebust } else if (len < XDR_MAX_NETOBJ) { 3595e4fd72a1STrond Myklebust if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0) 3596409924e4STrond Myklebust ret = NFS_ATTR_FATTR_OWNER; 3597409924e4STrond Myklebust else 35981da177e4SLinus Torvalds dprintk("%s: nfs_map_name_to_uid failed!\n", 35993110ff80SHarvey Harrison __func__); 36001da177e4SLinus Torvalds } else 3601fe82a183SChuck Lever dprintk("%s: name too long (%u)!\n", 36023110ff80SHarvey Harrison __func__, len); 36031da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_OWNER; 36041da177e4SLinus Torvalds } 36053110ff80SHarvey Harrison dprintk("%s: uid=%d\n", __func__, (int)*uid); 3606409924e4STrond Myklebust return ret; 3607c0eae66eSBenny Halevy out_overflow: 3608c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3609c0eae66eSBenny Halevy return -EIO; 36101da177e4SLinus Torvalds } 36111da177e4SLinus Torvalds 361280e52aceSTrond Myklebust static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, 3613e4fd72a1STrond Myklebust const struct nfs_server *server, uint32_t *gid, int may_sleep) 36141da177e4SLinus Torvalds { 36158687b63aSAl Viro uint32_t len; 36168687b63aSAl Viro __be32 *p; 3617409924e4STrond Myklebust int ret = 0; 36181da177e4SLinus Torvalds 36191da177e4SLinus Torvalds *gid = -2; 36201da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U))) 36211da177e4SLinus Torvalds return -EIO; 36221da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) { 3623c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3624c0eae66eSBenny Halevy if (unlikely(!p)) 3625c0eae66eSBenny Halevy goto out_overflow; 3626cccddf4fSBenny Halevy len = be32_to_cpup(p); 3627c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 3628c0eae66eSBenny Halevy if (unlikely(!p)) 3629c0eae66eSBenny Halevy goto out_overflow; 363080e52aceSTrond Myklebust if (!may_sleep) { 363180e52aceSTrond Myklebust /* do nothing */ 363280e52aceSTrond Myklebust } else if (len < XDR_MAX_NETOBJ) { 3633e4fd72a1STrond Myklebust if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0) 3634409924e4STrond Myklebust ret = NFS_ATTR_FATTR_GROUP; 3635409924e4STrond Myklebust else 36361da177e4SLinus Torvalds dprintk("%s: nfs_map_group_to_gid failed!\n", 36373110ff80SHarvey Harrison __func__); 36381da177e4SLinus Torvalds } else 3639fe82a183SChuck Lever dprintk("%s: name too long (%u)!\n", 36403110ff80SHarvey Harrison __func__, len); 36411da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP; 36421da177e4SLinus Torvalds } 36433110ff80SHarvey Harrison dprintk("%s: gid=%d\n", __func__, (int)*gid); 3644409924e4STrond Myklebust return ret; 3645c0eae66eSBenny Halevy out_overflow: 3646c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3647c0eae66eSBenny Halevy return -EIO; 36481da177e4SLinus Torvalds } 36491da177e4SLinus Torvalds 36501da177e4SLinus Torvalds static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) 36511da177e4SLinus Torvalds { 36528687b63aSAl Viro uint32_t major = 0, minor = 0; 36538687b63aSAl Viro __be32 *p; 3654409924e4STrond Myklebust int ret = 0; 36551da177e4SLinus Torvalds 36561da177e4SLinus Torvalds *rdev = MKDEV(0,0); 36571da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U))) 36581da177e4SLinus Torvalds return -EIO; 36591da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) { 36601da177e4SLinus Torvalds dev_t tmp; 36611da177e4SLinus Torvalds 3662c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3663c0eae66eSBenny Halevy if (unlikely(!p)) 3664c0eae66eSBenny Halevy goto out_overflow; 36656f723f77SBenny Halevy major = be32_to_cpup(p++); 3666cccddf4fSBenny Halevy minor = be32_to_cpup(p); 36671da177e4SLinus Torvalds tmp = MKDEV(major, minor); 36681da177e4SLinus Torvalds if (MAJOR(tmp) == major && MINOR(tmp) == minor) 36691da177e4SLinus Torvalds *rdev = tmp; 36701da177e4SLinus Torvalds bitmap[1] &= ~ FATTR4_WORD1_RAWDEV; 3671409924e4STrond Myklebust ret = NFS_ATTR_FATTR_RDEV; 36721da177e4SLinus Torvalds } 36733110ff80SHarvey Harrison dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor); 3674409924e4STrond Myklebust return ret; 3675c0eae66eSBenny Halevy out_overflow: 3676c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3677c0eae66eSBenny Halevy return -EIO; 36781da177e4SLinus Torvalds } 36791da177e4SLinus Torvalds 36801da177e4SLinus Torvalds static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 36811da177e4SLinus Torvalds { 36828687b63aSAl Viro __be32 *p; 36831da177e4SLinus Torvalds int status = 0; 36841da177e4SLinus Torvalds 36851da177e4SLinus Torvalds *res = 0; 36861da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U))) 36871da177e4SLinus Torvalds return -EIO; 36881da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) { 3689c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3690c0eae66eSBenny Halevy if (unlikely(!p)) 3691c0eae66eSBenny Halevy goto out_overflow; 3692cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 36931da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL; 36941da177e4SLinus Torvalds } 36953110ff80SHarvey Harrison dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res); 36961da177e4SLinus Torvalds return status; 3697c0eae66eSBenny Halevy out_overflow: 3698c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3699c0eae66eSBenny Halevy return -EIO; 37001da177e4SLinus Torvalds } 37011da177e4SLinus Torvalds 37021da177e4SLinus Torvalds static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 37031da177e4SLinus Torvalds { 37048687b63aSAl Viro __be32 *p; 37051da177e4SLinus Torvalds int status = 0; 37061da177e4SLinus Torvalds 37071da177e4SLinus Torvalds *res = 0; 37081da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U))) 37091da177e4SLinus Torvalds return -EIO; 37101da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) { 3711c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3712c0eae66eSBenny Halevy if (unlikely(!p)) 3713c0eae66eSBenny Halevy goto out_overflow; 3714cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 37151da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE; 37161da177e4SLinus Torvalds } 37173110ff80SHarvey Harrison dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res); 37181da177e4SLinus Torvalds return status; 3719c0eae66eSBenny Halevy out_overflow: 3720c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3721c0eae66eSBenny Halevy return -EIO; 37221da177e4SLinus Torvalds } 37231da177e4SLinus Torvalds 37241da177e4SLinus Torvalds static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 37251da177e4SLinus Torvalds { 37268687b63aSAl Viro __be32 *p; 37271da177e4SLinus Torvalds int status = 0; 37281da177e4SLinus Torvalds 37291da177e4SLinus Torvalds *res = 0; 37301da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U))) 37311da177e4SLinus Torvalds return -EIO; 37321da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) { 3733c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3734c0eae66eSBenny Halevy if (unlikely(!p)) 3735c0eae66eSBenny Halevy goto out_overflow; 3736cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 37371da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL; 37381da177e4SLinus Torvalds } 37393110ff80SHarvey Harrison dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res); 37401da177e4SLinus Torvalds return status; 3741c0eae66eSBenny Halevy out_overflow: 3742c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3743c0eae66eSBenny Halevy return -EIO; 37441da177e4SLinus Torvalds } 37451da177e4SLinus Torvalds 37461da177e4SLinus Torvalds static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) 37471da177e4SLinus Torvalds { 37488687b63aSAl Viro __be32 *p; 3749409924e4STrond Myklebust int ret = 0; 37501da177e4SLinus Torvalds 37511da177e4SLinus Torvalds *used = 0; 37521da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U))) 37531da177e4SLinus Torvalds return -EIO; 37541da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) { 3755c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3756c0eae66eSBenny Halevy if (unlikely(!p)) 3757c0eae66eSBenny Halevy goto out_overflow; 3758cccddf4fSBenny Halevy xdr_decode_hyper(p, used); 37591da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_USED; 3760409924e4STrond Myklebust ret = NFS_ATTR_FATTR_SPACE_USED; 37611da177e4SLinus Torvalds } 37623110ff80SHarvey Harrison dprintk("%s: space used=%Lu\n", __func__, 37631da177e4SLinus Torvalds (unsigned long long)*used); 3764409924e4STrond Myklebust return ret; 3765c0eae66eSBenny Halevy out_overflow: 3766c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3767c0eae66eSBenny Halevy return -EIO; 37681da177e4SLinus Torvalds } 37691da177e4SLinus Torvalds 37701da177e4SLinus Torvalds static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time) 37711da177e4SLinus Torvalds { 37728687b63aSAl Viro __be32 *p; 37731da177e4SLinus Torvalds uint64_t sec; 37741da177e4SLinus Torvalds uint32_t nsec; 37751da177e4SLinus Torvalds 3776c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 3777c0eae66eSBenny Halevy if (unlikely(!p)) 3778c0eae66eSBenny Halevy goto out_overflow; 37793ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &sec); 3780cccddf4fSBenny Halevy nsec = be32_to_cpup(p); 37811da177e4SLinus Torvalds time->tv_sec = (time_t)sec; 37821da177e4SLinus Torvalds time->tv_nsec = (long)nsec; 37831da177e4SLinus Torvalds return 0; 3784c0eae66eSBenny Halevy out_overflow: 3785c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3786c0eae66eSBenny Halevy return -EIO; 37871da177e4SLinus Torvalds } 37881da177e4SLinus Torvalds 37891da177e4SLinus Torvalds static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) 37901da177e4SLinus Torvalds { 37911da177e4SLinus Torvalds int status = 0; 37921da177e4SLinus Torvalds 37931da177e4SLinus Torvalds time->tv_sec = 0; 37941da177e4SLinus Torvalds time->tv_nsec = 0; 37951da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U))) 37961da177e4SLinus Torvalds return -EIO; 37971da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) { 37981da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 3799409924e4STrond Myklebust if (status == 0) 3800409924e4STrond Myklebust status = NFS_ATTR_FATTR_ATIME; 38011da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS; 38021da177e4SLinus Torvalds } 38033110ff80SHarvey Harrison dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec); 38041da177e4SLinus Torvalds return status; 38051da177e4SLinus Torvalds } 38061da177e4SLinus Torvalds 38071da177e4SLinus Torvalds static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) 38081da177e4SLinus Torvalds { 38091da177e4SLinus Torvalds int status = 0; 38101da177e4SLinus Torvalds 38111da177e4SLinus Torvalds time->tv_sec = 0; 38121da177e4SLinus Torvalds time->tv_nsec = 0; 38131da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U))) 38141da177e4SLinus Torvalds return -EIO; 38151da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) { 38161da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 3817409924e4STrond Myklebust if (status == 0) 3818409924e4STrond Myklebust status = NFS_ATTR_FATTR_CTIME; 38191da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA; 38201da177e4SLinus Torvalds } 38213110ff80SHarvey Harrison dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec); 38221da177e4SLinus Torvalds return status; 38231da177e4SLinus Torvalds } 38241da177e4SLinus Torvalds 382555b6e774SRicardo Labiaga static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, 382655b6e774SRicardo Labiaga struct timespec *time) 382755b6e774SRicardo Labiaga { 382855b6e774SRicardo Labiaga int status = 0; 382955b6e774SRicardo Labiaga 383055b6e774SRicardo Labiaga time->tv_sec = 0; 383155b6e774SRicardo Labiaga time->tv_nsec = 0; 383255b6e774SRicardo Labiaga if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U))) 383355b6e774SRicardo Labiaga return -EIO; 383455b6e774SRicardo Labiaga if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) { 383555b6e774SRicardo Labiaga status = decode_attr_time(xdr, time); 383655b6e774SRicardo Labiaga bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA; 383755b6e774SRicardo Labiaga } 383855b6e774SRicardo Labiaga dprintk("%s: time_delta=%ld %ld\n", __func__, (long)time->tv_sec, 383955b6e774SRicardo Labiaga (long)time->tv_nsec); 384055b6e774SRicardo Labiaga return status; 384155b6e774SRicardo Labiaga } 384255b6e774SRicardo Labiaga 38431da177e4SLinus Torvalds static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) 38441da177e4SLinus Torvalds { 38451da177e4SLinus Torvalds int status = 0; 38461da177e4SLinus Torvalds 38471da177e4SLinus Torvalds time->tv_sec = 0; 38481da177e4SLinus Torvalds time->tv_nsec = 0; 38491da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U))) 38501da177e4SLinus Torvalds return -EIO; 38511da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) { 38521da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 3853409924e4STrond Myklebust if (status == 0) 3854409924e4STrond Myklebust status = NFS_ATTR_FATTR_MTIME; 38551da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY; 38561da177e4SLinus Torvalds } 38573110ff80SHarvey Harrison dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec); 38581da177e4SLinus Torvalds return status; 38591da177e4SLinus Torvalds } 38601da177e4SLinus Torvalds 38618687b63aSAl Viro static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen) 38621da177e4SLinus Torvalds { 38631da177e4SLinus Torvalds unsigned int attrwords = XDR_QUADLEN(attrlen); 38641da177e4SLinus Torvalds unsigned int nwords = xdr->p - savep; 38651da177e4SLinus Torvalds 38661da177e4SLinus Torvalds if (unlikely(attrwords != nwords)) { 3867fe82a183SChuck Lever dprintk("%s: server returned incorrect attribute length: " 3868fe82a183SChuck Lever "%u %c %u\n", 38693110ff80SHarvey Harrison __func__, 38701da177e4SLinus Torvalds attrwords << 2, 38711da177e4SLinus Torvalds (attrwords < nwords) ? '<' : '>', 38721da177e4SLinus Torvalds nwords << 2); 38731da177e4SLinus Torvalds return -EIO; 38741da177e4SLinus Torvalds } 38751da177e4SLinus Torvalds return 0; 38761da177e4SLinus Torvalds } 38771da177e4SLinus Torvalds 38781da177e4SLinus Torvalds static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 38791da177e4SLinus Torvalds { 38808687b63aSAl Viro __be32 *p; 38811da177e4SLinus Torvalds 3882c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 20); 3883c0eae66eSBenny Halevy if (unlikely(!p)) 3884c0eae66eSBenny Halevy goto out_overflow; 38856f723f77SBenny Halevy cinfo->atomic = be32_to_cpup(p++); 38863ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &cinfo->before); 3887cccddf4fSBenny Halevy xdr_decode_hyper(p, &cinfo->after); 38881da177e4SLinus Torvalds return 0; 3889c0eae66eSBenny Halevy out_overflow: 3890c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3891c0eae66eSBenny Halevy return -EIO; 38921da177e4SLinus Torvalds } 38931da177e4SLinus Torvalds 38941da177e4SLinus Torvalds static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access) 38951da177e4SLinus Torvalds { 38968687b63aSAl Viro __be32 *p; 38971da177e4SLinus Torvalds uint32_t supp, acc; 38981da177e4SLinus Torvalds int status; 38991da177e4SLinus Torvalds 39001da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_ACCESS); 39011da177e4SLinus Torvalds if (status) 39021da177e4SLinus Torvalds return status; 3903c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3904c0eae66eSBenny Halevy if (unlikely(!p)) 3905c0eae66eSBenny Halevy goto out_overflow; 39066f723f77SBenny Halevy supp = be32_to_cpup(p++); 3907cccddf4fSBenny Halevy acc = be32_to_cpup(p); 39081da177e4SLinus Torvalds access->supported = supp; 39091da177e4SLinus Torvalds access->access = acc; 39101da177e4SLinus Torvalds return 0; 3911c0eae66eSBenny Halevy out_overflow: 3912c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3913c0eae66eSBenny Halevy return -EIO; 39141da177e4SLinus Torvalds } 39151da177e4SLinus Torvalds 391607d30434SBenny Halevy static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len) 39171da177e4SLinus Torvalds { 39188687b63aSAl Viro __be32 *p; 391907d30434SBenny Halevy 392007d30434SBenny Halevy p = xdr_inline_decode(xdr, len); 392107d30434SBenny Halevy if (likely(p)) { 392207d30434SBenny Halevy memcpy(buf, p, len); 392307d30434SBenny Halevy return 0; 392407d30434SBenny Halevy } 392507d30434SBenny Halevy print_overflow_msg(__func__, xdr); 392607d30434SBenny Halevy return -EIO; 392707d30434SBenny Halevy } 392807d30434SBenny Halevy 392907d30434SBenny Halevy static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 393007d30434SBenny Halevy { 393107d30434SBenny Halevy return decode_opaque_fixed(xdr, stateid->data, NFS4_STATEID_SIZE); 39321da177e4SLinus Torvalds } 39331da177e4SLinus Torvalds 39341da177e4SLinus Torvalds static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) 39351da177e4SLinus Torvalds { 39361da177e4SLinus Torvalds int status; 39371da177e4SLinus Torvalds 39381da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_CLOSE); 3939c1d51931STrond Myklebust if (status != -EIO) 3940c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 394107d30434SBenny Halevy if (!status) 394207d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 39431da177e4SLinus Torvalds return status; 39441da177e4SLinus Torvalds } 39451da177e4SLinus Torvalds 3946db942bbdSBenny Halevy static int decode_verifier(struct xdr_stream *xdr, void *verifier) 3947db942bbdSBenny Halevy { 3948db942bbdSBenny Halevy return decode_opaque_fixed(xdr, verifier, 8); 39491da177e4SLinus Torvalds } 39501da177e4SLinus Torvalds 39511da177e4SLinus Torvalds static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res) 39521da177e4SLinus Torvalds { 39531da177e4SLinus Torvalds int status; 39541da177e4SLinus Torvalds 39551da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_COMMIT); 3956db942bbdSBenny Halevy if (!status) 3957db942bbdSBenny Halevy status = decode_verifier(xdr, res->verf->verifier); 39581da177e4SLinus Torvalds return status; 39591da177e4SLinus Torvalds } 39601da177e4SLinus Torvalds 39611da177e4SLinus Torvalds static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 39621da177e4SLinus Torvalds { 39638687b63aSAl Viro __be32 *p; 39641da177e4SLinus Torvalds uint32_t bmlen; 39651da177e4SLinus Torvalds int status; 39661da177e4SLinus Torvalds 39671da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_CREATE); 39681da177e4SLinus Torvalds if (status) 39691da177e4SLinus Torvalds return status; 39701da177e4SLinus Torvalds if ((status = decode_change_info(xdr, cinfo))) 39711da177e4SLinus Torvalds return status; 3972c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3973c0eae66eSBenny Halevy if (unlikely(!p)) 3974c0eae66eSBenny Halevy goto out_overflow; 3975cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 3976c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, bmlen << 2); 3977c0eae66eSBenny Halevy if (likely(p)) 39781da177e4SLinus Torvalds return 0; 3979c0eae66eSBenny Halevy out_overflow: 3980c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3981c0eae66eSBenny Halevy return -EIO; 39821da177e4SLinus Torvalds } 39831da177e4SLinus Torvalds 39841da177e4SLinus Torvalds static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) 39851da177e4SLinus Torvalds { 39868687b63aSAl Viro __be32 *savep; 39876c0195a4SAndy Adamson uint32_t attrlen, bitmap[2] = {0}; 39881da177e4SLinus Torvalds int status; 39891da177e4SLinus Torvalds 39901da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 39911da177e4SLinus Torvalds goto xdr_error; 39921da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 39931da177e4SLinus Torvalds goto xdr_error; 39941da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 39951da177e4SLinus Torvalds goto xdr_error; 39961da177e4SLinus Torvalds if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0) 39971da177e4SLinus Torvalds goto xdr_error; 39981da177e4SLinus Torvalds if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0) 39991da177e4SLinus Torvalds goto xdr_error; 40001da177e4SLinus Torvalds if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0) 40011da177e4SLinus Torvalds goto xdr_error; 40021da177e4SLinus Torvalds if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0) 40031da177e4SLinus Torvalds goto xdr_error; 40041da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 40051da177e4SLinus Torvalds xdr_error: 40063110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 40071da177e4SLinus Torvalds return status; 40081da177e4SLinus Torvalds } 40091da177e4SLinus Torvalds 40101da177e4SLinus Torvalds static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) 40111da177e4SLinus Torvalds { 40128687b63aSAl Viro __be32 *savep; 40136c0195a4SAndy Adamson uint32_t attrlen, bitmap[2] = {0}; 40141da177e4SLinus Torvalds int status; 40151da177e4SLinus Torvalds 40161da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 40171da177e4SLinus Torvalds goto xdr_error; 40181da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 40191da177e4SLinus Torvalds goto xdr_error; 40201da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 40211da177e4SLinus Torvalds goto xdr_error; 40221da177e4SLinus Torvalds 40231da177e4SLinus Torvalds if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0) 40241da177e4SLinus Torvalds goto xdr_error; 40251da177e4SLinus Torvalds if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0) 40261da177e4SLinus Torvalds goto xdr_error; 40271da177e4SLinus Torvalds if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0) 40281da177e4SLinus Torvalds goto xdr_error; 40291da177e4SLinus Torvalds if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0) 40301da177e4SLinus Torvalds goto xdr_error; 40311da177e4SLinus Torvalds if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0) 40321da177e4SLinus Torvalds goto xdr_error; 40331da177e4SLinus Torvalds if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0) 40341da177e4SLinus Torvalds goto xdr_error; 40351da177e4SLinus Torvalds 40361da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 40371da177e4SLinus Torvalds xdr_error: 40383110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 40391da177e4SLinus Torvalds return status; 40401da177e4SLinus Torvalds } 40411da177e4SLinus Torvalds 40421da177e4SLinus Torvalds static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) 40431da177e4SLinus Torvalds { 40448687b63aSAl Viro __be32 *savep; 40456c0195a4SAndy Adamson uint32_t attrlen, bitmap[2] = {0}; 40461da177e4SLinus Torvalds int status; 40471da177e4SLinus Torvalds 40481da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 40491da177e4SLinus Torvalds goto xdr_error; 40501da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 40511da177e4SLinus Torvalds goto xdr_error; 40521da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 40531da177e4SLinus Torvalds goto xdr_error; 40541da177e4SLinus Torvalds 40551da177e4SLinus Torvalds if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0) 40561da177e4SLinus Torvalds goto xdr_error; 40571da177e4SLinus Torvalds if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0) 40581da177e4SLinus Torvalds goto xdr_error; 40591da177e4SLinus Torvalds 40601da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 40611da177e4SLinus Torvalds xdr_error: 40623110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 40631da177e4SLinus Torvalds return status; 40641da177e4SLinus Torvalds } 40651da177e4SLinus Torvalds 4066ae42c70aSBryan Schumaker static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, 4067ae42c70aSBryan Schumaker struct nfs_fattr *fattr, struct nfs_fh *fh, 406880e52aceSTrond Myklebust const struct nfs_server *server, int may_sleep) 40691da177e4SLinus Torvalds { 4070bca79478STrond Myklebust int status; 4071bca79478STrond Myklebust umode_t fmode = 0; 4072ae42c70aSBryan Schumaker uint32_t type; 40731da177e4SLinus Torvalds 4074f26c7a78STrond Myklebust status = decode_attr_type(xdr, bitmap, &type); 4075f26c7a78STrond Myklebust if (status < 0) 40761da177e4SLinus Torvalds goto xdr_error; 4077409924e4STrond Myklebust fattr->mode = 0; 4078409924e4STrond Myklebust if (status != 0) { 4079409924e4STrond Myklebust fattr->mode |= nfs_type2fmt[type]; 4080409924e4STrond Myklebust fattr->valid |= status; 4081409924e4STrond Myklebust } 40821da177e4SLinus Torvalds 4083f26c7a78STrond Myklebust status = decode_attr_change(xdr, bitmap, &fattr->change_attr); 4084f26c7a78STrond Myklebust if (status < 0) 40851da177e4SLinus Torvalds goto xdr_error; 4086409924e4STrond Myklebust fattr->valid |= status; 4087f26c7a78STrond Myklebust 4088f26c7a78STrond Myklebust status = decode_attr_size(xdr, bitmap, &fattr->size); 4089f26c7a78STrond Myklebust if (status < 0) 40901da177e4SLinus Torvalds goto xdr_error; 4091409924e4STrond Myklebust fattr->valid |= status; 4092f26c7a78STrond Myklebust 4093f26c7a78STrond Myklebust status = decode_attr_fsid(xdr, bitmap, &fattr->fsid); 4094f26c7a78STrond Myklebust if (status < 0) 40951da177e4SLinus Torvalds goto xdr_error; 4096409924e4STrond Myklebust fattr->valid |= status; 4097f26c7a78STrond Myklebust 4098ae42c70aSBryan Schumaker status = decode_attr_error(xdr, bitmap); 40997ebb9315SBryan Schumaker if (status == -NFS4ERR_WRONGSEC) { 41007ebb9315SBryan Schumaker nfs_fixup_secinfo_attributes(fattr, fh); 41017ebb9315SBryan Schumaker status = 0; 41027ebb9315SBryan Schumaker } 4103ae42c70aSBryan Schumaker if (status < 0) 4104ae42c70aSBryan Schumaker goto xdr_error; 4105ae42c70aSBryan Schumaker 4106ae42c70aSBryan Schumaker status = decode_attr_filehandle(xdr, bitmap, fh); 4107ae42c70aSBryan Schumaker if (status < 0) 4108ae42c70aSBryan Schumaker goto xdr_error; 4109ae42c70aSBryan Schumaker 4110f26c7a78STrond Myklebust status = decode_attr_fileid(xdr, bitmap, &fattr->fileid); 4111f26c7a78STrond Myklebust if (status < 0) 41121da177e4SLinus Torvalds goto xdr_error; 4113409924e4STrond Myklebust fattr->valid |= status; 4114f26c7a78STrond Myklebust 4115f26c7a78STrond Myklebust status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, 41167aaa0b3bSManoj Naik struct nfs4_fs_locations, 4117f26c7a78STrond Myklebust fattr)); 4118f26c7a78STrond Myklebust if (status < 0) 4119683b57b4STrond Myklebust goto xdr_error; 4120409924e4STrond Myklebust fattr->valid |= status; 4121f26c7a78STrond Myklebust 4122f26c7a78STrond Myklebust status = decode_attr_mode(xdr, bitmap, &fmode); 4123f26c7a78STrond Myklebust if (status < 0) 41241da177e4SLinus Torvalds goto xdr_error; 4125409924e4STrond Myklebust if (status != 0) { 41261da177e4SLinus Torvalds fattr->mode |= fmode; 4127409924e4STrond Myklebust fattr->valid |= status; 4128409924e4STrond Myklebust } 4129f26c7a78STrond Myklebust 4130f26c7a78STrond Myklebust status = decode_attr_nlink(xdr, bitmap, &fattr->nlink); 4131f26c7a78STrond Myklebust if (status < 0) 41321da177e4SLinus Torvalds goto xdr_error; 4133409924e4STrond Myklebust fattr->valid |= status; 4134f26c7a78STrond Myklebust 4135e4fd72a1STrond Myklebust status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, may_sleep); 4136f26c7a78STrond Myklebust if (status < 0) 41371da177e4SLinus Torvalds goto xdr_error; 4138409924e4STrond Myklebust fattr->valid |= status; 4139f26c7a78STrond Myklebust 4140e4fd72a1STrond Myklebust status = decode_attr_group(xdr, bitmap, server, &fattr->gid, may_sleep); 4141f26c7a78STrond Myklebust if (status < 0) 41421da177e4SLinus Torvalds goto xdr_error; 4143409924e4STrond Myklebust fattr->valid |= status; 4144f26c7a78STrond Myklebust 4145f26c7a78STrond Myklebust status = decode_attr_rdev(xdr, bitmap, &fattr->rdev); 4146f26c7a78STrond Myklebust if (status < 0) 41471da177e4SLinus Torvalds goto xdr_error; 4148409924e4STrond Myklebust fattr->valid |= status; 4149f26c7a78STrond Myklebust 4150f26c7a78STrond Myklebust status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used); 4151f26c7a78STrond Myklebust if (status < 0) 41521da177e4SLinus Torvalds goto xdr_error; 4153409924e4STrond Myklebust fattr->valid |= status; 4154f26c7a78STrond Myklebust 4155f26c7a78STrond Myklebust status = decode_attr_time_access(xdr, bitmap, &fattr->atime); 4156f26c7a78STrond Myklebust if (status < 0) 41571da177e4SLinus Torvalds goto xdr_error; 4158409924e4STrond Myklebust fattr->valid |= status; 4159f26c7a78STrond Myklebust 4160f26c7a78STrond Myklebust status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime); 4161f26c7a78STrond Myklebust if (status < 0) 41621da177e4SLinus Torvalds goto xdr_error; 4163409924e4STrond Myklebust fattr->valid |= status; 4164f26c7a78STrond Myklebust 4165f26c7a78STrond Myklebust status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime); 4166f26c7a78STrond Myklebust if (status < 0) 41671da177e4SLinus Torvalds goto xdr_error; 4168409924e4STrond Myklebust fattr->valid |= status; 4169f26c7a78STrond Myklebust 417028331a46STrond Myklebust status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid); 4171f26c7a78STrond Myklebust if (status < 0) 417299baf625SManoj Naik goto xdr_error; 4173409924e4STrond Myklebust fattr->valid |= status; 4174f26c7a78STrond Myklebust 4175ae42c70aSBryan Schumaker xdr_error: 4176ae42c70aSBryan Schumaker dprintk("%s: xdr returned %d\n", __func__, -status); 4177ae42c70aSBryan Schumaker return status; 4178ae42c70aSBryan Schumaker } 4179ae42c70aSBryan Schumaker 4180ae42c70aSBryan Schumaker static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, 4181ae42c70aSBryan Schumaker struct nfs_fh *fh, const struct nfs_server *server, int may_sleep) 4182ae42c70aSBryan Schumaker { 4183ae42c70aSBryan Schumaker __be32 *savep; 4184ae42c70aSBryan Schumaker uint32_t attrlen, 4185ae42c70aSBryan Schumaker bitmap[2] = {0}; 4186ae42c70aSBryan Schumaker int status; 4187ae42c70aSBryan Schumaker 4188ae42c70aSBryan Schumaker status = decode_op_hdr(xdr, OP_GETATTR); 4189ae42c70aSBryan Schumaker if (status < 0) 4190ae42c70aSBryan Schumaker goto xdr_error; 4191ae42c70aSBryan Schumaker 4192ae42c70aSBryan Schumaker status = decode_attr_bitmap(xdr, bitmap); 4193ae42c70aSBryan Schumaker if (status < 0) 4194ae42c70aSBryan Schumaker goto xdr_error; 4195ae42c70aSBryan Schumaker 4196ae42c70aSBryan Schumaker status = decode_attr_length(xdr, &attrlen, &savep); 4197ae42c70aSBryan Schumaker if (status < 0) 4198ae42c70aSBryan Schumaker goto xdr_error; 4199ae42c70aSBryan Schumaker 4200ae42c70aSBryan Schumaker status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep); 4201ae42c70aSBryan Schumaker if (status < 0) 4202ae42c70aSBryan Schumaker goto xdr_error; 4203ae42c70aSBryan Schumaker 4204f26c7a78STrond Myklebust status = verify_attr_len(xdr, savep, attrlen); 42051da177e4SLinus Torvalds xdr_error: 42063110ff80SHarvey Harrison dprintk("%s: xdr returned %d\n", __func__, -status); 42071da177e4SLinus Torvalds return status; 42081da177e4SLinus Torvalds } 42091da177e4SLinus Torvalds 4210ae42c70aSBryan Schumaker static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, 4211ae42c70aSBryan Schumaker const struct nfs_server *server, int may_sleep) 4212ae42c70aSBryan Schumaker { 4213ae42c70aSBryan Schumaker return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); 4214ae42c70aSBryan Schumaker } 42151da177e4SLinus Torvalds 4216504913fbSAndy Adamson /* 4217504913fbSAndy Adamson * Decode potentially multiple layout types. Currently we only support 4218504913fbSAndy Adamson * one layout driver per file system. 4219504913fbSAndy Adamson */ 4220504913fbSAndy Adamson static int decode_first_pnfs_layout_type(struct xdr_stream *xdr, 4221504913fbSAndy Adamson uint32_t *layouttype) 4222504913fbSAndy Adamson { 4223504913fbSAndy Adamson uint32_t *p; 4224504913fbSAndy Adamson int num; 4225504913fbSAndy Adamson 4226504913fbSAndy Adamson p = xdr_inline_decode(xdr, 4); 4227504913fbSAndy Adamson if (unlikely(!p)) 4228504913fbSAndy Adamson goto out_overflow; 4229504913fbSAndy Adamson num = be32_to_cpup(p); 4230504913fbSAndy Adamson 4231504913fbSAndy Adamson /* pNFS is not supported by the underlying file system */ 4232504913fbSAndy Adamson if (num == 0) { 4233504913fbSAndy Adamson *layouttype = 0; 4234504913fbSAndy Adamson return 0; 4235504913fbSAndy Adamson } 4236504913fbSAndy Adamson if (num > 1) 4237504913fbSAndy Adamson printk(KERN_INFO "%s: Warning: Multiple pNFS layout drivers " 4238504913fbSAndy Adamson "per filesystem not supported\n", __func__); 4239504913fbSAndy Adamson 4240504913fbSAndy Adamson /* Decode and set first layout type, move xdr->p past unused types */ 4241504913fbSAndy Adamson p = xdr_inline_decode(xdr, num * 4); 4242504913fbSAndy Adamson if (unlikely(!p)) 4243504913fbSAndy Adamson goto out_overflow; 4244504913fbSAndy Adamson *layouttype = be32_to_cpup(p); 4245504913fbSAndy Adamson return 0; 4246504913fbSAndy Adamson out_overflow: 4247504913fbSAndy Adamson print_overflow_msg(__func__, xdr); 4248504913fbSAndy Adamson return -EIO; 4249504913fbSAndy Adamson } 4250504913fbSAndy Adamson 4251504913fbSAndy Adamson /* 4252504913fbSAndy Adamson * The type of file system exported. 4253504913fbSAndy Adamson * Note we must ensure that layouttype is set in any non-error case. 4254504913fbSAndy Adamson */ 4255504913fbSAndy Adamson static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap, 4256504913fbSAndy Adamson uint32_t *layouttype) 4257504913fbSAndy Adamson { 4258504913fbSAndy Adamson int status = 0; 4259504913fbSAndy Adamson 4260504913fbSAndy Adamson dprintk("%s: bitmap is %x\n", __func__, bitmap[1]); 4261504913fbSAndy Adamson if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U))) 4262504913fbSAndy Adamson return -EIO; 4263504913fbSAndy Adamson if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) { 4264504913fbSAndy Adamson status = decode_first_pnfs_layout_type(xdr, layouttype); 4265504913fbSAndy Adamson bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES; 4266504913fbSAndy Adamson } else 4267504913fbSAndy Adamson *layouttype = 0; 4268504913fbSAndy Adamson return status; 4269504913fbSAndy Adamson } 4270504913fbSAndy Adamson 42711da177e4SLinus Torvalds static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) 42721da177e4SLinus Torvalds { 42738687b63aSAl Viro __be32 *savep; 42741da177e4SLinus Torvalds uint32_t attrlen, bitmap[2]; 42751da177e4SLinus Torvalds int status; 42761da177e4SLinus Torvalds 42771da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 42781da177e4SLinus Torvalds goto xdr_error; 42791da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 42801da177e4SLinus Torvalds goto xdr_error; 42811da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 42821da177e4SLinus Torvalds goto xdr_error; 42831da177e4SLinus Torvalds 42841da177e4SLinus Torvalds fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */ 42851da177e4SLinus Torvalds 42861da177e4SLinus Torvalds if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0) 42871da177e4SLinus Torvalds goto xdr_error; 42881da177e4SLinus Torvalds if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0) 42891da177e4SLinus Torvalds goto xdr_error; 42901da177e4SLinus Torvalds if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0) 42911da177e4SLinus Torvalds goto xdr_error; 42921da177e4SLinus Torvalds fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax; 42931da177e4SLinus Torvalds if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0) 42941da177e4SLinus Torvalds goto xdr_error; 42951da177e4SLinus Torvalds fsinfo->wtpref = fsinfo->wtmax; 429655b6e774SRicardo Labiaga status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta); 429755b6e774SRicardo Labiaga if (status != 0) 429855b6e774SRicardo Labiaga goto xdr_error; 4299504913fbSAndy Adamson status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype); 4300504913fbSAndy Adamson if (status != 0) 4301504913fbSAndy Adamson goto xdr_error; 43021da177e4SLinus Torvalds 43031da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 43041da177e4SLinus Torvalds xdr_error: 43053110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 43061da177e4SLinus Torvalds return status; 43071da177e4SLinus Torvalds } 43081da177e4SLinus Torvalds 43091da177e4SLinus Torvalds static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) 43101da177e4SLinus Torvalds { 43118687b63aSAl Viro __be32 *p; 43121da177e4SLinus Torvalds uint32_t len; 43131da177e4SLinus Torvalds int status; 43141da177e4SLinus Torvalds 43159936781dSTrond Myklebust /* Zero handle first to allow comparisons */ 43169936781dSTrond Myklebust memset(fh, 0, sizeof(*fh)); 43179936781dSTrond Myklebust 43181da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_GETFH); 43191da177e4SLinus Torvalds if (status) 43201da177e4SLinus Torvalds return status; 43211da177e4SLinus Torvalds 4322c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4323c0eae66eSBenny Halevy if (unlikely(!p)) 4324c0eae66eSBenny Halevy goto out_overflow; 4325cccddf4fSBenny Halevy len = be32_to_cpup(p); 43261da177e4SLinus Torvalds if (len > NFS4_FHSIZE) 43271da177e4SLinus Torvalds return -EIO; 43281da177e4SLinus Torvalds fh->size = len; 4329c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 4330c0eae66eSBenny Halevy if (unlikely(!p)) 4331c0eae66eSBenny Halevy goto out_overflow; 433299398d06SBenny Halevy memcpy(fh->data, p, len); 43331da177e4SLinus Torvalds return 0; 4334c0eae66eSBenny Halevy out_overflow: 4335c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4336c0eae66eSBenny Halevy return -EIO; 43371da177e4SLinus Torvalds } 43381da177e4SLinus Torvalds 43391da177e4SLinus Torvalds static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 43401da177e4SLinus Torvalds { 43411da177e4SLinus Torvalds int status; 43421da177e4SLinus Torvalds 43431da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LINK); 43441da177e4SLinus Torvalds if (status) 43451da177e4SLinus Torvalds return status; 43461da177e4SLinus Torvalds return decode_change_info(xdr, cinfo); 43471da177e4SLinus Torvalds } 43481da177e4SLinus Torvalds 43491da177e4SLinus Torvalds /* 43501da177e4SLinus Torvalds * We create the owner, so we know a proper owner.id length is 4. 43511da177e4SLinus Torvalds */ 4352911d1aafSTrond Myklebust static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) 43531da177e4SLinus Torvalds { 4354911d1aafSTrond Myklebust uint64_t offset, length, clientid; 43558687b63aSAl Viro __be32 *p; 4356911d1aafSTrond Myklebust uint32_t namelen, type; 43571da177e4SLinus Torvalds 4358babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 32); /* read 32 bytes */ 4359c0eae66eSBenny Halevy if (unlikely(!p)) 4360c0eae66eSBenny Halevy goto out_overflow; 4361babddc72SBryan Schumaker p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */ 43623ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &length); 4363babddc72SBryan Schumaker type = be32_to_cpup(p++); /* 4 byte read */ 4364babddc72SBryan Schumaker if (fl != NULL) { /* manipulate file lock */ 4365911d1aafSTrond Myklebust fl->fl_start = (loff_t)offset; 4366911d1aafSTrond Myklebust fl->fl_end = fl->fl_start + (loff_t)length - 1; 4367911d1aafSTrond Myklebust if (length == ~(uint64_t)0) 4368911d1aafSTrond Myklebust fl->fl_end = OFFSET_MAX; 4369911d1aafSTrond Myklebust fl->fl_type = F_WRLCK; 4370911d1aafSTrond Myklebust if (type & 1) 4371911d1aafSTrond Myklebust fl->fl_type = F_RDLCK; 4372911d1aafSTrond Myklebust fl->fl_pid = 0; 4373911d1aafSTrond Myklebust } 4374babddc72SBryan Schumaker p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */ 4375babddc72SBryan Schumaker namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */ 4376babddc72SBryan Schumaker p = xdr_inline_decode(xdr, namelen); /* variable size field */ 4377c0eae66eSBenny Halevy if (likely(p)) 43781da177e4SLinus Torvalds return -NFS4ERR_DENIED; 4379c0eae66eSBenny Halevy out_overflow: 4380c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4381c0eae66eSBenny Halevy return -EIO; 43821da177e4SLinus Torvalds } 43831da177e4SLinus Torvalds 4384911d1aafSTrond Myklebust static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) 43851da177e4SLinus Torvalds { 43861da177e4SLinus Torvalds int status; 43871da177e4SLinus Torvalds 43881da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCK); 4389c1d51931STrond Myklebust if (status == -EIO) 4390c1d51931STrond Myklebust goto out; 43911da177e4SLinus Torvalds if (status == 0) { 439207d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 439307d30434SBenny Halevy if (unlikely(status)) 439407d30434SBenny Halevy goto out; 43951da177e4SLinus Torvalds } else if (status == -NFS4ERR_DENIED) 4396c1d51931STrond Myklebust status = decode_lock_denied(xdr, NULL); 4397c1d51931STrond Myklebust if (res->open_seqid != NULL) 4398c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->open_seqid); 4399c1d51931STrond Myklebust nfs_increment_lock_seqid(status, res->lock_seqid); 4400c1d51931STrond Myklebust out: 44011da177e4SLinus Torvalds return status; 44021da177e4SLinus Torvalds } 44031da177e4SLinus Torvalds 4404911d1aafSTrond Myklebust static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res) 44051da177e4SLinus Torvalds { 44061da177e4SLinus Torvalds int status; 44071da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCKT); 44081da177e4SLinus Torvalds if (status == -NFS4ERR_DENIED) 4409911d1aafSTrond Myklebust return decode_lock_denied(xdr, res->denied); 44101da177e4SLinus Torvalds return status; 44111da177e4SLinus Torvalds } 44121da177e4SLinus Torvalds 4413911d1aafSTrond Myklebust static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) 44141da177e4SLinus Torvalds { 44151da177e4SLinus Torvalds int status; 44161da177e4SLinus Torvalds 44171da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCKU); 4418c1d51931STrond Myklebust if (status != -EIO) 4419c1d51931STrond Myklebust nfs_increment_lock_seqid(status, res->seqid); 442007d30434SBenny Halevy if (status == 0) 442107d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 44221da177e4SLinus Torvalds return status; 44231da177e4SLinus Torvalds } 44241da177e4SLinus Torvalds 4425d3c7b7ccSTrond Myklebust static int decode_release_lockowner(struct xdr_stream *xdr) 4426d3c7b7ccSTrond Myklebust { 4427d3c7b7ccSTrond Myklebust return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER); 4428d3c7b7ccSTrond Myklebust } 4429d3c7b7ccSTrond Myklebust 44301da177e4SLinus Torvalds static int decode_lookup(struct xdr_stream *xdr) 44311da177e4SLinus Torvalds { 44321da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_LOOKUP); 44331da177e4SLinus Torvalds } 44341da177e4SLinus Torvalds 44351da177e4SLinus Torvalds /* This is too sick! */ 44361da177e4SLinus Torvalds static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize) 44371da177e4SLinus Torvalds { 44388687b63aSAl Viro __be32 *p; 44391da177e4SLinus Torvalds uint32_t limit_type, nblocks, blocksize; 44401da177e4SLinus Torvalds 4441c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 4442c0eae66eSBenny Halevy if (unlikely(!p)) 4443c0eae66eSBenny Halevy goto out_overflow; 44446f723f77SBenny Halevy limit_type = be32_to_cpup(p++); 44451da177e4SLinus Torvalds switch (limit_type) { 44461da177e4SLinus Torvalds case 1: 4447cccddf4fSBenny Halevy xdr_decode_hyper(p, maxsize); 44481da177e4SLinus Torvalds break; 44491da177e4SLinus Torvalds case 2: 44506f723f77SBenny Halevy nblocks = be32_to_cpup(p++); 4451cccddf4fSBenny Halevy blocksize = be32_to_cpup(p); 44521da177e4SLinus Torvalds *maxsize = (uint64_t)nblocks * (uint64_t)blocksize; 44531da177e4SLinus Torvalds } 44541da177e4SLinus Torvalds return 0; 4455c0eae66eSBenny Halevy out_overflow: 4456c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4457c0eae66eSBenny Halevy return -EIO; 44581da177e4SLinus Torvalds } 44591da177e4SLinus Torvalds 44601da177e4SLinus Torvalds static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) 44611da177e4SLinus Torvalds { 44628687b63aSAl Viro __be32 *p; 44631da177e4SLinus Torvalds uint32_t delegation_type; 446407d30434SBenny Halevy int status; 44651da177e4SLinus Torvalds 4466c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4467c0eae66eSBenny Halevy if (unlikely(!p)) 4468c0eae66eSBenny Halevy goto out_overflow; 4469cccddf4fSBenny Halevy delegation_type = be32_to_cpup(p); 44701da177e4SLinus Torvalds if (delegation_type == NFS4_OPEN_DELEGATE_NONE) { 44711da177e4SLinus Torvalds res->delegation_type = 0; 44721da177e4SLinus Torvalds return 0; 44731da177e4SLinus Torvalds } 447407d30434SBenny Halevy status = decode_stateid(xdr, &res->delegation); 447507d30434SBenny Halevy if (unlikely(status)) 447607d30434SBenny Halevy return status; 4477c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4478c0eae66eSBenny Halevy if (unlikely(!p)) 4479c0eae66eSBenny Halevy goto out_overflow; 4480cccddf4fSBenny Halevy res->do_recall = be32_to_cpup(p); 448105d564feSAndy Adamson 44821da177e4SLinus Torvalds switch (delegation_type) { 44831da177e4SLinus Torvalds case NFS4_OPEN_DELEGATE_READ: 44841da177e4SLinus Torvalds res->delegation_type = FMODE_READ; 44851da177e4SLinus Torvalds break; 44861da177e4SLinus Torvalds case NFS4_OPEN_DELEGATE_WRITE: 44871da177e4SLinus Torvalds res->delegation_type = FMODE_WRITE|FMODE_READ; 44881da177e4SLinus Torvalds if (decode_space_limit(xdr, &res->maxsize) < 0) 44891da177e4SLinus Torvalds return -EIO; 44901da177e4SLinus Torvalds } 44917539bbabSDavid Howells return decode_ace(xdr, NULL, res->server->nfs_client); 4492c0eae66eSBenny Halevy out_overflow: 4493c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4494c0eae66eSBenny Halevy return -EIO; 44951da177e4SLinus Torvalds } 44961da177e4SLinus Torvalds 44971da177e4SLinus Torvalds static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) 44981da177e4SLinus Torvalds { 44998687b63aSAl Viro __be32 *p; 4500aa53ed54SJeff Layton uint32_t savewords, bmlen, i; 45011da177e4SLinus Torvalds int status; 45021da177e4SLinus Torvalds 45031da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_OPEN); 4504c1d51931STrond Myklebust if (status != -EIO) 4505c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 450607d30434SBenny Halevy if (!status) 450707d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 450807d30434SBenny Halevy if (unlikely(status)) 45091da177e4SLinus Torvalds return status; 45101da177e4SLinus Torvalds 45111da177e4SLinus Torvalds decode_change_info(xdr, &res->cinfo); 45121da177e4SLinus Torvalds 4513c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4514c0eae66eSBenny Halevy if (unlikely(!p)) 4515c0eae66eSBenny Halevy goto out_overflow; 45166f723f77SBenny Halevy res->rflags = be32_to_cpup(p++); 4517cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 45181da177e4SLinus Torvalds if (bmlen > 10) 45191da177e4SLinus Torvalds goto xdr_error; 45201da177e4SLinus Torvalds 4521c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, bmlen << 2); 4522c0eae66eSBenny Halevy if (unlikely(!p)) 4523c0eae66eSBenny Halevy goto out_overflow; 4524aa53ed54SJeff Layton savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE); 4525aa53ed54SJeff Layton for (i = 0; i < savewords; ++i) 45266f723f77SBenny Halevy res->attrset[i] = be32_to_cpup(p++); 4527aa53ed54SJeff Layton for (; i < NFS4_BITMAP_SIZE; i++) 4528aa53ed54SJeff Layton res->attrset[i] = 0; 4529aa53ed54SJeff Layton 45301da177e4SLinus Torvalds return decode_delegation(xdr, res); 45311da177e4SLinus Torvalds xdr_error: 45323110ff80SHarvey Harrison dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen); 45331da177e4SLinus Torvalds return -EIO; 4534c0eae66eSBenny Halevy out_overflow: 4535c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4536c0eae66eSBenny Halevy return -EIO; 45371da177e4SLinus Torvalds } 45381da177e4SLinus Torvalds 45391da177e4SLinus Torvalds static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res) 45401da177e4SLinus Torvalds { 45411da177e4SLinus Torvalds int status; 45421da177e4SLinus Torvalds 45431da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); 4544c1d51931STrond Myklebust if (status != -EIO) 4545c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 454607d30434SBenny Halevy if (!status) 454707d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 45481da177e4SLinus Torvalds return status; 45491da177e4SLinus Torvalds } 45501da177e4SLinus Torvalds 45511da177e4SLinus Torvalds static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res) 45521da177e4SLinus Torvalds { 45531da177e4SLinus Torvalds int status; 45541da177e4SLinus Torvalds 45551da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); 4556c1d51931STrond Myklebust if (status != -EIO) 4557c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 455807d30434SBenny Halevy if (!status) 455907d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 45601da177e4SLinus Torvalds return status; 45611da177e4SLinus Torvalds } 45621da177e4SLinus Torvalds 45631da177e4SLinus Torvalds static int decode_putfh(struct xdr_stream *xdr) 45641da177e4SLinus Torvalds { 45651da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_PUTFH); 45661da177e4SLinus Torvalds } 45671da177e4SLinus Torvalds 45681da177e4SLinus Torvalds static int decode_putrootfh(struct xdr_stream *xdr) 45691da177e4SLinus Torvalds { 45701da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_PUTROOTFH); 45711da177e4SLinus Torvalds } 45721da177e4SLinus Torvalds 45731da177e4SLinus Torvalds static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res) 45741da177e4SLinus Torvalds { 45751da177e4SLinus Torvalds struct kvec *iov = req->rq_rcv_buf.head; 45768687b63aSAl Viro __be32 *p; 45771da177e4SLinus Torvalds uint32_t count, eof, recvd, hdrlen; 45781da177e4SLinus Torvalds int status; 45791da177e4SLinus Torvalds 45801da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READ); 45811da177e4SLinus Torvalds if (status) 45821da177e4SLinus Torvalds return status; 4583c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4584c0eae66eSBenny Halevy if (unlikely(!p)) 4585c0eae66eSBenny Halevy goto out_overflow; 45866f723f77SBenny Halevy eof = be32_to_cpup(p++); 4587cccddf4fSBenny Halevy count = be32_to_cpup(p); 45888111f373SChuck Lever hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; 45891da177e4SLinus Torvalds recvd = req->rq_rcv_buf.len - hdrlen; 45901da177e4SLinus Torvalds if (count > recvd) { 4591fe82a183SChuck Lever dprintk("NFS: server cheating in read reply: " 45921da177e4SLinus Torvalds "count %u > recvd %u\n", count, recvd); 45931da177e4SLinus Torvalds count = recvd; 45941da177e4SLinus Torvalds eof = 0; 45951da177e4SLinus Torvalds } 45961da177e4SLinus Torvalds xdr_read_pages(xdr, count); 45971da177e4SLinus Torvalds res->eof = eof; 45981da177e4SLinus Torvalds res->count = count; 45991da177e4SLinus Torvalds return 0; 4600c0eae66eSBenny Halevy out_overflow: 4601c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4602c0eae66eSBenny Halevy return -EIO; 46031da177e4SLinus Torvalds } 46041da177e4SLinus Torvalds 46051da177e4SLinus Torvalds static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) 46061da177e4SLinus Torvalds { 46071da177e4SLinus Torvalds struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 46081da177e4SLinus Torvalds struct kvec *iov = rcvbuf->head; 4609bcecff77SChuck Lever size_t hdrlen; 4610bcecff77SChuck Lever u32 recvd, pglen = rcvbuf->page_len; 4611bcecff77SChuck Lever int status; 46121da177e4SLinus Torvalds 46131da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READDIR); 4614db942bbdSBenny Halevy if (!status) 4615db942bbdSBenny Halevy status = decode_verifier(xdr, readdir->verifier.data); 4616db942bbdSBenny Halevy if (unlikely(status)) 46171da177e4SLinus Torvalds return status; 461844109241SFred Isaman dprintk("%s: verifier = %08x:%08x\n", 461944109241SFred Isaman __func__, 4620eadf4598STrond Myklebust ((u32 *)readdir->verifier.data)[0], 4621eadf4598STrond Myklebust ((u32 *)readdir->verifier.data)[1]); 4622eadf4598STrond Myklebust 46231da177e4SLinus Torvalds 4624db942bbdSBenny Halevy hdrlen = (char *) xdr->p - (char *) iov->iov_base; 46251da177e4SLinus Torvalds recvd = rcvbuf->len - hdrlen; 46261da177e4SLinus Torvalds if (pglen > recvd) 46271da177e4SLinus Torvalds pglen = recvd; 46281da177e4SLinus Torvalds xdr_read_pages(xdr, pglen); 46291da177e4SLinus Torvalds 46307bda2cdfSJeff Layton 4631ac396128STrond Myklebust return pglen; 46321da177e4SLinus Torvalds } 46331da177e4SLinus Torvalds 46341da177e4SLinus Torvalds static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) 46351da177e4SLinus Torvalds { 46361da177e4SLinus Torvalds struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 46371da177e4SLinus Torvalds struct kvec *iov = rcvbuf->head; 4638bcecff77SChuck Lever size_t hdrlen; 4639bcecff77SChuck Lever u32 len, recvd; 46408687b63aSAl Viro __be32 *p; 46411da177e4SLinus Torvalds int status; 46421da177e4SLinus Torvalds 46431da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READLINK); 46441da177e4SLinus Torvalds if (status) 46451da177e4SLinus Torvalds return status; 46461da177e4SLinus Torvalds 46471da177e4SLinus Torvalds /* Convert length of symlink */ 4648c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4649c0eae66eSBenny Halevy if (unlikely(!p)) 4650c0eae66eSBenny Halevy goto out_overflow; 4651cccddf4fSBenny Halevy len = be32_to_cpup(p); 46521da177e4SLinus Torvalds if (len >= rcvbuf->page_len || len <= 0) { 4653fe82a183SChuck Lever dprintk("nfs: server returned giant symlink!\n"); 46541da177e4SLinus Torvalds return -ENAMETOOLONG; 46551da177e4SLinus Torvalds } 46561da177e4SLinus Torvalds hdrlen = (char *) xdr->p - (char *) iov->iov_base; 46571da177e4SLinus Torvalds recvd = req->rq_rcv_buf.len - hdrlen; 46581da177e4SLinus Torvalds if (recvd < len) { 4659fe82a183SChuck Lever dprintk("NFS: server cheating in readlink reply: " 46601da177e4SLinus Torvalds "count %u > recvd %u\n", len, recvd); 46611da177e4SLinus Torvalds return -EIO; 46621da177e4SLinus Torvalds } 46631da177e4SLinus Torvalds xdr_read_pages(xdr, len); 46641da177e4SLinus Torvalds /* 46651da177e4SLinus Torvalds * The XDR encode routine has set things up so that 46661da177e4SLinus Torvalds * the link text will be copied directly into the 46671da177e4SLinus Torvalds * buffer. We just have to do overflow-checking, 46681da177e4SLinus Torvalds * and and null-terminate the text (the VFS expects 46691da177e4SLinus Torvalds * null-termination). 46701da177e4SLinus Torvalds */ 4671b4687da7SChuck Lever xdr_terminate_string(rcvbuf, len); 46721da177e4SLinus Torvalds return 0; 4673c0eae66eSBenny Halevy out_overflow: 4674c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4675c0eae66eSBenny Halevy return -EIO; 46761da177e4SLinus Torvalds } 46771da177e4SLinus Torvalds 46781da177e4SLinus Torvalds static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 46791da177e4SLinus Torvalds { 46801da177e4SLinus Torvalds int status; 46811da177e4SLinus Torvalds 46821da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_REMOVE); 46831da177e4SLinus Torvalds if (status) 46841da177e4SLinus Torvalds goto out; 46851da177e4SLinus Torvalds status = decode_change_info(xdr, cinfo); 46861da177e4SLinus Torvalds out: 46871da177e4SLinus Torvalds return status; 46881da177e4SLinus Torvalds } 46891da177e4SLinus Torvalds 46901da177e4SLinus Torvalds static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo, 46911da177e4SLinus Torvalds struct nfs4_change_info *new_cinfo) 46921da177e4SLinus Torvalds { 46931da177e4SLinus Torvalds int status; 46941da177e4SLinus Torvalds 46951da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_RENAME); 46961da177e4SLinus Torvalds if (status) 46971da177e4SLinus Torvalds goto out; 46981da177e4SLinus Torvalds if ((status = decode_change_info(xdr, old_cinfo))) 46991da177e4SLinus Torvalds goto out; 47001da177e4SLinus Torvalds status = decode_change_info(xdr, new_cinfo); 47011da177e4SLinus Torvalds out: 47021da177e4SLinus Torvalds return status; 47031da177e4SLinus Torvalds } 47041da177e4SLinus Torvalds 47051da177e4SLinus Torvalds static int decode_renew(struct xdr_stream *xdr) 47061da177e4SLinus Torvalds { 47071da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_RENEW); 47081da177e4SLinus Torvalds } 47091da177e4SLinus Torvalds 471056ae19f3STrond Myklebust static int 471156ae19f3STrond Myklebust decode_restorefh(struct xdr_stream *xdr) 471256ae19f3STrond Myklebust { 471356ae19f3STrond Myklebust return decode_op_hdr(xdr, OP_RESTOREFH); 471456ae19f3STrond Myklebust } 471556ae19f3STrond Myklebust 4716029d105eSJ. Bruce Fields static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, 4717029d105eSJ. Bruce Fields size_t *acl_len) 4718029d105eSJ. Bruce Fields { 47198687b63aSAl Viro __be32 *savep; 4720029d105eSJ. Bruce Fields uint32_t attrlen, 4721029d105eSJ. Bruce Fields bitmap[2] = {0}; 4722029d105eSJ. Bruce Fields struct kvec *iov = req->rq_rcv_buf.head; 4723029d105eSJ. Bruce Fields int status; 4724029d105eSJ. Bruce Fields 4725029d105eSJ. Bruce Fields *acl_len = 0; 4726029d105eSJ. Bruce Fields if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 4727029d105eSJ. Bruce Fields goto out; 4728029d105eSJ. Bruce Fields if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 4729029d105eSJ. Bruce Fields goto out; 4730029d105eSJ. Bruce Fields if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 4731029d105eSJ. Bruce Fields goto out; 4732029d105eSJ. Bruce Fields 4733029d105eSJ. Bruce Fields if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) 4734029d105eSJ. Bruce Fields return -EIO; 4735029d105eSJ. Bruce Fields if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { 4736bcecff77SChuck Lever size_t hdrlen; 4737bcecff77SChuck Lever u32 recvd; 4738029d105eSJ. Bruce Fields 4739029d105eSJ. Bruce Fields /* We ignore &savep and don't do consistency checks on 4740029d105eSJ. Bruce Fields * the attr length. Let userspace figure it out.... */ 4741029d105eSJ. Bruce Fields hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; 4742029d105eSJ. Bruce Fields recvd = req->rq_rcv_buf.len - hdrlen; 4743029d105eSJ. Bruce Fields if (attrlen > recvd) { 4744fe82a183SChuck Lever dprintk("NFS: server cheating in getattr" 4745029d105eSJ. Bruce Fields " acl reply: attrlen %u > recvd %u\n", 4746029d105eSJ. Bruce Fields attrlen, recvd); 4747029d105eSJ. Bruce Fields return -EINVAL; 4748029d105eSJ. Bruce Fields } 4749029d105eSJ. Bruce Fields xdr_read_pages(xdr, attrlen); 4750029d105eSJ. Bruce Fields *acl_len = attrlen; 47518c233cf9SJ. Bruce Fields } else 47528c233cf9SJ. Bruce Fields status = -EOPNOTSUPP; 4753029d105eSJ. Bruce Fields 4754029d105eSJ. Bruce Fields out: 4755029d105eSJ. Bruce Fields return status; 4756029d105eSJ. Bruce Fields } 4757029d105eSJ. Bruce Fields 47581da177e4SLinus Torvalds static int 47591da177e4SLinus Torvalds decode_savefh(struct xdr_stream *xdr) 47601da177e4SLinus Torvalds { 47611da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_SAVEFH); 47621da177e4SLinus Torvalds } 47631da177e4SLinus Torvalds 47649e9ecc03SBenny Halevy static int decode_setattr(struct xdr_stream *xdr) 47651da177e4SLinus Torvalds { 47668687b63aSAl Viro __be32 *p; 47671da177e4SLinus Torvalds uint32_t bmlen; 47681da177e4SLinus Torvalds int status; 47691da177e4SLinus Torvalds 47701da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_SETATTR); 47711da177e4SLinus Torvalds if (status) 47721da177e4SLinus Torvalds return status; 4773c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4774c0eae66eSBenny Halevy if (unlikely(!p)) 4775c0eae66eSBenny Halevy goto out_overflow; 4776cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 4777c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, bmlen << 2); 4778c0eae66eSBenny Halevy if (likely(p)) 47791da177e4SLinus Torvalds return 0; 4780c0eae66eSBenny Halevy out_overflow: 4781c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4782c0eae66eSBenny Halevy return -EIO; 47831da177e4SLinus Torvalds } 47841da177e4SLinus Torvalds 4785bb8b27e5STrond Myklebust static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res) 47861da177e4SLinus Torvalds { 47878687b63aSAl Viro __be32 *p; 47881da177e4SLinus Torvalds uint32_t opnum; 47891da177e4SLinus Torvalds int32_t nfserr; 47901da177e4SLinus Torvalds 4791c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4792c0eae66eSBenny Halevy if (unlikely(!p)) 4793c0eae66eSBenny Halevy goto out_overflow; 47946f723f77SBenny Halevy opnum = be32_to_cpup(p++); 47951da177e4SLinus Torvalds if (opnum != OP_SETCLIENTID) { 4796fe82a183SChuck Lever dprintk("nfs: decode_setclientid: Server returned operation" 47971da177e4SLinus Torvalds " %d\n", opnum); 47981da177e4SLinus Torvalds return -EIO; 47991da177e4SLinus Torvalds } 4800cccddf4fSBenny Halevy nfserr = be32_to_cpup(p); 48011da177e4SLinus Torvalds if (nfserr == NFS_OK) { 4802c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE); 4803c0eae66eSBenny Halevy if (unlikely(!p)) 4804c0eae66eSBenny Halevy goto out_overflow; 4805bb8b27e5STrond Myklebust p = xdr_decode_hyper(p, &res->clientid); 4806bb8b27e5STrond Myklebust memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE); 48071da177e4SLinus Torvalds } else if (nfserr == NFSERR_CLID_INUSE) { 48081da177e4SLinus Torvalds uint32_t len; 48091da177e4SLinus Torvalds 48101da177e4SLinus Torvalds /* skip netid string */ 4811c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4812c0eae66eSBenny Halevy if (unlikely(!p)) 4813c0eae66eSBenny Halevy goto out_overflow; 4814cccddf4fSBenny Halevy len = be32_to_cpup(p); 4815c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 4816c0eae66eSBenny Halevy if (unlikely(!p)) 4817c0eae66eSBenny Halevy goto out_overflow; 48181da177e4SLinus Torvalds 48191da177e4SLinus Torvalds /* skip uaddr string */ 4820c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4821c0eae66eSBenny Halevy if (unlikely(!p)) 4822c0eae66eSBenny Halevy goto out_overflow; 4823cccddf4fSBenny Halevy len = be32_to_cpup(p); 4824c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 4825c0eae66eSBenny Halevy if (unlikely(!p)) 4826c0eae66eSBenny Halevy goto out_overflow; 48271da177e4SLinus Torvalds return -NFSERR_CLID_INUSE; 48281da177e4SLinus Torvalds } else 4829856dff3dSBenny Halevy return nfs4_stat_to_errno(nfserr); 48301da177e4SLinus Torvalds 48311da177e4SLinus Torvalds return 0; 4832c0eae66eSBenny Halevy out_overflow: 4833c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4834c0eae66eSBenny Halevy return -EIO; 48351da177e4SLinus Torvalds } 48361da177e4SLinus Torvalds 48371da177e4SLinus Torvalds static int decode_setclientid_confirm(struct xdr_stream *xdr) 48381da177e4SLinus Torvalds { 48391da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM); 48401da177e4SLinus Torvalds } 48411da177e4SLinus Torvalds 48421da177e4SLinus Torvalds static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res) 48431da177e4SLinus Torvalds { 48448687b63aSAl Viro __be32 *p; 48451da177e4SLinus Torvalds int status; 48461da177e4SLinus Torvalds 48471da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_WRITE); 48481da177e4SLinus Torvalds if (status) 48491da177e4SLinus Torvalds return status; 48501da177e4SLinus Torvalds 4851c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 16); 4852c0eae66eSBenny Halevy if (unlikely(!p)) 4853c0eae66eSBenny Halevy goto out_overflow; 48546f723f77SBenny Halevy res->count = be32_to_cpup(p++); 48556f723f77SBenny Halevy res->verf->committed = be32_to_cpup(p++); 485699398d06SBenny Halevy memcpy(res->verf->verifier, p, 8); 48571da177e4SLinus Torvalds return 0; 4858c0eae66eSBenny Halevy out_overflow: 4859c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4860c0eae66eSBenny Halevy return -EIO; 48611da177e4SLinus Torvalds } 48621da177e4SLinus Torvalds 48631da177e4SLinus Torvalds static int decode_delegreturn(struct xdr_stream *xdr) 48641da177e4SLinus Torvalds { 48651da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_DELEGRETURN); 48661da177e4SLinus Torvalds } 48671da177e4SLinus Torvalds 48685a5ea0d4SBryan Schumaker static int decode_secinfo_gss(struct xdr_stream *xdr, struct nfs4_secinfo_flavor *flavor) 48695a5ea0d4SBryan Schumaker { 48705a5ea0d4SBryan Schumaker __be32 *p; 48715a5ea0d4SBryan Schumaker 48725a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 4); 48735a5ea0d4SBryan Schumaker if (unlikely(!p)) 48745a5ea0d4SBryan Schumaker goto out_overflow; 48755a5ea0d4SBryan Schumaker flavor->gss.sec_oid4.len = be32_to_cpup(p); 48765a5ea0d4SBryan Schumaker if (flavor->gss.sec_oid4.len > GSS_OID_MAX_LEN) 48775a5ea0d4SBryan Schumaker goto out_err; 48785a5ea0d4SBryan Schumaker 48795a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, flavor->gss.sec_oid4.len); 48805a5ea0d4SBryan Schumaker if (unlikely(!p)) 48815a5ea0d4SBryan Schumaker goto out_overflow; 48825a5ea0d4SBryan Schumaker memcpy(flavor->gss.sec_oid4.data, p, flavor->gss.sec_oid4.len); 48835a5ea0d4SBryan Schumaker 48845a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 8); 48855a5ea0d4SBryan Schumaker if (unlikely(!p)) 48865a5ea0d4SBryan Schumaker goto out_overflow; 48875a5ea0d4SBryan Schumaker flavor->gss.qop4 = be32_to_cpup(p++); 48885a5ea0d4SBryan Schumaker flavor->gss.service = be32_to_cpup(p); 48895a5ea0d4SBryan Schumaker 48905a5ea0d4SBryan Schumaker return 0; 48915a5ea0d4SBryan Schumaker 48925a5ea0d4SBryan Schumaker out_overflow: 48935a5ea0d4SBryan Schumaker print_overflow_msg(__func__, xdr); 48945a5ea0d4SBryan Schumaker return -EIO; 48955a5ea0d4SBryan Schumaker out_err: 48965a5ea0d4SBryan Schumaker return -EINVAL; 48975a5ea0d4SBryan Schumaker } 48985a5ea0d4SBryan Schumaker 48995a5ea0d4SBryan Schumaker static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) 49005a5ea0d4SBryan Schumaker { 49015a5ea0d4SBryan Schumaker struct nfs4_secinfo_flavor *sec_flavor; 49025a5ea0d4SBryan Schumaker int status; 49035a5ea0d4SBryan Schumaker __be32 *p; 4904c3dfc280SBryan Schumaker int i, num_flavors; 49055a5ea0d4SBryan Schumaker 49065a5ea0d4SBryan Schumaker status = decode_op_hdr(xdr, OP_SECINFO); 4907613e901eSBryan Schumaker if (status) 4908613e901eSBryan Schumaker goto out; 49095a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 4); 49105a5ea0d4SBryan Schumaker if (unlikely(!p)) 49115a5ea0d4SBryan Schumaker goto out_overflow; 49125a5ea0d4SBryan Schumaker 4913c3dfc280SBryan Schumaker res->flavors->num_flavors = 0; 4914c3dfc280SBryan Schumaker num_flavors = be32_to_cpup(p); 4915c3dfc280SBryan Schumaker 4916c3dfc280SBryan Schumaker for (i = 0; i < num_flavors; i++) { 49175a5ea0d4SBryan Schumaker sec_flavor = &res->flavors->flavors[i]; 4918c3dfc280SBryan Schumaker if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE) 49195a5ea0d4SBryan Schumaker break; 49205a5ea0d4SBryan Schumaker 49215a5ea0d4SBryan Schumaker p = xdr_inline_decode(xdr, 4); 49225a5ea0d4SBryan Schumaker if (unlikely(!p)) 49235a5ea0d4SBryan Schumaker goto out_overflow; 49245a5ea0d4SBryan Schumaker sec_flavor->flavor = be32_to_cpup(p); 49255a5ea0d4SBryan Schumaker 49265a5ea0d4SBryan Schumaker if (sec_flavor->flavor == RPC_AUTH_GSS) { 4927613e901eSBryan Schumaker status = decode_secinfo_gss(xdr, sec_flavor); 4928613e901eSBryan Schumaker if (status) 4929613e901eSBryan Schumaker goto out; 49305a5ea0d4SBryan Schumaker } 4931c3dfc280SBryan Schumaker res->flavors->num_flavors++; 49325a5ea0d4SBryan Schumaker } 49335a5ea0d4SBryan Schumaker 4934613e901eSBryan Schumaker out: 4935613e901eSBryan Schumaker return status; 49365a5ea0d4SBryan Schumaker out_overflow: 49375a5ea0d4SBryan Schumaker print_overflow_msg(__func__, xdr); 49385a5ea0d4SBryan Schumaker return -EIO; 49395a5ea0d4SBryan Schumaker } 49405a5ea0d4SBryan Schumaker 494199fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 494299fe60d0SBenny Halevy static int decode_exchange_id(struct xdr_stream *xdr, 494399fe60d0SBenny Halevy struct nfs41_exchange_id_res *res) 494499fe60d0SBenny Halevy { 494599fe60d0SBenny Halevy __be32 *p; 494699fe60d0SBenny Halevy uint32_t dummy; 49472460ba57SBenny Halevy char *dummy_str; 494899fe60d0SBenny Halevy int status; 494999fe60d0SBenny Halevy struct nfs_client *clp = res->client; 495099fe60d0SBenny Halevy 495199fe60d0SBenny Halevy status = decode_op_hdr(xdr, OP_EXCHANGE_ID); 495299fe60d0SBenny Halevy if (status) 495399fe60d0SBenny Halevy return status; 495499fe60d0SBenny Halevy 4955c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4956c0eae66eSBenny Halevy if (unlikely(!p)) 4957c0eae66eSBenny Halevy goto out_overflow; 4958114f64b5SAndy Adamson xdr_decode_hyper(p, &clp->cl_clientid); 4959c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 4960c0eae66eSBenny Halevy if (unlikely(!p)) 4961c0eae66eSBenny Halevy goto out_overflow; 49626f723f77SBenny Halevy clp->cl_seqid = be32_to_cpup(p++); 49636f723f77SBenny Halevy clp->cl_exchange_flags = be32_to_cpup(p++); 496499fe60d0SBenny Halevy 496599fe60d0SBenny Halevy /* We ask for SP4_NONE */ 4966cccddf4fSBenny Halevy dummy = be32_to_cpup(p); 496799fe60d0SBenny Halevy if (dummy != SP4_NONE) 496899fe60d0SBenny Halevy return -EIO; 496999fe60d0SBenny Halevy 497099fe60d0SBenny Halevy /* Throw away minor_id */ 4971c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4972c0eae66eSBenny Halevy if (unlikely(!p)) 4973c0eae66eSBenny Halevy goto out_overflow; 497499fe60d0SBenny Halevy 497599fe60d0SBenny Halevy /* Throw away Major id */ 49762460ba57SBenny Halevy status = decode_opaque_inline(xdr, &dummy, &dummy_str); 49772460ba57SBenny Halevy if (unlikely(status)) 49782460ba57SBenny Halevy return status; 497999fe60d0SBenny Halevy 498099fe60d0SBenny Halevy /* Throw away server_scope */ 49812460ba57SBenny Halevy status = decode_opaque_inline(xdr, &dummy, &dummy_str); 49822460ba57SBenny Halevy if (unlikely(status)) 49832460ba57SBenny Halevy return status; 498499fe60d0SBenny Halevy 498599fe60d0SBenny Halevy /* Throw away Implementation id array */ 49862460ba57SBenny Halevy status = decode_opaque_inline(xdr, &dummy, &dummy_str); 49872460ba57SBenny Halevy if (unlikely(status)) 49882460ba57SBenny Halevy return status; 498999fe60d0SBenny Halevy 499099fe60d0SBenny Halevy return 0; 4991c0eae66eSBenny Halevy out_overflow: 4992c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4993c0eae66eSBenny Halevy return -EIO; 499499fe60d0SBenny Halevy } 4995fc931582SAndy Adamson 4996fc931582SAndy Adamson static int decode_chan_attrs(struct xdr_stream *xdr, 4997fc931582SAndy Adamson struct nfs4_channel_attrs *attrs) 4998fc931582SAndy Adamson { 4999fc931582SAndy Adamson __be32 *p; 5000fc931582SAndy Adamson u32 nr_attrs; 5001fc931582SAndy Adamson 5002c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 28); 5003c0eae66eSBenny Halevy if (unlikely(!p)) 5004c0eae66eSBenny Halevy goto out_overflow; 50056f723f77SBenny Halevy attrs->headerpadsz = be32_to_cpup(p++); 50066f723f77SBenny Halevy attrs->max_rqst_sz = be32_to_cpup(p++); 50076f723f77SBenny Halevy attrs->max_resp_sz = be32_to_cpup(p++); 50086f723f77SBenny Halevy attrs->max_resp_sz_cached = be32_to_cpup(p++); 50096f723f77SBenny Halevy attrs->max_ops = be32_to_cpup(p++); 50106f723f77SBenny Halevy attrs->max_reqs = be32_to_cpup(p++); 5011cccddf4fSBenny Halevy nr_attrs = be32_to_cpup(p); 5012fc931582SAndy Adamson if (unlikely(nr_attrs > 1)) { 5013fc931582SAndy Adamson printk(KERN_WARNING "%s: Invalid rdma channel attrs count %u\n", 5014fc931582SAndy Adamson __func__, nr_attrs); 5015fc931582SAndy Adamson return -EINVAL; 5016fc931582SAndy Adamson } 5017c0eae66eSBenny Halevy if (nr_attrs == 1) { 5018c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */ 5019c0eae66eSBenny Halevy if (unlikely(!p)) 5020c0eae66eSBenny Halevy goto out_overflow; 5021c0eae66eSBenny Halevy } 5022fc931582SAndy Adamson return 0; 5023c0eae66eSBenny Halevy out_overflow: 5024c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 5025c0eae66eSBenny Halevy return -EIO; 5026fc931582SAndy Adamson } 5027fc931582SAndy Adamson 5028e78291e4SBenny Halevy static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid) 5029e78291e4SBenny Halevy { 5030e78291e4SBenny Halevy return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN); 5031fc931582SAndy Adamson } 5032fc931582SAndy Adamson 5033fc931582SAndy Adamson static int decode_create_session(struct xdr_stream *xdr, 5034fc931582SAndy Adamson struct nfs41_create_session_res *res) 5035fc931582SAndy Adamson { 5036fc931582SAndy Adamson __be32 *p; 5037fc931582SAndy Adamson int status; 5038fc931582SAndy Adamson struct nfs_client *clp = res->client; 5039fc931582SAndy Adamson struct nfs4_session *session = clp->cl_session; 5040fc931582SAndy Adamson 5041fc931582SAndy Adamson status = decode_op_hdr(xdr, OP_CREATE_SESSION); 5042e78291e4SBenny Halevy if (!status) 5043e78291e4SBenny Halevy status = decode_sessionid(xdr, &session->sess_id); 5044e78291e4SBenny Halevy if (unlikely(status)) 5045fc931582SAndy Adamson return status; 5046fc931582SAndy Adamson 5047fc931582SAndy Adamson /* seqid, flags */ 5048c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 5049c0eae66eSBenny Halevy if (unlikely(!p)) 5050c0eae66eSBenny Halevy goto out_overflow; 50516f723f77SBenny Halevy clp->cl_seqid = be32_to_cpup(p++); 5052cccddf4fSBenny Halevy session->flags = be32_to_cpup(p); 5053fc931582SAndy Adamson 5054fc931582SAndy Adamson /* Channel attributes */ 5055fc931582SAndy Adamson status = decode_chan_attrs(xdr, &session->fc_attrs); 5056fc931582SAndy Adamson if (!status) 5057fc931582SAndy Adamson status = decode_chan_attrs(xdr, &session->bc_attrs); 5058fc931582SAndy Adamson return status; 5059c0eae66eSBenny Halevy out_overflow: 5060c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 5061c0eae66eSBenny Halevy return -EIO; 5062fc931582SAndy Adamson } 50630f3e66c6SAndy Adamson 50640f3e66c6SAndy Adamson static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) 50650f3e66c6SAndy Adamson { 50660f3e66c6SAndy Adamson return decode_op_hdr(xdr, OP_DESTROY_SESSION); 50670f3e66c6SAndy Adamson } 506818019753SRicardo Labiaga 506918019753SRicardo Labiaga static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) 507018019753SRicardo Labiaga { 507118019753SRicardo Labiaga return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); 507218019753SRicardo Labiaga } 507399fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 507499fe60d0SBenny Halevy 50759b7b9fccSAndy Adamson static int decode_sequence(struct xdr_stream *xdr, 50769b7b9fccSAndy Adamson struct nfs4_sequence_res *res, 50779b7b9fccSAndy Adamson struct rpc_rqst *rqstp) 50789b7b9fccSAndy Adamson { 50799b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 5080fc01cea9SAndy Adamson struct nfs4_sessionid id; 5081fc01cea9SAndy Adamson u32 dummy; 5082fc01cea9SAndy Adamson int status; 5083fc01cea9SAndy Adamson __be32 *p; 5084fc01cea9SAndy Adamson 50859b7b9fccSAndy Adamson if (!res->sr_session) 50869b7b9fccSAndy Adamson return 0; 50879b7b9fccSAndy Adamson 5088fc01cea9SAndy Adamson status = decode_op_hdr(xdr, OP_SEQUENCE); 5089e78291e4SBenny Halevy if (!status) 5090e78291e4SBenny Halevy status = decode_sessionid(xdr, &id); 5091e78291e4SBenny Halevy if (unlikely(status)) 5092fc01cea9SAndy Adamson goto out_err; 50939b7b9fccSAndy Adamson 5094fc01cea9SAndy Adamson /* 5095fc01cea9SAndy Adamson * If the server returns different values for sessionID, slotID or 5096fc01cea9SAndy Adamson * sequence number, the server is looney tunes. 5097fc01cea9SAndy Adamson */ 5098fdcb4577STrond Myklebust status = -EREMOTEIO; 5099fc01cea9SAndy Adamson 5100fc01cea9SAndy Adamson if (memcmp(id.data, res->sr_session->sess_id.data, 5101fc01cea9SAndy Adamson NFS4_MAX_SESSIONID_LEN)) { 5102fc01cea9SAndy Adamson dprintk("%s Invalid session id\n", __func__); 5103fc01cea9SAndy Adamson goto out_err; 5104fc01cea9SAndy Adamson } 5105e78291e4SBenny Halevy 5106c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 20); 5107c0eae66eSBenny Halevy if (unlikely(!p)) 5108c0eae66eSBenny Halevy goto out_overflow; 5109e78291e4SBenny Halevy 5110fc01cea9SAndy Adamson /* seqid */ 51116f723f77SBenny Halevy dummy = be32_to_cpup(p++); 5112dfb4f309SBenny Halevy if (dummy != res->sr_slot->seq_nr) { 5113fc01cea9SAndy Adamson dprintk("%s Invalid sequence number\n", __func__); 5114fc01cea9SAndy Adamson goto out_err; 5115fc01cea9SAndy Adamson } 5116fc01cea9SAndy Adamson /* slot id */ 51176f723f77SBenny Halevy dummy = be32_to_cpup(p++); 5118dfb4f309SBenny Halevy if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) { 5119fc01cea9SAndy Adamson dprintk("%s Invalid slot id\n", __func__); 5120fc01cea9SAndy Adamson goto out_err; 5121fc01cea9SAndy Adamson } 5122fc01cea9SAndy Adamson /* highest slot id - currently not processed */ 51236f723f77SBenny Halevy dummy = be32_to_cpup(p++); 5124fc01cea9SAndy Adamson /* target highest slot id - currently not processed */ 51256f723f77SBenny Halevy dummy = be32_to_cpup(p++); 51260629e370SAlexandros Batsakis /* result flags */ 51270629e370SAlexandros Batsakis res->sr_status_flags = be32_to_cpup(p); 5128fc01cea9SAndy Adamson status = 0; 5129fc01cea9SAndy Adamson out_err: 5130fc01cea9SAndy Adamson res->sr_status = status; 5131fc01cea9SAndy Adamson return status; 5132c0eae66eSBenny Halevy out_overflow: 5133c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 5134c0eae66eSBenny Halevy status = -EIO; 5135c0eae66eSBenny Halevy goto out_err; 5136fc01cea9SAndy Adamson #else /* CONFIG_NFS_V4_1 */ 51379b7b9fccSAndy Adamson return 0; 5138fc01cea9SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 51399b7b9fccSAndy Adamson } 51409b7b9fccSAndy Adamson 5141b1f69b75SAndy Adamson #if defined(CONFIG_NFS_V4_1) 5142b1f69b75SAndy Adamson 5143b1f69b75SAndy Adamson static int decode_getdeviceinfo(struct xdr_stream *xdr, 5144b1f69b75SAndy Adamson struct pnfs_device *pdev) 5145b1f69b75SAndy Adamson { 5146b1f69b75SAndy Adamson __be32 *p; 5147b1f69b75SAndy Adamson uint32_t len, type; 5148b1f69b75SAndy Adamson int status; 5149b1f69b75SAndy Adamson 5150b1f69b75SAndy Adamson status = decode_op_hdr(xdr, OP_GETDEVICEINFO); 5151b1f69b75SAndy Adamson if (status) { 5152b1f69b75SAndy Adamson if (status == -ETOOSMALL) { 5153b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4); 5154b1f69b75SAndy Adamson if (unlikely(!p)) 5155b1f69b75SAndy Adamson goto out_overflow; 5156b1f69b75SAndy Adamson pdev->mincount = be32_to_cpup(p); 5157b1f69b75SAndy Adamson dprintk("%s: Min count too small. mincnt = %u\n", 5158b1f69b75SAndy Adamson __func__, pdev->mincount); 5159b1f69b75SAndy Adamson } 5160b1f69b75SAndy Adamson return status; 5161b1f69b75SAndy Adamson } 5162b1f69b75SAndy Adamson 5163b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 8); 5164b1f69b75SAndy Adamson if (unlikely(!p)) 5165b1f69b75SAndy Adamson goto out_overflow; 5166b1f69b75SAndy Adamson type = be32_to_cpup(p++); 5167b1f69b75SAndy Adamson if (type != pdev->layout_type) { 5168b1f69b75SAndy Adamson dprintk("%s: layout mismatch req: %u pdev: %u\n", 5169b1f69b75SAndy Adamson __func__, pdev->layout_type, type); 5170b1f69b75SAndy Adamson return -EINVAL; 5171b1f69b75SAndy Adamson } 5172b1f69b75SAndy Adamson /* 5173b1f69b75SAndy Adamson * Get the length of the opaque device_addr4. xdr_read_pages places 5174b1f69b75SAndy Adamson * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages) 5175b1f69b75SAndy Adamson * and places the remaining xdr data in xdr_buf->tail 5176b1f69b75SAndy Adamson */ 5177b1f69b75SAndy Adamson pdev->mincount = be32_to_cpup(p); 5178b1f69b75SAndy Adamson xdr_read_pages(xdr, pdev->mincount); /* include space for the length */ 5179b1f69b75SAndy Adamson 5180b1f69b75SAndy Adamson /* Parse notification bitmap, verifying that it is zero. */ 5181b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4); 5182b1f69b75SAndy Adamson if (unlikely(!p)) 5183b1f69b75SAndy Adamson goto out_overflow; 5184b1f69b75SAndy Adamson len = be32_to_cpup(p); 5185b1f69b75SAndy Adamson if (len) { 5186ead00597SChuck Lever uint32_t i; 5187b1f69b75SAndy Adamson 5188b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4 * len); 5189b1f69b75SAndy Adamson if (unlikely(!p)) 5190b1f69b75SAndy Adamson goto out_overflow; 5191b1f69b75SAndy Adamson for (i = 0; i < len; i++, p++) { 5192b1f69b75SAndy Adamson if (be32_to_cpup(p)) { 5193b1f69b75SAndy Adamson dprintk("%s: notifications not supported\n", 5194b1f69b75SAndy Adamson __func__); 5195b1f69b75SAndy Adamson return -EIO; 5196b1f69b75SAndy Adamson } 5197b1f69b75SAndy Adamson } 5198b1f69b75SAndy Adamson } 5199b1f69b75SAndy Adamson return 0; 5200b1f69b75SAndy Adamson out_overflow: 5201b1f69b75SAndy Adamson print_overflow_msg(__func__, xdr); 5202b1f69b75SAndy Adamson return -EIO; 5203b1f69b75SAndy Adamson } 5204b1f69b75SAndy Adamson 5205b1f69b75SAndy Adamson static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, 5206b1f69b75SAndy Adamson struct nfs4_layoutget_res *res) 5207b1f69b75SAndy Adamson { 5208b1f69b75SAndy Adamson __be32 *p; 5209b1f69b75SAndy Adamson int status; 5210b1f69b75SAndy Adamson u32 layout_count; 521135124a09SWeston Andros Adamson struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 521235124a09SWeston Andros Adamson struct kvec *iov = rcvbuf->head; 521335124a09SWeston Andros Adamson u32 hdrlen, recvd; 5214b1f69b75SAndy Adamson 5215b1f69b75SAndy Adamson status = decode_op_hdr(xdr, OP_LAYOUTGET); 5216b1f69b75SAndy Adamson if (status) 5217b1f69b75SAndy Adamson return status; 5218b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 8 + NFS4_STATEID_SIZE); 5219b1f69b75SAndy Adamson if (unlikely(!p)) 5220b1f69b75SAndy Adamson goto out_overflow; 5221b1f69b75SAndy Adamson res->return_on_close = be32_to_cpup(p++); 5222b1f69b75SAndy Adamson p = xdr_decode_opaque_fixed(p, res->stateid.data, NFS4_STATEID_SIZE); 5223b1f69b75SAndy Adamson layout_count = be32_to_cpup(p); 5224b1f69b75SAndy Adamson if (!layout_count) { 5225b1f69b75SAndy Adamson dprintk("%s: server responded with empty layout array\n", 5226b1f69b75SAndy Adamson __func__); 5227b1f69b75SAndy Adamson return -EINVAL; 5228b1f69b75SAndy Adamson } 5229b1f69b75SAndy Adamson 523035124a09SWeston Andros Adamson p = xdr_inline_decode(xdr, 28); 5231b1f69b75SAndy Adamson if (unlikely(!p)) 5232b1f69b75SAndy Adamson goto out_overflow; 5233b1f69b75SAndy Adamson p = xdr_decode_hyper(p, &res->range.offset); 5234b1f69b75SAndy Adamson p = xdr_decode_hyper(p, &res->range.length); 5235b1f69b75SAndy Adamson res->range.iomode = be32_to_cpup(p++); 5236b1f69b75SAndy Adamson res->type = be32_to_cpup(p++); 523735124a09SWeston Andros Adamson res->layoutp->len = be32_to_cpup(p); 5238b1f69b75SAndy Adamson 5239b1f69b75SAndy Adamson dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", 5240b1f69b75SAndy Adamson __func__, 5241b1f69b75SAndy Adamson (unsigned long)res->range.offset, 5242b1f69b75SAndy Adamson (unsigned long)res->range.length, 5243b1f69b75SAndy Adamson res->range.iomode, 5244b1f69b75SAndy Adamson res->type, 524535124a09SWeston Andros Adamson res->layoutp->len); 5246b1f69b75SAndy Adamson 524735124a09SWeston Andros Adamson hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; 524835124a09SWeston Andros Adamson recvd = req->rq_rcv_buf.len - hdrlen; 524935124a09SWeston Andros Adamson if (res->layoutp->len > recvd) { 525035124a09SWeston Andros Adamson dprintk("NFS: server cheating in layoutget reply: " 525135124a09SWeston Andros Adamson "layout len %u > recvd %u\n", 525235124a09SWeston Andros Adamson res->layoutp->len, recvd); 525335124a09SWeston Andros Adamson return -EINVAL; 525435124a09SWeston Andros Adamson } 525535124a09SWeston Andros Adamson 525635124a09SWeston Andros Adamson xdr_read_pages(xdr, res->layoutp->len); 5257b1f69b75SAndy Adamson 5258b1f69b75SAndy Adamson if (layout_count > 1) { 5259b1f69b75SAndy Adamson /* We only handle a length one array at the moment. Any 5260b1f69b75SAndy Adamson * further entries are just ignored. Note that this means 5261b1f69b75SAndy Adamson * the client may see a response that is less than the 5262b1f69b75SAndy Adamson * minimum it requested. 5263b1f69b75SAndy Adamson */ 5264b1f69b75SAndy Adamson dprintk("%s: server responded with %d layouts, dropping tail\n", 5265b1f69b75SAndy Adamson __func__, layout_count); 5266b1f69b75SAndy Adamson } 5267b1f69b75SAndy Adamson 5268b1f69b75SAndy Adamson return 0; 5269b1f69b75SAndy Adamson out_overflow: 5270b1f69b75SAndy Adamson print_overflow_msg(__func__, xdr); 5271b1f69b75SAndy Adamson return -EIO; 5272b1f69b75SAndy Adamson } 5273863a3c6cSAndy Adamson 5274cbe82603SBenny Halevy static int decode_layoutreturn(struct xdr_stream *xdr, 5275cbe82603SBenny Halevy struct nfs4_layoutreturn_res *res) 5276cbe82603SBenny Halevy { 5277cbe82603SBenny Halevy __be32 *p; 5278cbe82603SBenny Halevy int status; 5279cbe82603SBenny Halevy 5280cbe82603SBenny Halevy status = decode_op_hdr(xdr, OP_LAYOUTRETURN); 5281cbe82603SBenny Halevy if (status) 5282cbe82603SBenny Halevy return status; 5283cbe82603SBenny Halevy p = xdr_inline_decode(xdr, 4); 5284cbe82603SBenny Halevy if (unlikely(!p)) 5285cbe82603SBenny Halevy goto out_overflow; 5286cbe82603SBenny Halevy res->lrs_present = be32_to_cpup(p); 5287cbe82603SBenny Halevy if (res->lrs_present) 5288cbe82603SBenny Halevy status = decode_stateid(xdr, &res->stateid); 5289cbe82603SBenny Halevy return status; 5290cbe82603SBenny Halevy out_overflow: 5291cbe82603SBenny Halevy print_overflow_msg(__func__, xdr); 5292cbe82603SBenny Halevy return -EIO; 5293cbe82603SBenny Halevy } 5294cbe82603SBenny Halevy 5295863a3c6cSAndy Adamson static int decode_layoutcommit(struct xdr_stream *xdr, 5296863a3c6cSAndy Adamson struct rpc_rqst *req, 5297863a3c6cSAndy Adamson struct nfs4_layoutcommit_res *res) 5298863a3c6cSAndy Adamson { 5299863a3c6cSAndy Adamson __be32 *p; 5300863a3c6cSAndy Adamson __u32 sizechanged; 5301863a3c6cSAndy Adamson int status; 5302863a3c6cSAndy Adamson 5303863a3c6cSAndy Adamson status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); 5304863a3c6cSAndy Adamson if (status) 5305863a3c6cSAndy Adamson return status; 5306863a3c6cSAndy Adamson 5307863a3c6cSAndy Adamson p = xdr_inline_decode(xdr, 4); 5308863a3c6cSAndy Adamson if (unlikely(!p)) 5309863a3c6cSAndy Adamson goto out_overflow; 5310863a3c6cSAndy Adamson sizechanged = be32_to_cpup(p); 5311863a3c6cSAndy Adamson 5312863a3c6cSAndy Adamson if (sizechanged) { 5313863a3c6cSAndy Adamson /* throw away new size */ 5314863a3c6cSAndy Adamson p = xdr_inline_decode(xdr, 8); 5315863a3c6cSAndy Adamson if (unlikely(!p)) 5316863a3c6cSAndy Adamson goto out_overflow; 5317863a3c6cSAndy Adamson } 5318863a3c6cSAndy Adamson return 0; 5319863a3c6cSAndy Adamson out_overflow: 5320863a3c6cSAndy Adamson print_overflow_msg(__func__, xdr); 5321863a3c6cSAndy Adamson return -EIO; 5322863a3c6cSAndy Adamson } 5323b1f69b75SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 5324b1f69b75SAndy Adamson 53251da177e4SLinus Torvalds /* 532649c2559eSBenny Halevy * END OF "GENERIC" DECODE ROUTINES. 532749c2559eSBenny Halevy */ 532849c2559eSBenny Halevy 532949c2559eSBenny Halevy /* 53301da177e4SLinus Torvalds * Decode OPEN_DOWNGRADE response 53311da177e4SLinus Torvalds */ 5332bf269551SChuck Lever static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, 5333bf269551SChuck Lever struct xdr_stream *xdr, 5334bf269551SChuck Lever struct nfs_closeres *res) 53351da177e4SLinus Torvalds { 53361da177e4SLinus Torvalds struct compound_hdr hdr; 53371da177e4SLinus Torvalds int status; 53381da177e4SLinus Torvalds 5339bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 53401da177e4SLinus Torvalds if (status) 53411da177e4SLinus Torvalds goto out; 5342bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 53439b7b9fccSAndy Adamson if (status) 53449b7b9fccSAndy Adamson goto out; 5345bf269551SChuck Lever status = decode_putfh(xdr); 53461da177e4SLinus Torvalds if (status) 53471da177e4SLinus Torvalds goto out; 5348bf269551SChuck Lever status = decode_open_downgrade(xdr, res); 5349516a6af6STrond Myklebust if (status != 0) 5350516a6af6STrond Myklebust goto out; 5351bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 535280e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 53531da177e4SLinus Torvalds out: 53541da177e4SLinus Torvalds return status; 53551da177e4SLinus Torvalds } 53561da177e4SLinus Torvalds 53571da177e4SLinus Torvalds /* 53581da177e4SLinus Torvalds * Decode ACCESS response 53591da177e4SLinus Torvalds */ 5360bf269551SChuck Lever static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5361bf269551SChuck Lever struct nfs4_accessres *res) 53621da177e4SLinus Torvalds { 53631da177e4SLinus Torvalds struct compound_hdr hdr; 53641da177e4SLinus Torvalds int status; 53651da177e4SLinus Torvalds 5366bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 53679b7b9fccSAndy Adamson if (status) 53689b7b9fccSAndy Adamson goto out; 5369bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 53709b7b9fccSAndy Adamson if (status) 53711da177e4SLinus Torvalds goto out; 5372bf269551SChuck Lever status = decode_putfh(xdr); 537376b32999STrond Myklebust if (status != 0) 537476b32999STrond Myklebust goto out; 5375bf269551SChuck Lever status = decode_access(xdr, res); 537676b32999STrond Myklebust if (status != 0) 537776b32999STrond Myklebust goto out; 5378bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 537980e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 53801da177e4SLinus Torvalds out: 53811da177e4SLinus Torvalds return status; 53821da177e4SLinus Torvalds } 53831da177e4SLinus Torvalds 53841da177e4SLinus Torvalds /* 53851da177e4SLinus Torvalds * Decode LOOKUP response 53861da177e4SLinus Torvalds */ 5387bf269551SChuck Lever static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5388bf269551SChuck Lever struct nfs4_lookup_res *res) 53891da177e4SLinus Torvalds { 53901da177e4SLinus Torvalds struct compound_hdr hdr; 53911da177e4SLinus Torvalds int status; 53921da177e4SLinus Torvalds 5393bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 53949b7b9fccSAndy Adamson if (status) 53959b7b9fccSAndy Adamson goto out; 5396bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 53979b7b9fccSAndy Adamson if (status) 53981da177e4SLinus Torvalds goto out; 5399bf269551SChuck Lever status = decode_putfh(xdr); 5400bf269551SChuck Lever if (status) 54011da177e4SLinus Torvalds goto out; 5402bf269551SChuck Lever status = decode_lookup(xdr); 5403bf269551SChuck Lever if (status) 54041da177e4SLinus Torvalds goto out; 5405bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 5406bf269551SChuck Lever if (status) 54071da177e4SLinus Torvalds goto out; 5408bf269551SChuck Lever status = decode_getfattr(xdr, res->fattr, res->server 540980e52aceSTrond Myklebust ,!RPC_IS_ASYNC(rqstp->rq_task)); 54101da177e4SLinus Torvalds out: 54111da177e4SLinus Torvalds return status; 54121da177e4SLinus Torvalds } 54131da177e4SLinus Torvalds 54141da177e4SLinus Torvalds /* 54151da177e4SLinus Torvalds * Decode LOOKUP_ROOT response 54161da177e4SLinus Torvalds */ 5417bf269551SChuck Lever static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, 5418bf269551SChuck Lever struct xdr_stream *xdr, 5419bf269551SChuck Lever struct nfs4_lookup_res *res) 54201da177e4SLinus Torvalds { 54211da177e4SLinus Torvalds struct compound_hdr hdr; 54221da177e4SLinus Torvalds int status; 54231da177e4SLinus Torvalds 5424bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 54259b7b9fccSAndy Adamson if (status) 54269b7b9fccSAndy Adamson goto out; 5427bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 54289b7b9fccSAndy Adamson if (status) 54291da177e4SLinus Torvalds goto out; 5430bf269551SChuck Lever status = decode_putrootfh(xdr); 5431bf269551SChuck Lever if (status) 54321da177e4SLinus Torvalds goto out; 5433bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 5434bf269551SChuck Lever if (status == 0) 5435bf269551SChuck Lever status = decode_getfattr(xdr, res->fattr, res->server, 543680e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 54371da177e4SLinus Torvalds out: 54381da177e4SLinus Torvalds return status; 54391da177e4SLinus Torvalds } 54401da177e4SLinus Torvalds 54411da177e4SLinus Torvalds /* 54421da177e4SLinus Torvalds * Decode REMOVE response 54431da177e4SLinus Torvalds */ 5444bf269551SChuck Lever static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5445bf269551SChuck Lever struct nfs_removeres *res) 54461da177e4SLinus Torvalds { 54471da177e4SLinus Torvalds struct compound_hdr hdr; 54481da177e4SLinus Torvalds int status; 54491da177e4SLinus Torvalds 5450bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 54519b7b9fccSAndy Adamson if (status) 54529b7b9fccSAndy Adamson goto out; 5453bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 54549b7b9fccSAndy Adamson if (status) 54551da177e4SLinus Torvalds goto out; 5456bf269551SChuck Lever status = decode_putfh(xdr); 5457bf269551SChuck Lever if (status) 545816e42959STrond Myklebust goto out; 5459bf269551SChuck Lever status = decode_remove(xdr, &res->cinfo); 5460bf269551SChuck Lever if (status) 546116e42959STrond Myklebust goto out; 5462bf269551SChuck Lever decode_getfattr(xdr, res->dir_attr, res->server, 546380e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 54641da177e4SLinus Torvalds out: 54651da177e4SLinus Torvalds return status; 54661da177e4SLinus Torvalds } 54671da177e4SLinus Torvalds 54681da177e4SLinus Torvalds /* 54691da177e4SLinus Torvalds * Decode RENAME response 54701da177e4SLinus Torvalds */ 5471bf269551SChuck Lever static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5472bf269551SChuck Lever struct nfs_renameres *res) 54731da177e4SLinus Torvalds { 54741da177e4SLinus Torvalds struct compound_hdr hdr; 54751da177e4SLinus Torvalds int status; 54761da177e4SLinus Torvalds 5477bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 54789b7b9fccSAndy Adamson if (status) 54799b7b9fccSAndy Adamson goto out; 5480bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 54819b7b9fccSAndy Adamson if (status) 54821da177e4SLinus Torvalds goto out; 5483bf269551SChuck Lever status = decode_putfh(xdr); 5484bf269551SChuck Lever if (status) 54851da177e4SLinus Torvalds goto out; 5486bf269551SChuck Lever status = decode_savefh(xdr); 5487bf269551SChuck Lever if (status) 54881da177e4SLinus Torvalds goto out; 5489bf269551SChuck Lever status = decode_putfh(xdr); 5490bf269551SChuck Lever if (status) 54911da177e4SLinus Torvalds goto out; 5492bf269551SChuck Lever status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo); 5493bf269551SChuck Lever if (status) 54946caf2c82STrond Myklebust goto out; 54956caf2c82STrond Myklebust /* Current FH is target directory */ 5496bf269551SChuck Lever if (decode_getfattr(xdr, res->new_fattr, res->server, 549780e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)) != 0) 54986caf2c82STrond Myklebust goto out; 5499bf269551SChuck Lever status = decode_restorefh(xdr); 5500bf269551SChuck Lever if (status) 55016caf2c82STrond Myklebust goto out; 5502bf269551SChuck Lever decode_getfattr(xdr, res->old_fattr, res->server, 550380e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 55041da177e4SLinus Torvalds out: 55051da177e4SLinus Torvalds return status; 55061da177e4SLinus Torvalds } 55071da177e4SLinus Torvalds 55081da177e4SLinus Torvalds /* 55091da177e4SLinus Torvalds * Decode LINK response 55101da177e4SLinus Torvalds */ 5511bf269551SChuck Lever static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5512bf269551SChuck Lever struct nfs4_link_res *res) 55131da177e4SLinus Torvalds { 55141da177e4SLinus Torvalds struct compound_hdr hdr; 55151da177e4SLinus Torvalds int status; 55161da177e4SLinus Torvalds 5517bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 55189b7b9fccSAndy Adamson if (status) 55199b7b9fccSAndy Adamson goto out; 5520bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 55219b7b9fccSAndy Adamson if (status) 55221da177e4SLinus Torvalds goto out; 5523bf269551SChuck Lever status = decode_putfh(xdr); 5524bf269551SChuck Lever if (status) 55251da177e4SLinus Torvalds goto out; 5526bf269551SChuck Lever status = decode_savefh(xdr); 5527bf269551SChuck Lever if (status) 55281da177e4SLinus Torvalds goto out; 5529bf269551SChuck Lever status = decode_putfh(xdr); 5530bf269551SChuck Lever if (status) 55311da177e4SLinus Torvalds goto out; 5532bf269551SChuck Lever status = decode_link(xdr, &res->cinfo); 5533bf269551SChuck Lever if (status) 553491ba2eeeSTrond Myklebust goto out; 553591ba2eeeSTrond Myklebust /* 553691ba2eeeSTrond Myklebust * Note order: OP_LINK leaves the directory as the current 553791ba2eeeSTrond Myklebust * filehandle. 553891ba2eeeSTrond Myklebust */ 5539bf269551SChuck Lever if (decode_getfattr(xdr, res->dir_attr, res->server, 554080e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)) != 0) 554191ba2eeeSTrond Myklebust goto out; 5542bf269551SChuck Lever status = decode_restorefh(xdr); 5543bf269551SChuck Lever if (status) 554491ba2eeeSTrond Myklebust goto out; 5545bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 554680e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 55471da177e4SLinus Torvalds out: 55481da177e4SLinus Torvalds return status; 55491da177e4SLinus Torvalds } 55501da177e4SLinus Torvalds 55511da177e4SLinus Torvalds /* 55521da177e4SLinus Torvalds * Decode CREATE response 55531da177e4SLinus Torvalds */ 5554bf269551SChuck Lever static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5555bf269551SChuck Lever struct nfs4_create_res *res) 55561da177e4SLinus Torvalds { 55571da177e4SLinus Torvalds struct compound_hdr hdr; 55581da177e4SLinus Torvalds int status; 55591da177e4SLinus Torvalds 5560bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 55619b7b9fccSAndy Adamson if (status) 55629b7b9fccSAndy Adamson goto out; 5563bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 55649b7b9fccSAndy Adamson if (status) 55651da177e4SLinus Torvalds goto out; 5566bf269551SChuck Lever status = decode_putfh(xdr); 5567bf269551SChuck Lever if (status) 55681da177e4SLinus Torvalds goto out; 5569bf269551SChuck Lever status = decode_savefh(xdr); 5570bf269551SChuck Lever if (status) 557156ae19f3STrond Myklebust goto out; 5572bf269551SChuck Lever status = decode_create(xdr, &res->dir_cinfo); 5573bf269551SChuck Lever if (status) 55741da177e4SLinus Torvalds goto out; 5575bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 5576bf269551SChuck Lever if (status) 55771da177e4SLinus Torvalds goto out; 5578bf269551SChuck Lever if (decode_getfattr(xdr, res->fattr, res->server, 557980e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)) != 0) 558056ae19f3STrond Myklebust goto out; 5581bf269551SChuck Lever status = decode_restorefh(xdr); 5582bf269551SChuck Lever if (status) 558356ae19f3STrond Myklebust goto out; 5584bf269551SChuck Lever decode_getfattr(xdr, res->dir_fattr, res->server, 558580e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 55861da177e4SLinus Torvalds out: 55871da177e4SLinus Torvalds return status; 55881da177e4SLinus Torvalds } 55891da177e4SLinus Torvalds 55901da177e4SLinus Torvalds /* 55911da177e4SLinus Torvalds * Decode SYMLINK response 55921da177e4SLinus Torvalds */ 5593bf269551SChuck Lever static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5594bf269551SChuck Lever struct nfs4_create_res *res) 55951da177e4SLinus Torvalds { 5596bf269551SChuck Lever return nfs4_xdr_dec_create(rqstp, xdr, res); 55971da177e4SLinus Torvalds } 55981da177e4SLinus Torvalds 55991da177e4SLinus Torvalds /* 56001da177e4SLinus Torvalds * Decode GETATTR response 56011da177e4SLinus Torvalds */ 5602bf269551SChuck Lever static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5603bf269551SChuck Lever struct nfs4_getattr_res *res) 56041da177e4SLinus Torvalds { 56051da177e4SLinus Torvalds struct compound_hdr hdr; 56061da177e4SLinus Torvalds int status; 56071da177e4SLinus Torvalds 5608bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 56091da177e4SLinus Torvalds if (status) 56101da177e4SLinus Torvalds goto out; 5611bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 56129b7b9fccSAndy Adamson if (status) 56139b7b9fccSAndy Adamson goto out; 5614bf269551SChuck Lever status = decode_putfh(xdr); 56151da177e4SLinus Torvalds if (status) 56161da177e4SLinus Torvalds goto out; 5617bf269551SChuck Lever status = decode_getfattr(xdr, res->fattr, res->server, 561880e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 56191da177e4SLinus Torvalds out: 56201da177e4SLinus Torvalds return status; 56211da177e4SLinus Torvalds } 56221da177e4SLinus Torvalds 562323ec6965SJ. Bruce Fields /* 562423ec6965SJ. Bruce Fields * Encode an SETACL request 562523ec6965SJ. Bruce Fields */ 56269f06c719SChuck Lever static void nfs4_xdr_enc_setacl(struct rpc_rqst *req, struct xdr_stream *xdr, 56279f06c719SChuck Lever struct nfs_setaclargs *args) 562823ec6965SJ. Bruce Fields { 562923ec6965SJ. Bruce Fields struct compound_hdr hdr = { 563066cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 563123ec6965SJ. Bruce Fields }; 563223ec6965SJ. Bruce Fields 56339f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 56349f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 56359f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 56369f06c719SChuck Lever encode_setacl(xdr, args, &hdr); 5637d017931cSAndy Adamson encode_nops(&hdr); 563823ec6965SJ. Bruce Fields } 563905d564feSAndy Adamson 564023ec6965SJ. Bruce Fields /* 564123ec6965SJ. Bruce Fields * Decode SETACL response 564223ec6965SJ. Bruce Fields */ 564323ec6965SJ. Bruce Fields static int 5644bf269551SChuck Lever nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 564573c403a9SBenny Halevy struct nfs_setaclres *res) 564623ec6965SJ. Bruce Fields { 564723ec6965SJ. Bruce Fields struct compound_hdr hdr; 564823ec6965SJ. Bruce Fields int status; 564923ec6965SJ. Bruce Fields 5650bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 565123ec6965SJ. Bruce Fields if (status) 565223ec6965SJ. Bruce Fields goto out; 5653bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 56549b7b9fccSAndy Adamson if (status) 56559b7b9fccSAndy Adamson goto out; 5656bf269551SChuck Lever status = decode_putfh(xdr); 565723ec6965SJ. Bruce Fields if (status) 565823ec6965SJ. Bruce Fields goto out; 5659bf269551SChuck Lever status = decode_setattr(xdr); 566023ec6965SJ. Bruce Fields out: 566123ec6965SJ. Bruce Fields return status; 566223ec6965SJ. Bruce Fields } 56631da177e4SLinus Torvalds 56641da177e4SLinus Torvalds /* 5665029d105eSJ. Bruce Fields * Decode GETACL response 5666029d105eSJ. Bruce Fields */ 5667029d105eSJ. Bruce Fields static int 5668bf269551SChuck Lever nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5669663c79b3SBenny Halevy struct nfs_getaclres *res) 5670029d105eSJ. Bruce Fields { 5671029d105eSJ. Bruce Fields struct compound_hdr hdr; 5672029d105eSJ. Bruce Fields int status; 5673029d105eSJ. Bruce Fields 5674bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 5675029d105eSJ. Bruce Fields if (status) 5676029d105eSJ. Bruce Fields goto out; 5677bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 56789b7b9fccSAndy Adamson if (status) 56799b7b9fccSAndy Adamson goto out; 5680bf269551SChuck Lever status = decode_putfh(xdr); 5681029d105eSJ. Bruce Fields if (status) 5682029d105eSJ. Bruce Fields goto out; 5683bf269551SChuck Lever status = decode_getacl(xdr, rqstp, &res->acl_len); 5684029d105eSJ. Bruce Fields 5685029d105eSJ. Bruce Fields out: 5686029d105eSJ. Bruce Fields return status; 5687029d105eSJ. Bruce Fields } 5688029d105eSJ. Bruce Fields 5689029d105eSJ. Bruce Fields /* 56901da177e4SLinus Torvalds * Decode CLOSE response 56911da177e4SLinus Torvalds */ 5692bf269551SChuck Lever static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5693bf269551SChuck Lever struct nfs_closeres *res) 56941da177e4SLinus Torvalds { 56951da177e4SLinus Torvalds struct compound_hdr hdr; 56961da177e4SLinus Torvalds int status; 56971da177e4SLinus Torvalds 5698bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 56991da177e4SLinus Torvalds if (status) 57001da177e4SLinus Torvalds goto out; 5701bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 57029b7b9fccSAndy Adamson if (status) 57039b7b9fccSAndy Adamson goto out; 5704bf269551SChuck Lever status = decode_putfh(xdr); 57051da177e4SLinus Torvalds if (status) 57061da177e4SLinus Torvalds goto out; 5707bf269551SChuck Lever status = decode_close(xdr, res); 5708516a6af6STrond Myklebust if (status != 0) 5709516a6af6STrond Myklebust goto out; 5710516a6af6STrond Myklebust /* 5711516a6af6STrond Myklebust * Note: Server may do delete on close for this file 5712516a6af6STrond Myklebust * in which case the getattr call will fail with 5713516a6af6STrond Myklebust * an ESTALE error. Shouldn't be a problem, 5714516a6af6STrond Myklebust * though, since fattr->valid will remain unset. 5715516a6af6STrond Myklebust */ 5716bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 571780e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 57181da177e4SLinus Torvalds out: 57191da177e4SLinus Torvalds return status; 57201da177e4SLinus Torvalds } 57211da177e4SLinus Torvalds 57221da177e4SLinus Torvalds /* 57231da177e4SLinus Torvalds * Decode OPEN response 57241da177e4SLinus Torvalds */ 5725bf269551SChuck Lever static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5726bf269551SChuck Lever struct nfs_openres *res) 57271da177e4SLinus Torvalds { 57281da177e4SLinus Torvalds struct compound_hdr hdr; 57291da177e4SLinus Torvalds int status; 57301da177e4SLinus Torvalds 5731bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 57321da177e4SLinus Torvalds if (status) 57331da177e4SLinus Torvalds goto out; 5734bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 57359b7b9fccSAndy Adamson if (status) 57369b7b9fccSAndy Adamson goto out; 5737bf269551SChuck Lever status = decode_putfh(xdr); 57381da177e4SLinus Torvalds if (status) 57391da177e4SLinus Torvalds goto out; 5740bf269551SChuck Lever status = decode_savefh(xdr); 574156ae19f3STrond Myklebust if (status) 574256ae19f3STrond Myklebust goto out; 5743bf269551SChuck Lever status = decode_open(xdr, res); 57441da177e4SLinus Torvalds if (status) 57451da177e4SLinus Torvalds goto out; 5746bf269551SChuck Lever if (decode_getfh(xdr, &res->fh) != 0) 57471da177e4SLinus Torvalds goto out; 5748bf269551SChuck Lever if (decode_getfattr(xdr, res->f_attr, res->server, 574980e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)) != 0) 575056ae19f3STrond Myklebust goto out; 5751bf269551SChuck Lever if (decode_restorefh(xdr) != 0) 575256ae19f3STrond Myklebust goto out; 5753bf269551SChuck Lever decode_getfattr(xdr, res->dir_attr, res->server, 575480e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 57551da177e4SLinus Torvalds out: 57561da177e4SLinus Torvalds return status; 57571da177e4SLinus Torvalds } 57581da177e4SLinus Torvalds 57591da177e4SLinus Torvalds /* 57601da177e4SLinus Torvalds * Decode OPEN_CONFIRM response 57611da177e4SLinus Torvalds */ 5762bf269551SChuck Lever static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, 5763bf269551SChuck Lever struct xdr_stream *xdr, 5764bf269551SChuck Lever struct nfs_open_confirmres *res) 57651da177e4SLinus Torvalds { 57661da177e4SLinus Torvalds struct compound_hdr hdr; 57671da177e4SLinus Torvalds int status; 57681da177e4SLinus Torvalds 5769bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 57701da177e4SLinus Torvalds if (status) 57711da177e4SLinus Torvalds goto out; 5772bf269551SChuck Lever status = decode_putfh(xdr); 57731da177e4SLinus Torvalds if (status) 57741da177e4SLinus Torvalds goto out; 5775bf269551SChuck Lever status = decode_open_confirm(xdr, res); 57761da177e4SLinus Torvalds out: 57771da177e4SLinus Torvalds return status; 57781da177e4SLinus Torvalds } 57791da177e4SLinus Torvalds 57801da177e4SLinus Torvalds /* 57811da177e4SLinus Torvalds * Decode OPEN response 57821da177e4SLinus Torvalds */ 5783bf269551SChuck Lever static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, 5784bf269551SChuck Lever struct xdr_stream *xdr, 5785bf269551SChuck Lever struct nfs_openres *res) 57861da177e4SLinus Torvalds { 57871da177e4SLinus Torvalds struct compound_hdr hdr; 57881da177e4SLinus Torvalds int status; 57891da177e4SLinus Torvalds 5790bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 57911da177e4SLinus Torvalds if (status) 57921da177e4SLinus Torvalds goto out; 5793bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 57949b7b9fccSAndy Adamson if (status) 57959b7b9fccSAndy Adamson goto out; 5796bf269551SChuck Lever status = decode_putfh(xdr); 57971da177e4SLinus Torvalds if (status) 57981da177e4SLinus Torvalds goto out; 5799bf269551SChuck Lever status = decode_open(xdr, res); 5800864472e9STrond Myklebust if (status) 5801864472e9STrond Myklebust goto out; 5802bf269551SChuck Lever decode_getfattr(xdr, res->f_attr, res->server, 580380e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 58041da177e4SLinus Torvalds out: 58051da177e4SLinus Torvalds return status; 58061da177e4SLinus Torvalds } 58071da177e4SLinus Torvalds 58081da177e4SLinus Torvalds /* 58091da177e4SLinus Torvalds * Decode SETATTR response 58101da177e4SLinus Torvalds */ 5811bf269551SChuck Lever static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, 5812bf269551SChuck Lever struct xdr_stream *xdr, 5813bf269551SChuck Lever struct nfs_setattrres *res) 58141da177e4SLinus Torvalds { 58151da177e4SLinus Torvalds struct compound_hdr hdr; 58161da177e4SLinus Torvalds int status; 58171da177e4SLinus Torvalds 5818bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 58191da177e4SLinus Torvalds if (status) 58201da177e4SLinus Torvalds goto out; 5821bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 58229b7b9fccSAndy Adamson if (status) 58239b7b9fccSAndy Adamson goto out; 5824bf269551SChuck Lever status = decode_putfh(xdr); 58251da177e4SLinus Torvalds if (status) 58261da177e4SLinus Torvalds goto out; 5827bf269551SChuck Lever status = decode_setattr(xdr); 58281da177e4SLinus Torvalds if (status) 58291da177e4SLinus Torvalds goto out; 5830bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 583180e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 58321da177e4SLinus Torvalds out: 58331da177e4SLinus Torvalds return status; 58341da177e4SLinus Torvalds } 58351da177e4SLinus Torvalds 58361da177e4SLinus Torvalds /* 58371da177e4SLinus Torvalds * Decode LOCK response 58381da177e4SLinus Torvalds */ 5839bf269551SChuck Lever static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5840bf269551SChuck Lever struct nfs_lock_res *res) 58411da177e4SLinus Torvalds { 58421da177e4SLinus Torvalds struct compound_hdr hdr; 58431da177e4SLinus Torvalds int status; 58441da177e4SLinus Torvalds 5845bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 58461da177e4SLinus Torvalds if (status) 58471da177e4SLinus Torvalds goto out; 5848bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 58499b7b9fccSAndy Adamson if (status) 58509b7b9fccSAndy Adamson goto out; 5851bf269551SChuck Lever status = decode_putfh(xdr); 58521da177e4SLinus Torvalds if (status) 58531da177e4SLinus Torvalds goto out; 5854bf269551SChuck Lever status = decode_lock(xdr, res); 58551da177e4SLinus Torvalds out: 58561da177e4SLinus Torvalds return status; 58571da177e4SLinus Torvalds } 58581da177e4SLinus Torvalds 58591da177e4SLinus Torvalds /* 58601da177e4SLinus Torvalds * Decode LOCKT response 58611da177e4SLinus Torvalds */ 5862bf269551SChuck Lever static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5863bf269551SChuck Lever struct nfs_lockt_res *res) 58641da177e4SLinus Torvalds { 58651da177e4SLinus Torvalds struct compound_hdr hdr; 58661da177e4SLinus Torvalds int status; 58671da177e4SLinus Torvalds 5868bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 58691da177e4SLinus Torvalds if (status) 58701da177e4SLinus Torvalds goto out; 5871bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 58729b7b9fccSAndy Adamson if (status) 58739b7b9fccSAndy Adamson goto out; 5874bf269551SChuck Lever status = decode_putfh(xdr); 58751da177e4SLinus Torvalds if (status) 58761da177e4SLinus Torvalds goto out; 5877bf269551SChuck Lever status = decode_lockt(xdr, res); 58781da177e4SLinus Torvalds out: 58791da177e4SLinus Torvalds return status; 58801da177e4SLinus Torvalds } 58811da177e4SLinus Torvalds 58821da177e4SLinus Torvalds /* 58831da177e4SLinus Torvalds * Decode LOCKU response 58841da177e4SLinus Torvalds */ 5885bf269551SChuck Lever static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5886bf269551SChuck Lever struct nfs_locku_res *res) 58871da177e4SLinus Torvalds { 58881da177e4SLinus Torvalds struct compound_hdr hdr; 58891da177e4SLinus Torvalds int status; 58901da177e4SLinus Torvalds 5891bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 58921da177e4SLinus Torvalds if (status) 58931da177e4SLinus Torvalds goto out; 5894bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 58959b7b9fccSAndy Adamson if (status) 58969b7b9fccSAndy Adamson goto out; 5897bf269551SChuck Lever status = decode_putfh(xdr); 58981da177e4SLinus Torvalds if (status) 58991da177e4SLinus Torvalds goto out; 5900bf269551SChuck Lever status = decode_locku(xdr, res); 59011da177e4SLinus Torvalds out: 59021da177e4SLinus Torvalds return status; 59031da177e4SLinus Torvalds } 59041da177e4SLinus Torvalds 5905bf269551SChuck Lever static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, 5906bf269551SChuck Lever struct xdr_stream *xdr, void *dummy) 5907d3c7b7ccSTrond Myklebust { 5908d3c7b7ccSTrond Myklebust struct compound_hdr hdr; 5909d3c7b7ccSTrond Myklebust int status; 5910d3c7b7ccSTrond Myklebust 5911bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 5912d3c7b7ccSTrond Myklebust if (!status) 5913bf269551SChuck Lever status = decode_release_lockowner(xdr); 5914d3c7b7ccSTrond Myklebust return status; 5915d3c7b7ccSTrond Myklebust } 5916d3c7b7ccSTrond Myklebust 59171da177e4SLinus Torvalds /* 59181da177e4SLinus Torvalds * Decode READLINK response 59191da177e4SLinus Torvalds */ 5920bf269551SChuck Lever static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, 5921bf269551SChuck Lever struct xdr_stream *xdr, 5922f50c7000SBenny Halevy struct nfs4_readlink_res *res) 59231da177e4SLinus Torvalds { 59241da177e4SLinus Torvalds struct compound_hdr hdr; 59251da177e4SLinus Torvalds int status; 59261da177e4SLinus Torvalds 5927bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 59281da177e4SLinus Torvalds if (status) 59291da177e4SLinus Torvalds goto out; 5930bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 59319b7b9fccSAndy Adamson if (status) 59329b7b9fccSAndy Adamson goto out; 5933bf269551SChuck Lever status = decode_putfh(xdr); 59341da177e4SLinus Torvalds if (status) 59351da177e4SLinus Torvalds goto out; 5936bf269551SChuck Lever status = decode_readlink(xdr, rqstp); 59371da177e4SLinus Torvalds out: 59381da177e4SLinus Torvalds return status; 59391da177e4SLinus Torvalds } 59401da177e4SLinus Torvalds 59411da177e4SLinus Torvalds /* 59421da177e4SLinus Torvalds * Decode READDIR response 59431da177e4SLinus Torvalds */ 5944bf269551SChuck Lever static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5945bf269551SChuck Lever struct nfs4_readdir_res *res) 59461da177e4SLinus Torvalds { 59471da177e4SLinus Torvalds struct compound_hdr hdr; 59481da177e4SLinus Torvalds int status; 59491da177e4SLinus Torvalds 5950bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 59511da177e4SLinus Torvalds if (status) 59521da177e4SLinus Torvalds goto out; 5953bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 59549b7b9fccSAndy Adamson if (status) 59559b7b9fccSAndy Adamson goto out; 5956bf269551SChuck Lever status = decode_putfh(xdr); 59571da177e4SLinus Torvalds if (status) 59581da177e4SLinus Torvalds goto out; 5959bf269551SChuck Lever status = decode_readdir(xdr, rqstp, res); 59601da177e4SLinus Torvalds out: 59611da177e4SLinus Torvalds return status; 59621da177e4SLinus Torvalds } 59631da177e4SLinus Torvalds 59641da177e4SLinus Torvalds /* 59651da177e4SLinus Torvalds * Decode Read response 59661da177e4SLinus Torvalds */ 5967bf269551SChuck Lever static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5968bf269551SChuck Lever struct nfs_readres *res) 59691da177e4SLinus Torvalds { 59701da177e4SLinus Torvalds struct compound_hdr hdr; 59711da177e4SLinus Torvalds int status; 59721da177e4SLinus Torvalds 5973bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 59741da177e4SLinus Torvalds if (status) 59751da177e4SLinus Torvalds goto out; 5976bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 59779b7b9fccSAndy Adamson if (status) 59789b7b9fccSAndy Adamson goto out; 5979bf269551SChuck Lever status = decode_putfh(xdr); 59801da177e4SLinus Torvalds if (status) 59811da177e4SLinus Torvalds goto out; 5982bf269551SChuck Lever status = decode_read(xdr, rqstp, res); 59831da177e4SLinus Torvalds if (!status) 59841da177e4SLinus Torvalds status = res->count; 59851da177e4SLinus Torvalds out: 59861da177e4SLinus Torvalds return status; 59871da177e4SLinus Torvalds } 59881da177e4SLinus Torvalds 59891da177e4SLinus Torvalds /* 59901da177e4SLinus Torvalds * Decode WRITE response 59911da177e4SLinus Torvalds */ 5992bf269551SChuck Lever static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5993bf269551SChuck Lever struct nfs_writeres *res) 59941da177e4SLinus Torvalds { 59951da177e4SLinus Torvalds struct compound_hdr hdr; 59961da177e4SLinus Torvalds int status; 59971da177e4SLinus Torvalds 5998bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 59991da177e4SLinus Torvalds if (status) 60001da177e4SLinus Torvalds goto out; 6001bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 60029b7b9fccSAndy Adamson if (status) 60039b7b9fccSAndy Adamson goto out; 6004bf269551SChuck Lever status = decode_putfh(xdr); 60051da177e4SLinus Torvalds if (status) 60061da177e4SLinus Torvalds goto out; 6007bf269551SChuck Lever status = decode_write(xdr, res); 60084f9838c7STrond Myklebust if (status) 60094f9838c7STrond Myklebust goto out; 60107ffd1064SFred Isaman if (res->fattr) 6011bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 601280e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 60131da177e4SLinus Torvalds if (!status) 60141da177e4SLinus Torvalds status = res->count; 60151da177e4SLinus Torvalds out: 60161da177e4SLinus Torvalds return status; 60171da177e4SLinus Torvalds } 60181da177e4SLinus Torvalds 60191da177e4SLinus Torvalds /* 60201da177e4SLinus Torvalds * Decode COMMIT response 60211da177e4SLinus Torvalds */ 6022bf269551SChuck Lever static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6023bf269551SChuck Lever struct nfs_writeres *res) 60241da177e4SLinus Torvalds { 60251da177e4SLinus Torvalds struct compound_hdr hdr; 60261da177e4SLinus Torvalds int status; 60271da177e4SLinus Torvalds 6028bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 60291da177e4SLinus Torvalds if (status) 60301da177e4SLinus Torvalds goto out; 6031bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 60329b7b9fccSAndy Adamson if (status) 60339b7b9fccSAndy Adamson goto out; 6034bf269551SChuck Lever status = decode_putfh(xdr); 60351da177e4SLinus Torvalds if (status) 60361da177e4SLinus Torvalds goto out; 6037bf269551SChuck Lever status = decode_commit(xdr, res); 60384f9838c7STrond Myklebust if (status) 60394f9838c7STrond Myklebust goto out; 6040988b6dceSFred Isaman if (res->fattr) 6041bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 604280e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 60431da177e4SLinus Torvalds out: 60441da177e4SLinus Torvalds return status; 60451da177e4SLinus Torvalds } 60461da177e4SLinus Torvalds 60471da177e4SLinus Torvalds /* 60488b173218SRicardo Labiaga * Decode FSINFO response 60491da177e4SLinus Torvalds */ 6050bf269551SChuck Lever static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, 60513dda5e43SBenny Halevy struct nfs4_fsinfo_res *res) 60521da177e4SLinus Torvalds { 60531da177e4SLinus Torvalds struct compound_hdr hdr; 60541da177e4SLinus Torvalds int status; 60551da177e4SLinus Torvalds 6056bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 60571da177e4SLinus Torvalds if (!status) 6058bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 60599b7b9fccSAndy Adamson if (!status) 6060bf269551SChuck Lever status = decode_putfh(xdr); 60611da177e4SLinus Torvalds if (!status) 6062bf269551SChuck Lever status = decode_fsinfo(xdr, res->fsinfo); 60631da177e4SLinus Torvalds return status; 60641da177e4SLinus Torvalds } 60651da177e4SLinus Torvalds 60661da177e4SLinus Torvalds /* 60678b173218SRicardo Labiaga * Decode PATHCONF response 60681da177e4SLinus Torvalds */ 6069bf269551SChuck Lever static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, 6070d45b2989SBenny Halevy struct nfs4_pathconf_res *res) 60711da177e4SLinus Torvalds { 60721da177e4SLinus Torvalds struct compound_hdr hdr; 60731da177e4SLinus Torvalds int status; 60741da177e4SLinus Torvalds 6075bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 60761da177e4SLinus Torvalds if (!status) 6077bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 60789b7b9fccSAndy Adamson if (!status) 6079bf269551SChuck Lever status = decode_putfh(xdr); 60801da177e4SLinus Torvalds if (!status) 6081bf269551SChuck Lever status = decode_pathconf(xdr, res->pathconf); 60821da177e4SLinus Torvalds return status; 60831da177e4SLinus Torvalds } 60841da177e4SLinus Torvalds 60851da177e4SLinus Torvalds /* 60868b173218SRicardo Labiaga * Decode STATFS response 60871da177e4SLinus Torvalds */ 6088bf269551SChuck Lever static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, 608924ad148aSBenny Halevy struct nfs4_statfs_res *res) 60901da177e4SLinus Torvalds { 60911da177e4SLinus Torvalds struct compound_hdr hdr; 60921da177e4SLinus Torvalds int status; 60931da177e4SLinus Torvalds 6094bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 60951da177e4SLinus Torvalds if (!status) 6096bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 60979b7b9fccSAndy Adamson if (!status) 6098bf269551SChuck Lever status = decode_putfh(xdr); 60991da177e4SLinus Torvalds if (!status) 6100bf269551SChuck Lever status = decode_statfs(xdr, res->fsstat); 61011da177e4SLinus Torvalds return status; 61021da177e4SLinus Torvalds } 61031da177e4SLinus Torvalds 61041da177e4SLinus Torvalds /* 61058b173218SRicardo Labiaga * Decode GETATTR_BITMAP response 61061da177e4SLinus Torvalds */ 6107bf269551SChuck Lever static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, 6108bf269551SChuck Lever struct xdr_stream *xdr, 6109bf269551SChuck Lever struct nfs4_server_caps_res *res) 61101da177e4SLinus Torvalds { 61111da177e4SLinus Torvalds struct compound_hdr hdr; 61121da177e4SLinus Torvalds int status; 61131da177e4SLinus Torvalds 6114bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 61159b7b9fccSAndy Adamson if (status) 61169b7b9fccSAndy Adamson goto out; 6117bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 61189b7b9fccSAndy Adamson if (status) 61191da177e4SLinus Torvalds goto out; 6120bf269551SChuck Lever status = decode_putfh(xdr); 6121bf269551SChuck Lever if (status) 61221da177e4SLinus Torvalds goto out; 6123bf269551SChuck Lever status = decode_server_caps(xdr, res); 61241da177e4SLinus Torvalds out: 61251da177e4SLinus Torvalds return status; 61261da177e4SLinus Torvalds } 61271da177e4SLinus Torvalds 61281da177e4SLinus Torvalds /* 61291da177e4SLinus Torvalds * Decode RENEW response 61301da177e4SLinus Torvalds */ 6131bf269551SChuck Lever static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 6132bf269551SChuck Lever void *__unused) 61331da177e4SLinus Torvalds { 61341da177e4SLinus Torvalds struct compound_hdr hdr; 61351da177e4SLinus Torvalds int status; 61361da177e4SLinus Torvalds 6137bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 61381da177e4SLinus Torvalds if (!status) 6139bf269551SChuck Lever status = decode_renew(xdr); 61401da177e4SLinus Torvalds return status; 61411da177e4SLinus Torvalds } 61421da177e4SLinus Torvalds 61431da177e4SLinus Torvalds /* 61448b173218SRicardo Labiaga * Decode SETCLIENTID response 61451da177e4SLinus Torvalds */ 6146bf269551SChuck Lever static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, 6147bf269551SChuck Lever struct xdr_stream *xdr, 6148bb8b27e5STrond Myklebust struct nfs4_setclientid_res *res) 61491da177e4SLinus Torvalds { 61501da177e4SLinus Torvalds struct compound_hdr hdr; 61511da177e4SLinus Torvalds int status; 61521da177e4SLinus Torvalds 6153bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 61541da177e4SLinus Torvalds if (!status) 6155bf269551SChuck Lever status = decode_setclientid(xdr, res); 61561da177e4SLinus Torvalds return status; 61571da177e4SLinus Torvalds } 61581da177e4SLinus Torvalds 61591da177e4SLinus Torvalds /* 61608b173218SRicardo Labiaga * Decode SETCLIENTID_CONFIRM response 61611da177e4SLinus Torvalds */ 6162bf269551SChuck Lever static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, 6163bf269551SChuck Lever struct xdr_stream *xdr, 6164bf269551SChuck Lever struct nfs_fsinfo *fsinfo) 61651da177e4SLinus Torvalds { 61661da177e4SLinus Torvalds struct compound_hdr hdr; 61671da177e4SLinus Torvalds int status; 61681da177e4SLinus Torvalds 6169bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 61701da177e4SLinus Torvalds if (!status) 6171bf269551SChuck Lever status = decode_setclientid_confirm(xdr); 61721da177e4SLinus Torvalds if (!status) 6173bf269551SChuck Lever status = decode_putrootfh(xdr); 61741da177e4SLinus Torvalds if (!status) 6175bf269551SChuck Lever status = decode_fsinfo(xdr, fsinfo); 61761da177e4SLinus Torvalds return status; 61771da177e4SLinus Torvalds } 61781da177e4SLinus Torvalds 61791da177e4SLinus Torvalds /* 61808b173218SRicardo Labiaga * Decode DELEGRETURN response 61811da177e4SLinus Torvalds */ 6182bf269551SChuck Lever static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, 6183bf269551SChuck Lever struct xdr_stream *xdr, 6184bf269551SChuck Lever struct nfs4_delegreturnres *res) 61851da177e4SLinus Torvalds { 61861da177e4SLinus Torvalds struct compound_hdr hdr; 61871da177e4SLinus Torvalds int status; 61881da177e4SLinus Torvalds 6189bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 61909b7b9fccSAndy Adamson if (status) 61919b7b9fccSAndy Adamson goto out; 6192bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 61939b7b9fccSAndy Adamson if (status) 6194fa178f29STrond Myklebust goto out; 6195bf269551SChuck Lever status = decode_putfh(xdr); 6196fa178f29STrond Myklebust if (status != 0) 6197fa178f29STrond Myklebust goto out; 6198bf269551SChuck Lever status = decode_delegreturn(xdr); 6199556ae3bbSJeff Layton if (status != 0) 6200556ae3bbSJeff Layton goto out; 6201bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 620280e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 6203fa178f29STrond Myklebust out: 62041da177e4SLinus Torvalds return status; 62051da177e4SLinus Torvalds } 62061da177e4SLinus Torvalds 6207683b57b4STrond Myklebust /* 62088b173218SRicardo Labiaga * Decode FS_LOCATIONS response 6209683b57b4STrond Myklebust */ 6210bf269551SChuck Lever static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, 6211bf269551SChuck Lever struct xdr_stream *xdr, 621222958463SBenny Halevy struct nfs4_fs_locations_res *res) 6213683b57b4STrond Myklebust { 6214683b57b4STrond Myklebust struct compound_hdr hdr; 6215683b57b4STrond Myklebust int status; 6216683b57b4STrond Myklebust 6217bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 62189b7b9fccSAndy Adamson if (status) 62199b7b9fccSAndy Adamson goto out; 6220bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 62219b7b9fccSAndy Adamson if (status) 6222683b57b4STrond Myklebust goto out; 6223bf269551SChuck Lever status = decode_putfh(xdr); 6224bf269551SChuck Lever if (status) 6225683b57b4STrond Myklebust goto out; 6226bf269551SChuck Lever status = decode_lookup(xdr); 6227bf269551SChuck Lever if (status) 6228683b57b4STrond Myklebust goto out; 6229bf269551SChuck Lever xdr_enter_page(xdr, PAGE_SIZE); 6230bf269551SChuck Lever status = decode_getfattr(xdr, &res->fs_locations->fattr, 623180e52aceSTrond Myklebust res->fs_locations->server, 623280e52aceSTrond Myklebust !RPC_IS_ASYNC(req->rq_task)); 6233683b57b4STrond Myklebust out: 6234683b57b4STrond Myklebust return status; 6235683b57b4STrond Myklebust } 6236683b57b4STrond Myklebust 62375a5ea0d4SBryan Schumaker /* 62385a5ea0d4SBryan Schumaker * Decode SECINFO response 62395a5ea0d4SBryan Schumaker */ 62405a5ea0d4SBryan Schumaker static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp, 62415a5ea0d4SBryan Schumaker struct xdr_stream *xdr, 62425a5ea0d4SBryan Schumaker struct nfs4_secinfo_res *res) 62435a5ea0d4SBryan Schumaker { 62445a5ea0d4SBryan Schumaker struct compound_hdr hdr; 62455a5ea0d4SBryan Schumaker int status; 62465a5ea0d4SBryan Schumaker 62475a5ea0d4SBryan Schumaker status = decode_compound_hdr(xdr, &hdr); 62485a5ea0d4SBryan Schumaker if (status) 62495a5ea0d4SBryan Schumaker goto out; 62505a5ea0d4SBryan Schumaker status = decode_sequence(xdr, &res->seq_res, rqstp); 62515a5ea0d4SBryan Schumaker if (status) 62525a5ea0d4SBryan Schumaker goto out; 62535a5ea0d4SBryan Schumaker status = decode_putfh(xdr); 62545a5ea0d4SBryan Schumaker if (status) 62555a5ea0d4SBryan Schumaker goto out; 62565a5ea0d4SBryan Schumaker status = decode_secinfo(xdr, res); 62575a5ea0d4SBryan Schumaker if (status) 62585a5ea0d4SBryan Schumaker goto out; 62595a5ea0d4SBryan Schumaker out: 62605a5ea0d4SBryan Schumaker return status; 62615a5ea0d4SBryan Schumaker } 62625a5ea0d4SBryan Schumaker 626399fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 626499fe60d0SBenny Halevy /* 62658b173218SRicardo Labiaga * Decode EXCHANGE_ID response 626699fe60d0SBenny Halevy */ 6267bf269551SChuck Lever static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, 6268bf269551SChuck Lever struct xdr_stream *xdr, 626999fe60d0SBenny Halevy void *res) 627099fe60d0SBenny Halevy { 627199fe60d0SBenny Halevy struct compound_hdr hdr; 627299fe60d0SBenny Halevy int status; 627399fe60d0SBenny Halevy 6274bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 627599fe60d0SBenny Halevy if (!status) 6276bf269551SChuck Lever status = decode_exchange_id(xdr, res); 627799fe60d0SBenny Halevy return status; 627899fe60d0SBenny Halevy } 62792050f0ccSAndy Adamson 62802050f0ccSAndy Adamson /* 62818b173218SRicardo Labiaga * Decode CREATE_SESSION response 6282fc931582SAndy Adamson */ 6283bf269551SChuck Lever static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, 6284bf269551SChuck Lever struct xdr_stream *xdr, 6285fc931582SAndy Adamson struct nfs41_create_session_res *res) 6286fc931582SAndy Adamson { 6287fc931582SAndy Adamson struct compound_hdr hdr; 6288fc931582SAndy Adamson int status; 6289fc931582SAndy Adamson 6290bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6291fc931582SAndy Adamson if (!status) 6292bf269551SChuck Lever status = decode_create_session(xdr, res); 6293fc931582SAndy Adamson return status; 6294fc931582SAndy Adamson } 6295fc931582SAndy Adamson 6296fc931582SAndy Adamson /* 62978b173218SRicardo Labiaga * Decode DESTROY_SESSION response 62980f3e66c6SAndy Adamson */ 6299bf269551SChuck Lever static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, 6300bf269551SChuck Lever struct xdr_stream *xdr, 6301bf269551SChuck Lever void *res) 63020f3e66c6SAndy Adamson { 63030f3e66c6SAndy Adamson struct compound_hdr hdr; 63040f3e66c6SAndy Adamson int status; 63050f3e66c6SAndy Adamson 6306bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 63070f3e66c6SAndy Adamson if (!status) 6308bf269551SChuck Lever status = decode_destroy_session(xdr, res); 63090f3e66c6SAndy Adamson return status; 63100f3e66c6SAndy Adamson } 63110f3e66c6SAndy Adamson 63120f3e66c6SAndy Adamson /* 63138b173218SRicardo Labiaga * Decode SEQUENCE response 6314fc01cea9SAndy Adamson */ 6315bf269551SChuck Lever static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, 6316bf269551SChuck Lever struct xdr_stream *xdr, 6317fc01cea9SAndy Adamson struct nfs4_sequence_res *res) 6318fc01cea9SAndy Adamson { 6319fc01cea9SAndy Adamson struct compound_hdr hdr; 6320fc01cea9SAndy Adamson int status; 6321fc01cea9SAndy Adamson 6322bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6323fc01cea9SAndy Adamson if (!status) 6324bf269551SChuck Lever status = decode_sequence(xdr, res, rqstp); 6325fc01cea9SAndy Adamson return status; 6326fc01cea9SAndy Adamson } 6327fc01cea9SAndy Adamson 6328fc01cea9SAndy Adamson /* 63298b173218SRicardo Labiaga * Decode GET_LEASE_TIME response 63302050f0ccSAndy Adamson */ 6331bf269551SChuck Lever static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, 6332bf269551SChuck Lever struct xdr_stream *xdr, 63332050f0ccSAndy Adamson struct nfs4_get_lease_time_res *res) 63342050f0ccSAndy Adamson { 63352050f0ccSAndy Adamson struct compound_hdr hdr; 63362050f0ccSAndy Adamson int status; 63372050f0ccSAndy Adamson 6338bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 63392050f0ccSAndy Adamson if (!status) 6340bf269551SChuck Lever status = decode_sequence(xdr, &res->lr_seq_res, rqstp); 63412050f0ccSAndy Adamson if (!status) 6342bf269551SChuck Lever status = decode_putrootfh(xdr); 63432050f0ccSAndy Adamson if (!status) 6344bf269551SChuck Lever status = decode_fsinfo(xdr, res->lr_fsinfo); 63452050f0ccSAndy Adamson return status; 63462050f0ccSAndy Adamson } 634718019753SRicardo Labiaga 634818019753SRicardo Labiaga /* 634918019753SRicardo Labiaga * Decode RECLAIM_COMPLETE response 635018019753SRicardo Labiaga */ 6351bf269551SChuck Lever static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, 6352bf269551SChuck Lever struct xdr_stream *xdr, 635318019753SRicardo Labiaga struct nfs41_reclaim_complete_res *res) 635418019753SRicardo Labiaga { 635518019753SRicardo Labiaga struct compound_hdr hdr; 635618019753SRicardo Labiaga int status; 635718019753SRicardo Labiaga 6358bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 635918019753SRicardo Labiaga if (!status) 6360bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 636118019753SRicardo Labiaga if (!status) 6362bf269551SChuck Lever status = decode_reclaim_complete(xdr, (void *)NULL); 636318019753SRicardo Labiaga return status; 636418019753SRicardo Labiaga } 6365b1f69b75SAndy Adamson 6366b1f69b75SAndy Adamson /* 6367b1f69b75SAndy Adamson * Decode GETDEVINFO response 6368b1f69b75SAndy Adamson */ 6369bf269551SChuck Lever static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, 6370bf269551SChuck Lever struct xdr_stream *xdr, 6371b1f69b75SAndy Adamson struct nfs4_getdeviceinfo_res *res) 6372b1f69b75SAndy Adamson { 6373b1f69b75SAndy Adamson struct compound_hdr hdr; 6374b1f69b75SAndy Adamson int status; 6375b1f69b75SAndy Adamson 6376bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6377b1f69b75SAndy Adamson if (status != 0) 6378b1f69b75SAndy Adamson goto out; 6379bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 6380b1f69b75SAndy Adamson if (status != 0) 6381b1f69b75SAndy Adamson goto out; 6382bf269551SChuck Lever status = decode_getdeviceinfo(xdr, res->pdev); 6383b1f69b75SAndy Adamson out: 6384b1f69b75SAndy Adamson return status; 6385b1f69b75SAndy Adamson } 6386b1f69b75SAndy Adamson 6387b1f69b75SAndy Adamson /* 6388b1f69b75SAndy Adamson * Decode LAYOUTGET response 6389b1f69b75SAndy Adamson */ 6390bf269551SChuck Lever static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, 6391bf269551SChuck Lever struct xdr_stream *xdr, 6392b1f69b75SAndy Adamson struct nfs4_layoutget_res *res) 6393b1f69b75SAndy Adamson { 6394b1f69b75SAndy Adamson struct compound_hdr hdr; 6395b1f69b75SAndy Adamson int status; 6396b1f69b75SAndy Adamson 6397bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6398b1f69b75SAndy Adamson if (status) 6399b1f69b75SAndy Adamson goto out; 6400bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 6401b1f69b75SAndy Adamson if (status) 6402b1f69b75SAndy Adamson goto out; 6403bf269551SChuck Lever status = decode_putfh(xdr); 6404b1f69b75SAndy Adamson if (status) 6405b1f69b75SAndy Adamson goto out; 6406bf269551SChuck Lever status = decode_layoutget(xdr, rqstp, res); 6407b1f69b75SAndy Adamson out: 6408b1f69b75SAndy Adamson return status; 6409b1f69b75SAndy Adamson } 6410863a3c6cSAndy Adamson 6411863a3c6cSAndy Adamson /* 6412cbe82603SBenny Halevy * Decode LAYOUTRETURN response 6413cbe82603SBenny Halevy */ 6414cbe82603SBenny Halevy static int nfs4_xdr_dec_layoutreturn(struct rpc_rqst *rqstp, 6415cbe82603SBenny Halevy struct xdr_stream *xdr, 6416cbe82603SBenny Halevy struct nfs4_layoutreturn_res *res) 6417cbe82603SBenny Halevy { 6418cbe82603SBenny Halevy struct compound_hdr hdr; 6419cbe82603SBenny Halevy int status; 6420cbe82603SBenny Halevy 6421cbe82603SBenny Halevy status = decode_compound_hdr(xdr, &hdr); 6422cbe82603SBenny Halevy if (status) 6423cbe82603SBenny Halevy goto out; 6424cbe82603SBenny Halevy status = decode_sequence(xdr, &res->seq_res, rqstp); 6425cbe82603SBenny Halevy if (status) 6426cbe82603SBenny Halevy goto out; 6427cbe82603SBenny Halevy status = decode_putfh(xdr); 6428cbe82603SBenny Halevy if (status) 6429cbe82603SBenny Halevy goto out; 6430cbe82603SBenny Halevy status = decode_layoutreturn(xdr, res); 6431cbe82603SBenny Halevy out: 6432cbe82603SBenny Halevy return status; 6433cbe82603SBenny Halevy } 6434cbe82603SBenny Halevy 6435cbe82603SBenny Halevy /* 6436863a3c6cSAndy Adamson * Decode LAYOUTCOMMIT response 6437863a3c6cSAndy Adamson */ 6438863a3c6cSAndy Adamson static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, 6439863a3c6cSAndy Adamson struct xdr_stream *xdr, 6440863a3c6cSAndy Adamson struct nfs4_layoutcommit_res *res) 6441863a3c6cSAndy Adamson { 6442863a3c6cSAndy Adamson struct compound_hdr hdr; 6443863a3c6cSAndy Adamson int status; 6444863a3c6cSAndy Adamson 6445863a3c6cSAndy Adamson status = decode_compound_hdr(xdr, &hdr); 6446863a3c6cSAndy Adamson if (status) 6447863a3c6cSAndy Adamson goto out; 6448863a3c6cSAndy Adamson status = decode_sequence(xdr, &res->seq_res, rqstp); 6449863a3c6cSAndy Adamson if (status) 6450863a3c6cSAndy Adamson goto out; 6451863a3c6cSAndy Adamson status = decode_putfh(xdr); 6452863a3c6cSAndy Adamson if (status) 6453863a3c6cSAndy Adamson goto out; 6454863a3c6cSAndy Adamson status = decode_layoutcommit(xdr, rqstp, res); 6455863a3c6cSAndy Adamson if (status) 6456863a3c6cSAndy Adamson goto out; 6457863a3c6cSAndy Adamson decode_getfattr(xdr, res->fattr, res->server, 6458863a3c6cSAndy Adamson !RPC_IS_ASYNC(rqstp->rq_task)); 6459863a3c6cSAndy Adamson out: 6460863a3c6cSAndy Adamson return status; 6461863a3c6cSAndy Adamson } 646299fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 646399fe60d0SBenny Halevy 6464573c4e1eSChuck Lever /** 6465573c4e1eSChuck Lever * nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in 6466573c4e1eSChuck Lever * the local page cache. 6467573c4e1eSChuck Lever * @xdr: XDR stream where entry resides 6468573c4e1eSChuck Lever * @entry: buffer to fill in with entry data 6469573c4e1eSChuck Lever * @plus: boolean indicating whether this should be a readdirplus entry 6470573c4e1eSChuck Lever * 6471573c4e1eSChuck Lever * Returns zero if successful, otherwise a negative errno value is 6472573c4e1eSChuck Lever * returned. 6473573c4e1eSChuck Lever * 6474573c4e1eSChuck Lever * This function is not invoked during READDIR reply decoding, but 6475573c4e1eSChuck Lever * rather whenever an application invokes the getdents(2) system call 6476573c4e1eSChuck Lever * on a directory already in our cache. 6477573c4e1eSChuck Lever */ 6478573c4e1eSChuck Lever int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, 6479573c4e1eSChuck Lever int plus) 64801da177e4SLinus Torvalds { 64811da177e4SLinus Torvalds uint32_t bitmap[2] = {0}; 64821da177e4SLinus Torvalds uint32_t len; 6483babddc72SBryan Schumaker __be32 *p = xdr_inline_decode(xdr, 4); 6484babddc72SBryan Schumaker if (unlikely(!p)) 6485babddc72SBryan Schumaker goto out_overflow; 6486c08e76d0SChuck Lever if (*p == xdr_zero) { 6487babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 4); 6488babddc72SBryan Schumaker if (unlikely(!p)) 6489babddc72SBryan Schumaker goto out_overflow; 6490c08e76d0SChuck Lever if (*p == xdr_zero) 6491573c4e1eSChuck Lever return -EAGAIN; 64921da177e4SLinus Torvalds entry->eof = 1; 6493573c4e1eSChuck Lever return -EBADCOOKIE; 64941da177e4SLinus Torvalds } 64951da177e4SLinus Torvalds 6496babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 12); 6497babddc72SBryan Schumaker if (unlikely(!p)) 6498babddc72SBryan Schumaker goto out_overflow; 64991da177e4SLinus Torvalds entry->prev_cookie = entry->cookie; 65001da177e4SLinus Torvalds p = xdr_decode_hyper(p, &entry->cookie); 6501c08e76d0SChuck Lever entry->len = be32_to_cpup(p); 6502babddc72SBryan Schumaker 65039af8c222STrond Myklebust p = xdr_inline_decode(xdr, entry->len); 6504babddc72SBryan Schumaker if (unlikely(!p)) 6505babddc72SBryan Schumaker goto out_overflow; 65061da177e4SLinus Torvalds entry->name = (const char *) p; 65071da177e4SLinus Torvalds 65081da177e4SLinus Torvalds /* 65091da177e4SLinus Torvalds * In case the server doesn't return an inode number, 65101da177e4SLinus Torvalds * we fake one here. (We don't use inode number 0, 65111da177e4SLinus Torvalds * since glibc seems to choke on it...) 65121da177e4SLinus Torvalds */ 65131da177e4SLinus Torvalds entry->ino = 1; 65144f082222STrond Myklebust entry->fattr->valid = 0; 65151da177e4SLinus Torvalds 65169af8c222STrond Myklebust if (decode_attr_bitmap(xdr, bitmap) < 0) 6517babddc72SBryan Schumaker goto out_overflow; 65189af8c222STrond Myklebust 65199af8c222STrond Myklebust if (decode_attr_length(xdr, &len, &p) < 0) 6520babddc72SBryan Schumaker goto out_overflow; 65219af8c222STrond Myklebust 6522573c4e1eSChuck Lever if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, 6523573c4e1eSChuck Lever entry->server, 1) < 0) 6524babddc72SBryan Schumaker goto out_overflow; 652528331a46STrond Myklebust if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) 652628331a46STrond Myklebust entry->ino = entry->fattr->mounted_on_fileid; 652728331a46STrond Myklebust else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) 652882f2e547SBryan Schumaker entry->ino = entry->fattr->fileid; 65299af8c222STrond Myklebust 65300b26a0bfSTrond Myklebust entry->d_type = DT_UNKNOWN; 65310b26a0bfSTrond Myklebust if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE) 65320b26a0bfSTrond Myklebust entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); 65330b26a0bfSTrond Myklebust 6534573c4e1eSChuck Lever return 0; 6535babddc72SBryan Schumaker 6536babddc72SBryan Schumaker out_overflow: 6537babddc72SBryan Schumaker print_overflow_msg(__func__, xdr); 6538573c4e1eSChuck Lever return -EAGAIN; 65391da177e4SLinus Torvalds } 65401da177e4SLinus Torvalds 65411da177e4SLinus Torvalds /* 65421da177e4SLinus Torvalds * We need to translate between nfs status return values and 65431da177e4SLinus Torvalds * the local errno values which may not be the same. 65441da177e4SLinus Torvalds */ 65451da177e4SLinus Torvalds static struct { 65461da177e4SLinus Torvalds int stat; 65471da177e4SLinus Torvalds int errno; 65481da177e4SLinus Torvalds } nfs_errtbl[] = { 65491da177e4SLinus Torvalds { NFS4_OK, 0 }, 6550856dff3dSBenny Halevy { NFS4ERR_PERM, -EPERM }, 6551856dff3dSBenny Halevy { NFS4ERR_NOENT, -ENOENT }, 6552856dff3dSBenny Halevy { NFS4ERR_IO, -errno_NFSERR_IO}, 6553856dff3dSBenny Halevy { NFS4ERR_NXIO, -ENXIO }, 6554856dff3dSBenny Halevy { NFS4ERR_ACCESS, -EACCES }, 6555856dff3dSBenny Halevy { NFS4ERR_EXIST, -EEXIST }, 6556856dff3dSBenny Halevy { NFS4ERR_XDEV, -EXDEV }, 6557856dff3dSBenny Halevy { NFS4ERR_NOTDIR, -ENOTDIR }, 6558856dff3dSBenny Halevy { NFS4ERR_ISDIR, -EISDIR }, 6559856dff3dSBenny Halevy { NFS4ERR_INVAL, -EINVAL }, 6560856dff3dSBenny Halevy { NFS4ERR_FBIG, -EFBIG }, 6561856dff3dSBenny Halevy { NFS4ERR_NOSPC, -ENOSPC }, 6562856dff3dSBenny Halevy { NFS4ERR_ROFS, -EROFS }, 6563856dff3dSBenny Halevy { NFS4ERR_MLINK, -EMLINK }, 6564856dff3dSBenny Halevy { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG }, 6565856dff3dSBenny Halevy { NFS4ERR_NOTEMPTY, -ENOTEMPTY }, 6566856dff3dSBenny Halevy { NFS4ERR_DQUOT, -EDQUOT }, 6567856dff3dSBenny Halevy { NFS4ERR_STALE, -ESTALE }, 6568856dff3dSBenny Halevy { NFS4ERR_BADHANDLE, -EBADHANDLE }, 6569856dff3dSBenny Halevy { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, 6570856dff3dSBenny Halevy { NFS4ERR_NOTSUPP, -ENOTSUPP }, 6571856dff3dSBenny Halevy { NFS4ERR_TOOSMALL, -ETOOSMALL }, 6572fdcb4577STrond Myklebust { NFS4ERR_SERVERFAULT, -EREMOTEIO }, 6573856dff3dSBenny Halevy { NFS4ERR_BADTYPE, -EBADTYPE }, 6574856dff3dSBenny Halevy { NFS4ERR_LOCKED, -EAGAIN }, 6575856dff3dSBenny Halevy { NFS4ERR_SYMLINK, -ELOOP }, 6576856dff3dSBenny Halevy { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, 6577856dff3dSBenny Halevy { NFS4ERR_DEADLOCK, -EDEADLK }, 6578856dff3dSBenny Halevy { -1, -EIO } 65791da177e4SLinus Torvalds }; 65801da177e4SLinus Torvalds 65811da177e4SLinus Torvalds /* 65821da177e4SLinus Torvalds * Convert an NFS error code to a local one. 65831da177e4SLinus Torvalds * This one is used jointly by NFSv2 and NFSv3. 65841da177e4SLinus Torvalds */ 65851da177e4SLinus Torvalds static int 65860a8ea437SDavid Howells nfs4_stat_to_errno(int stat) 65871da177e4SLinus Torvalds { 65881da177e4SLinus Torvalds int i; 65891da177e4SLinus Torvalds for (i = 0; nfs_errtbl[i].stat != -1; i++) { 65901da177e4SLinus Torvalds if (nfs_errtbl[i].stat == stat) 65911da177e4SLinus Torvalds return nfs_errtbl[i].errno; 65921da177e4SLinus Torvalds } 65931da177e4SLinus Torvalds if (stat <= 10000 || stat > 10100) { 65941da177e4SLinus Torvalds /* The server is looney tunes. */ 6595fdcb4577STrond Myklebust return -EREMOTEIO; 65961da177e4SLinus Torvalds } 65971da177e4SLinus Torvalds /* If we cannot translate the error, the recovery routines should 65981da177e4SLinus Torvalds * handle it. 65991da177e4SLinus Torvalds * Note: remaining NFSv4 error codes have values > 10000, so should 66001da177e4SLinus Torvalds * not conflict with native Linux error codes. 66011da177e4SLinus Torvalds */ 6602856dff3dSBenny Halevy return -stat; 66031da177e4SLinus Torvalds } 66041da177e4SLinus Torvalds 66051da177e4SLinus Torvalds #define PROC(proc, argtype, restype) \ 66061da177e4SLinus Torvalds [NFSPROC4_CLNT_##proc] = { \ 66071da177e4SLinus Torvalds .p_proc = NFSPROC4_COMPOUND, \ 66089f06c719SChuck Lever .p_encode = (kxdreproc_t)nfs4_xdr_##argtype, \ 6609bf269551SChuck Lever .p_decode = (kxdrdproc_t)nfs4_xdr_##restype, \ 66102bea90d4SChuck Lever .p_arglen = NFS4_##argtype##_sz, \ 66112bea90d4SChuck Lever .p_replen = NFS4_##restype##_sz, \ 6612cc0175c1SChuck Lever .p_statidx = NFSPROC4_CLNT_##proc, \ 6613cc0175c1SChuck Lever .p_name = #proc, \ 66141da177e4SLinus Torvalds } 66151da177e4SLinus Torvalds 66161da177e4SLinus Torvalds struct rpc_procinfo nfs4_procedures[] = { 66171da177e4SLinus Torvalds PROC(READ, enc_read, dec_read), 66181da177e4SLinus Torvalds PROC(WRITE, enc_write, dec_write), 66191da177e4SLinus Torvalds PROC(COMMIT, enc_commit, dec_commit), 66201da177e4SLinus Torvalds PROC(OPEN, enc_open, dec_open), 66211da177e4SLinus Torvalds PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm), 66221da177e4SLinus Torvalds PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr), 66231da177e4SLinus Torvalds PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade), 66241da177e4SLinus Torvalds PROC(CLOSE, enc_close, dec_close), 66251da177e4SLinus Torvalds PROC(SETATTR, enc_setattr, dec_setattr), 66261da177e4SLinus Torvalds PROC(FSINFO, enc_fsinfo, dec_fsinfo), 66271da177e4SLinus Torvalds PROC(RENEW, enc_renew, dec_renew), 66281da177e4SLinus Torvalds PROC(SETCLIENTID, enc_setclientid, dec_setclientid), 66291da177e4SLinus Torvalds PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm), 66301da177e4SLinus Torvalds PROC(LOCK, enc_lock, dec_lock), 66311da177e4SLinus Torvalds PROC(LOCKT, enc_lockt, dec_lockt), 66321da177e4SLinus Torvalds PROC(LOCKU, enc_locku, dec_locku), 66331da177e4SLinus Torvalds PROC(ACCESS, enc_access, dec_access), 66341da177e4SLinus Torvalds PROC(GETATTR, enc_getattr, dec_getattr), 66351da177e4SLinus Torvalds PROC(LOOKUP, enc_lookup, dec_lookup), 66361da177e4SLinus Torvalds PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), 66371da177e4SLinus Torvalds PROC(REMOVE, enc_remove, dec_remove), 66381da177e4SLinus Torvalds PROC(RENAME, enc_rename, dec_rename), 66391da177e4SLinus Torvalds PROC(LINK, enc_link, dec_link), 66401da177e4SLinus Torvalds PROC(SYMLINK, enc_symlink, dec_symlink), 66411da177e4SLinus Torvalds PROC(CREATE, enc_create, dec_create), 66421da177e4SLinus Torvalds PROC(PATHCONF, enc_pathconf, dec_pathconf), 66431da177e4SLinus Torvalds PROC(STATFS, enc_statfs, dec_statfs), 66441da177e4SLinus Torvalds PROC(READLINK, enc_readlink, dec_readlink), 66451da177e4SLinus Torvalds PROC(READDIR, enc_readdir, dec_readdir), 66461da177e4SLinus Torvalds PROC(SERVER_CAPS, enc_server_caps, dec_server_caps), 66471da177e4SLinus Torvalds PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), 6648029d105eSJ. Bruce Fields PROC(GETACL, enc_getacl, dec_getacl), 664923ec6965SJ. Bruce Fields PROC(SETACL, enc_setacl, dec_setacl), 6650683b57b4STrond Myklebust PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), 6651d3c7b7ccSTrond Myklebust PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), 66525a5ea0d4SBryan Schumaker PROC(SECINFO, enc_secinfo, dec_secinfo), 665399fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 665499fe60d0SBenny Halevy PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), 6655fc931582SAndy Adamson PROC(CREATE_SESSION, enc_create_session, dec_create_session), 66560f3e66c6SAndy Adamson PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), 6657fc01cea9SAndy Adamson PROC(SEQUENCE, enc_sequence, dec_sequence), 66582050f0ccSAndy Adamson PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), 665918019753SRicardo Labiaga PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), 6660b1f69b75SAndy Adamson PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), 6661b1f69b75SAndy Adamson PROC(LAYOUTGET, enc_layoutget, dec_layoutget), 6662863a3c6cSAndy Adamson PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), 6663cbe82603SBenny Halevy PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), 666499fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 66651da177e4SLinus Torvalds }; 66661da177e4SLinus Torvalds 66671da177e4SLinus Torvalds struct rpc_version nfs_version4 = { 66681da177e4SLinus Torvalds .number = 4, 6669e8c96f8cSTobias Klauser .nrprocs = ARRAY_SIZE(nfs4_procedures), 66701da177e4SLinus Torvalds .procs = nfs4_procedures 66711da177e4SLinus Torvalds }; 66721da177e4SLinus Torvalds 66731da177e4SLinus Torvalds /* 66741da177e4SLinus Torvalds * Local variables: 66751da177e4SLinus Torvalds * c-basic-offset: 8 66761da177e4SLinus Torvalds * End: 66771da177e4SLinus Torvalds */ 6678