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> 491da177e4SLinus Torvalds #include <linux/nfs.h> 501da177e4SLinus Torvalds #include <linux/nfs4.h> 511da177e4SLinus Torvalds #include <linux/nfs_fs.h> 521da177e4SLinus Torvalds #include <linux/nfs_idmap.h> 534ce79717STrond Myklebust #include "nfs4_fs.h" 544882ef72SAlexandros Batsakis #include "internal.h" 55b1f69b75SAndy Adamson #include "pnfs.h" 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds #define NFSDBG_FACILITY NFSDBG_XDR 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds /* Mapping from NFS error code to "errno" error code. */ 601da177e4SLinus Torvalds #define errno_NFSERR_IO EIO 611da177e4SLinus Torvalds 620a8ea437SDavid Howells static int nfs4_stat_to_errno(int); 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds /* NFSv4 COMPOUND tags are only wanted for debugging purposes */ 651da177e4SLinus Torvalds #ifdef DEBUG 661da177e4SLinus Torvalds #define NFS4_MAXTAGLEN 20 671da177e4SLinus Torvalds #else 681da177e4SLinus Torvalds #define NFS4_MAXTAGLEN 0 691da177e4SLinus Torvalds #endif 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds /* lock,open owner id: 729f958ab8STrond Myklebust * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) 731da177e4SLinus Torvalds */ 74d035c36cSTrond Myklebust #define open_owner_id_maxsz (1 + 1 + 4) 75d035c36cSTrond Myklebust #define lock_owner_id_maxsz (1 + 1 + 4) 769104a55dSTrond Myklebust #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 771da177e4SLinus Torvalds #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) 781da177e4SLinus Torvalds #define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) 791da177e4SLinus Torvalds #define op_encode_hdr_maxsz (1) 801da177e4SLinus Torvalds #define op_decode_hdr_maxsz (2) 819104a55dSTrond Myklebust #define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) 829104a55dSTrond Myklebust #define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) 839104a55dSTrond Myklebust #define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) 849104a55dSTrond Myklebust #define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) 851da177e4SLinus Torvalds #define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \ 861da177e4SLinus Torvalds (NFS4_FHSIZE >> 2)) 871da177e4SLinus Torvalds #define decode_putfh_maxsz (op_decode_hdr_maxsz) 881da177e4SLinus Torvalds #define encode_putrootfh_maxsz (op_encode_hdr_maxsz) 891da177e4SLinus Torvalds #define decode_putrootfh_maxsz (op_decode_hdr_maxsz) 901da177e4SLinus Torvalds #define encode_getfh_maxsz (op_encode_hdr_maxsz) 911da177e4SLinus Torvalds #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ 921da177e4SLinus Torvalds ((3+NFS4_FHSIZE) >> 2)) 9396928206SJ. Bruce Fields #define nfs4_fattr_bitmap_maxsz 3 9496928206SJ. Bruce Fields #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) 951da177e4SLinus Torvalds #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) 961da177e4SLinus Torvalds #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) 97bd625ba8STrond Myklebust #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 98bd625ba8STrond Myklebust #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 9996928206SJ. Bruce Fields /* This is based on getfattr, which uses the most attributes: */ 10096928206SJ. Bruce Fields #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ 101bd625ba8STrond Myklebust 3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz)) 10296928206SJ. Bruce Fields #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ 10396928206SJ. Bruce Fields nfs4_fattr_value_maxsz) 10496928206SJ. Bruce Fields #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) 1059104a55dSTrond Myklebust #define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \ 1069104a55dSTrond Myklebust 1 + 2 + 1 + \ 1079104a55dSTrond Myklebust nfs4_owner_maxsz + \ 1089104a55dSTrond Myklebust nfs4_group_maxsz + \ 1099104a55dSTrond Myklebust 4 + 4) 1101da177e4SLinus Torvalds #define encode_savefh_maxsz (op_encode_hdr_maxsz) 1111da177e4SLinus Torvalds #define decode_savefh_maxsz (op_decode_hdr_maxsz) 11256ae19f3STrond Myklebust #define encode_restorefh_maxsz (op_encode_hdr_maxsz) 11356ae19f3STrond Myklebust #define decode_restorefh_maxsz (op_decode_hdr_maxsz) 1142f42b5d0SFred Isaman #define encode_fsinfo_maxsz (encode_getattr_maxsz) 1151da177e4SLinus Torvalds #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) 1161da177e4SLinus Torvalds #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) 1171da177e4SLinus Torvalds #define decode_renew_maxsz (op_decode_hdr_maxsz) 1181da177e4SLinus Torvalds #define encode_setclientid_maxsz \ 1191da177e4SLinus Torvalds (op_encode_hdr_maxsz + \ 120cc38bac3SChuck Lever XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ 121cc38bac3SChuck Lever XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \ 122cc38bac3SChuck Lever 1 /* sc_prog */ + \ 123cc38bac3SChuck Lever XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ 124cc38bac3SChuck Lever XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ 125cc38bac3SChuck Lever 1) /* sc_cb_ident */ 1261da177e4SLinus Torvalds #define decode_setclientid_maxsz \ 1271da177e4SLinus Torvalds (op_decode_hdr_maxsz + \ 1281da177e4SLinus Torvalds 2 + \ 1291da177e4SLinus Torvalds 1024) /* large value for CLID_INUSE */ 1301da177e4SLinus Torvalds #define encode_setclientid_confirm_maxsz \ 1311da177e4SLinus Torvalds (op_encode_hdr_maxsz + \ 1321da177e4SLinus Torvalds 3 + (NFS4_VERIFIER_SIZE >> 2)) 1331da177e4SLinus Torvalds #define decode_setclientid_confirm_maxsz \ 1341da177e4SLinus Torvalds (op_decode_hdr_maxsz) 135e6889620STrond Myklebust #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) 136e6889620STrond Myklebust #define decode_lookup_maxsz (op_decode_hdr_maxsz) 1372cebf828STrond Myklebust #define encode_share_access_maxsz \ 1382cebf828STrond Myklebust (2) 1394882ef72SAlexandros Batsakis #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) 1402cebf828STrond Myklebust #define encode_opentype_maxsz (1 + encode_createmode_maxsz) 1412cebf828STrond Myklebust #define encode_claim_null_maxsz (1 + nfs4_name_maxsz) 1422cebf828STrond Myklebust #define encode_open_maxsz (op_encode_hdr_maxsz + \ 1432cebf828STrond Myklebust 2 + encode_share_access_maxsz + 2 + \ 1442cebf828STrond Myklebust open_owner_id_maxsz + \ 1452cebf828STrond Myklebust encode_opentype_maxsz + \ 1462cebf828STrond Myklebust encode_claim_null_maxsz) 1472cebf828STrond Myklebust #define decode_ace_maxsz (3 + nfs4_owner_maxsz) 1489104a55dSTrond Myklebust #define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \ 1492cebf828STrond Myklebust decode_ace_maxsz) 1502cebf828STrond Myklebust #define decode_change_info_maxsz (5) 1512cebf828STrond Myklebust #define decode_open_maxsz (op_decode_hdr_maxsz + \ 1529104a55dSTrond Myklebust decode_stateid_maxsz + \ 1532cebf828STrond Myklebust decode_change_info_maxsz + 1 + \ 1542cebf828STrond Myklebust nfs4_fattr_bitmap_maxsz + \ 1552cebf828STrond Myklebust decode_delegation_maxsz) 1569104a55dSTrond Myklebust #define encode_open_confirm_maxsz \ 1579104a55dSTrond Myklebust (op_encode_hdr_maxsz + \ 1589104a55dSTrond Myklebust encode_stateid_maxsz + 1) 1599104a55dSTrond Myklebust #define decode_open_confirm_maxsz \ 1609104a55dSTrond Myklebust (op_decode_hdr_maxsz + \ 1619104a55dSTrond Myklebust decode_stateid_maxsz) 1629104a55dSTrond Myklebust #define encode_open_downgrade_maxsz \ 1639104a55dSTrond Myklebust (op_encode_hdr_maxsz + \ 1649104a55dSTrond Myklebust encode_stateid_maxsz + 1 + \ 1659104a55dSTrond Myklebust encode_share_access_maxsz) 1669104a55dSTrond Myklebust #define decode_open_downgrade_maxsz \ 1679104a55dSTrond Myklebust (op_decode_hdr_maxsz + \ 1689104a55dSTrond Myklebust decode_stateid_maxsz) 1699104a55dSTrond Myklebust #define encode_close_maxsz (op_encode_hdr_maxsz + \ 1709104a55dSTrond Myklebust 1 + encode_stateid_maxsz) 1719104a55dSTrond Myklebust #define decode_close_maxsz (op_decode_hdr_maxsz + \ 1729104a55dSTrond Myklebust decode_stateid_maxsz) 1739104a55dSTrond Myklebust #define encode_setattr_maxsz (op_encode_hdr_maxsz + \ 1749104a55dSTrond Myklebust encode_stateid_maxsz + \ 1759104a55dSTrond Myklebust encode_attrs_maxsz) 1769104a55dSTrond Myklebust #define decode_setattr_maxsz (op_decode_hdr_maxsz + \ 1779104a55dSTrond Myklebust nfs4_fattr_bitmap_maxsz) 1789104a55dSTrond Myklebust #define encode_read_maxsz (op_encode_hdr_maxsz + \ 1799104a55dSTrond Myklebust encode_stateid_maxsz + 3) 1809104a55dSTrond Myklebust #define decode_read_maxsz (op_decode_hdr_maxsz + 2) 1819104a55dSTrond Myklebust #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ 1829104a55dSTrond Myklebust 2 + encode_verifier_maxsz + 5) 1839104a55dSTrond Myklebust #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ 1849104a55dSTrond Myklebust decode_verifier_maxsz) 1859104a55dSTrond Myklebust #define encode_readlink_maxsz (op_encode_hdr_maxsz) 1869104a55dSTrond Myklebust #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) 1879104a55dSTrond Myklebust #define encode_write_maxsz (op_encode_hdr_maxsz + \ 1889104a55dSTrond Myklebust encode_stateid_maxsz + 4) 1899104a55dSTrond Myklebust #define decode_write_maxsz (op_decode_hdr_maxsz + \ 1909104a55dSTrond Myklebust 2 + decode_verifier_maxsz) 1919104a55dSTrond Myklebust #define encode_commit_maxsz (op_encode_hdr_maxsz + 3) 1929104a55dSTrond Myklebust #define decode_commit_maxsz (op_decode_hdr_maxsz + \ 1939104a55dSTrond Myklebust decode_verifier_maxsz) 1941da177e4SLinus Torvalds #define encode_remove_maxsz (op_encode_hdr_maxsz + \ 1951da177e4SLinus Torvalds nfs4_name_maxsz) 1966ce18391SBenny Halevy #define decode_remove_maxsz (op_decode_hdr_maxsz + \ 1976ce18391SBenny Halevy decode_change_info_maxsz) 1981da177e4SLinus Torvalds #define encode_rename_maxsz (op_encode_hdr_maxsz + \ 1991da177e4SLinus Torvalds 2 * nfs4_name_maxsz) 2006ce18391SBenny Halevy #define decode_rename_maxsz (op_decode_hdr_maxsz + \ 2016ce18391SBenny Halevy decode_change_info_maxsz + \ 2026ce18391SBenny Halevy decode_change_info_maxsz) 2031da177e4SLinus Torvalds #define encode_link_maxsz (op_encode_hdr_maxsz + \ 2041da177e4SLinus Torvalds nfs4_name_maxsz) 2056ce18391SBenny Halevy #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) 206daccbdedSTrond Myklebust #define encode_lockowner_maxsz (7) 2079104a55dSTrond Myklebust #define encode_lock_maxsz (op_encode_hdr_maxsz + \ 2089104a55dSTrond Myklebust 7 + \ 209daccbdedSTrond Myklebust 1 + encode_stateid_maxsz + 1 + \ 210daccbdedSTrond Myklebust encode_lockowner_maxsz) 2119104a55dSTrond Myklebust #define decode_lock_denied_maxsz \ 2129104a55dSTrond Myklebust (8 + decode_lockowner_maxsz) 2139104a55dSTrond Myklebust #define decode_lock_maxsz (op_decode_hdr_maxsz + \ 2149104a55dSTrond Myklebust decode_lock_denied_maxsz) 215daccbdedSTrond Myklebust #define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \ 216daccbdedSTrond Myklebust encode_lockowner_maxsz) 2179104a55dSTrond Myklebust #define decode_lockt_maxsz (op_decode_hdr_maxsz + \ 2189104a55dSTrond Myklebust decode_lock_denied_maxsz) 2199104a55dSTrond Myklebust #define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \ 2209104a55dSTrond Myklebust encode_stateid_maxsz + \ 2219104a55dSTrond Myklebust 4) 2229104a55dSTrond Myklebust #define decode_locku_maxsz (op_decode_hdr_maxsz + \ 2239104a55dSTrond Myklebust decode_stateid_maxsz) 224d3c7b7ccSTrond Myklebust #define encode_release_lockowner_maxsz \ 225d3c7b7ccSTrond Myklebust (op_encode_hdr_maxsz + \ 226d3c7b7ccSTrond Myklebust encode_lockowner_maxsz) 227d3c7b7ccSTrond Myklebust #define decode_release_lockowner_maxsz \ 228d3c7b7ccSTrond Myklebust (op_decode_hdr_maxsz) 2299104a55dSTrond Myklebust #define encode_access_maxsz (op_encode_hdr_maxsz + 1) 2309104a55dSTrond Myklebust #define decode_access_maxsz (op_decode_hdr_maxsz + 2) 2311da177e4SLinus Torvalds #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ 2321da177e4SLinus Torvalds 1 + nfs4_name_maxsz + \ 23394a6d753SChuck Lever 1 + \ 23496928206SJ. Bruce Fields nfs4_fattr_maxsz) 2351da177e4SLinus Torvalds #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) 2361da177e4SLinus Torvalds #define encode_create_maxsz (op_encode_hdr_maxsz + \ 2379104a55dSTrond Myklebust 1 + 2 + nfs4_name_maxsz + \ 2389104a55dSTrond Myklebust encode_attrs_maxsz) 2392cebf828STrond Myklebust #define decode_create_maxsz (op_decode_hdr_maxsz + \ 2402cebf828STrond Myklebust decode_change_info_maxsz + \ 2412cebf828STrond Myklebust nfs4_fattr_bitmap_maxsz) 2429104a55dSTrond Myklebust #define encode_statfs_maxsz (encode_getattr_maxsz) 2439104a55dSTrond Myklebust #define decode_statfs_maxsz (decode_getattr_maxsz) 2441da177e4SLinus Torvalds #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) 2451da177e4SLinus Torvalds #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) 2469104a55dSTrond Myklebust #define encode_getacl_maxsz (encode_getattr_maxsz) 2479104a55dSTrond Myklebust #define decode_getacl_maxsz (op_decode_hdr_maxsz + \ 2489104a55dSTrond Myklebust nfs4_fattr_bitmap_maxsz + 1) 2499104a55dSTrond Myklebust #define encode_setacl_maxsz (op_encode_hdr_maxsz + \ 2509104a55dSTrond Myklebust encode_stateid_maxsz + 3) 2519104a55dSTrond Myklebust #define decode_setacl_maxsz (decode_setattr_maxsz) 252e6889620STrond Myklebust #define encode_fs_locations_maxsz \ 253e6889620STrond Myklebust (encode_getattr_maxsz) 254e6889620STrond Myklebust #define decode_fs_locations_maxsz \ 255e6889620STrond Myklebust (0) 2569b7b9fccSAndy Adamson 2579b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 258fc931582SAndy Adamson #define NFS4_MAX_MACHINE_NAME_LEN (64) 259fc931582SAndy Adamson 26099fe60d0SBenny Halevy #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ 26199fe60d0SBenny Halevy encode_verifier_maxsz + \ 26299fe60d0SBenny Halevy 1 /* co_ownerid.len */ + \ 26399fe60d0SBenny Halevy XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \ 26499fe60d0SBenny Halevy 1 /* flags */ + \ 26599fe60d0SBenny Halevy 1 /* spa_how */ + \ 26699fe60d0SBenny Halevy 0 /* SP4_NONE (for now) */ + \ 26799fe60d0SBenny Halevy 1 /* zero implemetation id array */) 26899fe60d0SBenny Halevy #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \ 26999fe60d0SBenny Halevy 2 /* eir_clientid */ + \ 27099fe60d0SBenny Halevy 1 /* eir_sequenceid */ + \ 27199fe60d0SBenny Halevy 1 /* eir_flags */ + \ 27299fe60d0SBenny Halevy 1 /* spr_how */ + \ 27399fe60d0SBenny Halevy 0 /* SP4_NONE (for now) */ + \ 27499fe60d0SBenny Halevy 2 /* eir_server_owner.so_minor_id */ + \ 27599fe60d0SBenny Halevy /* eir_server_owner.so_major_id<> */ \ 27699fe60d0SBenny Halevy XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ 27799fe60d0SBenny Halevy /* eir_server_scope<> */ \ 27899fe60d0SBenny Halevy XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ 27999fe60d0SBenny Halevy 1 /* eir_server_impl_id array length */ + \ 28099fe60d0SBenny Halevy 0 /* ignored eir_server_impl_id contents */) 281fc931582SAndy Adamson #define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */) 282fc931582SAndy Adamson #define decode_channel_attrs_maxsz (6 + \ 283fc931582SAndy Adamson 1 /* ca_rdma_ird.len */ + \ 284fc931582SAndy Adamson 1 /* ca_rdma_ird */) 285fc931582SAndy Adamson #define encode_create_session_maxsz (op_encode_hdr_maxsz + \ 286fc931582SAndy Adamson 2 /* csa_clientid */ + \ 287fc931582SAndy Adamson 1 /* csa_sequence */ + \ 288fc931582SAndy Adamson 1 /* csa_flags */ + \ 289fc931582SAndy Adamson encode_channel_attrs_maxsz + \ 290fc931582SAndy Adamson encode_channel_attrs_maxsz + \ 291fc931582SAndy Adamson 1 /* csa_cb_program */ + \ 292fc931582SAndy Adamson 1 /* csa_sec_parms.len (1) */ + \ 293fc931582SAndy Adamson 1 /* cb_secflavor (AUTH_SYS) */ + \ 294fc931582SAndy Adamson 1 /* stamp */ + \ 295fc931582SAndy Adamson 1 /* machinename.len */ + \ 296fc931582SAndy Adamson XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \ 297fc931582SAndy Adamson 1 /* uid */ + \ 298fc931582SAndy Adamson 1 /* gid */ + \ 299fc931582SAndy Adamson 1 /* gids.len (0) */) 300fc931582SAndy Adamson #define decode_create_session_maxsz (op_decode_hdr_maxsz + \ 301fc931582SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ 302fc931582SAndy Adamson 1 /* csr_sequence */ + \ 303fc931582SAndy Adamson 1 /* csr_flags */ + \ 304fc931582SAndy Adamson decode_channel_attrs_maxsz + \ 305fc931582SAndy Adamson decode_channel_attrs_maxsz) 3060f3e66c6SAndy Adamson #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) 3070f3e66c6SAndy Adamson #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) 308fc01cea9SAndy Adamson #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ 309fc01cea9SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) 310fc01cea9SAndy Adamson #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ 311fc01cea9SAndy Adamson XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) 31218019753SRicardo Labiaga #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) 31318019753SRicardo Labiaga #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) 314b1f69b75SAndy Adamson #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \ 315b1f69b75SAndy Adamson XDR_QUADLEN(NFS4_DEVICEID4_SIZE)) 316b1f69b75SAndy Adamson #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ 317b1f69b75SAndy Adamson 1 /* layout type */ + \ 318b1f69b75SAndy Adamson 1 /* opaque devaddr4 length */ + \ 319b1f69b75SAndy Adamson /* devaddr4 payload is read into page */ \ 320b1f69b75SAndy Adamson 1 /* notification bitmap length */ + \ 321b1f69b75SAndy Adamson 1 /* notification bitmap */) 322b1f69b75SAndy Adamson #define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \ 323b1f69b75SAndy Adamson encode_stateid_maxsz) 324b1f69b75SAndy Adamson #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ 325b1f69b75SAndy Adamson decode_stateid_maxsz + \ 326b1f69b75SAndy Adamson XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) 327863a3c6cSAndy Adamson #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ 328863a3c6cSAndy Adamson 2 /* offset */ + \ 329863a3c6cSAndy Adamson 2 /* length */ + \ 330863a3c6cSAndy Adamson 1 /* reclaim */ + \ 331863a3c6cSAndy Adamson encode_stateid_maxsz + \ 332863a3c6cSAndy Adamson 1 /* new offset (true) */ + \ 333863a3c6cSAndy Adamson 2 /* last byte written */ + \ 334863a3c6cSAndy Adamson 1 /* nt_timechanged (false) */ + \ 335863a3c6cSAndy Adamson 1 /* layoutupdate4 layout type */ + \ 336863a3c6cSAndy Adamson 1 /* NULL filelayout layoutupdate4 payload */) 337863a3c6cSAndy Adamson #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) 338863a3c6cSAndy Adamson 3399b7b9fccSAndy Adamson #else /* CONFIG_NFS_V4_1 */ 3409b7b9fccSAndy Adamson #define encode_sequence_maxsz 0 3419b7b9fccSAndy Adamson #define decode_sequence_maxsz 0 3429b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 3439b7b9fccSAndy Adamson 3441da177e4SLinus Torvalds #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ 3451da177e4SLinus Torvalds #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ 3461da177e4SLinus Torvalds #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ 3479b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3481da177e4SLinus Torvalds encode_putfh_maxsz + \ 3499104a55dSTrond Myklebust encode_read_maxsz) 3501da177e4SLinus Torvalds #define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \ 3519b7b9fccSAndy Adamson decode_sequence_maxsz + \ 3521da177e4SLinus Torvalds decode_putfh_maxsz + \ 3539104a55dSTrond Myklebust decode_read_maxsz) 3541da177e4SLinus Torvalds #define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \ 3559b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3561da177e4SLinus Torvalds encode_putfh_maxsz + \ 3579104a55dSTrond Myklebust encode_readlink_maxsz) 3581da177e4SLinus Torvalds #define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \ 3599b7b9fccSAndy Adamson decode_sequence_maxsz + \ 3601da177e4SLinus Torvalds decode_putfh_maxsz + \ 3619104a55dSTrond Myklebust decode_readlink_maxsz) 3621da177e4SLinus Torvalds #define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \ 3639b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3641da177e4SLinus Torvalds encode_putfh_maxsz + \ 3659104a55dSTrond Myklebust encode_readdir_maxsz) 3661da177e4SLinus Torvalds #define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \ 3679b7b9fccSAndy Adamson decode_sequence_maxsz + \ 3681da177e4SLinus Torvalds decode_putfh_maxsz + \ 3699104a55dSTrond Myklebust decode_readdir_maxsz) 3701da177e4SLinus Torvalds #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ 3719b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3721da177e4SLinus Torvalds encode_putfh_maxsz + \ 3739104a55dSTrond Myklebust encode_write_maxsz + \ 3744f9838c7STrond Myklebust encode_getattr_maxsz) 3751da177e4SLinus Torvalds #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ 3769b7b9fccSAndy Adamson decode_sequence_maxsz + \ 3771da177e4SLinus Torvalds decode_putfh_maxsz + \ 3789104a55dSTrond Myklebust decode_write_maxsz + \ 3794f9838c7STrond Myklebust decode_getattr_maxsz) 3801da177e4SLinus Torvalds #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ 3819b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3821da177e4SLinus Torvalds encode_putfh_maxsz + \ 3839104a55dSTrond Myklebust encode_commit_maxsz + \ 3844f9838c7STrond Myklebust encode_getattr_maxsz) 3851da177e4SLinus Torvalds #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ 3869b7b9fccSAndy Adamson decode_sequence_maxsz + \ 3871da177e4SLinus Torvalds decode_putfh_maxsz + \ 3889104a55dSTrond Myklebust decode_commit_maxsz + \ 3894f9838c7STrond Myklebust decode_getattr_maxsz) 3901da177e4SLinus Torvalds #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ 3919b7b9fccSAndy Adamson encode_sequence_maxsz + \ 3921da177e4SLinus Torvalds encode_putfh_maxsz + \ 3932cebf828STrond Myklebust encode_savefh_maxsz + \ 3942cebf828STrond Myklebust encode_open_maxsz + \ 3952cebf828STrond Myklebust encode_getfh_maxsz + \ 3961da177e4SLinus Torvalds encode_getattr_maxsz + \ 3972cebf828STrond Myklebust encode_restorefh_maxsz + \ 3982cebf828STrond Myklebust encode_getattr_maxsz) 3991da177e4SLinus Torvalds #define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ 4009b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4011da177e4SLinus Torvalds decode_putfh_maxsz + \ 4022cebf828STrond Myklebust decode_savefh_maxsz + \ 4032cebf828STrond Myklebust decode_open_maxsz + \ 4042cebf828STrond Myklebust decode_getfh_maxsz + \ 4051da177e4SLinus Torvalds decode_getattr_maxsz + \ 4062cebf828STrond Myklebust decode_restorefh_maxsz + \ 4072cebf828STrond Myklebust decode_getattr_maxsz) 4081da177e4SLinus Torvalds #define NFS4_enc_open_confirm_sz \ 4091da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 4101da177e4SLinus Torvalds encode_putfh_maxsz + \ 4119104a55dSTrond Myklebust encode_open_confirm_maxsz) 4129104a55dSTrond Myklebust #define NFS4_dec_open_confirm_sz \ 4139104a55dSTrond Myklebust (compound_decode_hdr_maxsz + \ 4141da177e4SLinus Torvalds decode_putfh_maxsz + \ 4159104a55dSTrond Myklebust decode_open_confirm_maxsz) 4161da177e4SLinus Torvalds #define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \ 4179b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4181da177e4SLinus Torvalds encode_putfh_maxsz + \ 4192cebf828STrond Myklebust encode_open_maxsz + \ 4202cebf828STrond Myklebust encode_getattr_maxsz) 4211da177e4SLinus Torvalds #define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \ 4229b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4231da177e4SLinus Torvalds decode_putfh_maxsz + \ 4242cebf828STrond Myklebust decode_open_maxsz + \ 4252cebf828STrond Myklebust decode_getattr_maxsz) 4261da177e4SLinus Torvalds #define NFS4_enc_open_downgrade_sz \ 4271da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 4289b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4291da177e4SLinus Torvalds encode_putfh_maxsz + \ 4309104a55dSTrond Myklebust encode_open_downgrade_maxsz + \ 431516a6af6STrond Myklebust encode_getattr_maxsz) 4321da177e4SLinus Torvalds #define NFS4_dec_open_downgrade_sz \ 4331da177e4SLinus Torvalds (compound_decode_hdr_maxsz + \ 4349b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4351da177e4SLinus Torvalds decode_putfh_maxsz + \ 4369104a55dSTrond Myklebust decode_open_downgrade_maxsz + \ 437516a6af6STrond Myklebust decode_getattr_maxsz) 4381da177e4SLinus Torvalds #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ 4399b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4401da177e4SLinus Torvalds encode_putfh_maxsz + \ 4419104a55dSTrond Myklebust encode_close_maxsz + \ 442516a6af6STrond Myklebust encode_getattr_maxsz) 4431da177e4SLinus Torvalds #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ 4449b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4451da177e4SLinus Torvalds decode_putfh_maxsz + \ 4469104a55dSTrond Myklebust decode_close_maxsz + \ 447516a6af6STrond Myklebust decode_getattr_maxsz) 4481da177e4SLinus Torvalds #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ 4499b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4501da177e4SLinus Torvalds encode_putfh_maxsz + \ 4519104a55dSTrond Myklebust encode_setattr_maxsz + \ 4521da177e4SLinus Torvalds encode_getattr_maxsz) 4531da177e4SLinus Torvalds #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ 4549b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4551da177e4SLinus Torvalds decode_putfh_maxsz + \ 4569104a55dSTrond Myklebust decode_setattr_maxsz + \ 4579104a55dSTrond Myklebust decode_getattr_maxsz) 4581da177e4SLinus Torvalds #define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \ 4599b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4601da177e4SLinus Torvalds encode_putfh_maxsz + \ 4611da177e4SLinus Torvalds encode_fsinfo_maxsz) 4621da177e4SLinus Torvalds #define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \ 4639b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4641da177e4SLinus Torvalds decode_putfh_maxsz + \ 4651da177e4SLinus Torvalds decode_fsinfo_maxsz) 4661da177e4SLinus Torvalds #define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \ 4671da177e4SLinus Torvalds encode_renew_maxsz) 4681da177e4SLinus Torvalds #define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \ 4691da177e4SLinus Torvalds decode_renew_maxsz) 4701da177e4SLinus Torvalds #define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \ 4711da177e4SLinus Torvalds encode_setclientid_maxsz) 4721da177e4SLinus Torvalds #define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \ 4731da177e4SLinus Torvalds decode_setclientid_maxsz) 4741da177e4SLinus Torvalds #define NFS4_enc_setclientid_confirm_sz \ 4751da177e4SLinus Torvalds (compound_encode_hdr_maxsz + \ 4761da177e4SLinus Torvalds encode_setclientid_confirm_maxsz + \ 4771da177e4SLinus Torvalds encode_putrootfh_maxsz + \ 4781da177e4SLinus Torvalds encode_fsinfo_maxsz) 4791da177e4SLinus Torvalds #define NFS4_dec_setclientid_confirm_sz \ 4801da177e4SLinus Torvalds (compound_decode_hdr_maxsz + \ 4811da177e4SLinus Torvalds decode_setclientid_confirm_maxsz + \ 4821da177e4SLinus Torvalds decode_putrootfh_maxsz + \ 4831da177e4SLinus Torvalds decode_fsinfo_maxsz) 4841da177e4SLinus Torvalds #define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \ 4859b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4861da177e4SLinus Torvalds encode_putfh_maxsz + \ 4879104a55dSTrond Myklebust encode_lock_maxsz) 4881da177e4SLinus Torvalds #define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \ 4899b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4901da177e4SLinus Torvalds decode_putfh_maxsz + \ 4919104a55dSTrond Myklebust decode_lock_maxsz) 4921da177e4SLinus Torvalds #define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \ 4939b7b9fccSAndy Adamson encode_sequence_maxsz + \ 4941da177e4SLinus Torvalds encode_putfh_maxsz + \ 4959104a55dSTrond Myklebust encode_lockt_maxsz) 4969104a55dSTrond Myklebust #define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \ 4979b7b9fccSAndy Adamson decode_sequence_maxsz + \ 4989104a55dSTrond Myklebust decode_putfh_maxsz + \ 4999104a55dSTrond Myklebust decode_lockt_maxsz) 5001da177e4SLinus Torvalds #define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \ 5019b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5021da177e4SLinus Torvalds encode_putfh_maxsz + \ 5039104a55dSTrond Myklebust encode_locku_maxsz) 5041da177e4SLinus Torvalds #define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \ 5059b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5061da177e4SLinus Torvalds decode_putfh_maxsz + \ 5079104a55dSTrond Myklebust decode_locku_maxsz) 508d3c7b7ccSTrond Myklebust #define NFS4_enc_release_lockowner_sz \ 509d3c7b7ccSTrond Myklebust (compound_encode_hdr_maxsz + \ 510d3c7b7ccSTrond Myklebust encode_lockowner_maxsz) 511d3c7b7ccSTrond Myklebust #define NFS4_dec_release_lockowner_sz \ 512d3c7b7ccSTrond Myklebust (compound_decode_hdr_maxsz + \ 513d3c7b7ccSTrond Myklebust decode_lockowner_maxsz) 5141da177e4SLinus Torvalds #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ 5159b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5161da177e4SLinus Torvalds encode_putfh_maxsz + \ 51776b32999STrond Myklebust encode_access_maxsz + \ 51876b32999STrond Myklebust encode_getattr_maxsz) 5191da177e4SLinus Torvalds #define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ 5209b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5211da177e4SLinus Torvalds decode_putfh_maxsz + \ 52276b32999STrond Myklebust decode_access_maxsz + \ 52376b32999STrond Myklebust decode_getattr_maxsz) 5241da177e4SLinus Torvalds #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ 5259b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5261da177e4SLinus Torvalds encode_putfh_maxsz + \ 5271da177e4SLinus Torvalds encode_getattr_maxsz) 5281da177e4SLinus Torvalds #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ 5299b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5301da177e4SLinus Torvalds decode_putfh_maxsz + \ 5311da177e4SLinus Torvalds decode_getattr_maxsz) 5321da177e4SLinus Torvalds #define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ 5339b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5341da177e4SLinus Torvalds encode_putfh_maxsz + \ 5351da177e4SLinus Torvalds encode_lookup_maxsz + \ 5361da177e4SLinus Torvalds encode_getattr_maxsz + \ 5371da177e4SLinus Torvalds encode_getfh_maxsz) 5381da177e4SLinus Torvalds #define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \ 5399b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5401da177e4SLinus Torvalds decode_putfh_maxsz + \ 541e6889620STrond Myklebust decode_lookup_maxsz + \ 5421da177e4SLinus Torvalds decode_getattr_maxsz + \ 5431da177e4SLinus Torvalds decode_getfh_maxsz) 5441da177e4SLinus Torvalds #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ 5459b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5461da177e4SLinus Torvalds encode_putrootfh_maxsz + \ 5471da177e4SLinus Torvalds encode_getattr_maxsz + \ 5481da177e4SLinus Torvalds encode_getfh_maxsz) 5491da177e4SLinus Torvalds #define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \ 5509b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5511da177e4SLinus Torvalds decode_putrootfh_maxsz + \ 5521da177e4SLinus Torvalds decode_getattr_maxsz + \ 5531da177e4SLinus Torvalds decode_getfh_maxsz) 5541da177e4SLinus Torvalds #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ 5559b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5561da177e4SLinus Torvalds encode_putfh_maxsz + \ 55716e42959STrond Myklebust encode_remove_maxsz + \ 55816e42959STrond Myklebust encode_getattr_maxsz) 5591da177e4SLinus Torvalds #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ 5609b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5611da177e4SLinus Torvalds decode_putfh_maxsz + \ 5626ce18391SBenny Halevy decode_remove_maxsz + \ 56316e42959STrond Myklebust decode_getattr_maxsz) 5641da177e4SLinus Torvalds #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ 5659b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5661da177e4SLinus Torvalds encode_putfh_maxsz + \ 5671da177e4SLinus Torvalds encode_savefh_maxsz + \ 5681da177e4SLinus Torvalds encode_putfh_maxsz + \ 5696caf2c82STrond Myklebust encode_rename_maxsz + \ 5706caf2c82STrond Myklebust encode_getattr_maxsz + \ 5716caf2c82STrond Myklebust encode_restorefh_maxsz + \ 5726caf2c82STrond Myklebust encode_getattr_maxsz) 5731da177e4SLinus Torvalds #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ 5749b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5751da177e4SLinus Torvalds decode_putfh_maxsz + \ 5761da177e4SLinus Torvalds decode_savefh_maxsz + \ 5771da177e4SLinus Torvalds decode_putfh_maxsz + \ 5786caf2c82STrond Myklebust decode_rename_maxsz + \ 5796caf2c82STrond Myklebust decode_getattr_maxsz + \ 5806caf2c82STrond Myklebust decode_restorefh_maxsz + \ 5816caf2c82STrond Myklebust decode_getattr_maxsz) 5821da177e4SLinus Torvalds #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ 5839b7b9fccSAndy Adamson encode_sequence_maxsz + \ 5841da177e4SLinus Torvalds encode_putfh_maxsz + \ 5851da177e4SLinus Torvalds encode_savefh_maxsz + \ 5861da177e4SLinus Torvalds encode_putfh_maxsz + \ 58791ba2eeeSTrond Myklebust encode_link_maxsz + \ 58891ba2eeeSTrond Myklebust decode_getattr_maxsz + \ 58991ba2eeeSTrond Myklebust encode_restorefh_maxsz + \ 59091ba2eeeSTrond Myklebust decode_getattr_maxsz) 5911da177e4SLinus Torvalds #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ 5929b7b9fccSAndy Adamson decode_sequence_maxsz + \ 5931da177e4SLinus Torvalds decode_putfh_maxsz + \ 5941da177e4SLinus Torvalds decode_savefh_maxsz + \ 5951da177e4SLinus Torvalds decode_putfh_maxsz + \ 59691ba2eeeSTrond Myklebust decode_link_maxsz + \ 59791ba2eeeSTrond Myklebust decode_getattr_maxsz + \ 59891ba2eeeSTrond Myklebust decode_restorefh_maxsz + \ 59991ba2eeeSTrond Myklebust decode_getattr_maxsz) 6001da177e4SLinus Torvalds #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ 6019b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6021da177e4SLinus Torvalds encode_putfh_maxsz + \ 6031da177e4SLinus Torvalds encode_symlink_maxsz + \ 6041da177e4SLinus Torvalds encode_getattr_maxsz + \ 6051da177e4SLinus Torvalds encode_getfh_maxsz) 6061da177e4SLinus Torvalds #define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \ 6079b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6081da177e4SLinus Torvalds decode_putfh_maxsz + \ 6091da177e4SLinus Torvalds decode_symlink_maxsz + \ 6101da177e4SLinus Torvalds decode_getattr_maxsz + \ 6111da177e4SLinus Torvalds decode_getfh_maxsz) 6121da177e4SLinus Torvalds #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ 6139b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6141da177e4SLinus Torvalds encode_putfh_maxsz + \ 61556ae19f3STrond Myklebust encode_savefh_maxsz + \ 6161da177e4SLinus Torvalds encode_create_maxsz + \ 61756ae19f3STrond Myklebust encode_getfh_maxsz + \ 6181da177e4SLinus Torvalds encode_getattr_maxsz + \ 61956ae19f3STrond Myklebust encode_restorefh_maxsz + \ 62056ae19f3STrond Myklebust encode_getattr_maxsz) 6211da177e4SLinus Torvalds #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ 6229b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6231da177e4SLinus Torvalds decode_putfh_maxsz + \ 62456ae19f3STrond Myklebust decode_savefh_maxsz + \ 6251da177e4SLinus Torvalds decode_create_maxsz + \ 62656ae19f3STrond Myklebust decode_getfh_maxsz + \ 6271da177e4SLinus Torvalds decode_getattr_maxsz + \ 62856ae19f3STrond Myklebust decode_restorefh_maxsz + \ 62956ae19f3STrond Myklebust decode_getattr_maxsz) 6301da177e4SLinus Torvalds #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ 6319b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6321da177e4SLinus Torvalds encode_putfh_maxsz + \ 6331da177e4SLinus Torvalds encode_getattr_maxsz) 6341da177e4SLinus Torvalds #define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \ 6359b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6361da177e4SLinus Torvalds decode_putfh_maxsz + \ 6371da177e4SLinus Torvalds decode_getattr_maxsz) 6381da177e4SLinus Torvalds #define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \ 6399b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6401da177e4SLinus Torvalds encode_putfh_maxsz + \ 6419104a55dSTrond Myklebust encode_statfs_maxsz) 6421da177e4SLinus Torvalds #define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \ 6439b7b9fccSAndy Adamson decode_sequence_maxsz + \ 6441da177e4SLinus Torvalds decode_putfh_maxsz + \ 6459104a55dSTrond Myklebust decode_statfs_maxsz) 6461da177e4SLinus Torvalds #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ 6479b7b9fccSAndy Adamson encode_sequence_maxsz + \ 648ab91f264STrond Myklebust encode_putfh_maxsz + \ 6491da177e4SLinus Torvalds encode_getattr_maxsz) 6501da177e4SLinus Torvalds #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ 6519b7b9fccSAndy Adamson decode_sequence_maxsz + \ 652ab91f264STrond Myklebust decode_putfh_maxsz + \ 6531da177e4SLinus Torvalds decode_getattr_maxsz) 6541da177e4SLinus Torvalds #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ 6559b7b9fccSAndy Adamson encode_sequence_maxsz + \ 6561da177e4SLinus Torvalds encode_putfh_maxsz + \ 657fa178f29STrond Myklebust encode_delegreturn_maxsz + \ 658fa178f29STrond Myklebust encode_getattr_maxsz) 6591da177e4SLinus Torvalds #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ 6609b7b9fccSAndy Adamson decode_sequence_maxsz + \ 661fa178f29STrond Myklebust decode_delegreturn_maxsz + \ 662fa178f29STrond Myklebust decode_getattr_maxsz) 663029d105eSJ. Bruce Fields #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ 6649b7b9fccSAndy Adamson encode_sequence_maxsz + \ 665029d105eSJ. Bruce Fields encode_putfh_maxsz + \ 6669104a55dSTrond Myklebust encode_getacl_maxsz) 667029d105eSJ. Bruce Fields #define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ 6689b7b9fccSAndy Adamson decode_sequence_maxsz + \ 669029d105eSJ. Bruce Fields decode_putfh_maxsz + \ 6709104a55dSTrond Myklebust decode_getacl_maxsz) 67123ec6965SJ. Bruce Fields #define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ 6729b7b9fccSAndy Adamson encode_sequence_maxsz + \ 67323ec6965SJ. Bruce Fields encode_putfh_maxsz + \ 6749104a55dSTrond Myklebust encode_setacl_maxsz) 67523ec6965SJ. Bruce Fields #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ 6769b7b9fccSAndy Adamson decode_sequence_maxsz + \ 67723ec6965SJ. Bruce Fields decode_putfh_maxsz + \ 6789104a55dSTrond Myklebust decode_setacl_maxsz) 679683b57b4STrond Myklebust #define NFS4_enc_fs_locations_sz \ 680683b57b4STrond Myklebust (compound_encode_hdr_maxsz + \ 6819b7b9fccSAndy Adamson encode_sequence_maxsz + \ 682683b57b4STrond Myklebust encode_putfh_maxsz + \ 683e6889620STrond Myklebust encode_lookup_maxsz + \ 684e6889620STrond Myklebust encode_fs_locations_maxsz) 685683b57b4STrond Myklebust #define NFS4_dec_fs_locations_sz \ 686683b57b4STrond Myklebust (compound_decode_hdr_maxsz + \ 6879b7b9fccSAndy Adamson decode_sequence_maxsz + \ 688683b57b4STrond Myklebust decode_putfh_maxsz + \ 689e6889620STrond Myklebust decode_lookup_maxsz + \ 690e6889620STrond Myklebust decode_fs_locations_maxsz) 69199fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 69299fe60d0SBenny Halevy #define NFS4_enc_exchange_id_sz \ 69399fe60d0SBenny Halevy (compound_encode_hdr_maxsz + \ 69499fe60d0SBenny Halevy encode_exchange_id_maxsz) 69599fe60d0SBenny Halevy #define NFS4_dec_exchange_id_sz \ 69699fe60d0SBenny Halevy (compound_decode_hdr_maxsz + \ 69799fe60d0SBenny Halevy decode_exchange_id_maxsz) 698fc931582SAndy Adamson #define NFS4_enc_create_session_sz \ 699fc931582SAndy Adamson (compound_encode_hdr_maxsz + \ 700fc931582SAndy Adamson encode_create_session_maxsz) 701fc931582SAndy Adamson #define NFS4_dec_create_session_sz \ 702fc931582SAndy Adamson (compound_decode_hdr_maxsz + \ 703fc931582SAndy Adamson decode_create_session_maxsz) 7040f3e66c6SAndy Adamson #define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \ 7050f3e66c6SAndy Adamson encode_destroy_session_maxsz) 7060f3e66c6SAndy Adamson #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ 7070f3e66c6SAndy Adamson decode_destroy_session_maxsz) 708fc01cea9SAndy Adamson #define NFS4_enc_sequence_sz \ 709fc01cea9SAndy Adamson (compound_decode_hdr_maxsz + \ 710fc01cea9SAndy Adamson encode_sequence_maxsz) 711fc01cea9SAndy Adamson #define NFS4_dec_sequence_sz \ 712fc01cea9SAndy Adamson (compound_decode_hdr_maxsz + \ 713fc01cea9SAndy Adamson decode_sequence_maxsz) 7142050f0ccSAndy Adamson #define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \ 7152050f0ccSAndy Adamson encode_sequence_maxsz + \ 7162050f0ccSAndy Adamson encode_putrootfh_maxsz + \ 7172050f0ccSAndy Adamson encode_fsinfo_maxsz) 7182050f0ccSAndy Adamson #define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \ 7192050f0ccSAndy Adamson decode_sequence_maxsz + \ 7202050f0ccSAndy Adamson decode_putrootfh_maxsz + \ 7212050f0ccSAndy Adamson decode_fsinfo_maxsz) 72218019753SRicardo Labiaga #define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \ 72318019753SRicardo Labiaga encode_sequence_maxsz + \ 72418019753SRicardo Labiaga encode_reclaim_complete_maxsz) 72518019753SRicardo Labiaga #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ 72618019753SRicardo Labiaga decode_sequence_maxsz + \ 72718019753SRicardo Labiaga decode_reclaim_complete_maxsz) 728b1f69b75SAndy Adamson #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ 729b1f69b75SAndy Adamson encode_sequence_maxsz +\ 730b1f69b75SAndy Adamson encode_getdeviceinfo_maxsz) 731b1f69b75SAndy Adamson #define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \ 732b1f69b75SAndy Adamson decode_sequence_maxsz + \ 733b1f69b75SAndy Adamson decode_getdeviceinfo_maxsz) 734b1f69b75SAndy Adamson #define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \ 735b1f69b75SAndy Adamson encode_sequence_maxsz + \ 736b1f69b75SAndy Adamson encode_putfh_maxsz + \ 737b1f69b75SAndy Adamson encode_layoutget_maxsz) 738b1f69b75SAndy Adamson #define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \ 739b1f69b75SAndy Adamson decode_sequence_maxsz + \ 740b1f69b75SAndy Adamson decode_putfh_maxsz + \ 741b1f69b75SAndy Adamson decode_layoutget_maxsz) 742863a3c6cSAndy Adamson #define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ 743863a3c6cSAndy Adamson encode_sequence_maxsz +\ 744863a3c6cSAndy Adamson encode_putfh_maxsz + \ 745863a3c6cSAndy Adamson encode_layoutcommit_maxsz + \ 746863a3c6cSAndy Adamson encode_getattr_maxsz) 747863a3c6cSAndy Adamson #define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ 748863a3c6cSAndy Adamson decode_sequence_maxsz + \ 749863a3c6cSAndy Adamson decode_putfh_maxsz + \ 750863a3c6cSAndy Adamson decode_layoutcommit_maxsz + \ 751863a3c6cSAndy Adamson decode_getattr_maxsz) 752863a3c6cSAndy Adamson 7532449ea2eSAlexandros Batsakis 7542449ea2eSAlexandros Batsakis const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 7552449ea2eSAlexandros Batsakis compound_encode_hdr_maxsz + 7562449ea2eSAlexandros Batsakis encode_sequence_maxsz + 7572449ea2eSAlexandros Batsakis encode_putfh_maxsz + 7582449ea2eSAlexandros Batsakis encode_getattr_maxsz) * 7592449ea2eSAlexandros Batsakis XDR_UNIT); 7602449ea2eSAlexandros Batsakis 7612449ea2eSAlexandros Batsakis const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 7622449ea2eSAlexandros Batsakis compound_decode_hdr_maxsz + 7632449ea2eSAlexandros Batsakis decode_sequence_maxsz + 7642449ea2eSAlexandros Batsakis decode_putfh_maxsz) * 7652449ea2eSAlexandros Batsakis XDR_UNIT); 76699fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 7671da177e4SLinus Torvalds 768bca79478STrond Myklebust static const umode_t nfs_type2fmt[] = { 769bca79478STrond Myklebust [NF4BAD] = 0, 770bca79478STrond Myklebust [NF4REG] = S_IFREG, 771bca79478STrond Myklebust [NF4DIR] = S_IFDIR, 772bca79478STrond Myklebust [NF4BLK] = S_IFBLK, 773bca79478STrond Myklebust [NF4CHR] = S_IFCHR, 774bca79478STrond Myklebust [NF4LNK] = S_IFLNK, 775bca79478STrond Myklebust [NF4SOCK] = S_IFSOCK, 776bca79478STrond Myklebust [NF4FIFO] = S_IFIFO, 777bca79478STrond Myklebust [NF4ATTRDIR] = 0, 778bca79478STrond Myklebust [NF4NAMEDATTR] = 0, 7791da177e4SLinus Torvalds }; 7801da177e4SLinus Torvalds 7811da177e4SLinus Torvalds struct compound_hdr { 7821da177e4SLinus Torvalds int32_t status; 7831da177e4SLinus Torvalds uint32_t nops; 784d017931cSAndy Adamson __be32 * nops_p; 7851da177e4SLinus Torvalds uint32_t taglen; 7861da177e4SLinus Torvalds char * tag; 7870c4e8c18SBenny Halevy uint32_t replen; /* expected reply words */ 78866cc0429SBenny Halevy u32 minorversion; 7891da177e4SLinus Torvalds }; 7901da177e4SLinus Torvalds 79113c65ce9SBenny Halevy static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes) 79213c65ce9SBenny Halevy { 79313c65ce9SBenny Halevy __be32 *p = xdr_reserve_space(xdr, nbytes); 79413c65ce9SBenny Halevy BUG_ON(!p); 79513c65ce9SBenny Halevy return p; 79613c65ce9SBenny Halevy } 7971da177e4SLinus Torvalds 7981da177e4SLinus Torvalds static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) 7991da177e4SLinus Torvalds { 8008687b63aSAl Viro __be32 *p; 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds p = xdr_reserve_space(xdr, 4 + len); 8031da177e4SLinus Torvalds BUG_ON(p == NULL); 8041da177e4SLinus Torvalds xdr_encode_opaque(p, str, len); 8051da177e4SLinus Torvalds } 8061da177e4SLinus Torvalds 8070c4e8c18SBenny Halevy static void encode_compound_hdr(struct xdr_stream *xdr, 8080c4e8c18SBenny Halevy struct rpc_rqst *req, 8090c4e8c18SBenny Halevy struct compound_hdr *hdr) 8101da177e4SLinus Torvalds { 8118687b63aSAl Viro __be32 *p; 812a17c2153STrond Myklebust struct rpc_auth *auth = req->rq_cred->cr_auth; 8130c4e8c18SBenny Halevy 8140c4e8c18SBenny Halevy /* initialize running count of expected bytes in reply. 8150c4e8c18SBenny Halevy * NOTE: the replied tag SHOULD be the same is the one sent, 8160c4e8c18SBenny Halevy * but this is not required as a MUST for the server to do so. */ 8170c4e8c18SBenny Halevy hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen; 8181da177e4SLinus Torvalds 8191da177e4SLinus Torvalds dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag); 8201da177e4SLinus Torvalds BUG_ON(hdr->taglen > NFS4_MAXTAGLEN); 821811652bdSBenny Halevy p = reserve_space(xdr, 4 + hdr->taglen + 8); 822811652bdSBenny Halevy p = xdr_encode_opaque(p, hdr->tag, hdr->taglen); 823e75bc1c8SBenny Halevy *p++ = cpu_to_be32(hdr->minorversion); 824d017931cSAndy Adamson hdr->nops_p = p; 82534558513SBenny Halevy *p = cpu_to_be32(hdr->nops); 826d017931cSAndy Adamson } 827d017931cSAndy Adamson 828d017931cSAndy Adamson static void encode_nops(struct compound_hdr *hdr) 829d017931cSAndy Adamson { 830fc931582SAndy Adamson BUG_ON(hdr->nops > NFS4_MAX_OPS); 831d017931cSAndy Adamson *hdr->nops_p = htonl(hdr->nops); 8321da177e4SLinus Torvalds } 8331da177e4SLinus Torvalds 8341da177e4SLinus Torvalds static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf) 8351da177e4SLinus Torvalds { 8368687b63aSAl Viro __be32 *p; 8371da177e4SLinus Torvalds 8381da177e4SLinus Torvalds p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE); 8391da177e4SLinus Torvalds BUG_ON(p == NULL); 8401da177e4SLinus Torvalds xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE); 8411da177e4SLinus Torvalds } 8421da177e4SLinus Torvalds 843cf8cdbe5SAndy Adamson static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server) 8441da177e4SLinus Torvalds { 8451da177e4SLinus Torvalds char owner_name[IDMAP_NAMESZ]; 8461da177e4SLinus Torvalds char owner_group[IDMAP_NAMESZ]; 8471da177e4SLinus Torvalds int owner_namelen = 0; 8481da177e4SLinus Torvalds int owner_grouplen = 0; 8498687b63aSAl Viro __be32 *p; 8508687b63aSAl Viro __be32 *q; 8511da177e4SLinus Torvalds int len; 8521da177e4SLinus Torvalds uint32_t bmval0 = 0; 8531da177e4SLinus Torvalds uint32_t bmval1 = 0; 8541da177e4SLinus Torvalds 8551da177e4SLinus Torvalds /* 8561da177e4SLinus Torvalds * We reserve enough space to write the entire attribute buffer at once. 8571da177e4SLinus Torvalds * In the worst-case, this would be 8581da177e4SLinus Torvalds * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) 8591da177e4SLinus Torvalds * = 36 bytes, plus any contribution from variable-length fields 86023ec6965SJ. Bruce Fields * such as owner/group. 8611da177e4SLinus Torvalds */ 8621da177e4SLinus Torvalds len = 16; 8631da177e4SLinus Torvalds 8641da177e4SLinus Torvalds /* Sigh */ 8651da177e4SLinus Torvalds if (iap->ia_valid & ATTR_SIZE) 8661da177e4SLinus Torvalds len += 8; 8671da177e4SLinus Torvalds if (iap->ia_valid & ATTR_MODE) 8681da177e4SLinus Torvalds len += 4; 8691da177e4SLinus Torvalds if (iap->ia_valid & ATTR_UID) { 870e4fd72a1STrond Myklebust owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); 8711da177e4SLinus Torvalds if (owner_namelen < 0) { 872fe82a183SChuck Lever dprintk("nfs: couldn't resolve uid %d to string\n", 8731da177e4SLinus Torvalds iap->ia_uid); 8741da177e4SLinus Torvalds /* XXX */ 8751da177e4SLinus Torvalds strcpy(owner_name, "nobody"); 8761da177e4SLinus Torvalds owner_namelen = sizeof("nobody") - 1; 8771da177e4SLinus Torvalds /* goto out; */ 8781da177e4SLinus Torvalds } 8791da177e4SLinus Torvalds len += 4 + (XDR_QUADLEN(owner_namelen) << 2); 8801da177e4SLinus Torvalds } 8811da177e4SLinus Torvalds if (iap->ia_valid & ATTR_GID) { 882e4fd72a1STrond Myklebust owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ); 8831da177e4SLinus Torvalds if (owner_grouplen < 0) { 884fe82a183SChuck Lever dprintk("nfs: couldn't resolve gid %d to string\n", 8851da177e4SLinus Torvalds iap->ia_gid); 8861da177e4SLinus Torvalds strcpy(owner_group, "nobody"); 8871da177e4SLinus Torvalds owner_grouplen = sizeof("nobody") - 1; 8881da177e4SLinus Torvalds /* goto out; */ 8891da177e4SLinus Torvalds } 8901da177e4SLinus Torvalds len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); 8911da177e4SLinus Torvalds } 8921da177e4SLinus Torvalds if (iap->ia_valid & ATTR_ATIME_SET) 8931da177e4SLinus Torvalds len += 16; 8941da177e4SLinus Torvalds else if (iap->ia_valid & ATTR_ATIME) 8951da177e4SLinus Torvalds len += 4; 8961da177e4SLinus Torvalds if (iap->ia_valid & ATTR_MTIME_SET) 8971da177e4SLinus Torvalds len += 16; 8981da177e4SLinus Torvalds else if (iap->ia_valid & ATTR_MTIME) 8991da177e4SLinus Torvalds len += 4; 90013c65ce9SBenny Halevy p = reserve_space(xdr, len); 9011da177e4SLinus Torvalds 9021da177e4SLinus Torvalds /* 9031da177e4SLinus Torvalds * We write the bitmap length now, but leave the bitmap and the attribute 9041da177e4SLinus Torvalds * buffer length to be backfilled at the end of this routine. 9051da177e4SLinus Torvalds */ 906e75bc1c8SBenny Halevy *p++ = cpu_to_be32(2); 9071da177e4SLinus Torvalds q = p; 9081da177e4SLinus Torvalds p += 3; 9091da177e4SLinus Torvalds 9101da177e4SLinus Torvalds if (iap->ia_valid & ATTR_SIZE) { 9111da177e4SLinus Torvalds bmval0 |= FATTR4_WORD0_SIZE; 912b95be5a9SBenny Halevy p = xdr_encode_hyper(p, iap->ia_size); 9131da177e4SLinus Torvalds } 9141da177e4SLinus Torvalds if (iap->ia_valid & ATTR_MODE) { 9151da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_MODE; 916e75bc1c8SBenny Halevy *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); 9171da177e4SLinus Torvalds } 9181da177e4SLinus Torvalds if (iap->ia_valid & ATTR_UID) { 9191da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_OWNER; 920811652bdSBenny Halevy p = xdr_encode_opaque(p, owner_name, owner_namelen); 9211da177e4SLinus Torvalds } 9221da177e4SLinus Torvalds if (iap->ia_valid & ATTR_GID) { 9231da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_OWNER_GROUP; 924811652bdSBenny Halevy p = xdr_encode_opaque(p, owner_group, owner_grouplen); 9251da177e4SLinus Torvalds } 9261da177e4SLinus Torvalds if (iap->ia_valid & ATTR_ATIME_SET) { 9271da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; 928e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 929e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); 930d3f6baaaSTrond Myklebust *p++ = cpu_to_be32(iap->ia_atime.tv_sec); 931d3f6baaaSTrond Myklebust *p++ = cpu_to_be32(iap->ia_atime.tv_nsec); 9321da177e4SLinus Torvalds } 9331da177e4SLinus Torvalds else if (iap->ia_valid & ATTR_ATIME) { 9341da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; 935e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); 9361da177e4SLinus Torvalds } 9371da177e4SLinus Torvalds if (iap->ia_valid & ATTR_MTIME_SET) { 9381da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; 939e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 940e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); 941e75bc1c8SBenny Halevy *p++ = cpu_to_be32(iap->ia_mtime.tv_sec); 942e75bc1c8SBenny Halevy *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec); 9431da177e4SLinus Torvalds } 9441da177e4SLinus Torvalds else if (iap->ia_valid & ATTR_MTIME) { 9451da177e4SLinus Torvalds bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; 946e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); 9471da177e4SLinus Torvalds } 9481da177e4SLinus Torvalds 9491da177e4SLinus Torvalds /* 9501da177e4SLinus Torvalds * Now we backfill the bitmap and the attribute buffer length. 9511da177e4SLinus Torvalds */ 9521da177e4SLinus Torvalds if (len != ((char *)p - (char *)q) + 4) { 953fe82a183SChuck Lever printk(KERN_ERR "nfs: Attr length error, %u != %Zu\n", 9541da177e4SLinus Torvalds len, ((char *)p - (char *)q) + 4); 9551da177e4SLinus Torvalds BUG(); 9561da177e4SLinus Torvalds } 9571da177e4SLinus Torvalds len = (char *)p - (char *)q - 12; 9581da177e4SLinus Torvalds *q++ = htonl(bmval0); 9591da177e4SLinus Torvalds *q++ = htonl(bmval1); 96034558513SBenny Halevy *q = htonl(len); 9611da177e4SLinus Torvalds 9621da177e4SLinus Torvalds /* out: */ 9631da177e4SLinus Torvalds } 9641da177e4SLinus Torvalds 965cf8cdbe5SAndy Adamson static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr) 9661da177e4SLinus Torvalds { 9678687b63aSAl Viro __be32 *p; 9681da177e4SLinus Torvalds 96913c65ce9SBenny Halevy p = reserve_space(xdr, 8); 970e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_ACCESS); 97134558513SBenny Halevy *p = cpu_to_be32(access); 972d017931cSAndy Adamson hdr->nops++; 973dadf0c27SBenny Halevy hdr->replen += decode_access_maxsz; 9741da177e4SLinus Torvalds } 9751da177e4SLinus Torvalds 976cf8cdbe5SAndy Adamson static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) 9771da177e4SLinus Torvalds { 9788687b63aSAl Viro __be32 *p; 9791da177e4SLinus Torvalds 98013c65ce9SBenny Halevy p = reserve_space(xdr, 8+NFS4_STATEID_SIZE); 981e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_CLOSE); 982e75bc1c8SBenny Halevy *p++ = cpu_to_be32(arg->seqid->sequence->counter); 98334558513SBenny Halevy xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); 984d017931cSAndy Adamson hdr->nops++; 985dadf0c27SBenny Halevy hdr->replen += decode_close_maxsz; 9861da177e4SLinus Torvalds } 9871da177e4SLinus Torvalds 988cf8cdbe5SAndy Adamson static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) 9891da177e4SLinus Torvalds { 9908687b63aSAl Viro __be32 *p; 9911da177e4SLinus Torvalds 99213c65ce9SBenny Halevy p = reserve_space(xdr, 16); 993e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_COMMIT); 994b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 99534558513SBenny Halevy *p = cpu_to_be32(args->count); 996d017931cSAndy Adamson hdr->nops++; 997dadf0c27SBenny Halevy hdr->replen += decode_commit_maxsz; 9981da177e4SLinus Torvalds } 9991da177e4SLinus Torvalds 1000cf8cdbe5SAndy Adamson static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr) 10011da177e4SLinus Torvalds { 10028687b63aSAl Viro __be32 *p; 10031da177e4SLinus Torvalds 100413c65ce9SBenny Halevy p = reserve_space(xdr, 8); 1005e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_CREATE); 100634558513SBenny Halevy *p = cpu_to_be32(create->ftype); 10071da177e4SLinus Torvalds 10081da177e4SLinus Torvalds switch (create->ftype) { 10091da177e4SLinus Torvalds case NF4LNK: 101013c65ce9SBenny Halevy p = reserve_space(xdr, 4); 101134558513SBenny Halevy *p = cpu_to_be32(create->u.symlink.len); 101294a6d753SChuck Lever xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len); 10131da177e4SLinus Torvalds break; 10141da177e4SLinus Torvalds 10151da177e4SLinus Torvalds case NF4BLK: case NF4CHR: 101613c65ce9SBenny Halevy p = reserve_space(xdr, 8); 1017e75bc1c8SBenny Halevy *p++ = cpu_to_be32(create->u.device.specdata1); 101834558513SBenny Halevy *p = cpu_to_be32(create->u.device.specdata2); 10191da177e4SLinus Torvalds break; 10201da177e4SLinus Torvalds 10211da177e4SLinus Torvalds default: 10221da177e4SLinus Torvalds break; 10231da177e4SLinus Torvalds } 10241da177e4SLinus Torvalds 1025811652bdSBenny Halevy encode_string(xdr, create->name->len, create->name->name); 1026d017931cSAndy Adamson hdr->nops++; 1027dadf0c27SBenny Halevy hdr->replen += decode_create_maxsz; 10281da177e4SLinus Torvalds 1029cf8cdbe5SAndy Adamson encode_attrs(xdr, create->attrs, create->server); 10301da177e4SLinus Torvalds } 10311da177e4SLinus Torvalds 1032cf8cdbe5SAndy Adamson static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) 10331da177e4SLinus Torvalds { 10348687b63aSAl Viro __be32 *p; 10351da177e4SLinus Torvalds 103613c65ce9SBenny Halevy p = reserve_space(xdr, 12); 1037e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_GETATTR); 1038e75bc1c8SBenny Halevy *p++ = cpu_to_be32(1); 103934558513SBenny Halevy *p = cpu_to_be32(bitmap); 1040d017931cSAndy Adamson hdr->nops++; 1041dadf0c27SBenny Halevy hdr->replen += decode_getattr_maxsz; 10421da177e4SLinus Torvalds } 10431da177e4SLinus Torvalds 1044cf8cdbe5SAndy Adamson static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr) 10451da177e4SLinus Torvalds { 10468687b63aSAl Viro __be32 *p; 10471da177e4SLinus Torvalds 104813c65ce9SBenny Halevy p = reserve_space(xdr, 16); 1049e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_GETATTR); 1050e75bc1c8SBenny Halevy *p++ = cpu_to_be32(2); 1051e75bc1c8SBenny Halevy *p++ = cpu_to_be32(bm0); 105234558513SBenny Halevy *p = cpu_to_be32(bm1); 1053d017931cSAndy Adamson hdr->nops++; 1054dadf0c27SBenny Halevy hdr->replen += decode_getattr_maxsz; 10551da177e4SLinus Torvalds } 10561da177e4SLinus Torvalds 1057cf8cdbe5SAndy Adamson static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 10581da177e4SLinus Torvalds { 1059cf8cdbe5SAndy Adamson encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], 1060d017931cSAndy Adamson bitmask[1] & nfs4_fattr_bitmap[1], hdr); 10611da177e4SLinus Torvalds } 10621da177e4SLinus Torvalds 1063cf8cdbe5SAndy Adamson static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 10641da177e4SLinus Torvalds { 1065cf8cdbe5SAndy Adamson encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0], 1066d017931cSAndy Adamson bitmask[1] & nfs4_fsinfo_bitmap[1], hdr); 10671da177e4SLinus Torvalds } 10681da177e4SLinus Torvalds 1069cf8cdbe5SAndy Adamson static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 1070830b8e33SManoj Naik { 1071cf8cdbe5SAndy Adamson encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0], 1072cf8cdbe5SAndy Adamson bitmask[1] & nfs4_fs_locations_bitmap[1], hdr); 1073830b8e33SManoj Naik } 1074830b8e33SManoj Naik 1075cf8cdbe5SAndy Adamson static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr) 10761da177e4SLinus Torvalds { 10778687b63aSAl Viro __be32 *p; 10781da177e4SLinus Torvalds 107913c65ce9SBenny Halevy p = reserve_space(xdr, 4); 108034558513SBenny Halevy *p = cpu_to_be32(OP_GETFH); 1081d017931cSAndy Adamson hdr->nops++; 1082dadf0c27SBenny Halevy hdr->replen += decode_getfh_maxsz; 10831da177e4SLinus Torvalds } 10841da177e4SLinus Torvalds 1085cf8cdbe5SAndy Adamson static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 10861da177e4SLinus Torvalds { 10878687b63aSAl Viro __be32 *p; 10881da177e4SLinus Torvalds 108913c65ce9SBenny Halevy p = reserve_space(xdr, 8 + name->len); 1090e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_LINK); 1091811652bdSBenny Halevy xdr_encode_opaque(p, name->name, name->len); 1092d017931cSAndy Adamson hdr->nops++; 1093dadf0c27SBenny Halevy hdr->replen += decode_link_maxsz; 10941da177e4SLinus Torvalds } 10951da177e4SLinus Torvalds 1096911d1aafSTrond Myklebust static inline int nfs4_lock_type(struct file_lock *fl, int block) 1097911d1aafSTrond Myklebust { 1098911d1aafSTrond Myklebust if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK) 1099911d1aafSTrond Myklebust return block ? NFS4_READW_LT : NFS4_READ_LT; 1100911d1aafSTrond Myklebust return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; 1101911d1aafSTrond Myklebust } 1102911d1aafSTrond Myklebust 1103911d1aafSTrond Myklebust static inline uint64_t nfs4_lock_length(struct file_lock *fl) 1104911d1aafSTrond Myklebust { 1105911d1aafSTrond Myklebust if (fl->fl_end == OFFSET_MAX) 1106911d1aafSTrond Myklebust return ~(uint64_t)0; 1107911d1aafSTrond Myklebust return fl->fl_end - fl->fl_start + 1; 1108911d1aafSTrond Myklebust } 1109911d1aafSTrond Myklebust 1110daccbdedSTrond Myklebust static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner) 1111daccbdedSTrond Myklebust { 1112daccbdedSTrond Myklebust __be32 *p; 1113daccbdedSTrond Myklebust 1114d035c36cSTrond Myklebust p = reserve_space(xdr, 32); 1115daccbdedSTrond Myklebust p = xdr_encode_hyper(p, lowner->clientid); 1116d035c36cSTrond Myklebust *p++ = cpu_to_be32(20); 1117daccbdedSTrond Myklebust p = xdr_encode_opaque_fixed(p, "lock id:", 8); 1118d035c36cSTrond Myklebust *p++ = cpu_to_be32(lowner->s_dev); 1119daccbdedSTrond Myklebust xdr_encode_hyper(p, lowner->id); 1120daccbdedSTrond Myklebust } 1121daccbdedSTrond Myklebust 11221da177e4SLinus Torvalds /* 11231da177e4SLinus Torvalds * opcode,type,reclaim,offset,length,new_lock_owner = 32 11241da177e4SLinus Torvalds * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 11251da177e4SLinus Torvalds */ 1126cf8cdbe5SAndy Adamson static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr) 11271da177e4SLinus Torvalds { 11288687b63aSAl Viro __be32 *p; 11291da177e4SLinus Torvalds 113013c65ce9SBenny Halevy p = reserve_space(xdr, 32); 1131e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_LOCK); 1132e75bc1c8SBenny Halevy *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block)); 1133e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->reclaim); 1134b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 1135b95be5a9SBenny Halevy p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 113634558513SBenny Halevy *p = cpu_to_be32(args->new_lock_owner); 1137911d1aafSTrond Myklebust if (args->new_lock_owner){ 1138daccbdedSTrond Myklebust p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); 1139e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->open_seqid->sequence->counter); 114093f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, args->open_stateid->data, NFS4_STATEID_SIZE); 1141e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->lock_seqid->sequence->counter); 1142daccbdedSTrond Myklebust encode_lockowner(xdr, &args->lock_owner); 11431da177e4SLinus Torvalds } 11441da177e4SLinus Torvalds else { 114513c65ce9SBenny Halevy p = reserve_space(xdr, NFS4_STATEID_SIZE+4); 114693f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, args->lock_stateid->data, NFS4_STATEID_SIZE); 114734558513SBenny Halevy *p = cpu_to_be32(args->lock_seqid->sequence->counter); 11481da177e4SLinus Torvalds } 1149d017931cSAndy Adamson hdr->nops++; 1150dadf0c27SBenny Halevy hdr->replen += decode_lock_maxsz; 11511da177e4SLinus Torvalds } 11521da177e4SLinus Torvalds 1153cf8cdbe5SAndy Adamson static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr) 11541da177e4SLinus Torvalds { 11558687b63aSAl Viro __be32 *p; 11561da177e4SLinus Torvalds 1157daccbdedSTrond Myklebust p = reserve_space(xdr, 24); 1158e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_LOCKT); 1159e75bc1c8SBenny Halevy *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); 1160b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 1161b95be5a9SBenny Halevy p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 1162daccbdedSTrond Myklebust encode_lockowner(xdr, &args->lock_owner); 1163d017931cSAndy Adamson hdr->nops++; 1164dadf0c27SBenny Halevy hdr->replen += decode_lockt_maxsz; 11651da177e4SLinus Torvalds } 11661da177e4SLinus Torvalds 1167cf8cdbe5SAndy Adamson static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr) 11681da177e4SLinus Torvalds { 11698687b63aSAl Viro __be32 *p; 11701da177e4SLinus Torvalds 117113c65ce9SBenny Halevy p = reserve_space(xdr, 12+NFS4_STATEID_SIZE+16); 1172e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_LOCKU); 1173e75bc1c8SBenny Halevy *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); 1174e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->seqid->sequence->counter); 117593f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); 1176b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->fl->fl_start); 117734558513SBenny Halevy xdr_encode_hyper(p, nfs4_lock_length(args->fl)); 1178d017931cSAndy Adamson hdr->nops++; 1179dadf0c27SBenny Halevy hdr->replen += decode_locku_maxsz; 11801da177e4SLinus Torvalds } 11811da177e4SLinus Torvalds 1182d3c7b7ccSTrond Myklebust static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr) 1183d3c7b7ccSTrond Myklebust { 1184d3c7b7ccSTrond Myklebust __be32 *p; 1185d3c7b7ccSTrond Myklebust 1186d3c7b7ccSTrond Myklebust p = reserve_space(xdr, 4); 1187d3c7b7ccSTrond Myklebust *p = cpu_to_be32(OP_RELEASE_LOCKOWNER); 1188d3c7b7ccSTrond Myklebust encode_lockowner(xdr, lowner); 1189d3c7b7ccSTrond Myklebust hdr->nops++; 1190d3c7b7ccSTrond Myklebust hdr->replen += decode_release_lockowner_maxsz; 1191d3c7b7ccSTrond Myklebust } 1192d3c7b7ccSTrond Myklebust 1193cf8cdbe5SAndy Adamson static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 11941da177e4SLinus Torvalds { 11951da177e4SLinus Torvalds int len = name->len; 11968687b63aSAl Viro __be32 *p; 11971da177e4SLinus Torvalds 119813c65ce9SBenny Halevy p = reserve_space(xdr, 8 + len); 1199e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_LOOKUP); 1200811652bdSBenny Halevy xdr_encode_opaque(p, name->name, len); 1201d017931cSAndy Adamson hdr->nops++; 1202dadf0c27SBenny Halevy hdr->replen += decode_lookup_maxsz; 12031da177e4SLinus Torvalds } 12041da177e4SLinus Torvalds 1205dc0b027dSTrond Myklebust static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode) 12061da177e4SLinus Torvalds { 12078687b63aSAl Viro __be32 *p; 12081da177e4SLinus Torvalds 120913c65ce9SBenny Halevy p = reserve_space(xdr, 8); 1210dc0b027dSTrond Myklebust switch (fmode & (FMODE_READ|FMODE_WRITE)) { 12111da177e4SLinus Torvalds case FMODE_READ: 1212e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ); 12131da177e4SLinus Torvalds break; 12141da177e4SLinus Torvalds case FMODE_WRITE: 1215e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE); 12161da177e4SLinus Torvalds break; 12171da177e4SLinus Torvalds case FMODE_READ|FMODE_WRITE: 1218e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH); 12191da177e4SLinus Torvalds break; 12201da177e4SLinus Torvalds default: 1221e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); 12221da177e4SLinus Torvalds } 122334558513SBenny Halevy *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */ 12241da177e4SLinus Torvalds } 12251da177e4SLinus Torvalds 12261da177e4SLinus Torvalds static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg) 12271da177e4SLinus Torvalds { 12288687b63aSAl Viro __be32 *p; 12291da177e4SLinus Torvalds /* 12301da177e4SLinus Torvalds * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, 12311da177e4SLinus Torvalds * owner 4 = 32 12321da177e4SLinus Torvalds */ 123313c65ce9SBenny Halevy p = reserve_space(xdr, 8); 1234e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_OPEN); 123534558513SBenny Halevy *p = cpu_to_be32(arg->seqid->sequence->counter); 1236dc0b027dSTrond Myklebust encode_share_access(xdr, arg->fmode); 1237d035c36cSTrond Myklebust p = reserve_space(xdr, 32); 1238b95be5a9SBenny Halevy p = xdr_encode_hyper(p, arg->clientid); 1239d035c36cSTrond Myklebust *p++ = cpu_to_be32(20); 124093f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, "open id:", 8); 1241d035c36cSTrond Myklebust *p++ = cpu_to_be32(arg->server->s_dev); 124234558513SBenny Halevy xdr_encode_hyper(p, arg->id); 12431da177e4SLinus Torvalds } 12441da177e4SLinus Torvalds 12451da177e4SLinus Torvalds static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) 12461da177e4SLinus Torvalds { 12478687b63aSAl Viro __be32 *p; 12484882ef72SAlexandros Batsakis struct nfs_client *clp; 12491da177e4SLinus Torvalds 125013c65ce9SBenny Halevy p = reserve_space(xdr, 4); 12511da177e4SLinus Torvalds switch(arg->open_flags & O_EXCL) { 12521da177e4SLinus Torvalds case 0: 125334558513SBenny Halevy *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); 12541da177e4SLinus Torvalds encode_attrs(xdr, arg->u.attrs, arg->server); 12551da177e4SLinus Torvalds break; 12561da177e4SLinus Torvalds default: 12574882ef72SAlexandros Batsakis clp = arg->server->nfs_client; 1258a4432345STrond Myklebust if (clp->cl_mvops->minor_version > 0) { 12594882ef72SAlexandros Batsakis if (nfs4_has_persistent_session(clp)) { 12604882ef72SAlexandros Batsakis *p = cpu_to_be32(NFS4_CREATE_GUARDED); 12614882ef72SAlexandros Batsakis encode_attrs(xdr, arg->u.attrs, arg->server); 12624882ef72SAlexandros Batsakis } else { 12634882ef72SAlexandros Batsakis struct iattr dummy; 12644882ef72SAlexandros Batsakis 12654882ef72SAlexandros Batsakis *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); 12664882ef72SAlexandros Batsakis encode_nfs4_verifier(xdr, &arg->u.verifier); 12674882ef72SAlexandros Batsakis dummy.ia_valid = 0; 12684882ef72SAlexandros Batsakis encode_attrs(xdr, &dummy, arg->server); 12694882ef72SAlexandros Batsakis } 12704882ef72SAlexandros Batsakis } else { 127134558513SBenny Halevy *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); 12721da177e4SLinus Torvalds encode_nfs4_verifier(xdr, &arg->u.verifier); 12731da177e4SLinus Torvalds } 12741da177e4SLinus Torvalds } 12754882ef72SAlexandros Batsakis } 12761da177e4SLinus Torvalds 12771da177e4SLinus Torvalds static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg) 12781da177e4SLinus Torvalds { 12798687b63aSAl Viro __be32 *p; 12801da177e4SLinus Torvalds 128113c65ce9SBenny Halevy p = reserve_space(xdr, 4); 12821da177e4SLinus Torvalds switch (arg->open_flags & O_CREAT) { 12831da177e4SLinus Torvalds case 0: 128434558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_NOCREATE); 12851da177e4SLinus Torvalds break; 12861da177e4SLinus Torvalds default: 12871da177e4SLinus Torvalds BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL); 128834558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CREATE); 12891da177e4SLinus Torvalds encode_createmode(xdr, arg); 12901da177e4SLinus Torvalds } 12911da177e4SLinus Torvalds } 12921da177e4SLinus Torvalds 1293bd7bf9d5STrond Myklebust static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type) 12941da177e4SLinus Torvalds { 12958687b63aSAl Viro __be32 *p; 12961da177e4SLinus Torvalds 129713c65ce9SBenny Halevy p = reserve_space(xdr, 4); 12981da177e4SLinus Torvalds switch (delegation_type) { 12991da177e4SLinus Torvalds case 0: 130034558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE); 13011da177e4SLinus Torvalds break; 13021da177e4SLinus Torvalds case FMODE_READ: 130334558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ); 13041da177e4SLinus Torvalds break; 13051da177e4SLinus Torvalds case FMODE_WRITE|FMODE_READ: 130634558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE); 13071da177e4SLinus Torvalds break; 13081da177e4SLinus Torvalds default: 13091da177e4SLinus Torvalds BUG(); 13101da177e4SLinus Torvalds } 13111da177e4SLinus Torvalds } 13121da177e4SLinus Torvalds 13131da177e4SLinus Torvalds static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name) 13141da177e4SLinus Torvalds { 13158687b63aSAl Viro __be32 *p; 13161da177e4SLinus Torvalds 131713c65ce9SBenny Halevy p = reserve_space(xdr, 4); 131834558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL); 13191da177e4SLinus Torvalds encode_string(xdr, name->len, name->name); 13201da177e4SLinus Torvalds } 13211da177e4SLinus Torvalds 1322bd7bf9d5STrond Myklebust static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type) 13231da177e4SLinus Torvalds { 13248687b63aSAl Viro __be32 *p; 13251da177e4SLinus Torvalds 132613c65ce9SBenny Halevy p = reserve_space(xdr, 4); 132734558513SBenny Halevy *p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS); 13281da177e4SLinus Torvalds encode_delegation_type(xdr, type); 13291da177e4SLinus Torvalds } 13301da177e4SLinus Torvalds 13311da177e4SLinus Torvalds static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid) 13321da177e4SLinus Torvalds { 13338687b63aSAl Viro __be32 *p; 13341da177e4SLinus Torvalds 133513c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); 1336e75bc1c8SBenny Halevy *p++ = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR); 133734558513SBenny Halevy xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE); 13381da177e4SLinus Torvalds encode_string(xdr, name->len, name->name); 13391da177e4SLinus Torvalds } 13401da177e4SLinus Torvalds 1341cf8cdbe5SAndy Adamson static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr) 13421da177e4SLinus Torvalds { 13431da177e4SLinus Torvalds encode_openhdr(xdr, arg); 13441da177e4SLinus Torvalds encode_opentype(xdr, arg); 13451da177e4SLinus Torvalds switch (arg->claim) { 13461da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_NULL: 13471da177e4SLinus Torvalds encode_claim_null(xdr, arg->name); 13481da177e4SLinus Torvalds break; 13491da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_PREVIOUS: 13501da177e4SLinus Torvalds encode_claim_previous(xdr, arg->u.delegation_type); 13511da177e4SLinus Torvalds break; 13521da177e4SLinus Torvalds case NFS4_OPEN_CLAIM_DELEGATE_CUR: 13531da177e4SLinus Torvalds encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation); 13541da177e4SLinus Torvalds break; 13551da177e4SLinus Torvalds default: 13561da177e4SLinus Torvalds BUG(); 13571da177e4SLinus Torvalds } 1358d017931cSAndy Adamson hdr->nops++; 1359dadf0c27SBenny Halevy hdr->replen += decode_open_maxsz; 13601da177e4SLinus Torvalds } 13611da177e4SLinus Torvalds 1362cf8cdbe5SAndy Adamson static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr) 13631da177e4SLinus Torvalds { 13648687b63aSAl Viro __be32 *p; 13651da177e4SLinus Torvalds 136613c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); 1367e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_OPEN_CONFIRM); 136893f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); 136934558513SBenny Halevy *p = cpu_to_be32(arg->seqid->sequence->counter); 1370d017931cSAndy Adamson hdr->nops++; 1371dadf0c27SBenny Halevy hdr->replen += decode_open_confirm_maxsz; 13721da177e4SLinus Torvalds } 13731da177e4SLinus Torvalds 1374cf8cdbe5SAndy Adamson static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) 13751da177e4SLinus Torvalds { 13768687b63aSAl Viro __be32 *p; 13771da177e4SLinus Torvalds 137813c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); 1379e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_OPEN_DOWNGRADE); 138093f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); 138134558513SBenny Halevy *p = cpu_to_be32(arg->seqid->sequence->counter); 1382dc0b027dSTrond Myklebust encode_share_access(xdr, arg->fmode); 1383d017931cSAndy Adamson hdr->nops++; 1384dadf0c27SBenny Halevy hdr->replen += decode_open_downgrade_maxsz; 13851da177e4SLinus Torvalds } 13861da177e4SLinus Torvalds 1387cf8cdbe5SAndy Adamson static void 1388d017931cSAndy Adamson encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr) 13891da177e4SLinus Torvalds { 13901da177e4SLinus Torvalds int len = fh->size; 13918687b63aSAl Viro __be32 *p; 13921da177e4SLinus Torvalds 139313c65ce9SBenny Halevy p = reserve_space(xdr, 8 + len); 1394e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_PUTFH); 1395811652bdSBenny Halevy xdr_encode_opaque(p, fh->data, len); 1396d017931cSAndy Adamson hdr->nops++; 1397dadf0c27SBenny Halevy hdr->replen += decode_putfh_maxsz; 13981da177e4SLinus Torvalds } 13991da177e4SLinus Torvalds 1400cf8cdbe5SAndy Adamson static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr) 14011da177e4SLinus Torvalds { 14028687b63aSAl Viro __be32 *p; 14031da177e4SLinus Torvalds 140413c65ce9SBenny Halevy p = reserve_space(xdr, 4); 140534558513SBenny Halevy *p = cpu_to_be32(OP_PUTROOTFH); 1406d017931cSAndy Adamson hdr->nops++; 1407dadf0c27SBenny Halevy hdr->replen += decode_putrootfh_maxsz; 14081da177e4SLinus Torvalds } 14091da177e4SLinus Torvalds 141089d1ea65SAndy 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) 14111da177e4SLinus Torvalds { 14121da177e4SLinus Torvalds nfs4_stateid stateid; 14138687b63aSAl Viro __be32 *p; 14141da177e4SLinus Torvalds 141513c65ce9SBenny Halevy p = reserve_space(xdr, NFS4_STATEID_SIZE); 14161da177e4SLinus Torvalds if (ctx->state != NULL) { 141777041ed9STrond Myklebust nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid); 141889d1ea65SAndy Adamson if (zero_seqid) 141989d1ea65SAndy Adamson stateid.stateid.seqid = 0; 142034558513SBenny Halevy xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE); 14211da177e4SLinus Torvalds } else 142234558513SBenny Halevy xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); 14231da177e4SLinus Torvalds } 14241da177e4SLinus Torvalds 1425cf8cdbe5SAndy Adamson static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, struct compound_hdr *hdr) 14261da177e4SLinus Torvalds { 14278687b63aSAl Viro __be32 *p; 14281da177e4SLinus Torvalds 142913c65ce9SBenny Halevy p = reserve_space(xdr, 4); 143034558513SBenny Halevy *p = cpu_to_be32(OP_READ); 14311da177e4SLinus Torvalds 143289d1ea65SAndy Adamson encode_stateid(xdr, args->context, args->lock_context, 143389d1ea65SAndy Adamson hdr->minorversion); 14341da177e4SLinus Torvalds 143513c65ce9SBenny Halevy p = reserve_space(xdr, 12); 1436b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 143734558513SBenny Halevy *p = cpu_to_be32(args->count); 1438d017931cSAndy Adamson hdr->nops++; 1439dadf0c27SBenny Halevy hdr->replen += decode_read_maxsz; 14401da177e4SLinus Torvalds } 14411da177e4SLinus Torvalds 1442cf8cdbe5SAndy Adamson static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) 14431da177e4SLinus Torvalds { 144482f2e547SBryan Schumaker uint32_t attrs[2] = {0, 0}; 14456f7a35bdSTrond Myklebust uint32_t dircount = readdir->count >> 1; 14468687b63aSAl Viro __be32 *p; 14471da177e4SLinus Torvalds 144882f2e547SBryan Schumaker if (readdir->plus) { 144982f2e547SBryan Schumaker attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| 145082f2e547SBryan Schumaker FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE; 145182f2e547SBryan Schumaker attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER| 145282f2e547SBryan Schumaker FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| 145382f2e547SBryan Schumaker FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| 145482f2e547SBryan Schumaker FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; 14556f7a35bdSTrond Myklebust dircount >>= 1; 145682f2e547SBryan Schumaker } 145782f2e547SBryan Schumaker attrs[0] |= FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID; 145882f2e547SBryan Schumaker attrs[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID; 145997d312d0SManoj Naik /* Switch to mounted_on_fileid if the server supports it */ 146097d312d0SManoj Naik if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) 146197d312d0SManoj Naik attrs[0] &= ~FATTR4_WORD0_FILEID; 146297d312d0SManoj Naik else 146397d312d0SManoj Naik attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; 14646f7a35bdSTrond Myklebust 14656f7a35bdSTrond Myklebust p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20); 14666f7a35bdSTrond Myklebust *p++ = cpu_to_be32(OP_READDIR); 14676f7a35bdSTrond Myklebust p = xdr_encode_hyper(p, readdir->cookie); 14686f7a35bdSTrond Myklebust p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE); 14696f7a35bdSTrond Myklebust *p++ = cpu_to_be32(dircount); 14706f7a35bdSTrond Myklebust *p++ = cpu_to_be32(readdir->count); 14716f7a35bdSTrond Myklebust *p++ = cpu_to_be32(2); 147282f2e547SBryan Schumaker 1473e75bc1c8SBenny Halevy *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); 147434558513SBenny Halevy *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); 1475d017931cSAndy Adamson hdr->nops++; 1476dadf0c27SBenny Halevy hdr->replen += decode_readdir_maxsz; 147744109241SFred Isaman dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", 147844109241SFred Isaman __func__, 1479eadf4598STrond Myklebust (unsigned long long)readdir->cookie, 1480eadf4598STrond Myklebust ((u32 *)readdir->verifier.data)[0], 1481eadf4598STrond Myklebust ((u32 *)readdir->verifier.data)[1], 1482eadf4598STrond Myklebust attrs[0] & readdir->bitmask[0], 1483eadf4598STrond Myklebust attrs[1] & readdir->bitmask[1]); 14841da177e4SLinus Torvalds } 14851da177e4SLinus Torvalds 1486cf8cdbe5SAndy Adamson static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) 14871da177e4SLinus Torvalds { 14888687b63aSAl Viro __be32 *p; 14891da177e4SLinus Torvalds 149013c65ce9SBenny Halevy p = reserve_space(xdr, 4); 149134558513SBenny Halevy *p = cpu_to_be32(OP_READLINK); 1492d017931cSAndy Adamson hdr->nops++; 1493dadf0c27SBenny Halevy hdr->replen += decode_readlink_maxsz; 14941da177e4SLinus Torvalds } 14951da177e4SLinus Torvalds 1496cf8cdbe5SAndy Adamson static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 14971da177e4SLinus Torvalds { 14988687b63aSAl Viro __be32 *p; 14991da177e4SLinus Torvalds 150013c65ce9SBenny Halevy p = reserve_space(xdr, 8 + name->len); 1501e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_REMOVE); 1502811652bdSBenny Halevy xdr_encode_opaque(p, name->name, name->len); 1503d017931cSAndy Adamson hdr->nops++; 1504dadf0c27SBenny Halevy hdr->replen += decode_remove_maxsz; 15051da177e4SLinus Torvalds } 15061da177e4SLinus Torvalds 1507cf8cdbe5SAndy Adamson static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr) 15081da177e4SLinus Torvalds { 15098687b63aSAl Viro __be32 *p; 15101da177e4SLinus Torvalds 1511811652bdSBenny Halevy p = reserve_space(xdr, 4); 1512811652bdSBenny Halevy *p = cpu_to_be32(OP_RENAME); 1513811652bdSBenny Halevy encode_string(xdr, oldname->len, oldname->name); 1514811652bdSBenny Halevy encode_string(xdr, newname->len, newname->name); 1515d017931cSAndy Adamson hdr->nops++; 1516dadf0c27SBenny Halevy hdr->replen += decode_rename_maxsz; 15171da177e4SLinus Torvalds } 15181da177e4SLinus Torvalds 1519cf8cdbe5SAndy Adamson static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid, struct compound_hdr *hdr) 15201da177e4SLinus Torvalds { 15218687b63aSAl Viro __be32 *p; 15221da177e4SLinus Torvalds 152313c65ce9SBenny Halevy p = reserve_space(xdr, 12); 1524e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_RENEW); 152534558513SBenny Halevy xdr_encode_hyper(p, client_stateid->cl_clientid); 1526d017931cSAndy Adamson hdr->nops++; 1527dadf0c27SBenny Halevy hdr->replen += decode_renew_maxsz; 15281da177e4SLinus Torvalds } 15291da177e4SLinus Torvalds 1530cf8cdbe5SAndy Adamson static void 1531d017931cSAndy Adamson encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr) 153256ae19f3STrond Myklebust { 15338687b63aSAl Viro __be32 *p; 153456ae19f3STrond Myklebust 153513c65ce9SBenny Halevy p = reserve_space(xdr, 4); 153634558513SBenny Halevy *p = cpu_to_be32(OP_RESTOREFH); 1537d017931cSAndy Adamson hdr->nops++; 1538dadf0c27SBenny Halevy hdr->replen += decode_restorefh_maxsz; 153956ae19f3STrond Myklebust } 154056ae19f3STrond Myklebust 15419f06c719SChuck Lever static void 1542d017931cSAndy Adamson encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compound_hdr *hdr) 154323ec6965SJ. Bruce Fields { 15448687b63aSAl Viro __be32 *p; 154523ec6965SJ. Bruce Fields 154613c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); 1547e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_SETATTR); 154834558513SBenny Halevy xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); 154913c65ce9SBenny Halevy p = reserve_space(xdr, 2*4); 1550e75bc1c8SBenny Halevy *p++ = cpu_to_be32(1); 155134558513SBenny Halevy *p = cpu_to_be32(FATTR4_WORD0_ACL); 15529f06c719SChuck Lever BUG_ON(arg->acl_len % 4); 155313c65ce9SBenny Halevy p = reserve_space(xdr, 4); 155434558513SBenny Halevy *p = cpu_to_be32(arg->acl_len); 155523ec6965SJ. Bruce Fields xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); 1556d017931cSAndy Adamson hdr->nops++; 1557dadf0c27SBenny Halevy hdr->replen += decode_setacl_maxsz; 155823ec6965SJ. Bruce Fields } 155923ec6965SJ. Bruce Fields 1560cf8cdbe5SAndy Adamson static void 1561d017931cSAndy Adamson encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr) 15621da177e4SLinus Torvalds { 15638687b63aSAl Viro __be32 *p; 15641da177e4SLinus Torvalds 156513c65ce9SBenny Halevy p = reserve_space(xdr, 4); 156634558513SBenny Halevy *p = cpu_to_be32(OP_SAVEFH); 1567d017931cSAndy Adamson hdr->nops++; 1568dadf0c27SBenny Halevy hdr->replen += decode_savefh_maxsz; 15691da177e4SLinus Torvalds } 15701da177e4SLinus Torvalds 1571cf8cdbe5SAndy Adamson static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr) 15721da177e4SLinus Torvalds { 15738687b63aSAl Viro __be32 *p; 15741da177e4SLinus Torvalds 157513c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); 1576e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_SETATTR); 157734558513SBenny Halevy xdr_encode_opaque_fixed(p, arg->stateid.data, NFS4_STATEID_SIZE); 1578d017931cSAndy Adamson hdr->nops++; 1579dadf0c27SBenny Halevy hdr->replen += decode_setattr_maxsz; 1580cf8cdbe5SAndy Adamson encode_attrs(xdr, arg->iap, server); 15811da177e4SLinus Torvalds } 15821da177e4SLinus Torvalds 1583cf8cdbe5SAndy Adamson static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) 15841da177e4SLinus Torvalds { 15858687b63aSAl Viro __be32 *p; 15861da177e4SLinus Torvalds 158713c65ce9SBenny Halevy p = reserve_space(xdr, 4 + NFS4_VERIFIER_SIZE); 1588e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_SETCLIENTID); 158934558513SBenny Halevy xdr_encode_opaque_fixed(p, setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE); 15901da177e4SLinus Torvalds 15911da177e4SLinus Torvalds encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name); 159213c65ce9SBenny Halevy p = reserve_space(xdr, 4); 159334558513SBenny Halevy *p = cpu_to_be32(setclientid->sc_prog); 15941da177e4SLinus Torvalds encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid); 15951da177e4SLinus Torvalds encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr); 159613c65ce9SBenny Halevy p = reserve_space(xdr, 4); 159734558513SBenny Halevy *p = cpu_to_be32(setclientid->sc_cb_ident); 1598d017931cSAndy Adamson hdr->nops++; 1599dadf0c27SBenny Halevy hdr->replen += decode_setclientid_maxsz; 16001da177e4SLinus Torvalds } 16011da177e4SLinus Torvalds 1602bb8b27e5STrond Myklebust static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr) 16031da177e4SLinus Torvalds { 16048687b63aSAl Viro __be32 *p; 16051da177e4SLinus Torvalds 160613c65ce9SBenny Halevy p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE); 1607e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM); 1608bb8b27e5STrond Myklebust p = xdr_encode_hyper(p, arg->clientid); 1609bb8b27e5STrond Myklebust xdr_encode_opaque_fixed(p, arg->confirm.data, NFS4_VERIFIER_SIZE); 1610d017931cSAndy Adamson hdr->nops++; 1611dadf0c27SBenny Halevy hdr->replen += decode_setclientid_confirm_maxsz; 16121da177e4SLinus Torvalds } 16131da177e4SLinus Torvalds 1614cf8cdbe5SAndy Adamson static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) 16151da177e4SLinus Torvalds { 16168687b63aSAl Viro __be32 *p; 16171da177e4SLinus Torvalds 161813c65ce9SBenny Halevy p = reserve_space(xdr, 4); 161934558513SBenny Halevy *p = cpu_to_be32(OP_WRITE); 16201da177e4SLinus Torvalds 162189d1ea65SAndy Adamson encode_stateid(xdr, args->context, args->lock_context, 162289d1ea65SAndy Adamson hdr->minorversion); 16231da177e4SLinus Torvalds 162413c65ce9SBenny Halevy p = reserve_space(xdr, 16); 1625b95be5a9SBenny Halevy p = xdr_encode_hyper(p, args->offset); 1626e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->stable); 162734558513SBenny Halevy *p = cpu_to_be32(args->count); 16281da177e4SLinus Torvalds 16291da177e4SLinus Torvalds xdr_write_pages(xdr, args->pages, args->pgbase, args->count); 1630d017931cSAndy Adamson hdr->nops++; 1631dadf0c27SBenny Halevy hdr->replen += decode_write_maxsz; 16321da177e4SLinus Torvalds } 16331da177e4SLinus Torvalds 1634cf8cdbe5SAndy Adamson static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr) 16351da177e4SLinus Torvalds { 16368687b63aSAl Viro __be32 *p; 16371da177e4SLinus Torvalds 163813c65ce9SBenny Halevy p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); 16391da177e4SLinus Torvalds 1640e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_DELEGRETURN); 164134558513SBenny Halevy xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE); 1642d017931cSAndy Adamson hdr->nops++; 1643dadf0c27SBenny Halevy hdr->replen += decode_delegreturn_maxsz; 16441da177e4SLinus Torvalds } 16459b7b9fccSAndy Adamson 164699fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 16479b7b9fccSAndy Adamson /* NFSv4.1 operations */ 164899fe60d0SBenny Halevy static void encode_exchange_id(struct xdr_stream *xdr, 164999fe60d0SBenny Halevy struct nfs41_exchange_id_args *args, 165099fe60d0SBenny Halevy struct compound_hdr *hdr) 165199fe60d0SBenny Halevy { 165299fe60d0SBenny Halevy __be32 *p; 165399fe60d0SBenny Halevy 165413c65ce9SBenny Halevy p = reserve_space(xdr, 4 + sizeof(args->verifier->data)); 1655e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_EXCHANGE_ID); 165634558513SBenny Halevy xdr_encode_opaque_fixed(p, args->verifier->data, sizeof(args->verifier->data)); 165799fe60d0SBenny Halevy 165899fe60d0SBenny Halevy encode_string(xdr, args->id_len, args->id); 165999fe60d0SBenny Halevy 166013c65ce9SBenny Halevy p = reserve_space(xdr, 12); 1661e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->flags); 1662e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* zero length state_protect4_a */ 166334558513SBenny Halevy *p = cpu_to_be32(0); /* zero length implementation id array */ 166499fe60d0SBenny Halevy hdr->nops++; 166599fe60d0SBenny Halevy hdr->replen += decode_exchange_id_maxsz; 166699fe60d0SBenny Halevy } 1667fc931582SAndy Adamson 1668fc931582SAndy Adamson static void encode_create_session(struct xdr_stream *xdr, 1669fc931582SAndy Adamson struct nfs41_create_session_args *args, 1670fc931582SAndy Adamson struct compound_hdr *hdr) 1671fc931582SAndy Adamson { 1672fc931582SAndy Adamson __be32 *p; 1673fc931582SAndy Adamson char machine_name[NFS4_MAX_MACHINE_NAME_LEN]; 1674fc931582SAndy Adamson uint32_t len; 1675fc931582SAndy Adamson struct nfs_client *clp = args->client; 16768e0d46e1SMike Sager u32 max_resp_sz_cached; 16778e0d46e1SMike Sager 16788e0d46e1SMike Sager /* 16798e0d46e1SMike Sager * Assumes OPEN is the biggest non-idempotent compound. 16808e0d46e1SMike Sager * 2 is the verifier. 16818e0d46e1SMike Sager */ 16828e0d46e1SMike Sager max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + 16838e0d46e1SMike Sager RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT; 1684fc931582SAndy Adamson 1685fc931582SAndy Adamson len = scnprintf(machine_name, sizeof(machine_name), "%s", 1686fc931582SAndy Adamson clp->cl_ipaddr); 168742edd698SBenny Halevy 168813c65ce9SBenny Halevy p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12); 1689e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_CREATE_SESSION); 1690114f64b5SAndy Adamson p = xdr_encode_hyper(p, clp->cl_clientid); 1691e75bc1c8SBenny Halevy *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ 1692e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->flags); /*flags */ 1693fc931582SAndy Adamson 1694fc931582SAndy Adamson /* Fore Channel */ 1695e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ 1696e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ 1697e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ 16988e0d46e1SMike Sager *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ 1699e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */ 1700e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */ 1701e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ 1702fc931582SAndy Adamson 1703fc931582SAndy Adamson /* Back Channel */ 1704e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ 1705e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ 1706e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ 1707e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ 1708e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */ 1709e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */ 1710e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ 1711fc931582SAndy Adamson 1712e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->cb_program); /* cb_program */ 1713e75bc1c8SBenny Halevy *p++ = cpu_to_be32(1); 1714e75bc1c8SBenny Halevy *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ 1715fc931582SAndy Adamson 1716fc931582SAndy Adamson /* authsys_parms rfc1831 */ 1717e75bc1c8SBenny Halevy *p++ = cpu_to_be32((u32)clp->cl_boot_time.tv_nsec); /* stamp */ 1718811652bdSBenny Halevy p = xdr_encode_opaque(p, machine_name, len); 1719e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* UID */ 1720e75bc1c8SBenny Halevy *p++ = cpu_to_be32(0); /* GID */ 172134558513SBenny Halevy *p = cpu_to_be32(0); /* No more gids */ 1722fc931582SAndy Adamson hdr->nops++; 1723fc931582SAndy Adamson hdr->replen += decode_create_session_maxsz; 1724fc931582SAndy Adamson } 17250f3e66c6SAndy Adamson 17260f3e66c6SAndy Adamson static void encode_destroy_session(struct xdr_stream *xdr, 17270f3e66c6SAndy Adamson struct nfs4_session *session, 17280f3e66c6SAndy Adamson struct compound_hdr *hdr) 17290f3e66c6SAndy Adamson { 17300f3e66c6SAndy Adamson __be32 *p; 173113c65ce9SBenny Halevy p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN); 1732e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_DESTROY_SESSION); 173334558513SBenny Halevy xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); 17340f3e66c6SAndy Adamson hdr->nops++; 17350f3e66c6SAndy Adamson hdr->replen += decode_destroy_session_maxsz; 17360f3e66c6SAndy Adamson } 173718019753SRicardo Labiaga 173818019753SRicardo Labiaga static void encode_reclaim_complete(struct xdr_stream *xdr, 173918019753SRicardo Labiaga struct nfs41_reclaim_complete_args *args, 174018019753SRicardo Labiaga struct compound_hdr *hdr) 174118019753SRicardo Labiaga { 174218019753SRicardo Labiaga __be32 *p; 174318019753SRicardo Labiaga 174418019753SRicardo Labiaga p = reserve_space(xdr, 8); 174518019753SRicardo Labiaga *p++ = cpu_to_be32(OP_RECLAIM_COMPLETE); 174618019753SRicardo Labiaga *p++ = cpu_to_be32(args->one_fs); 174718019753SRicardo Labiaga hdr->nops++; 174818019753SRicardo Labiaga hdr->replen += decode_reclaim_complete_maxsz; 174918019753SRicardo Labiaga } 175099fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 175199fe60d0SBenny Halevy 17529b7b9fccSAndy Adamson static void encode_sequence(struct xdr_stream *xdr, 17539b7b9fccSAndy Adamson const struct nfs4_sequence_args *args, 17549b7b9fccSAndy Adamson struct compound_hdr *hdr) 17559b7b9fccSAndy Adamson { 17569b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 17579b7b9fccSAndy Adamson struct nfs4_session *session = args->sa_session; 1758fc01cea9SAndy Adamson struct nfs4_slot_table *tp; 1759fc01cea9SAndy Adamson struct nfs4_slot *slot; 1760fc01cea9SAndy Adamson __be32 *p; 17619b7b9fccSAndy Adamson 17629b7b9fccSAndy Adamson if (!session) 17639b7b9fccSAndy Adamson return; 17649b7b9fccSAndy Adamson 1765fc01cea9SAndy Adamson tp = &session->fc_slot_table; 1766fc01cea9SAndy Adamson 1767fc01cea9SAndy Adamson WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE); 1768fc01cea9SAndy Adamson slot = tp->slots + args->sa_slotid; 1769fc01cea9SAndy Adamson 177013c65ce9SBenny Halevy p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN + 16); 1771e75bc1c8SBenny Halevy *p++ = cpu_to_be32(OP_SEQUENCE); 1772fc01cea9SAndy Adamson 1773fc01cea9SAndy Adamson /* 1774fc01cea9SAndy Adamson * Sessionid + seqid + slotid + max slotid + cache_this 1775fc01cea9SAndy Adamson */ 1776fc01cea9SAndy Adamson dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d " 1777fc01cea9SAndy Adamson "max_slotid=%d cache_this=%d\n", 1778fc01cea9SAndy Adamson __func__, 1779fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[0], 1780fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[1], 1781fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[2], 1782fc01cea9SAndy Adamson ((u32 *)session->sess_id.data)[3], 1783fc01cea9SAndy Adamson slot->seq_nr, args->sa_slotid, 1784fc01cea9SAndy Adamson tp->highest_used_slotid, args->sa_cache_this); 178593f0cf25SBenny Halevy p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); 1786e75bc1c8SBenny Halevy *p++ = cpu_to_be32(slot->seq_nr); 1787e75bc1c8SBenny Halevy *p++ = cpu_to_be32(args->sa_slotid); 1788e75bc1c8SBenny Halevy *p++ = cpu_to_be32(tp->highest_used_slotid); 178934558513SBenny Halevy *p = cpu_to_be32(args->sa_cache_this); 17909b7b9fccSAndy Adamson hdr->nops++; 17919b7b9fccSAndy Adamson hdr->replen += decode_sequence_maxsz; 17929b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 17939b7b9fccSAndy Adamson } 17949b7b9fccSAndy Adamson 1795b1f69b75SAndy Adamson #ifdef CONFIG_NFS_V4_1 1796b1f69b75SAndy Adamson static void 1797b1f69b75SAndy Adamson encode_getdeviceinfo(struct xdr_stream *xdr, 1798b1f69b75SAndy Adamson const struct nfs4_getdeviceinfo_args *args, 1799b1f69b75SAndy Adamson struct compound_hdr *hdr) 1800b1f69b75SAndy Adamson { 1801b1f69b75SAndy Adamson __be32 *p; 1802b1f69b75SAndy Adamson 1803b1f69b75SAndy Adamson p = reserve_space(xdr, 16 + NFS4_DEVICEID4_SIZE); 1804b1f69b75SAndy Adamson *p++ = cpu_to_be32(OP_GETDEVICEINFO); 1805b1f69b75SAndy Adamson p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, 1806b1f69b75SAndy Adamson NFS4_DEVICEID4_SIZE); 1807b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->pdev->layout_type); 1808b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->pdev->pglen); /* gdia_maxcount */ 1809b1f69b75SAndy Adamson *p++ = cpu_to_be32(0); /* bitmap length 0 */ 1810b1f69b75SAndy Adamson hdr->nops++; 1811b1f69b75SAndy Adamson hdr->replen += decode_getdeviceinfo_maxsz; 1812b1f69b75SAndy Adamson } 1813b1f69b75SAndy Adamson 1814b1f69b75SAndy Adamson static void 1815b1f69b75SAndy Adamson encode_layoutget(struct xdr_stream *xdr, 1816b1f69b75SAndy Adamson const struct nfs4_layoutget_args *args, 1817b1f69b75SAndy Adamson struct compound_hdr *hdr) 1818b1f69b75SAndy Adamson { 1819b1f69b75SAndy Adamson __be32 *p; 1820b1f69b75SAndy Adamson 1821b1f69b75SAndy Adamson p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); 1822b1f69b75SAndy Adamson *p++ = cpu_to_be32(OP_LAYOUTGET); 1823b1f69b75SAndy Adamson *p++ = cpu_to_be32(0); /* Signal layout available */ 1824b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->type); 1825b1f69b75SAndy Adamson *p++ = cpu_to_be32(args->range.iomode); 1826b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->range.offset); 1827b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->range.length); 1828b1f69b75SAndy Adamson p = xdr_encode_hyper(p, args->minlength); 1829cf7d63f1SFred Isaman p = xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE); 1830b1f69b75SAndy Adamson *p = cpu_to_be32(args->maxcount); 1831b1f69b75SAndy Adamson 1832b1f69b75SAndy Adamson dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", 1833b1f69b75SAndy Adamson __func__, 1834b1f69b75SAndy Adamson args->type, 1835b1f69b75SAndy Adamson args->range.iomode, 1836b1f69b75SAndy Adamson (unsigned long)args->range.offset, 1837b1f69b75SAndy Adamson (unsigned long)args->range.length, 1838b1f69b75SAndy Adamson args->maxcount); 1839b1f69b75SAndy Adamson hdr->nops++; 1840b1f69b75SAndy Adamson hdr->replen += decode_layoutget_maxsz; 1841b1f69b75SAndy Adamson } 1842863a3c6cSAndy Adamson 1843863a3c6cSAndy Adamson static int 1844863a3c6cSAndy Adamson encode_layoutcommit(struct xdr_stream *xdr, 1845863a3c6cSAndy Adamson const struct nfs4_layoutcommit_args *args, 1846863a3c6cSAndy Adamson struct compound_hdr *hdr) 1847863a3c6cSAndy Adamson { 1848863a3c6cSAndy Adamson __be32 *p; 1849863a3c6cSAndy Adamson 1850863a3c6cSAndy Adamson dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, 1851863a3c6cSAndy Adamson NFS_SERVER(args->inode)->pnfs_curr_ld->id); 1852863a3c6cSAndy Adamson 1853863a3c6cSAndy Adamson p = reserve_space(xdr, 48 + NFS4_STATEID_SIZE); 1854863a3c6cSAndy Adamson *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); 1855863a3c6cSAndy Adamson /* Only whole file layouts */ 1856863a3c6cSAndy Adamson p = xdr_encode_hyper(p, 0); /* offset */ 1857863a3c6cSAndy Adamson p = xdr_encode_hyper(p, NFS4_MAX_UINT64); /* length */ 1858863a3c6cSAndy Adamson *p++ = cpu_to_be32(0); /* reclaim */ 1859863a3c6cSAndy Adamson p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); 1860863a3c6cSAndy Adamson *p++ = cpu_to_be32(1); /* newoffset = TRUE */ 1861863a3c6cSAndy Adamson p = xdr_encode_hyper(p, args->lastbytewritten); 1862863a3c6cSAndy Adamson *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ 1863863a3c6cSAndy Adamson *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ 1864863a3c6cSAndy Adamson *p++ = cpu_to_be32(0); /* no file layout payload */ 1865863a3c6cSAndy Adamson 1866863a3c6cSAndy Adamson hdr->nops++; 1867863a3c6cSAndy Adamson hdr->replen += decode_layoutcommit_maxsz; 1868863a3c6cSAndy Adamson return 0; 1869863a3c6cSAndy Adamson } 1870b1f69b75SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 1871b1f69b75SAndy Adamson 18721da177e4SLinus Torvalds /* 18731da177e4SLinus Torvalds * END OF "GENERIC" ENCODE ROUTINES. 18741da177e4SLinus Torvalds */ 18751da177e4SLinus Torvalds 187666cc0429SBenny Halevy static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) 187766cc0429SBenny Halevy { 187866cc0429SBenny Halevy #if defined(CONFIG_NFS_V4_1) 187966cc0429SBenny Halevy if (args->sa_session) 1880a4432345STrond Myklebust return args->sa_session->clp->cl_mvops->minor_version; 188166cc0429SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 188266cc0429SBenny Halevy return 0; 188366cc0429SBenny Halevy } 188466cc0429SBenny Halevy 18851da177e4SLinus Torvalds /* 18861da177e4SLinus Torvalds * Encode an ACCESS request 18871da177e4SLinus Torvalds */ 18889f06c719SChuck Lever static void nfs4_xdr_enc_access(struct rpc_rqst *req, struct xdr_stream *xdr, 18899f06c719SChuck Lever const struct nfs4_accessargs *args) 18901da177e4SLinus Torvalds { 18911da177e4SLinus Torvalds struct compound_hdr hdr = { 189266cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 18931da177e4SLinus Torvalds }; 18941da177e4SLinus Torvalds 18959f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 18969f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 18979f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 18989f06c719SChuck Lever encode_access(xdr, args->access, &hdr); 18999f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 1900d017931cSAndy Adamson encode_nops(&hdr); 19011da177e4SLinus Torvalds } 19021da177e4SLinus Torvalds 19031da177e4SLinus Torvalds /* 19041da177e4SLinus Torvalds * Encode LOOKUP request 19051da177e4SLinus Torvalds */ 19069f06c719SChuck Lever static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr, 19079f06c719SChuck Lever const struct nfs4_lookup_arg *args) 19081da177e4SLinus Torvalds { 19091da177e4SLinus Torvalds struct compound_hdr hdr = { 191066cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 19111da177e4SLinus Torvalds }; 19121da177e4SLinus Torvalds 19139f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 19149f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 19159f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 19169f06c719SChuck Lever encode_lookup(xdr, args->name, &hdr); 19179f06c719SChuck Lever encode_getfh(xdr, &hdr); 19189f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 1919d017931cSAndy Adamson encode_nops(&hdr); 19201da177e4SLinus Torvalds } 19211da177e4SLinus Torvalds 19221da177e4SLinus Torvalds /* 19231da177e4SLinus Torvalds * Encode LOOKUP_ROOT request 19241da177e4SLinus Torvalds */ 19259f06c719SChuck Lever static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, 19269f06c719SChuck Lever struct xdr_stream *xdr, 19279f06c719SChuck Lever const struct nfs4_lookup_root_arg *args) 19281da177e4SLinus Torvalds { 19291da177e4SLinus Torvalds struct compound_hdr hdr = { 193066cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 19311da177e4SLinus Torvalds }; 19321da177e4SLinus Torvalds 19339f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 19349f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 19359f06c719SChuck Lever encode_putrootfh(xdr, &hdr); 19369f06c719SChuck Lever encode_getfh(xdr, &hdr); 19379f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 1938d017931cSAndy Adamson encode_nops(&hdr); 19391da177e4SLinus Torvalds } 19401da177e4SLinus Torvalds 19411da177e4SLinus Torvalds /* 19421da177e4SLinus Torvalds * Encode REMOVE request 19431da177e4SLinus Torvalds */ 19449f06c719SChuck Lever static void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr, 19459f06c719SChuck Lever const struct nfs_removeargs *args) 19461da177e4SLinus Torvalds { 19471da177e4SLinus Torvalds struct compound_hdr hdr = { 194866cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 19491da177e4SLinus Torvalds }; 19501da177e4SLinus Torvalds 19519f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 19529f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 19539f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 19549f06c719SChuck Lever encode_remove(xdr, &args->name, &hdr); 19559f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 1956d017931cSAndy Adamson encode_nops(&hdr); 19571da177e4SLinus Torvalds } 19581da177e4SLinus Torvalds 19591da177e4SLinus Torvalds /* 19601da177e4SLinus Torvalds * Encode RENAME request 19611da177e4SLinus Torvalds */ 19629f06c719SChuck Lever static void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr, 19639f06c719SChuck Lever const struct nfs_renameargs *args) 19641da177e4SLinus Torvalds { 19651da177e4SLinus Torvalds struct compound_hdr hdr = { 196666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 19671da177e4SLinus Torvalds }; 19681da177e4SLinus Torvalds 19699f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 19709f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 19719f06c719SChuck Lever encode_putfh(xdr, args->old_dir, &hdr); 19729f06c719SChuck Lever encode_savefh(xdr, &hdr); 19739f06c719SChuck Lever encode_putfh(xdr, args->new_dir, &hdr); 19749f06c719SChuck Lever encode_rename(xdr, args->old_name, args->new_name, &hdr); 19759f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 19769f06c719SChuck Lever encode_restorefh(xdr, &hdr); 19779f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 1978d017931cSAndy Adamson encode_nops(&hdr); 19791da177e4SLinus Torvalds } 19801da177e4SLinus Torvalds 19811da177e4SLinus Torvalds /* 19821da177e4SLinus Torvalds * Encode LINK request 19831da177e4SLinus Torvalds */ 19849f06c719SChuck Lever static void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr, 19859f06c719SChuck Lever const struct nfs4_link_arg *args) 19861da177e4SLinus Torvalds { 19871da177e4SLinus Torvalds struct compound_hdr hdr = { 198866cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 19891da177e4SLinus Torvalds }; 19901da177e4SLinus Torvalds 19919f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 19929f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 19939f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 19949f06c719SChuck Lever encode_savefh(xdr, &hdr); 19959f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 19969f06c719SChuck Lever encode_link(xdr, args->name, &hdr); 19979f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 19989f06c719SChuck Lever encode_restorefh(xdr, &hdr); 19999f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2000d017931cSAndy Adamson encode_nops(&hdr); 20011da177e4SLinus Torvalds } 20021da177e4SLinus Torvalds 20031da177e4SLinus Torvalds /* 20041da177e4SLinus Torvalds * Encode CREATE request 20051da177e4SLinus Torvalds */ 20069f06c719SChuck Lever static void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr, 20079f06c719SChuck Lever const struct nfs4_create_arg *args) 20081da177e4SLinus Torvalds { 20091da177e4SLinus Torvalds struct compound_hdr hdr = { 201066cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 20111da177e4SLinus Torvalds }; 20121da177e4SLinus Torvalds 20139f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 20149f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 20159f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 20169f06c719SChuck Lever encode_savefh(xdr, &hdr); 20179f06c719SChuck Lever encode_create(xdr, args, &hdr); 20189f06c719SChuck Lever encode_getfh(xdr, &hdr); 20199f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 20209f06c719SChuck Lever encode_restorefh(xdr, &hdr); 20219f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2022d017931cSAndy Adamson encode_nops(&hdr); 20231da177e4SLinus Torvalds } 20241da177e4SLinus Torvalds 20251da177e4SLinus Torvalds /* 20261da177e4SLinus Torvalds * Encode SYMLINK request 20271da177e4SLinus Torvalds */ 20289f06c719SChuck Lever static void nfs4_xdr_enc_symlink(struct rpc_rqst *req, struct xdr_stream *xdr, 20299f06c719SChuck Lever const struct nfs4_create_arg *args) 20301da177e4SLinus Torvalds { 20319f06c719SChuck Lever nfs4_xdr_enc_create(req, xdr, args); 20321da177e4SLinus Torvalds } 20331da177e4SLinus Torvalds 20341da177e4SLinus Torvalds /* 20351da177e4SLinus Torvalds * Encode GETATTR request 20361da177e4SLinus Torvalds */ 20379f06c719SChuck Lever static void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr, 20389f06c719SChuck Lever const struct nfs4_getattr_arg *args) 20391da177e4SLinus Torvalds { 20401da177e4SLinus Torvalds struct compound_hdr hdr = { 204166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 20421da177e4SLinus Torvalds }; 20431da177e4SLinus Torvalds 20449f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 20459f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 20469f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 20479f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2048d017931cSAndy Adamson encode_nops(&hdr); 20491da177e4SLinus Torvalds } 20501da177e4SLinus Torvalds 20511da177e4SLinus Torvalds /* 20521da177e4SLinus Torvalds * Encode a CLOSE request 20531da177e4SLinus Torvalds */ 20549f06c719SChuck Lever static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr, 20559f06c719SChuck Lever struct nfs_closeargs *args) 20561da177e4SLinus Torvalds { 20571da177e4SLinus Torvalds struct compound_hdr hdr = { 205866cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 20591da177e4SLinus Torvalds }; 20601da177e4SLinus Torvalds 20619f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 20629f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 20639f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 20649f06c719SChuck Lever encode_close(xdr, args, &hdr); 20659f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2066d017931cSAndy Adamson encode_nops(&hdr); 20671da177e4SLinus Torvalds } 20681da177e4SLinus Torvalds 20691da177e4SLinus Torvalds /* 20701da177e4SLinus Torvalds * Encode an OPEN request 20711da177e4SLinus Torvalds */ 20729f06c719SChuck Lever static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, 20739f06c719SChuck Lever struct nfs_openargs *args) 20741da177e4SLinus Torvalds { 20751da177e4SLinus Torvalds struct compound_hdr hdr = { 207666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 20771da177e4SLinus Torvalds }; 20781da177e4SLinus Torvalds 20799f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 20809f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 20819f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 20829f06c719SChuck Lever encode_savefh(xdr, &hdr); 20839f06c719SChuck Lever encode_open(xdr, args, &hdr); 20849f06c719SChuck Lever encode_getfh(xdr, &hdr); 20859f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 20869f06c719SChuck Lever encode_restorefh(xdr, &hdr); 20879f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2088d017931cSAndy Adamson encode_nops(&hdr); 20891da177e4SLinus Torvalds } 20901da177e4SLinus Torvalds 20911da177e4SLinus Torvalds /* 20921da177e4SLinus Torvalds * Encode an OPEN_CONFIRM request 20931da177e4SLinus Torvalds */ 20949f06c719SChuck Lever static void nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, 20959f06c719SChuck Lever struct xdr_stream *xdr, 20969f06c719SChuck Lever struct nfs_open_confirmargs *args) 20971da177e4SLinus Torvalds { 20981da177e4SLinus Torvalds struct compound_hdr hdr = { 2099d017931cSAndy Adamson .nops = 0, 21001da177e4SLinus Torvalds }; 21011da177e4SLinus Torvalds 21029f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21039f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21049f06c719SChuck Lever encode_open_confirm(xdr, args, &hdr); 2105d017931cSAndy Adamson encode_nops(&hdr); 21061da177e4SLinus Torvalds } 21071da177e4SLinus Torvalds 21081da177e4SLinus Torvalds /* 21091da177e4SLinus Torvalds * Encode an OPEN request with no attributes. 21101da177e4SLinus Torvalds */ 21119f06c719SChuck Lever static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, 21129f06c719SChuck Lever struct xdr_stream *xdr, 21139f06c719SChuck Lever struct nfs_openargs *args) 21141da177e4SLinus Torvalds { 21151da177e4SLinus Torvalds struct compound_hdr hdr = { 211666cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21171da177e4SLinus Torvalds }; 21181da177e4SLinus Torvalds 21199f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21209f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21219f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21229f06c719SChuck Lever encode_open(xdr, args, &hdr); 21239f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2124d017931cSAndy Adamson encode_nops(&hdr); 21251da177e4SLinus Torvalds } 21261da177e4SLinus Torvalds 21271da177e4SLinus Torvalds /* 21281da177e4SLinus Torvalds * Encode an OPEN_DOWNGRADE request 21291da177e4SLinus Torvalds */ 21309f06c719SChuck Lever static void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, 21319f06c719SChuck Lever struct xdr_stream *xdr, 21329f06c719SChuck Lever struct nfs_closeargs *args) 21331da177e4SLinus Torvalds { 21341da177e4SLinus Torvalds struct compound_hdr hdr = { 213566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21361da177e4SLinus Torvalds }; 21371da177e4SLinus Torvalds 21389f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21399f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21409f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21419f06c719SChuck Lever encode_open_downgrade(xdr, args, &hdr); 21429f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2143d017931cSAndy Adamson encode_nops(&hdr); 21441da177e4SLinus Torvalds } 21451da177e4SLinus Torvalds 21461da177e4SLinus Torvalds /* 21471da177e4SLinus Torvalds * Encode a LOCK request 21481da177e4SLinus Torvalds */ 21499f06c719SChuck Lever static void nfs4_xdr_enc_lock(struct rpc_rqst *req, struct xdr_stream *xdr, 21509f06c719SChuck Lever struct nfs_lock_args *args) 21511da177e4SLinus Torvalds { 21521da177e4SLinus Torvalds struct compound_hdr hdr = { 215366cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21541da177e4SLinus Torvalds }; 21551da177e4SLinus Torvalds 21569f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21579f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21589f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21599f06c719SChuck Lever encode_lock(xdr, args, &hdr); 2160d017931cSAndy Adamson encode_nops(&hdr); 21611da177e4SLinus Torvalds } 21621da177e4SLinus Torvalds 21631da177e4SLinus Torvalds /* 21641da177e4SLinus Torvalds * Encode a LOCKT request 21651da177e4SLinus Torvalds */ 21669f06c719SChuck Lever static void nfs4_xdr_enc_lockt(struct rpc_rqst *req, struct xdr_stream *xdr, 21679f06c719SChuck Lever struct nfs_lockt_args *args) 21681da177e4SLinus Torvalds { 21691da177e4SLinus Torvalds struct compound_hdr hdr = { 217066cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 21711da177e4SLinus Torvalds }; 21721da177e4SLinus Torvalds 21739f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 21749f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 21759f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 21769f06c719SChuck Lever encode_lockt(xdr, args, &hdr); 2177d017931cSAndy Adamson encode_nops(&hdr); 21781da177e4SLinus Torvalds } 21791da177e4SLinus Torvalds 21801da177e4SLinus Torvalds /* 21811da177e4SLinus Torvalds * Encode a LOCKU request 21821da177e4SLinus Torvalds */ 21839f06c719SChuck Lever static void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr, 21849f06c719SChuck Lever struct nfs_locku_args *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_locku(xdr, args, &hdr); 2194d017931cSAndy Adamson encode_nops(&hdr); 21951da177e4SLinus Torvalds } 21961da177e4SLinus Torvalds 21979f06c719SChuck Lever static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, 21989f06c719SChuck Lever struct xdr_stream *xdr, 21999f06c719SChuck Lever struct nfs_release_lockowner_args *args) 2200d3c7b7ccSTrond Myklebust { 2201d3c7b7ccSTrond Myklebust struct compound_hdr hdr = { 2202d3c7b7ccSTrond Myklebust .minorversion = 0, 2203d3c7b7ccSTrond Myklebust }; 2204d3c7b7ccSTrond Myklebust 22059f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22069f06c719SChuck Lever encode_release_lockowner(xdr, &args->lock_owner, &hdr); 2207d3c7b7ccSTrond Myklebust encode_nops(&hdr); 2208d3c7b7ccSTrond Myklebust } 2209d3c7b7ccSTrond Myklebust 22101da177e4SLinus Torvalds /* 22111da177e4SLinus Torvalds * Encode a READLINK request 22121da177e4SLinus Torvalds */ 22139f06c719SChuck Lever static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr, 22149f06c719SChuck Lever const struct nfs4_readlink *args) 22151da177e4SLinus Torvalds { 22161da177e4SLinus Torvalds struct compound_hdr hdr = { 221766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22181da177e4SLinus Torvalds }; 22191da177e4SLinus Torvalds 22209f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22219f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22229f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22239f06c719SChuck Lever encode_readlink(xdr, args, req, &hdr); 2224e3a535e1STrond Myklebust 222528f56694SBenny Halevy xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages, 2226e3a535e1STrond Myklebust args->pgbase, args->pglen); 2227d017931cSAndy Adamson encode_nops(&hdr); 22281da177e4SLinus Torvalds } 22291da177e4SLinus Torvalds 22301da177e4SLinus Torvalds /* 22311da177e4SLinus Torvalds * Encode a READDIR request 22321da177e4SLinus Torvalds */ 22339f06c719SChuck Lever static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr, 22349f06c719SChuck Lever const struct nfs4_readdir_arg *args) 22351da177e4SLinus Torvalds { 22361da177e4SLinus Torvalds struct compound_hdr hdr = { 223766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22381da177e4SLinus Torvalds }; 22391da177e4SLinus Torvalds 22409f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22419f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22429f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22439f06c719SChuck Lever encode_readdir(xdr, args, req, &hdr); 2244d6ac02dfSTrond Myklebust 224528f56694SBenny Halevy xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages, 2246d6ac02dfSTrond Myklebust args->pgbase, args->count); 2247d6ac02dfSTrond Myklebust dprintk("%s: inlined page args = (%u, %p, %u, %u)\n", 224828f56694SBenny Halevy __func__, hdr.replen << 2, args->pages, 2249d6ac02dfSTrond Myklebust args->pgbase, args->count); 2250d017931cSAndy Adamson encode_nops(&hdr); 22511da177e4SLinus Torvalds } 22521da177e4SLinus Torvalds 22531da177e4SLinus Torvalds /* 22541da177e4SLinus Torvalds * Encode a READ request 22551da177e4SLinus Torvalds */ 22569f06c719SChuck Lever static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr, 22579f06c719SChuck Lever struct nfs_readargs *args) 22581da177e4SLinus Torvalds { 22591da177e4SLinus Torvalds struct compound_hdr hdr = { 226066cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22611da177e4SLinus Torvalds }; 22621da177e4SLinus Torvalds 22639f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22649f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22659f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22669f06c719SChuck Lever encode_read(xdr, args, &hdr); 22671da177e4SLinus Torvalds 226828f56694SBenny Halevy xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, 22691da177e4SLinus Torvalds args->pages, args->pgbase, args->count); 22704f22ccc3S\"Talpey, Thomas\ req->rq_rcv_buf.flags |= XDRBUF_READ; 2271d017931cSAndy Adamson encode_nops(&hdr); 22721da177e4SLinus Torvalds } 22731da177e4SLinus Torvalds 22741da177e4SLinus Torvalds /* 22751da177e4SLinus Torvalds * Encode an SETATTR request 22761da177e4SLinus Torvalds */ 22779f06c719SChuck Lever static void nfs4_xdr_enc_setattr(struct rpc_rqst *req, struct xdr_stream *xdr, 22789f06c719SChuck Lever struct nfs_setattrargs *args) 22791da177e4SLinus Torvalds { 22801da177e4SLinus Torvalds struct compound_hdr hdr = { 228166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 22821da177e4SLinus Torvalds }; 22831da177e4SLinus Torvalds 22849f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 22859f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 22869f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 22879f06c719SChuck Lever encode_setattr(xdr, args, args->server, &hdr); 22889f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2289d017931cSAndy Adamson encode_nops(&hdr); 22901da177e4SLinus Torvalds } 22911da177e4SLinus Torvalds 22921da177e4SLinus Torvalds /* 2293029d105eSJ. Bruce Fields * Encode a GETACL request 2294029d105eSJ. Bruce Fields */ 22959f06c719SChuck Lever static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, 2296029d105eSJ. Bruce Fields struct nfs_getaclargs *args) 2297029d105eSJ. Bruce Fields { 2298029d105eSJ. Bruce Fields struct compound_hdr hdr = { 229966cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2300029d105eSJ. Bruce Fields }; 230128f56694SBenny Halevy uint32_t replen; 2302029d105eSJ. Bruce Fields 23039f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23049f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23059f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 2306d327cf74SJ. Bruce Fields replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1; 23079f06c719SChuck Lever encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); 2308cf8cdbe5SAndy Adamson 230928f56694SBenny Halevy xdr_inline_pages(&req->rq_rcv_buf, replen << 2, 2310029d105eSJ. Bruce Fields args->acl_pages, args->acl_pgbase, args->acl_len); 2311d017931cSAndy Adamson encode_nops(&hdr); 2312029d105eSJ. Bruce Fields } 2313029d105eSJ. Bruce Fields 2314029d105eSJ. Bruce Fields /* 23151da177e4SLinus Torvalds * Encode a WRITE request 23161da177e4SLinus Torvalds */ 23179f06c719SChuck Lever static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr, 23189f06c719SChuck Lever struct nfs_writeargs *args) 23191da177e4SLinus Torvalds { 23201da177e4SLinus Torvalds struct compound_hdr hdr = { 232166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23221da177e4SLinus Torvalds }; 23231da177e4SLinus Torvalds 23249f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23259f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23269f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23279f06c719SChuck Lever encode_write(xdr, args, &hdr); 23284f22ccc3S\"Talpey, Thomas\ req->rq_snd_buf.flags |= XDRBUF_WRITE; 23297ffd1064SFred Isaman if (args->bitmask) 23309f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2331d017931cSAndy Adamson encode_nops(&hdr); 23321da177e4SLinus Torvalds } 23331da177e4SLinus Torvalds 23341da177e4SLinus Torvalds /* 23351da177e4SLinus Torvalds * a COMMIT request 23361da177e4SLinus Torvalds */ 23379f06c719SChuck Lever static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, 23389f06c719SChuck Lever struct nfs_writeargs *args) 23391da177e4SLinus Torvalds { 23401da177e4SLinus Torvalds struct compound_hdr hdr = { 234166cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23421da177e4SLinus Torvalds }; 23431da177e4SLinus Torvalds 23449f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23459f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23469f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23479f06c719SChuck Lever encode_commit(xdr, args, &hdr); 2348988b6dceSFred Isaman if (args->bitmask) 23499f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2350d017931cSAndy Adamson encode_nops(&hdr); 23511da177e4SLinus Torvalds } 23521da177e4SLinus Torvalds 23531da177e4SLinus Torvalds /* 23541da177e4SLinus Torvalds * FSINFO request 23551da177e4SLinus Torvalds */ 23569f06c719SChuck Lever static void nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, 23579f06c719SChuck Lever struct nfs4_fsinfo_arg *args) 23581da177e4SLinus Torvalds { 23591da177e4SLinus Torvalds struct compound_hdr hdr = { 236066cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23611da177e4SLinus Torvalds }; 23621da177e4SLinus Torvalds 23639f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23649f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23659f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23669f06c719SChuck Lever encode_fsinfo(xdr, args->bitmask, &hdr); 2367d017931cSAndy Adamson encode_nops(&hdr); 23681da177e4SLinus Torvalds } 23691da177e4SLinus Torvalds 23701da177e4SLinus Torvalds /* 23711da177e4SLinus Torvalds * a PATHCONF request 23721da177e4SLinus Torvalds */ 23739f06c719SChuck Lever static void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, 23749f06c719SChuck Lever const struct nfs4_pathconf_arg *args) 23751da177e4SLinus Torvalds { 23761da177e4SLinus Torvalds struct compound_hdr hdr = { 237766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23781da177e4SLinus Torvalds }; 23791da177e4SLinus Torvalds 23809f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23819f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 23829f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 23839f06c719SChuck Lever encode_getattr_one(xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0], 2384d017931cSAndy Adamson &hdr); 2385d017931cSAndy Adamson encode_nops(&hdr); 23861da177e4SLinus Torvalds } 23871da177e4SLinus Torvalds 23881da177e4SLinus Torvalds /* 23891da177e4SLinus Torvalds * a STATFS request 23901da177e4SLinus Torvalds */ 23919f06c719SChuck Lever static void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, 23929f06c719SChuck Lever const struct nfs4_statfs_arg *args) 23931da177e4SLinus Torvalds { 23941da177e4SLinus Torvalds struct compound_hdr hdr = { 239566cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 23961da177e4SLinus Torvalds }; 23971da177e4SLinus Torvalds 23989f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 23999f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24009f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 24019f06c719SChuck Lever encode_getattr_two(xdr, args->bitmask[0] & nfs4_statfs_bitmap[0], 2402d017931cSAndy Adamson args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr); 2403d017931cSAndy Adamson encode_nops(&hdr); 24041da177e4SLinus Torvalds } 24051da177e4SLinus Torvalds 24061da177e4SLinus Torvalds /* 24071da177e4SLinus Torvalds * GETATTR_BITMAP request 24081da177e4SLinus Torvalds */ 24099f06c719SChuck Lever static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req, 24109f06c719SChuck Lever struct xdr_stream *xdr, 241143652ad5SBenny Halevy struct nfs4_server_caps_arg *args) 24121da177e4SLinus Torvalds { 24131da177e4SLinus Torvalds struct compound_hdr hdr = { 241466cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 24151da177e4SLinus Torvalds }; 24161da177e4SLinus Torvalds 24179f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24189f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 24199f06c719SChuck Lever encode_putfh(xdr, args->fhandle, &hdr); 24209f06c719SChuck Lever encode_getattr_one(xdr, FATTR4_WORD0_SUPPORTED_ATTRS| 24211da177e4SLinus Torvalds FATTR4_WORD0_LINK_SUPPORT| 24221da177e4SLinus Torvalds FATTR4_WORD0_SYMLINK_SUPPORT| 2423d017931cSAndy Adamson FATTR4_WORD0_ACLSUPPORT, &hdr); 2424d017931cSAndy Adamson encode_nops(&hdr); 24251da177e4SLinus Torvalds } 24261da177e4SLinus Torvalds 24271da177e4SLinus Torvalds /* 24281da177e4SLinus Torvalds * a RENEW request 24291da177e4SLinus Torvalds */ 24309f06c719SChuck Lever static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr, 24319f06c719SChuck Lever struct nfs_client *clp) 24321da177e4SLinus Torvalds { 24331da177e4SLinus Torvalds struct compound_hdr hdr = { 2434d017931cSAndy Adamson .nops = 0, 24351da177e4SLinus Torvalds }; 24361da177e4SLinus Torvalds 24379f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24389f06c719SChuck Lever encode_renew(xdr, clp, &hdr); 2439d017931cSAndy Adamson encode_nops(&hdr); 24401da177e4SLinus Torvalds } 24411da177e4SLinus Torvalds 24421da177e4SLinus Torvalds /* 24431da177e4SLinus Torvalds * a SETCLIENTID request 24441da177e4SLinus Torvalds */ 24459f06c719SChuck Lever static void nfs4_xdr_enc_setclientid(struct rpc_rqst *req, 24469f06c719SChuck Lever struct xdr_stream *xdr, 24479f06c719SChuck Lever struct nfs4_setclientid *sc) 24481da177e4SLinus Torvalds { 24491da177e4SLinus Torvalds struct compound_hdr hdr = { 2450d017931cSAndy Adamson .nops = 0, 24511da177e4SLinus Torvalds }; 24521da177e4SLinus Torvalds 24539f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24549f06c719SChuck Lever encode_setclientid(xdr, sc, &hdr); 2455d017931cSAndy Adamson encode_nops(&hdr); 24561da177e4SLinus Torvalds } 24571da177e4SLinus Torvalds 24581da177e4SLinus Torvalds /* 24591da177e4SLinus Torvalds * a SETCLIENTID_CONFIRM request 24601da177e4SLinus Torvalds */ 24619f06c719SChuck Lever static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, 24629f06c719SChuck Lever struct xdr_stream *xdr, 24639f06c719SChuck Lever struct nfs4_setclientid_res *arg) 24641da177e4SLinus Torvalds { 24651da177e4SLinus Torvalds struct compound_hdr hdr = { 2466d017931cSAndy Adamson .nops = 0, 24671da177e4SLinus Torvalds }; 24681da177e4SLinus Torvalds const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 }; 24691da177e4SLinus Torvalds 24709f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 24719f06c719SChuck Lever encode_setclientid_confirm(xdr, arg, &hdr); 24729f06c719SChuck Lever encode_putrootfh(xdr, &hdr); 24739f06c719SChuck Lever encode_fsinfo(xdr, lease_bitmap, &hdr); 2474d017931cSAndy Adamson encode_nops(&hdr); 24751da177e4SLinus Torvalds } 24761da177e4SLinus Torvalds 24771da177e4SLinus Torvalds /* 24781da177e4SLinus Torvalds * DELEGRETURN request 24791da177e4SLinus Torvalds */ 24809f06c719SChuck Lever static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, 24819f06c719SChuck Lever struct xdr_stream *xdr, 24829f06c719SChuck Lever const struct nfs4_delegreturnargs *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_delegreturn(xdr, args->stateid, &hdr); 24929f06c719SChuck Lever encode_getfattr(xdr, args->bitmask, &hdr); 2493d017931cSAndy Adamson encode_nops(&hdr); 24941da177e4SLinus Torvalds } 24951da177e4SLinus Torvalds 24961da177e4SLinus Torvalds /* 2497683b57b4STrond Myklebust * Encode FS_LOCATIONS request 2498683b57b4STrond Myklebust */ 24999f06c719SChuck Lever static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, 25009f06c719SChuck Lever struct xdr_stream *xdr, 25019f06c719SChuck Lever struct nfs4_fs_locations_arg *args) 2502683b57b4STrond Myklebust { 2503683b57b4STrond Myklebust struct compound_hdr hdr = { 250466cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2505683b57b4STrond Myklebust }; 250628f56694SBenny Halevy uint32_t replen; 2507683b57b4STrond Myklebust 25089f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25099f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 25109f06c719SChuck Lever encode_putfh(xdr, args->dir_fh, &hdr); 25119f06c719SChuck Lever encode_lookup(xdr, args->name, &hdr); 251228f56694SBenny Halevy replen = hdr.replen; /* get the attribute into args->page */ 25139f06c719SChuck Lever encode_fs_locations(xdr, args->bitmask, &hdr); 2514cf8cdbe5SAndy Adamson 251528f56694SBenny Halevy xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page, 2516683b57b4STrond Myklebust 0, PAGE_SIZE); 2517d017931cSAndy Adamson encode_nops(&hdr); 2518683b57b4STrond Myklebust } 2519683b57b4STrond Myklebust 252099fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 252199fe60d0SBenny Halevy /* 252299fe60d0SBenny Halevy * EXCHANGE_ID request 252399fe60d0SBenny Halevy */ 25249f06c719SChuck Lever static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, 25259f06c719SChuck Lever struct xdr_stream *xdr, 252699fe60d0SBenny Halevy struct nfs41_exchange_id_args *args) 252799fe60d0SBenny Halevy { 252899fe60d0SBenny Halevy struct compound_hdr hdr = { 2529a4432345STrond Myklebust .minorversion = args->client->cl_mvops->minor_version, 253099fe60d0SBenny Halevy }; 253199fe60d0SBenny Halevy 25329f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25339f06c719SChuck Lever encode_exchange_id(xdr, args, &hdr); 253499fe60d0SBenny Halevy encode_nops(&hdr); 253599fe60d0SBenny Halevy } 25362050f0ccSAndy Adamson 25372050f0ccSAndy Adamson /* 2538fc931582SAndy Adamson * a CREATE_SESSION request 2539fc931582SAndy Adamson */ 25409f06c719SChuck Lever static void nfs4_xdr_enc_create_session(struct rpc_rqst *req, 25419f06c719SChuck Lever struct xdr_stream *xdr, 2542fc931582SAndy Adamson struct nfs41_create_session_args *args) 2543fc931582SAndy Adamson { 2544fc931582SAndy Adamson struct compound_hdr hdr = { 2545a4432345STrond Myklebust .minorversion = args->client->cl_mvops->minor_version, 2546fc931582SAndy Adamson }; 2547fc931582SAndy Adamson 25489f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25499f06c719SChuck Lever encode_create_session(xdr, args, &hdr); 2550fc931582SAndy Adamson encode_nops(&hdr); 2551fc931582SAndy Adamson } 2552fc931582SAndy Adamson 2553fc931582SAndy Adamson /* 25540f3e66c6SAndy Adamson * a DESTROY_SESSION request 25550f3e66c6SAndy Adamson */ 25569f06c719SChuck Lever static void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, 25579f06c719SChuck Lever struct xdr_stream *xdr, 25580f3e66c6SAndy Adamson struct nfs4_session *session) 25590f3e66c6SAndy Adamson { 25600f3e66c6SAndy Adamson struct compound_hdr hdr = { 2561a4432345STrond Myklebust .minorversion = session->clp->cl_mvops->minor_version, 25620f3e66c6SAndy Adamson }; 25630f3e66c6SAndy Adamson 25649f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25659f06c719SChuck Lever encode_destroy_session(xdr, session, &hdr); 25660f3e66c6SAndy Adamson encode_nops(&hdr); 25670f3e66c6SAndy Adamson } 25680f3e66c6SAndy Adamson 25690f3e66c6SAndy Adamson /* 2570fc01cea9SAndy Adamson * a SEQUENCE request 2571fc01cea9SAndy Adamson */ 25729f06c719SChuck Lever static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr, 2573fc01cea9SAndy Adamson struct nfs4_sequence_args *args) 2574fc01cea9SAndy Adamson { 2575fc01cea9SAndy Adamson struct compound_hdr hdr = { 2576fc01cea9SAndy Adamson .minorversion = nfs4_xdr_minorversion(args), 2577fc01cea9SAndy Adamson }; 2578fc01cea9SAndy Adamson 25799f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25809f06c719SChuck Lever encode_sequence(xdr, args, &hdr); 2581fc01cea9SAndy Adamson encode_nops(&hdr); 2582fc01cea9SAndy Adamson } 2583fc01cea9SAndy Adamson 2584fc01cea9SAndy Adamson /* 25852050f0ccSAndy Adamson * a GET_LEASE_TIME request 25862050f0ccSAndy Adamson */ 25879f06c719SChuck Lever static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, 25889f06c719SChuck Lever struct xdr_stream *xdr, 25892050f0ccSAndy Adamson struct nfs4_get_lease_time_args *args) 25902050f0ccSAndy Adamson { 25912050f0ccSAndy Adamson struct compound_hdr hdr = { 25922050f0ccSAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->la_seq_args), 25932050f0ccSAndy Adamson }; 25942050f0ccSAndy Adamson const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 }; 25952050f0ccSAndy Adamson 25969f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 25979f06c719SChuck Lever encode_sequence(xdr, &args->la_seq_args, &hdr); 25989f06c719SChuck Lever encode_putrootfh(xdr, &hdr); 25999f06c719SChuck Lever encode_fsinfo(xdr, lease_bitmap, &hdr); 26002050f0ccSAndy Adamson encode_nops(&hdr); 26012050f0ccSAndy Adamson } 260218019753SRicardo Labiaga 260318019753SRicardo Labiaga /* 260418019753SRicardo Labiaga * a RECLAIM_COMPLETE request 260518019753SRicardo Labiaga */ 26069f06c719SChuck Lever static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, 26079f06c719SChuck Lever struct xdr_stream *xdr, 260818019753SRicardo Labiaga struct nfs41_reclaim_complete_args *args) 260918019753SRicardo Labiaga { 261018019753SRicardo Labiaga struct compound_hdr hdr = { 261118019753SRicardo Labiaga .minorversion = nfs4_xdr_minorversion(&args->seq_args) 261218019753SRicardo Labiaga }; 261318019753SRicardo Labiaga 26149f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26159f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26169f06c719SChuck Lever encode_reclaim_complete(xdr, args, &hdr); 261718019753SRicardo Labiaga encode_nops(&hdr); 261818019753SRicardo Labiaga } 261918019753SRicardo Labiaga 2620b1f69b75SAndy Adamson /* 2621b1f69b75SAndy Adamson * Encode GETDEVICEINFO request 2622b1f69b75SAndy Adamson */ 26239f06c719SChuck Lever static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, 26249f06c719SChuck Lever struct xdr_stream *xdr, 2625b1f69b75SAndy Adamson struct nfs4_getdeviceinfo_args *args) 2626b1f69b75SAndy Adamson { 2627b1f69b75SAndy Adamson struct compound_hdr hdr = { 2628b1f69b75SAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2629b1f69b75SAndy Adamson }; 2630b1f69b75SAndy Adamson 26319f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26329f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26339f06c719SChuck Lever encode_getdeviceinfo(xdr, args, &hdr); 2634b1f69b75SAndy Adamson 2635b1f69b75SAndy Adamson /* set up reply kvec. Subtract notification bitmap max size (2) 2636b1f69b75SAndy Adamson * so that notification bitmap is put in xdr_buf tail */ 2637b1f69b75SAndy Adamson xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2, 2638b1f69b75SAndy Adamson args->pdev->pages, args->pdev->pgbase, 2639b1f69b75SAndy Adamson args->pdev->pglen); 2640b1f69b75SAndy Adamson 2641b1f69b75SAndy Adamson encode_nops(&hdr); 2642b1f69b75SAndy Adamson } 2643b1f69b75SAndy Adamson 2644b1f69b75SAndy Adamson /* 2645b1f69b75SAndy Adamson * Encode LAYOUTGET request 2646b1f69b75SAndy Adamson */ 26479f06c719SChuck Lever static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, 26489f06c719SChuck Lever struct xdr_stream *xdr, 2649b1f69b75SAndy Adamson struct nfs4_layoutget_args *args) 2650b1f69b75SAndy Adamson { 2651b1f69b75SAndy Adamson struct compound_hdr hdr = { 2652b1f69b75SAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2653b1f69b75SAndy Adamson }; 2654b1f69b75SAndy Adamson 26559f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 26569f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 26579f06c719SChuck Lever encode_putfh(xdr, NFS_FH(args->inode), &hdr); 26589f06c719SChuck Lever encode_layoutget(xdr, args, &hdr); 2659b1f69b75SAndy Adamson encode_nops(&hdr); 2660b1f69b75SAndy Adamson } 2661863a3c6cSAndy Adamson 2662863a3c6cSAndy Adamson /* 2663863a3c6cSAndy Adamson * Encode LAYOUTCOMMIT request 2664863a3c6cSAndy Adamson */ 2665863a3c6cSAndy Adamson static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, 2666863a3c6cSAndy Adamson struct xdr_stream *xdr, 2667863a3c6cSAndy Adamson struct nfs4_layoutcommit_args *args) 2668863a3c6cSAndy Adamson { 2669863a3c6cSAndy Adamson struct compound_hdr hdr = { 2670863a3c6cSAndy Adamson .minorversion = nfs4_xdr_minorversion(&args->seq_args), 2671863a3c6cSAndy Adamson }; 2672863a3c6cSAndy Adamson 2673863a3c6cSAndy Adamson encode_compound_hdr(xdr, req, &hdr); 2674863a3c6cSAndy Adamson encode_sequence(xdr, &args->seq_args, &hdr); 2675863a3c6cSAndy Adamson encode_putfh(xdr, NFS_FH(args->inode), &hdr); 2676863a3c6cSAndy Adamson encode_layoutcommit(xdr, args, &hdr); 2677863a3c6cSAndy Adamson encode_getfattr(xdr, args->bitmask, &hdr); 2678863a3c6cSAndy Adamson encode_nops(&hdr); 2679863a3c6cSAndy Adamson return 0; 2680863a3c6cSAndy Adamson } 268199fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 268299fe60d0SBenny Halevy 2683686841b3SBenny Halevy static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) 2684686841b3SBenny Halevy { 2685686841b3SBenny Halevy dprintk("nfs: %s: prematurely hit end of receive buffer. " 2686686841b3SBenny Halevy "Remaining buffer length is %tu words.\n", 2687686841b3SBenny Halevy func, xdr->end - xdr->p); 2688686841b3SBenny Halevy } 26891da177e4SLinus Torvalds 2690683b57b4STrond Myklebust static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) 26911da177e4SLinus Torvalds { 26928687b63aSAl Viro __be32 *p; 26931da177e4SLinus Torvalds 2694c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2695c0eae66eSBenny Halevy if (unlikely(!p)) 2696c0eae66eSBenny Halevy goto out_overflow; 2697cccddf4fSBenny Halevy *len = be32_to_cpup(p); 2698c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, *len); 2699c0eae66eSBenny Halevy if (unlikely(!p)) 2700c0eae66eSBenny Halevy goto out_overflow; 27011da177e4SLinus Torvalds *string = (char *)p; 27021da177e4SLinus Torvalds return 0; 2703c0eae66eSBenny Halevy out_overflow: 2704c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2705c0eae66eSBenny Halevy return -EIO; 27061da177e4SLinus Torvalds } 27071da177e4SLinus Torvalds 27081da177e4SLinus Torvalds static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) 27091da177e4SLinus Torvalds { 27108687b63aSAl Viro __be32 *p; 27111da177e4SLinus Torvalds 2712c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 2713c0eae66eSBenny Halevy if (unlikely(!p)) 2714c0eae66eSBenny Halevy goto out_overflow; 27156f723f77SBenny Halevy hdr->status = be32_to_cpup(p++); 2716cccddf4fSBenny Halevy hdr->taglen = be32_to_cpup(p); 27171da177e4SLinus Torvalds 2718c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, hdr->taglen + 4); 2719c0eae66eSBenny Halevy if (unlikely(!p)) 2720c0eae66eSBenny Halevy goto out_overflow; 27211da177e4SLinus Torvalds hdr->tag = (char *)p; 27221da177e4SLinus Torvalds p += XDR_QUADLEN(hdr->taglen); 2723cccddf4fSBenny Halevy hdr->nops = be32_to_cpup(p); 2724aadf6152SBenny Halevy if (unlikely(hdr->nops < 1)) 2725aadf6152SBenny Halevy return nfs4_stat_to_errno(hdr->status); 27261da177e4SLinus Torvalds return 0; 2727c0eae66eSBenny Halevy out_overflow: 2728c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2729c0eae66eSBenny Halevy return -EIO; 27301da177e4SLinus Torvalds } 27311da177e4SLinus Torvalds 27321da177e4SLinus Torvalds static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) 27331da177e4SLinus Torvalds { 27348687b63aSAl Viro __be32 *p; 27351da177e4SLinus Torvalds uint32_t opnum; 27361da177e4SLinus Torvalds int32_t nfserr; 27371da177e4SLinus Torvalds 2738c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 2739c0eae66eSBenny Halevy if (unlikely(!p)) 2740c0eae66eSBenny Halevy goto out_overflow; 27416f723f77SBenny Halevy opnum = be32_to_cpup(p++); 27421da177e4SLinus Torvalds if (opnum != expected) { 2743fe82a183SChuck Lever dprintk("nfs: Server returned operation" 27441da177e4SLinus Torvalds " %d but we issued a request for %d\n", 27451da177e4SLinus Torvalds opnum, expected); 27461da177e4SLinus Torvalds return -EIO; 27471da177e4SLinus Torvalds } 2748cccddf4fSBenny Halevy nfserr = be32_to_cpup(p); 27491da177e4SLinus Torvalds if (nfserr != NFS_OK) 2750856dff3dSBenny Halevy return nfs4_stat_to_errno(nfserr); 27511da177e4SLinus Torvalds return 0; 2752c0eae66eSBenny Halevy out_overflow: 2753c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2754c0eae66eSBenny Halevy return -EIO; 27551da177e4SLinus Torvalds } 27561da177e4SLinus Torvalds 27571da177e4SLinus Torvalds /* Dummy routine */ 2758adfa6f98SDavid Howells static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp) 27591da177e4SLinus Torvalds { 27608687b63aSAl Viro __be32 *p; 2761683b57b4STrond Myklebust unsigned int strlen; 27621da177e4SLinus Torvalds char *str; 27631da177e4SLinus Torvalds 2764c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 2765c0eae66eSBenny Halevy if (likely(p)) 27661da177e4SLinus Torvalds return decode_opaque_inline(xdr, &strlen, &str); 2767c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2768c0eae66eSBenny Halevy return -EIO; 27691da177e4SLinus Torvalds } 27701da177e4SLinus Torvalds 27711da177e4SLinus Torvalds static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) 27721da177e4SLinus Torvalds { 27738687b63aSAl Viro uint32_t bmlen; 27748687b63aSAl Viro __be32 *p; 27751da177e4SLinus Torvalds 2776c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2777c0eae66eSBenny Halevy if (unlikely(!p)) 2778c0eae66eSBenny Halevy goto out_overflow; 2779cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 27801da177e4SLinus Torvalds 27811da177e4SLinus Torvalds bitmap[0] = bitmap[1] = 0; 2782c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, (bmlen << 2)); 2783c0eae66eSBenny Halevy if (unlikely(!p)) 2784c0eae66eSBenny Halevy goto out_overflow; 27851da177e4SLinus Torvalds if (bmlen > 0) { 27866f723f77SBenny Halevy bitmap[0] = be32_to_cpup(p++); 27871da177e4SLinus Torvalds if (bmlen > 1) 2788cccddf4fSBenny Halevy bitmap[1] = be32_to_cpup(p); 27891da177e4SLinus Torvalds } 27901da177e4SLinus Torvalds return 0; 2791c0eae66eSBenny Halevy out_overflow: 2792c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2793c0eae66eSBenny Halevy return -EIO; 27941da177e4SLinus Torvalds } 27951da177e4SLinus Torvalds 27968687b63aSAl Viro static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep) 27971da177e4SLinus Torvalds { 27988687b63aSAl Viro __be32 *p; 27991da177e4SLinus Torvalds 2800c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2801c0eae66eSBenny Halevy if (unlikely(!p)) 2802c0eae66eSBenny Halevy goto out_overflow; 2803cccddf4fSBenny Halevy *attrlen = be32_to_cpup(p); 28041da177e4SLinus Torvalds *savep = xdr->p; 28051da177e4SLinus Torvalds return 0; 2806c0eae66eSBenny Halevy out_overflow: 2807c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2808c0eae66eSBenny Halevy return -EIO; 28091da177e4SLinus Torvalds } 28101da177e4SLinus Torvalds 28111da177e4SLinus Torvalds static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask) 28121da177e4SLinus Torvalds { 28131da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) { 28143388bff5SRoman Borisov int ret; 28153388bff5SRoman Borisov ret = decode_attr_bitmap(xdr, bitmask); 28163388bff5SRoman Borisov if (unlikely(ret < 0)) 28173388bff5SRoman Borisov return ret; 28181da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS; 28191da177e4SLinus Torvalds } else 28201da177e4SLinus Torvalds bitmask[0] = bitmask[1] = 0; 282144109241SFred Isaman dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]); 28221da177e4SLinus Torvalds return 0; 28231da177e4SLinus Torvalds } 28241da177e4SLinus Torvalds 28251da177e4SLinus Torvalds static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type) 28261da177e4SLinus Torvalds { 28278687b63aSAl Viro __be32 *p; 2828409924e4STrond Myklebust int ret = 0; 28291da177e4SLinus Torvalds 28301da177e4SLinus Torvalds *type = 0; 28311da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U))) 28321da177e4SLinus Torvalds return -EIO; 28331da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) { 2834c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2835c0eae66eSBenny Halevy if (unlikely(!p)) 2836c0eae66eSBenny Halevy goto out_overflow; 2837cccddf4fSBenny Halevy *type = be32_to_cpup(p); 28381da177e4SLinus Torvalds if (*type < NF4REG || *type > NF4NAMEDATTR) { 28393110ff80SHarvey Harrison dprintk("%s: bad type %d\n", __func__, *type); 28401da177e4SLinus Torvalds return -EIO; 28411da177e4SLinus Torvalds } 28421da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_TYPE; 2843409924e4STrond Myklebust ret = NFS_ATTR_FATTR_TYPE; 28441da177e4SLinus Torvalds } 2845bca79478STrond Myklebust dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]); 2846409924e4STrond Myklebust return ret; 2847c0eae66eSBenny Halevy out_overflow: 2848c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2849c0eae66eSBenny Halevy return -EIO; 28501da177e4SLinus Torvalds } 28511da177e4SLinus Torvalds 28521da177e4SLinus Torvalds static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) 28531da177e4SLinus Torvalds { 28548687b63aSAl Viro __be32 *p; 2855409924e4STrond Myklebust int ret = 0; 28561da177e4SLinus Torvalds 28571da177e4SLinus Torvalds *change = 0; 28581da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U))) 28591da177e4SLinus Torvalds return -EIO; 28601da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) { 2861c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 2862c0eae66eSBenny Halevy if (unlikely(!p)) 2863c0eae66eSBenny Halevy goto out_overflow; 2864cccddf4fSBenny Halevy xdr_decode_hyper(p, change); 28651da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_CHANGE; 2866409924e4STrond Myklebust ret = NFS_ATTR_FATTR_CHANGE; 28671da177e4SLinus Torvalds } 28683110ff80SHarvey Harrison dprintk("%s: change attribute=%Lu\n", __func__, 28691da177e4SLinus Torvalds (unsigned long long)*change); 2870409924e4STrond Myklebust return ret; 2871c0eae66eSBenny Halevy out_overflow: 2872c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2873c0eae66eSBenny Halevy return -EIO; 28741da177e4SLinus Torvalds } 28751da177e4SLinus Torvalds 28761da177e4SLinus Torvalds static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) 28771da177e4SLinus Torvalds { 28788687b63aSAl Viro __be32 *p; 2879409924e4STrond Myklebust int ret = 0; 28801da177e4SLinus Torvalds 28811da177e4SLinus Torvalds *size = 0; 28821da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U))) 28831da177e4SLinus Torvalds return -EIO; 28841da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) { 2885c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 2886c0eae66eSBenny Halevy if (unlikely(!p)) 2887c0eae66eSBenny Halevy goto out_overflow; 2888cccddf4fSBenny Halevy xdr_decode_hyper(p, size); 28891da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SIZE; 2890409924e4STrond Myklebust ret = NFS_ATTR_FATTR_SIZE; 28911da177e4SLinus Torvalds } 28923110ff80SHarvey Harrison dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size); 2893409924e4STrond Myklebust return ret; 2894c0eae66eSBenny Halevy out_overflow: 2895c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2896c0eae66eSBenny Halevy return -EIO; 28971da177e4SLinus Torvalds } 28981da177e4SLinus Torvalds 28991da177e4SLinus Torvalds static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 29001da177e4SLinus Torvalds { 29018687b63aSAl Viro __be32 *p; 29021da177e4SLinus Torvalds 29031da177e4SLinus Torvalds *res = 0; 29041da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U))) 29051da177e4SLinus Torvalds return -EIO; 29061da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) { 2907c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2908c0eae66eSBenny Halevy if (unlikely(!p)) 2909c0eae66eSBenny Halevy goto out_overflow; 2910cccddf4fSBenny Halevy *res = be32_to_cpup(p); 29111da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT; 29121da177e4SLinus Torvalds } 29133110ff80SHarvey Harrison dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true"); 29141da177e4SLinus Torvalds return 0; 2915c0eae66eSBenny Halevy out_overflow: 2916c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2917c0eae66eSBenny Halevy return -EIO; 29181da177e4SLinus Torvalds } 29191da177e4SLinus Torvalds 29201da177e4SLinus Torvalds static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 29211da177e4SLinus Torvalds { 29228687b63aSAl Viro __be32 *p; 29231da177e4SLinus Torvalds 29241da177e4SLinus Torvalds *res = 0; 29251da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U))) 29261da177e4SLinus Torvalds return -EIO; 29271da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) { 2928c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2929c0eae66eSBenny Halevy if (unlikely(!p)) 2930c0eae66eSBenny Halevy goto out_overflow; 2931cccddf4fSBenny Halevy *res = be32_to_cpup(p); 29321da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT; 29331da177e4SLinus Torvalds } 29343110ff80SHarvey Harrison dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true"); 29351da177e4SLinus Torvalds return 0; 2936c0eae66eSBenny Halevy out_overflow: 2937c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2938c0eae66eSBenny Halevy return -EIO; 29391da177e4SLinus Torvalds } 29401da177e4SLinus Torvalds 29418b4bdcf8STrond Myklebust static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) 29421da177e4SLinus Torvalds { 29438687b63aSAl Viro __be32 *p; 2944409924e4STrond Myklebust int ret = 0; 29451da177e4SLinus Torvalds 29461da177e4SLinus Torvalds fsid->major = 0; 29471da177e4SLinus Torvalds fsid->minor = 0; 29481da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U))) 29491da177e4SLinus Torvalds return -EIO; 29501da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FSID)) { 2951c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 16); 2952c0eae66eSBenny Halevy if (unlikely(!p)) 2953c0eae66eSBenny Halevy goto out_overflow; 29543ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &fsid->major); 2955cccddf4fSBenny Halevy xdr_decode_hyper(p, &fsid->minor); 29561da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FSID; 2957409924e4STrond Myklebust ret = NFS_ATTR_FATTR_FSID; 29581da177e4SLinus Torvalds } 29593110ff80SHarvey Harrison dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__, 29601da177e4SLinus Torvalds (unsigned long long)fsid->major, 29611da177e4SLinus Torvalds (unsigned long long)fsid->minor); 2962409924e4STrond Myklebust return ret; 2963c0eae66eSBenny Halevy out_overflow: 2964c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2965c0eae66eSBenny Halevy return -EIO; 29661da177e4SLinus Torvalds } 29671da177e4SLinus Torvalds 29681da177e4SLinus Torvalds static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 29691da177e4SLinus Torvalds { 29708687b63aSAl Viro __be32 *p; 29711da177e4SLinus Torvalds 29721da177e4SLinus Torvalds *res = 60; 29731da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U))) 29741da177e4SLinus Torvalds return -EIO; 29751da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) { 2976c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 2977c0eae66eSBenny Halevy if (unlikely(!p)) 2978c0eae66eSBenny Halevy goto out_overflow; 2979cccddf4fSBenny Halevy *res = be32_to_cpup(p); 29801da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME; 29811da177e4SLinus Torvalds } 29823110ff80SHarvey Harrison dprintk("%s: file size=%u\n", __func__, (unsigned int)*res); 29831da177e4SLinus Torvalds return 0; 2984c0eae66eSBenny Halevy out_overflow: 2985c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 2986c0eae66eSBenny Halevy return -EIO; 29871da177e4SLinus Torvalds } 29881da177e4SLinus Torvalds 2989ae42c70aSBryan Schumaker static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) 2990ae42c70aSBryan Schumaker { 2991ae42c70aSBryan Schumaker __be32 *p; 2992ae42c70aSBryan Schumaker 2993ae42c70aSBryan Schumaker if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U))) 2994ae42c70aSBryan Schumaker return -EIO; 2995ae42c70aSBryan Schumaker if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) { 2996ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, 4); 2997ae42c70aSBryan Schumaker if (unlikely(!p)) 2998ae42c70aSBryan Schumaker goto out_overflow; 2999ae42c70aSBryan Schumaker bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; 3000ae42c70aSBryan Schumaker } 3001ae42c70aSBryan Schumaker return 0; 3002ae42c70aSBryan Schumaker out_overflow: 3003ae42c70aSBryan Schumaker print_overflow_msg(__func__, xdr); 3004ae42c70aSBryan Schumaker return -EIO; 3005ae42c70aSBryan Schumaker } 3006ae42c70aSBryan Schumaker 3007ae42c70aSBryan Schumaker static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh) 3008ae42c70aSBryan Schumaker { 3009ae42c70aSBryan Schumaker __be32 *p; 3010ae42c70aSBryan Schumaker int len; 3011ae42c70aSBryan Schumaker 30127ad07353STrond Myklebust if (fh != NULL) 3013ae42c70aSBryan Schumaker memset(fh, 0, sizeof(*fh)); 3014ae42c70aSBryan Schumaker 3015ae42c70aSBryan Schumaker if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U))) 3016ae42c70aSBryan Schumaker return -EIO; 3017ae42c70aSBryan Schumaker if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) { 3018ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, 4); 3019ae42c70aSBryan Schumaker if (unlikely(!p)) 3020ae42c70aSBryan Schumaker goto out_overflow; 3021ae42c70aSBryan Schumaker len = be32_to_cpup(p); 3022ae42c70aSBryan Schumaker if (len > NFS4_FHSIZE) 3023ae42c70aSBryan Schumaker return -EIO; 3024ae42c70aSBryan Schumaker p = xdr_inline_decode(xdr, len); 3025ae42c70aSBryan Schumaker if (unlikely(!p)) 3026ae42c70aSBryan Schumaker goto out_overflow; 30277ad07353STrond Myklebust if (fh != NULL) { 3028ae42c70aSBryan Schumaker memcpy(fh->data, p, len); 30297ad07353STrond Myklebust fh->size = len; 30307ad07353STrond Myklebust } 3031ae42c70aSBryan Schumaker bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE; 3032ae42c70aSBryan Schumaker } 3033ae42c70aSBryan Schumaker return 0; 3034ae42c70aSBryan Schumaker out_overflow: 3035ae42c70aSBryan Schumaker print_overflow_msg(__func__, xdr); 3036ae42c70aSBryan Schumaker return -EIO; 3037ae42c70aSBryan Schumaker } 3038ae42c70aSBryan Schumaker 30391da177e4SLinus Torvalds static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 30401da177e4SLinus Torvalds { 30418687b63aSAl Viro __be32 *p; 30421da177e4SLinus Torvalds 30431da177e4SLinus Torvalds *res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL; 30441da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U))) 30451da177e4SLinus Torvalds return -EIO; 30461da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { 3047c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3048c0eae66eSBenny Halevy if (unlikely(!p)) 3049c0eae66eSBenny Halevy goto out_overflow; 3050cccddf4fSBenny Halevy *res = be32_to_cpup(p); 30511da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT; 30521da177e4SLinus Torvalds } 30533110ff80SHarvey Harrison dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res); 30541da177e4SLinus Torvalds return 0; 3055c0eae66eSBenny Halevy out_overflow: 3056c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3057c0eae66eSBenny Halevy return -EIO; 30581da177e4SLinus Torvalds } 30591da177e4SLinus Torvalds 30601da177e4SLinus Torvalds static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) 30611da177e4SLinus Torvalds { 30628687b63aSAl Viro __be32 *p; 3063409924e4STrond Myklebust int ret = 0; 30641da177e4SLinus Torvalds 30651da177e4SLinus Torvalds *fileid = 0; 30661da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U))) 30671da177e4SLinus Torvalds return -EIO; 30681da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) { 3069c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3070c0eae66eSBenny Halevy if (unlikely(!p)) 3071c0eae66eSBenny Halevy goto out_overflow; 3072cccddf4fSBenny Halevy xdr_decode_hyper(p, fileid); 30731da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILEID; 3074409924e4STrond Myklebust ret = NFS_ATTR_FATTR_FILEID; 30751da177e4SLinus Torvalds } 30763110ff80SHarvey Harrison dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); 3077409924e4STrond Myklebust return ret; 3078c0eae66eSBenny Halevy out_overflow: 3079c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3080c0eae66eSBenny Halevy return -EIO; 30811da177e4SLinus Torvalds } 30821da177e4SLinus Torvalds 308399baf625SManoj Naik static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) 308499baf625SManoj Naik { 30858687b63aSAl Viro __be32 *p; 3086409924e4STrond Myklebust int ret = 0; 308799baf625SManoj Naik 308899baf625SManoj Naik *fileid = 0; 308999baf625SManoj Naik if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U))) 309099baf625SManoj Naik return -EIO; 309199baf625SManoj Naik if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) { 3092c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3093c0eae66eSBenny Halevy if (unlikely(!p)) 3094c0eae66eSBenny Halevy goto out_overflow; 3095cccddf4fSBenny Halevy xdr_decode_hyper(p, fileid); 309699baf625SManoj Naik bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; 3097409924e4STrond Myklebust ret = NFS_ATTR_FATTR_FILEID; 309899baf625SManoj Naik } 30993110ff80SHarvey Harrison dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); 3100409924e4STrond Myklebust return ret; 3101c0eae66eSBenny Halevy out_overflow: 3102c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3103c0eae66eSBenny Halevy return -EIO; 310499baf625SManoj Naik } 310599baf625SManoj Naik 31061da177e4SLinus Torvalds static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 31071da177e4SLinus Torvalds { 31088687b63aSAl Viro __be32 *p; 31091da177e4SLinus Torvalds int status = 0; 31101da177e4SLinus Torvalds 31111da177e4SLinus Torvalds *res = 0; 31121da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U))) 31131da177e4SLinus Torvalds return -EIO; 31141da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) { 3115c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3116c0eae66eSBenny Halevy if (unlikely(!p)) 3117c0eae66eSBenny Halevy goto out_overflow; 3118cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 31191da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL; 31201da177e4SLinus Torvalds } 31213110ff80SHarvey Harrison dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res); 31221da177e4SLinus Torvalds return status; 3123c0eae66eSBenny Halevy out_overflow: 3124c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3125c0eae66eSBenny Halevy return -EIO; 31261da177e4SLinus Torvalds } 31271da177e4SLinus Torvalds 31281da177e4SLinus Torvalds static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 31291da177e4SLinus Torvalds { 31308687b63aSAl Viro __be32 *p; 31311da177e4SLinus Torvalds int status = 0; 31321da177e4SLinus Torvalds 31331da177e4SLinus Torvalds *res = 0; 31341da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U))) 31351da177e4SLinus Torvalds return -EIO; 31361da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) { 3137c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3138c0eae66eSBenny Halevy if (unlikely(!p)) 3139c0eae66eSBenny Halevy goto out_overflow; 3140cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 31411da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_FREE; 31421da177e4SLinus Torvalds } 31433110ff80SHarvey Harrison dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res); 31441da177e4SLinus Torvalds return status; 3145c0eae66eSBenny Halevy out_overflow: 3146c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3147c0eae66eSBenny Halevy return -EIO; 31481da177e4SLinus Torvalds } 31491da177e4SLinus Torvalds 31501da177e4SLinus Torvalds static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 31511da177e4SLinus Torvalds { 31528687b63aSAl Viro __be32 *p; 31531da177e4SLinus Torvalds int status = 0; 31541da177e4SLinus Torvalds 31551da177e4SLinus Torvalds *res = 0; 31561da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U))) 31571da177e4SLinus Torvalds return -EIO; 31581da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) { 3159c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3160c0eae66eSBenny Halevy if (unlikely(!p)) 3161c0eae66eSBenny Halevy goto out_overflow; 3162cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 31631da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL; 31641da177e4SLinus Torvalds } 31653110ff80SHarvey Harrison dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res); 31661da177e4SLinus Torvalds return status; 3167c0eae66eSBenny Halevy out_overflow: 3168c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3169c0eae66eSBenny Halevy return -EIO; 31701da177e4SLinus Torvalds } 31711da177e4SLinus Torvalds 31727aaa0b3bSManoj Naik static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) 31737aaa0b3bSManoj Naik { 3174464ad6b1SChuck Lever u32 n; 31758687b63aSAl Viro __be32 *p; 31767aaa0b3bSManoj Naik int status = 0; 31777aaa0b3bSManoj Naik 3178c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3179c0eae66eSBenny Halevy if (unlikely(!p)) 3180c0eae66eSBenny Halevy goto out_overflow; 3181cccddf4fSBenny Halevy n = be32_to_cpup(p); 318233a43f28SAndy Adamson if (n == 0) 318333a43f28SAndy Adamson goto root_path; 31847aaa0b3bSManoj Naik dprintk("path "); 31857aaa0b3bSManoj Naik path->ncomponents = 0; 31867aaa0b3bSManoj Naik while (path->ncomponents < n) { 31877aaa0b3bSManoj Naik struct nfs4_string *component = &path->components[path->ncomponents]; 31887aaa0b3bSManoj Naik status = decode_opaque_inline(xdr, &component->len, &component->data); 31897aaa0b3bSManoj Naik if (unlikely(status != 0)) 31907aaa0b3bSManoj Naik goto out_eio; 31917aaa0b3bSManoj Naik if (path->ncomponents != n) 31927aaa0b3bSManoj Naik dprintk("/"); 31937aaa0b3bSManoj Naik dprintk("%s", component->data); 31947aaa0b3bSManoj Naik if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS) 31957aaa0b3bSManoj Naik path->ncomponents++; 31967aaa0b3bSManoj Naik else { 31977aaa0b3bSManoj Naik dprintk("cannot parse %d components in path\n", n); 31987aaa0b3bSManoj Naik goto out_eio; 31997aaa0b3bSManoj Naik } 32007aaa0b3bSManoj Naik } 32017aaa0b3bSManoj Naik out: 32027aaa0b3bSManoj Naik dprintk("\n"); 32037aaa0b3bSManoj Naik return status; 320433a43f28SAndy Adamson root_path: 320533a43f28SAndy Adamson /* a root pathname is sent as a zero component4 */ 320633a43f28SAndy Adamson path->ncomponents = 1; 320733a43f28SAndy Adamson path->components[0].len=0; 320833a43f28SAndy Adamson path->components[0].data=NULL; 320933a43f28SAndy Adamson dprintk("path /\n"); 321033a43f28SAndy Adamson goto out; 32117aaa0b3bSManoj Naik out_eio: 32127aaa0b3bSManoj Naik dprintk(" status %d", status); 32137aaa0b3bSManoj Naik status = -EIO; 32147aaa0b3bSManoj Naik goto out; 3215c0eae66eSBenny Halevy out_overflow: 3216c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3217c0eae66eSBenny Halevy return -EIO; 32187aaa0b3bSManoj Naik } 32197aaa0b3bSManoj Naik 32207aaa0b3bSManoj Naik static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) 3221683b57b4STrond Myklebust { 3222683b57b4STrond Myklebust int n; 32238687b63aSAl Viro __be32 *p; 3224683b57b4STrond Myklebust int status = -EIO; 3225683b57b4STrond Myklebust 3226683b57b4STrond Myklebust if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U))) 3227683b57b4STrond Myklebust goto out; 3228683b57b4STrond Myklebust status = 0; 3229683b57b4STrond Myklebust if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) 3230683b57b4STrond Myklebust goto out; 32313110ff80SHarvey Harrison dprintk("%s: fsroot ", __func__); 32327aaa0b3bSManoj Naik status = decode_pathname(xdr, &res->fs_path); 3233683b57b4STrond Myklebust if (unlikely(status != 0)) 3234683b57b4STrond Myklebust goto out; 3235c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3236c0eae66eSBenny Halevy if (unlikely(!p)) 3237c0eae66eSBenny Halevy goto out_overflow; 3238cccddf4fSBenny Halevy n = be32_to_cpup(p); 3239683b57b4STrond Myklebust if (n <= 0) 3240683b57b4STrond Myklebust goto out_eio; 3241683b57b4STrond Myklebust res->nlocations = 0; 3242683b57b4STrond Myklebust while (res->nlocations < n) { 3243464ad6b1SChuck Lever u32 m; 32447aaa0b3bSManoj Naik struct nfs4_fs_location *loc = &res->locations[res->nlocations]; 3245683b57b4STrond Myklebust 3246c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3247c0eae66eSBenny Halevy if (unlikely(!p)) 3248c0eae66eSBenny Halevy goto out_overflow; 3249cccddf4fSBenny Halevy m = be32_to_cpup(p); 32507aaa0b3bSManoj Naik 32517aaa0b3bSManoj Naik loc->nservers = 0; 32523110ff80SHarvey Harrison dprintk("%s: servers ", __func__); 32537aaa0b3bSManoj Naik while (loc->nservers < m) { 32547aaa0b3bSManoj Naik struct nfs4_string *server = &loc->servers[loc->nservers]; 32557aaa0b3bSManoj Naik status = decode_opaque_inline(xdr, &server->len, &server->data); 3256683b57b4STrond Myklebust if (unlikely(status != 0)) 3257683b57b4STrond Myklebust goto out_eio; 32587aaa0b3bSManoj Naik dprintk("%s ", server->data); 32597aaa0b3bSManoj Naik if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS) 32607aaa0b3bSManoj Naik loc->nservers++; 32617aaa0b3bSManoj Naik else { 3262464ad6b1SChuck Lever unsigned int i; 3263464ad6b1SChuck Lever dprintk("%s: using first %u of %u servers " 3264464ad6b1SChuck Lever "returned for location %u\n", 32653110ff80SHarvey Harrison __func__, 3266464ad6b1SChuck Lever NFS4_FS_LOCATION_MAXSERVERS, 3267464ad6b1SChuck Lever m, res->nlocations); 32687aaa0b3bSManoj Naik for (i = loc->nservers; i < m; i++) { 32692e42c3e2STrond Myklebust unsigned int len; 32707aaa0b3bSManoj Naik char *data; 32717aaa0b3bSManoj Naik status = decode_opaque_inline(xdr, &len, &data); 3272683b57b4STrond Myklebust if (unlikely(status != 0)) 3273683b57b4STrond Myklebust goto out_eio; 32747aaa0b3bSManoj Naik } 32757aaa0b3bSManoj Naik } 32767aaa0b3bSManoj Naik } 32777aaa0b3bSManoj Naik status = decode_pathname(xdr, &loc->rootpath); 32787aaa0b3bSManoj Naik if (unlikely(status != 0)) 32797aaa0b3bSManoj Naik goto out_eio; 32807aaa0b3bSManoj Naik if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES) 3281683b57b4STrond Myklebust res->nlocations++; 3282683b57b4STrond Myklebust } 3283409924e4STrond Myklebust if (res->nlocations != 0) 3284409924e4STrond Myklebust status = NFS_ATTR_FATTR_V4_REFERRAL; 3285683b57b4STrond Myklebust out: 32863110ff80SHarvey Harrison dprintk("%s: fs_locations done, error = %d\n", __func__, status); 3287683b57b4STrond Myklebust return status; 3288c0eae66eSBenny Halevy out_overflow: 3289c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3290683b57b4STrond Myklebust out_eio: 3291683b57b4STrond Myklebust status = -EIO; 3292683b57b4STrond Myklebust goto out; 3293683b57b4STrond Myklebust } 3294683b57b4STrond Myklebust 32951da177e4SLinus Torvalds static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 32961da177e4SLinus Torvalds { 32978687b63aSAl Viro __be32 *p; 32981da177e4SLinus Torvalds int status = 0; 32991da177e4SLinus Torvalds 33001da177e4SLinus Torvalds *res = 0; 33011da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U))) 33021da177e4SLinus Torvalds return -EIO; 33031da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) { 3304c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3305c0eae66eSBenny Halevy if (unlikely(!p)) 3306c0eae66eSBenny Halevy goto out_overflow; 3307cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 33081da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE; 33091da177e4SLinus Torvalds } 33103110ff80SHarvey Harrison dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res); 33111da177e4SLinus Torvalds return status; 3312c0eae66eSBenny Halevy out_overflow: 3313c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3314c0eae66eSBenny Halevy return -EIO; 33151da177e4SLinus Torvalds } 33161da177e4SLinus Torvalds 33171da177e4SLinus Torvalds static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink) 33181da177e4SLinus Torvalds { 33198687b63aSAl Viro __be32 *p; 33201da177e4SLinus Torvalds int status = 0; 33211da177e4SLinus Torvalds 33221da177e4SLinus Torvalds *maxlink = 1; 33231da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U))) 33241da177e4SLinus Torvalds return -EIO; 33251da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) { 3326c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3327c0eae66eSBenny Halevy if (unlikely(!p)) 3328c0eae66eSBenny Halevy goto out_overflow; 3329cccddf4fSBenny Halevy *maxlink = be32_to_cpup(p); 33301da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXLINK; 33311da177e4SLinus Torvalds } 33323110ff80SHarvey Harrison dprintk("%s: maxlink=%u\n", __func__, *maxlink); 33331da177e4SLinus Torvalds return status; 3334c0eae66eSBenny Halevy out_overflow: 3335c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3336c0eae66eSBenny Halevy return -EIO; 33371da177e4SLinus Torvalds } 33381da177e4SLinus Torvalds 33391da177e4SLinus Torvalds static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname) 33401da177e4SLinus Torvalds { 33418687b63aSAl Viro __be32 *p; 33421da177e4SLinus Torvalds int status = 0; 33431da177e4SLinus Torvalds 33441da177e4SLinus Torvalds *maxname = 1024; 33451da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U))) 33461da177e4SLinus Torvalds return -EIO; 33471da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) { 3348c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3349c0eae66eSBenny Halevy if (unlikely(!p)) 3350c0eae66eSBenny Halevy goto out_overflow; 3351cccddf4fSBenny Halevy *maxname = be32_to_cpup(p); 33521da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXNAME; 33531da177e4SLinus Torvalds } 33543110ff80SHarvey Harrison dprintk("%s: maxname=%u\n", __func__, *maxname); 33551da177e4SLinus Torvalds return status; 3356c0eae66eSBenny Halevy out_overflow: 3357c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3358c0eae66eSBenny Halevy return -EIO; 33591da177e4SLinus Torvalds } 33601da177e4SLinus Torvalds 33611da177e4SLinus Torvalds static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 33621da177e4SLinus Torvalds { 33638687b63aSAl Viro __be32 *p; 33641da177e4SLinus Torvalds int status = 0; 33651da177e4SLinus Torvalds 33661da177e4SLinus Torvalds *res = 1024; 33671da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U))) 33681da177e4SLinus Torvalds return -EIO; 33691da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) { 33701da177e4SLinus Torvalds uint64_t maxread; 3371c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3372c0eae66eSBenny Halevy if (unlikely(!p)) 3373c0eae66eSBenny Halevy goto out_overflow; 3374cccddf4fSBenny Halevy xdr_decode_hyper(p, &maxread); 33751da177e4SLinus Torvalds if (maxread > 0x7FFFFFFF) 33761da177e4SLinus Torvalds maxread = 0x7FFFFFFF; 33771da177e4SLinus Torvalds *res = (uint32_t)maxread; 33781da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXREAD; 33791da177e4SLinus Torvalds } 33803110ff80SHarvey Harrison dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res); 33811da177e4SLinus Torvalds return status; 3382c0eae66eSBenny Halevy out_overflow: 3383c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3384c0eae66eSBenny Halevy return -EIO; 33851da177e4SLinus Torvalds } 33861da177e4SLinus Torvalds 33871da177e4SLinus Torvalds static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) 33881da177e4SLinus Torvalds { 33898687b63aSAl Viro __be32 *p; 33901da177e4SLinus Torvalds int status = 0; 33911da177e4SLinus Torvalds 33921da177e4SLinus Torvalds *res = 1024; 33931da177e4SLinus Torvalds if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U))) 33941da177e4SLinus Torvalds return -EIO; 33951da177e4SLinus Torvalds if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) { 33961da177e4SLinus Torvalds uint64_t maxwrite; 3397c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3398c0eae66eSBenny Halevy if (unlikely(!p)) 3399c0eae66eSBenny Halevy goto out_overflow; 3400cccddf4fSBenny Halevy xdr_decode_hyper(p, &maxwrite); 34011da177e4SLinus Torvalds if (maxwrite > 0x7FFFFFFF) 34021da177e4SLinus Torvalds maxwrite = 0x7FFFFFFF; 34031da177e4SLinus Torvalds *res = (uint32_t)maxwrite; 34041da177e4SLinus Torvalds bitmap[0] &= ~FATTR4_WORD0_MAXWRITE; 34051da177e4SLinus Torvalds } 34063110ff80SHarvey Harrison dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res); 34071da177e4SLinus Torvalds return status; 3408c0eae66eSBenny Halevy out_overflow: 3409c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3410c0eae66eSBenny Halevy return -EIO; 34111da177e4SLinus Torvalds } 34121da177e4SLinus Torvalds 3413bca79478STrond Myklebust static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode) 34141da177e4SLinus Torvalds { 3415bca79478STrond Myklebust uint32_t tmp; 34168687b63aSAl Viro __be32 *p; 3417409924e4STrond Myklebust int ret = 0; 34181da177e4SLinus Torvalds 34191da177e4SLinus Torvalds *mode = 0; 34201da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U))) 34211da177e4SLinus Torvalds return -EIO; 34221da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_MODE)) { 3423c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3424c0eae66eSBenny Halevy if (unlikely(!p)) 3425c0eae66eSBenny Halevy goto out_overflow; 3426cccddf4fSBenny Halevy tmp = be32_to_cpup(p); 3427bca79478STrond Myklebust *mode = tmp & ~S_IFMT; 34281da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_MODE; 3429409924e4STrond Myklebust ret = NFS_ATTR_FATTR_MODE; 34301da177e4SLinus Torvalds } 34313110ff80SHarvey Harrison dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode); 3432409924e4STrond Myklebust return ret; 3433c0eae66eSBenny Halevy out_overflow: 3434c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3435c0eae66eSBenny Halevy return -EIO; 34361da177e4SLinus Torvalds } 34371da177e4SLinus Torvalds 34381da177e4SLinus Torvalds static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) 34391da177e4SLinus Torvalds { 34408687b63aSAl Viro __be32 *p; 3441409924e4STrond Myklebust int ret = 0; 34421da177e4SLinus Torvalds 34431da177e4SLinus Torvalds *nlink = 1; 34441da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U))) 34451da177e4SLinus Torvalds return -EIO; 34461da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) { 3447c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3448c0eae66eSBenny Halevy if (unlikely(!p)) 3449c0eae66eSBenny Halevy goto out_overflow; 3450cccddf4fSBenny Halevy *nlink = be32_to_cpup(p); 34511da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_NUMLINKS; 3452409924e4STrond Myklebust ret = NFS_ATTR_FATTR_NLINK; 34531da177e4SLinus Torvalds } 34543110ff80SHarvey Harrison dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink); 3455409924e4STrond Myklebust return ret; 3456c0eae66eSBenny Halevy out_overflow: 3457c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3458c0eae66eSBenny Halevy return -EIO; 34591da177e4SLinus Torvalds } 34601da177e4SLinus Torvalds 346180e52aceSTrond Myklebust static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, 3462e4fd72a1STrond Myklebust const struct nfs_server *server, uint32_t *uid, int may_sleep) 34631da177e4SLinus Torvalds { 34648687b63aSAl Viro uint32_t len; 34658687b63aSAl Viro __be32 *p; 3466409924e4STrond Myklebust int ret = 0; 34671da177e4SLinus Torvalds 34681da177e4SLinus Torvalds *uid = -2; 34691da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U))) 34701da177e4SLinus Torvalds return -EIO; 34711da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) { 3472c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3473c0eae66eSBenny Halevy if (unlikely(!p)) 3474c0eae66eSBenny Halevy goto out_overflow; 3475cccddf4fSBenny Halevy len = be32_to_cpup(p); 3476c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 3477c0eae66eSBenny Halevy if (unlikely(!p)) 3478c0eae66eSBenny Halevy goto out_overflow; 347980e52aceSTrond Myklebust if (!may_sleep) { 348080e52aceSTrond Myklebust /* do nothing */ 348180e52aceSTrond Myklebust } else if (len < XDR_MAX_NETOBJ) { 3482e4fd72a1STrond Myklebust if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0) 3483409924e4STrond Myklebust ret = NFS_ATTR_FATTR_OWNER; 3484409924e4STrond Myklebust else 34851da177e4SLinus Torvalds dprintk("%s: nfs_map_name_to_uid failed!\n", 34863110ff80SHarvey Harrison __func__); 34871da177e4SLinus Torvalds } else 3488fe82a183SChuck Lever dprintk("%s: name too long (%u)!\n", 34893110ff80SHarvey Harrison __func__, len); 34901da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_OWNER; 34911da177e4SLinus Torvalds } 34923110ff80SHarvey Harrison dprintk("%s: uid=%d\n", __func__, (int)*uid); 3493409924e4STrond Myklebust return ret; 3494c0eae66eSBenny Halevy out_overflow: 3495c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3496c0eae66eSBenny Halevy return -EIO; 34971da177e4SLinus Torvalds } 34981da177e4SLinus Torvalds 349980e52aceSTrond Myklebust static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, 3500e4fd72a1STrond Myklebust const struct nfs_server *server, uint32_t *gid, int may_sleep) 35011da177e4SLinus Torvalds { 35028687b63aSAl Viro uint32_t len; 35038687b63aSAl Viro __be32 *p; 3504409924e4STrond Myklebust int ret = 0; 35051da177e4SLinus Torvalds 35061da177e4SLinus Torvalds *gid = -2; 35071da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U))) 35081da177e4SLinus Torvalds return -EIO; 35091da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) { 3510c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3511c0eae66eSBenny Halevy if (unlikely(!p)) 3512c0eae66eSBenny Halevy goto out_overflow; 3513cccddf4fSBenny Halevy len = be32_to_cpup(p); 3514c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 3515c0eae66eSBenny Halevy if (unlikely(!p)) 3516c0eae66eSBenny Halevy goto out_overflow; 351780e52aceSTrond Myklebust if (!may_sleep) { 351880e52aceSTrond Myklebust /* do nothing */ 351980e52aceSTrond Myklebust } else if (len < XDR_MAX_NETOBJ) { 3520e4fd72a1STrond Myklebust if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0) 3521409924e4STrond Myklebust ret = NFS_ATTR_FATTR_GROUP; 3522409924e4STrond Myklebust else 35231da177e4SLinus Torvalds dprintk("%s: nfs_map_group_to_gid failed!\n", 35243110ff80SHarvey Harrison __func__); 35251da177e4SLinus Torvalds } else 3526fe82a183SChuck Lever dprintk("%s: name too long (%u)!\n", 35273110ff80SHarvey Harrison __func__, len); 35281da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP; 35291da177e4SLinus Torvalds } 35303110ff80SHarvey Harrison dprintk("%s: gid=%d\n", __func__, (int)*gid); 3531409924e4STrond Myklebust return ret; 3532c0eae66eSBenny Halevy out_overflow: 3533c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3534c0eae66eSBenny Halevy return -EIO; 35351da177e4SLinus Torvalds } 35361da177e4SLinus Torvalds 35371da177e4SLinus Torvalds static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) 35381da177e4SLinus Torvalds { 35398687b63aSAl Viro uint32_t major = 0, minor = 0; 35408687b63aSAl Viro __be32 *p; 3541409924e4STrond Myklebust int ret = 0; 35421da177e4SLinus Torvalds 35431da177e4SLinus Torvalds *rdev = MKDEV(0,0); 35441da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U))) 35451da177e4SLinus Torvalds return -EIO; 35461da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) { 35471da177e4SLinus Torvalds dev_t tmp; 35481da177e4SLinus Torvalds 3549c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3550c0eae66eSBenny Halevy if (unlikely(!p)) 3551c0eae66eSBenny Halevy goto out_overflow; 35526f723f77SBenny Halevy major = be32_to_cpup(p++); 3553cccddf4fSBenny Halevy minor = be32_to_cpup(p); 35541da177e4SLinus Torvalds tmp = MKDEV(major, minor); 35551da177e4SLinus Torvalds if (MAJOR(tmp) == major && MINOR(tmp) == minor) 35561da177e4SLinus Torvalds *rdev = tmp; 35571da177e4SLinus Torvalds bitmap[1] &= ~ FATTR4_WORD1_RAWDEV; 3558409924e4STrond Myklebust ret = NFS_ATTR_FATTR_RDEV; 35591da177e4SLinus Torvalds } 35603110ff80SHarvey Harrison dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor); 3561409924e4STrond Myklebust return ret; 3562c0eae66eSBenny Halevy out_overflow: 3563c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3564c0eae66eSBenny Halevy return -EIO; 35651da177e4SLinus Torvalds } 35661da177e4SLinus Torvalds 35671da177e4SLinus Torvalds static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 35681da177e4SLinus Torvalds { 35698687b63aSAl Viro __be32 *p; 35701da177e4SLinus Torvalds int status = 0; 35711da177e4SLinus Torvalds 35721da177e4SLinus Torvalds *res = 0; 35731da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U))) 35741da177e4SLinus Torvalds return -EIO; 35751da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) { 3576c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3577c0eae66eSBenny Halevy if (unlikely(!p)) 3578c0eae66eSBenny Halevy goto out_overflow; 3579cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 35801da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL; 35811da177e4SLinus Torvalds } 35823110ff80SHarvey Harrison dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res); 35831da177e4SLinus Torvalds return status; 3584c0eae66eSBenny Halevy out_overflow: 3585c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3586c0eae66eSBenny Halevy return -EIO; 35871da177e4SLinus Torvalds } 35881da177e4SLinus Torvalds 35891da177e4SLinus Torvalds static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 35901da177e4SLinus Torvalds { 35918687b63aSAl Viro __be32 *p; 35921da177e4SLinus Torvalds int status = 0; 35931da177e4SLinus Torvalds 35941da177e4SLinus Torvalds *res = 0; 35951da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U))) 35961da177e4SLinus Torvalds return -EIO; 35971da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) { 3598c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3599c0eae66eSBenny Halevy if (unlikely(!p)) 3600c0eae66eSBenny Halevy goto out_overflow; 3601cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 36021da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE; 36031da177e4SLinus Torvalds } 36043110ff80SHarvey Harrison dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res); 36051da177e4SLinus Torvalds return status; 3606c0eae66eSBenny Halevy out_overflow: 3607c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3608c0eae66eSBenny Halevy return -EIO; 36091da177e4SLinus Torvalds } 36101da177e4SLinus Torvalds 36111da177e4SLinus Torvalds static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) 36121da177e4SLinus Torvalds { 36138687b63aSAl Viro __be32 *p; 36141da177e4SLinus Torvalds int status = 0; 36151da177e4SLinus Torvalds 36161da177e4SLinus Torvalds *res = 0; 36171da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U))) 36181da177e4SLinus Torvalds return -EIO; 36191da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) { 3620c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3621c0eae66eSBenny Halevy if (unlikely(!p)) 3622c0eae66eSBenny Halevy goto out_overflow; 3623cccddf4fSBenny Halevy xdr_decode_hyper(p, res); 36241da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL; 36251da177e4SLinus Torvalds } 36263110ff80SHarvey Harrison dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res); 36271da177e4SLinus Torvalds return status; 3628c0eae66eSBenny Halevy out_overflow: 3629c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3630c0eae66eSBenny Halevy return -EIO; 36311da177e4SLinus Torvalds } 36321da177e4SLinus Torvalds 36331da177e4SLinus Torvalds static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) 36341da177e4SLinus Torvalds { 36358687b63aSAl Viro __be32 *p; 3636409924e4STrond Myklebust int ret = 0; 36371da177e4SLinus Torvalds 36381da177e4SLinus Torvalds *used = 0; 36391da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U))) 36401da177e4SLinus Torvalds return -EIO; 36411da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) { 3642c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3643c0eae66eSBenny Halevy if (unlikely(!p)) 3644c0eae66eSBenny Halevy goto out_overflow; 3645cccddf4fSBenny Halevy xdr_decode_hyper(p, used); 36461da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_SPACE_USED; 3647409924e4STrond Myklebust ret = NFS_ATTR_FATTR_SPACE_USED; 36481da177e4SLinus Torvalds } 36493110ff80SHarvey Harrison dprintk("%s: space used=%Lu\n", __func__, 36501da177e4SLinus Torvalds (unsigned long long)*used); 3651409924e4STrond Myklebust return ret; 3652c0eae66eSBenny Halevy out_overflow: 3653c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3654c0eae66eSBenny Halevy return -EIO; 36551da177e4SLinus Torvalds } 36561da177e4SLinus Torvalds 36571da177e4SLinus Torvalds static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time) 36581da177e4SLinus Torvalds { 36598687b63aSAl Viro __be32 *p; 36601da177e4SLinus Torvalds uint64_t sec; 36611da177e4SLinus Torvalds uint32_t nsec; 36621da177e4SLinus Torvalds 3663c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 3664c0eae66eSBenny Halevy if (unlikely(!p)) 3665c0eae66eSBenny Halevy goto out_overflow; 36663ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &sec); 3667cccddf4fSBenny Halevy nsec = be32_to_cpup(p); 36681da177e4SLinus Torvalds time->tv_sec = (time_t)sec; 36691da177e4SLinus Torvalds time->tv_nsec = (long)nsec; 36701da177e4SLinus Torvalds return 0; 3671c0eae66eSBenny Halevy out_overflow: 3672c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3673c0eae66eSBenny Halevy return -EIO; 36741da177e4SLinus Torvalds } 36751da177e4SLinus Torvalds 36761da177e4SLinus Torvalds static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) 36771da177e4SLinus Torvalds { 36781da177e4SLinus Torvalds int status = 0; 36791da177e4SLinus Torvalds 36801da177e4SLinus Torvalds time->tv_sec = 0; 36811da177e4SLinus Torvalds time->tv_nsec = 0; 36821da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U))) 36831da177e4SLinus Torvalds return -EIO; 36841da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) { 36851da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 3686409924e4STrond Myklebust if (status == 0) 3687409924e4STrond Myklebust status = NFS_ATTR_FATTR_ATIME; 36881da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS; 36891da177e4SLinus Torvalds } 36903110ff80SHarvey Harrison dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec); 36911da177e4SLinus Torvalds return status; 36921da177e4SLinus Torvalds } 36931da177e4SLinus Torvalds 36941da177e4SLinus Torvalds static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) 36951da177e4SLinus Torvalds { 36961da177e4SLinus Torvalds int status = 0; 36971da177e4SLinus Torvalds 36981da177e4SLinus Torvalds time->tv_sec = 0; 36991da177e4SLinus Torvalds time->tv_nsec = 0; 37001da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U))) 37011da177e4SLinus Torvalds return -EIO; 37021da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) { 37031da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 3704409924e4STrond Myklebust if (status == 0) 3705409924e4STrond Myklebust status = NFS_ATTR_FATTR_CTIME; 37061da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA; 37071da177e4SLinus Torvalds } 37083110ff80SHarvey Harrison dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec); 37091da177e4SLinus Torvalds return status; 37101da177e4SLinus Torvalds } 37111da177e4SLinus Torvalds 371255b6e774SRicardo Labiaga static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, 371355b6e774SRicardo Labiaga struct timespec *time) 371455b6e774SRicardo Labiaga { 371555b6e774SRicardo Labiaga int status = 0; 371655b6e774SRicardo Labiaga 371755b6e774SRicardo Labiaga time->tv_sec = 0; 371855b6e774SRicardo Labiaga time->tv_nsec = 0; 371955b6e774SRicardo Labiaga if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U))) 372055b6e774SRicardo Labiaga return -EIO; 372155b6e774SRicardo Labiaga if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) { 372255b6e774SRicardo Labiaga status = decode_attr_time(xdr, time); 372355b6e774SRicardo Labiaga bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA; 372455b6e774SRicardo Labiaga } 372555b6e774SRicardo Labiaga dprintk("%s: time_delta=%ld %ld\n", __func__, (long)time->tv_sec, 372655b6e774SRicardo Labiaga (long)time->tv_nsec); 372755b6e774SRicardo Labiaga return status; 372855b6e774SRicardo Labiaga } 372955b6e774SRicardo Labiaga 37301da177e4SLinus Torvalds static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) 37311da177e4SLinus Torvalds { 37321da177e4SLinus Torvalds int status = 0; 37331da177e4SLinus Torvalds 37341da177e4SLinus Torvalds time->tv_sec = 0; 37351da177e4SLinus Torvalds time->tv_nsec = 0; 37361da177e4SLinus Torvalds if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U))) 37371da177e4SLinus Torvalds return -EIO; 37381da177e4SLinus Torvalds if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) { 37391da177e4SLinus Torvalds status = decode_attr_time(xdr, time); 3740409924e4STrond Myklebust if (status == 0) 3741409924e4STrond Myklebust status = NFS_ATTR_FATTR_MTIME; 37421da177e4SLinus Torvalds bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY; 37431da177e4SLinus Torvalds } 37443110ff80SHarvey Harrison dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec); 37451da177e4SLinus Torvalds return status; 37461da177e4SLinus Torvalds } 37471da177e4SLinus Torvalds 37488687b63aSAl Viro static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen) 37491da177e4SLinus Torvalds { 37501da177e4SLinus Torvalds unsigned int attrwords = XDR_QUADLEN(attrlen); 37511da177e4SLinus Torvalds unsigned int nwords = xdr->p - savep; 37521da177e4SLinus Torvalds 37531da177e4SLinus Torvalds if (unlikely(attrwords != nwords)) { 3754fe82a183SChuck Lever dprintk("%s: server returned incorrect attribute length: " 3755fe82a183SChuck Lever "%u %c %u\n", 37563110ff80SHarvey Harrison __func__, 37571da177e4SLinus Torvalds attrwords << 2, 37581da177e4SLinus Torvalds (attrwords < nwords) ? '<' : '>', 37591da177e4SLinus Torvalds nwords << 2); 37601da177e4SLinus Torvalds return -EIO; 37611da177e4SLinus Torvalds } 37621da177e4SLinus Torvalds return 0; 37631da177e4SLinus Torvalds } 37641da177e4SLinus Torvalds 37651da177e4SLinus Torvalds static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 37661da177e4SLinus Torvalds { 37678687b63aSAl Viro __be32 *p; 37681da177e4SLinus Torvalds 3769c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 20); 3770c0eae66eSBenny Halevy if (unlikely(!p)) 3771c0eae66eSBenny Halevy goto out_overflow; 37726f723f77SBenny Halevy cinfo->atomic = be32_to_cpup(p++); 37733ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &cinfo->before); 3774cccddf4fSBenny Halevy xdr_decode_hyper(p, &cinfo->after); 37751da177e4SLinus Torvalds return 0; 3776c0eae66eSBenny Halevy out_overflow: 3777c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3778c0eae66eSBenny Halevy return -EIO; 37791da177e4SLinus Torvalds } 37801da177e4SLinus Torvalds 37811da177e4SLinus Torvalds static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access) 37821da177e4SLinus Torvalds { 37838687b63aSAl Viro __be32 *p; 37841da177e4SLinus Torvalds uint32_t supp, acc; 37851da177e4SLinus Torvalds int status; 37861da177e4SLinus Torvalds 37871da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_ACCESS); 37881da177e4SLinus Torvalds if (status) 37891da177e4SLinus Torvalds return status; 3790c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 3791c0eae66eSBenny Halevy if (unlikely(!p)) 3792c0eae66eSBenny Halevy goto out_overflow; 37936f723f77SBenny Halevy supp = be32_to_cpup(p++); 3794cccddf4fSBenny Halevy acc = be32_to_cpup(p); 37951da177e4SLinus Torvalds access->supported = supp; 37961da177e4SLinus Torvalds access->access = acc; 37971da177e4SLinus Torvalds return 0; 3798c0eae66eSBenny Halevy out_overflow: 3799c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3800c0eae66eSBenny Halevy return -EIO; 38011da177e4SLinus Torvalds } 38021da177e4SLinus Torvalds 380307d30434SBenny Halevy static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len) 38041da177e4SLinus Torvalds { 38058687b63aSAl Viro __be32 *p; 380607d30434SBenny Halevy 380707d30434SBenny Halevy p = xdr_inline_decode(xdr, len); 380807d30434SBenny Halevy if (likely(p)) { 380907d30434SBenny Halevy memcpy(buf, p, len); 381007d30434SBenny Halevy return 0; 381107d30434SBenny Halevy } 381207d30434SBenny Halevy print_overflow_msg(__func__, xdr); 381307d30434SBenny Halevy return -EIO; 381407d30434SBenny Halevy } 381507d30434SBenny Halevy 381607d30434SBenny Halevy static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 381707d30434SBenny Halevy { 381807d30434SBenny Halevy return decode_opaque_fixed(xdr, stateid->data, NFS4_STATEID_SIZE); 38191da177e4SLinus Torvalds } 38201da177e4SLinus Torvalds 38211da177e4SLinus Torvalds static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) 38221da177e4SLinus Torvalds { 38231da177e4SLinus Torvalds int status; 38241da177e4SLinus Torvalds 38251da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_CLOSE); 3826c1d51931STrond Myklebust if (status != -EIO) 3827c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 382807d30434SBenny Halevy if (!status) 382907d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 38301da177e4SLinus Torvalds return status; 38311da177e4SLinus Torvalds } 38321da177e4SLinus Torvalds 3833db942bbdSBenny Halevy static int decode_verifier(struct xdr_stream *xdr, void *verifier) 3834db942bbdSBenny Halevy { 3835db942bbdSBenny Halevy return decode_opaque_fixed(xdr, verifier, 8); 38361da177e4SLinus Torvalds } 38371da177e4SLinus Torvalds 38381da177e4SLinus Torvalds static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res) 38391da177e4SLinus Torvalds { 38401da177e4SLinus Torvalds int status; 38411da177e4SLinus Torvalds 38421da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_COMMIT); 3843db942bbdSBenny Halevy if (!status) 3844db942bbdSBenny Halevy status = decode_verifier(xdr, res->verf->verifier); 38451da177e4SLinus Torvalds return status; 38461da177e4SLinus Torvalds } 38471da177e4SLinus Torvalds 38481da177e4SLinus Torvalds static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 38491da177e4SLinus Torvalds { 38508687b63aSAl Viro __be32 *p; 38511da177e4SLinus Torvalds uint32_t bmlen; 38521da177e4SLinus Torvalds int status; 38531da177e4SLinus Torvalds 38541da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_CREATE); 38551da177e4SLinus Torvalds if (status) 38561da177e4SLinus Torvalds return status; 38571da177e4SLinus Torvalds if ((status = decode_change_info(xdr, cinfo))) 38581da177e4SLinus Torvalds return status; 3859c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 3860c0eae66eSBenny Halevy if (unlikely(!p)) 3861c0eae66eSBenny Halevy goto out_overflow; 3862cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 3863c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, bmlen << 2); 3864c0eae66eSBenny Halevy if (likely(p)) 38651da177e4SLinus Torvalds return 0; 3866c0eae66eSBenny Halevy out_overflow: 3867c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 3868c0eae66eSBenny Halevy return -EIO; 38691da177e4SLinus Torvalds } 38701da177e4SLinus Torvalds 38711da177e4SLinus Torvalds static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) 38721da177e4SLinus Torvalds { 38738687b63aSAl Viro __be32 *savep; 38746c0195a4SAndy Adamson uint32_t attrlen, bitmap[2] = {0}; 38751da177e4SLinus Torvalds int status; 38761da177e4SLinus Torvalds 38771da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 38781da177e4SLinus Torvalds goto xdr_error; 38791da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 38801da177e4SLinus Torvalds goto xdr_error; 38811da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 38821da177e4SLinus Torvalds goto xdr_error; 38831da177e4SLinus Torvalds if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0) 38841da177e4SLinus Torvalds goto xdr_error; 38851da177e4SLinus Torvalds if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0) 38861da177e4SLinus Torvalds goto xdr_error; 38871da177e4SLinus Torvalds if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0) 38881da177e4SLinus Torvalds goto xdr_error; 38891da177e4SLinus Torvalds if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0) 38901da177e4SLinus Torvalds goto xdr_error; 38911da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 38921da177e4SLinus Torvalds xdr_error: 38933110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 38941da177e4SLinus Torvalds return status; 38951da177e4SLinus Torvalds } 38961da177e4SLinus Torvalds 38971da177e4SLinus Torvalds static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) 38981da177e4SLinus Torvalds { 38998687b63aSAl Viro __be32 *savep; 39006c0195a4SAndy Adamson uint32_t attrlen, bitmap[2] = {0}; 39011da177e4SLinus Torvalds int status; 39021da177e4SLinus Torvalds 39031da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 39041da177e4SLinus Torvalds goto xdr_error; 39051da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 39061da177e4SLinus Torvalds goto xdr_error; 39071da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 39081da177e4SLinus Torvalds goto xdr_error; 39091da177e4SLinus Torvalds 39101da177e4SLinus Torvalds if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0) 39111da177e4SLinus Torvalds goto xdr_error; 39121da177e4SLinus Torvalds if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0) 39131da177e4SLinus Torvalds goto xdr_error; 39141da177e4SLinus Torvalds if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0) 39151da177e4SLinus Torvalds goto xdr_error; 39161da177e4SLinus Torvalds if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0) 39171da177e4SLinus Torvalds goto xdr_error; 39181da177e4SLinus Torvalds if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0) 39191da177e4SLinus Torvalds goto xdr_error; 39201da177e4SLinus Torvalds if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0) 39211da177e4SLinus Torvalds goto xdr_error; 39221da177e4SLinus Torvalds 39231da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 39241da177e4SLinus Torvalds xdr_error: 39253110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 39261da177e4SLinus Torvalds return status; 39271da177e4SLinus Torvalds } 39281da177e4SLinus Torvalds 39291da177e4SLinus Torvalds static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) 39301da177e4SLinus Torvalds { 39318687b63aSAl Viro __be32 *savep; 39326c0195a4SAndy Adamson uint32_t attrlen, bitmap[2] = {0}; 39331da177e4SLinus Torvalds int status; 39341da177e4SLinus Torvalds 39351da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 39361da177e4SLinus Torvalds goto xdr_error; 39371da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 39381da177e4SLinus Torvalds goto xdr_error; 39391da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 39401da177e4SLinus Torvalds goto xdr_error; 39411da177e4SLinus Torvalds 39421da177e4SLinus Torvalds if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0) 39431da177e4SLinus Torvalds goto xdr_error; 39441da177e4SLinus Torvalds if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0) 39451da177e4SLinus Torvalds goto xdr_error; 39461da177e4SLinus Torvalds 39471da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 39481da177e4SLinus Torvalds xdr_error: 39493110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 39501da177e4SLinus Torvalds return status; 39511da177e4SLinus Torvalds } 39521da177e4SLinus Torvalds 3953ae42c70aSBryan Schumaker static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, 3954ae42c70aSBryan Schumaker struct nfs_fattr *fattr, struct nfs_fh *fh, 395580e52aceSTrond Myklebust const struct nfs_server *server, int may_sleep) 39561da177e4SLinus Torvalds { 3957bca79478STrond Myklebust int status; 3958bca79478STrond Myklebust umode_t fmode = 0; 395999baf625SManoj Naik uint64_t fileid; 3960ae42c70aSBryan Schumaker uint32_t type; 39611da177e4SLinus Torvalds 3962f26c7a78STrond Myklebust status = decode_attr_type(xdr, bitmap, &type); 3963f26c7a78STrond Myklebust if (status < 0) 39641da177e4SLinus Torvalds goto xdr_error; 3965409924e4STrond Myklebust fattr->mode = 0; 3966409924e4STrond Myklebust if (status != 0) { 3967409924e4STrond Myklebust fattr->mode |= nfs_type2fmt[type]; 3968409924e4STrond Myklebust fattr->valid |= status; 3969409924e4STrond Myklebust } 39701da177e4SLinus Torvalds 3971f26c7a78STrond Myklebust status = decode_attr_change(xdr, bitmap, &fattr->change_attr); 3972f26c7a78STrond Myklebust if (status < 0) 39731da177e4SLinus Torvalds goto xdr_error; 3974409924e4STrond Myklebust fattr->valid |= status; 3975f26c7a78STrond Myklebust 3976f26c7a78STrond Myklebust status = decode_attr_size(xdr, bitmap, &fattr->size); 3977f26c7a78STrond Myklebust if (status < 0) 39781da177e4SLinus Torvalds goto xdr_error; 3979409924e4STrond Myklebust fattr->valid |= status; 3980f26c7a78STrond Myklebust 3981f26c7a78STrond Myklebust status = decode_attr_fsid(xdr, bitmap, &fattr->fsid); 3982f26c7a78STrond Myklebust if (status < 0) 39831da177e4SLinus Torvalds goto xdr_error; 3984409924e4STrond Myklebust fattr->valid |= status; 3985f26c7a78STrond Myklebust 3986ae42c70aSBryan Schumaker status = decode_attr_error(xdr, bitmap); 3987ae42c70aSBryan Schumaker if (status < 0) 3988ae42c70aSBryan Schumaker goto xdr_error; 3989ae42c70aSBryan Schumaker 3990ae42c70aSBryan Schumaker status = decode_attr_filehandle(xdr, bitmap, fh); 3991ae42c70aSBryan Schumaker if (status < 0) 3992ae42c70aSBryan Schumaker goto xdr_error; 3993ae42c70aSBryan Schumaker 3994f26c7a78STrond Myklebust status = decode_attr_fileid(xdr, bitmap, &fattr->fileid); 3995f26c7a78STrond Myklebust if (status < 0) 39961da177e4SLinus Torvalds goto xdr_error; 3997409924e4STrond Myklebust fattr->valid |= status; 3998f26c7a78STrond Myklebust 3999f26c7a78STrond Myklebust status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, 40007aaa0b3bSManoj Naik struct nfs4_fs_locations, 4001f26c7a78STrond Myklebust fattr)); 4002f26c7a78STrond Myklebust if (status < 0) 4003683b57b4STrond Myklebust goto xdr_error; 4004409924e4STrond Myklebust fattr->valid |= status; 4005f26c7a78STrond Myklebust 4006f26c7a78STrond Myklebust status = decode_attr_mode(xdr, bitmap, &fmode); 4007f26c7a78STrond Myklebust if (status < 0) 40081da177e4SLinus Torvalds goto xdr_error; 4009409924e4STrond Myklebust if (status != 0) { 40101da177e4SLinus Torvalds fattr->mode |= fmode; 4011409924e4STrond Myklebust fattr->valid |= status; 4012409924e4STrond Myklebust } 4013f26c7a78STrond Myklebust 4014f26c7a78STrond Myklebust status = decode_attr_nlink(xdr, bitmap, &fattr->nlink); 4015f26c7a78STrond Myklebust if (status < 0) 40161da177e4SLinus Torvalds goto xdr_error; 4017409924e4STrond Myklebust fattr->valid |= status; 4018f26c7a78STrond Myklebust 4019e4fd72a1STrond Myklebust status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, may_sleep); 4020f26c7a78STrond Myklebust if (status < 0) 40211da177e4SLinus Torvalds goto xdr_error; 4022409924e4STrond Myklebust fattr->valid |= status; 4023f26c7a78STrond Myklebust 4024e4fd72a1STrond Myklebust status = decode_attr_group(xdr, bitmap, server, &fattr->gid, may_sleep); 4025f26c7a78STrond Myklebust if (status < 0) 40261da177e4SLinus Torvalds goto xdr_error; 4027409924e4STrond Myklebust fattr->valid |= status; 4028f26c7a78STrond Myklebust 4029f26c7a78STrond Myklebust status = decode_attr_rdev(xdr, bitmap, &fattr->rdev); 4030f26c7a78STrond Myklebust if (status < 0) 40311da177e4SLinus Torvalds goto xdr_error; 4032409924e4STrond Myklebust fattr->valid |= status; 4033f26c7a78STrond Myklebust 4034f26c7a78STrond Myklebust status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used); 4035f26c7a78STrond Myklebust if (status < 0) 40361da177e4SLinus Torvalds goto xdr_error; 4037409924e4STrond Myklebust fattr->valid |= status; 4038f26c7a78STrond Myklebust 4039f26c7a78STrond Myklebust status = decode_attr_time_access(xdr, bitmap, &fattr->atime); 4040f26c7a78STrond Myklebust if (status < 0) 40411da177e4SLinus Torvalds goto xdr_error; 4042409924e4STrond Myklebust fattr->valid |= status; 4043f26c7a78STrond Myklebust 4044f26c7a78STrond Myklebust status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime); 4045f26c7a78STrond Myklebust if (status < 0) 40461da177e4SLinus Torvalds goto xdr_error; 4047409924e4STrond Myklebust fattr->valid |= status; 4048f26c7a78STrond Myklebust 4049f26c7a78STrond Myklebust status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime); 4050f26c7a78STrond Myklebust if (status < 0) 40511da177e4SLinus Torvalds goto xdr_error; 4052409924e4STrond Myklebust fattr->valid |= status; 4053f26c7a78STrond Myklebust 4054f26c7a78STrond Myklebust status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid); 4055f26c7a78STrond Myklebust if (status < 0) 405699baf625SManoj Naik goto xdr_error; 40573201f3ddSTrond Myklebust if (status != 0 && !(fattr->valid & status)) { 405899baf625SManoj Naik fattr->fileid = fileid; 4059409924e4STrond Myklebust fattr->valid |= status; 4060409924e4STrond Myklebust } 4061f26c7a78STrond Myklebust 4062ae42c70aSBryan Schumaker xdr_error: 4063ae42c70aSBryan Schumaker dprintk("%s: xdr returned %d\n", __func__, -status); 4064ae42c70aSBryan Schumaker return status; 4065ae42c70aSBryan Schumaker } 4066ae42c70aSBryan Schumaker 4067ae42c70aSBryan Schumaker static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, 4068ae42c70aSBryan Schumaker struct nfs_fh *fh, const struct nfs_server *server, int may_sleep) 4069ae42c70aSBryan Schumaker { 4070ae42c70aSBryan Schumaker __be32 *savep; 4071ae42c70aSBryan Schumaker uint32_t attrlen, 4072ae42c70aSBryan Schumaker bitmap[2] = {0}; 4073ae42c70aSBryan Schumaker int status; 4074ae42c70aSBryan Schumaker 4075ae42c70aSBryan Schumaker status = decode_op_hdr(xdr, OP_GETATTR); 4076ae42c70aSBryan Schumaker if (status < 0) 4077ae42c70aSBryan Schumaker goto xdr_error; 4078ae42c70aSBryan Schumaker 4079ae42c70aSBryan Schumaker status = decode_attr_bitmap(xdr, bitmap); 4080ae42c70aSBryan Schumaker if (status < 0) 4081ae42c70aSBryan Schumaker goto xdr_error; 4082ae42c70aSBryan Schumaker 4083ae42c70aSBryan Schumaker status = decode_attr_length(xdr, &attrlen, &savep); 4084ae42c70aSBryan Schumaker if (status < 0) 4085ae42c70aSBryan Schumaker goto xdr_error; 4086ae42c70aSBryan Schumaker 4087ae42c70aSBryan Schumaker status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep); 4088ae42c70aSBryan Schumaker if (status < 0) 4089ae42c70aSBryan Schumaker goto xdr_error; 4090ae42c70aSBryan Schumaker 4091f26c7a78STrond Myklebust status = verify_attr_len(xdr, savep, attrlen); 40921da177e4SLinus Torvalds xdr_error: 40933110ff80SHarvey Harrison dprintk("%s: xdr returned %d\n", __func__, -status); 40941da177e4SLinus Torvalds return status; 40951da177e4SLinus Torvalds } 40961da177e4SLinus Torvalds 4097ae42c70aSBryan Schumaker static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, 4098ae42c70aSBryan Schumaker const struct nfs_server *server, int may_sleep) 4099ae42c70aSBryan Schumaker { 4100ae42c70aSBryan Schumaker return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); 4101ae42c70aSBryan Schumaker } 41021da177e4SLinus Torvalds 4103504913fbSAndy Adamson /* 4104504913fbSAndy Adamson * Decode potentially multiple layout types. Currently we only support 4105504913fbSAndy Adamson * one layout driver per file system. 4106504913fbSAndy Adamson */ 4107504913fbSAndy Adamson static int decode_first_pnfs_layout_type(struct xdr_stream *xdr, 4108504913fbSAndy Adamson uint32_t *layouttype) 4109504913fbSAndy Adamson { 4110504913fbSAndy Adamson uint32_t *p; 4111504913fbSAndy Adamson int num; 4112504913fbSAndy Adamson 4113504913fbSAndy Adamson p = xdr_inline_decode(xdr, 4); 4114504913fbSAndy Adamson if (unlikely(!p)) 4115504913fbSAndy Adamson goto out_overflow; 4116504913fbSAndy Adamson num = be32_to_cpup(p); 4117504913fbSAndy Adamson 4118504913fbSAndy Adamson /* pNFS is not supported by the underlying file system */ 4119504913fbSAndy Adamson if (num == 0) { 4120504913fbSAndy Adamson *layouttype = 0; 4121504913fbSAndy Adamson return 0; 4122504913fbSAndy Adamson } 4123504913fbSAndy Adamson if (num > 1) 4124504913fbSAndy Adamson printk(KERN_INFO "%s: Warning: Multiple pNFS layout drivers " 4125504913fbSAndy Adamson "per filesystem not supported\n", __func__); 4126504913fbSAndy Adamson 4127504913fbSAndy Adamson /* Decode and set first layout type, move xdr->p past unused types */ 4128504913fbSAndy Adamson p = xdr_inline_decode(xdr, num * 4); 4129504913fbSAndy Adamson if (unlikely(!p)) 4130504913fbSAndy Adamson goto out_overflow; 4131504913fbSAndy Adamson *layouttype = be32_to_cpup(p); 4132504913fbSAndy Adamson return 0; 4133504913fbSAndy Adamson out_overflow: 4134504913fbSAndy Adamson print_overflow_msg(__func__, xdr); 4135504913fbSAndy Adamson return -EIO; 4136504913fbSAndy Adamson } 4137504913fbSAndy Adamson 4138504913fbSAndy Adamson /* 4139504913fbSAndy Adamson * The type of file system exported. 4140504913fbSAndy Adamson * Note we must ensure that layouttype is set in any non-error case. 4141504913fbSAndy Adamson */ 4142504913fbSAndy Adamson static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap, 4143504913fbSAndy Adamson uint32_t *layouttype) 4144504913fbSAndy Adamson { 4145504913fbSAndy Adamson int status = 0; 4146504913fbSAndy Adamson 4147504913fbSAndy Adamson dprintk("%s: bitmap is %x\n", __func__, bitmap[1]); 4148504913fbSAndy Adamson if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U))) 4149504913fbSAndy Adamson return -EIO; 4150504913fbSAndy Adamson if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) { 4151504913fbSAndy Adamson status = decode_first_pnfs_layout_type(xdr, layouttype); 4152504913fbSAndy Adamson bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES; 4153504913fbSAndy Adamson } else 4154504913fbSAndy Adamson *layouttype = 0; 4155504913fbSAndy Adamson return status; 4156504913fbSAndy Adamson } 4157504913fbSAndy Adamson 41581da177e4SLinus Torvalds static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) 41591da177e4SLinus Torvalds { 41608687b63aSAl Viro __be32 *savep; 41611da177e4SLinus Torvalds uint32_t attrlen, bitmap[2]; 41621da177e4SLinus Torvalds int status; 41631da177e4SLinus Torvalds 41641da177e4SLinus Torvalds if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 41651da177e4SLinus Torvalds goto xdr_error; 41661da177e4SLinus Torvalds if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 41671da177e4SLinus Torvalds goto xdr_error; 41681da177e4SLinus Torvalds if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 41691da177e4SLinus Torvalds goto xdr_error; 41701da177e4SLinus Torvalds 41711da177e4SLinus Torvalds fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */ 41721da177e4SLinus Torvalds 41731da177e4SLinus Torvalds if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0) 41741da177e4SLinus Torvalds goto xdr_error; 41751da177e4SLinus Torvalds if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0) 41761da177e4SLinus Torvalds goto xdr_error; 41771da177e4SLinus Torvalds if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0) 41781da177e4SLinus Torvalds goto xdr_error; 41791da177e4SLinus Torvalds fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax; 41801da177e4SLinus Torvalds if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0) 41811da177e4SLinus Torvalds goto xdr_error; 41821da177e4SLinus Torvalds fsinfo->wtpref = fsinfo->wtmax; 418355b6e774SRicardo Labiaga status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta); 418455b6e774SRicardo Labiaga if (status != 0) 418555b6e774SRicardo Labiaga goto xdr_error; 4186504913fbSAndy Adamson status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype); 4187504913fbSAndy Adamson if (status != 0) 4188504913fbSAndy Adamson goto xdr_error; 41891da177e4SLinus Torvalds 41901da177e4SLinus Torvalds status = verify_attr_len(xdr, savep, attrlen); 41911da177e4SLinus Torvalds xdr_error: 41923110ff80SHarvey Harrison dprintk("%s: xdr returned %d!\n", __func__, -status); 41931da177e4SLinus Torvalds return status; 41941da177e4SLinus Torvalds } 41951da177e4SLinus Torvalds 41961da177e4SLinus Torvalds static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) 41971da177e4SLinus Torvalds { 41988687b63aSAl Viro __be32 *p; 41991da177e4SLinus Torvalds uint32_t len; 42001da177e4SLinus Torvalds int status; 42011da177e4SLinus Torvalds 42029936781dSTrond Myklebust /* Zero handle first to allow comparisons */ 42039936781dSTrond Myklebust memset(fh, 0, sizeof(*fh)); 42049936781dSTrond Myklebust 42051da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_GETFH); 42061da177e4SLinus Torvalds if (status) 42071da177e4SLinus Torvalds return status; 42081da177e4SLinus Torvalds 4209c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4210c0eae66eSBenny Halevy if (unlikely(!p)) 4211c0eae66eSBenny Halevy goto out_overflow; 4212cccddf4fSBenny Halevy len = be32_to_cpup(p); 42131da177e4SLinus Torvalds if (len > NFS4_FHSIZE) 42141da177e4SLinus Torvalds return -EIO; 42151da177e4SLinus Torvalds fh->size = len; 4216c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 4217c0eae66eSBenny Halevy if (unlikely(!p)) 4218c0eae66eSBenny Halevy goto out_overflow; 421999398d06SBenny Halevy memcpy(fh->data, p, len); 42201da177e4SLinus Torvalds return 0; 4221c0eae66eSBenny Halevy out_overflow: 4222c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4223c0eae66eSBenny Halevy return -EIO; 42241da177e4SLinus Torvalds } 42251da177e4SLinus Torvalds 42261da177e4SLinus Torvalds static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 42271da177e4SLinus Torvalds { 42281da177e4SLinus Torvalds int status; 42291da177e4SLinus Torvalds 42301da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LINK); 42311da177e4SLinus Torvalds if (status) 42321da177e4SLinus Torvalds return status; 42331da177e4SLinus Torvalds return decode_change_info(xdr, cinfo); 42341da177e4SLinus Torvalds } 42351da177e4SLinus Torvalds 42361da177e4SLinus Torvalds /* 42371da177e4SLinus Torvalds * We create the owner, so we know a proper owner.id length is 4. 42381da177e4SLinus Torvalds */ 4239911d1aafSTrond Myklebust static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) 42401da177e4SLinus Torvalds { 4241911d1aafSTrond Myklebust uint64_t offset, length, clientid; 42428687b63aSAl Viro __be32 *p; 4243911d1aafSTrond Myklebust uint32_t namelen, type; 42441da177e4SLinus Torvalds 4245babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 32); /* read 32 bytes */ 4246c0eae66eSBenny Halevy if (unlikely(!p)) 4247c0eae66eSBenny Halevy goto out_overflow; 4248babddc72SBryan Schumaker p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */ 42493ceb4dbbSBenny Halevy p = xdr_decode_hyper(p, &length); 4250babddc72SBryan Schumaker type = be32_to_cpup(p++); /* 4 byte read */ 4251babddc72SBryan Schumaker if (fl != NULL) { /* manipulate file lock */ 4252911d1aafSTrond Myklebust fl->fl_start = (loff_t)offset; 4253911d1aafSTrond Myklebust fl->fl_end = fl->fl_start + (loff_t)length - 1; 4254911d1aafSTrond Myklebust if (length == ~(uint64_t)0) 4255911d1aafSTrond Myklebust fl->fl_end = OFFSET_MAX; 4256911d1aafSTrond Myklebust fl->fl_type = F_WRLCK; 4257911d1aafSTrond Myklebust if (type & 1) 4258911d1aafSTrond Myklebust fl->fl_type = F_RDLCK; 4259911d1aafSTrond Myklebust fl->fl_pid = 0; 4260911d1aafSTrond Myklebust } 4261babddc72SBryan Schumaker p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */ 4262babddc72SBryan Schumaker namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */ 4263babddc72SBryan Schumaker p = xdr_inline_decode(xdr, namelen); /* variable size field */ 4264c0eae66eSBenny Halevy if (likely(p)) 42651da177e4SLinus Torvalds return -NFS4ERR_DENIED; 4266c0eae66eSBenny Halevy out_overflow: 4267c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4268c0eae66eSBenny Halevy return -EIO; 42691da177e4SLinus Torvalds } 42701da177e4SLinus Torvalds 4271911d1aafSTrond Myklebust static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) 42721da177e4SLinus Torvalds { 42731da177e4SLinus Torvalds int status; 42741da177e4SLinus Torvalds 42751da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCK); 4276c1d51931STrond Myklebust if (status == -EIO) 4277c1d51931STrond Myklebust goto out; 42781da177e4SLinus Torvalds if (status == 0) { 427907d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 428007d30434SBenny Halevy if (unlikely(status)) 428107d30434SBenny Halevy goto out; 42821da177e4SLinus Torvalds } else if (status == -NFS4ERR_DENIED) 4283c1d51931STrond Myklebust status = decode_lock_denied(xdr, NULL); 4284c1d51931STrond Myklebust if (res->open_seqid != NULL) 4285c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->open_seqid); 4286c1d51931STrond Myklebust nfs_increment_lock_seqid(status, res->lock_seqid); 4287c1d51931STrond Myklebust out: 42881da177e4SLinus Torvalds return status; 42891da177e4SLinus Torvalds } 42901da177e4SLinus Torvalds 4291911d1aafSTrond Myklebust static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res) 42921da177e4SLinus Torvalds { 42931da177e4SLinus Torvalds int status; 42941da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCKT); 42951da177e4SLinus Torvalds if (status == -NFS4ERR_DENIED) 4296911d1aafSTrond Myklebust return decode_lock_denied(xdr, res->denied); 42971da177e4SLinus Torvalds return status; 42981da177e4SLinus Torvalds } 42991da177e4SLinus Torvalds 4300911d1aafSTrond Myklebust static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) 43011da177e4SLinus Torvalds { 43021da177e4SLinus Torvalds int status; 43031da177e4SLinus Torvalds 43041da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_LOCKU); 4305c1d51931STrond Myklebust if (status != -EIO) 4306c1d51931STrond Myklebust nfs_increment_lock_seqid(status, res->seqid); 430707d30434SBenny Halevy if (status == 0) 430807d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 43091da177e4SLinus Torvalds return status; 43101da177e4SLinus Torvalds } 43111da177e4SLinus Torvalds 4312d3c7b7ccSTrond Myklebust static int decode_release_lockowner(struct xdr_stream *xdr) 4313d3c7b7ccSTrond Myklebust { 4314d3c7b7ccSTrond Myklebust return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER); 4315d3c7b7ccSTrond Myklebust } 4316d3c7b7ccSTrond Myklebust 43171da177e4SLinus Torvalds static int decode_lookup(struct xdr_stream *xdr) 43181da177e4SLinus Torvalds { 43191da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_LOOKUP); 43201da177e4SLinus Torvalds } 43211da177e4SLinus Torvalds 43221da177e4SLinus Torvalds /* This is too sick! */ 43231da177e4SLinus Torvalds static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize) 43241da177e4SLinus Torvalds { 43258687b63aSAl Viro __be32 *p; 43261da177e4SLinus Torvalds uint32_t limit_type, nblocks, blocksize; 43271da177e4SLinus Torvalds 4328c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 4329c0eae66eSBenny Halevy if (unlikely(!p)) 4330c0eae66eSBenny Halevy goto out_overflow; 43316f723f77SBenny Halevy limit_type = be32_to_cpup(p++); 43321da177e4SLinus Torvalds switch (limit_type) { 43331da177e4SLinus Torvalds case 1: 4334cccddf4fSBenny Halevy xdr_decode_hyper(p, maxsize); 43351da177e4SLinus Torvalds break; 43361da177e4SLinus Torvalds case 2: 43376f723f77SBenny Halevy nblocks = be32_to_cpup(p++); 4338cccddf4fSBenny Halevy blocksize = be32_to_cpup(p); 43391da177e4SLinus Torvalds *maxsize = (uint64_t)nblocks * (uint64_t)blocksize; 43401da177e4SLinus Torvalds } 43411da177e4SLinus Torvalds return 0; 4342c0eae66eSBenny Halevy out_overflow: 4343c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4344c0eae66eSBenny Halevy return -EIO; 43451da177e4SLinus Torvalds } 43461da177e4SLinus Torvalds 43471da177e4SLinus Torvalds static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) 43481da177e4SLinus Torvalds { 43498687b63aSAl Viro __be32 *p; 43501da177e4SLinus Torvalds uint32_t delegation_type; 435107d30434SBenny Halevy int status; 43521da177e4SLinus Torvalds 4353c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4354c0eae66eSBenny Halevy if (unlikely(!p)) 4355c0eae66eSBenny Halevy goto out_overflow; 4356cccddf4fSBenny Halevy delegation_type = be32_to_cpup(p); 43571da177e4SLinus Torvalds if (delegation_type == NFS4_OPEN_DELEGATE_NONE) { 43581da177e4SLinus Torvalds res->delegation_type = 0; 43591da177e4SLinus Torvalds return 0; 43601da177e4SLinus Torvalds } 436107d30434SBenny Halevy status = decode_stateid(xdr, &res->delegation); 436207d30434SBenny Halevy if (unlikely(status)) 436307d30434SBenny Halevy return status; 4364c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4365c0eae66eSBenny Halevy if (unlikely(!p)) 4366c0eae66eSBenny Halevy goto out_overflow; 4367cccddf4fSBenny Halevy res->do_recall = be32_to_cpup(p); 436805d564feSAndy Adamson 43691da177e4SLinus Torvalds switch (delegation_type) { 43701da177e4SLinus Torvalds case NFS4_OPEN_DELEGATE_READ: 43711da177e4SLinus Torvalds res->delegation_type = FMODE_READ; 43721da177e4SLinus Torvalds break; 43731da177e4SLinus Torvalds case NFS4_OPEN_DELEGATE_WRITE: 43741da177e4SLinus Torvalds res->delegation_type = FMODE_WRITE|FMODE_READ; 43751da177e4SLinus Torvalds if (decode_space_limit(xdr, &res->maxsize) < 0) 43761da177e4SLinus Torvalds return -EIO; 43771da177e4SLinus Torvalds } 43787539bbabSDavid Howells return decode_ace(xdr, NULL, res->server->nfs_client); 4379c0eae66eSBenny Halevy out_overflow: 4380c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4381c0eae66eSBenny Halevy return -EIO; 43821da177e4SLinus Torvalds } 43831da177e4SLinus Torvalds 43841da177e4SLinus Torvalds static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) 43851da177e4SLinus Torvalds { 43868687b63aSAl Viro __be32 *p; 4387aa53ed54SJeff Layton uint32_t savewords, bmlen, i; 43881da177e4SLinus Torvalds int status; 43891da177e4SLinus Torvalds 43901da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_OPEN); 4391c1d51931STrond Myklebust if (status != -EIO) 4392c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 439307d30434SBenny Halevy if (!status) 439407d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 439507d30434SBenny Halevy if (unlikely(status)) 43961da177e4SLinus Torvalds return status; 43971da177e4SLinus Torvalds 43981da177e4SLinus Torvalds decode_change_info(xdr, &res->cinfo); 43991da177e4SLinus Torvalds 4400c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4401c0eae66eSBenny Halevy if (unlikely(!p)) 4402c0eae66eSBenny Halevy goto out_overflow; 44036f723f77SBenny Halevy res->rflags = be32_to_cpup(p++); 4404cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 44051da177e4SLinus Torvalds if (bmlen > 10) 44061da177e4SLinus Torvalds goto xdr_error; 44071da177e4SLinus Torvalds 4408c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, bmlen << 2); 4409c0eae66eSBenny Halevy if (unlikely(!p)) 4410c0eae66eSBenny Halevy goto out_overflow; 4411aa53ed54SJeff Layton savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE); 4412aa53ed54SJeff Layton for (i = 0; i < savewords; ++i) 44136f723f77SBenny Halevy res->attrset[i] = be32_to_cpup(p++); 4414aa53ed54SJeff Layton for (; i < NFS4_BITMAP_SIZE; i++) 4415aa53ed54SJeff Layton res->attrset[i] = 0; 4416aa53ed54SJeff Layton 44171da177e4SLinus Torvalds return decode_delegation(xdr, res); 44181da177e4SLinus Torvalds xdr_error: 44193110ff80SHarvey Harrison dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen); 44201da177e4SLinus Torvalds return -EIO; 4421c0eae66eSBenny Halevy out_overflow: 4422c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4423c0eae66eSBenny Halevy return -EIO; 44241da177e4SLinus Torvalds } 44251da177e4SLinus Torvalds 44261da177e4SLinus Torvalds static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res) 44271da177e4SLinus Torvalds { 44281da177e4SLinus Torvalds int status; 44291da177e4SLinus Torvalds 44301da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); 4431c1d51931STrond Myklebust if (status != -EIO) 4432c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 443307d30434SBenny Halevy if (!status) 443407d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 44351da177e4SLinus Torvalds return status; 44361da177e4SLinus Torvalds } 44371da177e4SLinus Torvalds 44381da177e4SLinus Torvalds static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res) 44391da177e4SLinus Torvalds { 44401da177e4SLinus Torvalds int status; 44411da177e4SLinus Torvalds 44421da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); 4443c1d51931STrond Myklebust if (status != -EIO) 4444c1d51931STrond Myklebust nfs_increment_open_seqid(status, res->seqid); 444507d30434SBenny Halevy if (!status) 444607d30434SBenny Halevy status = decode_stateid(xdr, &res->stateid); 44471da177e4SLinus Torvalds return status; 44481da177e4SLinus Torvalds } 44491da177e4SLinus Torvalds 44501da177e4SLinus Torvalds static int decode_putfh(struct xdr_stream *xdr) 44511da177e4SLinus Torvalds { 44521da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_PUTFH); 44531da177e4SLinus Torvalds } 44541da177e4SLinus Torvalds 44551da177e4SLinus Torvalds static int decode_putrootfh(struct xdr_stream *xdr) 44561da177e4SLinus Torvalds { 44571da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_PUTROOTFH); 44581da177e4SLinus Torvalds } 44591da177e4SLinus Torvalds 44601da177e4SLinus Torvalds static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res) 44611da177e4SLinus Torvalds { 44621da177e4SLinus Torvalds struct kvec *iov = req->rq_rcv_buf.head; 44638687b63aSAl Viro __be32 *p; 44641da177e4SLinus Torvalds uint32_t count, eof, recvd, hdrlen; 44651da177e4SLinus Torvalds int status; 44661da177e4SLinus Torvalds 44671da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READ); 44681da177e4SLinus Torvalds if (status) 44691da177e4SLinus Torvalds return status; 4470c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4471c0eae66eSBenny Halevy if (unlikely(!p)) 4472c0eae66eSBenny Halevy goto out_overflow; 44736f723f77SBenny Halevy eof = be32_to_cpup(p++); 4474cccddf4fSBenny Halevy count = be32_to_cpup(p); 44758111f373SChuck Lever hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; 44761da177e4SLinus Torvalds recvd = req->rq_rcv_buf.len - hdrlen; 44771da177e4SLinus Torvalds if (count > recvd) { 4478fe82a183SChuck Lever dprintk("NFS: server cheating in read reply: " 44791da177e4SLinus Torvalds "count %u > recvd %u\n", count, recvd); 44801da177e4SLinus Torvalds count = recvd; 44811da177e4SLinus Torvalds eof = 0; 44821da177e4SLinus Torvalds } 44831da177e4SLinus Torvalds xdr_read_pages(xdr, count); 44841da177e4SLinus Torvalds res->eof = eof; 44851da177e4SLinus Torvalds res->count = count; 44861da177e4SLinus Torvalds return 0; 4487c0eae66eSBenny Halevy out_overflow: 4488c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4489c0eae66eSBenny Halevy return -EIO; 44901da177e4SLinus Torvalds } 44911da177e4SLinus Torvalds 44921da177e4SLinus Torvalds static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) 44931da177e4SLinus Torvalds { 44941da177e4SLinus Torvalds struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 44951da177e4SLinus Torvalds struct kvec *iov = rcvbuf->head; 4496bcecff77SChuck Lever size_t hdrlen; 4497bcecff77SChuck Lever u32 recvd, pglen = rcvbuf->page_len; 4498bcecff77SChuck Lever int status; 44991da177e4SLinus Torvalds 45001da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READDIR); 4501db942bbdSBenny Halevy if (!status) 4502db942bbdSBenny Halevy status = decode_verifier(xdr, readdir->verifier.data); 4503db942bbdSBenny Halevy if (unlikely(status)) 45041da177e4SLinus Torvalds return status; 450544109241SFred Isaman dprintk("%s: verifier = %08x:%08x\n", 450644109241SFred Isaman __func__, 4507eadf4598STrond Myklebust ((u32 *)readdir->verifier.data)[0], 4508eadf4598STrond Myklebust ((u32 *)readdir->verifier.data)[1]); 4509eadf4598STrond Myklebust 45101da177e4SLinus Torvalds 4511db942bbdSBenny Halevy hdrlen = (char *) xdr->p - (char *) iov->iov_base; 45121da177e4SLinus Torvalds recvd = rcvbuf->len - hdrlen; 45131da177e4SLinus Torvalds if (pglen > recvd) 45141da177e4SLinus Torvalds pglen = recvd; 45151da177e4SLinus Torvalds xdr_read_pages(xdr, pglen); 45161da177e4SLinus Torvalds 45177bda2cdfSJeff Layton 4518ac396128STrond Myklebust return pglen; 45191da177e4SLinus Torvalds } 45201da177e4SLinus Torvalds 45211da177e4SLinus Torvalds static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) 45221da177e4SLinus Torvalds { 45231da177e4SLinus Torvalds struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 45241da177e4SLinus Torvalds struct kvec *iov = rcvbuf->head; 4525bcecff77SChuck Lever size_t hdrlen; 4526bcecff77SChuck Lever u32 len, recvd; 45278687b63aSAl Viro __be32 *p; 45281da177e4SLinus Torvalds int status; 45291da177e4SLinus Torvalds 45301da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_READLINK); 45311da177e4SLinus Torvalds if (status) 45321da177e4SLinus Torvalds return status; 45331da177e4SLinus Torvalds 45341da177e4SLinus Torvalds /* Convert length of symlink */ 4535c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4536c0eae66eSBenny Halevy if (unlikely(!p)) 4537c0eae66eSBenny Halevy goto out_overflow; 4538cccddf4fSBenny Halevy len = be32_to_cpup(p); 45391da177e4SLinus Torvalds if (len >= rcvbuf->page_len || len <= 0) { 4540fe82a183SChuck Lever dprintk("nfs: server returned giant symlink!\n"); 45411da177e4SLinus Torvalds return -ENAMETOOLONG; 45421da177e4SLinus Torvalds } 45431da177e4SLinus Torvalds hdrlen = (char *) xdr->p - (char *) iov->iov_base; 45441da177e4SLinus Torvalds recvd = req->rq_rcv_buf.len - hdrlen; 45451da177e4SLinus Torvalds if (recvd < len) { 4546fe82a183SChuck Lever dprintk("NFS: server cheating in readlink reply: " 45471da177e4SLinus Torvalds "count %u > recvd %u\n", len, recvd); 45481da177e4SLinus Torvalds return -EIO; 45491da177e4SLinus Torvalds } 45501da177e4SLinus Torvalds xdr_read_pages(xdr, len); 45511da177e4SLinus Torvalds /* 45521da177e4SLinus Torvalds * The XDR encode routine has set things up so that 45531da177e4SLinus Torvalds * the link text will be copied directly into the 45541da177e4SLinus Torvalds * buffer. We just have to do overflow-checking, 45551da177e4SLinus Torvalds * and and null-terminate the text (the VFS expects 45561da177e4SLinus Torvalds * null-termination). 45571da177e4SLinus Torvalds */ 4558b4687da7SChuck Lever xdr_terminate_string(rcvbuf, len); 45591da177e4SLinus Torvalds return 0; 4560c0eae66eSBenny Halevy out_overflow: 4561c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4562c0eae66eSBenny Halevy return -EIO; 45631da177e4SLinus Torvalds } 45641da177e4SLinus Torvalds 45651da177e4SLinus Torvalds static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) 45661da177e4SLinus Torvalds { 45671da177e4SLinus Torvalds int status; 45681da177e4SLinus Torvalds 45691da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_REMOVE); 45701da177e4SLinus Torvalds if (status) 45711da177e4SLinus Torvalds goto out; 45721da177e4SLinus Torvalds status = decode_change_info(xdr, cinfo); 45731da177e4SLinus Torvalds out: 45741da177e4SLinus Torvalds return status; 45751da177e4SLinus Torvalds } 45761da177e4SLinus Torvalds 45771da177e4SLinus Torvalds static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo, 45781da177e4SLinus Torvalds struct nfs4_change_info *new_cinfo) 45791da177e4SLinus Torvalds { 45801da177e4SLinus Torvalds int status; 45811da177e4SLinus Torvalds 45821da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_RENAME); 45831da177e4SLinus Torvalds if (status) 45841da177e4SLinus Torvalds goto out; 45851da177e4SLinus Torvalds if ((status = decode_change_info(xdr, old_cinfo))) 45861da177e4SLinus Torvalds goto out; 45871da177e4SLinus Torvalds status = decode_change_info(xdr, new_cinfo); 45881da177e4SLinus Torvalds out: 45891da177e4SLinus Torvalds return status; 45901da177e4SLinus Torvalds } 45911da177e4SLinus Torvalds 45921da177e4SLinus Torvalds static int decode_renew(struct xdr_stream *xdr) 45931da177e4SLinus Torvalds { 45941da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_RENEW); 45951da177e4SLinus Torvalds } 45961da177e4SLinus Torvalds 459756ae19f3STrond Myklebust static int 459856ae19f3STrond Myklebust decode_restorefh(struct xdr_stream *xdr) 459956ae19f3STrond Myklebust { 460056ae19f3STrond Myklebust return decode_op_hdr(xdr, OP_RESTOREFH); 460156ae19f3STrond Myklebust } 460256ae19f3STrond Myklebust 4603029d105eSJ. Bruce Fields static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, 4604029d105eSJ. Bruce Fields size_t *acl_len) 4605029d105eSJ. Bruce Fields { 46068687b63aSAl Viro __be32 *savep; 4607029d105eSJ. Bruce Fields uint32_t attrlen, 4608029d105eSJ. Bruce Fields bitmap[2] = {0}; 4609029d105eSJ. Bruce Fields struct kvec *iov = req->rq_rcv_buf.head; 4610029d105eSJ. Bruce Fields int status; 4611029d105eSJ. Bruce Fields 4612029d105eSJ. Bruce Fields *acl_len = 0; 4613029d105eSJ. Bruce Fields if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 4614029d105eSJ. Bruce Fields goto out; 4615029d105eSJ. Bruce Fields if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 4616029d105eSJ. Bruce Fields goto out; 4617029d105eSJ. Bruce Fields if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) 4618029d105eSJ. Bruce Fields goto out; 4619029d105eSJ. Bruce Fields 4620029d105eSJ. Bruce Fields if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) 4621029d105eSJ. Bruce Fields return -EIO; 4622029d105eSJ. Bruce Fields if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { 4623bcecff77SChuck Lever size_t hdrlen; 4624bcecff77SChuck Lever u32 recvd; 4625029d105eSJ. Bruce Fields 4626029d105eSJ. Bruce Fields /* We ignore &savep and don't do consistency checks on 4627029d105eSJ. Bruce Fields * the attr length. Let userspace figure it out.... */ 4628029d105eSJ. Bruce Fields hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; 4629029d105eSJ. Bruce Fields recvd = req->rq_rcv_buf.len - hdrlen; 4630029d105eSJ. Bruce Fields if (attrlen > recvd) { 4631fe82a183SChuck Lever dprintk("NFS: server cheating in getattr" 4632029d105eSJ. Bruce Fields " acl reply: attrlen %u > recvd %u\n", 4633029d105eSJ. Bruce Fields attrlen, recvd); 4634029d105eSJ. Bruce Fields return -EINVAL; 4635029d105eSJ. Bruce Fields } 4636029d105eSJ. Bruce Fields xdr_read_pages(xdr, attrlen); 4637029d105eSJ. Bruce Fields *acl_len = attrlen; 46388c233cf9SJ. Bruce Fields } else 46398c233cf9SJ. Bruce Fields status = -EOPNOTSUPP; 4640029d105eSJ. Bruce Fields 4641029d105eSJ. Bruce Fields out: 4642029d105eSJ. Bruce Fields return status; 4643029d105eSJ. Bruce Fields } 4644029d105eSJ. Bruce Fields 46451da177e4SLinus Torvalds static int 46461da177e4SLinus Torvalds decode_savefh(struct xdr_stream *xdr) 46471da177e4SLinus Torvalds { 46481da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_SAVEFH); 46491da177e4SLinus Torvalds } 46501da177e4SLinus Torvalds 46519e9ecc03SBenny Halevy static int decode_setattr(struct xdr_stream *xdr) 46521da177e4SLinus Torvalds { 46538687b63aSAl Viro __be32 *p; 46541da177e4SLinus Torvalds uint32_t bmlen; 46551da177e4SLinus Torvalds int status; 46561da177e4SLinus Torvalds 46571da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_SETATTR); 46581da177e4SLinus Torvalds if (status) 46591da177e4SLinus Torvalds return status; 4660c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4661c0eae66eSBenny Halevy if (unlikely(!p)) 4662c0eae66eSBenny Halevy goto out_overflow; 4663cccddf4fSBenny Halevy bmlen = be32_to_cpup(p); 4664c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, bmlen << 2); 4665c0eae66eSBenny Halevy if (likely(p)) 46661da177e4SLinus Torvalds return 0; 4667c0eae66eSBenny Halevy out_overflow: 4668c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4669c0eae66eSBenny Halevy return -EIO; 46701da177e4SLinus Torvalds } 46711da177e4SLinus Torvalds 4672bb8b27e5STrond Myklebust static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res) 46731da177e4SLinus Torvalds { 46748687b63aSAl Viro __be32 *p; 46751da177e4SLinus Torvalds uint32_t opnum; 46761da177e4SLinus Torvalds int32_t nfserr; 46771da177e4SLinus Torvalds 4678c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4679c0eae66eSBenny Halevy if (unlikely(!p)) 4680c0eae66eSBenny Halevy goto out_overflow; 46816f723f77SBenny Halevy opnum = be32_to_cpup(p++); 46821da177e4SLinus Torvalds if (opnum != OP_SETCLIENTID) { 4683fe82a183SChuck Lever dprintk("nfs: decode_setclientid: Server returned operation" 46841da177e4SLinus Torvalds " %d\n", opnum); 46851da177e4SLinus Torvalds return -EIO; 46861da177e4SLinus Torvalds } 4687cccddf4fSBenny Halevy nfserr = be32_to_cpup(p); 46881da177e4SLinus Torvalds if (nfserr == NFS_OK) { 4689c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE); 4690c0eae66eSBenny Halevy if (unlikely(!p)) 4691c0eae66eSBenny Halevy goto out_overflow; 4692bb8b27e5STrond Myklebust p = xdr_decode_hyper(p, &res->clientid); 4693bb8b27e5STrond Myklebust memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE); 46941da177e4SLinus Torvalds } else if (nfserr == NFSERR_CLID_INUSE) { 46951da177e4SLinus Torvalds uint32_t len; 46961da177e4SLinus Torvalds 46971da177e4SLinus Torvalds /* skip netid string */ 4698c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4699c0eae66eSBenny Halevy if (unlikely(!p)) 4700c0eae66eSBenny Halevy goto out_overflow; 4701cccddf4fSBenny Halevy len = be32_to_cpup(p); 4702c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 4703c0eae66eSBenny Halevy if (unlikely(!p)) 4704c0eae66eSBenny Halevy goto out_overflow; 47051da177e4SLinus Torvalds 47061da177e4SLinus Torvalds /* skip uaddr string */ 4707c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); 4708c0eae66eSBenny Halevy if (unlikely(!p)) 4709c0eae66eSBenny Halevy goto out_overflow; 4710cccddf4fSBenny Halevy len = be32_to_cpup(p); 4711c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, len); 4712c0eae66eSBenny Halevy if (unlikely(!p)) 4713c0eae66eSBenny Halevy goto out_overflow; 47141da177e4SLinus Torvalds return -NFSERR_CLID_INUSE; 47151da177e4SLinus Torvalds } else 4716856dff3dSBenny Halevy return nfs4_stat_to_errno(nfserr); 47171da177e4SLinus Torvalds 47181da177e4SLinus Torvalds return 0; 4719c0eae66eSBenny Halevy out_overflow: 4720c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4721c0eae66eSBenny Halevy return -EIO; 47221da177e4SLinus Torvalds } 47231da177e4SLinus Torvalds 47241da177e4SLinus Torvalds static int decode_setclientid_confirm(struct xdr_stream *xdr) 47251da177e4SLinus Torvalds { 47261da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM); 47271da177e4SLinus Torvalds } 47281da177e4SLinus Torvalds 47291da177e4SLinus Torvalds static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res) 47301da177e4SLinus Torvalds { 47318687b63aSAl Viro __be32 *p; 47321da177e4SLinus Torvalds int status; 47331da177e4SLinus Torvalds 47341da177e4SLinus Torvalds status = decode_op_hdr(xdr, OP_WRITE); 47351da177e4SLinus Torvalds if (status) 47361da177e4SLinus Torvalds return status; 47371da177e4SLinus Torvalds 4738c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 16); 4739c0eae66eSBenny Halevy if (unlikely(!p)) 4740c0eae66eSBenny Halevy goto out_overflow; 47416f723f77SBenny Halevy res->count = be32_to_cpup(p++); 47426f723f77SBenny Halevy res->verf->committed = be32_to_cpup(p++); 474399398d06SBenny Halevy memcpy(res->verf->verifier, p, 8); 47441da177e4SLinus Torvalds return 0; 4745c0eae66eSBenny Halevy out_overflow: 4746c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4747c0eae66eSBenny Halevy return -EIO; 47481da177e4SLinus Torvalds } 47491da177e4SLinus Torvalds 47501da177e4SLinus Torvalds static int decode_delegreturn(struct xdr_stream *xdr) 47511da177e4SLinus Torvalds { 47521da177e4SLinus Torvalds return decode_op_hdr(xdr, OP_DELEGRETURN); 47531da177e4SLinus Torvalds } 47541da177e4SLinus Torvalds 475599fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 475699fe60d0SBenny Halevy static int decode_exchange_id(struct xdr_stream *xdr, 475799fe60d0SBenny Halevy struct nfs41_exchange_id_res *res) 475899fe60d0SBenny Halevy { 475999fe60d0SBenny Halevy __be32 *p; 476099fe60d0SBenny Halevy uint32_t dummy; 47612460ba57SBenny Halevy char *dummy_str; 476299fe60d0SBenny Halevy int status; 476399fe60d0SBenny Halevy struct nfs_client *clp = res->client; 476499fe60d0SBenny Halevy 476599fe60d0SBenny Halevy status = decode_op_hdr(xdr, OP_EXCHANGE_ID); 476699fe60d0SBenny Halevy if (status) 476799fe60d0SBenny Halevy return status; 476899fe60d0SBenny Halevy 4769c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4770c0eae66eSBenny Halevy if (unlikely(!p)) 4771c0eae66eSBenny Halevy goto out_overflow; 4772114f64b5SAndy Adamson xdr_decode_hyper(p, &clp->cl_clientid); 4773c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 12); 4774c0eae66eSBenny Halevy if (unlikely(!p)) 4775c0eae66eSBenny Halevy goto out_overflow; 47766f723f77SBenny Halevy clp->cl_seqid = be32_to_cpup(p++); 47776f723f77SBenny Halevy clp->cl_exchange_flags = be32_to_cpup(p++); 477899fe60d0SBenny Halevy 477999fe60d0SBenny Halevy /* We ask for SP4_NONE */ 4780cccddf4fSBenny Halevy dummy = be32_to_cpup(p); 478199fe60d0SBenny Halevy if (dummy != SP4_NONE) 478299fe60d0SBenny Halevy return -EIO; 478399fe60d0SBenny Halevy 478499fe60d0SBenny Halevy /* Throw away minor_id */ 4785c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4786c0eae66eSBenny Halevy if (unlikely(!p)) 4787c0eae66eSBenny Halevy goto out_overflow; 478899fe60d0SBenny Halevy 478999fe60d0SBenny Halevy /* Throw away Major id */ 47902460ba57SBenny Halevy status = decode_opaque_inline(xdr, &dummy, &dummy_str); 47912460ba57SBenny Halevy if (unlikely(status)) 47922460ba57SBenny Halevy return status; 479399fe60d0SBenny Halevy 479499fe60d0SBenny Halevy /* Throw away server_scope */ 47952460ba57SBenny Halevy status = decode_opaque_inline(xdr, &dummy, &dummy_str); 47962460ba57SBenny Halevy if (unlikely(status)) 47972460ba57SBenny Halevy return status; 479899fe60d0SBenny Halevy 479999fe60d0SBenny Halevy /* Throw away Implementation id array */ 48002460ba57SBenny Halevy status = decode_opaque_inline(xdr, &dummy, &dummy_str); 48012460ba57SBenny Halevy if (unlikely(status)) 48022460ba57SBenny Halevy return status; 480399fe60d0SBenny Halevy 480499fe60d0SBenny Halevy return 0; 4805c0eae66eSBenny Halevy out_overflow: 4806c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4807c0eae66eSBenny Halevy return -EIO; 480899fe60d0SBenny Halevy } 4809fc931582SAndy Adamson 4810fc931582SAndy Adamson static int decode_chan_attrs(struct xdr_stream *xdr, 4811fc931582SAndy Adamson struct nfs4_channel_attrs *attrs) 4812fc931582SAndy Adamson { 4813fc931582SAndy Adamson __be32 *p; 4814fc931582SAndy Adamson u32 nr_attrs; 4815fc931582SAndy Adamson 4816c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 28); 4817c0eae66eSBenny Halevy if (unlikely(!p)) 4818c0eae66eSBenny Halevy goto out_overflow; 48196f723f77SBenny Halevy attrs->headerpadsz = be32_to_cpup(p++); 48206f723f77SBenny Halevy attrs->max_rqst_sz = be32_to_cpup(p++); 48216f723f77SBenny Halevy attrs->max_resp_sz = be32_to_cpup(p++); 48226f723f77SBenny Halevy attrs->max_resp_sz_cached = be32_to_cpup(p++); 48236f723f77SBenny Halevy attrs->max_ops = be32_to_cpup(p++); 48246f723f77SBenny Halevy attrs->max_reqs = be32_to_cpup(p++); 4825cccddf4fSBenny Halevy nr_attrs = be32_to_cpup(p); 4826fc931582SAndy Adamson if (unlikely(nr_attrs > 1)) { 4827fc931582SAndy Adamson printk(KERN_WARNING "%s: Invalid rdma channel attrs count %u\n", 4828fc931582SAndy Adamson __func__, nr_attrs); 4829fc931582SAndy Adamson return -EINVAL; 4830fc931582SAndy Adamson } 4831c0eae66eSBenny Halevy if (nr_attrs == 1) { 4832c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */ 4833c0eae66eSBenny Halevy if (unlikely(!p)) 4834c0eae66eSBenny Halevy goto out_overflow; 4835c0eae66eSBenny Halevy } 4836fc931582SAndy Adamson return 0; 4837c0eae66eSBenny Halevy out_overflow: 4838c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4839c0eae66eSBenny Halevy return -EIO; 4840fc931582SAndy Adamson } 4841fc931582SAndy Adamson 4842e78291e4SBenny Halevy static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid) 4843e78291e4SBenny Halevy { 4844e78291e4SBenny Halevy return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN); 4845fc931582SAndy Adamson } 4846fc931582SAndy Adamson 4847fc931582SAndy Adamson static int decode_create_session(struct xdr_stream *xdr, 4848fc931582SAndy Adamson struct nfs41_create_session_res *res) 4849fc931582SAndy Adamson { 4850fc931582SAndy Adamson __be32 *p; 4851fc931582SAndy Adamson int status; 4852fc931582SAndy Adamson struct nfs_client *clp = res->client; 4853fc931582SAndy Adamson struct nfs4_session *session = clp->cl_session; 4854fc931582SAndy Adamson 4855fc931582SAndy Adamson status = decode_op_hdr(xdr, OP_CREATE_SESSION); 4856e78291e4SBenny Halevy if (!status) 4857e78291e4SBenny Halevy status = decode_sessionid(xdr, &session->sess_id); 4858e78291e4SBenny Halevy if (unlikely(status)) 4859fc931582SAndy Adamson return status; 4860fc931582SAndy Adamson 4861fc931582SAndy Adamson /* seqid, flags */ 4862c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 8); 4863c0eae66eSBenny Halevy if (unlikely(!p)) 4864c0eae66eSBenny Halevy goto out_overflow; 48656f723f77SBenny Halevy clp->cl_seqid = be32_to_cpup(p++); 4866cccddf4fSBenny Halevy session->flags = be32_to_cpup(p); 4867fc931582SAndy Adamson 4868fc931582SAndy Adamson /* Channel attributes */ 4869fc931582SAndy Adamson status = decode_chan_attrs(xdr, &session->fc_attrs); 4870fc931582SAndy Adamson if (!status) 4871fc931582SAndy Adamson status = decode_chan_attrs(xdr, &session->bc_attrs); 4872fc931582SAndy Adamson return status; 4873c0eae66eSBenny Halevy out_overflow: 4874c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4875c0eae66eSBenny Halevy return -EIO; 4876fc931582SAndy Adamson } 48770f3e66c6SAndy Adamson 48780f3e66c6SAndy Adamson static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) 48790f3e66c6SAndy Adamson { 48800f3e66c6SAndy Adamson return decode_op_hdr(xdr, OP_DESTROY_SESSION); 48810f3e66c6SAndy Adamson } 488218019753SRicardo Labiaga 488318019753SRicardo Labiaga static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) 488418019753SRicardo Labiaga { 488518019753SRicardo Labiaga return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); 488618019753SRicardo Labiaga } 488799fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 488899fe60d0SBenny Halevy 48899b7b9fccSAndy Adamson static int decode_sequence(struct xdr_stream *xdr, 48909b7b9fccSAndy Adamson struct nfs4_sequence_res *res, 48919b7b9fccSAndy Adamson struct rpc_rqst *rqstp) 48929b7b9fccSAndy Adamson { 48939b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1) 4894fc01cea9SAndy Adamson struct nfs4_sessionid id; 4895fc01cea9SAndy Adamson u32 dummy; 4896fc01cea9SAndy Adamson int status; 4897fc01cea9SAndy Adamson __be32 *p; 4898fc01cea9SAndy Adamson 48999b7b9fccSAndy Adamson if (!res->sr_session) 49009b7b9fccSAndy Adamson return 0; 49019b7b9fccSAndy Adamson 4902fc01cea9SAndy Adamson status = decode_op_hdr(xdr, OP_SEQUENCE); 4903e78291e4SBenny Halevy if (!status) 4904e78291e4SBenny Halevy status = decode_sessionid(xdr, &id); 4905e78291e4SBenny Halevy if (unlikely(status)) 4906fc01cea9SAndy Adamson goto out_err; 49079b7b9fccSAndy Adamson 4908fc01cea9SAndy Adamson /* 4909fc01cea9SAndy Adamson * If the server returns different values for sessionID, slotID or 4910fc01cea9SAndy Adamson * sequence number, the server is looney tunes. 4911fc01cea9SAndy Adamson */ 4912fdcb4577STrond Myklebust status = -EREMOTEIO; 4913fc01cea9SAndy Adamson 4914fc01cea9SAndy Adamson if (memcmp(id.data, res->sr_session->sess_id.data, 4915fc01cea9SAndy Adamson NFS4_MAX_SESSIONID_LEN)) { 4916fc01cea9SAndy Adamson dprintk("%s Invalid session id\n", __func__); 4917fc01cea9SAndy Adamson goto out_err; 4918fc01cea9SAndy Adamson } 4919e78291e4SBenny Halevy 4920c0eae66eSBenny Halevy p = xdr_inline_decode(xdr, 20); 4921c0eae66eSBenny Halevy if (unlikely(!p)) 4922c0eae66eSBenny Halevy goto out_overflow; 4923e78291e4SBenny Halevy 4924fc01cea9SAndy Adamson /* seqid */ 49256f723f77SBenny Halevy dummy = be32_to_cpup(p++); 4926dfb4f309SBenny Halevy if (dummy != res->sr_slot->seq_nr) { 4927fc01cea9SAndy Adamson dprintk("%s Invalid sequence number\n", __func__); 4928fc01cea9SAndy Adamson goto out_err; 4929fc01cea9SAndy Adamson } 4930fc01cea9SAndy Adamson /* slot id */ 49316f723f77SBenny Halevy dummy = be32_to_cpup(p++); 4932dfb4f309SBenny Halevy if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) { 4933fc01cea9SAndy Adamson dprintk("%s Invalid slot id\n", __func__); 4934fc01cea9SAndy Adamson goto out_err; 4935fc01cea9SAndy Adamson } 4936fc01cea9SAndy Adamson /* highest slot id - currently not processed */ 49376f723f77SBenny Halevy dummy = be32_to_cpup(p++); 4938fc01cea9SAndy Adamson /* target highest slot id - currently not processed */ 49396f723f77SBenny Halevy dummy = be32_to_cpup(p++); 49400629e370SAlexandros Batsakis /* result flags */ 49410629e370SAlexandros Batsakis res->sr_status_flags = be32_to_cpup(p); 4942fc01cea9SAndy Adamson status = 0; 4943fc01cea9SAndy Adamson out_err: 4944fc01cea9SAndy Adamson res->sr_status = status; 4945fc01cea9SAndy Adamson return status; 4946c0eae66eSBenny Halevy out_overflow: 4947c0eae66eSBenny Halevy print_overflow_msg(__func__, xdr); 4948c0eae66eSBenny Halevy status = -EIO; 4949c0eae66eSBenny Halevy goto out_err; 4950fc01cea9SAndy Adamson #else /* CONFIG_NFS_V4_1 */ 49519b7b9fccSAndy Adamson return 0; 4952fc01cea9SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 49539b7b9fccSAndy Adamson } 49549b7b9fccSAndy Adamson 4955b1f69b75SAndy Adamson #if defined(CONFIG_NFS_V4_1) 4956b1f69b75SAndy Adamson 4957b1f69b75SAndy Adamson static int decode_getdeviceinfo(struct xdr_stream *xdr, 4958b1f69b75SAndy Adamson struct pnfs_device *pdev) 4959b1f69b75SAndy Adamson { 4960b1f69b75SAndy Adamson __be32 *p; 4961b1f69b75SAndy Adamson uint32_t len, type; 4962b1f69b75SAndy Adamson int status; 4963b1f69b75SAndy Adamson 4964b1f69b75SAndy Adamson status = decode_op_hdr(xdr, OP_GETDEVICEINFO); 4965b1f69b75SAndy Adamson if (status) { 4966b1f69b75SAndy Adamson if (status == -ETOOSMALL) { 4967b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4); 4968b1f69b75SAndy Adamson if (unlikely(!p)) 4969b1f69b75SAndy Adamson goto out_overflow; 4970b1f69b75SAndy Adamson pdev->mincount = be32_to_cpup(p); 4971b1f69b75SAndy Adamson dprintk("%s: Min count too small. mincnt = %u\n", 4972b1f69b75SAndy Adamson __func__, pdev->mincount); 4973b1f69b75SAndy Adamson } 4974b1f69b75SAndy Adamson return status; 4975b1f69b75SAndy Adamson } 4976b1f69b75SAndy Adamson 4977b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 8); 4978b1f69b75SAndy Adamson if (unlikely(!p)) 4979b1f69b75SAndy Adamson goto out_overflow; 4980b1f69b75SAndy Adamson type = be32_to_cpup(p++); 4981b1f69b75SAndy Adamson if (type != pdev->layout_type) { 4982b1f69b75SAndy Adamson dprintk("%s: layout mismatch req: %u pdev: %u\n", 4983b1f69b75SAndy Adamson __func__, pdev->layout_type, type); 4984b1f69b75SAndy Adamson return -EINVAL; 4985b1f69b75SAndy Adamson } 4986b1f69b75SAndy Adamson /* 4987b1f69b75SAndy Adamson * Get the length of the opaque device_addr4. xdr_read_pages places 4988b1f69b75SAndy Adamson * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages) 4989b1f69b75SAndy Adamson * and places the remaining xdr data in xdr_buf->tail 4990b1f69b75SAndy Adamson */ 4991b1f69b75SAndy Adamson pdev->mincount = be32_to_cpup(p); 4992b1f69b75SAndy Adamson xdr_read_pages(xdr, pdev->mincount); /* include space for the length */ 4993b1f69b75SAndy Adamson 4994b1f69b75SAndy Adamson /* Parse notification bitmap, verifying that it is zero. */ 4995b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4); 4996b1f69b75SAndy Adamson if (unlikely(!p)) 4997b1f69b75SAndy Adamson goto out_overflow; 4998b1f69b75SAndy Adamson len = be32_to_cpup(p); 4999b1f69b75SAndy Adamson if (len) { 5000ead00597SChuck Lever uint32_t i; 5001b1f69b75SAndy Adamson 5002b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 4 * len); 5003b1f69b75SAndy Adamson if (unlikely(!p)) 5004b1f69b75SAndy Adamson goto out_overflow; 5005b1f69b75SAndy Adamson for (i = 0; i < len; i++, p++) { 5006b1f69b75SAndy Adamson if (be32_to_cpup(p)) { 5007b1f69b75SAndy Adamson dprintk("%s: notifications not supported\n", 5008b1f69b75SAndy Adamson __func__); 5009b1f69b75SAndy Adamson return -EIO; 5010b1f69b75SAndy Adamson } 5011b1f69b75SAndy Adamson } 5012b1f69b75SAndy Adamson } 5013b1f69b75SAndy Adamson return 0; 5014b1f69b75SAndy Adamson out_overflow: 5015b1f69b75SAndy Adamson print_overflow_msg(__func__, xdr); 5016b1f69b75SAndy Adamson return -EIO; 5017b1f69b75SAndy Adamson } 5018b1f69b75SAndy Adamson 5019b1f69b75SAndy Adamson static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, 5020b1f69b75SAndy Adamson struct nfs4_layoutget_res *res) 5021b1f69b75SAndy Adamson { 5022b1f69b75SAndy Adamson __be32 *p; 5023b1f69b75SAndy Adamson int status; 5024b1f69b75SAndy Adamson u32 layout_count; 5025b1f69b75SAndy Adamson 5026b1f69b75SAndy Adamson status = decode_op_hdr(xdr, OP_LAYOUTGET); 5027b1f69b75SAndy Adamson if (status) 5028b1f69b75SAndy Adamson return status; 5029b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 8 + NFS4_STATEID_SIZE); 5030b1f69b75SAndy Adamson if (unlikely(!p)) 5031b1f69b75SAndy Adamson goto out_overflow; 5032b1f69b75SAndy Adamson res->return_on_close = be32_to_cpup(p++); 5033b1f69b75SAndy Adamson p = xdr_decode_opaque_fixed(p, res->stateid.data, NFS4_STATEID_SIZE); 5034b1f69b75SAndy Adamson layout_count = be32_to_cpup(p); 5035b1f69b75SAndy Adamson if (!layout_count) { 5036b1f69b75SAndy Adamson dprintk("%s: server responded with empty layout array\n", 5037b1f69b75SAndy Adamson __func__); 5038b1f69b75SAndy Adamson return -EINVAL; 5039b1f69b75SAndy Adamson } 5040b1f69b75SAndy Adamson 5041b1f69b75SAndy Adamson p = xdr_inline_decode(xdr, 24); 5042b1f69b75SAndy Adamson if (unlikely(!p)) 5043b1f69b75SAndy Adamson goto out_overflow; 5044b1f69b75SAndy Adamson p = xdr_decode_hyper(p, &res->range.offset); 5045b1f69b75SAndy Adamson p = xdr_decode_hyper(p, &res->range.length); 5046b1f69b75SAndy Adamson res->range.iomode = be32_to_cpup(p++); 5047b1f69b75SAndy Adamson res->type = be32_to_cpup(p++); 5048b1f69b75SAndy Adamson 5049b1f69b75SAndy Adamson status = decode_opaque_inline(xdr, &res->layout.len, (char **)&p); 5050b1f69b75SAndy Adamson if (unlikely(status)) 5051b1f69b75SAndy Adamson return status; 5052b1f69b75SAndy Adamson 5053b1f69b75SAndy Adamson dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", 5054b1f69b75SAndy Adamson __func__, 5055b1f69b75SAndy Adamson (unsigned long)res->range.offset, 5056b1f69b75SAndy Adamson (unsigned long)res->range.length, 5057b1f69b75SAndy Adamson res->range.iomode, 5058b1f69b75SAndy Adamson res->type, 5059b1f69b75SAndy Adamson res->layout.len); 5060b1f69b75SAndy Adamson 5061b1f69b75SAndy Adamson /* nfs4_proc_layoutget allocated a single page */ 5062b1f69b75SAndy Adamson if (res->layout.len > PAGE_SIZE) 5063b1f69b75SAndy Adamson return -ENOMEM; 5064b1f69b75SAndy Adamson memcpy(res->layout.buf, p, res->layout.len); 5065b1f69b75SAndy Adamson 5066b1f69b75SAndy Adamson if (layout_count > 1) { 5067b1f69b75SAndy Adamson /* We only handle a length one array at the moment. Any 5068b1f69b75SAndy Adamson * further entries are just ignored. Note that this means 5069b1f69b75SAndy Adamson * the client may see a response that is less than the 5070b1f69b75SAndy Adamson * minimum it requested. 5071b1f69b75SAndy Adamson */ 5072b1f69b75SAndy Adamson dprintk("%s: server responded with %d layouts, dropping tail\n", 5073b1f69b75SAndy Adamson __func__, layout_count); 5074b1f69b75SAndy Adamson } 5075b1f69b75SAndy Adamson 5076b1f69b75SAndy Adamson return 0; 5077b1f69b75SAndy Adamson out_overflow: 5078b1f69b75SAndy Adamson print_overflow_msg(__func__, xdr); 5079b1f69b75SAndy Adamson return -EIO; 5080b1f69b75SAndy Adamson } 5081863a3c6cSAndy Adamson 5082863a3c6cSAndy Adamson static int decode_layoutcommit(struct xdr_stream *xdr, 5083863a3c6cSAndy Adamson struct rpc_rqst *req, 5084863a3c6cSAndy Adamson struct nfs4_layoutcommit_res *res) 5085863a3c6cSAndy Adamson { 5086863a3c6cSAndy Adamson __be32 *p; 5087863a3c6cSAndy Adamson __u32 sizechanged; 5088863a3c6cSAndy Adamson int status; 5089863a3c6cSAndy Adamson 5090863a3c6cSAndy Adamson status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); 5091863a3c6cSAndy Adamson if (status) 5092863a3c6cSAndy Adamson return status; 5093863a3c6cSAndy Adamson 5094863a3c6cSAndy Adamson p = xdr_inline_decode(xdr, 4); 5095863a3c6cSAndy Adamson if (unlikely(!p)) 5096863a3c6cSAndy Adamson goto out_overflow; 5097863a3c6cSAndy Adamson sizechanged = be32_to_cpup(p); 5098863a3c6cSAndy Adamson 5099863a3c6cSAndy Adamson if (sizechanged) { 5100863a3c6cSAndy Adamson /* throw away new size */ 5101863a3c6cSAndy Adamson p = xdr_inline_decode(xdr, 8); 5102863a3c6cSAndy Adamson if (unlikely(!p)) 5103863a3c6cSAndy Adamson goto out_overflow; 5104863a3c6cSAndy Adamson } 5105863a3c6cSAndy Adamson return 0; 5106863a3c6cSAndy Adamson out_overflow: 5107863a3c6cSAndy Adamson print_overflow_msg(__func__, xdr); 5108863a3c6cSAndy Adamson return -EIO; 5109863a3c6cSAndy Adamson } 5110b1f69b75SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 5111b1f69b75SAndy Adamson 51121da177e4SLinus Torvalds /* 511349c2559eSBenny Halevy * END OF "GENERIC" DECODE ROUTINES. 511449c2559eSBenny Halevy */ 511549c2559eSBenny Halevy 511649c2559eSBenny Halevy /* 51171da177e4SLinus Torvalds * Decode OPEN_DOWNGRADE response 51181da177e4SLinus Torvalds */ 5119bf269551SChuck Lever static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, 5120bf269551SChuck Lever struct xdr_stream *xdr, 5121bf269551SChuck Lever struct nfs_closeres *res) 51221da177e4SLinus Torvalds { 51231da177e4SLinus Torvalds struct compound_hdr hdr; 51241da177e4SLinus Torvalds int status; 51251da177e4SLinus Torvalds 5126bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 51271da177e4SLinus Torvalds if (status) 51281da177e4SLinus Torvalds goto out; 5129bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 51309b7b9fccSAndy Adamson if (status) 51319b7b9fccSAndy Adamson goto out; 5132bf269551SChuck Lever status = decode_putfh(xdr); 51331da177e4SLinus Torvalds if (status) 51341da177e4SLinus Torvalds goto out; 5135bf269551SChuck Lever status = decode_open_downgrade(xdr, res); 5136516a6af6STrond Myklebust if (status != 0) 5137516a6af6STrond Myklebust goto out; 5138bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 513980e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 51401da177e4SLinus Torvalds out: 51411da177e4SLinus Torvalds return status; 51421da177e4SLinus Torvalds } 51431da177e4SLinus Torvalds 51441da177e4SLinus Torvalds /* 51451da177e4SLinus Torvalds * Decode ACCESS response 51461da177e4SLinus Torvalds */ 5147bf269551SChuck Lever static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5148bf269551SChuck Lever struct nfs4_accessres *res) 51491da177e4SLinus Torvalds { 51501da177e4SLinus Torvalds struct compound_hdr hdr; 51511da177e4SLinus Torvalds int status; 51521da177e4SLinus Torvalds 5153bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 51549b7b9fccSAndy Adamson if (status) 51559b7b9fccSAndy Adamson goto out; 5156bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 51579b7b9fccSAndy Adamson if (status) 51581da177e4SLinus Torvalds goto out; 5159bf269551SChuck Lever status = decode_putfh(xdr); 516076b32999STrond Myklebust if (status != 0) 516176b32999STrond Myklebust goto out; 5162bf269551SChuck Lever status = decode_access(xdr, res); 516376b32999STrond Myklebust if (status != 0) 516476b32999STrond Myklebust goto out; 5165bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 516680e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 51671da177e4SLinus Torvalds out: 51681da177e4SLinus Torvalds return status; 51691da177e4SLinus Torvalds } 51701da177e4SLinus Torvalds 51711da177e4SLinus Torvalds /* 51721da177e4SLinus Torvalds * Decode LOOKUP response 51731da177e4SLinus Torvalds */ 5174bf269551SChuck Lever static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5175bf269551SChuck Lever struct nfs4_lookup_res *res) 51761da177e4SLinus Torvalds { 51771da177e4SLinus Torvalds struct compound_hdr hdr; 51781da177e4SLinus Torvalds int status; 51791da177e4SLinus Torvalds 5180bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 51819b7b9fccSAndy Adamson if (status) 51829b7b9fccSAndy Adamson goto out; 5183bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 51849b7b9fccSAndy Adamson if (status) 51851da177e4SLinus Torvalds goto out; 5186bf269551SChuck Lever status = decode_putfh(xdr); 5187bf269551SChuck Lever if (status) 51881da177e4SLinus Torvalds goto out; 5189bf269551SChuck Lever status = decode_lookup(xdr); 5190bf269551SChuck Lever if (status) 51911da177e4SLinus Torvalds goto out; 5192bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 5193bf269551SChuck Lever if (status) 51941da177e4SLinus Torvalds goto out; 5195bf269551SChuck Lever status = decode_getfattr(xdr, res->fattr, res->server 519680e52aceSTrond Myklebust ,!RPC_IS_ASYNC(rqstp->rq_task)); 51971da177e4SLinus Torvalds out: 51981da177e4SLinus Torvalds return status; 51991da177e4SLinus Torvalds } 52001da177e4SLinus Torvalds 52011da177e4SLinus Torvalds /* 52021da177e4SLinus Torvalds * Decode LOOKUP_ROOT response 52031da177e4SLinus Torvalds */ 5204bf269551SChuck Lever static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, 5205bf269551SChuck Lever struct xdr_stream *xdr, 5206bf269551SChuck Lever struct nfs4_lookup_res *res) 52071da177e4SLinus Torvalds { 52081da177e4SLinus Torvalds struct compound_hdr hdr; 52091da177e4SLinus Torvalds int status; 52101da177e4SLinus Torvalds 5211bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 52129b7b9fccSAndy Adamson if (status) 52139b7b9fccSAndy Adamson goto out; 5214bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 52159b7b9fccSAndy Adamson if (status) 52161da177e4SLinus Torvalds goto out; 5217bf269551SChuck Lever status = decode_putrootfh(xdr); 5218bf269551SChuck Lever if (status) 52191da177e4SLinus Torvalds goto out; 5220bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 5221bf269551SChuck Lever if (status == 0) 5222bf269551SChuck Lever status = decode_getfattr(xdr, res->fattr, res->server, 522380e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 52241da177e4SLinus Torvalds out: 52251da177e4SLinus Torvalds return status; 52261da177e4SLinus Torvalds } 52271da177e4SLinus Torvalds 52281da177e4SLinus Torvalds /* 52291da177e4SLinus Torvalds * Decode REMOVE response 52301da177e4SLinus Torvalds */ 5231bf269551SChuck Lever static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5232bf269551SChuck Lever struct nfs_removeres *res) 52331da177e4SLinus Torvalds { 52341da177e4SLinus Torvalds struct compound_hdr hdr; 52351da177e4SLinus Torvalds int status; 52361da177e4SLinus Torvalds 5237bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 52389b7b9fccSAndy Adamson if (status) 52399b7b9fccSAndy Adamson goto out; 5240bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 52419b7b9fccSAndy Adamson if (status) 52421da177e4SLinus Torvalds goto out; 5243bf269551SChuck Lever status = decode_putfh(xdr); 5244bf269551SChuck Lever if (status) 524516e42959STrond Myklebust goto out; 5246bf269551SChuck Lever status = decode_remove(xdr, &res->cinfo); 5247bf269551SChuck Lever if (status) 524816e42959STrond Myklebust goto out; 5249bf269551SChuck Lever decode_getfattr(xdr, res->dir_attr, res->server, 525080e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 52511da177e4SLinus Torvalds out: 52521da177e4SLinus Torvalds return status; 52531da177e4SLinus Torvalds } 52541da177e4SLinus Torvalds 52551da177e4SLinus Torvalds /* 52561da177e4SLinus Torvalds * Decode RENAME response 52571da177e4SLinus Torvalds */ 5258bf269551SChuck Lever static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5259bf269551SChuck Lever struct nfs_renameres *res) 52601da177e4SLinus Torvalds { 52611da177e4SLinus Torvalds struct compound_hdr hdr; 52621da177e4SLinus Torvalds int status; 52631da177e4SLinus Torvalds 5264bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 52659b7b9fccSAndy Adamson if (status) 52669b7b9fccSAndy Adamson goto out; 5267bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 52689b7b9fccSAndy Adamson if (status) 52691da177e4SLinus Torvalds goto out; 5270bf269551SChuck Lever status = decode_putfh(xdr); 5271bf269551SChuck Lever if (status) 52721da177e4SLinus Torvalds goto out; 5273bf269551SChuck Lever status = decode_savefh(xdr); 5274bf269551SChuck Lever if (status) 52751da177e4SLinus Torvalds goto out; 5276bf269551SChuck Lever status = decode_putfh(xdr); 5277bf269551SChuck Lever if (status) 52781da177e4SLinus Torvalds goto out; 5279bf269551SChuck Lever status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo); 5280bf269551SChuck Lever if (status) 52816caf2c82STrond Myklebust goto out; 52826caf2c82STrond Myklebust /* Current FH is target directory */ 5283bf269551SChuck Lever if (decode_getfattr(xdr, res->new_fattr, res->server, 528480e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)) != 0) 52856caf2c82STrond Myklebust goto out; 5286bf269551SChuck Lever status = decode_restorefh(xdr); 5287bf269551SChuck Lever if (status) 52886caf2c82STrond Myklebust goto out; 5289bf269551SChuck Lever decode_getfattr(xdr, res->old_fattr, res->server, 529080e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 52911da177e4SLinus Torvalds out: 52921da177e4SLinus Torvalds return status; 52931da177e4SLinus Torvalds } 52941da177e4SLinus Torvalds 52951da177e4SLinus Torvalds /* 52961da177e4SLinus Torvalds * Decode LINK response 52971da177e4SLinus Torvalds */ 5298bf269551SChuck Lever static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5299bf269551SChuck Lever struct nfs4_link_res *res) 53001da177e4SLinus Torvalds { 53011da177e4SLinus Torvalds struct compound_hdr hdr; 53021da177e4SLinus Torvalds int status; 53031da177e4SLinus Torvalds 5304bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 53059b7b9fccSAndy Adamson if (status) 53069b7b9fccSAndy Adamson goto out; 5307bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 53089b7b9fccSAndy Adamson if (status) 53091da177e4SLinus Torvalds goto out; 5310bf269551SChuck Lever status = decode_putfh(xdr); 5311bf269551SChuck Lever if (status) 53121da177e4SLinus Torvalds goto out; 5313bf269551SChuck Lever status = decode_savefh(xdr); 5314bf269551SChuck Lever if (status) 53151da177e4SLinus Torvalds goto out; 5316bf269551SChuck Lever status = decode_putfh(xdr); 5317bf269551SChuck Lever if (status) 53181da177e4SLinus Torvalds goto out; 5319bf269551SChuck Lever status = decode_link(xdr, &res->cinfo); 5320bf269551SChuck Lever if (status) 532191ba2eeeSTrond Myklebust goto out; 532291ba2eeeSTrond Myklebust /* 532391ba2eeeSTrond Myklebust * Note order: OP_LINK leaves the directory as the current 532491ba2eeeSTrond Myklebust * filehandle. 532591ba2eeeSTrond Myklebust */ 5326bf269551SChuck Lever if (decode_getfattr(xdr, res->dir_attr, res->server, 532780e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)) != 0) 532891ba2eeeSTrond Myklebust goto out; 5329bf269551SChuck Lever status = decode_restorefh(xdr); 5330bf269551SChuck Lever if (status) 533191ba2eeeSTrond Myklebust goto out; 5332bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 533380e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 53341da177e4SLinus Torvalds out: 53351da177e4SLinus Torvalds return status; 53361da177e4SLinus Torvalds } 53371da177e4SLinus Torvalds 53381da177e4SLinus Torvalds /* 53391da177e4SLinus Torvalds * Decode CREATE response 53401da177e4SLinus Torvalds */ 5341bf269551SChuck Lever static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5342bf269551SChuck Lever struct nfs4_create_res *res) 53431da177e4SLinus Torvalds { 53441da177e4SLinus Torvalds struct compound_hdr hdr; 53451da177e4SLinus Torvalds int status; 53461da177e4SLinus Torvalds 5347bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 53489b7b9fccSAndy Adamson if (status) 53499b7b9fccSAndy Adamson goto out; 5350bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 53519b7b9fccSAndy Adamson if (status) 53521da177e4SLinus Torvalds goto out; 5353bf269551SChuck Lever status = decode_putfh(xdr); 5354bf269551SChuck Lever if (status) 53551da177e4SLinus Torvalds goto out; 5356bf269551SChuck Lever status = decode_savefh(xdr); 5357bf269551SChuck Lever if (status) 535856ae19f3STrond Myklebust goto out; 5359bf269551SChuck Lever status = decode_create(xdr, &res->dir_cinfo); 5360bf269551SChuck Lever if (status) 53611da177e4SLinus Torvalds goto out; 5362bf269551SChuck Lever status = decode_getfh(xdr, res->fh); 5363bf269551SChuck Lever if (status) 53641da177e4SLinus Torvalds goto out; 5365bf269551SChuck Lever if (decode_getfattr(xdr, res->fattr, res->server, 536680e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)) != 0) 536756ae19f3STrond Myklebust goto out; 5368bf269551SChuck Lever status = decode_restorefh(xdr); 5369bf269551SChuck Lever if (status) 537056ae19f3STrond Myklebust goto out; 5371bf269551SChuck Lever decode_getfattr(xdr, res->dir_fattr, res->server, 537280e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 53731da177e4SLinus Torvalds out: 53741da177e4SLinus Torvalds return status; 53751da177e4SLinus Torvalds } 53761da177e4SLinus Torvalds 53771da177e4SLinus Torvalds /* 53781da177e4SLinus Torvalds * Decode SYMLINK response 53791da177e4SLinus Torvalds */ 5380bf269551SChuck Lever static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5381bf269551SChuck Lever struct nfs4_create_res *res) 53821da177e4SLinus Torvalds { 5383bf269551SChuck Lever return nfs4_xdr_dec_create(rqstp, xdr, res); 53841da177e4SLinus Torvalds } 53851da177e4SLinus Torvalds 53861da177e4SLinus Torvalds /* 53871da177e4SLinus Torvalds * Decode GETATTR response 53881da177e4SLinus Torvalds */ 5389bf269551SChuck Lever static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5390bf269551SChuck Lever struct nfs4_getattr_res *res) 53911da177e4SLinus Torvalds { 53921da177e4SLinus Torvalds struct compound_hdr hdr; 53931da177e4SLinus Torvalds int status; 53941da177e4SLinus Torvalds 5395bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 53961da177e4SLinus Torvalds if (status) 53971da177e4SLinus Torvalds goto out; 5398bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 53999b7b9fccSAndy Adamson if (status) 54009b7b9fccSAndy Adamson goto out; 5401bf269551SChuck Lever status = decode_putfh(xdr); 54021da177e4SLinus Torvalds if (status) 54031da177e4SLinus Torvalds goto out; 5404bf269551SChuck Lever status = decode_getfattr(xdr, res->fattr, res->server, 540580e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 54061da177e4SLinus Torvalds out: 54071da177e4SLinus Torvalds return status; 54081da177e4SLinus Torvalds } 54091da177e4SLinus Torvalds 541023ec6965SJ. Bruce Fields /* 541123ec6965SJ. Bruce Fields * Encode an SETACL request 541223ec6965SJ. Bruce Fields */ 54139f06c719SChuck Lever static void nfs4_xdr_enc_setacl(struct rpc_rqst *req, struct xdr_stream *xdr, 54149f06c719SChuck Lever struct nfs_setaclargs *args) 541523ec6965SJ. Bruce Fields { 541623ec6965SJ. Bruce Fields struct compound_hdr hdr = { 541766cc0429SBenny Halevy .minorversion = nfs4_xdr_minorversion(&args->seq_args), 541823ec6965SJ. Bruce Fields }; 541923ec6965SJ. Bruce Fields 54209f06c719SChuck Lever encode_compound_hdr(xdr, req, &hdr); 54219f06c719SChuck Lever encode_sequence(xdr, &args->seq_args, &hdr); 54229f06c719SChuck Lever encode_putfh(xdr, args->fh, &hdr); 54239f06c719SChuck Lever encode_setacl(xdr, args, &hdr); 5424d017931cSAndy Adamson encode_nops(&hdr); 542523ec6965SJ. Bruce Fields } 542605d564feSAndy Adamson 542723ec6965SJ. Bruce Fields /* 542823ec6965SJ. Bruce Fields * Decode SETACL response 542923ec6965SJ. Bruce Fields */ 543023ec6965SJ. Bruce Fields static int 5431bf269551SChuck Lever nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 543273c403a9SBenny Halevy struct nfs_setaclres *res) 543323ec6965SJ. Bruce Fields { 543423ec6965SJ. Bruce Fields struct compound_hdr hdr; 543523ec6965SJ. Bruce Fields int status; 543623ec6965SJ. Bruce Fields 5437bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 543823ec6965SJ. Bruce Fields if (status) 543923ec6965SJ. Bruce Fields goto out; 5440bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 54419b7b9fccSAndy Adamson if (status) 54429b7b9fccSAndy Adamson goto out; 5443bf269551SChuck Lever status = decode_putfh(xdr); 544423ec6965SJ. Bruce Fields if (status) 544523ec6965SJ. Bruce Fields goto out; 5446bf269551SChuck Lever status = decode_setattr(xdr); 544723ec6965SJ. Bruce Fields out: 544823ec6965SJ. Bruce Fields return status; 544923ec6965SJ. Bruce Fields } 54501da177e4SLinus Torvalds 54511da177e4SLinus Torvalds /* 5452029d105eSJ. Bruce Fields * Decode GETACL response 5453029d105eSJ. Bruce Fields */ 5454029d105eSJ. Bruce Fields static int 5455bf269551SChuck Lever nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5456663c79b3SBenny Halevy struct nfs_getaclres *res) 5457029d105eSJ. Bruce Fields { 5458029d105eSJ. Bruce Fields struct compound_hdr hdr; 5459029d105eSJ. Bruce Fields int status; 5460029d105eSJ. Bruce Fields 5461bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 5462029d105eSJ. Bruce Fields if (status) 5463029d105eSJ. Bruce Fields goto out; 5464bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 54659b7b9fccSAndy Adamson if (status) 54669b7b9fccSAndy Adamson goto out; 5467bf269551SChuck Lever status = decode_putfh(xdr); 5468029d105eSJ. Bruce Fields if (status) 5469029d105eSJ. Bruce Fields goto out; 5470bf269551SChuck Lever status = decode_getacl(xdr, rqstp, &res->acl_len); 5471029d105eSJ. Bruce Fields 5472029d105eSJ. Bruce Fields out: 5473029d105eSJ. Bruce Fields return status; 5474029d105eSJ. Bruce Fields } 5475029d105eSJ. Bruce Fields 5476029d105eSJ. Bruce Fields /* 54771da177e4SLinus Torvalds * Decode CLOSE response 54781da177e4SLinus Torvalds */ 5479bf269551SChuck Lever static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5480bf269551SChuck Lever struct nfs_closeres *res) 54811da177e4SLinus Torvalds { 54821da177e4SLinus Torvalds struct compound_hdr hdr; 54831da177e4SLinus Torvalds int status; 54841da177e4SLinus Torvalds 5485bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 54861da177e4SLinus Torvalds if (status) 54871da177e4SLinus Torvalds goto out; 5488bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 54899b7b9fccSAndy Adamson if (status) 54909b7b9fccSAndy Adamson goto out; 5491bf269551SChuck Lever status = decode_putfh(xdr); 54921da177e4SLinus Torvalds if (status) 54931da177e4SLinus Torvalds goto out; 5494bf269551SChuck Lever status = decode_close(xdr, res); 5495516a6af6STrond Myklebust if (status != 0) 5496516a6af6STrond Myklebust goto out; 5497516a6af6STrond Myklebust /* 5498516a6af6STrond Myklebust * Note: Server may do delete on close for this file 5499516a6af6STrond Myklebust * in which case the getattr call will fail with 5500516a6af6STrond Myklebust * an ESTALE error. Shouldn't be a problem, 5501516a6af6STrond Myklebust * though, since fattr->valid will remain unset. 5502516a6af6STrond Myklebust */ 5503bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 550480e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 55051da177e4SLinus Torvalds out: 55061da177e4SLinus Torvalds return status; 55071da177e4SLinus Torvalds } 55081da177e4SLinus Torvalds 55091da177e4SLinus Torvalds /* 55101da177e4SLinus Torvalds * Decode OPEN response 55111da177e4SLinus Torvalds */ 5512bf269551SChuck Lever static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5513bf269551SChuck Lever struct nfs_openres *res) 55141da177e4SLinus Torvalds { 55151da177e4SLinus Torvalds struct compound_hdr hdr; 55161da177e4SLinus Torvalds int status; 55171da177e4SLinus Torvalds 5518bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 55191da177e4SLinus Torvalds if (status) 55201da177e4SLinus Torvalds goto out; 5521bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 55229b7b9fccSAndy Adamson if (status) 55239b7b9fccSAndy Adamson goto out; 5524bf269551SChuck Lever status = decode_putfh(xdr); 55251da177e4SLinus Torvalds if (status) 55261da177e4SLinus Torvalds goto out; 5527bf269551SChuck Lever status = decode_savefh(xdr); 552856ae19f3STrond Myklebust if (status) 552956ae19f3STrond Myklebust goto out; 5530bf269551SChuck Lever status = decode_open(xdr, res); 55311da177e4SLinus Torvalds if (status) 55321da177e4SLinus Torvalds goto out; 5533bf269551SChuck Lever if (decode_getfh(xdr, &res->fh) != 0) 55341da177e4SLinus Torvalds goto out; 5535bf269551SChuck Lever if (decode_getfattr(xdr, res->f_attr, res->server, 553680e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)) != 0) 553756ae19f3STrond Myklebust goto out; 5538bf269551SChuck Lever if (decode_restorefh(xdr) != 0) 553956ae19f3STrond Myklebust goto out; 5540bf269551SChuck Lever decode_getfattr(xdr, res->dir_attr, res->server, 554180e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 55421da177e4SLinus Torvalds out: 55431da177e4SLinus Torvalds return status; 55441da177e4SLinus Torvalds } 55451da177e4SLinus Torvalds 55461da177e4SLinus Torvalds /* 55471da177e4SLinus Torvalds * Decode OPEN_CONFIRM response 55481da177e4SLinus Torvalds */ 5549bf269551SChuck Lever static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, 5550bf269551SChuck Lever struct xdr_stream *xdr, 5551bf269551SChuck Lever struct nfs_open_confirmres *res) 55521da177e4SLinus Torvalds { 55531da177e4SLinus Torvalds struct compound_hdr hdr; 55541da177e4SLinus Torvalds int status; 55551da177e4SLinus Torvalds 5556bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 55571da177e4SLinus Torvalds if (status) 55581da177e4SLinus Torvalds goto out; 5559bf269551SChuck Lever status = decode_putfh(xdr); 55601da177e4SLinus Torvalds if (status) 55611da177e4SLinus Torvalds goto out; 5562bf269551SChuck Lever status = decode_open_confirm(xdr, res); 55631da177e4SLinus Torvalds out: 55641da177e4SLinus Torvalds return status; 55651da177e4SLinus Torvalds } 55661da177e4SLinus Torvalds 55671da177e4SLinus Torvalds /* 55681da177e4SLinus Torvalds * Decode OPEN response 55691da177e4SLinus Torvalds */ 5570bf269551SChuck Lever static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, 5571bf269551SChuck Lever struct xdr_stream *xdr, 5572bf269551SChuck Lever struct nfs_openres *res) 55731da177e4SLinus Torvalds { 55741da177e4SLinus Torvalds struct compound_hdr hdr; 55751da177e4SLinus Torvalds int status; 55761da177e4SLinus Torvalds 5577bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 55781da177e4SLinus Torvalds if (status) 55791da177e4SLinus Torvalds goto out; 5580bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 55819b7b9fccSAndy Adamson if (status) 55829b7b9fccSAndy Adamson goto out; 5583bf269551SChuck Lever status = decode_putfh(xdr); 55841da177e4SLinus Torvalds if (status) 55851da177e4SLinus Torvalds goto out; 5586bf269551SChuck Lever status = decode_open(xdr, res); 5587864472e9STrond Myklebust if (status) 5588864472e9STrond Myklebust goto out; 5589bf269551SChuck Lever decode_getfattr(xdr, res->f_attr, res->server, 559080e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 55911da177e4SLinus Torvalds out: 55921da177e4SLinus Torvalds return status; 55931da177e4SLinus Torvalds } 55941da177e4SLinus Torvalds 55951da177e4SLinus Torvalds /* 55961da177e4SLinus Torvalds * Decode SETATTR response 55971da177e4SLinus Torvalds */ 5598bf269551SChuck Lever static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, 5599bf269551SChuck Lever struct xdr_stream *xdr, 5600bf269551SChuck Lever struct nfs_setattrres *res) 56011da177e4SLinus Torvalds { 56021da177e4SLinus Torvalds struct compound_hdr hdr; 56031da177e4SLinus Torvalds int status; 56041da177e4SLinus Torvalds 5605bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 56061da177e4SLinus Torvalds if (status) 56071da177e4SLinus Torvalds goto out; 5608bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 56099b7b9fccSAndy Adamson if (status) 56109b7b9fccSAndy Adamson goto out; 5611bf269551SChuck Lever status = decode_putfh(xdr); 56121da177e4SLinus Torvalds if (status) 56131da177e4SLinus Torvalds goto out; 5614bf269551SChuck Lever status = decode_setattr(xdr); 56151da177e4SLinus Torvalds if (status) 56161da177e4SLinus Torvalds goto out; 5617bf269551SChuck Lever 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 56231da177e4SLinus Torvalds /* 56241da177e4SLinus Torvalds * Decode LOCK response 56251da177e4SLinus Torvalds */ 5626bf269551SChuck Lever static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5627bf269551SChuck Lever struct nfs_lock_res *res) 56281da177e4SLinus Torvalds { 56291da177e4SLinus Torvalds struct compound_hdr hdr; 56301da177e4SLinus Torvalds int status; 56311da177e4SLinus Torvalds 5632bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 56331da177e4SLinus Torvalds if (status) 56341da177e4SLinus Torvalds goto out; 5635bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 56369b7b9fccSAndy Adamson if (status) 56379b7b9fccSAndy Adamson goto out; 5638bf269551SChuck Lever status = decode_putfh(xdr); 56391da177e4SLinus Torvalds if (status) 56401da177e4SLinus Torvalds goto out; 5641bf269551SChuck Lever status = decode_lock(xdr, res); 56421da177e4SLinus Torvalds out: 56431da177e4SLinus Torvalds return status; 56441da177e4SLinus Torvalds } 56451da177e4SLinus Torvalds 56461da177e4SLinus Torvalds /* 56471da177e4SLinus Torvalds * Decode LOCKT response 56481da177e4SLinus Torvalds */ 5649bf269551SChuck Lever static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5650bf269551SChuck Lever struct nfs_lockt_res *res) 56511da177e4SLinus Torvalds { 56521da177e4SLinus Torvalds struct compound_hdr hdr; 56531da177e4SLinus Torvalds int status; 56541da177e4SLinus Torvalds 5655bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 56561da177e4SLinus Torvalds if (status) 56571da177e4SLinus Torvalds goto out; 5658bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 56599b7b9fccSAndy Adamson if (status) 56609b7b9fccSAndy Adamson goto out; 5661bf269551SChuck Lever status = decode_putfh(xdr); 56621da177e4SLinus Torvalds if (status) 56631da177e4SLinus Torvalds goto out; 5664bf269551SChuck Lever status = decode_lockt(xdr, res); 56651da177e4SLinus Torvalds out: 56661da177e4SLinus Torvalds return status; 56671da177e4SLinus Torvalds } 56681da177e4SLinus Torvalds 56691da177e4SLinus Torvalds /* 56701da177e4SLinus Torvalds * Decode LOCKU response 56711da177e4SLinus Torvalds */ 5672bf269551SChuck Lever static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5673bf269551SChuck Lever struct nfs_locku_res *res) 56741da177e4SLinus Torvalds { 56751da177e4SLinus Torvalds struct compound_hdr hdr; 56761da177e4SLinus Torvalds int status; 56771da177e4SLinus Torvalds 5678bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 56791da177e4SLinus Torvalds if (status) 56801da177e4SLinus Torvalds goto out; 5681bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 56829b7b9fccSAndy Adamson if (status) 56839b7b9fccSAndy Adamson goto out; 5684bf269551SChuck Lever status = decode_putfh(xdr); 56851da177e4SLinus Torvalds if (status) 56861da177e4SLinus Torvalds goto out; 5687bf269551SChuck Lever status = decode_locku(xdr, res); 56881da177e4SLinus Torvalds out: 56891da177e4SLinus Torvalds return status; 56901da177e4SLinus Torvalds } 56911da177e4SLinus Torvalds 5692bf269551SChuck Lever static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, 5693bf269551SChuck Lever struct xdr_stream *xdr, void *dummy) 5694d3c7b7ccSTrond Myklebust { 5695d3c7b7ccSTrond Myklebust struct compound_hdr hdr; 5696d3c7b7ccSTrond Myklebust int status; 5697d3c7b7ccSTrond Myklebust 5698bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 5699d3c7b7ccSTrond Myklebust if (!status) 5700bf269551SChuck Lever status = decode_release_lockowner(xdr); 5701d3c7b7ccSTrond Myklebust return status; 5702d3c7b7ccSTrond Myklebust } 5703d3c7b7ccSTrond Myklebust 57041da177e4SLinus Torvalds /* 57051da177e4SLinus Torvalds * Decode READLINK response 57061da177e4SLinus Torvalds */ 5707bf269551SChuck Lever static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, 5708bf269551SChuck Lever struct xdr_stream *xdr, 5709f50c7000SBenny Halevy struct nfs4_readlink_res *res) 57101da177e4SLinus Torvalds { 57111da177e4SLinus Torvalds struct compound_hdr hdr; 57121da177e4SLinus Torvalds int status; 57131da177e4SLinus Torvalds 5714bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 57151da177e4SLinus Torvalds if (status) 57161da177e4SLinus Torvalds goto out; 5717bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 57189b7b9fccSAndy Adamson if (status) 57199b7b9fccSAndy Adamson goto out; 5720bf269551SChuck Lever status = decode_putfh(xdr); 57211da177e4SLinus Torvalds if (status) 57221da177e4SLinus Torvalds goto out; 5723bf269551SChuck Lever status = decode_readlink(xdr, rqstp); 57241da177e4SLinus Torvalds out: 57251da177e4SLinus Torvalds return status; 57261da177e4SLinus Torvalds } 57271da177e4SLinus Torvalds 57281da177e4SLinus Torvalds /* 57291da177e4SLinus Torvalds * Decode READDIR response 57301da177e4SLinus Torvalds */ 5731bf269551SChuck Lever static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5732bf269551SChuck Lever struct nfs4_readdir_res *res) 57331da177e4SLinus Torvalds { 57341da177e4SLinus Torvalds struct compound_hdr hdr; 57351da177e4SLinus Torvalds int status; 57361da177e4SLinus Torvalds 5737bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 57381da177e4SLinus Torvalds if (status) 57391da177e4SLinus Torvalds goto out; 5740bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 57419b7b9fccSAndy Adamson if (status) 57429b7b9fccSAndy Adamson goto out; 5743bf269551SChuck Lever status = decode_putfh(xdr); 57441da177e4SLinus Torvalds if (status) 57451da177e4SLinus Torvalds goto out; 5746bf269551SChuck Lever status = decode_readdir(xdr, rqstp, res); 57471da177e4SLinus Torvalds out: 57481da177e4SLinus Torvalds return status; 57491da177e4SLinus Torvalds } 57501da177e4SLinus Torvalds 57511da177e4SLinus Torvalds /* 57521da177e4SLinus Torvalds * Decode Read response 57531da177e4SLinus Torvalds */ 5754bf269551SChuck Lever static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5755bf269551SChuck Lever struct nfs_readres *res) 57561da177e4SLinus Torvalds { 57571da177e4SLinus Torvalds struct compound_hdr hdr; 57581da177e4SLinus Torvalds int status; 57591da177e4SLinus Torvalds 5760bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 57611da177e4SLinus Torvalds if (status) 57621da177e4SLinus Torvalds goto out; 5763bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 57649b7b9fccSAndy Adamson if (status) 57659b7b9fccSAndy Adamson goto out; 5766bf269551SChuck Lever status = decode_putfh(xdr); 57671da177e4SLinus Torvalds if (status) 57681da177e4SLinus Torvalds goto out; 5769bf269551SChuck Lever status = decode_read(xdr, rqstp, res); 57701da177e4SLinus Torvalds if (!status) 57711da177e4SLinus Torvalds status = res->count; 57721da177e4SLinus Torvalds out: 57731da177e4SLinus Torvalds return status; 57741da177e4SLinus Torvalds } 57751da177e4SLinus Torvalds 57761da177e4SLinus Torvalds /* 57771da177e4SLinus Torvalds * Decode WRITE response 57781da177e4SLinus Torvalds */ 5779bf269551SChuck Lever static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5780bf269551SChuck Lever struct nfs_writeres *res) 57811da177e4SLinus Torvalds { 57821da177e4SLinus Torvalds struct compound_hdr hdr; 57831da177e4SLinus Torvalds int status; 57841da177e4SLinus Torvalds 5785bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 57861da177e4SLinus Torvalds if (status) 57871da177e4SLinus Torvalds goto out; 5788bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 57899b7b9fccSAndy Adamson if (status) 57909b7b9fccSAndy Adamson goto out; 5791bf269551SChuck Lever status = decode_putfh(xdr); 57921da177e4SLinus Torvalds if (status) 57931da177e4SLinus Torvalds goto out; 5794bf269551SChuck Lever status = decode_write(xdr, res); 57954f9838c7STrond Myklebust if (status) 57964f9838c7STrond Myklebust goto out; 57977ffd1064SFred Isaman if (res->fattr) 5798bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 579980e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 58001da177e4SLinus Torvalds if (!status) 58011da177e4SLinus Torvalds status = res->count; 58021da177e4SLinus Torvalds out: 58031da177e4SLinus Torvalds return status; 58041da177e4SLinus Torvalds } 58051da177e4SLinus Torvalds 58061da177e4SLinus Torvalds /* 58071da177e4SLinus Torvalds * Decode COMMIT response 58081da177e4SLinus Torvalds */ 5809bf269551SChuck Lever static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5810bf269551SChuck Lever struct nfs_writeres *res) 58111da177e4SLinus Torvalds { 58121da177e4SLinus Torvalds struct compound_hdr hdr; 58131da177e4SLinus Torvalds int status; 58141da177e4SLinus Torvalds 5815bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 58161da177e4SLinus Torvalds if (status) 58171da177e4SLinus Torvalds goto out; 5818bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 58199b7b9fccSAndy Adamson if (status) 58209b7b9fccSAndy Adamson goto out; 5821bf269551SChuck Lever status = decode_putfh(xdr); 58221da177e4SLinus Torvalds if (status) 58231da177e4SLinus Torvalds goto out; 5824bf269551SChuck Lever status = decode_commit(xdr, res); 58254f9838c7STrond Myklebust if (status) 58264f9838c7STrond Myklebust goto out; 5827988b6dceSFred Isaman if (res->fattr) 5828bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 582980e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 58301da177e4SLinus Torvalds out: 58311da177e4SLinus Torvalds return status; 58321da177e4SLinus Torvalds } 58331da177e4SLinus Torvalds 58341da177e4SLinus Torvalds /* 58358b173218SRicardo Labiaga * Decode FSINFO response 58361da177e4SLinus Torvalds */ 5837bf269551SChuck Lever static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, 58383dda5e43SBenny Halevy struct nfs4_fsinfo_res *res) 58391da177e4SLinus Torvalds { 58401da177e4SLinus Torvalds struct compound_hdr hdr; 58411da177e4SLinus Torvalds int status; 58421da177e4SLinus Torvalds 5843bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 58441da177e4SLinus Torvalds if (!status) 5845bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 58469b7b9fccSAndy Adamson if (!status) 5847bf269551SChuck Lever status = decode_putfh(xdr); 58481da177e4SLinus Torvalds if (!status) 5849bf269551SChuck Lever status = decode_fsinfo(xdr, res->fsinfo); 58501da177e4SLinus Torvalds return status; 58511da177e4SLinus Torvalds } 58521da177e4SLinus Torvalds 58531da177e4SLinus Torvalds /* 58548b173218SRicardo Labiaga * Decode PATHCONF response 58551da177e4SLinus Torvalds */ 5856bf269551SChuck Lever static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, 5857d45b2989SBenny Halevy struct nfs4_pathconf_res *res) 58581da177e4SLinus Torvalds { 58591da177e4SLinus Torvalds struct compound_hdr hdr; 58601da177e4SLinus Torvalds int status; 58611da177e4SLinus Torvalds 5862bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 58631da177e4SLinus Torvalds if (!status) 5864bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 58659b7b9fccSAndy Adamson if (!status) 5866bf269551SChuck Lever status = decode_putfh(xdr); 58671da177e4SLinus Torvalds if (!status) 5868bf269551SChuck Lever status = decode_pathconf(xdr, res->pathconf); 58691da177e4SLinus Torvalds return status; 58701da177e4SLinus Torvalds } 58711da177e4SLinus Torvalds 58721da177e4SLinus Torvalds /* 58738b173218SRicardo Labiaga * Decode STATFS response 58741da177e4SLinus Torvalds */ 5875bf269551SChuck Lever static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, 587624ad148aSBenny Halevy struct nfs4_statfs_res *res) 58771da177e4SLinus Torvalds { 58781da177e4SLinus Torvalds struct compound_hdr hdr; 58791da177e4SLinus Torvalds int status; 58801da177e4SLinus Torvalds 5881bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 58821da177e4SLinus Torvalds if (!status) 5883bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 58849b7b9fccSAndy Adamson if (!status) 5885bf269551SChuck Lever status = decode_putfh(xdr); 58861da177e4SLinus Torvalds if (!status) 5887bf269551SChuck Lever status = decode_statfs(xdr, res->fsstat); 58881da177e4SLinus Torvalds return status; 58891da177e4SLinus Torvalds } 58901da177e4SLinus Torvalds 58911da177e4SLinus Torvalds /* 58928b173218SRicardo Labiaga * Decode GETATTR_BITMAP response 58931da177e4SLinus Torvalds */ 5894bf269551SChuck Lever static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, 5895bf269551SChuck Lever struct xdr_stream *xdr, 5896bf269551SChuck Lever struct nfs4_server_caps_res *res) 58971da177e4SLinus Torvalds { 58981da177e4SLinus Torvalds struct compound_hdr hdr; 58991da177e4SLinus Torvalds int status; 59001da177e4SLinus Torvalds 5901bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 59029b7b9fccSAndy Adamson if (status) 59039b7b9fccSAndy Adamson goto out; 5904bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 59059b7b9fccSAndy Adamson if (status) 59061da177e4SLinus Torvalds goto out; 5907bf269551SChuck Lever status = decode_putfh(xdr); 5908bf269551SChuck Lever if (status) 59091da177e4SLinus Torvalds goto out; 5910bf269551SChuck Lever status = decode_server_caps(xdr, res); 59111da177e4SLinus Torvalds out: 59121da177e4SLinus Torvalds return status; 59131da177e4SLinus Torvalds } 59141da177e4SLinus Torvalds 59151da177e4SLinus Torvalds /* 59161da177e4SLinus Torvalds * Decode RENEW response 59171da177e4SLinus Torvalds */ 5918bf269551SChuck Lever static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr, 5919bf269551SChuck Lever void *__unused) 59201da177e4SLinus Torvalds { 59211da177e4SLinus Torvalds struct compound_hdr hdr; 59221da177e4SLinus Torvalds int status; 59231da177e4SLinus Torvalds 5924bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 59251da177e4SLinus Torvalds if (!status) 5926bf269551SChuck Lever status = decode_renew(xdr); 59271da177e4SLinus Torvalds return status; 59281da177e4SLinus Torvalds } 59291da177e4SLinus Torvalds 59301da177e4SLinus Torvalds /* 59318b173218SRicardo Labiaga * Decode SETCLIENTID response 59321da177e4SLinus Torvalds */ 5933bf269551SChuck Lever static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, 5934bf269551SChuck Lever struct xdr_stream *xdr, 5935bb8b27e5STrond Myklebust struct nfs4_setclientid_res *res) 59361da177e4SLinus Torvalds { 59371da177e4SLinus Torvalds struct compound_hdr hdr; 59381da177e4SLinus Torvalds int status; 59391da177e4SLinus Torvalds 5940bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 59411da177e4SLinus Torvalds if (!status) 5942bf269551SChuck Lever status = decode_setclientid(xdr, res); 59431da177e4SLinus Torvalds return status; 59441da177e4SLinus Torvalds } 59451da177e4SLinus Torvalds 59461da177e4SLinus Torvalds /* 59478b173218SRicardo Labiaga * Decode SETCLIENTID_CONFIRM response 59481da177e4SLinus Torvalds */ 5949bf269551SChuck Lever static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, 5950bf269551SChuck Lever struct xdr_stream *xdr, 5951bf269551SChuck Lever struct nfs_fsinfo *fsinfo) 59521da177e4SLinus Torvalds { 59531da177e4SLinus Torvalds struct compound_hdr hdr; 59541da177e4SLinus Torvalds int status; 59551da177e4SLinus Torvalds 5956bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 59571da177e4SLinus Torvalds if (!status) 5958bf269551SChuck Lever status = decode_setclientid_confirm(xdr); 59591da177e4SLinus Torvalds if (!status) 5960bf269551SChuck Lever status = decode_putrootfh(xdr); 59611da177e4SLinus Torvalds if (!status) 5962bf269551SChuck Lever status = decode_fsinfo(xdr, fsinfo); 59631da177e4SLinus Torvalds return status; 59641da177e4SLinus Torvalds } 59651da177e4SLinus Torvalds 59661da177e4SLinus Torvalds /* 59678b173218SRicardo Labiaga * Decode DELEGRETURN response 59681da177e4SLinus Torvalds */ 5969bf269551SChuck Lever static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, 5970bf269551SChuck Lever struct xdr_stream *xdr, 5971bf269551SChuck Lever struct nfs4_delegreturnres *res) 59721da177e4SLinus Torvalds { 59731da177e4SLinus Torvalds struct compound_hdr hdr; 59741da177e4SLinus Torvalds int status; 59751da177e4SLinus Torvalds 5976bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 59779b7b9fccSAndy Adamson if (status) 59789b7b9fccSAndy Adamson goto out; 5979bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 59809b7b9fccSAndy Adamson if (status) 5981fa178f29STrond Myklebust goto out; 5982bf269551SChuck Lever status = decode_putfh(xdr); 5983fa178f29STrond Myklebust if (status != 0) 5984fa178f29STrond Myklebust goto out; 5985bf269551SChuck Lever status = decode_delegreturn(xdr); 5986556ae3bbSJeff Layton if (status != 0) 5987556ae3bbSJeff Layton goto out; 5988bf269551SChuck Lever decode_getfattr(xdr, res->fattr, res->server, 598980e52aceSTrond Myklebust !RPC_IS_ASYNC(rqstp->rq_task)); 5990fa178f29STrond Myklebust out: 59911da177e4SLinus Torvalds return status; 59921da177e4SLinus Torvalds } 59931da177e4SLinus Torvalds 5994683b57b4STrond Myklebust /* 59958b173218SRicardo Labiaga * Decode FS_LOCATIONS response 5996683b57b4STrond Myklebust */ 5997bf269551SChuck Lever static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, 5998bf269551SChuck Lever struct xdr_stream *xdr, 599922958463SBenny Halevy struct nfs4_fs_locations_res *res) 6000683b57b4STrond Myklebust { 6001683b57b4STrond Myklebust struct compound_hdr hdr; 6002683b57b4STrond Myklebust int status; 6003683b57b4STrond Myklebust 6004bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 60059b7b9fccSAndy Adamson if (status) 60069b7b9fccSAndy Adamson goto out; 6007bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, req); 60089b7b9fccSAndy Adamson if (status) 6009683b57b4STrond Myklebust goto out; 6010bf269551SChuck Lever status = decode_putfh(xdr); 6011bf269551SChuck Lever if (status) 6012683b57b4STrond Myklebust goto out; 6013bf269551SChuck Lever status = decode_lookup(xdr); 6014bf269551SChuck Lever if (status) 6015683b57b4STrond Myklebust goto out; 6016bf269551SChuck Lever xdr_enter_page(xdr, PAGE_SIZE); 6017bf269551SChuck Lever status = decode_getfattr(xdr, &res->fs_locations->fattr, 601880e52aceSTrond Myklebust res->fs_locations->server, 601980e52aceSTrond Myklebust !RPC_IS_ASYNC(req->rq_task)); 6020683b57b4STrond Myklebust out: 6021683b57b4STrond Myklebust return status; 6022683b57b4STrond Myklebust } 6023683b57b4STrond Myklebust 602499fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 602599fe60d0SBenny Halevy /* 60268b173218SRicardo Labiaga * Decode EXCHANGE_ID response 602799fe60d0SBenny Halevy */ 6028bf269551SChuck Lever static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, 6029bf269551SChuck Lever struct xdr_stream *xdr, 603099fe60d0SBenny Halevy void *res) 603199fe60d0SBenny Halevy { 603299fe60d0SBenny Halevy struct compound_hdr hdr; 603399fe60d0SBenny Halevy int status; 603499fe60d0SBenny Halevy 6035bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 603699fe60d0SBenny Halevy if (!status) 6037bf269551SChuck Lever status = decode_exchange_id(xdr, res); 603899fe60d0SBenny Halevy return status; 603999fe60d0SBenny Halevy } 60402050f0ccSAndy Adamson 60412050f0ccSAndy Adamson /* 60428b173218SRicardo Labiaga * Decode CREATE_SESSION response 6043fc931582SAndy Adamson */ 6044bf269551SChuck Lever static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, 6045bf269551SChuck Lever struct xdr_stream *xdr, 6046fc931582SAndy Adamson struct nfs41_create_session_res *res) 6047fc931582SAndy Adamson { 6048fc931582SAndy Adamson struct compound_hdr hdr; 6049fc931582SAndy Adamson int status; 6050fc931582SAndy Adamson 6051bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6052fc931582SAndy Adamson if (!status) 6053bf269551SChuck Lever status = decode_create_session(xdr, res); 6054fc931582SAndy Adamson return status; 6055fc931582SAndy Adamson } 6056fc931582SAndy Adamson 6057fc931582SAndy Adamson /* 60588b173218SRicardo Labiaga * Decode DESTROY_SESSION response 60590f3e66c6SAndy Adamson */ 6060bf269551SChuck Lever static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, 6061bf269551SChuck Lever struct xdr_stream *xdr, 6062bf269551SChuck Lever void *res) 60630f3e66c6SAndy Adamson { 60640f3e66c6SAndy Adamson struct compound_hdr hdr; 60650f3e66c6SAndy Adamson int status; 60660f3e66c6SAndy Adamson 6067bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 60680f3e66c6SAndy Adamson if (!status) 6069bf269551SChuck Lever status = decode_destroy_session(xdr, res); 60700f3e66c6SAndy Adamson return status; 60710f3e66c6SAndy Adamson } 60720f3e66c6SAndy Adamson 60730f3e66c6SAndy Adamson /* 60748b173218SRicardo Labiaga * Decode SEQUENCE response 6075fc01cea9SAndy Adamson */ 6076bf269551SChuck Lever static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, 6077bf269551SChuck Lever struct xdr_stream *xdr, 6078fc01cea9SAndy Adamson struct nfs4_sequence_res *res) 6079fc01cea9SAndy Adamson { 6080fc01cea9SAndy Adamson struct compound_hdr hdr; 6081fc01cea9SAndy Adamson int status; 6082fc01cea9SAndy Adamson 6083bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6084fc01cea9SAndy Adamson if (!status) 6085bf269551SChuck Lever status = decode_sequence(xdr, res, rqstp); 6086fc01cea9SAndy Adamson return status; 6087fc01cea9SAndy Adamson } 6088fc01cea9SAndy Adamson 6089fc01cea9SAndy Adamson /* 60908b173218SRicardo Labiaga * Decode GET_LEASE_TIME response 60912050f0ccSAndy Adamson */ 6092bf269551SChuck Lever static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, 6093bf269551SChuck Lever struct xdr_stream *xdr, 60942050f0ccSAndy Adamson struct nfs4_get_lease_time_res *res) 60952050f0ccSAndy Adamson { 60962050f0ccSAndy Adamson struct compound_hdr hdr; 60972050f0ccSAndy Adamson int status; 60982050f0ccSAndy Adamson 6099bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 61002050f0ccSAndy Adamson if (!status) 6101bf269551SChuck Lever status = decode_sequence(xdr, &res->lr_seq_res, rqstp); 61022050f0ccSAndy Adamson if (!status) 6103bf269551SChuck Lever status = decode_putrootfh(xdr); 61042050f0ccSAndy Adamson if (!status) 6105bf269551SChuck Lever status = decode_fsinfo(xdr, res->lr_fsinfo); 61062050f0ccSAndy Adamson return status; 61072050f0ccSAndy Adamson } 610818019753SRicardo Labiaga 610918019753SRicardo Labiaga /* 611018019753SRicardo Labiaga * Decode RECLAIM_COMPLETE response 611118019753SRicardo Labiaga */ 6112bf269551SChuck Lever static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, 6113bf269551SChuck Lever struct xdr_stream *xdr, 611418019753SRicardo Labiaga struct nfs41_reclaim_complete_res *res) 611518019753SRicardo Labiaga { 611618019753SRicardo Labiaga struct compound_hdr hdr; 611718019753SRicardo Labiaga int status; 611818019753SRicardo Labiaga 6119bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 612018019753SRicardo Labiaga if (!status) 6121bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 612218019753SRicardo Labiaga if (!status) 6123bf269551SChuck Lever status = decode_reclaim_complete(xdr, (void *)NULL); 612418019753SRicardo Labiaga return status; 612518019753SRicardo Labiaga } 6126b1f69b75SAndy Adamson 6127b1f69b75SAndy Adamson /* 6128b1f69b75SAndy Adamson * Decode GETDEVINFO response 6129b1f69b75SAndy Adamson */ 6130bf269551SChuck Lever static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, 6131bf269551SChuck Lever struct xdr_stream *xdr, 6132b1f69b75SAndy Adamson struct nfs4_getdeviceinfo_res *res) 6133b1f69b75SAndy Adamson { 6134b1f69b75SAndy Adamson struct compound_hdr hdr; 6135b1f69b75SAndy Adamson int status; 6136b1f69b75SAndy Adamson 6137bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6138b1f69b75SAndy Adamson if (status != 0) 6139b1f69b75SAndy Adamson goto out; 6140bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 6141b1f69b75SAndy Adamson if (status != 0) 6142b1f69b75SAndy Adamson goto out; 6143bf269551SChuck Lever status = decode_getdeviceinfo(xdr, res->pdev); 6144b1f69b75SAndy Adamson out: 6145b1f69b75SAndy Adamson return status; 6146b1f69b75SAndy Adamson } 6147b1f69b75SAndy Adamson 6148b1f69b75SAndy Adamson /* 6149b1f69b75SAndy Adamson * Decode LAYOUTGET response 6150b1f69b75SAndy Adamson */ 6151bf269551SChuck Lever static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, 6152bf269551SChuck Lever struct xdr_stream *xdr, 6153b1f69b75SAndy Adamson struct nfs4_layoutget_res *res) 6154b1f69b75SAndy Adamson { 6155b1f69b75SAndy Adamson struct compound_hdr hdr; 6156b1f69b75SAndy Adamson int status; 6157b1f69b75SAndy Adamson 6158bf269551SChuck Lever status = decode_compound_hdr(xdr, &hdr); 6159b1f69b75SAndy Adamson if (status) 6160b1f69b75SAndy Adamson goto out; 6161bf269551SChuck Lever status = decode_sequence(xdr, &res->seq_res, rqstp); 6162b1f69b75SAndy Adamson if (status) 6163b1f69b75SAndy Adamson goto out; 6164bf269551SChuck Lever status = decode_putfh(xdr); 6165b1f69b75SAndy Adamson if (status) 6166b1f69b75SAndy Adamson goto out; 6167bf269551SChuck Lever status = decode_layoutget(xdr, rqstp, res); 6168b1f69b75SAndy Adamson out: 6169b1f69b75SAndy Adamson return status; 6170b1f69b75SAndy Adamson } 6171863a3c6cSAndy Adamson 6172863a3c6cSAndy Adamson /* 6173863a3c6cSAndy Adamson * Decode LAYOUTCOMMIT response 6174863a3c6cSAndy Adamson */ 6175863a3c6cSAndy Adamson static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, 6176863a3c6cSAndy Adamson struct xdr_stream *xdr, 6177863a3c6cSAndy Adamson struct nfs4_layoutcommit_res *res) 6178863a3c6cSAndy Adamson { 6179863a3c6cSAndy Adamson struct compound_hdr hdr; 6180863a3c6cSAndy Adamson int status; 6181863a3c6cSAndy Adamson 6182863a3c6cSAndy Adamson status = decode_compound_hdr(xdr, &hdr); 6183863a3c6cSAndy Adamson if (status) 6184863a3c6cSAndy Adamson goto out; 6185863a3c6cSAndy Adamson status = decode_sequence(xdr, &res->seq_res, rqstp); 6186863a3c6cSAndy Adamson if (status) 6187863a3c6cSAndy Adamson goto out; 6188863a3c6cSAndy Adamson status = decode_putfh(xdr); 6189863a3c6cSAndy Adamson if (status) 6190863a3c6cSAndy Adamson goto out; 6191863a3c6cSAndy Adamson status = decode_layoutcommit(xdr, rqstp, res); 6192863a3c6cSAndy Adamson if (status) 6193863a3c6cSAndy Adamson goto out; 6194863a3c6cSAndy Adamson decode_getfattr(xdr, res->fattr, res->server, 6195863a3c6cSAndy Adamson !RPC_IS_ASYNC(rqstp->rq_task)); 6196863a3c6cSAndy Adamson out: 6197863a3c6cSAndy Adamson return status; 6198863a3c6cSAndy Adamson } 619999fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 620099fe60d0SBenny Halevy 6201573c4e1eSChuck Lever /** 6202573c4e1eSChuck Lever * nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in 6203573c4e1eSChuck Lever * the local page cache. 6204573c4e1eSChuck Lever * @xdr: XDR stream where entry resides 6205573c4e1eSChuck Lever * @entry: buffer to fill in with entry data 6206573c4e1eSChuck Lever * @plus: boolean indicating whether this should be a readdirplus entry 6207573c4e1eSChuck Lever * 6208573c4e1eSChuck Lever * Returns zero if successful, otherwise a negative errno value is 6209573c4e1eSChuck Lever * returned. 6210573c4e1eSChuck Lever * 6211573c4e1eSChuck Lever * This function is not invoked during READDIR reply decoding, but 6212573c4e1eSChuck Lever * rather whenever an application invokes the getdents(2) system call 6213573c4e1eSChuck Lever * on a directory already in our cache. 6214573c4e1eSChuck Lever */ 6215573c4e1eSChuck Lever int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, 6216573c4e1eSChuck Lever int plus) 62171da177e4SLinus Torvalds { 62181da177e4SLinus Torvalds uint32_t bitmap[2] = {0}; 62191da177e4SLinus Torvalds uint32_t len; 6220babddc72SBryan Schumaker __be32 *p = xdr_inline_decode(xdr, 4); 6221babddc72SBryan Schumaker if (unlikely(!p)) 6222babddc72SBryan Schumaker goto out_overflow; 6223c08e76d0SChuck Lever if (*p == xdr_zero) { 6224babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 4); 6225babddc72SBryan Schumaker if (unlikely(!p)) 6226babddc72SBryan Schumaker goto out_overflow; 6227c08e76d0SChuck Lever if (*p == xdr_zero) 6228573c4e1eSChuck Lever return -EAGAIN; 62291da177e4SLinus Torvalds entry->eof = 1; 6230573c4e1eSChuck Lever return -EBADCOOKIE; 62311da177e4SLinus Torvalds } 62321da177e4SLinus Torvalds 6233babddc72SBryan Schumaker p = xdr_inline_decode(xdr, 12); 6234babddc72SBryan Schumaker if (unlikely(!p)) 6235babddc72SBryan Schumaker goto out_overflow; 62361da177e4SLinus Torvalds entry->prev_cookie = entry->cookie; 62371da177e4SLinus Torvalds p = xdr_decode_hyper(p, &entry->cookie); 6238c08e76d0SChuck Lever entry->len = be32_to_cpup(p); 6239babddc72SBryan Schumaker 62409af8c222STrond Myklebust p = xdr_inline_decode(xdr, entry->len); 6241babddc72SBryan Schumaker if (unlikely(!p)) 6242babddc72SBryan Schumaker goto out_overflow; 62431da177e4SLinus Torvalds entry->name = (const char *) p; 62441da177e4SLinus Torvalds 62451da177e4SLinus Torvalds /* 62461da177e4SLinus Torvalds * In case the server doesn't return an inode number, 62471da177e4SLinus Torvalds * we fake one here. (We don't use inode number 0, 62481da177e4SLinus Torvalds * since glibc seems to choke on it...) 62491da177e4SLinus Torvalds */ 62501da177e4SLinus Torvalds entry->ino = 1; 62514f082222STrond Myklebust entry->fattr->valid = 0; 62521da177e4SLinus Torvalds 62539af8c222STrond Myklebust if (decode_attr_bitmap(xdr, bitmap) < 0) 6254babddc72SBryan Schumaker goto out_overflow; 62559af8c222STrond Myklebust 62569af8c222STrond Myklebust if (decode_attr_length(xdr, &len, &p) < 0) 6257babddc72SBryan Schumaker goto out_overflow; 62589af8c222STrond Myklebust 6259573c4e1eSChuck Lever if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, 6260573c4e1eSChuck Lever entry->server, 1) < 0) 6261babddc72SBryan Schumaker goto out_overflow; 626282f2e547SBryan Schumaker if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) 626382f2e547SBryan Schumaker entry->ino = entry->fattr->fileid; 62649af8c222STrond Myklebust 62650b26a0bfSTrond Myklebust entry->d_type = DT_UNKNOWN; 62660b26a0bfSTrond Myklebust if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE) 62670b26a0bfSTrond Myklebust entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); 62680b26a0bfSTrond Myklebust 6269573c4e1eSChuck Lever return 0; 6270babddc72SBryan Schumaker 6271babddc72SBryan Schumaker out_overflow: 6272babddc72SBryan Schumaker print_overflow_msg(__func__, xdr); 6273573c4e1eSChuck Lever return -EAGAIN; 62741da177e4SLinus Torvalds } 62751da177e4SLinus Torvalds 62761da177e4SLinus Torvalds /* 62771da177e4SLinus Torvalds * We need to translate between nfs status return values and 62781da177e4SLinus Torvalds * the local errno values which may not be the same. 62791da177e4SLinus Torvalds */ 62801da177e4SLinus Torvalds static struct { 62811da177e4SLinus Torvalds int stat; 62821da177e4SLinus Torvalds int errno; 62831da177e4SLinus Torvalds } nfs_errtbl[] = { 62841da177e4SLinus Torvalds { NFS4_OK, 0 }, 6285856dff3dSBenny Halevy { NFS4ERR_PERM, -EPERM }, 6286856dff3dSBenny Halevy { NFS4ERR_NOENT, -ENOENT }, 6287856dff3dSBenny Halevy { NFS4ERR_IO, -errno_NFSERR_IO}, 6288856dff3dSBenny Halevy { NFS4ERR_NXIO, -ENXIO }, 6289856dff3dSBenny Halevy { NFS4ERR_ACCESS, -EACCES }, 6290856dff3dSBenny Halevy { NFS4ERR_EXIST, -EEXIST }, 6291856dff3dSBenny Halevy { NFS4ERR_XDEV, -EXDEV }, 6292856dff3dSBenny Halevy { NFS4ERR_NOTDIR, -ENOTDIR }, 6293856dff3dSBenny Halevy { NFS4ERR_ISDIR, -EISDIR }, 6294856dff3dSBenny Halevy { NFS4ERR_INVAL, -EINVAL }, 6295856dff3dSBenny Halevy { NFS4ERR_FBIG, -EFBIG }, 6296856dff3dSBenny Halevy { NFS4ERR_NOSPC, -ENOSPC }, 6297856dff3dSBenny Halevy { NFS4ERR_ROFS, -EROFS }, 6298856dff3dSBenny Halevy { NFS4ERR_MLINK, -EMLINK }, 6299856dff3dSBenny Halevy { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG }, 6300856dff3dSBenny Halevy { NFS4ERR_NOTEMPTY, -ENOTEMPTY }, 6301856dff3dSBenny Halevy { NFS4ERR_DQUOT, -EDQUOT }, 6302856dff3dSBenny Halevy { NFS4ERR_STALE, -ESTALE }, 6303856dff3dSBenny Halevy { NFS4ERR_BADHANDLE, -EBADHANDLE }, 6304856dff3dSBenny Halevy { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, 6305856dff3dSBenny Halevy { NFS4ERR_NOTSUPP, -ENOTSUPP }, 6306856dff3dSBenny Halevy { NFS4ERR_TOOSMALL, -ETOOSMALL }, 6307fdcb4577STrond Myklebust { NFS4ERR_SERVERFAULT, -EREMOTEIO }, 6308856dff3dSBenny Halevy { NFS4ERR_BADTYPE, -EBADTYPE }, 6309856dff3dSBenny Halevy { NFS4ERR_LOCKED, -EAGAIN }, 6310856dff3dSBenny Halevy { NFS4ERR_SYMLINK, -ELOOP }, 6311856dff3dSBenny Halevy { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, 6312856dff3dSBenny Halevy { NFS4ERR_DEADLOCK, -EDEADLK }, 6313856dff3dSBenny Halevy { NFS4ERR_WRONGSEC, -EPERM }, /* FIXME: this needs 63141da177e4SLinus Torvalds * to be handled by a 63151da177e4SLinus Torvalds * middle-layer. 63161da177e4SLinus Torvalds */ 6317856dff3dSBenny Halevy { -1, -EIO } 63181da177e4SLinus Torvalds }; 63191da177e4SLinus Torvalds 63201da177e4SLinus Torvalds /* 63211da177e4SLinus Torvalds * Convert an NFS error code to a local one. 63221da177e4SLinus Torvalds * This one is used jointly by NFSv2 and NFSv3. 63231da177e4SLinus Torvalds */ 63241da177e4SLinus Torvalds static int 63250a8ea437SDavid Howells nfs4_stat_to_errno(int stat) 63261da177e4SLinus Torvalds { 63271da177e4SLinus Torvalds int i; 63281da177e4SLinus Torvalds for (i = 0; nfs_errtbl[i].stat != -1; i++) { 63291da177e4SLinus Torvalds if (nfs_errtbl[i].stat == stat) 63301da177e4SLinus Torvalds return nfs_errtbl[i].errno; 63311da177e4SLinus Torvalds } 63321da177e4SLinus Torvalds if (stat <= 10000 || stat > 10100) { 63331da177e4SLinus Torvalds /* The server is looney tunes. */ 6334fdcb4577STrond Myklebust return -EREMOTEIO; 63351da177e4SLinus Torvalds } 63361da177e4SLinus Torvalds /* If we cannot translate the error, the recovery routines should 63371da177e4SLinus Torvalds * handle it. 63381da177e4SLinus Torvalds * Note: remaining NFSv4 error codes have values > 10000, so should 63391da177e4SLinus Torvalds * not conflict with native Linux error codes. 63401da177e4SLinus Torvalds */ 6341856dff3dSBenny Halevy return -stat; 63421da177e4SLinus Torvalds } 63431da177e4SLinus Torvalds 63441da177e4SLinus Torvalds #define PROC(proc, argtype, restype) \ 63451da177e4SLinus Torvalds [NFSPROC4_CLNT_##proc] = { \ 63461da177e4SLinus Torvalds .p_proc = NFSPROC4_COMPOUND, \ 63479f06c719SChuck Lever .p_encode = (kxdreproc_t)nfs4_xdr_##argtype, \ 6348bf269551SChuck Lever .p_decode = (kxdrdproc_t)nfs4_xdr_##restype, \ 63492bea90d4SChuck Lever .p_arglen = NFS4_##argtype##_sz, \ 63502bea90d4SChuck Lever .p_replen = NFS4_##restype##_sz, \ 6351cc0175c1SChuck Lever .p_statidx = NFSPROC4_CLNT_##proc, \ 6352cc0175c1SChuck Lever .p_name = #proc, \ 63531da177e4SLinus Torvalds } 63541da177e4SLinus Torvalds 63551da177e4SLinus Torvalds struct rpc_procinfo nfs4_procedures[] = { 63561da177e4SLinus Torvalds PROC(READ, enc_read, dec_read), 63571da177e4SLinus Torvalds PROC(WRITE, enc_write, dec_write), 63581da177e4SLinus Torvalds PROC(COMMIT, enc_commit, dec_commit), 63591da177e4SLinus Torvalds PROC(OPEN, enc_open, dec_open), 63601da177e4SLinus Torvalds PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm), 63611da177e4SLinus Torvalds PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr), 63621da177e4SLinus Torvalds PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade), 63631da177e4SLinus Torvalds PROC(CLOSE, enc_close, dec_close), 63641da177e4SLinus Torvalds PROC(SETATTR, enc_setattr, dec_setattr), 63651da177e4SLinus Torvalds PROC(FSINFO, enc_fsinfo, dec_fsinfo), 63661da177e4SLinus Torvalds PROC(RENEW, enc_renew, dec_renew), 63671da177e4SLinus Torvalds PROC(SETCLIENTID, enc_setclientid, dec_setclientid), 63681da177e4SLinus Torvalds PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm), 63691da177e4SLinus Torvalds PROC(LOCK, enc_lock, dec_lock), 63701da177e4SLinus Torvalds PROC(LOCKT, enc_lockt, dec_lockt), 63711da177e4SLinus Torvalds PROC(LOCKU, enc_locku, dec_locku), 63721da177e4SLinus Torvalds PROC(ACCESS, enc_access, dec_access), 63731da177e4SLinus Torvalds PROC(GETATTR, enc_getattr, dec_getattr), 63741da177e4SLinus Torvalds PROC(LOOKUP, enc_lookup, dec_lookup), 63751da177e4SLinus Torvalds PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), 63761da177e4SLinus Torvalds PROC(REMOVE, enc_remove, dec_remove), 63771da177e4SLinus Torvalds PROC(RENAME, enc_rename, dec_rename), 63781da177e4SLinus Torvalds PROC(LINK, enc_link, dec_link), 63791da177e4SLinus Torvalds PROC(SYMLINK, enc_symlink, dec_symlink), 63801da177e4SLinus Torvalds PROC(CREATE, enc_create, dec_create), 63811da177e4SLinus Torvalds PROC(PATHCONF, enc_pathconf, dec_pathconf), 63821da177e4SLinus Torvalds PROC(STATFS, enc_statfs, dec_statfs), 63831da177e4SLinus Torvalds PROC(READLINK, enc_readlink, dec_readlink), 63841da177e4SLinus Torvalds PROC(READDIR, enc_readdir, dec_readdir), 63851da177e4SLinus Torvalds PROC(SERVER_CAPS, enc_server_caps, dec_server_caps), 63861da177e4SLinus Torvalds PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), 6387029d105eSJ. Bruce Fields PROC(GETACL, enc_getacl, dec_getacl), 638823ec6965SJ. Bruce Fields PROC(SETACL, enc_setacl, dec_setacl), 6389683b57b4STrond Myklebust PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), 6390d3c7b7ccSTrond Myklebust PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), 639199fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1) 639299fe60d0SBenny Halevy PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), 6393fc931582SAndy Adamson PROC(CREATE_SESSION, enc_create_session, dec_create_session), 63940f3e66c6SAndy Adamson PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), 6395fc01cea9SAndy Adamson PROC(SEQUENCE, enc_sequence, dec_sequence), 63962050f0ccSAndy Adamson PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), 639718019753SRicardo Labiaga PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), 6398b1f69b75SAndy Adamson PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), 6399b1f69b75SAndy Adamson PROC(LAYOUTGET, enc_layoutget, dec_layoutget), 6400863a3c6cSAndy Adamson PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), 640199fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */ 64021da177e4SLinus Torvalds }; 64031da177e4SLinus Torvalds 64041da177e4SLinus Torvalds struct rpc_version nfs_version4 = { 64051da177e4SLinus Torvalds .number = 4, 6406e8c96f8cSTobias Klauser .nrprocs = ARRAY_SIZE(nfs4_procedures), 64071da177e4SLinus Torvalds .procs = nfs4_procedures 64081da177e4SLinus Torvalds }; 64091da177e4SLinus Torvalds 64101da177e4SLinus Torvalds /* 64111da177e4SLinus Torvalds * Local variables: 64121da177e4SLinus Torvalds * c-basic-offset: 8 64131da177e4SLinus Torvalds * End: 64141da177e4SLinus Torvalds */ 6415