2005-04-17 02:20:36 +04:00
/*
* fs / nfs / nfs4xdr . c
*
* Client - side XDR for NFSv4 .
*
* Copyright ( c ) 2002 The Regents of the University of Michigan .
* All rights reserved .
*
* Kendrick Smith < kmsmith @ umich . edu >
* Andy Adamson < andros @ umich . edu >
2008-12-24 00:06:15 +03:00
*
2005-04-17 02:20:36 +04:00
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED ` ` AS IS ' ' AND ANY EXPRESS OR IMPLIED
* WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR
* BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include <linux/param.h>
# include <linux/time.h>
# include <linux/mm.h>
# include <linux/errno.h>
# include <linux/string.h>
# include <linux/in.h>
# include <linux/pagemap.h>
# include <linux/proc_fs.h>
# include <linux/kdev_t.h>
2012-02-18 00:20:24 +04:00
# include <linux/module.h>
# include <linux/utsname.h>
2005-04-17 02:20:36 +04:00
# include <linux/sunrpc/clnt.h>
2009-12-05 21:36:55 +03:00
# include <linux/sunrpc/msg_prot.h>
2011-03-24 20:12:29 +03:00
# include <linux/sunrpc/gss_api.h>
2005-04-17 02:20:36 +04:00
# include <linux/nfs.h>
# include <linux/nfs4.h>
# include <linux/nfs_fs.h>
# include <linux/nfs_idmap.h>
NFS: Always use the same SETCLIENTID boot verifier
Currently our NFS client assigns a unique SETCLIENTID boot verifier
for each server IP address it knows about. It's set to CURRENT_TIME
when the struct nfs_client for that server IP is created.
During the SETCLIENTID operation, our client also presents an
nfs_client_id4 string to servers, as an identifier on which the server
can hang all of this client's NFSv4 state. Our client's
nfs_client_id4 string is unique for each server IP address.
An NFSv4 server is obligated to wipe all NFSv4 state associated with
an nfs_client_id4 string when the client presents the same
nfs_client_id4 string along with a changed SETCLIENTID boot verifier.
When our client unmounts the last of a server's shares, it destroys
that server's struct nfs_client. The next time the client mounts that
NFS server, it creates a fresh struct nfs_client with a fresh boot
verifier. On seeing the fresh verifer, the server wipes any previous
NFSv4 state associated with that nfs_client_id4.
However, NFSv4.1 clients are supposed to present the same
nfs_client_id4 string to all servers. And, to support Transparent
State Migration, the same nfs_client_id4 string should be presented
to all NFSv4.0 servers so they recognize that migrated state for this
client belongs with state a server may already have for this client.
(This is known as the Uniform Client String model).
If the nfs_client_id4 string is the same but the boot verifier changes
for each server IP address, SETCLIENTID and EXCHANGE_ID operations
from such a client could unintentionally result in a server wiping a
client's previously obtained lease.
Thus, if our NFS client is going to use a fixed nfs_client_id4 string,
either for NFSv4.0 or NFSv4.1 mounts, our NFS client should use a
boot verifier that does not change depending on server IP address.
Replace our current per-nfs_client boot verifier with a per-nfs_net
boot verifier.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
2012-05-22 06:45:41 +04:00
2005-06-22 21:16:21 +04:00
# include "nfs4_fs.h"
2009-12-05 21:30:21 +03:00
# include "internal.h"
2012-11-26 23:20:49 +04:00
# include "nfs4session.h"
2010-10-20 08:18:03 +04:00
# include "pnfs.h"
NFS: Always use the same SETCLIENTID boot verifier
Currently our NFS client assigns a unique SETCLIENTID boot verifier
for each server IP address it knows about. It's set to CURRENT_TIME
when the struct nfs_client for that server IP is created.
During the SETCLIENTID operation, our client also presents an
nfs_client_id4 string to servers, as an identifier on which the server
can hang all of this client's NFSv4 state. Our client's
nfs_client_id4 string is unique for each server IP address.
An NFSv4 server is obligated to wipe all NFSv4 state associated with
an nfs_client_id4 string when the client presents the same
nfs_client_id4 string along with a changed SETCLIENTID boot verifier.
When our client unmounts the last of a server's shares, it destroys
that server's struct nfs_client. The next time the client mounts that
NFS server, it creates a fresh struct nfs_client with a fresh boot
verifier. On seeing the fresh verifer, the server wipes any previous
NFSv4 state associated with that nfs_client_id4.
However, NFSv4.1 clients are supposed to present the same
nfs_client_id4 string to all servers. And, to support Transparent
State Migration, the same nfs_client_id4 string should be presented
to all NFSv4.0 servers so they recognize that migrated state for this
client belongs with state a server may already have for this client.
(This is known as the Uniform Client String model).
If the nfs_client_id4 string is the same but the boot verifier changes
for each server IP address, SETCLIENTID and EXCHANGE_ID operations
from such a client could unintentionally result in a server wiping a
client's previously obtained lease.
Thus, if our NFS client is going to use a fixed nfs_client_id4 string,
either for NFSv4.0 or NFSv4.1 mounts, our NFS client should use a
boot verifier that does not change depending on server IP address.
Replace our current per-nfs_client boot verifier with a per-nfs_net
boot verifier.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
2012-05-22 06:45:41 +04:00
# include "netns.h"
2005-04-17 02:20:36 +04:00
# define NFSDBG_FACILITY NFSDBG_XDR
/* Mapping from NFS error code to "errno" error code. */
# define errno_NFSERR_IO EIO
2006-08-23 04:06:08 +04:00
static int nfs4_stat_to_errno ( int ) ;
2005-04-17 02:20:36 +04:00
/* NFSv4 COMPOUND tags are only wanted for debugging purposes */
# ifdef DEBUG
# define NFS4_MAXTAGLEN 20
# else
# define NFS4_MAXTAGLEN 0
# endif
2008-12-24 00:06:15 +03:00
/* lock,open owner id:
2007-07-02 21:58:33 +04:00
* we currently use size 2 ( u64 ) out of ( NFS4_OPAQUE_LIMIT > > 2 )
2005-04-17 02:20:36 +04:00
*/
2012-04-21 03:24:51 +04:00
# define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2)
2010-12-21 18:45:27 +03:00
# define lock_owner_id_maxsz (1 + 1 + 4)
2007-07-18 05:52:42 +04:00
# define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
2005-04-17 02:20:36 +04:00
# define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
# define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
# define op_encode_hdr_maxsz (1)
# define op_decode_hdr_maxsz (2)
2007-07-18 05:52:42 +04:00
# define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
# define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
# define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
# define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
2005-04-17 02:20:36 +04:00
# define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \
( NFS4_FHSIZE > > 2 ) )
# define decode_putfh_maxsz (op_decode_hdr_maxsz)
# define encode_putrootfh_maxsz (op_encode_hdr_maxsz)
# define decode_putrootfh_maxsz (op_decode_hdr_maxsz)
# define encode_getfh_maxsz (op_encode_hdr_maxsz)
# define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \
( ( 3 + NFS4_FHSIZE ) > > 2 ) )
2011-07-12 01:17:42 +04:00
# define nfs4_fattr_bitmap_maxsz 4
2005-06-22 21:16:22 +04:00
# define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
2005-04-17 02:20:36 +04:00
# define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
# define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
2007-07-09 02:38:23 +04:00
# define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
# define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
2013-05-22 20:50:44 +04:00
# ifdef CONFIG_NFS_V4_SECURITY_LABEL
/* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */
# define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN))
# define encode_readdir_space 24
# define encode_readdir_bitmask_sz 3
# else
# define nfs4_label_maxsz 0
# define encode_readdir_space 20
# define encode_readdir_bitmask_sz 2
# endif
2012-05-23 13:02:34 +04:00
/* We support only one layout type per file system */
# define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8)
2005-06-22 21:16:22 +04:00
/* This is based on getfattr, which uses the most attributes: */
# define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
2012-05-23 13:02:34 +04:00
3 + 3 + 3 + nfs4_owner_maxsz + \
2013-05-22 20:50:44 +04:00
nfs4_group_maxsz + nfs4_label_maxsz + \
decode_mdsthreshold_maxsz ) )
2005-06-22 21:16:22 +04:00
# define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
nfs4_fattr_value_maxsz )
# define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
2007-07-18 05:52:42 +04:00
# define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \
1 + 2 + 1 + \
nfs4_owner_maxsz + \
nfs4_group_maxsz + \
2013-05-22 20:50:44 +04:00
nfs4_label_maxsz + \
2007-07-18 05:52:42 +04:00
4 + 4 )
2005-04-17 02:20:36 +04:00
# define encode_savefh_maxsz (op_encode_hdr_maxsz)
# define decode_savefh_maxsz (op_decode_hdr_maxsz)
2005-10-28 06:12:40 +04:00
# define encode_restorefh_maxsz (op_encode_hdr_maxsz)
# define decode_restorefh_maxsz (op_decode_hdr_maxsz)
2008-03-13 16:26:30 +03:00
# define encode_fsinfo_maxsz (encode_getattr_maxsz)
2011-07-31 04:52:37 +04:00
/* The 5 accounts for the PNFS attributes, and assumes that at most three
* layout types will be returned .
*/
# define decode_fsinfo_maxsz (op_decode_hdr_maxsz + \
nfs4_fattr_bitmap_maxsz + 4 + 8 + 5 )
2005-04-17 02:20:36 +04:00
# define encode_renew_maxsz (op_encode_hdr_maxsz + 3)
# define decode_renew_maxsz (op_decode_hdr_maxsz)
# define encode_setclientid_maxsz \
( op_encode_hdr_maxsz + \
2007-12-10 22:56:54 +03:00
XDR_QUADLEN ( NFS4_VERIFIER_SIZE ) + \
XDR_QUADLEN ( NFS4_SETCLIENTID_NAMELEN ) + \
1 /* sc_prog */ + \
XDR_QUADLEN ( RPCBIND_MAXNETIDLEN ) + \
XDR_QUADLEN ( RPCBIND_MAXUADDRLEN ) + \
1 ) /* sc_cb_ident */
2005-04-17 02:20:36 +04:00
# define decode_setclientid_maxsz \
( op_decode_hdr_maxsz + \
2 + \
1024 ) /* large value for CLID_INUSE */
# define encode_setclientid_confirm_maxsz \
( op_encode_hdr_maxsz + \
3 + ( NFS4_VERIFIER_SIZE > > 2 ) )
# define decode_setclientid_confirm_maxsz \
( op_decode_hdr_maxsz )
2007-07-02 21:58:30 +04:00
# define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
# define decode_lookup_maxsz (op_decode_hdr_maxsz)
2007-07-02 21:57:28 +04:00
# define encode_share_access_maxsz \
( 2 )
2009-12-05 21:30:21 +03:00
# define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz)
2007-07-02 21:57:28 +04:00
# define encode_opentype_maxsz (1 + encode_createmode_maxsz)
# define encode_claim_null_maxsz (1 + nfs4_name_maxsz)
# define encode_open_maxsz (op_encode_hdr_maxsz + \
2 + encode_share_access_maxsz + 2 + \
open_owner_id_maxsz + \
encode_opentype_maxsz + \
encode_claim_null_maxsz )
# define decode_ace_maxsz (3 + nfs4_owner_maxsz)
2007-07-18 05:52:42 +04:00
# define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \
2007-07-02 21:57:28 +04:00
decode_ace_maxsz )
# define decode_change_info_maxsz (5)
# define decode_open_maxsz (op_decode_hdr_maxsz + \
2007-07-18 05:52:42 +04:00
decode_stateid_maxsz + \
2007-07-02 21:57:28 +04:00
decode_change_info_maxsz + 1 + \
nfs4_fattr_bitmap_maxsz + \
decode_delegation_maxsz )
2007-07-18 05:52:42 +04:00
# define encode_open_confirm_maxsz \
( op_encode_hdr_maxsz + \
encode_stateid_maxsz + 1 )
# define decode_open_confirm_maxsz \
( op_decode_hdr_maxsz + \
decode_stateid_maxsz )
# define encode_open_downgrade_maxsz \
( op_encode_hdr_maxsz + \
encode_stateid_maxsz + 1 + \
encode_share_access_maxsz )
# define decode_open_downgrade_maxsz \
( op_decode_hdr_maxsz + \
decode_stateid_maxsz )
# define encode_close_maxsz (op_encode_hdr_maxsz + \
1 + encode_stateid_maxsz )
# define decode_close_maxsz (op_decode_hdr_maxsz + \
decode_stateid_maxsz )
# define encode_setattr_maxsz (op_encode_hdr_maxsz + \
encode_stateid_maxsz + \
encode_attrs_maxsz )
# define decode_setattr_maxsz (op_decode_hdr_maxsz + \
nfs4_fattr_bitmap_maxsz )
# define encode_read_maxsz (op_encode_hdr_maxsz + \
encode_stateid_maxsz + 3 )
# define decode_read_maxsz (op_decode_hdr_maxsz + 2)
# define encode_readdir_maxsz (op_encode_hdr_maxsz + \
2013-05-22 20:50:44 +04:00
2 + encode_verifier_maxsz + 5 + \
nfs4_label_maxsz )
2007-07-18 05:52:42 +04:00
# define decode_readdir_maxsz (op_decode_hdr_maxsz + \
2013-05-22 20:50:44 +04:00
decode_verifier_maxsz + \
nfs4_label_maxsz + nfs4_fattr_maxsz )
2007-07-18 05:52:42 +04:00
# define encode_readlink_maxsz (op_encode_hdr_maxsz)
# define decode_readlink_maxsz (op_decode_hdr_maxsz + 1)
# define encode_write_maxsz (op_encode_hdr_maxsz + \
encode_stateid_maxsz + 4 )
# define decode_write_maxsz (op_decode_hdr_maxsz + \
2 + decode_verifier_maxsz )
# define encode_commit_maxsz (op_encode_hdr_maxsz + 3)
# define decode_commit_maxsz (op_decode_hdr_maxsz + \
decode_verifier_maxsz )
2005-04-17 02:20:36 +04:00
# define encode_remove_maxsz (op_encode_hdr_maxsz + \
nfs4_name_maxsz )
2009-04-01 17:22:06 +04:00
# define decode_remove_maxsz (op_decode_hdr_maxsz + \
decode_change_info_maxsz )
2005-04-17 02:20:36 +04:00
# define encode_rename_maxsz (op_encode_hdr_maxsz + \
2 * nfs4_name_maxsz )
2009-04-01 17:22:06 +04:00
# define decode_rename_maxsz (op_decode_hdr_maxsz + \
decode_change_info_maxsz + \
decode_change_info_maxsz )
2005-04-17 02:20:36 +04:00
# define encode_link_maxsz (op_encode_hdr_maxsz + \
nfs4_name_maxsz )
2009-04-01 17:22:06 +04:00
# define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz)
2010-06-26 02:11:43 +04:00
# define encode_lockowner_maxsz (7)
2007-07-18 05:52:42 +04:00
# define encode_lock_maxsz (op_encode_hdr_maxsz + \
7 + \
2010-06-26 02:11:43 +04:00
1 + encode_stateid_maxsz + 1 + \
encode_lockowner_maxsz )
2007-07-18 05:52:42 +04:00
# define decode_lock_denied_maxsz \
( 8 + decode_lockowner_maxsz )
# define decode_lock_maxsz (op_decode_hdr_maxsz + \
decode_lock_denied_maxsz )
2010-06-26 02:11:43 +04:00
# define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \
encode_lockowner_maxsz )
2007-07-18 05:52:42 +04:00
# define decode_lockt_maxsz (op_decode_hdr_maxsz + \
decode_lock_denied_maxsz )
# define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \
encode_stateid_maxsz + \
4 )
# define decode_locku_maxsz (op_decode_hdr_maxsz + \
decode_stateid_maxsz )
2010-07-01 20:49:01 +04:00
# define encode_release_lockowner_maxsz \
( op_encode_hdr_maxsz + \
encode_lockowner_maxsz )
# define decode_release_lockowner_maxsz \
( op_decode_hdr_maxsz )
2007-07-18 05:52:42 +04:00
# define encode_access_maxsz (op_encode_hdr_maxsz + 1)
# define decode_access_maxsz (op_decode_hdr_maxsz + 2)
2005-04-17 02:20:36 +04:00
# define encode_symlink_maxsz (op_encode_hdr_maxsz + \
1 + nfs4_name_maxsz + \
2006-08-23 04:06:23 +04:00
1 + \
2005-06-22 21:16:22 +04:00
nfs4_fattr_maxsz )
2005-04-17 02:20:36 +04:00
# define decode_symlink_maxsz (op_decode_hdr_maxsz + 8)
# define encode_create_maxsz (op_encode_hdr_maxsz + \
2007-07-18 05:52:42 +04:00
1 + 2 + nfs4_name_maxsz + \
encode_attrs_maxsz )
2007-07-02 21:57:28 +04:00
# define decode_create_maxsz (op_decode_hdr_maxsz + \
decode_change_info_maxsz + \
nfs4_fattr_bitmap_maxsz )
2007-07-18 05:52:42 +04:00
# define encode_statfs_maxsz (encode_getattr_maxsz)
# define decode_statfs_maxsz (decode_getattr_maxsz)
2005-04-17 02:20:36 +04:00
# define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
# define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
2007-07-18 05:52:42 +04:00
# define encode_getacl_maxsz (encode_getattr_maxsz)
# define decode_getacl_maxsz (op_decode_hdr_maxsz + \
nfs4_fattr_bitmap_maxsz + 1 )
# define encode_setacl_maxsz (op_encode_hdr_maxsz + \
encode_stateid_maxsz + 3 )
# define decode_setacl_maxsz (decode_setattr_maxsz)
2007-07-02 21:58:30 +04:00
# define encode_fs_locations_maxsz \
( encode_getattr_maxsz )
# define decode_fs_locations_maxsz \
( 0 )
2011-03-24 20:12:29 +03:00
# define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
2011-06-02 23:07:35 +04:00
# define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4))
2009-04-01 17:22:11 +04:00
# if defined(CONFIG_NFS_V4_1)
2009-04-01 17:22:31 +04:00
# define NFS4_MAX_MACHINE_NAME_LEN (64)
2012-11-17 03:12:06 +04:00
# define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \
sizeof ( utsname ( ) - > version ) + sizeof ( utsname ( ) - > machine ) + 8 )
2009-04-01 17:22:31 +04:00
2009-04-01 17:22:29 +04:00
# define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
encode_verifier_maxsz + \
1 /* co_ownerid.len */ + \
XDR_QUADLEN ( NFS4_EXCHANGE_ID_LEN ) + \
1 /* flags */ + \
1 /* spa_how */ + \
2013-08-14 00:37:32 +04:00
/* max is SP4_MACH_CRED (for now) */ + \
1 + NFS4_OP_MAP_NUM_WORDS + \
1 + NFS4_OP_MAP_NUM_WORDS + \
2012-02-18 00:20:24 +04:00
1 /* implementation id array of size 1 */ + \
1 /* nii_domain */ + \
XDR_QUADLEN ( NFS4_OPAQUE_LIMIT ) + \
1 /* nii_name */ + \
2012-11-17 03:12:06 +04:00
XDR_QUADLEN ( IMPL_NAME_LIMIT ) + \
2012-02-18 00:20:24 +04:00
3 /* nii_date */ )
2009-04-01 17:22:29 +04:00
# define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
2 /* eir_clientid */ + \
1 /* eir_sequenceid */ + \
1 /* eir_flags */ + \
1 /* spr_how */ + \
2013-08-14 00:37:32 +04:00
/* max is SP4_MACH_CRED (for now) */ + \
1 + NFS4_OP_MAP_NUM_WORDS + \
1 + NFS4_OP_MAP_NUM_WORDS + \
2009-04-01 17:22:29 +04:00
2 /* eir_server_owner.so_minor_id */ + \
/* eir_server_owner.so_major_id<> */ \
XDR_QUADLEN ( NFS4_OPAQUE_LIMIT ) + 1 + \
/* eir_server_scope<> */ \
XDR_QUADLEN ( NFS4_OPAQUE_LIMIT ) + 1 + \
1 /* eir_server_impl_id array length */ + \
2012-02-18 00:20:26 +04:00
1 /* nii_domain */ + \
XDR_QUADLEN ( NFS4_OPAQUE_LIMIT ) + \
1 /* nii_name */ + \
XDR_QUADLEN ( NFS4_OPAQUE_LIMIT ) + \
3 /* nii_date */ )
2009-04-01 17:22:31 +04:00
# define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */ )
# define decode_channel_attrs_maxsz (6 + \
1 /* ca_rdma_ird.len */ + \
1 /* ca_rdma_ird */ )
# define encode_create_session_maxsz (op_encode_hdr_maxsz + \
2 /* csa_clientid */ + \
1 /* csa_sequence */ + \
1 /* csa_flags */ + \
encode_channel_attrs_maxsz + \
encode_channel_attrs_maxsz + \
1 /* csa_cb_program */ + \
1 /* csa_sec_parms.len (1) */ + \
1 /* cb_secflavor (AUTH_SYS) */ + \
1 /* stamp */ + \
1 /* machinename.len */ + \
XDR_QUADLEN ( NFS4_MAX_MACHINE_NAME_LEN ) + \
1 /* uid */ + \
1 /* gid */ + \
1 /* gids.len (0) */ )
# define decode_create_session_maxsz (op_decode_hdr_maxsz + \
XDR_QUADLEN ( NFS4_MAX_SESSIONID_LEN ) + \
1 /* csr_sequence */ + \
1 /* csr_flags */ + \
decode_channel_attrs_maxsz + \
decode_channel_attrs_maxsz )
2012-05-24 21:22:50 +04:00
# define encode_bind_conn_to_session_maxsz (op_encode_hdr_maxsz + \
/* bctsa_sessid */ \
XDR_QUADLEN ( NFS4_MAX_SESSIONID_LEN ) + \
1 /* bctsa_dir */ + \
1 /* bctsa_use_conn_in_rdma_mode */ )
# define decode_bind_conn_to_session_maxsz (op_decode_hdr_maxsz + \
/* bctsr_sessid */ \
XDR_QUADLEN ( NFS4_MAX_SESSIONID_LEN ) + \
1 /* bctsr_dir */ + \
1 /* bctsr_use_conn_in_rdma_mode */ )
2009-04-01 17:22:34 +04:00
# define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4)
# define decode_destroy_session_maxsz (op_decode_hdr_maxsz)
2012-05-26 01:18:09 +04:00
# define encode_destroy_clientid_maxsz (op_encode_hdr_maxsz + 2)
# define decode_destroy_clientid_maxsz (op_decode_hdr_maxsz)
2009-04-01 17:22:36 +04:00
# define encode_sequence_maxsz (op_encode_hdr_maxsz + \
XDR_QUADLEN ( NFS4_MAX_SESSIONID_LEN ) + 4 )
# define decode_sequence_maxsz (op_decode_hdr_maxsz + \
XDR_QUADLEN ( NFS4_MAX_SESSIONID_LEN ) + 5 )
2009-12-06 00:08:40 +03:00
# define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4)
# define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4)
2011-07-31 04:52:35 +04:00
# define encode_getdevicelist_maxsz (op_encode_hdr_maxsz + 4 + \
encode_verifier_maxsz )
# define decode_getdevicelist_maxsz (op_decode_hdr_maxsz + \
2 /* nfs_cookie4 gdlr_cookie */ + \
decode_verifier_maxsz \
/* verifier4 gdlr_verifier */ + \
1 /* gdlr_deviceid_list count */ + \
XDR_QUADLEN ( NFS4_PNFS_GETDEVLIST_MAXNUM * \
NFS4_DEVICEID4_SIZE ) \
/* gdlr_deviceid_list */ + \
1 /* bool gdlr_eof */ )
2010-10-20 08:18:03 +04:00
# define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \
XDR_QUADLEN ( NFS4_DEVICEID4_SIZE ) )
# define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \
1 /* layout type */ + \
1 /* opaque devaddr4 length */ + \
/* devaddr4 payload is read into page */ \
1 /* notification bitmap length */ + \
1 /* notification bitmap */ )
# define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \
encode_stateid_maxsz )
# define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \
decode_stateid_maxsz + \
XDR_QUADLEN ( PNFS_LAYOUT_MAXSIZE ) )
2011-03-23 16:27:54 +03:00
# define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \
2 /* offset */ + \
2 /* length */ + \
1 /* reclaim */ + \
encode_stateid_maxsz + \
1 /* new offset (true) */ + \
2 /* last byte written */ + \
1 /* nt_timechanged (false) */ + \
1 /* layoutupdate4 layout type */ + \
1 /* NULL filelayout layoutupdate4 payload */ )
# define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3)
2011-05-22 20:52:37 +04:00
# define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \
encode_stateid_maxsz + \
1 /* FIXME: opaque lrf_body always empty at the moment */ )
# define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \
1 + decode_stateid_maxsz )
2011-06-02 22:59:07 +04:00
# define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1)
# define decode_secinfo_no_name_maxsz decode_secinfo_maxsz
2011-06-02 22:59:08 +04:00
# define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \
XDR_QUADLEN ( NFS4_STATEID_SIZE ) )
# define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1)
2011-06-02 22:59:09 +04:00
# define encode_free_stateid_maxsz (op_encode_hdr_maxsz + 1 + \
XDR_QUADLEN ( NFS4_STATEID_SIZE ) )
2013-09-10 20:56:29 +04:00
# define decode_free_stateid_maxsz (op_decode_hdr_maxsz)
2009-04-01 17:22:11 +04:00
# else /* CONFIG_NFS_V4_1 */
# define encode_sequence_maxsz 0
# define decode_sequence_maxsz 0
# endif /* CONFIG_NFS_V4_1 */
2005-04-17 02:20:36 +04:00
# define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
# define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
# define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
encode_read_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
decode_read_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
encode_readlink_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
decode_readlink_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
encode_readdir_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
decode_readdir_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
encode_write_maxsz + \
2005-10-28 06:12:44 +04:00
encode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
decode_write_maxsz + \
2005-10-28 06:12:44 +04:00
decode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2012-04-29 18:44:42 +04:00
encode_commit_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2012-04-29 18:44:42 +04:00
decode_commit_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2007-07-02 21:57:28 +04:00
encode_putfh_maxsz + \
encode_open_maxsz + \
2012-09-10 22:00:46 +04:00
encode_access_maxsz + \
2007-07-02 21:57:28 +04:00
encode_getfh_maxsz + \
encode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2007-07-02 21:57:28 +04:00
decode_putfh_maxsz + \
decode_open_maxsz + \
2012-09-10 22:00:46 +04:00
decode_access_maxsz + \
2007-07-02 21:57:28 +04:00
decode_getfh_maxsz + \
decode_getattr_maxsz )
2007-07-18 05:52:42 +04:00
# define NFS4_enc_open_confirm_sz \
( compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_open_confirm_maxsz )
# define NFS4_dec_open_confirm_sz \
( compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_open_confirm_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2007-07-02 21:57:28 +04:00
encode_open_maxsz + \
2012-09-10 22:00:46 +04:00
encode_access_maxsz + \
2007-07-02 21:57:28 +04:00
encode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2007-07-02 21:57:28 +04:00
decode_open_maxsz + \
2012-09-10 22:00:46 +04:00
decode_access_maxsz + \
2007-07-02 21:57:28 +04:00
decode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_open_downgrade_sz \
( compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2007-07-18 05:52:42 +04:00
encode_putfh_maxsz + \
encode_open_downgrade_maxsz + \
encode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_open_downgrade_sz \
( compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2007-07-18 05:52:42 +04:00
decode_putfh_maxsz + \
decode_open_downgrade_maxsz + \
decode_getattr_maxsz )
# define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2007-07-18 05:52:42 +04:00
encode_putfh_maxsz + \
encode_close_maxsz + \
encode_getattr_maxsz )
# define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2007-07-18 05:52:42 +04:00
decode_putfh_maxsz + \
decode_close_maxsz + \
decode_getattr_maxsz )
# define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2007-07-18 05:52:42 +04:00
encode_putfh_maxsz + \
encode_setattr_maxsz + \
encode_getattr_maxsz )
# define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2007-07-18 05:52:42 +04:00
decode_putfh_maxsz + \
decode_setattr_maxsz + \
decode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
encode_fsinfo_maxsz )
# define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
decode_fsinfo_maxsz )
# define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \
encode_renew_maxsz )
# define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \
decode_renew_maxsz )
# define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \
encode_setclientid_maxsz )
# define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \
decode_setclientid_maxsz )
# define NFS4_enc_setclientid_confirm_sz \
( compound_encode_hdr_maxsz + \
2013-03-16 23:55:53 +04:00
encode_setclientid_confirm_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_setclientid_confirm_sz \
( compound_decode_hdr_maxsz + \
2013-03-16 23:55:53 +04:00
decode_setclientid_confirm_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
encode_lock_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
decode_lock_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
encode_lockt_maxsz )
# define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2007-07-18 05:52:42 +04:00
decode_putfh_maxsz + \
decode_lockt_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
encode_locku_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
decode_locku_maxsz )
2010-07-01 20:49:01 +04:00
# define NFS4_enc_release_lockowner_sz \
( compound_encode_hdr_maxsz + \
encode_lockowner_maxsz )
# define NFS4_dec_release_lockowner_sz \
( compound_decode_hdr_maxsz + \
decode_lockowner_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2007-08-11 01:45:11 +04:00
encode_access_maxsz + \
encode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2007-08-11 01:45:11 +04:00
decode_access_maxsz + \
decode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
encode_getattr_maxsz )
# define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
decode_getattr_maxsz )
# define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
encode_lookup_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz )
# define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2007-07-02 21:58:30 +04:00
decode_lookup_maxsz + \
2005-04-17 02:20:36 +04:00
decode_getattr_maxsz + \
decode_getfh_maxsz )
# define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putrootfh_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz )
# define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putrootfh_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz )
# define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2012-04-27 21:48:19 +04:00
encode_remove_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2012-04-27 21:48:19 +04:00
decode_remove_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_putfh_maxsz + \
2012-04-27 21:48:19 +04:00
encode_rename_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_putfh_maxsz + \
2012-04-27 21:48:19 +04:00
decode_rename_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_putfh_maxsz + \
2005-10-28 06:12:42 +04:00
encode_link_maxsz + \
encode_restorefh_maxsz + \
2012-04-27 21:48:17 +04:00
encode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_putfh_maxsz + \
2005-10-28 06:12:42 +04:00
decode_link_maxsz + \
decode_restorefh_maxsz + \
decode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
encode_symlink_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz )
# define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
decode_symlink_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz )
# define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
encode_create_maxsz + \
2005-10-28 06:12:40 +04:00
encode_getfh_maxsz + \
encode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
decode_create_maxsz + \
2005-10-28 06:12:40 +04:00
decode_getfh_maxsz + \
decode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
encode_getattr_maxsz )
# define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
decode_getattr_maxsz )
# define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
encode_statfs_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
decode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
decode_statfs_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2007-02-03 01:47:17 +03:00
encode_putfh_maxsz + \
2005-04-17 02:20:36 +04:00
encode_getattr_maxsz )
# define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2007-02-03 01:47:17 +03:00
decode_putfh_maxsz + \
2005-04-17 02:20:36 +04:00
decode_getattr_maxsz )
# define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-04-17 02:20:36 +04:00
encode_putfh_maxsz + \
2006-01-03 11:55:38 +03:00
encode_delegreturn_maxsz + \
encode_getattr_maxsz )
2005-04-17 02:20:36 +04:00
# define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2006-01-03 11:55:38 +03:00
decode_delegreturn_maxsz + \
decode_getattr_maxsz )
2005-06-22 21:16:22 +04:00
# define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-06-22 21:16:22 +04:00
encode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
encode_getacl_maxsz )
2005-06-22 21:16:22 +04:00
# define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-06-22 21:16:22 +04:00
decode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
decode_getacl_maxsz )
2005-06-22 21:16:22 +04:00
# define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2005-06-22 21:16:22 +04:00
encode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
encode_setacl_maxsz )
2005-06-22 21:16:22 +04:00
# define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2005-06-22 21:16:22 +04:00
decode_putfh_maxsz + \
2007-07-18 05:52:42 +04:00
decode_setacl_maxsz )
2006-06-09 17:34:22 +04:00
# define NFS4_enc_fs_locations_sz \
( compound_encode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
encode_sequence_maxsz + \
2006-06-09 17:34:22 +04:00
encode_putfh_maxsz + \
2007-07-02 21:58:30 +04:00
encode_lookup_maxsz + \
encode_fs_locations_maxsz )
2006-06-09 17:34:22 +04:00
# define NFS4_dec_fs_locations_sz \
( compound_decode_hdr_maxsz + \
2009-04-01 17:22:11 +04:00
decode_sequence_maxsz + \
2006-06-09 17:34:22 +04:00
decode_putfh_maxsz + \
2007-07-02 21:58:30 +04:00
decode_lookup_maxsz + \
decode_fs_locations_maxsz )
2011-03-24 20:12:29 +03:00
# define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_secinfo_maxsz )
# define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_secinfo_maxsz )
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
2012-05-24 21:22:50 +04:00
# define NFS4_enc_bind_conn_to_session_sz \
( compound_encode_hdr_maxsz + \
encode_bind_conn_to_session_maxsz )
# define NFS4_dec_bind_conn_to_session_sz \
( compound_decode_hdr_maxsz + \
decode_bind_conn_to_session_maxsz )
2009-04-01 17:22:29 +04:00
# define NFS4_enc_exchange_id_sz \
( compound_encode_hdr_maxsz + \
encode_exchange_id_maxsz )
# define NFS4_dec_exchange_id_sz \
( compound_decode_hdr_maxsz + \
decode_exchange_id_maxsz )
2009-04-01 17:22:31 +04:00
# define NFS4_enc_create_session_sz \
( compound_encode_hdr_maxsz + \
encode_create_session_maxsz )
# define NFS4_dec_create_session_sz \
( compound_decode_hdr_maxsz + \
decode_create_session_maxsz )
2009-04-01 17:22:34 +04:00
# define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \
encode_destroy_session_maxsz )
# define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \
decode_destroy_session_maxsz )
2012-05-26 01:18:09 +04:00
# define NFS4_enc_destroy_clientid_sz (compound_encode_hdr_maxsz + \
encode_destroy_clientid_maxsz )
# define NFS4_dec_destroy_clientid_sz (compound_decode_hdr_maxsz + \
decode_destroy_clientid_maxsz )
2009-04-01 17:22:36 +04:00
# define NFS4_enc_sequence_sz \
( compound_decode_hdr_maxsz + \
encode_sequence_maxsz )
# define NFS4_dec_sequence_sz \
( compound_decode_hdr_maxsz + \
decode_sequence_maxsz )
2009-04-01 17:22:30 +04:00
# define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putrootfh_maxsz + \
encode_fsinfo_maxsz )
# define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putrootfh_maxsz + \
decode_fsinfo_maxsz )
2009-12-06 00:08:40 +03:00
# define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_reclaim_complete_maxsz )
# define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_reclaim_complete_maxsz )
2011-07-31 04:52:35 +04:00
# define NFS4_enc_getdevicelist_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_getdevicelist_maxsz )
# define NFS4_dec_getdevicelist_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_getdevicelist_maxsz )
2010-10-20 08:18:03 +04:00
# define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_getdeviceinfo_maxsz )
# define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_getdeviceinfo_maxsz )
# define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_layoutget_maxsz )
# define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_layoutget_maxsz )
2011-03-23 16:27:54 +03:00
# define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_layoutcommit_maxsz + \
encode_getattr_maxsz )
# define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_layoutcommit_maxsz + \
decode_getattr_maxsz )
2011-05-22 20:52:37 +04:00
# define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_layoutreturn_maxsz )
# define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_layoutreturn_maxsz )
2011-06-02 22:59:07 +04:00
# define NFS4_enc_secinfo_no_name_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putrootfh_maxsz + \
encode_secinfo_no_name_maxsz )
# define NFS4_dec_secinfo_no_name_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putrootfh_maxsz + \
decode_secinfo_no_name_maxsz )
2011-06-02 22:59:08 +04:00
# define NFS4_enc_test_stateid_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_test_stateid_maxsz )
# define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_test_stateid_maxsz )
2011-06-02 22:59:09 +04:00
# define NFS4_enc_free_stateid_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_free_stateid_maxsz )
# define NFS4_dec_free_stateid_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_free_stateid_maxsz )
2009-12-05 21:36:55 +03:00
const u32 nfs41_maxwrite_overhead = ( ( RPC_MAX_HEADER_WITH_AUTH +
compound_encode_hdr_maxsz +
encode_sequence_maxsz +
encode_putfh_maxsz +
encode_getattr_maxsz ) *
XDR_UNIT ) ;
const u32 nfs41_maxread_overhead = ( ( RPC_MAX_HEADER_WITH_AUTH +
compound_decode_hdr_maxsz +
decode_sequence_maxsz +
decode_putfh_maxsz ) *
XDR_UNIT ) ;
2013-06-26 03:02:53 +04:00
const u32 nfs41_maxgetdevinfo_overhead = ( ( RPC_MAX_REPHEADER_WITH_AUTH +
compound_decode_hdr_maxsz +
decode_sequence_maxsz ) *
XDR_UNIT ) ;
EXPORT_SYMBOL_GPL ( nfs41_maxgetdevinfo_overhead ) ;
2009-04-01 17:22:29 +04:00
# endif /* CONFIG_NFS_V4_1 */
2005-04-17 02:20:36 +04:00
2009-03-11 21:10:26 +03:00
static const umode_t nfs_type2fmt [ ] = {
[ NF4BAD ] = 0 ,
[ NF4REG ] = S_IFREG ,
[ NF4DIR ] = S_IFDIR ,
[ NF4BLK ] = S_IFBLK ,
[ NF4CHR ] = S_IFCHR ,
[ NF4LNK ] = S_IFLNK ,
[ NF4SOCK ] = S_IFSOCK ,
[ NF4FIFO ] = S_IFIFO ,
[ NF4ATTRDIR ] = 0 ,
[ NF4NAMEDATTR ] = 0 ,
2005-04-17 02:20:36 +04:00
} ;
struct compound_hdr {
int32_t status ;
uint32_t nops ;
2008-12-24 00:06:17 +03:00
__be32 * nops_p ;
2005-04-17 02:20:36 +04:00
uint32_t taglen ;
char * tag ;
2009-04-01 17:22:07 +04:00
uint32_t replen ; /* expected reply words */
2009-04-01 17:22:10 +04:00
u32 minorversion ;
2005-04-17 02:20:36 +04:00
} ;
2009-08-14 18:19:25 +04:00
static __be32 * reserve_space ( struct xdr_stream * xdr , size_t nbytes )
{
__be32 * p = xdr_reserve_space ( xdr , nbytes ) ;
BUG_ON ( ! p ) ;
return p ;
}
2005-04-17 02:20:36 +04:00
2012-03-05 03:13:56 +04:00
static void encode_opaque_fixed ( struct xdr_stream * xdr , const void * buf , size_t len )
{
__be32 * p ;
p = xdr_reserve_space ( xdr , len ) ;
xdr_encode_opaque_fixed ( p , buf , len ) ;
}
2005-04-17 02:20:36 +04:00
static void encode_string ( struct xdr_stream * xdr , unsigned int len , const char * str )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2012-03-05 03:13:57 +04:00
p = reserve_space ( xdr , 4 + len ) ;
2005-04-17 02:20:36 +04:00
xdr_encode_opaque ( p , str , len ) ;
}
2012-03-05 03:13:57 +04:00
static void encode_uint32 ( struct xdr_stream * xdr , u32 n )
{
__be32 * p ;
p = reserve_space ( xdr , 4 ) ;
* p = cpu_to_be32 ( n ) ;
}
2012-03-05 20:40:12 +04:00
static void encode_uint64 ( struct xdr_stream * xdr , u64 n )
{
__be32 * p ;
p = reserve_space ( xdr , 8 ) ;
xdr_encode_hyper ( p , n ) ;
}
2012-03-05 03:13:57 +04:00
static void encode_nfs4_seqid ( struct xdr_stream * xdr ,
const struct nfs_seqid * seqid )
{
encode_uint32 ( xdr , seqid - > sequence - > counter ) ;
}
2009-04-01 17:22:07 +04:00
static void encode_compound_hdr ( struct xdr_stream * xdr ,
struct rpc_rqst * req ,
struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2010-07-31 22:29:08 +04:00
struct rpc_auth * auth = req - > rq_cred - > cr_auth ;
2009-04-01 17:22:07 +04:00
/* initialize running count of expected bytes in reply.
* NOTE : the replied tag SHOULD be the same is the one sent ,
* but this is not required as a MUST for the server to do so . */
hdr - > replen = RPC_REPHDRSIZE + auth - > au_rslack + 3 + hdr - > taglen ;
2005-04-17 02:20:36 +04:00
2012-10-15 19:51:21 +04:00
WARN_ON_ONCE ( hdr - > taglen > NFS4_MAXTAGLEN ) ;
2012-03-05 03:13:57 +04:00
encode_string ( xdr , hdr - > taglen , hdr - > tag ) ;
p = reserve_space ( xdr , 8 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( hdr - > minorversion ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops_p = p ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( hdr - > nops ) ;
2008-12-24 00:06:17 +03:00
}
2012-03-05 03:13:57 +04:00
static void encode_op_hdr ( struct xdr_stream * xdr , enum nfs_opnum4 op ,
uint32_t replen ,
struct compound_hdr * hdr )
{
encode_uint32 ( xdr , op ) ;
hdr - > nops + + ;
hdr - > replen + = replen ;
}
2008-12-24 00:06:17 +03:00
static void encode_nops ( struct compound_hdr * hdr )
{
2012-10-15 19:51:21 +04:00
WARN_ON_ONCE ( hdr - > nops > NFS4_MAX_OPS ) ;
2008-12-24 00:06:17 +03:00
* hdr - > nops_p = htonl ( hdr - > nops ) ;
2005-04-17 02:20:36 +04:00
}
2012-03-05 03:13:56 +04:00
static void encode_nfs4_stateid ( struct xdr_stream * xdr , const nfs4_stateid * stateid )
{
2012-03-05 03:13:57 +04:00
encode_opaque_fixed ( xdr , stateid , NFS4_STATEID_SIZE ) ;
2012-03-05 03:13:56 +04:00
}
2005-04-17 02:20:36 +04:00
static void encode_nfs4_verifier ( struct xdr_stream * xdr , const nfs4_verifier * verf )
{
2012-03-05 03:13:56 +04:00
encode_opaque_fixed ( xdr , verf - > data , NFS4_VERIFIER_SIZE ) ;
2005-04-17 02:20:36 +04:00
}
2013-05-22 20:50:44 +04:00
static void encode_attrs ( struct xdr_stream * xdr , const struct iattr * iap ,
const struct nfs4_label * label ,
const struct nfs_server * server )
2005-04-17 02:20:36 +04:00
{
char owner_name [ IDMAP_NAMESZ ] ;
char owner_group [ IDMAP_NAMESZ ] ;
int owner_namelen = 0 ;
int owner_grouplen = 0 ;
2006-10-20 10:28:48 +04:00
__be32 * p ;
2013-07-18 01:09:01 +04:00
unsigned i ;
uint32_t len = 0 ;
uint32_t bmval_len ;
uint32_t bmval [ 3 ] = { 0 } ;
2005-04-17 02:20:36 +04:00
/*
* We reserve enough space to write the entire attribute buffer at once .
* In the worst - case , this would be
2013-05-22 20:50:41 +04:00
* 16 ( bitmap ) + 4 ( attrlen ) + 8 ( size ) + 4 ( mode ) + 4 ( atime ) + 4 ( mtime )
* = 40 bytes , plus any contribution from variable - length fields
2005-06-22 21:16:22 +04:00
* such as owner / group .
2005-04-17 02:20:36 +04:00
*/
2013-07-18 01:09:01 +04:00
if ( iap - > ia_valid & ATTR_SIZE ) {
bmval [ 0 ] | = FATTR4_WORD0_SIZE ;
2005-04-17 02:20:36 +04:00
len + = 8 ;
2013-07-18 01:09:01 +04:00
}
if ( iap - > ia_valid & ATTR_MODE ) {
bmval [ 1 ] | = FATTR4_WORD1_MODE ;
2005-04-17 02:20:36 +04:00
len + = 4 ;
2013-07-18 01:09:01 +04:00
}
2005-04-17 02:20:36 +04:00
if ( iap - > ia_valid & ATTR_UID ) {
2011-02-23 02:44:31 +03:00
owner_namelen = nfs_map_uid_to_name ( server , iap - > ia_uid , owner_name , IDMAP_NAMESZ ) ;
2005-04-17 02:20:36 +04:00
if ( owner_namelen < 0 ) {
2007-09-12 02:01:10 +04:00
dprintk ( " nfs: couldn't resolve uid %d to string \n " ,
2013-02-02 02:22:02 +04:00
from_kuid ( & init_user_ns , iap - > ia_uid ) ) ;
2005-04-17 02:20:36 +04:00
/* XXX */
strcpy ( owner_name , " nobody " ) ;
owner_namelen = sizeof ( " nobody " ) - 1 ;
/* goto out; */
}
2013-07-18 01:09:01 +04:00
bmval [ 1 ] | = FATTR4_WORD1_OWNER ;
2005-04-17 02:20:36 +04:00
len + = 4 + ( XDR_QUADLEN ( owner_namelen ) < < 2 ) ;
}
if ( iap - > ia_valid & ATTR_GID ) {
2011-02-23 02:44:31 +03:00
owner_grouplen = nfs_map_gid_to_group ( server , iap - > ia_gid , owner_group , IDMAP_NAMESZ ) ;
2005-04-17 02:20:36 +04:00
if ( owner_grouplen < 0 ) {
2007-09-12 02:01:10 +04:00
dprintk ( " nfs: couldn't resolve gid %d to string \n " ,
2013-02-02 02:22:02 +04:00
from_kgid ( & init_user_ns , iap - > ia_gid ) ) ;
2005-04-17 02:20:36 +04:00
strcpy ( owner_group , " nobody " ) ;
owner_grouplen = sizeof ( " nobody " ) - 1 ;
/* goto out; */
}
2013-07-18 01:09:01 +04:00
bmval [ 1 ] | = FATTR4_WORD1_OWNER_GROUP ;
2005-04-17 02:20:36 +04:00
len + = 4 + ( XDR_QUADLEN ( owner_grouplen ) < < 2 ) ;
}
2013-07-18 01:09:01 +04:00
if ( iap - > ia_valid & ATTR_ATIME_SET ) {
bmval [ 1 ] | = FATTR4_WORD1_TIME_ACCESS_SET ;
2005-04-17 02:20:36 +04:00
len + = 16 ;
2013-07-18 01:09:01 +04:00
} else if ( iap - > ia_valid & ATTR_ATIME ) {
bmval [ 1 ] | = FATTR4_WORD1_TIME_ACCESS_SET ;
2005-04-17 02:20:36 +04:00
len + = 4 ;
2013-07-18 01:09:01 +04:00
}
if ( iap - > ia_valid & ATTR_MTIME_SET ) {
bmval [ 1 ] | = FATTR4_WORD1_TIME_MODIFY_SET ;
2005-04-17 02:20:36 +04:00
len + = 16 ;
2013-07-18 01:09:01 +04:00
} else if ( iap - > ia_valid & ATTR_MTIME ) {
bmval [ 1 ] | = FATTR4_WORD1_TIME_MODIFY_SET ;
2005-04-17 02:20:36 +04:00
len + = 4 ;
2013-07-18 01:09:01 +04:00
}
2013-07-18 00:43:16 +04:00
if ( label ) {
len + = 4 + 4 + 4 + ( XDR_QUADLEN ( label - > len ) < < 2 ) ;
2013-07-18 01:09:01 +04:00
bmval [ 2 ] | = FATTR4_WORD2_SECURITY_LABEL ;
2013-07-18 00:43:16 +04:00
}
2013-07-18 01:09:01 +04:00
if ( bmval [ 2 ] ! = 0 )
bmval_len = 3 ;
else if ( bmval [ 1 ] ! = 0 )
bmval_len = 2 ;
else
bmval_len = 1 ;
p = reserve_space ( xdr , 4 + ( bmval_len < < 2 ) + 4 + len ) ;
2005-04-17 02:20:36 +04:00
2013-07-18 00:43:16 +04:00
* p + + = cpu_to_be32 ( bmval_len ) ;
2013-07-18 01:09:01 +04:00
for ( i = 0 ; i < bmval_len ; i + + )
* p + + = cpu_to_be32 ( bmval [ i ] ) ;
* p + + = cpu_to_be32 ( len ) ;
2005-04-17 02:20:36 +04:00
2013-07-18 01:09:01 +04:00
if ( bmval [ 0 ] & FATTR4_WORD0_SIZE )
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , iap - > ia_size ) ;
2013-07-18 01:09:01 +04:00
if ( bmval [ 1 ] & FATTR4_WORD1_MODE )
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( iap - > ia_mode & S_IALLUGO ) ;
2013-07-18 01:09:01 +04:00
if ( bmval [ 1 ] & FATTR4_WORD1_OWNER )
2009-08-14 18:19:34 +04:00
p = xdr_encode_opaque ( p , owner_name , owner_namelen ) ;
2013-07-18 01:09:01 +04:00
if ( bmval [ 1 ] & FATTR4_WORD1_OWNER_GROUP )
2009-08-14 18:19:34 +04:00
p = xdr_encode_opaque ( p , owner_group , owner_grouplen ) ;
2013-07-18 01:09:01 +04:00
if ( bmval [ 1 ] & FATTR4_WORD1_TIME_ACCESS_SET ) {
if ( iap - > ia_valid & ATTR_ATIME_SET ) {
* p + + = cpu_to_be32 ( NFS4_SET_TO_CLIENT_TIME ) ;
p = xdr_encode_hyper ( p , ( s64 ) iap - > ia_atime . tv_sec ) ;
* p + + = cpu_to_be32 ( iap - > ia_atime . tv_nsec ) ;
} else
* p + + = cpu_to_be32 ( NFS4_SET_TO_SERVER_TIME ) ;
2005-04-17 02:20:36 +04:00
}
2013-07-18 01:09:01 +04:00
if ( bmval [ 1 ] & FATTR4_WORD1_TIME_MODIFY_SET ) {
if ( iap - > ia_valid & ATTR_MTIME_SET ) {
* p + + = cpu_to_be32 ( NFS4_SET_TO_CLIENT_TIME ) ;
p = xdr_encode_hyper ( p , ( s64 ) iap - > ia_mtime . tv_sec ) ;
* p + + = cpu_to_be32 ( iap - > ia_mtime . tv_nsec ) ;
} else
* p + + = cpu_to_be32 ( NFS4_SET_TO_SERVER_TIME ) ;
2005-04-17 02:20:36 +04:00
}
2013-07-18 01:09:01 +04:00
if ( bmval [ 2 ] & FATTR4_WORD2_SECURITY_LABEL ) {
2013-05-22 20:50:44 +04:00
* p + + = cpu_to_be32 ( label - > lfs ) ;
* p + + = cpu_to_be32 ( label - > pi ) ;
* p + + = cpu_to_be32 ( label - > len ) ;
p = xdr_encode_opaque_fixed ( p , label - > label , label - > len ) ;
}
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
/* out: */
}
2008-12-24 00:06:18 +03:00
static void encode_access ( struct xdr_stream * xdr , u32 access , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_ACCESS , decode_access_maxsz , hdr ) ;
encode_uint32 ( xdr , access ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_close ( struct xdr_stream * xdr , const struct nfs_closeargs * arg , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_CLOSE , decode_close_maxsz , hdr ) ;
2012-03-05 03:13:57 +04:00
encode_nfs4_seqid ( xdr , arg - > seqid ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , arg - > stateid ) ;
2005-04-17 02:20:36 +04:00
}
2012-04-20 22:47:39 +04:00
static void encode_commit ( struct xdr_stream * xdr , const struct nfs_commitargs * args , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2008-12-24 00:06:15 +03:00
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_COMMIT , decode_commit_maxsz , hdr ) ;
p = reserve_space ( xdr , 12 ) ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , args - > offset ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( args - > count ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_create ( struct xdr_stream * xdr , const struct nfs4_create_arg * create , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2008-12-24 00:06:15 +03:00
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_CREATE , decode_create_maxsz , hdr ) ;
encode_uint32 ( xdr , create - > ftype ) ;
2005-04-17 02:20:36 +04:00
switch ( create - > ftype ) {
case NF4LNK :
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( create - > u . symlink . len ) ;
2006-08-23 04:06:23 +04:00
xdr_write_pages ( xdr , create - > u . symlink . pages , 0 , create - > u . symlink . len ) ;
2005-04-17 02:20:36 +04:00
break ;
case NF4BLK : case NF4CHR :
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 8 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( create - > u . device . specdata1 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( create - > u . device . specdata2 ) ;
2005-04-17 02:20:36 +04:00
break ;
default :
break ;
}
2009-08-14 18:19:34 +04:00
encode_string ( xdr , create - > name - > len , create - > name - > name ) ;
2013-05-22 20:50:44 +04:00
encode_attrs ( xdr , create - > attrs , create - > label , create - > server ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_getattr_one ( struct xdr_stream * xdr , uint32_t bitmap , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_GETATTR , decode_getattr_maxsz , hdr ) ;
p = reserve_space ( xdr , 8 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( 1 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( bitmap ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_getattr_two ( struct xdr_stream * xdr , uint32_t bm0 , uint32_t bm1 , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_GETATTR , decode_getattr_maxsz , hdr ) ;
p = reserve_space ( xdr , 12 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( 2 ) ;
* p + + = cpu_to_be32 ( bm0 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( bm1 ) ;
2005-04-17 02:20:36 +04:00
}
2011-07-31 04:52:37 +04:00
static void
encode_getattr_three ( struct xdr_stream * xdr ,
uint32_t bm0 , uint32_t bm1 , uint32_t bm2 ,
struct compound_hdr * hdr )
{
__be32 * p ;
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_GETATTR , decode_getattr_maxsz , hdr ) ;
2011-07-31 04:52:37 +04:00
if ( bm2 ) {
p = reserve_space ( xdr , 16 ) ;
* p + + = cpu_to_be32 ( 3 ) ;
* p + + = cpu_to_be32 ( bm0 ) ;
* p + + = cpu_to_be32 ( bm1 ) ;
* p = cpu_to_be32 ( bm2 ) ;
} else if ( bm1 ) {
p = reserve_space ( xdr , 12 ) ;
* p + + = cpu_to_be32 ( 2 ) ;
* p + + = cpu_to_be32 ( bm0 ) ;
* p = cpu_to_be32 ( bm1 ) ;
} else {
p = reserve_space ( xdr , 8 ) ;
* p + + = cpu_to_be32 ( 1 ) ;
* p = cpu_to_be32 ( bm0 ) ;
}
}
2008-12-24 00:06:18 +03:00
static void encode_getfattr ( struct xdr_stream * xdr , const u32 * bitmask , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2013-05-22 20:50:41 +04:00
encode_getattr_three ( xdr , bitmask [ 0 ] & nfs4_fattr_bitmap [ 0 ] ,
bitmask [ 1 ] & nfs4_fattr_bitmap [ 1 ] ,
bitmask [ 2 ] & nfs4_fattr_bitmap [ 2 ] ,
hdr ) ;
2005-04-17 02:20:36 +04:00
}
2012-05-23 13:02:34 +04:00
static void encode_getfattr_open ( struct xdr_stream * xdr , const u32 * bitmask ,
2012-06-05 17:16:47 +04:00
const u32 * open_bitmap ,
2012-05-23 13:02:34 +04:00
struct compound_hdr * hdr )
{
encode_getattr_three ( xdr ,
2012-06-05 17:16:47 +04:00
bitmask [ 0 ] & open_bitmap [ 0 ] ,
bitmask [ 1 ] & open_bitmap [ 1 ] ,
bitmask [ 2 ] & open_bitmap [ 2 ] ,
2012-05-23 13:02:34 +04:00
hdr ) ;
}
2008-12-24 00:06:18 +03:00
static void encode_fsinfo ( struct xdr_stream * xdr , const u32 * bitmask , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2011-07-31 04:52:37 +04:00
encode_getattr_three ( xdr ,
bitmask [ 0 ] & nfs4_fsinfo_bitmap [ 0 ] ,
bitmask [ 1 ] & nfs4_fsinfo_bitmap [ 1 ] ,
bitmask [ 2 ] & nfs4_fsinfo_bitmap [ 2 ] ,
hdr ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_fs_locations ( struct xdr_stream * xdr , const u32 * bitmask , struct compound_hdr * hdr )
2006-06-09 17:34:25 +04:00
{
2008-12-24 00:06:18 +03:00
encode_getattr_two ( xdr , bitmask [ 0 ] & nfs4_fs_locations_bitmap [ 0 ] ,
bitmask [ 1 ] & nfs4_fs_locations_bitmap [ 1 ] , hdr ) ;
2006-06-09 17:34:25 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_getfh ( struct xdr_stream * xdr , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_GETFH , decode_getfh_maxsz , hdr ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_link ( struct xdr_stream * xdr , const struct qstr * name , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_LINK , decode_link_maxsz , hdr ) ;
2012-03-05 03:13:57 +04:00
encode_string ( xdr , name - > len , name - > name ) ;
2005-04-17 02:20:36 +04:00
}
2006-01-03 11:55:16 +03:00
static inline int nfs4_lock_type ( struct file_lock * fl , int block )
{
2012-07-23 23:49:56 +04:00
if ( fl - > fl_type = = F_RDLCK )
2006-01-03 11:55:16 +03:00
return block ? NFS4_READW_LT : NFS4_READ_LT ;
return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT ;
}
static inline uint64_t nfs4_lock_length ( struct file_lock * fl )
{
if ( fl - > fl_end = = OFFSET_MAX )
return ~ ( uint64_t ) 0 ;
return fl - > fl_end - fl - > fl_start + 1 ;
}
2010-06-26 02:11:43 +04:00
static void encode_lockowner ( struct xdr_stream * xdr , const struct nfs_lowner * lowner )
{
__be32 * p ;
2010-12-21 18:45:27 +03:00
p = reserve_space ( xdr , 32 ) ;
2010-06-26 02:11:43 +04:00
p = xdr_encode_hyper ( p , lowner - > clientid ) ;
2010-12-21 18:45:27 +03:00
* p + + = cpu_to_be32 ( 20 ) ;
2010-06-26 02:11:43 +04:00
p = xdr_encode_opaque_fixed ( p , " lock id: " , 8 ) ;
2010-12-21 18:45:27 +03:00
* p + + = cpu_to_be32 ( lowner - > s_dev ) ;
2010-06-26 02:11:43 +04:00
xdr_encode_hyper ( p , lowner - > id ) ;
}
2005-04-17 02:20:36 +04:00
/*
* opcode , type , reclaim , offset , length , new_lock_owner = 32
* open_seqid , open_stateid , lock_seqid , lock_owner . clientid , lock_owner . id = 40
*/
2008-12-24 00:06:18 +03:00
static void encode_lock ( struct xdr_stream * xdr , const struct nfs_lock_args * args , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_LOCK , decode_lock_maxsz , hdr ) ;
p = reserve_space ( xdr , 28 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( nfs4_lock_type ( args - > fl , args - > block ) ) ;
* p + + = cpu_to_be32 ( args - > reclaim ) ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , args - > fl - > fl_start ) ;
p = xdr_encode_hyper ( p , nfs4_lock_length ( args - > fl ) ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( args - > new_lock_owner ) ;
2006-01-03 11:55:16 +03:00
if ( args - > new_lock_owner ) {
2012-03-05 03:13:57 +04:00
encode_nfs4_seqid ( xdr , args - > open_seqid ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , args - > open_stateid ) ;
2012-03-05 03:13:57 +04:00
encode_nfs4_seqid ( xdr , args - > lock_seqid ) ;
2010-06-26 02:11:43 +04:00
encode_lockowner ( xdr , & args - > lock_owner ) ;
2005-04-17 02:20:36 +04:00
}
else {
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , args - > lock_stateid ) ;
2012-03-05 03:13:57 +04:00
encode_nfs4_seqid ( xdr , args - > lock_seqid ) ;
2005-04-17 02:20:36 +04:00
}
}
2008-12-24 00:06:18 +03:00
static void encode_lockt ( struct xdr_stream * xdr , const struct nfs_lockt_args * args , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_LOCKT , decode_lockt_maxsz , hdr ) ;
p = reserve_space ( xdr , 20 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( nfs4_lock_type ( args - > fl , 0 ) ) ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , args - > fl - > fl_start ) ;
p = xdr_encode_hyper ( p , nfs4_lock_length ( args - > fl ) ) ;
2010-06-26 02:11:43 +04:00
encode_lockowner ( xdr , & args - > lock_owner ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_locku ( struct xdr_stream * xdr , const struct nfs_locku_args * args , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_LOCKU , decode_locku_maxsz , hdr ) ;
encode_uint32 ( xdr , nfs4_lock_type ( args - > fl , 0 ) ) ;
2012-03-05 03:13:57 +04:00
encode_nfs4_seqid ( xdr , args - > seqid ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , args - > stateid ) ;
p = reserve_space ( xdr , 16 ) ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , args - > fl - > fl_start ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_hyper ( p , nfs4_lock_length ( args - > fl ) ) ;
2005-04-17 02:20:36 +04:00
}
2010-07-01 20:49:01 +04:00
static void encode_release_lockowner ( struct xdr_stream * xdr , const struct nfs_lowner * lowner , struct compound_hdr * hdr )
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_RELEASE_LOCKOWNER , decode_release_lockowner_maxsz , hdr ) ;
2010-07-01 20:49:01 +04:00
encode_lockowner ( xdr , lowner ) ;
}
2008-12-24 00:06:18 +03:00
static void encode_lookup ( struct xdr_stream * xdr , const struct qstr * name , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_LOOKUP , decode_lookup_maxsz , hdr ) ;
2012-03-05 03:13:57 +04:00
encode_string ( xdr , name - > len , name - > name ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-23 23:21:56 +03:00
static void encode_share_access ( struct xdr_stream * xdr , fmode_t fmode )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 8 ) ;
2008-12-23 23:21:56 +03:00
switch ( fmode & ( FMODE_READ | FMODE_WRITE ) ) {
2008-12-24 00:06:15 +03:00
case FMODE_READ :
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( NFS4_SHARE_ACCESS_READ ) ;
2008-12-24 00:06:15 +03:00
break ;
case FMODE_WRITE :
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( NFS4_SHARE_ACCESS_WRITE ) ;
2008-12-24 00:06:15 +03:00
break ;
case FMODE_READ | FMODE_WRITE :
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( NFS4_SHARE_ACCESS_BOTH ) ;
2008-12-24 00:06:15 +03:00
break ;
default :
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( 0 ) ;
2005-04-17 02:20:36 +04:00
}
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( 0 ) ; /* for linux, share_deny = 0 always */
2005-04-17 02:20:36 +04:00
}
static inline void encode_openhdr ( struct xdr_stream * xdr , const struct nfs_openargs * arg )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
/*
* opcode 4 , seqid 4 , share_access 4 , share_deny 4 , clientid 8 , ownerlen 4 ,
* owner 4 = 32
*/
2012-03-05 03:13:57 +04:00
encode_nfs4_seqid ( xdr , arg - > seqid ) ;
2008-12-23 23:21:56 +03:00
encode_share_access ( xdr , arg - > fmode ) ;
2012-04-21 03:24:51 +04:00
p = reserve_space ( xdr , 36 ) ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , arg - > clientid ) ;
2012-04-21 03:24:51 +04:00
* p + + = cpu_to_be32 ( 24 ) ;
2009-08-14 18:19:06 +04:00
p = xdr_encode_opaque_fixed ( p , " open id: " , 8 ) ;
2010-12-21 18:45:27 +03:00
* p + + = cpu_to_be32 ( arg - > server - > s_dev ) ;
2012-04-21 03:24:51 +04:00
* p + + = cpu_to_be32 ( arg - > id . uniquifier ) ;
xdr_encode_hyper ( p , arg - > id . create_time ) ;
2005-04-17 02:20:36 +04:00
}
static inline void encode_createmode ( struct xdr_stream * xdr , const struct nfs_openargs * arg )
{
2013-04-17 02:42:34 +04:00
struct iattr dummy ;
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 ) ;
2013-04-17 02:42:34 +04:00
switch ( arg - > createmode ) {
case NFS4_CREATE_UNCHECKED :
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( NFS4_CREATE_UNCHECKED ) ;
2013-05-22 20:50:44 +04:00
encode_attrs ( xdr , arg - > u . attrs , arg - > label , arg - > server ) ;
2008-12-24 00:06:15 +03:00
break ;
2013-04-17 02:42:34 +04:00
case NFS4_CREATE_GUARDED :
* p = cpu_to_be32 ( NFS4_CREATE_GUARDED ) ;
2013-05-22 20:50:44 +04:00
encode_attrs ( xdr , arg - > u . attrs , arg - > label , arg - > server ) ;
2013-04-17 02:42:34 +04:00
break ;
case NFS4_CREATE_EXCLUSIVE :
* p = cpu_to_be32 ( NFS4_CREATE_EXCLUSIVE ) ;
encode_nfs4_verifier ( xdr , & arg - > u . verifier ) ;
break ;
case NFS4_CREATE_EXCLUSIVE4_1 :
* p = cpu_to_be32 ( NFS4_CREATE_EXCLUSIVE4_1 ) ;
encode_nfs4_verifier ( xdr , & arg - > u . verifier ) ;
dummy . ia_valid = 0 ;
2013-05-22 20:50:44 +04:00
encode_attrs ( xdr , & dummy , arg - > label , arg - > server ) ;
2005-04-17 02:20:36 +04:00
}
}
static void encode_opentype ( struct xdr_stream * xdr , const struct nfs_openargs * arg )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 ) ;
2005-04-17 02:20:36 +04:00
switch ( arg - > open_flags & O_CREAT ) {
2008-12-24 00:06:15 +03:00
case 0 :
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( NFS4_OPEN_NOCREATE ) ;
2008-12-24 00:06:15 +03:00
break ;
default :
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( NFS4_OPEN_CREATE ) ;
2008-12-24 00:06:15 +03:00
encode_createmode ( xdr , arg ) ;
2005-04-17 02:20:36 +04:00
}
}
2008-12-23 23:21:53 +03:00
static inline void encode_delegation_type ( struct xdr_stream * xdr , fmode_t delegation_type )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 ) ;
2005-04-17 02:20:36 +04:00
switch ( delegation_type ) {
2008-12-24 00:06:15 +03:00
case 0 :
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( NFS4_OPEN_DELEGATE_NONE ) ;
2008-12-24 00:06:15 +03:00
break ;
case FMODE_READ :
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( NFS4_OPEN_DELEGATE_READ ) ;
2008-12-24 00:06:15 +03:00
break ;
case FMODE_WRITE | FMODE_READ :
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( NFS4_OPEN_DELEGATE_WRITE ) ;
2008-12-24 00:06:15 +03:00
break ;
default :
BUG ( ) ;
2005-04-17 02:20:36 +04:00
}
}
static inline void encode_claim_null ( struct xdr_stream * xdr , const struct qstr * name )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( NFS4_OPEN_CLAIM_NULL ) ;
2005-04-17 02:20:36 +04:00
encode_string ( xdr , name - > len , name - > name ) ;
}
2008-12-23 23:21:53 +03:00
static inline void encode_claim_previous ( struct xdr_stream * xdr , fmode_t type )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( NFS4_OPEN_CLAIM_PREVIOUS ) ;
2005-04-17 02:20:36 +04:00
encode_delegation_type ( xdr , type ) ;
}
static inline void encode_claim_delegate_cur ( struct xdr_stream * xdr , const struct qstr * name , const nfs4_stateid * stateid )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2012-03-05 03:13:56 +04:00
p = reserve_space ( xdr , 4 ) ;
* p = cpu_to_be32 ( NFS4_OPEN_CLAIM_DELEGATE_CUR ) ;
encode_nfs4_stateid ( xdr , stateid ) ;
2005-04-17 02:20:36 +04:00
encode_string ( xdr , name - > len , name - > name ) ;
}
2013-03-15 23:39:06 +04:00
static inline void encode_claim_fh ( struct xdr_stream * xdr )
{
__be32 * p ;
p = reserve_space ( xdr , 4 ) ;
* p = cpu_to_be32 ( NFS4_OPEN_CLAIM_FH ) ;
}
static inline void encode_claim_delegate_cur_fh ( struct xdr_stream * xdr , const nfs4_stateid * stateid )
{
__be32 * p ;
p = reserve_space ( xdr , 4 ) ;
* p = cpu_to_be32 ( NFS4_OPEN_CLAIM_DELEG_CUR_FH ) ;
encode_nfs4_stateid ( xdr , stateid ) ;
}
2008-12-24 00:06:18 +03:00
static void encode_open ( struct xdr_stream * xdr , const struct nfs_openargs * arg , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_OPEN , decode_open_maxsz , hdr ) ;
2005-04-17 02:20:36 +04:00
encode_openhdr ( xdr , arg ) ;
encode_opentype ( xdr , arg ) ;
switch ( arg - > claim ) {
2008-12-24 00:06:15 +03:00
case NFS4_OPEN_CLAIM_NULL :
encode_claim_null ( xdr , arg - > name ) ;
break ;
case NFS4_OPEN_CLAIM_PREVIOUS :
encode_claim_previous ( xdr , arg - > u . delegation_type ) ;
break ;
case NFS4_OPEN_CLAIM_DELEGATE_CUR :
encode_claim_delegate_cur ( xdr , arg - > name , & arg - > u . delegation ) ;
break ;
2013-03-15 23:39:06 +04:00
case NFS4_OPEN_CLAIM_FH :
encode_claim_fh ( xdr ) ;
break ;
case NFS4_OPEN_CLAIM_DELEG_CUR_FH :
encode_claim_delegate_cur_fh ( xdr , & arg - > u . delegation ) ;
break ;
2008-12-24 00:06:15 +03:00
default :
BUG ( ) ;
2005-04-17 02:20:36 +04:00
}
}
2008-12-24 00:06:18 +03:00
static void encode_open_confirm ( struct xdr_stream * xdr , const struct nfs_open_confirmargs * arg , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_OPEN_CONFIRM , decode_open_confirm_maxsz , hdr ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , arg - > stateid ) ;
2012-03-05 03:13:57 +04:00
encode_nfs4_seqid ( xdr , arg - > seqid ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_open_downgrade ( struct xdr_stream * xdr , const struct nfs_closeargs * arg , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_OPEN_DOWNGRADE , decode_open_downgrade_maxsz , hdr ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , arg - > stateid ) ;
2012-03-05 03:13:57 +04:00
encode_nfs4_seqid ( xdr , arg - > seqid ) ;
2008-12-23 23:21:56 +03:00
encode_share_access ( xdr , arg - > fmode ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void
2008-12-24 00:06:17 +03:00
encode_putfh ( struct xdr_stream * xdr , const struct nfs_fh * fh , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_PUTFH , decode_putfh_maxsz , hdr ) ;
2012-03-05 03:13:57 +04:00
encode_string ( xdr , fh - > size , fh - > data ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_putrootfh ( struct xdr_stream * xdr , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_PUTROOTFH , decode_putrootfh_maxsz , hdr ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_read ( struct xdr_stream * xdr , const struct nfs_readargs * args , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_READ , decode_read_maxsz , hdr ) ;
2013-03-17 23:52:00 +04:00
encode_nfs4_stateid ( xdr , & args - > stateid ) ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 12 ) ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , args - > offset ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( args - > count ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_readdir ( struct xdr_stream * xdr , const struct nfs4_readdir_arg * readdir , struct rpc_rqst * req , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2013-05-22 20:50:44 +04:00
uint32_t attrs [ 3 ] = {
2011-04-27 21:47:52 +04:00
FATTR4_WORD0_RDATTR_ERROR ,
FATTR4_WORD1_MOUNTED_ON_FILEID ,
} ;
2010-10-24 20:11:42 +04:00
uint32_t dircount = readdir - > count > > 1 ;
2012-03-03 02:14:31 +04:00
__be32 * p , verf [ 2 ] ;
2005-04-17 02:20:36 +04:00
NFS: Readdir plus in v4
By requsting more attributes during a readdir, we can mimic the readdir plus
operation that was in NFSv3.
To test, I ran the command `ls -lU --color=none` on directories with various
numbers of files. Without readdir plus, I see this:
n files | 100 | 1,000 | 10,000 | 100,000 | 1,000,000
--------+-----------+-----------+-----------+-----------+----------
real | 0m00.153s | 0m00.589s | 0m05.601s | 0m56.691s | 9m59.128s
user | 0m00.007s | 0m00.007s | 0m00.077s | 0m00.703s | 0m06.800s
sys | 0m00.010s | 0m00.070s | 0m00.633s | 0m06.423s | 1m10.005s
access | 3 | 1 | 1 | 4 | 31
getattr | 2 | 1 | 1 | 1 | 1
lookup | 104 | 1,003 | 10,003 | 100,003 | 1,000,003
readdir | 2 | 16 | 158 | 1,575 | 15,749
total | 111 | 1,021 | 10,163 | 101,583 | 1,015,784
With readdir plus enabled, I see this:
n files | 100 | 1,000 | 10,000 | 100,000 | 1,000,000
--------+-----------+-----------+-----------+-----------+----------
real | 0m00.115s | 0m00.206s | 0m01.079s | 0m12.521s | 2m07.528s
user | 0m00.003s | 0m00.003s | 0m00.040s | 0m00.290s | 0m03.296s
sys | 0m00.007s | 0m00.020s | 0m00.120s | 0m01.357s | 0m17.556s
access | 3 | 1 | 1 | 1 | 7
getattr | 2 | 1 | 1 | 1 | 1
lookup | 4 | 3 | 3 | 3 | 3
readdir | 6 | 62 | 630 | 6,300 | 62,993
total | 15 | 67 | 635 | 6,305 | 63,004
Readdir plus disabled has about a 16x increase in the number of rpc calls and
is 4 - 5 times slower on large directories.
Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
2010-10-22 00:33:18 +04:00
if ( readdir - > plus ) {
attrs [ 0 ] | = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE |
2011-04-27 21:47:52 +04:00
FATTR4_WORD0_FSID | FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FILEID ;
NFS: Readdir plus in v4
By requsting more attributes during a readdir, we can mimic the readdir plus
operation that was in NFSv3.
To test, I ran the command `ls -lU --color=none` on directories with various
numbers of files. Without readdir plus, I see this:
n files | 100 | 1,000 | 10,000 | 100,000 | 1,000,000
--------+-----------+-----------+-----------+-----------+----------
real | 0m00.153s | 0m00.589s | 0m05.601s | 0m56.691s | 9m59.128s
user | 0m00.007s | 0m00.007s | 0m00.077s | 0m00.703s | 0m06.800s
sys | 0m00.010s | 0m00.070s | 0m00.633s | 0m06.423s | 1m10.005s
access | 3 | 1 | 1 | 4 | 31
getattr | 2 | 1 | 1 | 1 | 1
lookup | 104 | 1,003 | 10,003 | 100,003 | 1,000,003
readdir | 2 | 16 | 158 | 1,575 | 15,749
total | 111 | 1,021 | 10,163 | 101,583 | 1,015,784
With readdir plus enabled, I see this:
n files | 100 | 1,000 | 10,000 | 100,000 | 1,000,000
--------+-----------+-----------+-----------+-----------+----------
real | 0m00.115s | 0m00.206s | 0m01.079s | 0m12.521s | 2m07.528s
user | 0m00.003s | 0m00.003s | 0m00.040s | 0m00.290s | 0m03.296s
sys | 0m00.007s | 0m00.020s | 0m00.120s | 0m01.357s | 0m17.556s
access | 3 | 1 | 1 | 1 | 7
getattr | 2 | 1 | 1 | 1 | 1
lookup | 4 | 3 | 3 | 3 | 3
readdir | 6 | 62 | 630 | 6,300 | 62,993
total | 15 | 67 | 635 | 6,305 | 63,004
Readdir plus disabled has about a 16x increase in the number of rpc calls and
is 4 - 5 times slower on large directories.
Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
2010-10-22 00:33:18 +04:00
attrs [ 1 ] | = FATTR4_WORD1_MODE | FATTR4_WORD1_NUMLINKS | FATTR4_WORD1_OWNER |
FATTR4_WORD1_OWNER_GROUP | FATTR4_WORD1_RAWDEV |
FATTR4_WORD1_SPACE_USED | FATTR4_WORD1_TIME_ACCESS |
FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY ;
2010-10-24 20:11:42 +04:00
dircount > > = 1 ;
NFS: Readdir plus in v4
By requsting more attributes during a readdir, we can mimic the readdir plus
operation that was in NFSv3.
To test, I ran the command `ls -lU --color=none` on directories with various
numbers of files. Without readdir plus, I see this:
n files | 100 | 1,000 | 10,000 | 100,000 | 1,000,000
--------+-----------+-----------+-----------+-----------+----------
real | 0m00.153s | 0m00.589s | 0m05.601s | 0m56.691s | 9m59.128s
user | 0m00.007s | 0m00.007s | 0m00.077s | 0m00.703s | 0m06.800s
sys | 0m00.010s | 0m00.070s | 0m00.633s | 0m06.423s | 1m10.005s
access | 3 | 1 | 1 | 4 | 31
getattr | 2 | 1 | 1 | 1 | 1
lookup | 104 | 1,003 | 10,003 | 100,003 | 1,000,003
readdir | 2 | 16 | 158 | 1,575 | 15,749
total | 111 | 1,021 | 10,163 | 101,583 | 1,015,784
With readdir plus enabled, I see this:
n files | 100 | 1,000 | 10,000 | 100,000 | 1,000,000
--------+-----------+-----------+-----------+-----------+----------
real | 0m00.115s | 0m00.206s | 0m01.079s | 0m12.521s | 2m07.528s
user | 0m00.003s | 0m00.003s | 0m00.040s | 0m00.290s | 0m03.296s
sys | 0m00.007s | 0m00.020s | 0m00.120s | 0m01.357s | 0m17.556s
access | 3 | 1 | 1 | 1 | 7
getattr | 2 | 1 | 1 | 1 | 1
lookup | 4 | 3 | 3 | 3 | 3
readdir | 6 | 62 | 630 | 6,300 | 62,993
total | 15 | 67 | 635 | 6,305 | 63,004
Readdir plus disabled has about a 16x increase in the number of rpc calls and
is 4 - 5 times slower on large directories.
Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
2010-10-22 00:33:18 +04:00
}
2011-04-27 21:47:52 +04:00
/* Use mounted_on_fileid only if the server supports it */
if ( ! ( readdir - > bitmask [ 1 ] & FATTR4_WORD1_MOUNTED_ON_FILEID ) )
attrs [ 0 ] | = FATTR4_WORD0_FILEID ;
NFS: Readdir plus in v4
By requsting more attributes during a readdir, we can mimic the readdir plus
operation that was in NFSv3.
To test, I ran the command `ls -lU --color=none` on directories with various
numbers of files. Without readdir plus, I see this:
n files | 100 | 1,000 | 10,000 | 100,000 | 1,000,000
--------+-----------+-----------+-----------+-----------+----------
real | 0m00.153s | 0m00.589s | 0m05.601s | 0m56.691s | 9m59.128s
user | 0m00.007s | 0m00.007s | 0m00.077s | 0m00.703s | 0m06.800s
sys | 0m00.010s | 0m00.070s | 0m00.633s | 0m06.423s | 1m10.005s
access | 3 | 1 | 1 | 4 | 31
getattr | 2 | 1 | 1 | 1 | 1
lookup | 104 | 1,003 | 10,003 | 100,003 | 1,000,003
readdir | 2 | 16 | 158 | 1,575 | 15,749
total | 111 | 1,021 | 10,163 | 101,583 | 1,015,784
With readdir plus enabled, I see this:
n files | 100 | 1,000 | 10,000 | 100,000 | 1,000,000
--------+-----------+-----------+-----------+-----------+----------
real | 0m00.115s | 0m00.206s | 0m01.079s | 0m12.521s | 2m07.528s
user | 0m00.003s | 0m00.003s | 0m00.040s | 0m00.290s | 0m03.296s
sys | 0m00.007s | 0m00.020s | 0m00.120s | 0m01.357s | 0m17.556s
access | 3 | 1 | 1 | 1 | 7
getattr | 2 | 1 | 1 | 1 | 1
lookup | 4 | 3 | 3 | 3 | 3
readdir | 6 | 62 | 630 | 6,300 | 62,993
total | 15 | 67 | 635 | 6,305 | 63,004
Readdir plus disabled has about a 16x increase in the number of rpc calls and
is 4 - 5 times slower on large directories.
Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
2010-10-22 00:33:18 +04:00
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_READDIR , decode_readdir_maxsz , hdr ) ;
2012-03-05 20:40:12 +04:00
encode_uint64 ( xdr , readdir - > cookie ) ;
2012-03-03 02:14:31 +04:00
encode_nfs4_verifier ( xdr , & readdir - > verifier ) ;
2013-05-22 20:50:44 +04:00
p = reserve_space ( xdr , encode_readdir_space ) ;
2010-10-24 20:11:42 +04:00
* p + + = cpu_to_be32 ( dircount ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( readdir - > count ) ;
2013-05-22 20:50:44 +04:00
* p + + = cpu_to_be32 ( encode_readdir_bitmask_sz ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( attrs [ 0 ] & readdir - > bitmask [ 0 ] ) ;
2013-05-22 20:50:44 +04:00
* p = cpu_to_be32 ( attrs [ 1 ] & readdir - > bitmask [ 1 ] ) ;
if ( encode_readdir_bitmask_sz > 2 ) {
if ( hdr - > minorversion > 1 )
attrs [ 2 ] | = FATTR4_WORD2_SECURITY_LABEL ;
p + + , * p + + = cpu_to_be32 ( attrs [ 2 ] & readdir - > bitmask [ 2 ] ) ;
}
2012-03-03 02:14:31 +04:00
memcpy ( verf , readdir - > verifier . data , sizeof ( verf ) ) ;
2013-05-22 20:50:44 +04:00
dprintk ( " %s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x \n " ,
2008-04-02 16:21:15 +04:00
__func__ ,
2005-06-22 21:16:39 +04:00
( unsigned long long ) readdir - > cookie ,
2012-03-03 02:14:31 +04:00
verf [ 0 ] , verf [ 1 ] ,
2005-06-22 21:16:39 +04:00
attrs [ 0 ] & readdir - > bitmask [ 0 ] ,
2013-05-22 20:50:44 +04:00
attrs [ 1 ] & readdir - > bitmask [ 1 ] ,
attrs [ 2 ] & readdir - > bitmask [ 2 ] ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_readlink ( struct xdr_stream * xdr , const struct nfs4_readlink * readlink , struct rpc_rqst * req , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_READLINK , decode_readlink_maxsz , hdr ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_remove ( struct xdr_stream * xdr , const struct qstr * name , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_REMOVE , decode_remove_maxsz , hdr ) ;
2012-03-05 03:13:57 +04:00
encode_string ( xdr , name - > len , name - > name ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_rename ( struct xdr_stream * xdr , const struct qstr * oldname , const struct qstr * newname , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_RENAME , decode_rename_maxsz , hdr ) ;
2009-08-14 18:19:34 +04:00
encode_string ( xdr , oldname - > len , oldname - > name ) ;
encode_string ( xdr , newname - > len , newname - > name ) ;
2005-04-17 02:20:36 +04:00
}
2012-03-02 02:01:48 +04:00
static void encode_renew ( struct xdr_stream * xdr , clientid4 clid ,
struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_RENEW , decode_renew_maxsz , hdr ) ;
2012-03-05 20:40:12 +04:00
encode_uint64 ( xdr , clid ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void
2008-12-24 00:06:17 +03:00
encode_restorefh ( struct xdr_stream * xdr , struct compound_hdr * hdr )
2005-10-28 06:12:40 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_RESTOREFH , decode_restorefh_maxsz , hdr ) ;
2005-10-28 06:12:40 +04:00
}
2010-12-14 17:59:18 +03:00
static void
2008-12-24 00:06:17 +03:00
encode_setacl ( struct xdr_stream * xdr , struct nfs_setaclargs * arg , struct compound_hdr * hdr )
2005-06-22 21:16:22 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-06-22 21:16:22 +04:00
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_SETATTR , decode_setacl_maxsz , hdr ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , & zero_stateid ) ;
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 2 * 4 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( 1 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( FATTR4_WORD0_ACL ) ;
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( arg - > acl_len ) ;
2005-06-22 21:16:22 +04:00
xdr_write_pages ( xdr , arg - > acl_pages , arg - > acl_pgbase , arg - > acl_len ) ;
}
2008-12-24 00:06:18 +03:00
static void
2008-12-24 00:06:17 +03:00
encode_savefh ( struct xdr_stream * xdr , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_SAVEFH , decode_savefh_maxsz , hdr ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_setattr ( struct xdr_stream * xdr , const struct nfs_setattrargs * arg , const struct nfs_server * server , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_SETATTR , decode_setattr_maxsz , hdr ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , & arg - > stateid ) ;
2013-05-22 20:50:44 +04:00
encode_attrs ( xdr , arg - > iap , arg - > label , server ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_setclientid ( struct xdr_stream * xdr , const struct nfs4_setclientid * setclientid , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2012-03-05 05:49:32 +04:00
encode_op_hdr ( xdr , OP_SETCLIENTID , decode_setclientid_maxsz , hdr ) ;
2012-03-03 02:14:31 +04:00
encode_nfs4_verifier ( xdr , setclientid - > sc_verifier ) ;
2005-04-17 02:20:36 +04:00
encode_string ( xdr , setclientid - > sc_name_len , setclientid - > sc_name ) ;
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( setclientid - > sc_prog ) ;
2005-04-17 02:20:36 +04:00
encode_string ( xdr , setclientid - > sc_netid_len , setclientid - > sc_netid ) ;
encode_string ( xdr , setclientid - > sc_uaddr_len , setclientid - > sc_uaddr ) ;
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( setclientid - > sc_cb_ident ) ;
2005-04-17 02:20:36 +04:00
}
2010-04-17 00:43:06 +04:00
static void encode_setclientid_confirm ( struct xdr_stream * xdr , const struct nfs4_setclientid_res * arg , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_SETCLIENTID_CONFIRM ,
decode_setclientid_confirm_maxsz , hdr ) ;
2012-03-05 20:40:12 +04:00
encode_uint64 ( xdr , arg - > clientid ) ;
2012-03-03 02:14:31 +04:00
encode_nfs4_verifier ( xdr , & arg - > confirm ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_write ( struct xdr_stream * xdr , const struct nfs_writeargs * args , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_WRITE , decode_write_maxsz , hdr ) ;
2013-03-17 23:52:00 +04:00
encode_nfs4_stateid ( xdr , & args - > stateid ) ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 16 ) ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , args - > offset ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( args - > stable ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( args - > count ) ;
2005-04-17 02:20:36 +04:00
xdr_write_pages ( xdr , args - > pages , args - > pgbase , args - > count ) ;
}
2008-12-24 00:06:18 +03:00
static void encode_delegreturn ( struct xdr_stream * xdr , const nfs4_stateid * stateid , struct compound_hdr * hdr )
2005-04-17 02:20:36 +04:00
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_DELEGRETURN , decode_delegreturn_maxsz , hdr ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , stateid ) ;
2005-04-17 02:20:36 +04:00
}
2009-04-01 17:22:11 +04:00
2011-03-24 20:12:29 +03:00
static void encode_secinfo ( struct xdr_stream * xdr , const struct qstr * name , struct compound_hdr * hdr )
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_SECINFO , decode_secinfo_maxsz , hdr ) ;
2012-03-05 03:13:57 +04:00
encode_string ( xdr , name - > len , name - > name ) ;
2011-03-24 20:12:29 +03:00
}
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
2009-04-01 17:22:11 +04:00
/* NFSv4.1 operations */
2012-05-24 21:22:50 +04:00
static void encode_bind_conn_to_session ( struct xdr_stream * xdr ,
struct nfs4_session * session ,
struct compound_hdr * hdr )
{
__be32 * p ;
encode_op_hdr ( xdr , OP_BIND_CONN_TO_SESSION ,
decode_bind_conn_to_session_maxsz , hdr ) ;
encode_opaque_fixed ( xdr , session - > sess_id . data , NFS4_MAX_SESSIONID_LEN ) ;
p = xdr_reserve_space ( xdr , 8 ) ;
* p + + = cpu_to_be32 ( NFS4_CDFC4_BACK_OR_BOTH ) ;
* p = 0 ; /* use_conn_in_rdma_mode = False */
}
2013-08-14 00:37:32 +04:00
static void encode_op_map ( struct xdr_stream * xdr , struct nfs4_op_map * op_map )
{
unsigned int i ;
encode_uint32 ( xdr , NFS4_OP_MAP_NUM_WORDS ) ;
for ( i = 0 ; i < NFS4_OP_MAP_NUM_WORDS ; i + + )
encode_uint32 ( xdr , op_map - > u . words [ i ] ) ;
}
2009-04-01 17:22:29 +04:00
static void encode_exchange_id ( struct xdr_stream * xdr ,
struct nfs41_exchange_id_args * args ,
struct compound_hdr * hdr )
{
__be32 * p ;
2012-11-17 03:12:06 +04:00
char impl_name [ IMPL_NAME_LIMIT ] ;
2012-02-18 00:20:24 +04:00
int len = 0 ;
2009-04-01 17:22:29 +04:00
2012-03-05 05:49:32 +04:00
encode_op_hdr ( xdr , OP_EXCHANGE_ID , decode_exchange_id_maxsz , hdr ) ;
2012-03-03 02:14:31 +04:00
encode_nfs4_verifier ( xdr , args - > verifier ) ;
2009-04-01 17:22:29 +04:00
encode_string ( xdr , args - > id_len , args - > id ) ;
2013-08-14 00:37:32 +04:00
encode_uint32 ( xdr , args - > flags ) ;
encode_uint32 ( xdr , args - > state_protect . how ) ;
switch ( args - > state_protect . how ) {
case SP4_NONE :
break ;
case SP4_MACH_CRED :
encode_op_map ( xdr , & args - > state_protect . enforce ) ;
encode_op_map ( xdr , & args - > state_protect . allow ) ;
break ;
default :
WARN_ON_ONCE ( 1 ) ;
break ;
}
2012-02-18 00:20:24 +04:00
if ( send_implementation_id & &
sizeof ( CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN ) > 1 & &
sizeof ( CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN )
2012-11-17 03:12:06 +04:00
< = sizeof ( impl_name ) + 1 )
2012-02-18 00:20:24 +04:00
len = snprintf ( impl_name , sizeof ( impl_name ) , " %s %s %s %s " ,
utsname ( ) - > sysname , utsname ( ) - > release ,
utsname ( ) - > version , utsname ( ) - > machine ) ;
if ( len > 0 ) {
2013-08-14 00:37:32 +04:00
encode_uint32 ( xdr , 1 ) ; /* implementation id array length=1 */
2012-02-18 00:20:24 +04:00
encode_string ( xdr ,
sizeof ( CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN ) - 1 ,
CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN ) ;
encode_string ( xdr , len , impl_name ) ;
/* just send zeros for nii_date - the date is in nii_name */
p = reserve_space ( xdr , 12 ) ;
p = xdr_encode_hyper ( p , 0 ) ;
* p = cpu_to_be32 ( 0 ) ;
} else
2013-08-14 00:37:32 +04:00
encode_uint32 ( xdr , 0 ) ; /* implementation id array length=0 */
2009-04-01 17:22:29 +04:00
}
2009-04-01 17:22:31 +04:00
static void encode_create_session ( struct xdr_stream * xdr ,
struct nfs41_create_session_args * args ,
struct compound_hdr * hdr )
{
__be32 * p ;
char machine_name [ NFS4_MAX_MACHINE_NAME_LEN ] ;
uint32_t len ;
struct nfs_client * clp = args - > client ;
NFS: Always use the same SETCLIENTID boot verifier
Currently our NFS client assigns a unique SETCLIENTID boot verifier
for each server IP address it knows about. It's set to CURRENT_TIME
when the struct nfs_client for that server IP is created.
During the SETCLIENTID operation, our client also presents an
nfs_client_id4 string to servers, as an identifier on which the server
can hang all of this client's NFSv4 state. Our client's
nfs_client_id4 string is unique for each server IP address.
An NFSv4 server is obligated to wipe all NFSv4 state associated with
an nfs_client_id4 string when the client presents the same
nfs_client_id4 string along with a changed SETCLIENTID boot verifier.
When our client unmounts the last of a server's shares, it destroys
that server's struct nfs_client. The next time the client mounts that
NFS server, it creates a fresh struct nfs_client with a fresh boot
verifier. On seeing the fresh verifer, the server wipes any previous
NFSv4 state associated with that nfs_client_id4.
However, NFSv4.1 clients are supposed to present the same
nfs_client_id4 string to all servers. And, to support Transparent
State Migration, the same nfs_client_id4 string should be presented
to all NFSv4.0 servers so they recognize that migrated state for this
client belongs with state a server may already have for this client.
(This is known as the Uniform Client String model).
If the nfs_client_id4 string is the same but the boot verifier changes
for each server IP address, SETCLIENTID and EXCHANGE_ID operations
from such a client could unintentionally result in a server wiping a
client's previously obtained lease.
Thus, if our NFS client is going to use a fixed nfs_client_id4 string,
either for NFSv4.0 or NFSv4.1 mounts, our NFS client should use a
boot verifier that does not change depending on server IP address.
Replace our current per-nfs_client boot verifier with a per-nfs_net
boot verifier.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
2012-05-22 06:45:41 +04:00
struct nfs_net * nn = net_generic ( clp - > cl_net , nfs_net_id ) ;
2009-12-17 20:06:26 +03:00
u32 max_resp_sz_cached ;
/*
* Assumes OPEN is the biggest non - idempotent compound .
* 2 is the verifier .
*/
max_resp_sz_cached = ( NFS4_dec_open_sz + RPC_REPHDRSIZE +
RPC_MAX_AUTH_SIZE + 2 ) * XDR_UNIT ;
2009-04-01 17:22:31 +04:00
2009-08-14 18:19:13 +04:00
len = scnprintf ( machine_name , sizeof ( machine_name ) , " %s " ,
clp - > cl_ipaddr ) ;
2009-04-01 17:22:31 +04:00
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_CREATE_SESSION , decode_create_session_maxsz , hdr ) ;
p = reserve_space ( xdr , 16 + 2 * 28 + 20 + len + 12 ) ;
2011-03-09 21:13:45 +03:00
p = xdr_encode_hyper ( p , clp - > cl_clientid ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( clp - > cl_seqid ) ; /*Sequence id */
* p + + = cpu_to_be32 ( args - > flags ) ; /*flags */
2009-04-01 17:22:31 +04:00
/* Fore Channel */
2011-06-12 01:08:39 +04:00
* p + + = cpu_to_be32 ( 0 ) ; /* header padding size */
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( args - > fc_attrs . max_rqst_sz ) ; /* max req size */
* p + + = cpu_to_be32 ( args - > fc_attrs . max_resp_sz ) ; /* max resp size */
2009-12-17 20:06:26 +03:00
* p + + = cpu_to_be32 ( max_resp_sz_cached ) ; /* Max resp sz cached */
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( args - > fc_attrs . max_ops ) ; /* max operations */
* p + + = cpu_to_be32 ( args - > fc_attrs . max_reqs ) ; /* max requests */
* p + + = cpu_to_be32 ( 0 ) ; /* rdmachannel_attrs */
2009-04-01 17:22:31 +04:00
/* Back Channel */
2011-06-12 01:08:39 +04:00
* p + + = cpu_to_be32 ( 0 ) ; /* header padding size */
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( args - > bc_attrs . max_rqst_sz ) ; /* max req size */
* p + + = cpu_to_be32 ( args - > bc_attrs . max_resp_sz ) ; /* max resp size */
* p + + = cpu_to_be32 ( args - > bc_attrs . max_resp_sz_cached ) ; /* Max resp sz cached */
* p + + = cpu_to_be32 ( args - > bc_attrs . max_ops ) ; /* max operations */
* p + + = cpu_to_be32 ( args - > bc_attrs . max_reqs ) ; /* max requests */
* p + + = cpu_to_be32 ( 0 ) ; /* rdmachannel_attrs */
2009-04-01 17:22:31 +04:00
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( args - > cb_program ) ; /* cb_program */
* p + + = cpu_to_be32 ( 1 ) ;
* p + + = cpu_to_be32 ( RPC_AUTH_UNIX ) ; /* auth_sys */
2009-04-01 17:22:31 +04:00
/* authsys_parms rfc1831 */
2013-08-21 23:48:42 +04:00
* p + + = cpu_to_be32 ( nn - > boot_time . tv_nsec ) ; /* stamp */
2009-08-14 18:19:34 +04:00
p = xdr_encode_opaque ( p , machine_name , len ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( 0 ) ; /* UID */
* p + + = cpu_to_be32 ( 0 ) ; /* GID */
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( 0 ) ; /* No more gids */
2009-04-01 17:22:31 +04:00
}
2009-04-01 17:22:34 +04:00
static void encode_destroy_session ( struct xdr_stream * xdr ,
struct nfs4_session * session ,
struct compound_hdr * hdr )
{
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_DESTROY_SESSION , decode_destroy_session_maxsz , hdr ) ;
encode_opaque_fixed ( xdr , session - > sess_id . data , NFS4_MAX_SESSIONID_LEN ) ;
2009-04-01 17:22:34 +04:00
}
2009-12-06 00:08:40 +03:00
2012-05-26 01:18:09 +04:00
static void encode_destroy_clientid ( struct xdr_stream * xdr ,
uint64_t clientid ,
struct compound_hdr * hdr )
{
encode_op_hdr ( xdr , OP_DESTROY_CLIENTID , decode_destroy_clientid_maxsz , hdr ) ;
encode_uint64 ( xdr , clientid ) ;
}
2009-12-06 00:08:40 +03:00
static void encode_reclaim_complete ( struct xdr_stream * xdr ,
struct nfs41_reclaim_complete_args * args ,
struct compound_hdr * hdr )
{
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_RECLAIM_COMPLETE , decode_reclaim_complete_maxsz , hdr ) ;
encode_uint32 ( xdr , args - > one_fs ) ;
2009-12-06 00:08:40 +03:00
}
2009-04-01 17:22:29 +04:00
# endif /* CONFIG_NFS_V4_1 */
2009-04-01 17:22:11 +04:00
static void encode_sequence ( struct xdr_stream * xdr ,
const struct nfs4_sequence_args * args ,
struct compound_hdr * hdr )
{
# if defined(CONFIG_NFS_V4_1)
2012-11-16 21:58:36 +04:00
struct nfs4_session * session ;
2009-04-01 17:22:36 +04:00
struct nfs4_slot_table * tp ;
2012-11-16 21:58:36 +04:00
struct nfs4_slot * slot = args - > sa_slot ;
2009-04-01 17:22:36 +04:00
__be32 * p ;
2009-04-01 17:22:11 +04:00
2012-11-16 21:58:36 +04:00
tp = slot - > table ;
session = tp - > session ;
2013-08-09 20:49:19 +04:00
if ( ! session )
return ;
2009-04-01 17:22:36 +04:00
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_SEQUENCE , decode_sequence_maxsz , hdr ) ;
2009-04-01 17:22:36 +04:00
/*
* Sessionid + seqid + slotid + max slotid + cache_this
*/
dprintk ( " %s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
" max_slotid=%d cache_this=%d \n " ,
__func__ ,
( ( u32 * ) session - > sess_id . data ) [ 0 ] ,
( ( u32 * ) session - > sess_id . data ) [ 1 ] ,
( ( u32 * ) session - > sess_id . data ) [ 2 ] ,
( ( u32 * ) session - > sess_id . data ) [ 3 ] ,
2012-11-16 21:58:36 +04:00
slot - > seq_nr , slot - > slot_nr ,
2009-04-01 17:22:36 +04:00
tp - > highest_used_slotid , args - > sa_cache_this ) ;
2012-03-05 20:27:16 +04:00
p = reserve_space ( xdr , NFS4_MAX_SESSIONID_LEN + 16 ) ;
2009-08-14 18:19:06 +04:00
p = xdr_encode_opaque_fixed ( p , session - > sess_id . data , NFS4_MAX_SESSIONID_LEN ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( slot - > seq_nr ) ;
2012-11-16 21:58:36 +04:00
* p + + = cpu_to_be32 ( slot - > slot_nr ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( tp - > highest_used_slotid ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( args - > sa_cache_this ) ;
2009-04-01 17:22:11 +04:00
# endif /* CONFIG_NFS_V4_1 */
}
2010-10-20 08:18:03 +04:00
# ifdef CONFIG_NFS_V4_1
2011-07-31 04:52:35 +04:00
static void
encode_getdevicelist ( struct xdr_stream * xdr ,
const struct nfs4_getdevicelist_args * args ,
struct compound_hdr * hdr )
{
__be32 * p ;
nfs4_verifier dummy = {
. data = " dummmmmy " ,
} ;
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_GETDEVICELIST , decode_getdevicelist_maxsz , hdr ) ;
p = reserve_space ( xdr , 16 ) ;
2011-07-31 04:52:35 +04:00
* p + + = cpu_to_be32 ( args - > layoutclass ) ;
* p + + = cpu_to_be32 ( NFS4_PNFS_GETDEVLIST_MAXNUM ) ;
xdr_encode_hyper ( p , 0ULL ) ; /* cookie */
encode_nfs4_verifier ( xdr , & dummy ) ;
}
2010-10-20 08:18:03 +04:00
static void
encode_getdeviceinfo ( struct xdr_stream * xdr ,
const struct nfs4_getdeviceinfo_args * args ,
struct compound_hdr * hdr )
{
__be32 * p ;
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_GETDEVICEINFO , decode_getdeviceinfo_maxsz , hdr ) ;
p = reserve_space ( xdr , 12 + NFS4_DEVICEID4_SIZE ) ;
2010-10-20 08:18:03 +04:00
p = xdr_encode_opaque_fixed ( p , args - > pdev - > dev_id . data ,
NFS4_DEVICEID4_SIZE ) ;
* p + + = cpu_to_be32 ( args - > pdev - > layout_type ) ;
2013-06-26 03:02:53 +04:00
* p + + = cpu_to_be32 ( args - > pdev - > maxcount ) ; /* gdia_maxcount */
2010-10-20 08:18:03 +04:00
* p + + = cpu_to_be32 ( 0 ) ; /* bitmap length 0 */
}
static void
encode_layoutget ( struct xdr_stream * xdr ,
const struct nfs4_layoutget_args * args ,
struct compound_hdr * hdr )
{
__be32 * p ;
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_LAYOUTGET , decode_layoutget_maxsz , hdr ) ;
p = reserve_space ( xdr , 36 ) ;
2010-10-20 08:18:03 +04:00
* p + + = cpu_to_be32 ( 0 ) ; /* Signal layout available */
* p + + = cpu_to_be32 ( args - > type ) ;
* p + + = cpu_to_be32 ( args - > range . iomode ) ;
p = xdr_encode_hyper ( p , args - > range . offset ) ;
p = xdr_encode_hyper ( p , args - > range . length ) ;
p = xdr_encode_hyper ( p , args - > minlength ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , & args - > stateid ) ;
2012-03-05 20:27:16 +04:00
encode_uint32 ( xdr , args - > maxcount ) ;
2010-10-20 08:18:03 +04:00
dprintk ( " %s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d \n " ,
__func__ ,
args - > type ,
args - > range . iomode ,
( unsigned long ) args - > range . offset ,
( unsigned long ) args - > range . length ,
args - > maxcount ) ;
}
2011-03-23 16:27:54 +03:00
static int
encode_layoutcommit ( struct xdr_stream * xdr ,
2011-05-22 20:53:48 +04:00
struct inode * inode ,
2011-03-23 16:27:54 +03:00
const struct nfs4_layoutcommit_args * args ,
struct compound_hdr * hdr )
{
__be32 * p ;
dprintk ( " %s: lbw: %llu type: %d \n " , __func__ , args - > lastbytewritten ,
NFS_SERVER ( args - > inode ) - > pnfs_curr_ld - > id ) ;
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_LAYOUTCOMMIT , decode_layoutcommit_maxsz , hdr ) ;
p = reserve_space ( xdr , 20 ) ;
2011-03-23 16:27:54 +03:00
/* Only whole file layouts */
p = xdr_encode_hyper ( p , 0 ) ; /* offset */
2011-07-31 04:52:34 +04:00
p = xdr_encode_hyper ( p , args - > lastbytewritten + 1 ) ; /* length */
2012-03-05 03:13:56 +04:00
* p = cpu_to_be32 ( 0 ) ; /* reclaim */
encode_nfs4_stateid ( xdr , & args - > stateid ) ;
p = reserve_space ( xdr , 20 ) ;
2011-03-23 16:27:54 +03:00
* p + + = cpu_to_be32 ( 1 ) ; /* newoffset = TRUE */
p = xdr_encode_hyper ( p , args - > lastbytewritten ) ;
* p + + = cpu_to_be32 ( 0 ) ; /* Never send time_modify_changed */
* p + + = cpu_to_be32 ( NFS_SERVER ( args - > inode ) - > pnfs_curr_ld - > id ) ; /* type */
2011-05-22 20:53:48 +04:00
if ( NFS_SERVER ( inode ) - > pnfs_curr_ld - > encode_layoutcommit )
NFS_SERVER ( inode ) - > pnfs_curr_ld - > encode_layoutcommit (
NFS_I ( inode ) - > layout , xdr , args ) ;
2012-03-05 20:27:16 +04:00
else
encode_uint32 ( xdr , 0 ) ; /* no layout-type payload */
2011-03-23 16:27:54 +03:00
return 0 ;
}
2011-05-22 20:52:37 +04:00
static void
encode_layoutreturn ( struct xdr_stream * xdr ,
const struct nfs4_layoutreturn_args * args ,
struct compound_hdr * hdr )
{
__be32 * p ;
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_LAYOUTRETURN , decode_layoutreturn_maxsz , hdr ) ;
p = reserve_space ( xdr , 16 ) ;
2011-05-22 20:52:37 +04:00
* p + + = cpu_to_be32 ( 0 ) ; /* reclaim. always 0 for now */
* p + + = cpu_to_be32 ( args - > layout_type ) ;
* p + + = cpu_to_be32 ( IOMODE_ANY ) ;
* p = cpu_to_be32 ( RETURN_FILE ) ;
2012-03-05 03:13:56 +04:00
p = reserve_space ( xdr , 16 ) ;
2011-05-22 20:52:37 +04:00
p = xdr_encode_hyper ( p , 0 ) ;
p = xdr_encode_hyper ( p , NFS4_MAX_UINT64 ) ;
spin_lock ( & args - > inode - > i_lock ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , & args - > stateid ) ;
2011-05-22 20:52:37 +04:00
spin_unlock ( & args - > inode - > i_lock ) ;
2011-05-22 20:53:10 +04:00
if ( NFS_SERVER ( args - > inode ) - > pnfs_curr_ld - > encode_layoutreturn ) {
NFS_SERVER ( args - > inode ) - > pnfs_curr_ld - > encode_layoutreturn (
NFS_I ( args - > inode ) - > layout , xdr , args ) ;
2012-03-05 20:27:16 +04:00
} else
encode_uint32 ( xdr , 0 ) ;
2011-05-22 20:52:37 +04:00
}
2011-06-02 22:59:07 +04:00
static int
encode_secinfo_no_name ( struct xdr_stream * xdr ,
const struct nfs41_secinfo_no_name_args * args ,
struct compound_hdr * hdr )
{
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_SECINFO_NO_NAME , decode_secinfo_no_name_maxsz , hdr ) ;
encode_uint32 ( xdr , args - > style ) ;
2011-06-02 22:59:07 +04:00
return 0 ;
}
2011-06-02 22:59:08 +04:00
static void encode_test_stateid ( struct xdr_stream * xdr ,
struct nfs41_test_stateid_args * args ,
struct compound_hdr * hdr )
{
2012-03-05 20:27:16 +04:00
encode_op_hdr ( xdr , OP_TEST_STATEID , decode_test_stateid_maxsz , hdr ) ;
encode_uint32 ( xdr , 1 ) ;
2012-03-05 03:13:56 +04:00
encode_nfs4_stateid ( xdr , args - > stateid ) ;
2011-06-02 22:59:08 +04:00
}
2011-06-02 22:59:09 +04:00
static void encode_free_stateid ( struct xdr_stream * xdr ,
struct nfs41_free_stateid_args * args ,
struct compound_hdr * hdr )
{
2012-03-05 03:13:57 +04:00
encode_op_hdr ( xdr , OP_FREE_STATEID , decode_free_stateid_maxsz , hdr ) ;
2013-05-03 22:40:01 +04:00
encode_nfs4_stateid ( xdr , & args - > stateid ) ;
2011-06-02 22:59:09 +04:00
}
2010-10-20 08:18:03 +04:00
# endif /* CONFIG_NFS_V4_1 */
2005-04-17 02:20:36 +04:00
/*
* END OF " GENERIC " ENCODE ROUTINES .
*/
2009-04-01 17:22:10 +04:00
static u32 nfs4_xdr_minorversion ( const struct nfs4_sequence_args * args )
{
# if defined(CONFIG_NFS_V4_1)
2013-08-09 20:49:19 +04:00
struct nfs4_session * session = args - > sa_slot - > table - > session ;
if ( session )
return session - > clp - > cl_mvops - > minor_version ;
2009-04-01 17:22:10 +04:00
# endif /* CONFIG_NFS_V4_1 */
return 0 ;
}
2005-04-17 02:20:36 +04:00
/*
* Encode an ACCESS request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_access ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs4_accessargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_access ( xdr , args - > access , & hdr ) ;
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode LOOKUP request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_lookup ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs4_lookup_arg * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > dir_fh , & hdr ) ;
encode_lookup ( xdr , args - > name , & hdr ) ;
encode_getfh ( xdr , & hdr ) ;
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode LOOKUP_ROOT request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_lookup_root ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
const struct nfs4_lookup_root_arg * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putrootfh ( xdr , & hdr ) ;
encode_getfh ( xdr , & hdr ) ;
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode REMOVE request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_remove ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs_removeargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_remove ( xdr , & args - > name , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode RENAME request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_rename ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs_renameargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > old_dir , & hdr ) ;
encode_savefh ( xdr , & hdr ) ;
encode_putfh ( xdr , args - > new_dir , & hdr ) ;
encode_rename ( xdr , args - > old_name , args - > new_name , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode LINK request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_link ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs4_link_arg * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_savefh ( xdr , & hdr ) ;
encode_putfh ( xdr , args - > dir_fh , & hdr ) ;
encode_link ( xdr , args - > name , & hdr ) ;
encode_restorefh ( xdr , & hdr ) ;
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode CREATE request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_create ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs4_create_arg * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > dir_fh , & hdr ) ;
encode_create ( xdr , args , & hdr ) ;
encode_getfh ( xdr , & hdr ) ;
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode SYMLINK request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_symlink ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs4_create_arg * args )
2005-04-17 02:20:36 +04:00
{
2010-12-14 17:59:18 +03:00
nfs4_xdr_enc_create ( req , xdr , args ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode GETATTR request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_getattr ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs4_getattr_arg * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a CLOSE request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_close ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_closeargs * args )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2008-12-24 00:06:15 +03:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_close ( xdr , args , & hdr ) ;
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode an OPEN request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_open ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_openargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_open ( xdr , args , & hdr ) ;
encode_getfh ( xdr , & hdr ) ;
2012-10-03 01:49:52 +04:00
if ( args - > access )
encode_access ( xdr , args - > access , & hdr ) ;
2012-06-05 17:16:47 +04:00
encode_getfattr_open ( xdr , args - > bitmask , args - > open_bitmap , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode an OPEN_CONFIRM request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_open_confirm ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs_open_confirmargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2008-12-24 00:06:17 +03:00
. nops = 0 ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_open_confirm ( xdr , args , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode an OPEN request with no attributes .
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_open_noattr ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs_openargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_open ( xdr , args , & hdr ) ;
2012-10-03 01:49:52 +04:00
if ( args - > access )
encode_access ( xdr , args - > access , & hdr ) ;
2012-10-03 05:07:32 +04:00
encode_getfattr_open ( xdr , args - > bitmask , args - > open_bitmap , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode an OPEN_DOWNGRADE request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_open_downgrade ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs_closeargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_open_downgrade ( xdr , args , & hdr ) ;
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a LOCK request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_lock ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_lock_args * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_lock ( xdr , args , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a LOCKT request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_lockt ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_lockt_args * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_lockt ( xdr , args , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a LOCKU request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_locku ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_locku_args * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_locku ( xdr , args , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_release_lockowner ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs_release_lockowner_args * args )
2010-07-01 20:49:01 +04:00
{
struct compound_hdr hdr = {
. minorversion = 0 ,
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_release_lockowner ( xdr , & args - > lock_owner , & hdr ) ;
2010-07-01 20:49:01 +04:00
encode_nops ( & hdr ) ;
}
2005-04-17 02:20:36 +04:00
/*
* Encode a READLINK request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_readlink ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs4_readlink * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_readlink ( xdr , args , req , & hdr ) ;
2007-07-19 18:03:38 +04:00
2009-04-01 17:22:09 +04:00
xdr_inline_pages ( & req - > rq_rcv_buf , hdr . replen < < 2 , args - > pages ,
2007-07-19 18:03:38 +04:00
args - > pgbase , args - > pglen ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a READDIR request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_readdir ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs4_readdir_arg * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_readdir ( xdr , args , req , & hdr ) ;
2007-07-19 18:03:37 +04:00
2009-04-01 17:22:09 +04:00
xdr_inline_pages ( & req - > rq_rcv_buf , hdr . replen < < 2 , args - > pages ,
2007-07-19 18:03:37 +04:00
args - > pgbase , args - > count ) ;
dprintk ( " %s: inlined page args = (%u, %p, %u, %u) \n " ,
2009-04-01 17:22:09 +04:00
__func__ , hdr . replen < < 2 , args - > pages ,
2007-07-19 18:03:37 +04:00
args - > pgbase , args - > count ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a READ request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_read ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_readargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_read ( xdr , args , & hdr ) ;
2005-04-17 02:20:36 +04:00
2009-04-01 17:22:09 +04:00
xdr_inline_pages ( & req - > rq_rcv_buf , hdr . replen < < 2 ,
2005-04-17 02:20:36 +04:00
args - > pages , args - > pgbase , args - > count ) ;
2007-09-10 21:44:58 +04:00
req - > rq_rcv_buf . flags | = XDRBUF_READ ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode an SETATTR request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_setattr ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_setattrargs * args )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2008-12-24 00:06:15 +03:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_setattr ( xdr , args , args - > server , & hdr ) ;
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
2005-06-22 21:16:22 +04:00
/*
* Encode a GETACL request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_getacl ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_getaclargs * args )
2005-06-22 21:16:22 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-06-22 21:16:22 +04:00
} ;
2009-04-01 17:22:09 +04:00
uint32_t replen ;
2005-06-22 21:16:22 +04:00
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
2011-12-07 20:55:27 +04:00
replen = hdr . replen + op_decode_hdr_maxsz + 1 ;
2010-12-14 17:59:18 +03:00
encode_getattr_two ( xdr , FATTR4_WORD0_ACL , 0 , & hdr ) ;
2008-12-24 00:06:18 +03:00
2009-04-01 17:22:09 +04:00
xdr_inline_pages ( & req - > rq_rcv_buf , replen < < 2 ,
2005-06-22 21:16:22 +04:00
args - > acl_pages , args - > acl_pgbase , args - > acl_len ) ;
2011-12-07 20:55:27 +04:00
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-06-22 21:16:22 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* Encode a WRITE request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_write ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_writeargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_write ( xdr , args , & hdr ) ;
2007-09-10 21:44:58 +04:00
req - > rq_snd_buf . flags | = XDRBUF_WRITE ;
2011-03-03 18:13:46 +03:00
if ( args - > bitmask )
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* a COMMIT request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_commit ( struct rpc_rqst * req , struct xdr_stream * xdr ,
2012-04-20 22:47:39 +04:00
struct nfs_commitargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_commit ( xdr , args , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* FSINFO request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_fsinfo ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs4_fsinfo_arg * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_fsinfo ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* a PATHCONF request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_pathconf ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs4_pathconf_arg * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_getattr_one ( xdr , args - > bitmask [ 0 ] & nfs4_pathconf_bitmap [ 0 ] ,
2008-12-24 00:06:18 +03:00
& hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* a STATFS request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_statfs ( struct rpc_rqst * req , struct xdr_stream * xdr ,
const struct nfs4_statfs_arg * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_getattr_two ( xdr , args - > bitmask [ 0 ] & nfs4_statfs_bitmap [ 0 ] ,
2008-12-24 00:06:18 +03:00
args - > bitmask [ 1 ] & nfs4_statfs_bitmap [ 1 ] , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* GETATTR_BITMAP request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_server_caps ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_server_caps_arg * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fhandle , & hdr ) ;
encode_getattr_one ( xdr , FATTR4_WORD0_SUPPORTED_ATTRS |
2012-03-02 02:02:05 +04:00
FATTR4_WORD0_FH_EXPIRE_TYPE |
2008-12-24 00:06:18 +03:00
FATTR4_WORD0_LINK_SUPPORT |
FATTR4_WORD0_SYMLINK_SUPPORT |
FATTR4_WORD0_ACLSUPPORT , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* a RENEW request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_renew ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_client * clp )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2008-12-24 00:06:17 +03:00
. nops = 0 ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
2012-03-02 02:01:48 +04:00
encode_renew ( xdr , clp - > cl_clientid , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* a SETCLIENTID request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_setclientid ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_setclientid * sc )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2008-12-24 00:06:17 +03:00
. nops = 0 ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_setclientid ( xdr , sc , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* a SETCLIENTID_CONFIRM request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_setclientid_confirm ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_setclientid_res * arg )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2008-12-24 00:06:17 +03:00
. nops = 0 ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_setclientid_confirm ( xdr , arg , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
/*
* DELEGRETURN request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_delegreturn ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
const struct nfs4_delegreturnargs * args )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fhandle , & hdr ) ;
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2012-04-29 00:05:03 +04:00
encode_delegreturn ( xdr , args - > stateid , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-04-17 02:20:36 +04:00
}
2006-06-09 17:34:22 +04:00
/*
* Encode FS_LOCATIONS request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_fs_locations ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_fs_locations_arg * args )
2006-06-09 17:34:22 +04:00
{
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2006-06-09 17:34:22 +04:00
} ;
2009-04-01 17:22:09 +04:00
uint32_t replen ;
2006-06-09 17:34:22 +04:00
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > dir_fh , & hdr ) ;
encode_lookup ( xdr , args - > name , & hdr ) ;
2009-04-01 17:22:09 +04:00
replen = hdr . replen ; /* get the attribute into args->page */
2010-12-14 17:59:18 +03:00
encode_fs_locations ( xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:18 +03:00
2009-04-01 17:22:09 +04:00
xdr_inline_pages ( & req - > rq_rcv_buf , replen < < 2 , & args - > page ,
2006-06-09 17:34:22 +04:00
0 , PAGE_SIZE ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2006-06-09 17:34:22 +04:00
}
2011-03-24 20:12:29 +03:00
/*
* Encode SECINFO request
*/
static void nfs4_xdr_enc_secinfo ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_secinfo_arg * args )
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
} ;
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > dir_fh , & hdr ) ;
encode_secinfo ( xdr , args - > name , & hdr ) ;
encode_nops ( & hdr ) ;
}
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
2012-05-24 21:22:50 +04:00
/*
* BIND_CONN_TO_SESSION request
*/
static void nfs4_xdr_enc_bind_conn_to_session ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs_client * clp )
{
struct compound_hdr hdr = {
. minorversion = clp - > cl_mvops - > minor_version ,
} ;
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_bind_conn_to_session ( xdr , clp - > cl_session , & hdr ) ;
encode_nops ( & hdr ) ;
}
2009-04-01 17:22:29 +04:00
/*
* EXCHANGE_ID request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_exchange_id ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs41_exchange_id_args * args )
2009-04-01 17:22:29 +04:00
{
struct compound_hdr hdr = {
2010-06-16 17:52:27 +04:00
. minorversion = args - > client - > cl_mvops - > minor_version ,
2009-04-01 17:22:29 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_exchange_id ( xdr , args , & hdr ) ;
2009-04-01 17:22:29 +04:00
encode_nops ( & hdr ) ;
}
2009-04-01 17:22:30 +04:00
2009-04-01 17:22:31 +04:00
/*
* a CREATE_SESSION request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_create_session ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs41_create_session_args * args )
2009-04-01 17:22:31 +04:00
{
struct compound_hdr hdr = {
2010-06-16 17:52:27 +04:00
. minorversion = args - > client - > cl_mvops - > minor_version ,
2009-04-01 17:22:31 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_create_session ( xdr , args , & hdr ) ;
2009-04-01 17:22:31 +04:00
encode_nops ( & hdr ) ;
}
2009-04-01 17:22:34 +04:00
/*
* a DESTROY_SESSION request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_destroy_session ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_session * session )
2009-04-01 17:22:34 +04:00
{
struct compound_hdr hdr = {
2010-06-16 17:52:27 +04:00
. minorversion = session - > clp - > cl_mvops - > minor_version ,
2009-04-01 17:22:34 +04:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_destroy_session ( xdr , session , & hdr ) ;
2009-04-01 17:22:34 +04:00
encode_nops ( & hdr ) ;
}
2012-05-26 01:18:09 +04:00
/*
* a DESTROY_CLIENTID request
*/
static void nfs4_xdr_enc_destroy_clientid ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs_client * clp )
{
struct compound_hdr hdr = {
. minorversion = clp - > cl_mvops - > minor_version ,
} ;
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_destroy_clientid ( xdr , clp - > cl_clientid , & hdr ) ;
encode_nops ( & hdr ) ;
}
2009-04-01 17:22:36 +04:00
/*
* a SEQUENCE request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_sequence ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs4_sequence_args * args )
2009-04-01 17:22:36 +04:00
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( args ) ,
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , args , & hdr ) ;
2009-04-01 17:22:36 +04:00
encode_nops ( & hdr ) ;
}
2009-04-01 17:22:30 +04:00
/*
* a GET_LEASE_TIME request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_get_lease_time ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_get_lease_time_args * args )
2009-04-01 17:22:30 +04:00
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > la_seq_args ) ,
} ;
2011-07-31 04:52:37 +04:00
const u32 lease_bitmap [ 3 ] = { FATTR4_WORD0_LEASE_TIME } ;
2009-04-01 17:22:30 +04:00
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > la_seq_args , & hdr ) ;
encode_putrootfh ( xdr , & hdr ) ;
encode_fsinfo ( xdr , lease_bitmap , & hdr ) ;
2009-04-01 17:22:30 +04:00
encode_nops ( & hdr ) ;
}
2009-12-06 00:08:40 +03:00
/*
* a RECLAIM_COMPLETE request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_reclaim_complete ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs41_reclaim_complete_args * args )
2009-12-06 00:08:40 +03:00
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args )
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_reclaim_complete ( xdr , args , & hdr ) ;
2009-12-06 00:08:40 +03:00
encode_nops ( & hdr ) ;
}
2011-07-31 04:52:35 +04:00
/*
* Encode GETDEVICELIST request
*/
static void nfs4_xdr_enc_getdevicelist ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_getdevicelist_args * args )
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
} ;
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_getdevicelist ( xdr , args , & hdr ) ;
encode_nops ( & hdr ) ;
}
2010-10-20 08:18:03 +04:00
/*
* Encode GETDEVICEINFO request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_getdeviceinfo ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_getdeviceinfo_args * args )
2010-10-20 08:18:03 +04:00
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_getdeviceinfo ( xdr , args , & hdr ) ;
2010-10-20 08:18:03 +04:00
/* set up reply kvec. Subtract notification bitmap max size (2)
* so that notification bitmap is put in xdr_buf tail */
xdr_inline_pages ( & req - > rq_rcv_buf , ( hdr . replen - 2 ) < < 2 ,
args - > pdev - > pages , args - > pdev - > pgbase ,
args - > pdev - > pglen ) ;
encode_nops ( & hdr ) ;
}
/*
* Encode LAYOUTGET request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_layoutget ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_layoutget_args * args )
2010-10-20 08:18:03 +04:00
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , NFS_FH ( args - > inode ) , & hdr ) ;
encode_layoutget ( xdr , args , & hdr ) ;
2011-03-24 23:48:21 +03:00
xdr_inline_pages ( & req - > rq_rcv_buf , hdr . replen < < 2 ,
args - > layout . pages , 0 , args - > layout . pglen ) ;
2010-10-20 08:18:03 +04:00
encode_nops ( & hdr ) ;
}
2011-03-23 16:27:54 +03:00
/*
* Encode LAYOUTCOMMIT request
*/
2011-05-22 20:52:37 +04:00
static void nfs4_xdr_enc_layoutcommit ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_layoutcommit_args * args )
2011-03-23 16:27:54 +03:00
{
2011-05-22 20:53:48 +04:00
struct nfs4_layoutcommit_data * data =
container_of ( args , struct nfs4_layoutcommit_data , args ) ;
2011-03-23 16:27:54 +03:00
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
} ;
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , NFS_FH ( args - > inode ) , & hdr ) ;
2011-05-22 20:53:48 +04:00
encode_layoutcommit ( xdr , data - > args . inode , args , & hdr ) ;
2011-03-23 16:27:54 +03:00
encode_getfattr ( xdr , args - > bitmask , & hdr ) ;
2010-10-20 08:18:03 +04:00
encode_nops ( & hdr ) ;
2011-05-22 20:52:37 +04:00
}
/*
* Encode LAYOUTRETURN request
*/
static void nfs4_xdr_enc_layoutreturn ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_layoutreturn_args * args )
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
} ;
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , NFS_FH ( args - > inode ) , & hdr ) ;
encode_layoutreturn ( xdr , args , & hdr ) ;
encode_nops ( & hdr ) ;
2010-10-20 08:18:03 +04:00
}
2011-06-02 22:59:07 +04:00
/*
* Encode SECINFO_NO_NAME request
*/
static int nfs4_xdr_enc_secinfo_no_name ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs41_secinfo_no_name_args * args )
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
} ;
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putrootfh ( xdr , & hdr ) ;
encode_secinfo_no_name ( xdr , args , & hdr ) ;
encode_nops ( & hdr ) ;
return 0 ;
}
2011-06-02 22:59:08 +04:00
/*
* Encode TEST_STATEID request
*/
static void nfs4_xdr_enc_test_stateid ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs41_test_stateid_args * args )
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
} ;
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_test_stateid ( xdr , args , & hdr ) ;
encode_nops ( & hdr ) ;
}
2011-06-02 22:59:09 +04:00
/*
* Encode FREE_STATEID request
*/
static void nfs4_xdr_enc_free_stateid ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs41_free_stateid_args * args )
{
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
} ;
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_free_stateid ( xdr , args , & hdr ) ;
encode_nops ( & hdr ) ;
}
2009-04-01 17:22:29 +04:00
# endif /* CONFIG_NFS_V4_1 */
2009-08-14 18:19:48 +04:00
static void print_overflow_msg ( const char * func , const struct xdr_stream * xdr )
{
dprintk ( " nfs: %s: prematurely hit end of receive buffer. "
" Remaining buffer length is %tu words. \n " ,
func , xdr - > end - xdr - > p ) ;
}
2005-04-17 02:20:36 +04:00
2006-06-09 17:34:22 +04:00
static int decode_opaque_inline ( struct xdr_stream * xdr , unsigned int * len , char * * string )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
* len = be32_to_cpup ( p ) ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , * len ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2005-04-17 02:20:36 +04:00
* string = ( char * ) p ;
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_compound_hdr ( struct xdr_stream * xdr , struct compound_hdr * hdr )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
hdr - > status = be32_to_cpup ( p + + ) ;
2009-08-14 18:20:19 +04:00
hdr - > taglen = be32_to_cpup ( p ) ;
2008-12-24 00:06:15 +03:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , hdr - > taglen + 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2005-04-17 02:20:36 +04:00
hdr - > tag = ( char * ) p ;
p + = XDR_QUADLEN ( hdr - > taglen ) ;
2009-08-14 18:20:19 +04:00
hdr - > nops = be32_to_cpup ( p ) ;
2008-12-24 00:06:13 +03:00
if ( unlikely ( hdr - > nops < 1 ) )
return nfs4_stat_to_errno ( hdr - > status ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_op_hdr ( struct xdr_stream * xdr , enum nfs_opnum4 expected )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
uint32_t opnum ;
int32_t nfserr ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
opnum = be32_to_cpup ( p + + ) ;
2005-04-17 02:20:36 +04:00
if ( opnum ! = expected ) {
2007-09-12 02:01:10 +04:00
dprintk ( " nfs: Server returned operation "
" %d but we issued a request for %d \n " ,
2005-04-17 02:20:36 +04:00
opnum , expected ) ;
return - EIO ;
}
2009-08-14 18:20:19 +04:00
nfserr = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
if ( nfserr ! = NFS_OK )
2008-03-31 18:39:06 +04:00
return nfs4_stat_to_errno ( nfserr ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
/* Dummy routine */
2006-08-23 04:06:08 +04:00
static int decode_ace ( struct xdr_stream * xdr , void * ace , struct nfs_client * clp )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2006-06-09 17:34:22 +04:00
unsigned int strlen ;
2005-04-17 02:20:36 +04:00
char * str ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 12 ) ;
if ( likely ( p ) )
return decode_opaque_inline ( xdr , & strlen , & str ) ;
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_bitmap ( struct xdr_stream * xdr , uint32_t * bitmap )
{
2006-10-20 10:28:48 +04:00
uint32_t bmlen ;
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
bmlen = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
2011-07-31 04:52:37 +04:00
bitmap [ 0 ] = bitmap [ 1 ] = bitmap [ 2 ] = 0 ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , ( bmlen < < 2 ) ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2005-04-17 02:20:36 +04:00
if ( bmlen > 0 ) {
2009-08-14 18:19:37 +04:00
bitmap [ 0 ] = be32_to_cpup ( p + + ) ;
2011-07-31 04:52:37 +04:00
if ( bmlen > 1 ) {
bitmap [ 1 ] = be32_to_cpup ( p + + ) ;
if ( bmlen > 2 )
bitmap [ 2 ] = be32_to_cpup ( p ) ;
}
2005-04-17 02:20:36 +04:00
}
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2012-06-21 19:18:13 +04:00
static int decode_attr_length ( struct xdr_stream * xdr , uint32_t * attrlen , unsigned int * savep )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
* attrlen = be32_to_cpup ( p ) ;
2012-06-21 19:18:13 +04:00
* savep = xdr_stream_pos ( xdr ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_supported ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * bitmask )
{
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_SUPPORTED_ATTRS ) ) {
2010-10-13 16:54:51 +04:00
int ret ;
ret = decode_attr_bitmap ( xdr , bitmask ) ;
if ( unlikely ( ret < 0 ) )
return ret ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_SUPPORTED_ATTRS ;
} else
2011-07-31 04:52:37 +04:00
bitmask [ 0 ] = bitmask [ 1 ] = bitmask [ 2 ] = 0 ;
dprintk ( " %s: bitmask=%08x:%08x:%08x \n " , __func__ ,
bitmask [ 0 ] , bitmask [ 1 ] , bitmask [ 2 ] ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int decode_attr_type ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * type )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
* type = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_TYPE - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_TYPE ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
* type = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
if ( * type < NF4REG | | * type > NF4NAMEDATTR ) {
2008-05-03 00:42:44 +04:00
dprintk ( " %s: bad type %d \n " , __func__ , * type ) ;
2005-04-17 02:20:36 +04:00
return - EIO ;
}
bitmap [ 0 ] & = ~ FATTR4_WORD0_TYPE ;
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_TYPE ;
2005-04-17 02:20:36 +04:00
}
2009-03-11 21:10:26 +03:00
dprintk ( " %s: type=0%o \n " , __func__ , nfs_type2fmt [ * type ] ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2012-03-02 02:02:05 +04:00
static int decode_attr_fh_expire_type ( struct xdr_stream * xdr ,
uint32_t * bitmap , uint32_t * type )
{
__be32 * p ;
* type = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_FH_EXPIRE_TYPE - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_FH_EXPIRE_TYPE ) ) {
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
* type = be32_to_cpup ( p ) ;
bitmap [ 0 ] & = ~ FATTR4_WORD0_FH_EXPIRE_TYPE ;
}
dprintk ( " %s: expire type=0x%x \n " , __func__ , * type ) ;
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
2005-04-17 02:20:36 +04:00
static int decode_attr_change ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * change )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
* change = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_CHANGE - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_CHANGE ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , change ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_CHANGE ;
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_CHANGE ;
2005-04-17 02:20:36 +04:00
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: change attribute=%Lu \n " , __func__ ,
2005-04-17 02:20:36 +04:00
( unsigned long long ) * change ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_size ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * size )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
* size = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_SIZE - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_SIZE ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , size ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_SIZE ;
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_SIZE ;
2005-04-17 02:20:36 +04:00
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: file size=%Lu \n " , __func__ , ( unsigned long long ) * size ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_link_support ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
* res = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_LINK_SUPPORT - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_LINK_SUPPORT ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
* res = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_LINK_SUPPORT ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: link support=%s \n " , __func__ , * res = = 0 ? " false " : " true " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_symlink_support ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
* res = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_SYMLINK_SUPPORT - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_SYMLINK_SUPPORT ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
* res = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_SYMLINK_SUPPORT ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: symlink support=%s \n " , __func__ , * res = = 0 ? " false " : " true " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2006-06-09 17:34:19 +04:00
static int decode_attr_fsid ( struct xdr_stream * xdr , uint32_t * bitmap , struct nfs_fsid * fsid )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
fsid - > major = 0 ;
fsid - > minor = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_FSID - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_FSID ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 16 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:41 +04:00
p = xdr_decode_hyper ( p , & fsid - > major ) ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , & fsid - > minor ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_FSID ;
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_FSID ;
2005-04-17 02:20:36 +04:00
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: fsid=(0x%Lx/0x%Lx) \n " , __func__ ,
2005-04-17 02:20:36 +04:00
( unsigned long long ) fsid - > major ,
( unsigned long long ) fsid - > minor ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_lease_time ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
* res = 60 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_LEASE_TIME - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_LEASE_TIME ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
* res = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_LEASE_TIME ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: file size=%u \n " , __func__ , ( unsigned int ) * res ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2011-06-16 21:15:41 +04:00
static int decode_attr_error ( struct xdr_stream * xdr , uint32_t * bitmap , int32_t * res )
2010-10-22 00:33:17 +04:00
{
__be32 * p ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_RDATTR_ERROR - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_RDATTR_ERROR ) ) {
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
bitmap [ 0 ] & = ~ FATTR4_WORD0_RDATTR_ERROR ;
2011-06-16 21:15:41 +04:00
* res = - be32_to_cpup ( p ) ;
2010-10-22 00:33:17 +04:00
}
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
static int decode_attr_filehandle ( struct xdr_stream * xdr , uint32_t * bitmap , struct nfs_fh * fh )
{
__be32 * p ;
int len ;
2010-10-23 23:34:20 +04:00
if ( fh ! = NULL )
memset ( fh , 0 , sizeof ( * fh ) ) ;
2010-10-22 00:33:17 +04:00
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_FILEHANDLE - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_FILEHANDLE ) ) {
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
len = be32_to_cpup ( p ) ;
if ( len > NFS4_FHSIZE )
return - EIO ;
p = xdr_inline_decode ( xdr , len ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2010-10-23 23:34:20 +04:00
if ( fh ! = NULL ) {
memcpy ( fh - > data , p , len ) ;
fh - > size = len ;
}
2010-10-22 00:33:17 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_FILEHANDLE ;
}
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
2005-04-17 02:20:36 +04:00
static int decode_attr_aclsupport ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
* res = ACL4_SUPPORT_ALLOW_ACL | ACL4_SUPPORT_DENY_ACL ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_ACLSUPPORT - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_ACLSUPPORT ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
* res = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_ACLSUPPORT ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: ACLs supported=%u \n " , __func__ , ( unsigned int ) * res ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_fileid ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * fileid )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
* fileid = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_FILEID - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_FILEID ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , fileid ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_FILEID ;
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_FILEID ;
2005-04-17 02:20:36 +04:00
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: fileid=%Lu \n " , __func__ , ( unsigned long long ) * fileid ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2006-06-09 17:34:24 +04:00
static int decode_attr_mounted_on_fileid ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * fileid )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2006-06-09 17:34:24 +04:00
* fileid = 0 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_MOUNTED_ON_FILEID - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_MOUNTED_ON_FILEID ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , fileid ) ;
2006-06-09 17:34:24 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_MOUNTED_ON_FILEID ;
2011-04-27 21:47:52 +04:00
ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID ;
2006-06-09 17:34:24 +04:00
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: fileid=%Lu \n " , __func__ , ( unsigned long long ) * fileid ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2006-06-09 17:34:24 +04:00
}
2005-04-17 02:20:36 +04:00
static int decode_attr_files_avail ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* res = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_FILES_AVAIL - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_FILES_AVAIL ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , res ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_FILES_AVAIL ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: files avail=%Lu \n " , __func__ , ( unsigned long long ) * res ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_files_free ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* res = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_FILES_FREE - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_FILES_FREE ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , res ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_FILES_FREE ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: files free=%Lu \n " , __func__ , ( unsigned long long ) * res ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_files_total ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* res = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_FILES_TOTAL - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_FILES_TOTAL ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , res ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_FILES_TOTAL ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: files total=%Lu \n " , __func__ , ( unsigned long long ) * res ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2006-06-09 17:34:23 +04:00
static int decode_pathname ( struct xdr_stream * xdr , struct nfs4_pathname * path )
{
2007-10-26 21:32:08 +04:00
u32 n ;
2006-10-20 10:28:48 +04:00
__be32 * p ;
2006-06-09 17:34:23 +04:00
int status = 0 ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
n = be32_to_cpup ( p ) ;
2006-06-09 17:34:30 +04:00
if ( n = = 0 )
goto root_path ;
2012-03-02 02:00:31 +04:00
dprintk ( " pathname4: " ) ;
2013-03-27 19:54:45 +04:00
if ( n > NFS4_PATHNAME_MAXCOMPONENTS ) {
dprintk ( " cannot parse %d components in path \n " , n ) ;
goto out_eio ;
}
for ( path - > ncomponents = 0 ; path - > ncomponents < n ; path - > ncomponents + + ) {
2006-06-09 17:34:23 +04:00
struct nfs4_string * component = & path - > components [ path - > ncomponents ] ;
status = decode_opaque_inline ( xdr , & component - > len , & component - > data ) ;
if ( unlikely ( status ! = 0 ) )
goto out_eio ;
2012-03-15 05:55:01 +04:00
ifdebug ( XDR )
2012-03-02 02:00:31 +04:00
pr_cont ( " %s%.*s " ,
( path - > ncomponents ! = n ? " / " : " " ) ,
component - > len , component - > data ) ;
2006-06-09 17:34:23 +04:00
}
out :
return status ;
2006-06-09 17:34:30 +04:00
root_path :
/* a root pathname is sent as a zero component4 */
path - > ncomponents = 1 ;
path - > components [ 0 ] . len = 0 ;
path - > components [ 0 ] . data = NULL ;
2012-03-02 02:00:31 +04:00
dprintk ( " pathname4: / \n " ) ;
2006-06-09 17:34:30 +04:00
goto out ;
2006-06-09 17:34:23 +04:00
out_eio :
dprintk ( " status %d " , status ) ;
status = - EIO ;
goto out ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2006-06-09 17:34:23 +04:00
}
static int decode_attr_fs_locations ( struct xdr_stream * xdr , uint32_t * bitmap , struct nfs4_fs_locations * res )
2006-06-09 17:34:22 +04:00
{
int n ;
2006-10-20 10:28:48 +04:00
__be32 * p ;
2006-06-09 17:34:22 +04:00
int status = - EIO ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_FS_LOCATIONS - 1U ) ) )
goto out ;
status = 0 ;
if ( unlikely ( ! ( bitmap [ 0 ] & FATTR4_WORD0_FS_LOCATIONS ) ) )
goto out ;
2012-01-31 00:43:56 +04:00
status = - EIO ;
/* Ignore borken servers that return unrequested attrs */
if ( unlikely ( res = = NULL ) )
goto out ;
2012-03-02 02:00:31 +04:00
dprintk ( " %s: fsroot: \n " , __func__ ) ;
2006-06-09 17:34:23 +04:00
status = decode_pathname ( xdr , & res - > fs_path ) ;
2006-06-09 17:34:22 +04:00
if ( unlikely ( status ! = 0 ) )
goto out ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
n = be32_to_cpup ( p ) ;
2006-06-09 17:34:22 +04:00
if ( n < = 0 )
goto out_eio ;
2013-03-27 19:54:45 +04:00
for ( res - > nlocations = 0 ; res - > nlocations < n ; res - > nlocations + + ) {
2007-10-26 21:32:08 +04:00
u32 m ;
2013-03-27 19:54:45 +04:00
struct nfs4_fs_location * loc ;
2006-06-09 17:34:22 +04:00
2013-03-27 19:54:45 +04:00
if ( res - > nlocations = = NFS4_FS_LOCATIONS_MAXENTRIES )
break ;
loc = & res - > locations [ res - > nlocations ] ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
m = be32_to_cpup ( p ) ;
2006-06-09 17:34:23 +04:00
2012-03-02 02:00:31 +04:00
dprintk ( " %s: servers: \n " , __func__ ) ;
2013-03-27 19:54:45 +04:00
for ( loc - > nservers = 0 ; loc - > nservers < m ; loc - > nservers + + ) {
struct nfs4_string * server ;
if ( loc - > nservers = = NFS4_FS_LOCATION_MAXSERVERS ) {
2007-10-26 21:32:08 +04:00
unsigned int i ;
dprintk ( " %s: using first %u of %u servers "
" returned for location %u \n " ,
2008-05-03 00:42:44 +04:00
__func__ ,
2007-10-26 21:32:08 +04:00
NFS4_FS_LOCATION_MAXSERVERS ,
m , res - > nlocations ) ;
2006-06-09 17:34:23 +04:00
for ( i = loc - > nservers ; i < m ; i + + ) {
2007-05-15 01:20:41 +04:00
unsigned int len ;
2006-06-09 17:34:23 +04:00
char * data ;
status = decode_opaque_inline ( xdr , & len , & data ) ;
if ( unlikely ( status ! = 0 ) )
goto out_eio ;
}
2013-03-27 19:54:45 +04:00
break ;
2006-06-09 17:34:23 +04:00
}
2013-03-27 19:54:45 +04:00
server = & loc - > servers [ loc - > nservers ] ;
status = decode_opaque_inline ( xdr , & server - > len , & server - > data ) ;
if ( unlikely ( status ! = 0 ) )
goto out_eio ;
dprintk ( " %s " , server - > data ) ;
2006-06-09 17:34:23 +04:00
}
status = decode_pathname ( xdr , & loc - > rootpath ) ;
2006-06-09 17:34:22 +04:00
if ( unlikely ( status ! = 0 ) )
goto out_eio ;
}
2009-03-11 21:10:27 +03:00
if ( res - > nlocations ! = 0 )
2012-03-02 02:01:57 +04:00
status = NFS_ATTR_FATTR_V4_LOCATIONS ;
2006-06-09 17:34:22 +04:00
out :
2008-05-03 00:42:44 +04:00
dprintk ( " %s: fs_locations done, error = %d \n " , __func__ , status ) ;
2006-06-09 17:34:22 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
2006-06-09 17:34:22 +04:00
out_eio :
status = - EIO ;
goto out ;
}
2005-04-17 02:20:36 +04:00
static int decode_attr_maxfilesize ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* res = 0 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_MAXFILESIZE - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_MAXFILESIZE ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , res ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_MAXFILESIZE ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: maxfilesize=%Lu \n " , __func__ , ( unsigned long long ) * res ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_maxlink ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * maxlink )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* maxlink = 1 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_MAXLINK - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_MAXLINK ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
* maxlink = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_MAXLINK ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: maxlink=%u \n " , __func__ , * maxlink ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_maxname ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * maxname )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* maxname = 1024 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_MAXNAME - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_MAXNAME ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
* maxname = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 0 ] & = ~ FATTR4_WORD0_MAXNAME ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: maxname=%u \n " , __func__ , * maxname ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_maxread ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* res = 1024 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_MAXREAD - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_MAXREAD ) ) {
uint64_t maxread ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , & maxread ) ;
2005-04-17 02:20:36 +04:00
if ( maxread > 0x7FFFFFFF )
maxread = 0x7FFFFFFF ;
* res = ( uint32_t ) maxread ;
bitmap [ 0 ] & = ~ FATTR4_WORD0_MAXREAD ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: maxread=%lu \n " , __func__ , ( unsigned long ) * res ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_maxwrite ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* res = 1024 ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_MAXWRITE - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_MAXWRITE ) ) {
uint64_t maxwrite ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , & maxwrite ) ;
2005-04-17 02:20:36 +04:00
if ( maxwrite > 0x7FFFFFFF )
maxwrite = 0x7FFFFFFF ;
* res = ( uint32_t ) maxwrite ;
bitmap [ 0 ] & = ~ FATTR4_WORD0_MAXWRITE ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: maxwrite=%lu \n " , __func__ , ( unsigned long ) * res ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2009-03-11 21:10:26 +03:00
static int decode_attr_mode ( struct xdr_stream * xdr , uint32_t * bitmap , umode_t * mode )
2005-04-17 02:20:36 +04:00
{
2009-03-11 21:10:26 +03:00
uint32_t tmp ;
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
* mode = 0 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_MODE - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_MODE ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
tmp = be32_to_cpup ( p ) ;
2009-03-11 21:10:26 +03:00
* mode = tmp & ~ S_IFMT ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_MODE ;
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_MODE ;
2005-04-17 02:20:36 +04:00
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: file mode=0%o \n " , __func__ , ( unsigned int ) * mode ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_nlink ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * nlink )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
* nlink = 1 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_NUMLINKS - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_NUMLINKS ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
* nlink = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_NUMLINKS ;
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_NLINK ;
2005-04-17 02:20:36 +04:00
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: nlink=%u \n " , __func__ , ( unsigned int ) * nlink ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2009-08-09 23:06:19 +04:00
static int decode_attr_owner ( struct xdr_stream * xdr , uint32_t * bitmap ,
2013-02-02 02:22:02 +04:00
const struct nfs_server * server , kuid_t * uid ,
2012-01-07 22:22:46 +04:00
struct nfs4_string * owner_name )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
uint32_t len ;
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
2013-02-02 02:22:02 +04:00
* uid = make_kuid ( & init_user_ns , - 2 ) ;
2005-04-17 02:20:36 +04:00
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_OWNER - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_OWNER ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
len = be32_to_cpup ( p ) ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , len ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2012-01-07 22:22:46 +04:00
if ( owner_name ! = NULL ) {
owner_name - > data = kmemdup ( p , len , GFP_NOWAIT ) ;
if ( owner_name - > data ! = NULL ) {
owner_name - > len = len ;
ret = NFS_ATTR_FATTR_OWNER_NAME ;
}
2009-08-09 23:06:19 +04:00
} else if ( len < XDR_MAX_NETOBJ ) {
2011-02-23 02:44:31 +03:00
if ( nfs_map_name_to_uid ( server , ( char * ) p , len , uid ) = = 0 )
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_OWNER ;
else
2005-04-17 02:20:36 +04:00
dprintk ( " %s: nfs_map_name_to_uid failed! \n " ,
2008-05-03 00:42:44 +04:00
__func__ ) ;
2005-04-17 02:20:36 +04:00
} else
2007-09-12 02:01:10 +04:00
dprintk ( " %s: name too long (%u)! \n " ,
2008-05-03 00:42:44 +04:00
__func__ , len ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_OWNER ;
}
2013-02-02 02:22:02 +04:00
dprintk ( " %s: uid=%d \n " , __func__ , ( int ) from_kuid ( & init_user_ns , * uid ) ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2009-08-09 23:06:19 +04:00
static int decode_attr_group ( struct xdr_stream * xdr , uint32_t * bitmap ,
2013-02-02 02:22:02 +04:00
const struct nfs_server * server , kgid_t * gid ,
2012-01-07 22:22:46 +04:00
struct nfs4_string * group_name )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
uint32_t len ;
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
2013-02-02 02:22:02 +04:00
* gid = make_kgid ( & init_user_ns , - 2 ) ;
2005-04-17 02:20:36 +04:00
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_OWNER_GROUP - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_OWNER_GROUP ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
len = be32_to_cpup ( p ) ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , len ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2012-01-07 22:22:46 +04:00
if ( group_name ! = NULL ) {
group_name - > data = kmemdup ( p , len , GFP_NOWAIT ) ;
if ( group_name - > data ! = NULL ) {
group_name - > len = len ;
ret = NFS_ATTR_FATTR_GROUP_NAME ;
}
2009-08-09 23:06:19 +04:00
} else if ( len < XDR_MAX_NETOBJ ) {
2011-02-23 02:44:31 +03:00
if ( nfs_map_group_to_gid ( server , ( char * ) p , len , gid ) = = 0 )
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_GROUP ;
else
2005-04-17 02:20:36 +04:00
dprintk ( " %s: nfs_map_group_to_gid failed! \n " ,
2008-05-03 00:42:44 +04:00
__func__ ) ;
2005-04-17 02:20:36 +04:00
} else
2007-09-12 02:01:10 +04:00
dprintk ( " %s: name too long (%u)! \n " ,
2008-05-03 00:42:44 +04:00
__func__ , len ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_OWNER_GROUP ;
}
2013-02-02 02:22:02 +04:00
dprintk ( " %s: gid=%d \n " , __func__ , ( int ) from_kgid ( & init_user_ns , * gid ) ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_rdev ( struct xdr_stream * xdr , uint32_t * bitmap , dev_t * rdev )
{
2006-10-20 10:28:48 +04:00
uint32_t major = 0 , minor = 0 ;
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
* rdev = MKDEV ( 0 , 0 ) ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_RAWDEV - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_RAWDEV ) ) {
dev_t tmp ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
major = be32_to_cpup ( p + + ) ;
2009-08-14 18:20:19 +04:00
minor = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
tmp = MKDEV ( major , minor ) ;
if ( MAJOR ( tmp ) = = major & & MINOR ( tmp ) = = minor )
* rdev = tmp ;
bitmap [ 1 ] & = ~ FATTR4_WORD1_RAWDEV ;
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_RDEV ;
2005-04-17 02:20:36 +04:00
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: rdev=(0x%x:0x%x) \n " , __func__ , major , minor ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_space_avail ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* res = 0 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_SPACE_AVAIL - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_SPACE_AVAIL ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , res ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_SPACE_AVAIL ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: space avail=%Lu \n " , __func__ , ( unsigned long long ) * res ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_space_free ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* res = 0 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_SPACE_FREE - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_SPACE_FREE ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , res ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_SPACE_FREE ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: space free=%Lu \n " , __func__ , ( unsigned long long ) * res ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_space_total ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status = 0 ;
* res = 0 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_SPACE_TOTAL - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_SPACE_TOTAL ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , res ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_SPACE_TOTAL ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: space total=%Lu \n " , __func__ , ( unsigned long long ) * res ) ;
2005-04-17 02:20:36 +04:00
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_space_used ( struct xdr_stream * xdr , uint32_t * bitmap , uint64_t * used )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-03-11 21:10:27 +03:00
int ret = 0 ;
2005-04-17 02:20:36 +04:00
* used = 0 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_SPACE_USED - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_SPACE_USED ) ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , used ) ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_SPACE_USED ;
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_SPACE_USED ;
2005-04-17 02:20:36 +04:00
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: space used=%Lu \n " , __func__ ,
2005-04-17 02:20:36 +04:00
( unsigned long long ) * used ) ;
2009-03-11 21:10:27 +03:00
return ret ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_time ( struct xdr_stream * xdr , struct timespec * time )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
uint64_t sec ;
uint32_t nsec ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 12 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:41 +04:00
p = xdr_decode_hyper ( p , & sec ) ;
2009-08-14 18:20:19 +04:00
nsec = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
time - > tv_sec = ( time_t ) sec ;
time - > tv_nsec = ( long ) nsec ;
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_attr_time_access ( struct xdr_stream * xdr , uint32_t * bitmap , struct timespec * time )
{
int status = 0 ;
time - > tv_sec = 0 ;
time - > tv_nsec = 0 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_TIME_ACCESS - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_TIME_ACCESS ) ) {
status = decode_attr_time ( xdr , time ) ;
2009-03-11 21:10:27 +03:00
if ( status = = 0 )
status = NFS_ATTR_FATTR_ATIME ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_TIME_ACCESS ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: atime=%ld \n " , __func__ , ( long ) time - > tv_sec ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
static int decode_attr_time_metadata ( struct xdr_stream * xdr , uint32_t * bitmap , struct timespec * time )
{
int status = 0 ;
time - > tv_sec = 0 ;
time - > tv_nsec = 0 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_TIME_METADATA - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_TIME_METADATA ) ) {
status = decode_attr_time ( xdr , time ) ;
2009-03-11 21:10:27 +03:00
if ( status = = 0 )
status = NFS_ATTR_FATTR_CTIME ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_TIME_METADATA ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: ctime=%ld \n " , __func__ , ( long ) time - > tv_sec ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
2010-10-13 03:30:06 +04:00
static int decode_attr_time_delta ( struct xdr_stream * xdr , uint32_t * bitmap ,
struct timespec * time )
{
int status = 0 ;
time - > tv_sec = 0 ;
time - > tv_nsec = 0 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_TIME_DELTA - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_TIME_DELTA ) ) {
status = decode_attr_time ( xdr , time ) ;
bitmap [ 1 ] & = ~ FATTR4_WORD1_TIME_DELTA ;
}
dprintk ( " %s: time_delta=%ld %ld \n " , __func__ , ( long ) time - > tv_sec ,
( long ) time - > tv_nsec ) ;
return status ;
}
2013-05-22 20:50:44 +04:00
static int decode_attr_security_label ( struct xdr_stream * xdr , uint32_t * bitmap ,
struct nfs4_label * label )
{
uint32_t pi = 0 ;
uint32_t lfs = 0 ;
__u32 len ;
__be32 * p ;
int status = 0 ;
if ( unlikely ( bitmap [ 2 ] & ( FATTR4_WORD2_SECURITY_LABEL - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 2 ] & FATTR4_WORD2_SECURITY_LABEL ) ) {
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
lfs = be32_to_cpup ( p + + ) ;
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
pi = be32_to_cpup ( p + + ) ;
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
len = be32_to_cpup ( p + + ) ;
p = xdr_inline_decode ( xdr , len ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
if ( len < NFS4_MAXLABELLEN ) {
if ( label ) {
memcpy ( label - > label , p , len ) ;
label - > len = len ;
label - > pi = pi ;
label - > lfs = lfs ;
status = NFS_ATTR_FATTR_V4_SECURITY_LABEL ;
}
bitmap [ 2 ] & = ~ FATTR4_WORD2_SECURITY_LABEL ;
} else
printk ( KERN_WARNING " %s: label too long (%u)! \n " ,
__func__ , len ) ;
}
if ( label & & label - > label )
dprintk ( " %s: label=%s, len=%d, PI=%d, LFS=%d \n " , __func__ ,
( char * ) label - > label , label - > len , label - > pi , label - > lfs ) ;
return status ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
2005-04-17 02:20:36 +04:00
static int decode_attr_time_modify ( struct xdr_stream * xdr , uint32_t * bitmap , struct timespec * time )
{
int status = 0 ;
time - > tv_sec = 0 ;
time - > tv_nsec = 0 ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_TIME_MODIFY - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 1 ] & FATTR4_WORD1_TIME_MODIFY ) ) {
status = decode_attr_time ( xdr , time ) ;
2009-03-11 21:10:27 +03:00
if ( status = = 0 )
status = NFS_ATTR_FATTR_MTIME ;
2005-04-17 02:20:36 +04:00
bitmap [ 1 ] & = ~ FATTR4_WORD1_TIME_MODIFY ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: mtime=%ld \n " , __func__ , ( long ) time - > tv_sec ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
2012-06-21 19:18:13 +04:00
static int verify_attr_len ( struct xdr_stream * xdr , unsigned int savep , uint32_t attrlen )
2005-04-17 02:20:36 +04:00
{
unsigned int attrwords = XDR_QUADLEN ( attrlen ) ;
2012-06-21 19:18:13 +04:00
unsigned int nwords = ( xdr_stream_pos ( xdr ) - savep ) > > 2 ;
2005-04-17 02:20:36 +04:00
if ( unlikely ( attrwords ! = nwords ) ) {
2007-09-12 02:01:10 +04:00
dprintk ( " %s: server returned incorrect attribute length: "
" %u %c %u \n " ,
2008-05-03 00:42:44 +04:00
__func__ ,
2005-04-17 02:20:36 +04:00
attrwords < < 2 ,
( attrwords < nwords ) ? ' < ' : ' > ' ,
nwords < < 2 ) ;
return - EIO ;
}
return 0 ;
}
static int decode_change_info ( struct xdr_stream * xdr , struct nfs4_change_info * cinfo )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 20 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
cinfo - > atomic = be32_to_cpup ( p + + ) ;
2009-08-14 18:19:41 +04:00
p = xdr_decode_hyper ( p , & cinfo - > before ) ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , & cinfo - > after ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2012-09-10 22:00:46 +04:00
static int decode_access ( struct xdr_stream * xdr , u32 * supported , u32 * access )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
uint32_t supp , acc ;
int status ;
status = decode_op_hdr ( xdr , OP_ACCESS ) ;
if ( status )
return status ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
supp = be32_to_cpup ( p + + ) ;
2009-08-14 18:20:19 +04:00
acc = be32_to_cpup ( p ) ;
2012-09-10 22:00:46 +04:00
* supported = supp ;
* access = acc ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2009-08-14 18:19:52 +04:00
static int decode_opaque_fixed ( struct xdr_stream * xdr , void * buf , size_t len )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-08-14 18:19:52 +04:00
p = xdr_inline_decode ( xdr , len ) ;
if ( likely ( p ) ) {
memcpy ( buf , p , len ) ;
return 0 ;
}
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
static int decode_stateid ( struct xdr_stream * xdr , nfs4_stateid * stateid )
{
2012-03-05 03:13:57 +04:00
return decode_opaque_fixed ( xdr , stateid , NFS4_STATEID_SIZE ) ;
2009-08-14 18:19:52 +04:00
}
static int decode_close ( struct xdr_stream * xdr , struct nfs_closeres * res )
{
2005-04-17 02:20:36 +04:00
int status ;
status = decode_op_hdr ( xdr , OP_CLOSE ) ;
2008-04-07 21:20:54 +04:00
if ( status ! = - EIO )
nfs_increment_open_seqid ( status , res - > seqid ) ;
2009-08-14 18:19:52 +04:00
if ( ! status )
status = decode_stateid ( xdr , & res - > stateid ) ;
return status ;
2005-04-17 02:20:36 +04:00
}
2009-08-14 18:19:56 +04:00
static int decode_verifier ( struct xdr_stream * xdr , void * verifier )
{
2012-03-03 02:14:31 +04:00
return decode_opaque_fixed ( xdr , verifier , NFS4_VERIFIER_SIZE ) ;
2005-04-17 02:20:36 +04:00
}
2012-06-08 19:56:09 +04:00
static int decode_write_verifier ( struct xdr_stream * xdr , struct nfs_write_verifier * verifier )
{
return decode_opaque_fixed ( xdr , verifier - > data , NFS4_VERIFIER_SIZE ) ;
}
2012-04-20 22:47:39 +04:00
static int decode_commit ( struct xdr_stream * xdr , struct nfs_commitres * res )
2005-04-17 02:20:36 +04:00
{
int status ;
status = decode_op_hdr ( xdr , OP_COMMIT ) ;
2009-08-14 18:19:56 +04:00
if ( ! status )
2012-06-08 19:56:09 +04:00
status = decode_write_verifier ( xdr , & res - > verf - > verifier ) ;
2009-08-14 18:19:56 +04:00
return status ;
2005-04-17 02:20:36 +04:00
}
static int decode_create ( struct xdr_stream * xdr , struct nfs4_change_info * cinfo )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
uint32_t bmlen ;
int status ;
status = decode_op_hdr ( xdr , OP_CREATE ) ;
if ( status )
return status ;
if ( ( status = decode_change_info ( xdr , cinfo ) ) )
return status ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
bmlen = be32_to_cpup ( p ) ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , bmlen < < 2 ) ;
if ( likely ( p ) )
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_server_caps ( struct xdr_stream * xdr , struct nfs4_server_caps_res * res )
{
2012-06-21 19:18:13 +04:00
unsigned int savep ;
2011-07-31 04:52:37 +04:00
uint32_t attrlen , bitmap [ 3 ] = { 0 } ;
2005-04-17 02:20:36 +04:00
int status ;
if ( ( status = decode_op_hdr ( xdr , OP_GETATTR ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_bitmap ( xdr , bitmap ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_length ( xdr , & attrlen , & savep ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_supported ( xdr , bitmap , res - > attr_bitmask ) ) ! = 0 )
goto xdr_error ;
2012-03-02 02:02:05 +04:00
if ( ( status = decode_attr_fh_expire_type ( xdr , bitmap ,
& res - > fh_expire_type ) ) ! = 0 )
goto xdr_error ;
2005-04-17 02:20:36 +04:00
if ( ( status = decode_attr_link_support ( xdr , bitmap , & res - > has_links ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_symlink_support ( xdr , bitmap , & res - > has_symlinks ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_aclsupport ( xdr , bitmap , & res - > acl_bitmask ) ) ! = 0 )
goto xdr_error ;
status = verify_attr_len ( xdr , savep , attrlen ) ;
xdr_error :
2008-05-03 00:42:44 +04:00
dprintk ( " %s: xdr returned %d! \n " , __func__ , - status ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
static int decode_statfs ( struct xdr_stream * xdr , struct nfs_fsstat * fsstat )
{
2012-06-21 19:18:13 +04:00
unsigned int savep ;
2011-07-31 04:52:37 +04:00
uint32_t attrlen , bitmap [ 3 ] = { 0 } ;
2005-04-17 02:20:36 +04:00
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
if ( ( status = decode_op_hdr ( xdr , OP_GETATTR ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_bitmap ( xdr , bitmap ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_length ( xdr , & attrlen , & savep ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_files_avail ( xdr , bitmap , & fsstat - > afiles ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_files_free ( xdr , bitmap , & fsstat - > ffiles ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_files_total ( xdr , bitmap , & fsstat - > tfiles ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_space_avail ( xdr , bitmap , & fsstat - > abytes ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_space_free ( xdr , bitmap , & fsstat - > fbytes ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_space_total ( xdr , bitmap , & fsstat - > tbytes ) ) ! = 0 )
goto xdr_error ;
status = verify_attr_len ( xdr , savep , attrlen ) ;
xdr_error :
2008-05-03 00:42:44 +04:00
dprintk ( " %s: xdr returned %d! \n " , __func__ , - status ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
static int decode_pathconf ( struct xdr_stream * xdr , struct nfs_pathconf * pathconf )
{
2012-06-21 19:18:13 +04:00
unsigned int savep ;
2011-07-31 04:52:37 +04:00
uint32_t attrlen , bitmap [ 3 ] = { 0 } ;
2005-04-17 02:20:36 +04:00
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
if ( ( status = decode_op_hdr ( xdr , OP_GETATTR ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_bitmap ( xdr , bitmap ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_length ( xdr , & attrlen , & savep ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_maxlink ( xdr , bitmap , & pathconf - > max_link ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_maxname ( xdr , bitmap , & pathconf - > max_namelen ) ) ! = 0 )
goto xdr_error ;
status = verify_attr_len ( xdr , savep , attrlen ) ;
xdr_error :
2008-05-03 00:42:44 +04:00
dprintk ( " %s: xdr returned %d! \n " , __func__ , - status ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
2012-05-23 13:02:34 +04:00
static int decode_threshold_hint ( struct xdr_stream * xdr ,
uint32_t * bitmap ,
uint64_t * res ,
uint32_t hint_bit )
{
__be32 * p ;
* res = 0 ;
if ( likely ( bitmap [ 0 ] & hint_bit ) ) {
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
xdr_decode_hyper ( p , res ) ;
}
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
static int decode_first_threshold_item4 ( struct xdr_stream * xdr ,
struct nfs4_threshold * res )
{
2012-06-21 19:18:13 +04:00
__be32 * p ;
unsigned int savep ;
2012-05-23 13:02:34 +04:00
uint32_t bitmap [ 3 ] = { 0 , } , attrlen ;
int status ;
/* layout type */
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) ) {
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
res - > l_type = be32_to_cpup ( p ) ;
/* thi_hintset bitmap */
status = decode_attr_bitmap ( xdr , bitmap ) ;
if ( status < 0 )
goto xdr_error ;
/* thi_hintlist length */
status = decode_attr_length ( xdr , & attrlen , & savep ) ;
if ( status < 0 )
goto xdr_error ;
/* thi_hintlist */
status = decode_threshold_hint ( xdr , bitmap , & res - > rd_sz , THRESHOLD_RD ) ;
if ( status < 0 )
goto xdr_error ;
status = decode_threshold_hint ( xdr , bitmap , & res - > wr_sz , THRESHOLD_WR ) ;
if ( status < 0 )
goto xdr_error ;
status = decode_threshold_hint ( xdr , bitmap , & res - > rd_io_sz ,
THRESHOLD_RD_IO ) ;
if ( status < 0 )
goto xdr_error ;
status = decode_threshold_hint ( xdr , bitmap , & res - > wr_io_sz ,
THRESHOLD_WR_IO ) ;
if ( status < 0 )
goto xdr_error ;
status = verify_attr_len ( xdr , savep , attrlen ) ;
res - > bm = bitmap [ 0 ] ;
dprintk ( " %s bm=0x%x rd_sz=%llu wr_sz=%llu rd_io=%llu wr_io=%llu \n " ,
__func__ , res - > bm , res - > rd_sz , res - > wr_sz , res - > rd_io_sz ,
res - > wr_io_sz ) ;
xdr_error :
dprintk ( " %s ret=%d! \n " , __func__ , status ) ;
return status ;
}
/*
* Thresholds on pNFS direct I / O vrs MDS I / O
*/
static int decode_attr_mdsthreshold ( struct xdr_stream * xdr ,
uint32_t * bitmap ,
struct nfs4_threshold * res )
{
__be32 * p ;
int status = 0 ;
uint32_t num ;
if ( unlikely ( bitmap [ 2 ] & ( FATTR4_WORD2_MDSTHRESHOLD - 1U ) ) )
return - EIO ;
2012-06-05 17:35:44 +04:00
if ( bitmap [ 2 ] & FATTR4_WORD2_MDSTHRESHOLD ) {
2012-06-05 17:16:47 +04:00
/* Did the server return an unrequested attribute? */
if ( unlikely ( res = = NULL ) )
return - EREMOTEIO ;
2012-05-23 13:02:34 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
num = be32_to_cpup ( p ) ;
if ( num = = 0 )
return 0 ;
if ( num > 1 )
printk ( KERN_INFO " %s: Warning: Multiple pNFS layout "
" drivers per filesystem not supported \n " ,
__func__ ) ;
status = decode_first_threshold_item4 ( xdr , res ) ;
2012-06-05 17:35:44 +04:00
bitmap [ 2 ] & = ~ FATTR4_WORD2_MDSTHRESHOLD ;
2012-05-23 13:02:34 +04:00
}
return status ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
2010-10-22 00:33:17 +04:00
static int decode_getfattr_attrs ( struct xdr_stream * xdr , uint32_t * bitmap ,
struct nfs_fattr * fattr , struct nfs_fh * fh ,
2013-05-22 20:50:44 +04:00
struct nfs4_fs_locations * fs_loc , struct nfs4_label * label ,
2012-01-07 22:22:46 +04:00
const struct nfs_server * server )
2005-04-17 02:20:36 +04:00
{
2009-03-11 21:10:26 +03:00
int status ;
umode_t fmode = 0 ;
2010-10-22 00:33:17 +04:00
uint32_t type ;
2011-06-16 21:15:41 +04:00
int32_t err ;
2005-04-17 02:20:36 +04:00
2009-03-11 21:10:26 +03:00
status = decode_attr_type ( xdr , bitmap , & type ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > mode = 0 ;
if ( status ! = 0 ) {
fattr - > mode | = nfs_type2fmt [ type ] ;
fattr - > valid | = status ;
}
2005-04-17 02:20:36 +04:00
2009-03-11 21:10:26 +03:00
status = decode_attr_change ( xdr , bitmap , & fattr - > change_attr ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
status = decode_attr_size ( xdr , bitmap , & fattr - > size ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
status = decode_attr_fsid ( xdr , bitmap , & fattr - > fsid ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
2011-06-16 21:15:41 +04:00
err = 0 ;
status = decode_attr_error ( xdr , bitmap , & err ) ;
2010-10-22 00:33:17 +04:00
if ( status < 0 )
goto xdr_error ;
status = decode_attr_filehandle ( xdr , bitmap , fh ) ;
if ( status < 0 )
goto xdr_error ;
2009-03-11 21:10:26 +03:00
status = decode_attr_fileid ( xdr , bitmap , & fattr - > fileid ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
2012-01-31 00:43:56 +04:00
status = decode_attr_fs_locations ( xdr , bitmap , fs_loc ) ;
2009-03-11 21:10:26 +03:00
if ( status < 0 )
2006-06-09 17:34:22 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
status = decode_attr_mode ( xdr , bitmap , & fmode ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
if ( status ! = 0 ) {
fattr - > mode | = fmode ;
fattr - > valid | = status ;
}
2009-03-11 21:10:26 +03:00
status = decode_attr_nlink ( xdr , bitmap , & fattr - > nlink ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
2012-01-07 22:22:46 +04:00
status = decode_attr_owner ( xdr , bitmap , server , & fattr - > uid , fattr - > owner_name ) ;
2009-03-11 21:10:26 +03:00
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
2012-01-07 22:22:46 +04:00
status = decode_attr_group ( xdr , bitmap , server , & fattr - > gid , fattr - > group_name ) ;
2009-03-11 21:10:26 +03:00
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
status = decode_attr_rdev ( xdr , bitmap , & fattr - > rdev ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
status = decode_attr_space_used ( xdr , bitmap , & fattr - > du . nfs3 . used ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
status = decode_attr_time_access ( xdr , bitmap , & fattr - > atime ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
status = decode_attr_time_metadata ( xdr , bitmap , & fattr - > ctime ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
status = decode_attr_time_modify ( xdr , bitmap , & fattr - > mtime ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
2011-04-27 21:47:52 +04:00
status = decode_attr_mounted_on_fileid ( xdr , bitmap , & fattr - > mounted_on_fileid ) ;
2009-03-11 21:10:26 +03:00
if ( status < 0 )
2006-06-09 17:34:24 +04:00
goto xdr_error ;
2011-04-27 21:47:52 +04:00
fattr - > valid | = status ;
2009-03-11 21:10:26 +03:00
2012-05-23 13:02:34 +04:00
status = decode_attr_mdsthreshold ( xdr , bitmap , fattr - > mdsthreshold ) ;
if ( status < 0 )
goto xdr_error ;
2013-05-22 20:50:44 +04:00
if ( label ) {
status = decode_attr_security_label ( xdr , bitmap , label ) ;
if ( status < 0 )
goto xdr_error ;
fattr - > valid | = status ;
}
2010-10-22 00:33:17 +04:00
xdr_error :
dprintk ( " %s: xdr returned %d \n " , __func__ , - status ) ;
return status ;
}
static int decode_getfattr_generic ( struct xdr_stream * xdr , struct nfs_fattr * fattr ,
2012-01-31 00:43:56 +04:00
struct nfs_fh * fh , struct nfs4_fs_locations * fs_loc ,
2013-05-22 20:50:44 +04:00
struct nfs4_label * label , const struct nfs_server * server )
2010-10-22 00:33:17 +04:00
{
2012-06-21 19:18:13 +04:00
unsigned int savep ;
2010-10-22 00:33:17 +04:00
uint32_t attrlen ,
2011-07-31 04:52:37 +04:00
bitmap [ 3 ] = { 0 } ;
2010-10-22 00:33:17 +04:00
int status ;
status = decode_op_hdr ( xdr , OP_GETATTR ) ;
if ( status < 0 )
goto xdr_error ;
status = decode_attr_bitmap ( xdr , bitmap ) ;
if ( status < 0 )
goto xdr_error ;
status = decode_attr_length ( xdr , & attrlen , & savep ) ;
if ( status < 0 )
goto xdr_error ;
2013-05-22 20:50:44 +04:00
status = decode_getfattr_attrs ( xdr , bitmap , fattr , fh , fs_loc ,
label , server ) ;
2010-10-22 00:33:17 +04:00
if ( status < 0 )
goto xdr_error ;
2009-03-11 21:10:26 +03:00
status = verify_attr_len ( xdr , savep , attrlen ) ;
2005-04-17 02:20:36 +04:00
xdr_error :
2008-05-03 00:42:44 +04:00
dprintk ( " %s: xdr returned %d \n " , __func__ , - status ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
2013-05-22 20:50:44 +04:00
static int decode_getfattr_label ( struct xdr_stream * xdr , struct nfs_fattr * fattr ,
struct nfs4_label * label , const struct nfs_server * server )
{
return decode_getfattr_generic ( xdr , fattr , NULL , NULL , label , server ) ;
}
2010-10-22 00:33:17 +04:00
static int decode_getfattr ( struct xdr_stream * xdr , struct nfs_fattr * fattr ,
2012-01-07 22:22:46 +04:00
const struct nfs_server * server )
2010-10-22 00:33:17 +04:00
{
2013-05-22 20:50:44 +04:00
return decode_getfattr_generic ( xdr , fattr , NULL , NULL , NULL , server ) ;
2010-10-22 00:33:17 +04:00
}
2005-04-17 02:20:36 +04:00
2010-10-20 08:17:57 +04:00
/*
* Decode potentially multiple layout types . Currently we only support
* one layout driver per file system .
*/
static int decode_first_pnfs_layout_type ( struct xdr_stream * xdr ,
uint32_t * layouttype )
{
2013-08-21 05:08:56 +04:00
__be32 * p ;
2010-10-20 08:17:57 +04:00
int num ;
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
num = be32_to_cpup ( p ) ;
/* pNFS is not supported by the underlying file system */
if ( num = = 0 ) {
* layouttype = 0 ;
return 0 ;
}
if ( num > 1 )
2012-01-26 22:32:23 +04:00
printk ( KERN_INFO " NFS: %s: Warning: Multiple pNFS layout "
" drivers per filesystem not supported \n " , __func__ ) ;
2010-10-20 08:17:57 +04:00
/* Decode and set first layout type, move xdr->p past unused types */
p = xdr_inline_decode ( xdr , num * 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
* layouttype = be32_to_cpup ( p ) ;
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
/*
* The type of file system exported .
* Note we must ensure that layouttype is set in any non - error case .
*/
static int decode_attr_pnfstype ( struct xdr_stream * xdr , uint32_t * bitmap ,
uint32_t * layouttype )
{
int status = 0 ;
dprintk ( " %s: bitmap is %x \n " , __func__ , bitmap [ 1 ] ) ;
if ( unlikely ( bitmap [ 1 ] & ( FATTR4_WORD1_FS_LAYOUT_TYPES - 1U ) ) )
return - EIO ;
if ( bitmap [ 1 ] & FATTR4_WORD1_FS_LAYOUT_TYPES ) {
status = decode_first_pnfs_layout_type ( xdr , layouttype ) ;
bitmap [ 1 ] & = ~ FATTR4_WORD1_FS_LAYOUT_TYPES ;
} else
* layouttype = 0 ;
return status ;
}
2011-07-31 04:52:37 +04:00
/*
* The prefered block size for layout directed io
*/
static int decode_attr_layout_blksize ( struct xdr_stream * xdr , uint32_t * bitmap ,
uint32_t * res )
{
__be32 * p ;
dprintk ( " %s: bitmap is %x \n " , __func__ , bitmap [ 2 ] ) ;
* res = 0 ;
if ( bitmap [ 2 ] & FATTR4_WORD2_LAYOUT_BLKSIZE ) {
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) ) {
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
* res = be32_to_cpup ( p ) ;
bitmap [ 2 ] & = ~ FATTR4_WORD2_LAYOUT_BLKSIZE ;
}
return 0 ;
}
2005-04-17 02:20:36 +04:00
static int decode_fsinfo ( struct xdr_stream * xdr , struct nfs_fsinfo * fsinfo )
{
2012-06-21 19:18:13 +04:00
unsigned int savep ;
2011-07-31 04:52:37 +04:00
uint32_t attrlen , bitmap [ 3 ] ;
2005-04-17 02:20:36 +04:00
int status ;
if ( ( status = decode_op_hdr ( xdr , OP_GETATTR ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_bitmap ( xdr , bitmap ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_length ( xdr , & attrlen , & savep ) ) ! = 0 )
goto xdr_error ;
fsinfo - > rtmult = fsinfo - > wtmult = 512 ; /* ??? */
if ( ( status = decode_attr_lease_time ( xdr , bitmap , & fsinfo - > lease_time ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_maxfilesize ( xdr , bitmap , & fsinfo - > maxfilesize ) ) ! = 0 )
goto xdr_error ;
if ( ( status = decode_attr_maxread ( xdr , bitmap , & fsinfo - > rtmax ) ) ! = 0 )
goto xdr_error ;
fsinfo - > rtpref = fsinfo - > dtpref = fsinfo - > rtmax ;
if ( ( status = decode_attr_maxwrite ( xdr , bitmap , & fsinfo - > wtmax ) ) ! = 0 )
goto xdr_error ;
fsinfo - > wtpref = fsinfo - > wtmax ;
2010-10-13 03:30:06 +04:00
status = decode_attr_time_delta ( xdr , bitmap , & fsinfo - > time_delta ) ;
2010-10-20 08:17:57 +04:00
if ( status ! = 0 )
goto xdr_error ;
status = decode_attr_pnfstype ( xdr , bitmap , & fsinfo - > layouttype ) ;
2010-10-13 03:30:06 +04:00
if ( status ! = 0 )
goto xdr_error ;
2011-07-31 04:52:37 +04:00
status = decode_attr_layout_blksize ( xdr , bitmap , & fsinfo - > blksize ) ;
if ( status )
goto xdr_error ;
2005-04-17 02:20:36 +04:00
status = verify_attr_len ( xdr , savep , attrlen ) ;
xdr_error :
2008-05-03 00:42:44 +04:00
dprintk ( " %s: xdr returned %d! \n " , __func__ , - status ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
static int decode_getfh ( struct xdr_stream * xdr , struct nfs_fh * fh )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
uint32_t len ;
int status ;
2007-07-18 05:52:41 +04:00
/* Zero handle first to allow comparisons */
memset ( fh , 0 , sizeof ( * fh ) ) ;
2005-04-17 02:20:36 +04:00
status = decode_op_hdr ( xdr , OP_GETFH ) ;
if ( status )
return status ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
len = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
if ( len > NFS4_FHSIZE )
return - EIO ;
fh - > size = len ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , len ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:05 +04:00
memcpy ( fh - > data , p , len ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_link ( struct xdr_stream * xdr , struct nfs4_change_info * cinfo )
{
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
status = decode_op_hdr ( xdr , OP_LINK ) ;
if ( status )
return status ;
return decode_change_info ( xdr , cinfo ) ;
}
/*
* We create the owner , so we know a proper owner . id length is 4.
*/
2006-01-03 11:55:16 +03:00
static int decode_lock_denied ( struct xdr_stream * xdr , struct file_lock * fl )
2005-04-17 02:20:36 +04:00
{
2006-01-03 11:55:16 +03:00
uint64_t offset , length , clientid ;
2006-10-20 10:28:48 +04:00
__be32 * p ;
2006-01-03 11:55:16 +03:00
uint32_t namelen , type ;
2005-04-17 02:20:36 +04:00
2010-10-20 23:44:29 +04:00
p = xdr_inline_decode ( xdr , 32 ) ; /* read 32 bytes */
2009-08-14 18:20:14 +04:00
if ( unlikely ( ! p ) )
goto out_overflow ;
2010-10-20 23:44:29 +04:00
p = xdr_decode_hyper ( p , & offset ) ; /* read 2 8-byte long words */
2009-08-14 18:19:41 +04:00
p = xdr_decode_hyper ( p , & length ) ;
2010-10-20 23:44:29 +04:00
type = be32_to_cpup ( p + + ) ; /* 4 byte read */
if ( fl ! = NULL ) { /* manipulate file lock */
2006-01-03 11:55:16 +03:00
fl - > fl_start = ( loff_t ) offset ;
fl - > fl_end = fl - > fl_start + ( loff_t ) length - 1 ;
if ( length = = ~ ( uint64_t ) 0 )
fl - > fl_end = OFFSET_MAX ;
fl - > fl_type = F_WRLCK ;
if ( type & 1 )
fl - > fl_type = F_RDLCK ;
fl - > fl_pid = 0 ;
}
2010-10-20 23:44:29 +04:00
p = xdr_decode_hyper ( p , & clientid ) ; /* read 8 bytes */
namelen = be32_to_cpup ( p ) ; /* read 4 bytes */ /* have read all 32 bytes now */
p = xdr_inline_decode ( xdr , namelen ) ; /* variable size field */
2009-08-14 18:20:14 +04:00
if ( likely ( p ) )
return - NFS4ERR_DENIED ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2006-01-03 11:55:16 +03:00
static int decode_lock ( struct xdr_stream * xdr , struct nfs_lock_res * res )
2005-04-17 02:20:36 +04:00
{
int status ;
status = decode_op_hdr ( xdr , OP_LOCK ) ;
2008-04-07 21:20:54 +04:00
if ( status = = - EIO )
goto out ;
2005-04-17 02:20:36 +04:00
if ( status = = 0 ) {
2009-08-14 18:19:52 +04:00
status = decode_stateid ( xdr , & res - > stateid ) ;
if ( unlikely ( status ) )
goto out ;
2005-04-17 02:20:36 +04:00
} else if ( status = = - NFS4ERR_DENIED )
2008-04-07 21:20:54 +04:00
status = decode_lock_denied ( xdr , NULL ) ;
if ( res - > open_seqid ! = NULL )
nfs_increment_open_seqid ( status , res - > open_seqid ) ;
nfs_increment_lock_seqid ( status , res - > lock_seqid ) ;
out :
2005-04-17 02:20:36 +04:00
return status ;
}
2006-01-03 11:55:16 +03:00
static int decode_lockt ( struct xdr_stream * xdr , struct nfs_lockt_res * res )
2005-04-17 02:20:36 +04:00
{
int status ;
status = decode_op_hdr ( xdr , OP_LOCKT ) ;
if ( status = = - NFS4ERR_DENIED )
2006-01-03 11:55:16 +03:00
return decode_lock_denied ( xdr , res - > denied ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
2006-01-03 11:55:16 +03:00
static int decode_locku ( struct xdr_stream * xdr , struct nfs_locku_res * res )
2005-04-17 02:20:36 +04:00
{
int status ;
status = decode_op_hdr ( xdr , OP_LOCKU ) ;
2008-04-07 21:20:54 +04:00
if ( status ! = - EIO )
nfs_increment_lock_seqid ( status , res - > seqid ) ;
2009-08-14 18:19:52 +04:00
if ( status = = 0 )
status = decode_stateid ( xdr , & res - > stateid ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
2010-07-01 20:49:01 +04:00
static int decode_release_lockowner ( struct xdr_stream * xdr )
{
return decode_op_hdr ( xdr , OP_RELEASE_LOCKOWNER ) ;
}
2005-04-17 02:20:36 +04:00
static int decode_lookup ( struct xdr_stream * xdr )
{
return decode_op_hdr ( xdr , OP_LOOKUP ) ;
}
/* This is too sick! */
static int decode_space_limit ( struct xdr_stream * xdr , u64 * maxsize )
{
2008-12-24 00:06:15 +03:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
uint32_t limit_type , nblocks , blocksize ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 12 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
limit_type = be32_to_cpup ( p + + ) ;
2005-04-17 02:20:36 +04:00
switch ( limit_type ) {
2008-12-24 00:06:15 +03:00
case 1 :
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , maxsize ) ;
2008-12-24 00:06:15 +03:00
break ;
case 2 :
2009-08-14 18:19:37 +04:00
nblocks = be32_to_cpup ( p + + ) ;
2009-08-14 18:20:19 +04:00
blocksize = be32_to_cpup ( p ) ;
2008-12-24 00:06:15 +03:00
* maxsize = ( uint64_t ) nblocks * ( uint64_t ) blocksize ;
2005-04-17 02:20:36 +04:00
}
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_delegation ( struct xdr_stream * xdr , struct nfs_openres * res )
{
2008-12-24 00:06:15 +03:00
__be32 * p ;
uint32_t delegation_type ;
2009-08-14 18:19:52 +04:00
int status ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
delegation_type = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
if ( delegation_type = = NFS4_OPEN_DELEGATE_NONE ) {
res - > delegation_type = 0 ;
return 0 ;
}
2009-08-14 18:19:52 +04:00
status = decode_stateid ( xdr , & res - > delegation ) ;
if ( unlikely ( status ) )
return status ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
res - > do_recall = be32_to_cpup ( p ) ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
switch ( delegation_type ) {
2008-12-24 00:06:15 +03:00
case NFS4_OPEN_DELEGATE_READ :
res - > delegation_type = FMODE_READ ;
break ;
case NFS4_OPEN_DELEGATE_WRITE :
res - > delegation_type = FMODE_WRITE | FMODE_READ ;
if ( decode_space_limit ( xdr , & res - > maxsize ) < 0 )
2005-04-17 02:20:36 +04:00
return - EIO ;
}
2006-08-23 04:06:09 +04:00
return decode_ace ( xdr , NULL , res - > server - > nfs_client ) ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_open ( struct xdr_stream * xdr , struct nfs_openres * res )
{
2008-12-24 00:06:15 +03:00
__be32 * p ;
2007-06-05 22:49:03 +04:00
uint32_t savewords , bmlen , i ;
2008-12-24 00:06:15 +03:00
int status ;
2005-04-17 02:20:36 +04:00
2008-12-24 00:06:15 +03:00
status = decode_op_hdr ( xdr , OP_OPEN ) ;
2008-04-07 21:20:54 +04:00
if ( status ! = - EIO )
nfs_increment_open_seqid ( status , res - > seqid ) ;
2009-08-14 18:19:52 +04:00
if ( ! status )
status = decode_stateid ( xdr , & res - > stateid ) ;
if ( unlikely ( status ) )
2008-12-24 00:06:15 +03:00
return status ;
2005-04-17 02:20:36 +04:00
2008-12-24 00:06:15 +03:00
decode_change_info ( xdr , & res - > cinfo ) ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
res - > rflags = be32_to_cpup ( p + + ) ;
2009-08-14 18:20:19 +04:00
bmlen = be32_to_cpup ( p ) ;
2008-12-24 00:06:15 +03:00
if ( bmlen > 10 )
goto xdr_error ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , bmlen < < 2 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2007-06-05 22:49:03 +04:00
savewords = min_t ( uint32_t , bmlen , NFS4_BITMAP_SIZE ) ;
for ( i = 0 ; i < savewords ; + + i )
2009-08-14 18:19:37 +04:00
res - > attrset [ i ] = be32_to_cpup ( p + + ) ;
2007-06-05 22:49:03 +04:00
for ( ; i < NFS4_BITMAP_SIZE ; i + + )
res - > attrset [ i ] = 0 ;
2005-04-17 02:20:36 +04:00
return decode_delegation ( xdr , res ) ;
xdr_error :
2008-05-03 00:42:44 +04:00
dprintk ( " %s: Bitmap too large! Length = %u \n " , __func__ , bmlen ) ;
2005-04-17 02:20:36 +04:00
return - EIO ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_open_confirm ( struct xdr_stream * xdr , struct nfs_open_confirmres * res )
{
int status ;
2008-12-24 00:06:15 +03:00
status = decode_op_hdr ( xdr , OP_OPEN_CONFIRM ) ;
2008-04-07 21:20:54 +04:00
if ( status ! = - EIO )
nfs_increment_open_seqid ( status , res - > seqid ) ;
2009-08-14 18:19:52 +04:00
if ( ! status )
status = decode_stateid ( xdr , & res - > stateid ) ;
return status ;
2005-04-17 02:20:36 +04:00
}
static int decode_open_downgrade ( struct xdr_stream * xdr , struct nfs_closeres * res )
{
int status ;
status = decode_op_hdr ( xdr , OP_OPEN_DOWNGRADE ) ;
2008-04-07 21:20:54 +04:00
if ( status ! = - EIO )
nfs_increment_open_seqid ( status , res - > seqid ) ;
2009-08-14 18:19:52 +04:00
if ( ! status )
status = decode_stateid ( xdr , & res - > stateid ) ;
return status ;
2005-04-17 02:20:36 +04:00
}
static int decode_putfh ( struct xdr_stream * xdr )
{
return decode_op_hdr ( xdr , OP_PUTFH ) ;
}
static int decode_putrootfh ( struct xdr_stream * xdr )
{
return decode_op_hdr ( xdr , OP_PUTROOTFH ) ;
}
static int decode_read ( struct xdr_stream * xdr , struct rpc_rqst * req , struct nfs_readres * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2012-06-21 06:35:05 +04:00
uint32_t count , eof , recvd ;
2005-04-17 02:20:36 +04:00
int status ;
status = decode_op_hdr ( xdr , OP_READ ) ;
if ( status )
return status ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
eof = be32_to_cpup ( p + + ) ;
2009-08-14 18:20:19 +04:00
count = be32_to_cpup ( p ) ;
2012-06-21 06:35:05 +04:00
recvd = xdr_read_pages ( xdr , count ) ;
2005-04-17 02:20:36 +04:00
if ( count > recvd ) {
2007-09-12 02:01:10 +04:00
dprintk ( " NFS: server cheating in read reply: "
2005-04-17 02:20:36 +04:00
" count %u > recvd %u \n " , count , recvd ) ;
count = recvd ;
eof = 0 ;
}
res - > eof = eof ;
res - > count = count ;
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_readdir ( struct xdr_stream * xdr , struct rpc_rqst * req , struct nfs4_readdir_res * readdir )
{
2007-10-26 21:32:03 +04:00
int status ;
2012-03-03 02:14:31 +04:00
__be32 verf [ 2 ] ;
2005-04-17 02:20:36 +04:00
status = decode_op_hdr ( xdr , OP_READDIR ) ;
2009-08-14 18:19:56 +04:00
if ( ! status )
status = decode_verifier ( xdr , readdir - > verifier . data ) ;
if ( unlikely ( status ) )
2005-04-17 02:20:36 +04:00
return status ;
2012-03-03 02:14:31 +04:00
memcpy ( verf , readdir - > verifier . data , sizeof ( verf ) ) ;
2008-04-02 16:21:15 +04:00
dprintk ( " %s: verifier = %08x:%08x \n " ,
2012-03-03 02:14:31 +04:00
__func__ , verf [ 0 ] , verf [ 1 ] ) ;
2012-06-21 06:35:05 +04:00
return xdr_read_pages ( xdr , xdr - > buf - > page_len ) ;
2005-04-17 02:20:36 +04:00
}
static int decode_readlink ( struct xdr_stream * xdr , struct rpc_rqst * req )
{
struct xdr_buf * rcvbuf = & req - > rq_rcv_buf ;
2007-10-26 21:32:03 +04:00
u32 len , recvd ;
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status ;
status = decode_op_hdr ( xdr , OP_READLINK ) ;
if ( status )
return status ;
/* Convert length of symlink */
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
len = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
if ( len > = rcvbuf - > page_len | | len < = 0 ) {
2007-09-12 02:01:10 +04:00
dprintk ( " nfs: server returned giant symlink! \n " ) ;
2005-04-17 02:20:36 +04:00
return - ENAMETOOLONG ;
}
2012-06-21 06:35:05 +04:00
recvd = xdr_read_pages ( xdr , len ) ;
2005-04-17 02:20:36 +04:00
if ( recvd < len ) {
2007-09-12 02:01:10 +04:00
dprintk ( " NFS: server cheating in readlink reply: "
2005-04-17 02:20:36 +04:00
" count %u > recvd %u \n " , len , recvd ) ;
return - EIO ;
}
/*
* The XDR encode routine has set things up so that
* the link text will be copied directly into the
* buffer . We just have to do overflow - checking ,
* and and null - terminate the text ( the VFS expects
* null - termination ) .
*/
2010-09-22 00:55:48 +04:00
xdr_terminate_string ( rcvbuf , len ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_remove ( struct xdr_stream * xdr , struct nfs4_change_info * cinfo )
{
int status ;
status = decode_op_hdr ( xdr , OP_REMOVE ) ;
if ( status )
goto out ;
status = decode_change_info ( xdr , cinfo ) ;
out :
return status ;
}
static int decode_rename ( struct xdr_stream * xdr , struct nfs4_change_info * old_cinfo ,
struct nfs4_change_info * new_cinfo )
{
int status ;
status = decode_op_hdr ( xdr , OP_RENAME ) ;
if ( status )
goto out ;
if ( ( status = decode_change_info ( xdr , old_cinfo ) ) )
goto out ;
status = decode_change_info ( xdr , new_cinfo ) ;
out :
return status ;
}
static int decode_renew ( struct xdr_stream * xdr )
{
return decode_op_hdr ( xdr , OP_RENEW ) ;
}
2005-10-28 06:12:40 +04:00
static int
decode_restorefh ( struct xdr_stream * xdr )
{
return decode_op_hdr ( xdr , OP_RESTOREFH ) ;
}
2005-06-22 21:16:22 +04:00
static int decode_getacl ( struct xdr_stream * xdr , struct rpc_rqst * req ,
2011-12-07 20:55:27 +04:00
struct nfs_getaclres * res )
2005-06-22 21:16:22 +04:00
{
2012-06-21 19:18:13 +04:00
unsigned int savep ;
2005-06-22 21:16:22 +04:00
uint32_t attrlen ,
2011-07-31 04:52:37 +04:00
bitmap [ 3 ] = { 0 } ;
2005-06-22 21:16:22 +04:00
int status ;
2012-08-15 01:14:17 +04:00
unsigned int pg_offset ;
2005-06-22 21:16:22 +04:00
2011-12-07 20:55:27 +04:00
res - > acl_len = 0 ;
2005-06-22 21:16:22 +04:00
if ( ( status = decode_op_hdr ( xdr , OP_GETATTR ) ) ! = 0 )
goto out ;
2012-04-17 17:35:39 +04:00
2012-08-15 01:30:10 +04:00
xdr_enter_page ( xdr , xdr - > buf - > page_len ) ;
2012-08-15 01:14:17 +04:00
/* Calculate the offset of the page data */
pg_offset = xdr - > buf - > head [ 0 ] . iov_len ;
2012-04-17 17:35:39 +04:00
2005-06-22 21:16:22 +04:00
if ( ( status = decode_attr_bitmap ( xdr , bitmap ) ) ! = 0 )
goto out ;
if ( ( status = decode_attr_length ( xdr , & attrlen , & savep ) ) ! = 0 )
goto out ;
if ( unlikely ( bitmap [ 0 ] & ( FATTR4_WORD0_ACL - 1U ) ) )
return - EIO ;
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_ACL ) ) {
2011-12-07 20:55:27 +04:00
/* The bitmap (xdr len + bitmaps) and the attr xdr len words
* are stored with the acl data to handle the problem of
* variable length bitmaps . */
2012-08-15 01:14:17 +04:00
res - > acl_data_offset = xdr_stream_pos ( xdr ) - pg_offset ;
2012-08-15 01:30:10 +04:00
res - > acl_len = attrlen ;
2012-08-26 22:44:43 +04:00
/* Check for receive buffer overflow */
if ( res - > acl_len > ( xdr - > nwords < < 2 ) | |
res - > acl_len + res - > acl_data_offset > xdr - > buf - > page_len ) {
res - > acl_flags | = NFS4_ACL_TRUNC ;
2012-08-15 01:30:10 +04:00
dprintk ( " NFS: acl reply: attrlen %u > page_len %u \n " ,
2012-08-15 01:14:17 +04:00
attrlen , xdr - > nwords < < 2 ) ;
2005-06-22 21:16:22 +04:00
}
2005-10-14 00:54:27 +04:00
} else
status = - EOPNOTSUPP ;
2005-06-22 21:16:22 +04:00
out :
return status ;
}
2005-04-17 02:20:36 +04:00
static int
decode_savefh ( struct xdr_stream * xdr )
{
return decode_op_hdr ( xdr , OP_SAVEFH ) ;
}
2009-04-01 17:22:00 +04:00
static int decode_setattr ( struct xdr_stream * xdr )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
uint32_t bmlen ;
int status ;
status = decode_op_hdr ( xdr , OP_SETATTR ) ;
if ( status )
return status ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
bmlen = be32_to_cpup ( p ) ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , bmlen < < 2 ) ;
if ( likely ( p ) )
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
2010-04-17 00:43:06 +04:00
static int decode_setclientid ( struct xdr_stream * xdr , struct nfs4_setclientid_res * res )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
uint32_t opnum ;
int32_t nfserr ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
opnum = be32_to_cpup ( p + + ) ;
2005-04-17 02:20:36 +04:00
if ( opnum ! = OP_SETCLIENTID ) {
2007-09-12 02:01:10 +04:00
dprintk ( " nfs: decode_setclientid: Server returned operation "
2008-12-24 00:06:15 +03:00
" %d \n " , opnum ) ;
2005-04-17 02:20:36 +04:00
return - EIO ;
}
2009-08-14 18:20:19 +04:00
nfserr = be32_to_cpup ( p ) ;
2005-04-17 02:20:36 +04:00
if ( nfserr = = NFS_OK ) {
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 + NFS4_VERIFIER_SIZE ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2010-04-17 00:43:06 +04:00
p = xdr_decode_hyper ( p , & res - > clientid ) ;
memcpy ( res - > confirm . data , p , NFS4_VERIFIER_SIZE ) ;
2005-04-17 02:20:36 +04:00
} else if ( nfserr = = NFSERR_CLID_INUSE ) {
uint32_t len ;
/* skip netid string */
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
len = be32_to_cpup ( p ) ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , len ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2005-04-17 02:20:36 +04:00
/* skip uaddr string */
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:19 +04:00
len = be32_to_cpup ( p ) ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , len ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2005-04-17 02:20:36 +04:00
return - NFSERR_CLID_INUSE ;
} else
2008-03-31 18:39:06 +04:00
return nfs4_stat_to_errno ( nfserr ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_setclientid_confirm ( struct xdr_stream * xdr )
{
return decode_op_hdr ( xdr , OP_SETCLIENTID_CONFIRM ) ;
}
static int decode_write ( struct xdr_stream * xdr , struct nfs_writeres * res )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
int status ;
status = decode_op_hdr ( xdr , OP_WRITE ) ;
if ( status )
return status ;
2012-06-08 19:56:09 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
2009-08-14 18:20:14 +04:00
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
res - > count = be32_to_cpup ( p + + ) ;
res - > verf - > committed = be32_to_cpup ( p + + ) ;
2012-06-08 19:56:09 +04:00
return decode_write_verifier ( xdr , & res - > verf - > verifier ) ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2005-04-17 02:20:36 +04:00
}
static int decode_delegreturn ( struct xdr_stream * xdr )
{
return decode_op_hdr ( xdr , OP_DELEGRETURN ) ;
}
2013-03-16 23:54:34 +04:00
static int decode_secinfo_gss ( struct xdr_stream * xdr ,
struct nfs4_secinfo4 * flavor )
2011-03-24 20:12:29 +03:00
{
2013-03-16 23:54:34 +04:00
u32 oid_len ;
2011-03-24 20:12:29 +03:00
__be32 * p ;
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2013-03-16 23:54:34 +04:00
oid_len = be32_to_cpup ( p ) ;
if ( oid_len > GSS_OID_MAX_LEN )
2011-03-24 20:12:29 +03:00
goto out_err ;
2013-03-16 23:54:34 +04:00
p = xdr_inline_decode ( xdr , oid_len ) ;
2011-03-24 20:12:29 +03:00
if ( unlikely ( ! p ) )
goto out_overflow ;
2013-03-16 23:54:34 +04:00
memcpy ( flavor - > flavor_info . oid . data , p , oid_len ) ;
flavor - > flavor_info . oid . len = oid_len ;
2011-03-24 20:12:29 +03:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2013-03-16 23:54:34 +04:00
flavor - > flavor_info . qop = be32_to_cpup ( p + + ) ;
flavor - > flavor_info . service = be32_to_cpup ( p ) ;
2011-03-24 20:12:29 +03:00
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
out_err :
return - EINVAL ;
}
2012-04-27 21:27:38 +04:00
static int decode_secinfo_common ( struct xdr_stream * xdr , struct nfs4_secinfo_res * res )
2011-03-24 20:12:29 +03:00
{
2013-03-16 23:54:34 +04:00
struct nfs4_secinfo4 * sec_flavor ;
unsigned int i , num_flavors ;
2011-03-24 20:12:29 +03:00
int status ;
__be32 * p ;
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2011-04-13 22:31:31 +04:00
res - > flavors - > num_flavors = 0 ;
num_flavors = be32_to_cpup ( p ) ;
for ( i = 0 ; i < num_flavors ; i + + ) {
2011-03-24 20:12:29 +03:00
sec_flavor = & res - > flavors - > flavors [ i ] ;
2011-04-13 22:31:31 +04:00
if ( ( char * ) & sec_flavor [ 1 ] - ( char * ) res - > flavors > PAGE_SIZE )
2011-03-24 20:12:29 +03:00
break ;
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
sec_flavor - > flavor = be32_to_cpup ( p ) ;
if ( sec_flavor - > flavor = = RPC_AUTH_GSS ) {
2011-04-27 23:28:44 +04:00
status = decode_secinfo_gss ( xdr , sec_flavor ) ;
if ( status )
goto out ;
2011-03-24 20:12:29 +03:00
}
2011-04-13 22:31:31 +04:00
res - > flavors - > num_flavors + + ;
2011-03-24 20:12:29 +03:00
}
2012-04-27 21:27:38 +04:00
status = 0 ;
2011-04-27 23:28:44 +04:00
out :
return status ;
2011-03-24 20:12:29 +03:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
2012-04-27 21:27:38 +04:00
static int decode_secinfo ( struct xdr_stream * xdr , struct nfs4_secinfo_res * res )
{
int status = decode_op_hdr ( xdr , OP_SECINFO ) ;
if ( status )
return status ;
return decode_secinfo_common ( xdr , res ) ;
}
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
2012-04-27 21:27:38 +04:00
static int decode_secinfo_no_name ( struct xdr_stream * xdr , struct nfs4_secinfo_res * res )
{
int status = decode_op_hdr ( xdr , OP_SECINFO_NO_NAME ) ;
if ( status )
return status ;
return decode_secinfo_common ( xdr , res ) ;
}
2013-08-14 00:37:32 +04:00
static int decode_op_map ( struct xdr_stream * xdr , struct nfs4_op_map * op_map )
{
__be32 * p ;
uint32_t bitmap_words ;
unsigned int i ;
p = xdr_inline_decode ( xdr , 4 ) ;
bitmap_words = be32_to_cpup ( p + + ) ;
if ( bitmap_words > NFS4_OP_MAP_NUM_WORDS )
return - EIO ;
p = xdr_inline_decode ( xdr , 4 * bitmap_words ) ;
for ( i = 0 ; i < bitmap_words ; i + + )
op_map - > u . words [ i ] = be32_to_cpup ( p + + ) ;
return 0 ;
}
2009-04-01 17:22:29 +04:00
static int decode_exchange_id ( struct xdr_stream * xdr ,
struct nfs41_exchange_id_res * res )
{
__be32 * p ;
uint32_t dummy ;
2009-08-14 18:20:10 +04:00
char * dummy_str ;
2009-04-01 17:22:29 +04:00
int status ;
2012-02-18 00:20:26 +04:00
uint32_t impl_id_count ;
2009-04-01 17:22:29 +04:00
status = decode_op_hdr ( xdr , OP_EXCHANGE_ID ) ;
if ( status )
return status ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2012-05-26 21:41:04 +04:00
xdr_decode_hyper ( p , & res - > clientid ) ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 12 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2012-05-26 21:41:04 +04:00
res - > seqid = be32_to_cpup ( p + + ) ;
res - > flags = be32_to_cpup ( p + + ) ;
2009-04-01 17:22:29 +04:00
2013-08-14 00:37:32 +04:00
res - > state_protect . how = be32_to_cpup ( p ) ;
switch ( res - > state_protect . how ) {
case SP4_NONE :
break ;
case SP4_MACH_CRED :
status = decode_op_map ( xdr , & res - > state_protect . enforce ) ;
if ( status )
return status ;
status = decode_op_map ( xdr , & res - > state_protect . allow ) ;
if ( status )
return status ;
break ;
default :
WARN_ON_ONCE ( 1 ) ;
2009-04-01 17:22:29 +04:00
return - EIO ;
2013-08-14 00:37:32 +04:00
}
2009-04-01 17:22:29 +04:00
2012-05-22 06:46:16 +04:00
/* server_owner4.so_minor_id */
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2012-05-22 06:46:16 +04:00
p = xdr_decode_hyper ( p , & res - > server_owner - > minor_id ) ;
2009-04-01 17:22:29 +04:00
2012-05-22 06:46:16 +04:00
/* server_owner4.so_major_id */
2009-08-14 18:20:10 +04:00
status = decode_opaque_inline ( xdr , & dummy , & dummy_str ) ;
if ( unlikely ( status ) )
return status ;
2012-05-22 06:46:16 +04:00
if ( unlikely ( dummy > NFS4_OPAQUE_LIMIT ) )
return - EIO ;
memcpy ( res - > server_owner - > major_id , dummy_str , dummy ) ;
res - > server_owner - > major_id_sz = dummy ;
2009-04-01 17:22:29 +04:00
2012-05-22 06:46:16 +04:00
/* server_scope4 */
2009-08-14 18:20:10 +04:00
status = decode_opaque_inline ( xdr , & dummy , & dummy_str ) ;
if ( unlikely ( status ) )
return status ;
2011-06-01 03:05:47 +04:00
if ( unlikely ( dummy > NFS4_OPAQUE_LIMIT ) )
return - EIO ;
memcpy ( res - > server_scope - > server_scope , dummy_str , dummy ) ;
res - > server_scope - > server_scope_sz = dummy ;
2012-02-18 00:20:26 +04:00
/* Implementation Id */
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
impl_id_count = be32_to_cpup ( p + + ) ;
2009-04-01 17:22:29 +04:00
2012-02-18 00:20:26 +04:00
if ( impl_id_count ) {
/* nii_domain */
status = decode_opaque_inline ( xdr , & dummy , & dummy_str ) ;
if ( unlikely ( status ) )
return status ;
if ( unlikely ( dummy > NFS4_OPAQUE_LIMIT ) )
return - EIO ;
memcpy ( res - > impl_id - > domain , dummy_str , dummy ) ;
/* nii_name */
status = decode_opaque_inline ( xdr , & dummy , & dummy_str ) ;
if ( unlikely ( status ) )
return status ;
if ( unlikely ( dummy > NFS4_OPAQUE_LIMIT ) )
return - EIO ;
memcpy ( res - > impl_id - > name , dummy_str , dummy ) ;
/* nii_date */
p = xdr_inline_decode ( xdr , 12 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
p = xdr_decode_hyper ( p , & res - > impl_id - > date . seconds ) ;
res - > impl_id - > date . nseconds = be32_to_cpup ( p ) ;
/* if there's more than one entry, ignore the rest */
}
2009-04-01 17:22:29 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2009-04-01 17:22:29 +04:00
}
2009-04-01 17:22:31 +04:00
static int decode_chan_attrs ( struct xdr_stream * xdr ,
struct nfs4_channel_attrs * attrs )
{
__be32 * p ;
2011-06-12 01:08:39 +04:00
u32 nr_attrs , val ;
2009-04-01 17:22:31 +04:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 28 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2011-06-12 01:08:39 +04:00
val = be32_to_cpup ( p + + ) ; /* headerpadsz */
if ( val )
return - EINVAL ; /* no support for header padding yet */
2009-08-14 18:19:37 +04:00
attrs - > max_rqst_sz = be32_to_cpup ( p + + ) ;
attrs - > max_resp_sz = be32_to_cpup ( p + + ) ;
attrs - > max_resp_sz_cached = be32_to_cpup ( p + + ) ;
attrs - > max_ops = be32_to_cpup ( p + + ) ;
attrs - > max_reqs = be32_to_cpup ( p + + ) ;
2009-08-14 18:20:19 +04:00
nr_attrs = be32_to_cpup ( p ) ;
2009-04-01 17:22:31 +04:00
if ( unlikely ( nr_attrs > 1 ) ) {
2012-01-26 22:32:23 +04:00
printk ( KERN_WARNING " NFS: %s: Invalid rdma channel attrs "
" count %u \n " , __func__ , nr_attrs ) ;
2009-04-01 17:22:31 +04:00
return - EINVAL ;
}
2009-08-14 18:20:14 +04:00
if ( nr_attrs = = 1 ) {
p = xdr_inline_decode ( xdr , 4 ) ; /* skip rdma_attrs */
if ( unlikely ( ! p ) )
goto out_overflow ;
}
2009-04-01 17:22:31 +04:00
return 0 ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2009-04-01 17:22:31 +04:00
}
2009-08-14 18:20:00 +04:00
static int decode_sessionid ( struct xdr_stream * xdr , struct nfs4_sessionid * sid )
{
return decode_opaque_fixed ( xdr , sid - > data , NFS4_MAX_SESSIONID_LEN ) ;
2009-04-01 17:22:31 +04:00
}
2012-05-24 21:22:50 +04:00
static int decode_bind_conn_to_session ( struct xdr_stream * xdr ,
struct nfs41_bind_conn_to_session_res * res )
{
__be32 * p ;
int status ;
status = decode_op_hdr ( xdr , OP_BIND_CONN_TO_SESSION ) ;
if ( ! status )
status = decode_sessionid ( xdr , & res - > session - > sess_id ) ;
if ( unlikely ( status ) )
return status ;
/* dir flags, rdma mode bool */
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
res - > dir = be32_to_cpup ( p + + ) ;
if ( res - > dir = = 0 | | res - > dir > NFS4_CDFS4_BOTH )
return - EIO ;
if ( be32_to_cpup ( p ) = = 0 )
res - > use_conn_in_rdma_mode = false ;
else
res - > use_conn_in_rdma_mode = true ;
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
2009-04-01 17:22:31 +04:00
static int decode_create_session ( struct xdr_stream * xdr ,
struct nfs41_create_session_res * res )
{
__be32 * p ;
int status ;
struct nfs_client * clp = res - > client ;
struct nfs4_session * session = clp - > cl_session ;
status = decode_op_hdr ( xdr , OP_CREATE_SESSION ) ;
2009-08-14 18:20:00 +04:00
if ( ! status )
status = decode_sessionid ( xdr , & session - > sess_id ) ;
if ( unlikely ( status ) )
2009-04-01 17:22:31 +04:00
return status ;
/* seqid, flags */
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
clp - > cl_seqid = be32_to_cpup ( p + + ) ;
2009-08-14 18:20:19 +04:00
session - > flags = be32_to_cpup ( p ) ;
2009-04-01 17:22:31 +04:00
/* Channel attributes */
status = decode_chan_attrs ( xdr , & session - > fc_attrs ) ;
if ( ! status )
status = decode_chan_attrs ( xdr , & session - > bc_attrs ) ;
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
2009-04-01 17:22:31 +04:00
}
2009-04-01 17:22:34 +04:00
static int decode_destroy_session ( struct xdr_stream * xdr , void * dummy )
{
return decode_op_hdr ( xdr , OP_DESTROY_SESSION ) ;
}
2009-12-06 00:08:40 +03:00
2012-05-26 01:18:09 +04:00
static int decode_destroy_clientid ( struct xdr_stream * xdr , void * dummy )
{
return decode_op_hdr ( xdr , OP_DESTROY_CLIENTID ) ;
}
2009-12-06 00:08:40 +03:00
static int decode_reclaim_complete ( struct xdr_stream * xdr , void * dummy )
{
return decode_op_hdr ( xdr , OP_RECLAIM_COMPLETE ) ;
}
2009-04-01 17:22:29 +04:00
# endif /* CONFIG_NFS_V4_1 */
2009-04-01 17:22:11 +04:00
static int decode_sequence ( struct xdr_stream * xdr ,
struct nfs4_sequence_res * res ,
struct rpc_rqst * rqstp )
{
# if defined(CONFIG_NFS_V4_1)
2012-11-16 21:25:01 +04:00
struct nfs4_session * session ;
2009-04-01 17:22:36 +04:00
struct nfs4_sessionid id ;
u32 dummy ;
int status ;
__be32 * p ;
2012-11-16 21:25:01 +04:00
if ( res - > sr_slot = = NULL )
2009-04-01 17:22:11 +04:00
return 0 ;
2013-08-09 20:49:19 +04:00
if ( ! res - > sr_slot - > table - > session )
return 0 ;
2009-04-01 17:22:11 +04:00
2009-04-01 17:22:36 +04:00
status = decode_op_hdr ( xdr , OP_SEQUENCE ) ;
2009-08-14 18:20:00 +04:00
if ( ! status )
status = decode_sessionid ( xdr , & id ) ;
if ( unlikely ( status ) )
2009-04-01 17:22:36 +04:00
goto out_err ;
2009-04-01 17:22:11 +04:00
2009-04-01 17:22:36 +04:00
/*
* If the server returns different values for sessionID , slotID or
* sequence number , the server is looney tunes .
*/
2010-02-08 17:32:40 +03:00
status = - EREMOTEIO ;
2012-11-16 21:25:01 +04:00
session = res - > sr_slot - > table - > session ;
2009-04-01 17:22:36 +04:00
2012-11-16 21:25:01 +04:00
if ( memcmp ( id . data , session - > sess_id . data ,
2009-04-01 17:22:36 +04:00
NFS4_MAX_SESSIONID_LEN ) ) {
dprintk ( " %s Invalid session id \n " , __func__ ) ;
goto out_err ;
}
2009-08-14 18:20:00 +04:00
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 20 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:20:00 +04:00
2009-04-01 17:22:36 +04:00
/* seqid */
2009-08-14 18:19:37 +04:00
dummy = be32_to_cpup ( p + + ) ;
2010-09-24 17:17:01 +04:00
if ( dummy ! = res - > sr_slot - > seq_nr ) {
2009-04-01 17:22:36 +04:00
dprintk ( " %s Invalid sequence number \n " , __func__ ) ;
goto out_err ;
}
/* slot id */
2009-08-14 18:19:37 +04:00
dummy = be32_to_cpup ( p + + ) ;
2012-11-16 21:45:06 +04:00
if ( dummy ! = res - > sr_slot - > slot_nr ) {
2009-04-01 17:22:36 +04:00
dprintk ( " %s Invalid slot id \n " , __func__ ) ;
goto out_err ;
}
2012-11-21 03:10:30 +04:00
/* highest slot id */
res - > sr_highest_slotid = be32_to_cpup ( p + + ) ;
2012-11-20 21:49:27 +04:00
/* target highest slot id */
res - > sr_target_highest_slotid = be32_to_cpup ( p + + ) ;
2009-12-05 21:46:14 +03:00
/* result flags */
res - > sr_status_flags = be32_to_cpup ( p ) ;
2009-04-01 17:22:36 +04:00
status = 0 ;
out_err :
res - > sr_status = status ;
return status ;
2009-08-14 18:20:14 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
status = - EIO ;
goto out_err ;
2009-04-01 17:22:36 +04:00
# else /* CONFIG_NFS_V4_1 */
2009-04-01 17:22:11 +04:00
return 0 ;
2009-04-01 17:22:36 +04:00
# endif /* CONFIG_NFS_V4_1 */
2009-04-01 17:22:11 +04:00
}
2010-10-20 08:18:03 +04:00
# if defined(CONFIG_NFS_V4_1)
2011-07-31 04:52:35 +04:00
/*
* TODO : Need to handle case when EOF ! = true ;
*/
static int decode_getdevicelist ( struct xdr_stream * xdr ,
struct pnfs_devicelist * res )
{
__be32 * p ;
int status , i ;
2012-06-08 20:01:14 +04:00
nfs4_verifier verftemp ;
2011-07-31 04:52:35 +04:00
status = decode_op_hdr ( xdr , OP_GETDEVICELIST ) ;
if ( status )
return status ;
p = xdr_inline_decode ( xdr , 8 + 8 + 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
/* TODO: Skip cookie for now */
p + = 2 ;
/* Read verifier */
2012-06-08 20:01:14 +04:00
p = xdr_decode_opaque_fixed ( p , verftemp . data , NFS4_VERIFIER_SIZE ) ;
2011-07-31 04:52:35 +04:00
res - > num_devs = be32_to_cpup ( p ) ;
dprintk ( " %s: num_dev %d \n " , __func__ , res - > num_devs ) ;
if ( res - > num_devs > NFS4_PNFS_GETDEVLIST_MAXNUM ) {
2012-01-26 22:32:23 +04:00
printk ( KERN_ERR " NFS: %s too many result dev_num %u \n " ,
2011-07-31 04:52:35 +04:00
__func__ , res - > num_devs ) ;
return - EIO ;
}
p = xdr_inline_decode ( xdr ,
res - > num_devs * NFS4_DEVICEID4_SIZE + 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
for ( i = 0 ; i < res - > num_devs ; i + + )
p = xdr_decode_opaque_fixed ( p , res - > dev_id [ i ] . data ,
NFS4_DEVICEID4_SIZE ) ;
res - > eof = be32_to_cpup ( p ) ;
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
2010-10-20 08:18:03 +04:00
static int decode_getdeviceinfo ( struct xdr_stream * xdr ,
struct pnfs_device * pdev )
{
__be32 * p ;
uint32_t len , type ;
int status ;
status = decode_op_hdr ( xdr , OP_GETDEVICEINFO ) ;
if ( status ) {
if ( status = = - ETOOSMALL ) {
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
pdev - > mincount = be32_to_cpup ( p ) ;
dprintk ( " %s: Min count too small. mincnt = %u \n " ,
__func__ , pdev - > mincount ) ;
}
return status ;
}
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
type = be32_to_cpup ( p + + ) ;
if ( type ! = pdev - > layout_type ) {
dprintk ( " %s: layout mismatch req: %u pdev: %u \n " ,
__func__ , pdev - > layout_type , type ) ;
return - EINVAL ;
}
/*
* Get the length of the opaque device_addr4 . xdr_read_pages places
* the opaque device_addr4 in the xdr_buf - > pages ( pnfs_device - > pages )
* and places the remaining xdr data in xdr_buf - > tail
*/
pdev - > mincount = be32_to_cpup ( p ) ;
2012-08-01 22:21:12 +04:00
if ( xdr_read_pages ( xdr , pdev - > mincount ) ! = pdev - > mincount )
goto out_overflow ;
2010-10-20 08:18:03 +04:00
/* Parse notification bitmap, verifying that it is zero. */
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
len = be32_to_cpup ( p ) ;
if ( len ) {
2010-12-14 17:58:21 +03:00
uint32_t i ;
2010-10-20 08:18:03 +04:00
p = xdr_inline_decode ( xdr , 4 * len ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
for ( i = 0 ; i < len ; i + + , p + + ) {
if ( be32_to_cpup ( p ) ) {
dprintk ( " %s: notifications not supported \n " ,
__func__ ) ;
return - EIO ;
}
}
}
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
static int decode_layoutget ( struct xdr_stream * xdr , struct rpc_rqst * req ,
struct nfs4_layoutget_res * res )
{
__be32 * p ;
int status ;
u32 layout_count ;
2012-06-21 06:35:05 +04:00
u32 recvd ;
2010-10-20 08:18:03 +04:00
status = decode_op_hdr ( xdr , OP_LAYOUTGET ) ;
if ( status )
return status ;
2012-03-05 03:13:56 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
res - > return_on_close = be32_to_cpup ( p ) ;
decode_stateid ( xdr , & res - > stateid ) ;
p = xdr_inline_decode ( xdr , 4 ) ;
2010-10-20 08:18:03 +04:00
if ( unlikely ( ! p ) )
goto out_overflow ;
layout_count = be32_to_cpup ( p ) ;
if ( ! layout_count ) {
dprintk ( " %s: server responded with empty layout array \n " ,
__func__ ) ;
return - EINVAL ;
}
2011-03-24 23:48:21 +03:00
p = xdr_inline_decode ( xdr , 28 ) ;
2010-10-20 08:18:03 +04:00
if ( unlikely ( ! p ) )
goto out_overflow ;
p = xdr_decode_hyper ( p , & res - > range . offset ) ;
p = xdr_decode_hyper ( p , & res - > range . length ) ;
res - > range . iomode = be32_to_cpup ( p + + ) ;
res - > type = be32_to_cpup ( p + + ) ;
2011-03-24 23:48:21 +03:00
res - > layoutp - > len = be32_to_cpup ( p ) ;
2010-10-20 08:18:03 +04:00
dprintk ( " %s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d \n " ,
__func__ ,
( unsigned long ) res - > range . offset ,
( unsigned long ) res - > range . length ,
res - > range . iomode ,
res - > type ,
2011-03-24 23:48:21 +03:00
res - > layoutp - > len ) ;
2012-06-21 06:35:05 +04:00
recvd = xdr_read_pages ( xdr , res - > layoutp - > len ) ;
2011-03-24 23:48:21 +03:00
if ( res - > layoutp - > len > recvd ) {
dprintk ( " NFS: server cheating in layoutget reply: "
" layout len %u > recvd %u \n " ,
res - > layoutp - > len , recvd ) ;
return - EINVAL ;
}
2010-10-20 08:18:03 +04:00
if ( layout_count > 1 ) {
/* We only handle a length one array at the moment. Any
* further entries are just ignored . Note that this means
* the client may see a response that is less than the
* minimum it requested .
*/
dprintk ( " %s: server responded with %d layouts, dropping tail \n " ,
__func__ , layout_count ) ;
}
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
2011-03-23 16:27:54 +03:00
2011-05-22 20:52:37 +04:00
static int decode_layoutreturn ( struct xdr_stream * xdr ,
struct nfs4_layoutreturn_res * res )
{
__be32 * p ;
int status ;
status = decode_op_hdr ( xdr , OP_LAYOUTRETURN ) ;
if ( status )
return status ;
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
res - > lrs_present = be32_to_cpup ( p ) ;
if ( res - > lrs_present )
status = decode_stateid ( xdr , & res - > stateid ) ;
return status ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
2011-03-23 16:27:54 +03:00
static int decode_layoutcommit ( struct xdr_stream * xdr ,
struct rpc_rqst * req ,
struct nfs4_layoutcommit_res * res )
{
__be32 * p ;
__u32 sizechanged ;
int status ;
status = decode_op_hdr ( xdr , OP_LAYOUTCOMMIT ) ;
2011-07-31 04:52:38 +04:00
res - > status = status ;
2011-03-23 16:27:54 +03:00
if ( status )
return status ;
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
sizechanged = be32_to_cpup ( p ) ;
if ( sizechanged ) {
/* throw away new size */
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
}
return 0 ;
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
return - EIO ;
}
2011-06-02 22:59:08 +04:00
static int decode_test_stateid ( struct xdr_stream * xdr ,
struct nfs41_test_stateid_res * res )
{
__be32 * p ;
int status ;
int num_res ;
status = decode_op_hdr ( xdr , OP_TEST_STATEID ) ;
if ( status )
return status ;
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
num_res = be32_to_cpup ( p + + ) ;
if ( num_res ! = 1 )
goto out ;
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
res - > status = be32_to_cpup ( p + + ) ;
2012-01-31 19:39:29 +04:00
return status ;
2011-06-02 22:59:08 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
out :
return - EIO ;
}
2011-06-02 22:59:09 +04:00
static int decode_free_stateid ( struct xdr_stream * xdr ,
struct nfs41_free_stateid_res * res )
{
2013-09-10 20:56:29 +04:00
res - > status = decode_op_hdr ( xdr , OP_FREE_STATEID ) ;
2011-06-02 22:59:09 +04:00
return res - > status ;
}
2010-10-20 08:18:03 +04:00
# endif /* CONFIG_NFS_V4_1 */
2008-12-24 00:06:16 +03:00
/*
* END OF " GENERIC " DECODE ROUTINES .
*/
2005-04-17 02:20:36 +04:00
/*
* Decode OPEN_DOWNGRADE response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_open_downgrade ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs_closeres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_open_downgrade ( xdr , res ) ;
2005-10-28 06:12:41 +04:00
if ( status ! = 0 )
goto out ;
2012-01-07 22:22:46 +04:00
decode_getfattr ( xdr , res - > fattr , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
2008-12-24 00:06:15 +03:00
return status ;
2005-04-17 02:20:36 +04:00
}
/*
* Decode ACCESS response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_access ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs4_accessres * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2009-04-01 17:22:11 +04:00
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2007-08-11 01:45:11 +04:00
if ( status ! = 0 )
goto out ;
2012-09-10 22:00:46 +04:00
status = decode_access ( xdr , & res - > supported , & res - > access ) ;
2007-08-11 01:45:11 +04:00
if ( status ! = 0 )
goto out ;
2012-01-07 22:22:46 +04:00
decode_getfattr ( xdr , res - > fattr , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode LOOKUP response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_lookup ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs4_lookup_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2009-04-01 17:22:11 +04:00
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_lookup ( xdr ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_getfh ( xdr , res - > fh ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2013-05-22 20:50:44 +04:00
status = decode_getfattr_label ( xdr , res - > fattr , res - > label , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode LOOKUP_ROOT response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_lookup_root ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs4_lookup_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2009-04-01 17:22:11 +04:00
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putrootfh ( xdr ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_getfh ( xdr , res - > fh ) ;
if ( status = = 0 )
2013-05-22 20:50:44 +04:00
status = decode_getfattr_label ( xdr , res - > fattr ,
res - > label , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode REMOVE response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_remove ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs_removeres * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2009-04-01 17:22:11 +04:00
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
if ( status )
2005-10-28 06:12:44 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_remove ( xdr , & res - > cinfo ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode RENAME response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_rename ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs_renameres * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2009-04-01 17:22:11 +04:00
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_savefh ( xdr ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_rename ( xdr , & res - > old_cinfo , & res - > new_cinfo ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode LINK response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_link ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs4_link_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2009-04-01 17:22:11 +04:00
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_savefh ( xdr ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_link ( xdr , & res - > cinfo ) ;
if ( status )
2005-10-28 06:12:42 +04:00
goto out ;
/*
* Note order : OP_LINK leaves the directory as the current
* filehandle .
*/
2010-12-14 17:59:29 +03:00
status = decode_restorefh ( xdr ) ;
if ( status )
2005-10-28 06:12:42 +04:00
goto out ;
2013-05-22 20:50:44 +04:00
decode_getfattr_label ( xdr , res - > fattr , res - > label , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode CREATE response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_create ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs4_create_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2009-04-01 17:22:11 +04:00
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
if ( status )
2005-10-28 06:12:40 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_create ( xdr , & res - > dir_cinfo ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_getfh ( xdr , res - > fh ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2013-05-22 20:50:44 +04:00
decode_getfattr_label ( xdr , res - > fattr , res - > label , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode SYMLINK response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_symlink ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs4_create_res * res )
2005-04-17 02:20:36 +04:00
{
2010-12-14 17:59:29 +03:00
return nfs4_xdr_dec_create ( rqstp , xdr , res ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Decode GETATTR response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_getattr ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs4_getattr_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2013-05-22 20:50:44 +04:00
status = decode_getfattr_label ( xdr , res - > fattr , res - > label , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
2005-06-22 21:16:22 +04:00
/*
* Encode an SETACL request
*/
2010-12-14 17:59:18 +03:00
static void nfs4_xdr_enc_setacl ( struct rpc_rqst * req , struct xdr_stream * xdr ,
struct nfs_setaclargs * args )
2005-06-22 21:16:22 +04:00
{
2008-12-24 00:06:15 +03:00
struct compound_hdr hdr = {
2009-04-01 17:22:10 +04:00
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args ) ,
2008-12-24 00:06:15 +03:00
} ;
2010-12-14 17:59:18 +03:00
encode_compound_hdr ( xdr , req , & hdr ) ;
encode_sequence ( xdr , & args - > seq_args , & hdr ) ;
encode_putfh ( xdr , args - > fh , & hdr ) ;
encode_setacl ( xdr , args , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2005-06-22 21:16:22 +04:00
}
2008-12-24 00:06:15 +03:00
2005-06-22 21:16:22 +04:00
/*
* Decode SETACL response
*/
static int
2010-12-14 17:59:29 +03:00
nfs4_xdr_dec_setacl ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
2009-04-01 17:22:01 +04:00
struct nfs_setaclres * res )
2005-06-22 21:16:22 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-06-22 21:16:22 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-06-22 21:16:22 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_setattr ( xdr ) ;
2005-06-22 21:16:22 +04:00
out :
return status ;
}
2005-04-17 02:20:36 +04:00
2005-06-22 21:16:22 +04:00
/*
* Decode GETACL response
*/
static int
2010-12-14 17:59:29 +03:00
nfs4_xdr_dec_getacl ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
2009-04-01 17:21:59 +04:00
struct nfs_getaclres * res )
2005-06-22 21:16:22 +04:00
{
struct compound_hdr hdr ;
int status ;
2012-02-04 03:30:53 +04:00
if ( res - > acl_scratch ! = NULL ) {
void * p = page_address ( res - > acl_scratch ) ;
xdr_set_scratch_buffer ( xdr , p , PAGE_SIZE ) ;
}
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-06-22 21:16:22 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-06-22 21:16:22 +04:00
if ( status )
goto out ;
2011-12-07 20:55:27 +04:00
status = decode_getacl ( xdr , rqstp , res ) ;
2005-06-22 21:16:22 +04:00
out :
return status ;
}
2005-04-17 02:20:36 +04:00
/*
* Decode CLOSE response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_close ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs_closeres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_close ( xdr , res ) ;
2005-10-28 06:12:41 +04:00
if ( status ! = 0 )
goto out ;
/*
* Note : Server may do delete on close for this file
* in which case the getattr call will fail with
* an ESTALE error . Shouldn ' t be a problem ,
* though , since fattr - > valid will remain unset .
*/
2012-01-07 22:22:46 +04:00
decode_getfattr ( xdr , res - > fattr , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
2008-12-24 00:06:15 +03:00
return status ;
2005-04-17 02:20:36 +04:00
}
/*
* Decode OPEN response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_open ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs_openres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_open ( xdr , res ) ;
2005-10-28 06:12:40 +04:00
if ( status )
goto out ;
2012-09-06 23:54:27 +04:00
status = decode_getfh ( xdr , & res - > fh ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2012-10-03 01:49:52 +04:00
if ( res - > access_request )
decode_access ( xdr , & res - > access_supported , & res - > access_result ) ;
2013-05-22 20:50:44 +04:00
decode_getfattr_label ( xdr , res - > f_attr , res - > f_label , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
2008-12-24 00:06:15 +03:00
return status ;
2005-04-17 02:20:36 +04:00
}
/*
* Decode OPEN_CONFIRM response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_open_confirm ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs_open_confirmres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_open_confirm ( xdr , res ) ;
2005-04-17 02:20:36 +04:00
out :
2008-12-24 00:06:15 +03:00
return status ;
2005-04-17 02:20:36 +04:00
}
/*
* Decode OPEN response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_open_noattr ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs_openres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_open ( xdr , res ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2012-10-03 01:49:52 +04:00
if ( res - > access_request )
decode_access ( xdr , & res - > access_supported , & res - > access_result ) ;
2012-01-07 22:22:46 +04:00
decode_getfattr ( xdr , res - > f_attr , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
2008-12-24 00:06:15 +03:00
return status ;
2005-04-17 02:20:36 +04:00
}
/*
* Decode SETATTR response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_setattr ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs_setattrres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_setattr ( xdr ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2013-05-22 20:50:44 +04:00
decode_getfattr_label ( xdr , res - > fattr , res - > label , res - > server ) ;
2005-04-17 02:20:36 +04:00
out :
2008-12-24 00:06:15 +03:00
return status ;
2005-04-17 02:20:36 +04:00
}
/*
* Decode LOCK response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_lock ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs_lock_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_lock ( xdr , res ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode LOCKT response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_lockt ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs_lockt_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_lockt ( xdr , res ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode LOCKU response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_locku ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs_locku_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_locku ( xdr , res ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_release_lockowner ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr , void * dummy )
2010-07-01 20:49:01 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2010-07-01 20:49:01 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_release_lockowner ( xdr ) ;
2010-07-01 20:49:01 +04:00
return status ;
}
2005-04-17 02:20:36 +04:00
/*
* Decode READLINK response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_readlink ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
2009-04-01 17:21:55 +04:00
struct nfs4_readlink_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_readlink ( xdr , rqstp ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode READDIR response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_readdir ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs4_readdir_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_readdir ( xdr , rqstp , res ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode Read response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_read ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs_readres * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_read ( xdr , rqstp , res ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
status = res - > count ;
out :
return status ;
}
/*
* Decode WRITE response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_write ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
struct nfs_writeres * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_write ( xdr , res ) ;
2005-10-28 06:12:44 +04:00
if ( status )
goto out ;
2011-03-03 18:13:46 +03:00
if ( res - > fattr )
2012-01-07 22:22:46 +04:00
decode_getfattr ( xdr , res - > fattr , res - > server ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
status = res - > count ;
out :
return status ;
}
/*
* Decode COMMIT response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_commit ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
2012-04-20 22:47:39 +04:00
struct nfs_commitres * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_commit ( xdr , res ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
2009-12-06 00:08:39 +03:00
* Decode FSINFO response
2005-04-17 02:20:36 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_fsinfo ( struct rpc_rqst * req , struct xdr_stream * xdr ,
2009-04-01 17:21:57 +04:00
struct nfs4_fsinfo_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , req ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_fsinfo ( xdr , res - > fsinfo ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
/*
2009-12-06 00:08:39 +03:00
* Decode PATHCONF response
2005-04-17 02:20:36 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_pathconf ( struct rpc_rqst * req , struct xdr_stream * xdr ,
2009-04-01 17:21:58 +04:00
struct nfs4_pathconf_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , req ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_pathconf ( xdr , res - > pathconf ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
/*
2009-12-06 00:08:39 +03:00
* Decode STATFS response
2005-04-17 02:20:36 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_statfs ( struct rpc_rqst * req , struct xdr_stream * xdr ,
2009-04-01 17:21:56 +04:00
struct nfs4_statfs_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , req ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_statfs ( xdr , res - > fsstat ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
/*
2009-12-06 00:08:39 +03:00
* Decode GETATTR_BITMAP response
2005-04-17 02:20:36 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_server_caps ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_server_caps_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , req ) ;
2009-04-01 17:22:11 +04:00
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_server_caps ( xdr , res ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode RENEW response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_renew ( struct rpc_rqst * rqstp , struct xdr_stream * xdr ,
void * __unused )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_renew ( xdr ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
/*
2009-12-06 00:08:39 +03:00
* Decode SETCLIENTID response
2005-04-17 02:20:36 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_setclientid ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
struct nfs4_setclientid_res * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_setclientid ( xdr , res ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
/*
2009-12-06 00:08:39 +03:00
* Decode SETCLIENTID_CONFIRM response
2005-04-17 02:20:36 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_setclientid_confirm ( struct rpc_rqst * req ,
2013-03-16 23:55:53 +04:00
struct xdr_stream * xdr )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_setclientid_confirm ( xdr ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
/*
2009-12-06 00:08:39 +03:00
* Decode DELEGRETURN response
2005-04-17 02:20:36 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_delegreturn ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs4_delegreturnres * res )
2005-04-17 02:20:36 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2009-04-01 17:22:11 +04:00
if ( status )
2006-01-03 11:55:38 +03:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2006-01-03 11:55:38 +03:00
if ( status ! = 0 )
goto out ;
2012-04-29 00:05:03 +04:00
status = decode_getfattr ( xdr , res - > fattr , res - > server ) ;
2010-03-21 19:10:36 +03:00
if ( status ! = 0 )
goto out ;
2012-04-29 00:05:03 +04:00
status = decode_delegreturn ( xdr ) ;
2006-01-03 11:55:38 +03:00
out :
2005-04-17 02:20:36 +04:00
return status ;
}
2006-06-09 17:34:22 +04:00
/*
2009-12-06 00:08:39 +03:00
* Decode FS_LOCATIONS response
2006-06-09 17:34:22 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_fs_locations ( struct rpc_rqst * req ,
struct xdr_stream * xdr ,
2009-04-01 17:22:02 +04:00
struct nfs4_fs_locations_res * res )
2006-06-09 17:34:22 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , req ) ;
2009-04-01 17:22:11 +04:00
if ( status )
2006-06-09 17:34:22 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
if ( status )
2006-06-09 17:34:22 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_lookup ( xdr ) ;
if ( status )
2006-06-09 17:34:22 +04:00
goto out ;
2010-12-14 17:59:29 +03:00
xdr_enter_page ( xdr , PAGE_SIZE ) ;
2012-01-31 00:43:56 +04:00
status = decode_getfattr_generic ( xdr , & res - > fs_locations - > fattr ,
NULL , res - > fs_locations ,
2013-05-22 20:50:44 +04:00
NULL , res - > fs_locations - > server ) ;
2006-06-09 17:34:22 +04:00
out :
return status ;
}
2011-03-24 20:12:29 +03:00
/*
* Decode SECINFO response
*/
static int nfs4_xdr_dec_secinfo ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs4_secinfo_res * res )
{
struct compound_hdr hdr ;
int status ;
status = decode_compound_hdr ( xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
if ( status )
goto out ;
status = decode_putfh ( xdr ) ;
if ( status )
goto out ;
status = decode_secinfo ( xdr , res ) ;
out :
return status ;
}
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
2012-05-24 21:22:50 +04:00
/*
* Decode BIND_CONN_TO_SESSION response
*/
static int nfs4_xdr_dec_bind_conn_to_session ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
void * res )
{
struct compound_hdr hdr ;
int status ;
status = decode_compound_hdr ( xdr , & hdr ) ;
if ( ! status )
status = decode_bind_conn_to_session ( xdr , res ) ;
return status ;
}
2009-04-01 17:22:29 +04:00
/*
2009-12-06 00:08:39 +03:00
* Decode EXCHANGE_ID response
2009-04-01 17:22:29 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_exchange_id ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
2009-04-01 17:22:29 +04:00
void * res )
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:29 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_exchange_id ( xdr , res ) ;
2009-04-01 17:22:29 +04:00
return status ;
}
2009-04-01 17:22:30 +04:00
2009-04-01 17:22:31 +04:00
/*
2009-12-06 00:08:39 +03:00
* Decode CREATE_SESSION response
2009-04-01 17:22:31 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_create_session ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
2009-04-01 17:22:31 +04:00
struct nfs41_create_session_res * res )
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:31 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_create_session ( xdr , res ) ;
2009-04-01 17:22:31 +04:00
return status ;
}
2009-04-01 17:22:34 +04:00
/*
2009-12-06 00:08:39 +03:00
* Decode DESTROY_SESSION response
2009-04-01 17:22:34 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_destroy_session ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
void * res )
2009-04-01 17:22:34 +04:00
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:34 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_destroy_session ( xdr , res ) ;
2009-04-01 17:22:34 +04:00
return status ;
}
2012-05-26 01:18:09 +04:00
/*
* Decode DESTROY_CLIENTID response
*/
static int nfs4_xdr_dec_destroy_clientid ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
void * res )
{
struct compound_hdr hdr ;
int status ;
status = decode_compound_hdr ( xdr , & hdr ) ;
if ( ! status )
status = decode_destroy_clientid ( xdr , res ) ;
return status ;
}
2009-04-01 17:22:36 +04:00
/*
2009-12-06 00:08:39 +03:00
* Decode SEQUENCE response
2009-04-01 17:22:36 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_sequence ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
2009-04-01 17:22:36 +04:00
struct nfs4_sequence_res * res )
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:36 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , res , rqstp ) ;
2009-04-01 17:22:36 +04:00
return status ;
}
2009-04-01 17:22:30 +04:00
/*
2009-12-06 00:08:39 +03:00
* Decode GET_LEASE_TIME response
2009-04-01 17:22:30 +04:00
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_get_lease_time ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
2009-04-01 17:22:30 +04:00
struct nfs4_get_lease_time_res * res )
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-04-01 17:22:30 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > lr_seq_res , rqstp ) ;
2009-04-01 17:22:30 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_putrootfh ( xdr ) ;
2009-04-01 17:22:30 +04:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_fsinfo ( xdr , res - > lr_fsinfo ) ;
2009-04-01 17:22:30 +04:00
return status ;
}
2009-12-06 00:08:40 +03:00
/*
* Decode RECLAIM_COMPLETE response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_reclaim_complete ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
2009-12-06 00:08:40 +03:00
struct nfs41_reclaim_complete_res * res )
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2009-12-06 00:08:40 +03:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2009-12-06 00:08:40 +03:00
if ( ! status )
2010-12-14 17:59:29 +03:00
status = decode_reclaim_complete ( xdr , ( void * ) NULL ) ;
2009-12-06 00:08:40 +03:00
return status ;
}
2010-10-20 08:18:03 +04:00
2011-07-31 04:52:35 +04:00
/*
* Decode GETDEVICELIST response
*/
static int nfs4_xdr_dec_getdevicelist ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs4_getdevicelist_res * res )
{
struct compound_hdr hdr ;
int status ;
dprintk ( " encoding getdevicelist! \n " ) ;
status = decode_compound_hdr ( xdr , & hdr ) ;
if ( status ! = 0 )
goto out ;
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
if ( status ! = 0 )
goto out ;
status = decode_putfh ( xdr ) ;
if ( status ! = 0 )
goto out ;
status = decode_getdevicelist ( xdr , res - > devlist ) ;
out :
return status ;
}
2010-10-20 08:18:03 +04:00
/*
* Decode GETDEVINFO response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_getdeviceinfo ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
2010-10-20 08:18:03 +04:00
struct nfs4_getdeviceinfo_res * res )
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2010-10-20 08:18:03 +04:00
if ( status ! = 0 )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2010-10-20 08:18:03 +04:00
if ( status ! = 0 )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_getdeviceinfo ( xdr , res - > pdev ) ;
2010-10-20 08:18:03 +04:00
out :
return status ;
}
/*
* Decode LAYOUTGET response
*/
2010-12-14 17:59:29 +03:00
static int nfs4_xdr_dec_layoutget ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
2010-10-20 08:18:03 +04:00
struct nfs4_layoutget_res * res )
{
struct compound_hdr hdr ;
int status ;
2010-12-14 17:59:29 +03:00
status = decode_compound_hdr ( xdr , & hdr ) ;
2010-10-20 08:18:03 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
2010-10-20 08:18:03 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_putfh ( xdr ) ;
2010-10-20 08:18:03 +04:00
if ( status )
goto out ;
2010-12-14 17:59:29 +03:00
status = decode_layoutget ( xdr , rqstp , res ) ;
2010-10-20 08:18:03 +04:00
out :
return status ;
}
2011-03-23 16:27:54 +03:00
2011-05-22 20:52:37 +04:00
/*
* Decode LAYOUTRETURN response
*/
static int nfs4_xdr_dec_layoutreturn ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs4_layoutreturn_res * res )
{
struct compound_hdr hdr ;
int status ;
status = decode_compound_hdr ( xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
if ( status )
goto out ;
status = decode_putfh ( xdr ) ;
if ( status )
goto out ;
status = decode_layoutreturn ( xdr , res ) ;
out :
return status ;
}
2011-03-23 16:27:54 +03:00
/*
* Decode LAYOUTCOMMIT response
*/
static int nfs4_xdr_dec_layoutcommit ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs4_layoutcommit_res * res )
{
struct compound_hdr hdr ;
int status ;
status = decode_compound_hdr ( xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
if ( status )
goto out ;
status = decode_putfh ( xdr ) ;
if ( status )
goto out ;
status = decode_layoutcommit ( xdr , rqstp , res ) ;
if ( status )
goto out ;
2012-01-07 22:22:46 +04:00
decode_getfattr ( xdr , res - > fattr , res - > server ) ;
2011-03-23 16:27:54 +03:00
out :
return status ;
}
2011-06-02 22:59:07 +04:00
/*
* Decode SECINFO_NO_NAME response
*/
static int nfs4_xdr_dec_secinfo_no_name ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs4_secinfo_res * res )
{
struct compound_hdr hdr ;
int status ;
status = decode_compound_hdr ( xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
if ( status )
goto out ;
status = decode_putrootfh ( xdr ) ;
if ( status )
goto out ;
2012-04-27 21:27:38 +04:00
status = decode_secinfo_no_name ( xdr , res ) ;
2011-06-02 22:59:07 +04:00
out :
return status ;
}
2011-06-02 22:59:08 +04:00
/*
* Decode TEST_STATEID response
*/
static int nfs4_xdr_dec_test_stateid ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs41_test_stateid_res * res )
{
struct compound_hdr hdr ;
int status ;
status = decode_compound_hdr ( xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
if ( status )
goto out ;
status = decode_test_stateid ( xdr , res ) ;
out :
return status ;
}
2011-06-02 22:59:09 +04:00
/*
* Decode FREE_STATEID response
*/
static int nfs4_xdr_dec_free_stateid ( struct rpc_rqst * rqstp ,
struct xdr_stream * xdr ,
struct nfs41_free_stateid_res * res )
{
struct compound_hdr hdr ;
int status ;
status = decode_compound_hdr ( xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( xdr , & res - > seq_res , rqstp ) ;
if ( status )
goto out ;
status = decode_free_stateid ( xdr , res ) ;
out :
return status ;
}
2009-04-01 17:22:29 +04:00
# endif /* CONFIG_NFS_V4_1 */
2010-12-14 17:58:11 +03:00
/**
* nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in
* the local page cache .
* @ xdr : XDR stream where entry resides
* @ entry : buffer to fill in with entry data
* @ plus : boolean indicating whether this should be a readdirplus entry
*
* Returns zero if successful , otherwise a negative errno value is
* returned .
*
* This function is not invoked during READDIR reply decoding , but
* rather whenever an application invokes the getdents ( 2 ) system call
* on a directory already in our cache .
*/
int nfs4_decode_dirent ( struct xdr_stream * xdr , struct nfs_entry * entry ,
int plus )
2005-04-17 02:20:36 +04:00
{
2012-06-21 19:18:13 +04:00
unsigned int savep ;
2011-07-31 04:52:37 +04:00
uint32_t bitmap [ 3 ] = { 0 } ;
2005-04-17 02:20:36 +04:00
uint32_t len ;
2010-10-20 23:44:29 +04:00
__be32 * p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2011-01-28 20:40:55 +03:00
if ( * p = = xdr_zero ) {
2010-10-20 23:44:29 +04:00
p = xdr_inline_decode ( xdr , 4 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2011-01-28 20:40:55 +03:00
if ( * p = = xdr_zero )
2010-12-14 17:58:11 +03:00
return - EAGAIN ;
2005-04-17 02:20:36 +04:00
entry - > eof = 1 ;
2010-12-14 17:58:11 +03:00
return - EBADCOOKIE ;
2005-04-17 02:20:36 +04:00
}
2010-10-20 23:44:29 +04:00
p = xdr_inline_decode ( xdr , 12 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2005-04-17 02:20:36 +04:00
entry - > prev_cookie = entry - > cookie ;
p = xdr_decode_hyper ( p , & entry - > cookie ) ;
2011-01-28 20:40:55 +03:00
entry - > len = be32_to_cpup ( p ) ;
2010-10-20 23:44:29 +04:00
2010-10-24 19:52:55 +04:00
p = xdr_inline_decode ( xdr , entry - > len ) ;
2010-10-20 23:44:29 +04:00
if ( unlikely ( ! p ) )
goto out_overflow ;
2005-04-17 02:20:36 +04:00
entry - > name = ( const char * ) p ;
/*
* In case the server doesn ' t return an inode number ,
* we fake one here . ( We don ' t use inode number 0 ,
* since glibc seems to choke on it . . . )
*/
entry - > ino = 1 ;
2010-10-24 21:14:02 +04:00
entry - > fattr - > valid = 0 ;
2005-04-17 02:20:36 +04:00
2010-10-24 19:52:55 +04:00
if ( decode_attr_bitmap ( xdr , bitmap ) < 0 )
goto out_overflow ;
2012-06-21 19:18:13 +04:00
if ( decode_attr_length ( xdr , & len , & savep ) < 0 )
2010-10-24 19:52:55 +04:00
goto out_overflow ;
2010-12-14 17:58:11 +03:00
if ( decode_getfattr_attrs ( xdr , bitmap , entry - > fattr , entry - > fh ,
2013-05-22 20:50:44 +04:00
NULL , entry - > label , entry - > server ) < 0 )
2010-10-24 19:52:55 +04:00
goto out_overflow ;
2011-04-27 21:47:52 +04:00
if ( entry - > fattr - > valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID )
entry - > ino = entry - > fattr - > mounted_on_fileid ;
else if ( entry - > fattr - > valid & NFS_ATTR_FATTR_FILEID )
2010-10-24 19:52:55 +04:00
entry - > ino = entry - > fattr - > fileid ;
2010-11-20 22:26:44 +03:00
entry - > d_type = DT_UNKNOWN ;
if ( entry - > fattr - > valid & NFS_ATTR_FATTR_TYPE )
entry - > d_type = nfs_umode_to_dtype ( entry - > fattr - > mode ) ;
2010-12-14 17:58:11 +03:00
return 0 ;
2010-10-20 23:44:29 +04:00
out_overflow :
print_overflow_msg ( __func__ , xdr ) ;
2010-12-14 17:58:11 +03:00
return - EAGAIN ;
2005-04-17 02:20:36 +04:00
}
/*
* We need to translate between nfs status return values and
* the local errno values which may not be the same .
*/
static struct {
int stat ;
int errno ;
} nfs_errtbl [ ] = {
{ NFS4_OK , 0 } ,
2008-03-31 18:39:06 +04:00
{ NFS4ERR_PERM , - EPERM } ,
{ NFS4ERR_NOENT , - ENOENT } ,
{ NFS4ERR_IO , - errno_NFSERR_IO } ,
{ NFS4ERR_NXIO , - ENXIO } ,
{ NFS4ERR_ACCESS , - EACCES } ,
{ NFS4ERR_EXIST , - EEXIST } ,
{ NFS4ERR_XDEV , - EXDEV } ,
{ NFS4ERR_NOTDIR , - ENOTDIR } ,
{ NFS4ERR_ISDIR , - EISDIR } ,
{ NFS4ERR_INVAL , - EINVAL } ,
{ NFS4ERR_FBIG , - EFBIG } ,
{ NFS4ERR_NOSPC , - ENOSPC } ,
{ NFS4ERR_ROFS , - EROFS } ,
{ NFS4ERR_MLINK , - EMLINK } ,
{ NFS4ERR_NAMETOOLONG , - ENAMETOOLONG } ,
{ NFS4ERR_NOTEMPTY , - ENOTEMPTY } ,
{ NFS4ERR_DQUOT , - EDQUOT } ,
{ NFS4ERR_STALE , - ESTALE } ,
{ NFS4ERR_BADHANDLE , - EBADHANDLE } ,
{ NFS4ERR_BAD_COOKIE , - EBADCOOKIE } ,
{ NFS4ERR_NOTSUPP , - ENOTSUPP } ,
{ NFS4ERR_TOOSMALL , - ETOOSMALL } ,
2010-02-08 17:32:40 +03:00
{ NFS4ERR_SERVERFAULT , - EREMOTEIO } ,
2008-03-31 18:39:06 +04:00
{ NFS4ERR_BADTYPE , - EBADTYPE } ,
{ NFS4ERR_LOCKED , - EAGAIN } ,
{ NFS4ERR_SYMLINK , - ELOOP } ,
{ NFS4ERR_OP_ILLEGAL , - EOPNOTSUPP } ,
{ NFS4ERR_DEADLOCK , - EDEADLK } ,
{ - 1 , - EIO }
2005-04-17 02:20:36 +04:00
} ;
/*
* Convert an NFS error code to a local one .
* This one is used jointly by NFSv2 and NFSv3 .
*/
static int
2006-08-23 04:06:08 +04:00
nfs4_stat_to_errno ( int stat )
2005-04-17 02:20:36 +04:00
{
int i ;
for ( i = 0 ; nfs_errtbl [ i ] . stat ! = - 1 ; i + + ) {
if ( nfs_errtbl [ i ] . stat = = stat )
return nfs_errtbl [ i ] . errno ;
}
if ( stat < = 10000 | | stat > 10100 ) {
/* The server is looney tunes. */
2010-02-08 17:32:40 +03:00
return - EREMOTEIO ;
2005-04-17 02:20:36 +04:00
}
/* If we cannot translate the error, the recovery routines should
* handle it .
* Note : remaining NFSv4 error codes have values > 10000 , so should
* not conflict with native Linux error codes .
*/
2008-03-31 18:39:06 +04:00
return - stat ;
2005-04-17 02:20:36 +04:00
}
# define PROC(proc, argtype, restype) \
[ NFSPROC4_CLNT_ # # proc ] = { \
. p_proc = NFSPROC4_COMPOUND , \
2010-12-14 17:59:18 +03:00
. p_encode = ( kxdreproc_t ) nfs4_xdr_ # # argtype , \
2010-12-14 17:59:29 +03:00
. p_decode = ( kxdrdproc_t ) nfs4_xdr_ # # restype , \
2007-03-30 00:47:53 +04:00
. p_arglen = NFS4_ # # argtype # # _sz , \
. p_replen = NFS4_ # # restype # # _sz , \
2006-03-20 21:44:22 +03:00
. p_statidx = NFSPROC4_CLNT_ # # proc , \
. p_name = # proc , \
2008-12-24 00:06:15 +03:00
}
2005-04-17 02:20:36 +04:00
struct rpc_procinfo nfs4_procedures [ ] = {
2010-12-14 17:57:42 +03:00
PROC ( READ , enc_read , dec_read ) ,
PROC ( WRITE , enc_write , dec_write ) ,
PROC ( COMMIT , enc_commit , dec_commit ) ,
PROC ( OPEN , enc_open , dec_open ) ,
PROC ( OPEN_CONFIRM , enc_open_confirm , dec_open_confirm ) ,
PROC ( OPEN_NOATTR , enc_open_noattr , dec_open_noattr ) ,
PROC ( OPEN_DOWNGRADE , enc_open_downgrade , dec_open_downgrade ) ,
PROC ( CLOSE , enc_close , dec_close ) ,
PROC ( SETATTR , enc_setattr , dec_setattr ) ,
PROC ( FSINFO , enc_fsinfo , dec_fsinfo ) ,
PROC ( RENEW , enc_renew , dec_renew ) ,
PROC ( SETCLIENTID , enc_setclientid , dec_setclientid ) ,
PROC ( SETCLIENTID_CONFIRM , enc_setclientid_confirm , dec_setclientid_confirm ) ,
PROC ( LOCK , enc_lock , dec_lock ) ,
PROC ( LOCKT , enc_lockt , dec_lockt ) ,
PROC ( LOCKU , enc_locku , dec_locku ) ,
PROC ( ACCESS , enc_access , dec_access ) ,
PROC ( GETATTR , enc_getattr , dec_getattr ) ,
PROC ( LOOKUP , enc_lookup , dec_lookup ) ,
PROC ( LOOKUP_ROOT , enc_lookup_root , dec_lookup_root ) ,
PROC ( REMOVE , enc_remove , dec_remove ) ,
PROC ( RENAME , enc_rename , dec_rename ) ,
PROC ( LINK , enc_link , dec_link ) ,
PROC ( SYMLINK , enc_symlink , dec_symlink ) ,
PROC ( CREATE , enc_create , dec_create ) ,
PROC ( PATHCONF , enc_pathconf , dec_pathconf ) ,
PROC ( STATFS , enc_statfs , dec_statfs ) ,
PROC ( READLINK , enc_readlink , dec_readlink ) ,
PROC ( READDIR , enc_readdir , dec_readdir ) ,
PROC ( SERVER_CAPS , enc_server_caps , dec_server_caps ) ,
PROC ( DELEGRETURN , enc_delegreturn , dec_delegreturn ) ,
PROC ( GETACL , enc_getacl , dec_getacl ) ,
PROC ( SETACL , enc_setacl , dec_setacl ) ,
PROC ( FS_LOCATIONS , enc_fs_locations , dec_fs_locations ) ,
PROC ( RELEASE_LOCKOWNER , enc_release_lockowner , dec_release_lockowner ) ,
2011-03-24 20:12:29 +03:00
PROC ( SECINFO , enc_secinfo , dec_secinfo ) ,
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
2010-12-14 17:57:42 +03:00
PROC ( EXCHANGE_ID , enc_exchange_id , dec_exchange_id ) ,
PROC ( CREATE_SESSION , enc_create_session , dec_create_session ) ,
PROC ( DESTROY_SESSION , enc_destroy_session , dec_destroy_session ) ,
PROC ( SEQUENCE , enc_sequence , dec_sequence ) ,
PROC ( GET_LEASE_TIME , enc_get_lease_time , dec_get_lease_time ) ,
PROC ( RECLAIM_COMPLETE , enc_reclaim_complete , dec_reclaim_complete ) ,
PROC ( GETDEVICEINFO , enc_getdeviceinfo , dec_getdeviceinfo ) ,
PROC ( LAYOUTGET , enc_layoutget , dec_layoutget ) ,
2011-03-23 16:27:54 +03:00
PROC ( LAYOUTCOMMIT , enc_layoutcommit , dec_layoutcommit ) ,
2011-05-22 20:52:37 +04:00
PROC ( LAYOUTRETURN , enc_layoutreturn , dec_layoutreturn ) ,
2011-06-02 22:59:07 +04:00
PROC ( SECINFO_NO_NAME , enc_secinfo_no_name , dec_secinfo_no_name ) ,
2011-06-02 22:59:08 +04:00
PROC ( TEST_STATEID , enc_test_stateid , dec_test_stateid ) ,
2011-06-02 22:59:09 +04:00
PROC ( FREE_STATEID , enc_free_stateid , dec_free_stateid ) ,
2011-07-31 04:52:35 +04:00
PROC ( GETDEVICELIST , enc_getdevicelist , dec_getdevicelist ) ,
2012-05-26 01:11:42 +04:00
PROC ( BIND_CONN_TO_SESSION ,
enc_bind_conn_to_session , dec_bind_conn_to_session ) ,
2012-05-26 01:18:09 +04:00
PROC ( DESTROY_CLIENTID , enc_destroy_clientid , dec_destroy_clientid ) ,
2009-04-01 17:22:29 +04:00
# endif /* CONFIG_NFS_V4_1 */
2005-04-17 02:20:36 +04:00
} ;
2012-01-20 22:53:56 +04:00
const struct rpc_version nfs_version4 = {
2005-04-17 02:20:36 +04:00
. number = 4 ,
2006-03-24 14:15:34 +03:00
. nrprocs = ARRAY_SIZE ( nfs4_procedures ) ,
2005-04-17 02:20:36 +04:00
. procs = nfs4_procedures
} ;
/*
* Local variables :
* c - basic - offset : 8
* End :
*/