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>
# include <linux/sunrpc/clnt.h>
2009-12-05 21:36:55 +03:00
# include <linux/sunrpc/msg_prot.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>
2005-06-22 21:16:21 +04:00
# include "nfs4_fs.h"
2009-12-05 21:30:21 +03:00
# include "internal.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
*/
2007-07-02 21:58:33 +04:00
# define open_owner_id_maxsz (1 + 4)
# define lock_owner_id_maxsz (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 ) )
2005-06-22 21:16:22 +04:00
# define nfs4_fattr_bitmap_maxsz 3
# 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))
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 + \
2007-07-09 02:38:23 +04:00
3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_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 + \
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)
2005-04-17 02:20:36 +04:00
# define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11)
# 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 + \
2 + encode_verifier_maxsz + 5 )
# define decode_readdir_maxsz (op_decode_hdr_maxsz + \
decode_verifier_maxsz )
# 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 )
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)
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 */ + \
0 /* SP4_NONE (for now) */ + \
1 /* zero implemetation id array */ )
# define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
2 /* eir_clientid */ + \
1 /* eir_sequenceid */ + \
1 /* eir_flags */ + \
1 /* spr_how */ + \
0 /* SP4_NONE (for now) */ + \
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 */ + \
0 /* ignored eir_server_impl_id contents */ )
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 )
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)
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)
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 + \
2007-07-18 05:52:42 +04:00
encode_commit_maxsz + \
2005-10-28 06:12:44 +04:00
encode_getattr_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 + \
2007-07-18 05:52:42 +04:00
decode_commit_maxsz + \
2005-10-28 06:12:44 +04:00
decode_getattr_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_savefh_maxsz + \
encode_open_maxsz + \
encode_getfh_maxsz + \
encode_getattr_maxsz + \
encode_restorefh_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_savefh_maxsz + \
decode_open_maxsz + \
decode_getfh_maxsz + \
decode_getattr_maxsz + \
decode_restorefh_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 + \
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 + \
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 + \
encode_setclientid_confirm_maxsz + \
encode_putrootfh_maxsz + \
encode_fsinfo_maxsz )
# define NFS4_dec_setclientid_confirm_sz \
( compound_decode_hdr_maxsz + \
decode_setclientid_confirm_maxsz + \
decode_putrootfh_maxsz + \
decode_fsinfo_maxsz )
# 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 + \
2005-10-28 06:12:44 +04:00
encode_remove_maxsz + \
encode_getattr_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 + \
2009-04-01 17:22:06 +04:00
decode_remove_maxsz + \
2005-10-28 06:12:44 +04:00
decode_getattr_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 + \
2005-10-28 06:12:43 +04:00
encode_rename_maxsz + \
encode_getattr_maxsz + \
encode_restorefh_maxsz + \
encode_getattr_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 + \
2005-10-28 06:12:43 +04:00
decode_rename_maxsz + \
decode_getattr_maxsz + \
decode_restorefh_maxsz + \
decode_getattr_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 + \
decode_getattr_maxsz + \
encode_restorefh_maxsz + \
decode_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_getattr_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 + \
2005-10-28 06:12:40 +04:00
encode_savefh_maxsz + \
2005-04-17 02:20:36 +04:00
encode_create_maxsz + \
2005-10-28 06:12:40 +04:00
encode_getfh_maxsz + \
2005-04-17 02:20:36 +04:00
encode_getattr_maxsz + \
2005-10-28 06:12:40 +04:00
encode_restorefh_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 + \
2005-10-28 06:12:40 +04:00
decode_savefh_maxsz + \
2005-04-17 02:20:36 +04:00
decode_create_maxsz + \
2005-10-28 06:12:40 +04:00
decode_getfh_maxsz + \
2005-04-17 02:20:36 +04:00
decode_getattr_maxsz + \
2005-10-28 06:12:40 +04:00
decode_restorefh_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 )
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
# 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 )
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 )
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 ) ;
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
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
p = xdr_reserve_space ( xdr , 4 + len ) ;
BUG_ON ( p = = NULL ) ;
xdr_encode_opaque ( p , str , len ) ;
}
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
dprintk ( " encode_compound: tag=%.*s \n " , ( int ) hdr - > taglen , hdr - > tag ) ;
BUG_ON ( hdr - > taglen > NFS4_MAXTAGLEN ) ;
2009-08-14 18:19:34 +04:00
p = reserve_space ( xdr , 4 + hdr - > taglen + 8 ) ;
p = xdr_encode_opaque ( p , hdr - > tag , hdr - > taglen ) ;
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
}
static void encode_nops ( struct compound_hdr * hdr )
{
2009-04-01 17:22:31 +04:00
BUG_ON ( 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
}
static void encode_nfs4_verifier ( struct xdr_stream * xdr , const nfs4_verifier * verf )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
p = xdr_reserve_space ( xdr , NFS4_VERIFIER_SIZE ) ;
BUG_ON ( p = = NULL ) ;
xdr_encode_opaque_fixed ( p , verf - > data , NFS4_VERIFIER_SIZE ) ;
}
2008-12-24 00:06:18 +03:00
static void encode_attrs ( struct xdr_stream * xdr , const struct iattr * iap , 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 ;
__be32 * q ;
2005-04-17 02:20:36 +04:00
int len ;
uint32_t bmval0 = 0 ;
uint32_t bmval1 = 0 ;
/*
* We reserve enough space to write the entire attribute buffer at once .
* In the worst - case , this would be
* 12 ( bitmap ) + 4 ( attrlen ) + 8 ( size ) + 4 ( mode ) + 4 ( atime ) + 4 ( mtime )
* = 36 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
*/
len = 16 ;
/* Sigh */
if ( iap - > ia_valid & ATTR_SIZE )
len + = 8 ;
if ( iap - > ia_valid & ATTR_MODE )
len + = 4 ;
if ( iap - > ia_valid & ATTR_UID ) {
2006-08-23 04:06:09 +04:00
owner_namelen = nfs_map_uid_to_name ( server - > nfs_client , iap - > ia_uid , owner_name ) ;
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 " ,
iap - > ia_uid ) ;
2005-04-17 02:20:36 +04:00
/* XXX */
strcpy ( owner_name , " nobody " ) ;
owner_namelen = sizeof ( " nobody " ) - 1 ;
/* goto out; */
}
len + = 4 + ( XDR_QUADLEN ( owner_namelen ) < < 2 ) ;
}
if ( iap - > ia_valid & ATTR_GID ) {
2006-08-23 04:06:09 +04:00
owner_grouplen = nfs_map_gid_to_group ( server - > nfs_client , iap - > ia_gid , owner_group ) ;
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 " ,
iap - > ia_gid ) ;
2005-04-17 02:20:36 +04:00
strcpy ( owner_group , " nobody " ) ;
owner_grouplen = sizeof ( " nobody " ) - 1 ;
/* goto out; */
}
len + = 4 + ( XDR_QUADLEN ( owner_grouplen ) < < 2 ) ;
}
if ( iap - > ia_valid & ATTR_ATIME_SET )
len + = 16 ;
else if ( iap - > ia_valid & ATTR_ATIME )
len + = 4 ;
if ( iap - > ia_valid & ATTR_MTIME_SET )
len + = 16 ;
else if ( iap - > ia_valid & ATTR_MTIME )
len + = 4 ;
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , len ) ;
2005-04-17 02:20:36 +04:00
/*
* We write the bitmap length now , but leave the bitmap and the attribute
* buffer length to be backfilled at the end of this routine .
*/
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( 2 ) ;
2005-04-17 02:20:36 +04:00
q = p ;
p + = 3 ;
if ( iap - > ia_valid & ATTR_SIZE ) {
bmval0 | = FATTR4_WORD0_SIZE ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , iap - > ia_size ) ;
2005-04-17 02:20:36 +04:00
}
if ( iap - > ia_valid & ATTR_MODE ) {
bmval1 | = FATTR4_WORD1_MODE ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( iap - > ia_mode & S_IALLUGO ) ;
2005-04-17 02:20:36 +04:00
}
if ( iap - > ia_valid & ATTR_UID ) {
bmval1 | = FATTR4_WORD1_OWNER ;
2009-08-14 18:19:34 +04:00
p = xdr_encode_opaque ( p , owner_name , owner_namelen ) ;
2005-04-17 02:20:36 +04:00
}
if ( iap - > ia_valid & ATTR_GID ) {
bmval1 | = FATTR4_WORD1_OWNER_GROUP ;
2009-08-14 18:19:34 +04:00
p = xdr_encode_opaque ( p , owner_group , owner_grouplen ) ;
2005-04-17 02:20:36 +04:00
}
if ( iap - > ia_valid & ATTR_ATIME_SET ) {
bmval1 | = FATTR4_WORD1_TIME_ACCESS_SET ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( NFS4_SET_TO_CLIENT_TIME ) ;
* p + + = cpu_to_be32 ( 0 ) ;
2010-06-22 16:52:39 +04:00
* p + + = cpu_to_be32 ( iap - > ia_atime . tv_sec ) ;
* p + + = cpu_to_be32 ( iap - > ia_atime . tv_nsec ) ;
2005-04-17 02:20:36 +04:00
}
else if ( iap - > ia_valid & ATTR_ATIME ) {
bmval1 | = FATTR4_WORD1_TIME_ACCESS_SET ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( NFS4_SET_TO_SERVER_TIME ) ;
2005-04-17 02:20:36 +04:00
}
if ( iap - > ia_valid & ATTR_MTIME_SET ) {
bmval1 | = FATTR4_WORD1_TIME_MODIFY_SET ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( NFS4_SET_TO_CLIENT_TIME ) ;
* p + + = cpu_to_be32 ( 0 ) ;
* p + + = cpu_to_be32 ( iap - > ia_mtime . tv_sec ) ;
* p + + = cpu_to_be32 ( iap - > ia_mtime . tv_nsec ) ;
2005-04-17 02:20:36 +04:00
}
else if ( iap - > ia_valid & ATTR_MTIME ) {
bmval1 | = FATTR4_WORD1_TIME_MODIFY_SET ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( NFS4_SET_TO_SERVER_TIME ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
/*
* Now we backfill the bitmap and the attribute buffer length .
*/
if ( len ! = ( ( char * ) p - ( char * ) q ) + 4 ) {
2007-09-12 02:01:10 +04:00
printk ( KERN_ERR " nfs: Attr length error, %u != %Zu \n " ,
2005-04-17 02:20:36 +04:00
len , ( ( char * ) p - ( char * ) q ) + 4 ) ;
BUG ( ) ;
}
len = ( char * ) p - ( char * ) q - 12 ;
* q + + = htonl ( bmval0 ) ;
* q + + = htonl ( bmval1 ) ;
2009-08-14 18:19:30 +04:00
* q = htonl ( len ) ;
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
{
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 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_ACCESS ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( access ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_access_maxsz ;
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
{
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 + NFS4_STATEID_SIZE ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_CLOSE ) ;
* p + + = cpu_to_be32 ( arg - > seqid - > sequence - > counter ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_opaque_fixed ( p , arg - > stateid - > data , NFS4_STATEID_SIZE ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_close_maxsz ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_commit ( 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 ;
2008-12-24 00:06:15 +03:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 16 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_COMMIT ) ;
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 ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_commit_maxsz ;
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
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 ( OP_CREATE ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( 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 ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_create_maxsz ;
2005-04-17 02:20:36 +04:00
2008-12-24 00:06:18 +03:00
encode_attrs ( xdr , create - > attrs , 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
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 12 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_GETATTR ) ;
* p + + = cpu_to_be32 ( 1 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( bitmap ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_getattr_maxsz ;
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
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 16 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_GETATTR ) ;
* p + + = cpu_to_be32 ( 2 ) ;
* p + + = cpu_to_be32 ( bm0 ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( bm1 ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_getattr_maxsz ;
2005-04-17 02:20:36 +04:00
}
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
{
2008-12-24 00:06:18 +03:00
encode_getattr_two ( xdr , bitmask [ 0 ] & nfs4_fattr_bitmap [ 0 ] ,
bitmask [ 1 ] & nfs4_fattr_bitmap [ 1 ] , hdr ) ;
2005-04-17 02:20:36 +04:00
}
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
{
2008-12-24 00:06:18 +03:00
encode_getattr_two ( xdr , bitmask [ 0 ] & nfs4_fsinfo_bitmap [ 0 ] ,
bitmask [ 1 ] & nfs4_fsinfo_bitmap [ 1 ] , 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
{
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 ( OP_GETFH ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_getfh_maxsz ;
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
{
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 + name - > len ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_LINK ) ;
2009-08-14 18:19:34 +04:00
xdr_encode_opaque ( p , name - > name , name - > len ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_link_maxsz ;
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 )
{
if ( ( fl - > fl_type & ( F_RDLCK | F_WRLCK | F_UNLCK ) ) = = F_RDLCK )
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 ;
p = reserve_space ( xdr , 28 ) ;
p = xdr_encode_hyper ( p , lowner - > clientid ) ;
* p + + = cpu_to_be32 ( 16 ) ;
p = xdr_encode_opaque_fixed ( p , " lock id: " , 8 ) ;
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
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 32 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_LOCK ) ;
* 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 ) {
2010-06-26 02:11:43 +04:00
p = reserve_space ( xdr , 4 + NFS4_STATEID_SIZE + 4 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( args - > open_seqid - > sequence - > counter ) ;
2009-08-14 18:19:06 +04:00
p = xdr_encode_opaque_fixed ( p , args - > open_stateid - > data , NFS4_STATEID_SIZE ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( args - > lock_seqid - > sequence - > counter ) ;
2010-06-26 02:11:43 +04:00
encode_lockowner ( xdr , & args - > lock_owner ) ;
2005-04-17 02:20:36 +04:00
}
else {
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , NFS4_STATEID_SIZE + 4 ) ;
2009-08-14 18:19:06 +04:00
p = xdr_encode_opaque_fixed ( p , args - > lock_stateid - > data , NFS4_STATEID_SIZE ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( args - > lock_seqid - > sequence - > counter ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_lock_maxsz ;
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
2010-06-26 02:11:43 +04:00
p = reserve_space ( xdr , 24 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_LOCKT ) ;
* 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 ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_lockt_maxsz ;
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
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 12 + NFS4_STATEID_SIZE + 16 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_LOCKU ) ;
* p + + = cpu_to_be32 ( nfs4_lock_type ( args - > fl , 0 ) ) ;
* p + + = cpu_to_be32 ( args - > seqid - > sequence - > counter ) ;
2009-08-14 18:19:06 +04:00
p = xdr_encode_opaque_fixed ( p , args - > stateid - > data , NFS4_STATEID_SIZE ) ;
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 ) ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_locku_maxsz ;
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 )
{
__be32 * p ;
p = reserve_space ( xdr , 4 ) ;
* p = cpu_to_be32 ( OP_RELEASE_LOCKOWNER ) ;
encode_lockowner ( xdr , lowner ) ;
hdr - > nops + + ;
hdr - > replen + = decode_release_lockowner_maxsz ;
}
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
{
int len = name - > len ;
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 + len ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_LOOKUP ) ;
2009-08-14 18:19:34 +04:00
xdr_encode_opaque ( p , name - > name , len ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_lookup_maxsz ;
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
*/
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 ( OP_OPEN ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( arg - > seqid - > sequence - > counter ) ;
2008-12-23 23:21:56 +03:00
encode_share_access ( xdr , arg - > fmode ) ;
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 28 ) ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , arg - > clientid ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( 16 ) ;
2009-08-14 18:19:06 +04:00
p = xdr_encode_opaque_fixed ( p , " open id: " , 8 ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_hyper ( p , arg - > id ) ;
2005-04-17 02:20:36 +04:00
}
static inline void encode_createmode ( struct xdr_stream * xdr , const struct nfs_openargs * arg )
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2009-12-05 21:30:21 +03:00
struct nfs_client * clp ;
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_EXCL ) {
2008-12-24 00:06:15 +03:00
case 0 :
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( NFS4_CREATE_UNCHECKED ) ;
2008-12-24 00:06:15 +03:00
encode_attrs ( xdr , arg - > u . attrs , arg - > server ) ;
break ;
default :
2009-12-05 21:30:21 +03:00
clp = arg - > server - > nfs_client ;
2010-06-16 17:52:27 +04:00
if ( clp - > cl_mvops - > minor_version > 0 ) {
2009-12-05 21:30:21 +03:00
if ( nfs4_has_persistent_session ( clp ) ) {
* p = cpu_to_be32 ( NFS4_CREATE_GUARDED ) ;
encode_attrs ( xdr , arg - > u . attrs , arg - > server ) ;
} else {
struct iattr dummy ;
* p = cpu_to_be32 ( NFS4_CREATE_EXCLUSIVE4_1 ) ;
encode_nfs4_verifier ( xdr , & arg - > u . verifier ) ;
dummy . ia_valid = 0 ;
encode_attrs ( xdr , & dummy , arg - > server ) ;
}
} else {
* p = cpu_to_be32 ( NFS4_CREATE_EXCLUSIVE ) ;
encode_nfs4_verifier ( xdr , & arg - > u . verifier ) ;
}
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 :
BUG_ON ( arg - > claim ! = NFS4_OPEN_CLAIM_NULL ) ;
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
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 + NFS4_STATEID_SIZE ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( NFS4_OPEN_CLAIM_DELEGATE_CUR ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_opaque_fixed ( p , stateid - > data , NFS4_STATEID_SIZE ) ;
2005-04-17 02:20:36 +04:00
encode_string ( xdr , name - > len , name - > name ) ;
}
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
{
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 ;
default :
BUG ( ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_open_maxsz ;
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
{
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 + NFS4_STATEID_SIZE + 4 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_OPEN_CONFIRM ) ;
2009-08-14 18:19:06 +04:00
p = xdr_encode_opaque_fixed ( p , arg - > stateid - > data , NFS4_STATEID_SIZE ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( arg - > seqid - > sequence - > counter ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_open_confirm_maxsz ;
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
{
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 + NFS4_STATEID_SIZE + 4 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_OPEN_DOWNGRADE ) ;
2009-08-14 18:19:06 +04:00
p = xdr_encode_opaque_fixed ( p , arg - > stateid - > data , NFS4_STATEID_SIZE ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( arg - > seqid - > sequence - > counter ) ;
2008-12-23 23:21:56 +03:00
encode_share_access ( xdr , arg - > fmode ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_open_downgrade_maxsz ;
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
{
int len = fh - > size ;
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 + len ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_PUTFH ) ;
2009-08-14 18:19:34 +04:00
xdr_encode_opaque ( p , fh - > data , len ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_putfh_maxsz ;
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
{
2008-12-24 00:06:15 +03:00
__be32 * p ;
2008-12-24 00:06:15 +03: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 ( OP_PUTROOTFH ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_putrootfh_maxsz ;
2005-04-17 02:20:36 +04:00
}
2010-06-26 00:35:53 +04:00
static void encode_stateid ( struct xdr_stream * xdr , const struct nfs_open_context * ctx , const struct nfs_lock_context * l_ctx )
2005-04-17 02:20:36 +04:00
{
nfs4_stateid stateid ;
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 , NFS4_STATEID_SIZE ) ;
2005-04-17 02:20:36 +04:00
if ( ctx - > state ! = NULL ) {
2010-07-01 20:49:11 +04:00
nfs4_copy_stateid ( & stateid , ctx - > state , l_ctx - > lockowner , l_ctx - > pid ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_opaque_fixed ( p , stateid . data , NFS4_STATEID_SIZE ) ;
2005-04-17 02:20:36 +04:00
} else
2009-08-14 18:19:30 +04:00
xdr_encode_opaque_fixed ( p , zero_stateid . data , NFS4_STATEID_SIZE ) ;
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
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 ( OP_READ ) ;
2005-04-17 02:20:36 +04:00
2010-06-26 00:35:53 +04:00
encode_stateid ( xdr , args - > context , args - > lock_context ) ;
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 ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_read_maxsz ;
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
{
2005-06-22 21:16:39 +04:00
uint32_t attrs [ 2 ] = {
FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_FILEID ,
FATTR4_WORD1_MOUNTED_ON_FILEID ,
} ;
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 , 12 + NFS4_VERIFIER_SIZE + 20 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_READDIR ) ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , readdir - > cookie ) ;
2009-08-14 18:19:06 +04:00
p = xdr_encode_opaque_fixed ( p , readdir - > verifier . data , NFS4_VERIFIER_SIZE ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( readdir - > count > > 1 ) ; /* We're not doing readdirplus */
* p + + = cpu_to_be32 ( readdir - > count ) ;
* p + + = cpu_to_be32 ( 2 ) ;
2005-06-22 21:16:39 +04:00
/* Switch to mounted_on_fileid if the server supports it */
if ( readdir - > bitmask [ 1 ] & FATTR4_WORD1_MOUNTED_ON_FILEID )
attrs [ 0 ] & = ~ FATTR4_WORD0_FILEID ;
else
attrs [ 1 ] & = ~ FATTR4_WORD1_MOUNTED_ON_FILEID ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( attrs [ 0 ] & readdir - > bitmask [ 0 ] ) ;
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( attrs [ 1 ] & readdir - > bitmask [ 1 ] ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_readdir_maxsz ;
2008-04-02 16:21:15 +04:00
dprintk ( " %s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x \n " ,
__func__ ,
2005-06-22 21:16:39 +04:00
( unsigned long long ) readdir - > cookie ,
( ( u32 * ) readdir - > verifier . data ) [ 0 ] ,
( ( u32 * ) readdir - > verifier . data ) [ 1 ] ,
attrs [ 0 ] & readdir - > bitmask [ 0 ] ,
attrs [ 1 ] & readdir - > bitmask [ 1 ] ) ;
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
{
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 ( OP_READLINK ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_readlink_maxsz ;
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
{
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 + name - > len ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_REMOVE ) ;
2009-08-14 18:19:34 +04:00
xdr_encode_opaque ( p , name - > name , name - > len ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_remove_maxsz ;
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
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:34 +04:00
p = reserve_space ( xdr , 4 ) ;
* p = cpu_to_be32 ( OP_RENAME ) ;
encode_string ( xdr , oldname - > len , oldname - > name ) ;
encode_string ( xdr , newname - > len , newname - > name ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_rename_maxsz ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:06:18 +03:00
static void encode_renew ( struct xdr_stream * xdr , const struct nfs_client * client_stateid , 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
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 12 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_RENEW ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_hyper ( p , client_stateid - > cl_clientid ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_renew_maxsz ;
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
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-10-28 06:12:40 +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 ( OP_RESTOREFH ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_restorefh_maxsz ;
2005-10-28 06:12:40 +04:00
}
2005-06-22 21:16:22 +04:00
static int
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
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 + NFS4_STATEID_SIZE ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_SETATTR ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_opaque_fixed ( p , zero_stateid . data , NFS4_STATEID_SIZE ) ;
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 ) ;
2005-06-22 21:16:22 +04:00
if ( arg - > acl_len % 4 )
return - EINVAL ;
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:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_setacl_maxsz ;
2005-06-22 21:16:22 +04:00
return 0 ;
}
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
{
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 ( OP_SAVEFH ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_savefh_maxsz ;
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
{
2006-10-20 10:28:48 +04:00
__be32 * p ;
2008-12-24 00:06:15 +03:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 + NFS4_STATEID_SIZE ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_SETATTR ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_opaque_fixed ( p , arg - > stateid . data , NFS4_STATEID_SIZE ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_setattr_maxsz ;
2008-12-24 00:06:18 +03:00
encode_attrs ( xdr , arg - > iap , 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
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 + NFS4_VERIFIER_SIZE ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_SETCLIENTID ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_opaque_fixed ( p , setclientid - > sc_verifier - > data , NFS4_VERIFIER_SIZE ) ;
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 ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_setclientid_maxsz ;
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
{
2008-12-24 00:06:15 +03:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 12 + NFS4_VERIFIER_SIZE ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_SETCLIENTID_CONFIRM ) ;
2010-04-17 00:43:06 +04:00
p = xdr_encode_hyper ( p , arg - > clientid ) ;
xdr_encode_opaque_fixed ( p , arg - > confirm . data , NFS4_VERIFIER_SIZE ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_setclientid_confirm_maxsz ;
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
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 ( OP_WRITE ) ;
2005-04-17 02:20:36 +04:00
2010-06-26 00:35:53 +04:00
encode_stateid ( xdr , args - > context , args - > lock_context ) ;
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:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_write_maxsz ;
2005-04-17 02:20:36 +04:00
}
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
{
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 + NFS4_STATEID_SIZE ) ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_DELEGRETURN ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_opaque_fixed ( p , stateid - > data , NFS4_STATEID_SIZE ) ;
2008-12-24 00:06:17 +03:00
hdr - > nops + + ;
2009-04-01 17:22:08 +04:00
hdr - > replen + = decode_delegreturn_maxsz ;
2005-04-17 02:20:36 +04:00
}
2009-04-01 17:22:11 +04: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 */
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 ;
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 + sizeof ( args - > verifier - > data ) ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_EXCHANGE_ID ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_opaque_fixed ( p , args - > verifier - > data , sizeof ( args - > verifier - > data ) ) ;
2009-04-01 17:22:29 +04:00
encode_string ( xdr , args - > id_len , args - > id ) ;
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 12 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( args - > flags ) ;
* p + + = cpu_to_be32 ( 0 ) ; /* zero length state_protect4_a */
2009-08-14 18:19:30 +04:00
* p = cpu_to_be32 ( 0 ) ; /* zero length implementation id array */
2009-04-01 17:22:29 +04:00
hdr - > nops + + ;
hdr - > replen + = decode_exchange_id_maxsz ;
}
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 ;
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
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 20 + 2 * 28 + 20 + len + 12 ) ;
2009-08-14 18:19:13 +04:00
* p + + = cpu_to_be32 ( OP_CREATE_SESSION ) ;
2009-08-14 18:19:01 +04:00
p = xdr_encode_hyper ( p , clp - > cl_ex_clid ) ;
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 */
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( args - > fc_attrs . headerpadsz ) ; /* header padding size */
* 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 */
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( args - > fc_attrs . headerpadsz ) ; /* header padding size */
* 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 */
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( ( u32 ) clp - > cl_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
hdr - > nops + + ;
hdr - > replen + = decode_create_session_maxsz ;
}
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 )
{
__be32 * p ;
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 + NFS4_MAX_SESSIONID_LEN ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_DESTROY_SESSION ) ;
2009-08-14 18:19:30 +04:00
xdr_encode_opaque_fixed ( p , session - > sess_id . data , NFS4_MAX_SESSIONID_LEN ) ;
2009-04-01 17:22:34 +04:00
hdr - > nops + + ;
hdr - > replen + = decode_destroy_session_maxsz ;
}
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 )
{
__be32 * p ;
p = reserve_space ( xdr , 8 ) ;
* p + + = cpu_to_be32 ( OP_RECLAIM_COMPLETE ) ;
* p + + = cpu_to_be32 ( args - > one_fs ) ;
hdr - > nops + + ;
hdr - > replen + = decode_reclaim_complete_maxsz ;
}
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)
struct nfs4_session * session = args - > sa_session ;
2009-04-01 17:22:36 +04:00
struct nfs4_slot_table * tp ;
struct nfs4_slot * slot ;
__be32 * p ;
2009-04-01 17:22:11 +04:00
if ( ! session )
return ;
2009-04-01 17:22:36 +04:00
tp = & session - > fc_slot_table ;
WARN_ON ( args - > sa_slotid = = NFS4_MAX_SLOT_TABLE ) ;
slot = tp - > slots + args - > sa_slotid ;
2009-08-14 18:19:25 +04:00
p = reserve_space ( xdr , 4 + NFS4_MAX_SESSIONID_LEN + 16 ) ;
2009-08-14 18:18:54 +04:00
* p + + = cpu_to_be32 ( OP_SEQUENCE ) ;
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 ] ,
slot - > seq_nr , args - > sa_slotid ,
tp - > highest_used_slotid , args - > sa_cache_this ) ;
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 ) ;
* p + + = cpu_to_be32 ( args - > sa_slotid ) ;
* 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
hdr - > nops + + ;
hdr - > replen + = decode_sequence_maxsz ;
# 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)
if ( args - > sa_session )
2010-06-16 17:52:27 +04:00
return args - > sa_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
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_access ( struct rpc_rqst * req , __be32 * p , const struct nfs4_accessargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode LOOKUP request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_lookup ( struct rpc_rqst * req , __be32 * p , const struct nfs4_lookup_arg * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode LOOKUP_ROOT request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_lookup_root ( struct rpc_rqst * req , __be32 * p , const struct nfs4_lookup_root_arg * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode REMOVE request
*/
2007-07-14 23:39:57 +04:00
static int nfs4_xdr_enc_remove ( struct rpc_rqst * req , __be32 * p , const struct nfs_removeargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_remove ( & xdr , & args - > name , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode RENAME request
*/
2010-09-18 01:30:25 +04:00
static int nfs4_xdr_enc_rename ( struct rpc_rqst * req , __be32 * p , const struct nfs_renameargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
encode_restorefh ( & xdr , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode LINK request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_link ( struct rpc_rqst * req , __be32 * p , const struct nfs4_link_arg * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_savefh ( & xdr , & hdr ) ;
encode_putfh ( & xdr , args - > dir_fh , & hdr ) ;
encode_link ( & xdr , args - > name , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
encode_restorefh ( & xdr , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode CREATE request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_create ( struct rpc_rqst * req , __be32 * p , const struct nfs4_create_arg * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > dir_fh , & hdr ) ;
encode_savefh ( & xdr , & hdr ) ;
encode_create ( & xdr , args , & hdr ) ;
encode_getfh ( & xdr , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
encode_restorefh ( & xdr , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode SYMLINK request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_symlink ( struct rpc_rqst * req , __be32 * p , const struct nfs4_create_arg * args )
2005-04-17 02:20:36 +04:00
{
return nfs4_xdr_enc_create ( req , p , args ) ;
}
/*
* Encode GETATTR request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_getattr ( struct rpc_rqst * req , __be32 * p , const struct nfs4_getattr_arg * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a CLOSE request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_close ( struct rpc_rqst * req , __be32 * p , struct nfs_closeargs * args )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode an OPEN request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_open ( struct rpc_rqst * req , __be32 * p , struct nfs_openargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_savefh ( & xdr , & hdr ) ;
encode_open ( & xdr , args , & hdr ) ;
encode_getfh ( & xdr , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
encode_restorefh ( & xdr , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode an OPEN_CONFIRM request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_open_confirm ( struct rpc_rqst * req , __be32 * p , struct nfs_open_confirmargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr = {
2008-12-24 00:06:17 +03:00
. nops = 0 ,
2005-04-17 02:20:36 +04:00
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_open_confirm ( & xdr , args , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode an OPEN request with no attributes .
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_open_noattr ( struct rpc_rqst * req , __be32 * p , struct nfs_openargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_open ( & xdr , args , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode an OPEN_DOWNGRADE request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_open_downgrade ( struct rpc_rqst * req , __be32 * p , struct nfs_closeargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a LOCK request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_lock ( struct rpc_rqst * req , __be32 * p , struct nfs_lock_args * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_lock ( & xdr , args , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a LOCKT request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_lockt ( struct rpc_rqst * req , __be32 * p , struct nfs_lockt_args * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_lockt ( & xdr , args , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a LOCKU request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_locku ( struct rpc_rqst * req , __be32 * p , struct nfs_locku_args * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_locku ( & xdr , args , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2010-07-01 20:49:01 +04:00
static int nfs4_xdr_enc_release_lockowner ( struct rpc_rqst * req , __be32 * p , struct nfs_release_lockowner_args * args )
{
struct xdr_stream xdr ;
struct compound_hdr hdr = {
. minorversion = 0 ,
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
encode_compound_hdr ( & xdr , req , & hdr ) ;
encode_release_lockowner ( & xdr , & args - > lock_owner , & hdr ) ;
encode_nops ( & hdr ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
/*
* Encode a READLINK request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_readlink ( struct rpc_rqst * req , __be32 * p , const struct nfs4_readlink * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a READDIR request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_readdir ( struct rpc_rqst * req , __be32 * p , const struct nfs4_readdir_arg * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode a READ request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_read ( struct rpc_rqst * req , __be32 * p , struct nfs_readargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* Encode an SETATTR request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_setattr ( struct rpc_rqst * req , __be32 * p , struct nfs_setattrargs * args )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2005-06-22 21:16:22 +04:00
/*
* Encode a GETACL request
*/
static int
2006-10-20 10:28:48 +04:00
nfs4_xdr_enc_getacl ( struct rpc_rqst * req , __be32 * p ,
2005-06-22 21:16:22 +04:00
struct nfs_getaclargs * args )
{
struct xdr_stream xdr ;
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
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
2009-12-03 16:10:17 +03:00
replen = hdr . replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1 ;
2008-12-24 00:06:18 +03:00
encode_getattr_two ( & xdr , FATTR4_WORD0_ACL , 0 , & hdr ) ;
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 ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-06-22 21:16:22 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* Encode a WRITE request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_write ( struct rpc_rqst * req , __be32 * p , struct nfs_writeargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 ;
2008-12-24 00:06:18 +03:00
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* a COMMIT request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_commit ( struct rpc_rqst * req , __be32 * p , struct nfs_writeargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_commit ( & xdr , args , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* FSINFO request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_fsinfo ( struct rpc_rqst * req , __be32 * p , struct nfs4_fsinfo_arg * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_fsinfo ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* a PATHCONF request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_pathconf ( struct rpc_rqst * req , __be32 * p , const struct nfs4_pathconf_arg * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_getattr_one ( & xdr , args - > bitmask [ 0 ] & nfs4_pathconf_bitmap [ 0 ] ,
& hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* a STATFS request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_statfs ( struct rpc_rqst * req , __be32 * p , const struct nfs4_statfs_arg * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
encode_getattr_two ( & xdr , args - > bitmask [ 0 ] & nfs4_statfs_bitmap [ 0 ] ,
args - > bitmask [ 1 ] & nfs4_statfs_bitmap [ 1 ] , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* GETATTR_BITMAP request
*/
2009-04-01 17:21:54 +04:00
static int nfs4_xdr_enc_server_caps ( struct rpc_rqst * req , __be32 * p ,
struct nfs4_server_caps_arg * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2009-04-01 17:21:54 +04:00
encode_putfh ( & xdr , args - > fhandle , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_getattr_one ( & xdr , FATTR4_WORD0_SUPPORTED_ATTRS |
FATTR4_WORD0_LINK_SUPPORT |
FATTR4_WORD0_SYMLINK_SUPPORT |
FATTR4_WORD0_ACLSUPPORT , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* a RENEW request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_renew ( struct rpc_rqst * req , __be32 * p , struct nfs_client * clp )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr = {
2008-12-24 00:06:17 +03:00
. nops = 0 ,
2005-04-17 02:20:36 +04:00
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_renew ( & xdr , clp , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* a SETCLIENTID request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_setclientid ( struct rpc_rqst * req , __be32 * p , struct nfs4_setclientid * sc )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr = {
2008-12-24 00:06:17 +03:00
. nops = 0 ,
2005-04-17 02:20:36 +04:00
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_setclientid ( & xdr , sc , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* a SETCLIENTID_CONFIRM request
*/
2010-04-17 00:43:06 +04:00
static int nfs4_xdr_enc_setclientid_confirm ( struct rpc_rqst * req , __be32 * p , struct nfs4_setclientid_res * arg )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr = {
2008-12-24 00:06:17 +03:00
. nops = 0 ,
2005-04-17 02:20:36 +04:00
} ;
const u32 lease_bitmap [ 2 ] = { FATTR4_WORD0_LEASE_TIME , 0 } ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2010-04-17 00:43:06 +04:00
encode_setclientid_confirm ( & xdr , arg , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putrootfh ( & xdr , & hdr ) ;
encode_fsinfo ( & xdr , lease_bitmap , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* DELEGRETURN request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_delegreturn ( struct rpc_rqst * req , __be32 * p , const struct nfs4_delegreturnargs * args )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fhandle , & hdr ) ;
encode_delegreturn ( & xdr , args - > stateid , & hdr ) ;
encode_getfattr ( & xdr , args - > bitmask , & hdr ) ;
2008-12-24 00:06:17 +03:00
encode_nops ( & hdr ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2006-06-09 17:34:22 +04:00
/*
* Encode FS_LOCATIONS request
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_enc_fs_locations ( struct rpc_rqst * req , __be32 * p , struct nfs4_fs_locations_arg * args )
2006-06-09 17:34:22 +04:00
{
struct xdr_stream xdr ;
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
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
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 */
2008-12-24 00:06:18 +03:00
encode_fs_locations ( & xdr , args - > bitmask , & hdr ) ;
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 ) ;
2008-12-24 00:06:18 +03:00
return 0 ;
2006-06-09 17:34:22 +04:00
}
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
/*
* EXCHANGE_ID request
*/
static int nfs4_xdr_enc_exchange_id ( struct rpc_rqst * req , uint32_t * p ,
struct nfs41_exchange_id_args * args )
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
encode_compound_hdr ( & xdr , req , & hdr ) ;
encode_exchange_id ( & xdr , args , & hdr ) ;
encode_nops ( & hdr ) ;
return 0 ;
}
2009-04-01 17:22:30 +04:00
2009-04-01 17:22:31 +04:00
/*
* a CREATE_SESSION request
*/
static int nfs4_xdr_enc_create_session ( struct rpc_rqst * req , uint32_t * p ,
struct nfs41_create_session_args * args )
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
encode_compound_hdr ( & xdr , req , & hdr ) ;
encode_create_session ( & xdr , args , & hdr ) ;
encode_nops ( & hdr ) ;
return 0 ;
}
2009-04-01 17:22:34 +04:00
/*
* a DESTROY_SESSION request
*/
static int nfs4_xdr_enc_destroy_session ( struct rpc_rqst * req , uint32_t * p ,
struct nfs4_session * session )
{
struct xdr_stream xdr ;
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
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
encode_compound_hdr ( & xdr , req , & hdr ) ;
encode_destroy_session ( & xdr , session , & hdr ) ;
encode_nops ( & hdr ) ;
return 0 ;
}
2009-04-01 17:22:36 +04:00
/*
* a SEQUENCE request
*/
static int nfs4_xdr_enc_sequence ( struct rpc_rqst * req , uint32_t * p ,
struct nfs4_sequence_args * args )
{
struct xdr_stream xdr ;
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( args ) ,
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
encode_compound_hdr ( & xdr , req , & hdr ) ;
encode_sequence ( & xdr , args , & hdr ) ;
encode_nops ( & hdr ) ;
return 0 ;
}
2009-04-01 17:22:30 +04:00
/*
* a GET_LEASE_TIME request
*/
static int nfs4_xdr_enc_get_lease_time ( struct rpc_rqst * req , uint32_t * p ,
struct nfs4_get_lease_time_args * args )
{
struct xdr_stream xdr ;
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > la_seq_args ) ,
} ;
const u32 lease_bitmap [ 2 ] = { FATTR4_WORD0_LEASE_TIME , 0 } ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
encode_compound_hdr ( & xdr , req , & hdr ) ;
encode_sequence ( & xdr , & args - > la_seq_args , & hdr ) ;
encode_putrootfh ( & xdr , & hdr ) ;
encode_fsinfo ( & xdr , lease_bitmap , & hdr ) ;
encode_nops ( & hdr ) ;
return 0 ;
}
2009-12-06 00:08:40 +03:00
/*
* a RECLAIM_COMPLETE request
*/
static int nfs4_xdr_enc_reclaim_complete ( struct rpc_rqst * req , uint32_t * p ,
struct nfs41_reclaim_complete_args * args )
{
struct xdr_stream xdr ;
struct compound_hdr hdr = {
. minorversion = nfs4_xdr_minorversion ( & args - > seq_args )
} ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
encode_compound_hdr ( & xdr , req , & hdr ) ;
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
encode_reclaim_complete ( & xdr , args , & hdr ) ;
encode_nops ( & hdr ) ;
return 0 ;
}
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
bitmap [ 0 ] = bitmap [ 1 ] = 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 + + ) ;
2005-04-17 02:20:36 +04:00
if ( bmlen > 1 )
2009-08-14 18:20:19 +04:00
bitmap [ 1 ] = 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
}
2006-10-20 10:28:48 +04:00
static inline int decode_attr_length ( struct xdr_stream * xdr , uint32_t * attrlen , __be32 * * 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 ) ;
2005-04-17 02:20:36 +04:00
* savep = xdr - > 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_attr_supported ( struct xdr_stream * xdr , uint32_t * bitmap , uint32_t * bitmask )
{
if ( likely ( bitmap [ 0 ] & FATTR4_WORD0_SUPPORTED_ATTRS ) ) {
decode_attr_bitmap ( xdr , bitmask ) ;
bitmap [ 0 ] & = ~ FATTR4_WORD0_SUPPORTED_ATTRS ;
} else
bitmask [ 0 ] = bitmask [ 1 ] = 0 ;
2008-04-02 16:21:15 +04:00
dprintk ( " %s: bitmask=%08x:%08x \n " , __func__ , bitmask [ 0 ] , bitmask [ 1 ] ) ;
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
}
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
}
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 ;
2009-03-11 21:10:27 +03:00
ret = NFS_ATTR_FATTR_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 ;
2006-06-09 17:34:23 +04:00
dprintk ( " path " ) ;
path - > ncomponents = 0 ;
while ( path - > ncomponents < n ) {
struct nfs4_string * component = & path - > components [ path - > ncomponents ] ;
status = decode_opaque_inline ( xdr , & component - > len , & component - > data ) ;
if ( unlikely ( status ! = 0 ) )
goto out_eio ;
if ( path - > ncomponents ! = n )
dprintk ( " / " ) ;
dprintk ( " %s " , component - > data ) ;
if ( path - > ncomponents < NFS4_PATHNAME_MAXCOMPONENTS )
path - > ncomponents + + ;
else {
dprintk ( " cannot parse %d components in path \n " , n ) ;
goto out_eio ;
}
}
out :
dprintk ( " \n " ) ;
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 ;
dprintk ( " path / \n " ) ;
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 ;
2008-05-03 00:42:44 +04:00
dprintk ( " %s: fsroot " , __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 ;
res - > nlocations = 0 ;
while ( res - > nlocations < n ) {
2007-10-26 21:32:08 +04:00
u32 m ;
2006-06-09 17:34:23 +04:00
struct nfs4_fs_location * loc = & res - > locations [ res - > nlocations ] ;
2006-06-09 17:34:22 +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
m = be32_to_cpup ( p ) ;
2006-06-09 17:34:23 +04:00
loc - > nservers = 0 ;
2008-05-03 00:42:44 +04:00
dprintk ( " %s: servers " , __func__ ) ;
2006-06-09 17:34:23 +04:00
while ( loc - > nservers < m ) {
struct nfs4_string * 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 ) ;
if ( loc - > nservers < NFS4_FS_LOCATION_MAXSERVERS )
loc - > nservers + + ;
else {
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 ;
}
}
}
status = decode_pathname ( xdr , & loc - > rootpath ) ;
2006-06-09 17:34:22 +04:00
if ( unlikely ( status ! = 0 ) )
goto out_eio ;
2006-06-09 17:34:23 +04:00
if ( res - > nlocations < NFS4_FS_LOCATIONS_MAXENTRIES )
2006-06-09 17:34:22 +04:00
res - > nlocations + + ;
}
2009-03-11 21:10:27 +03:00
if ( res - > nlocations ! = 0 )
status = NFS_ATTR_FATTR_V4_REFERRAL ;
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 ,
struct nfs_client * clp , uint32_t * uid , int may_sleep )
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
* uid = - 2 ;
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 ;
2009-08-09 23:06:19 +04:00
if ( ! may_sleep ) {
/* do nothing */
} else if ( len < XDR_MAX_NETOBJ ) {
2009-03-11 21:10:27 +03:00
if ( nfs_map_name_to_uid ( clp , ( char * ) p , len , uid ) = = 0 )
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 ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: uid=%d \n " , __func__ , ( int ) * 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 ,
struct nfs_client * clp , uint32_t * gid , int may_sleep )
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
* gid = - 2 ;
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 ;
2009-08-09 23:06:19 +04:00
if ( ! may_sleep ) {
/* do nothing */
} else if ( len < XDR_MAX_NETOBJ ) {
2009-03-11 21:10:27 +03:00
if ( nfs_map_group_to_gid ( clp , ( char * ) p , len , gid ) = = 0 )
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 ;
}
2008-05-03 00:42:44 +04:00
dprintk ( " %s: gid=%d \n " , __func__ , ( int ) * 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 ;
}
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 ;
}
2006-10-20 10:28:48 +04:00
static int verify_attr_len ( struct xdr_stream * xdr , __be32 * savep , uint32_t attrlen )
2005-04-17 02:20:36 +04:00
{
unsigned int attrwords = XDR_QUADLEN ( attrlen ) ;
unsigned int nwords = xdr - > p - savep ;
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
}
static int decode_access ( struct xdr_stream * xdr , struct nfs4_accessres * access )
{
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 ) ;
2005-04-17 02:20:36 +04:00
access - > supported = supp ;
access - > access = acc ;
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 )
{
return decode_opaque_fixed ( xdr , stateid - > data , NFS4_STATEID_SIZE ) ;
}
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 )
{
return decode_opaque_fixed ( xdr , verifier , 8 ) ;
2005-04-17 02:20:36 +04:00
}
static int decode_commit ( struct xdr_stream * xdr , struct nfs_writeres * res )
{
int status ;
status = decode_op_hdr ( xdr , OP_COMMIT ) ;
2009-08-14 18:19:56 +04:00
if ( ! status )
status = decode_verifier ( xdr , res - > verf - > verifier ) ;
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 )
{
2006-10-20 10:28:48 +04:00
__be32 * savep ;
2008-12-24 00:06:15 +03:00
uint32_t attrlen , bitmap [ 2 ] = { 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 ;
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 )
{
2006-10-20 10:28:48 +04:00
__be32 * savep ;
2008-12-24 00:06:15 +03:00
uint32_t attrlen , bitmap [ 2 ] = { 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 )
{
2006-10-20 10:28:48 +04:00
__be32 * savep ;
2008-12-24 00:06:15 +03:00
uint32_t attrlen , bitmap [ 2 ] = { 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 ;
}
2009-08-09 23:06:19 +04:00
static int decode_getfattr ( struct xdr_stream * xdr , struct nfs_fattr * fattr ,
const struct nfs_server * server , int may_sleep )
2005-04-17 02:20:36 +04:00
{
2006-10-20 10:28:48 +04:00
__be32 * savep ;
2005-04-17 02:20:36 +04:00
uint32_t attrlen ,
bitmap [ 2 ] = { 0 } ,
type ;
2009-03-11 21:10:26 +03:00
int status ;
umode_t fmode = 0 ;
2006-06-09 17:34:24 +04:00
uint64_t fileid ;
2005-04-17 02:20:36 +04:00
2009-03-11 21:10:26 +03:00
status = decode_op_hdr ( xdr , OP_GETATTR ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:26 +03:00
status = decode_attr_bitmap ( xdr , bitmap ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
2009-03-11 21:10:26 +03:00
status = decode_attr_length ( xdr , & attrlen , & savep ) ;
if ( status < 0 )
2005-04-17 02:20:36 +04:00
goto xdr_error ;
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
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
status = decode_attr_fs_locations ( xdr , bitmap , container_of ( fattr ,
2006-06-09 17:34:23 +04:00
struct nfs4_fs_locations ,
2009-03-11 21:10:26 +03:00
fattr ) ) ;
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
2009-08-09 23:06:19 +04:00
status = decode_attr_owner ( xdr , bitmap , server - > nfs_client ,
& fattr - > uid , may_sleep ) ;
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
2009-08-09 23:06:19 +04:00
status = decode_attr_group ( xdr , bitmap , server - > nfs_client ,
& fattr - > gid , may_sleep ) ;
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
status = decode_attr_mounted_on_fileid ( xdr , bitmap , & fileid ) ;
if ( status < 0 )
2006-06-09 17:34:24 +04:00
goto xdr_error ;
2009-03-11 21:10:27 +03:00
if ( status ! = 0 & & ! ( fattr - > valid & status ) ) {
2006-06-09 17:34:24 +04:00
fattr - > fileid = fileid ;
2009-03-11 21:10:27 +03:00
fattr - > valid | = status ;
}
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 ;
}
static int decode_fsinfo ( struct xdr_stream * xdr , struct nfs_fsinfo * fsinfo )
{
2006-10-20 10:28:48 +04:00
__be32 * savep ;
2005-04-17 02:20:36 +04:00
uint32_t attrlen , bitmap [ 2 ] ;
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 ;
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
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 32 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:41 +04:00
p = xdr_decode_hyper ( p , & offset ) ;
p = xdr_decode_hyper ( p , & length ) ;
2009-08-14 18:19:37 +04:00
type = be32_to_cpup ( p + + ) ;
2006-01-03 11:55:16 +03:00
if ( fl ! = NULL ) {
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 ;
}
2009-08-14 18:19:41 +04:00
p = xdr_decode_hyper ( p , & clientid ) ;
2009-08-14 18:20:19 +04:00
namelen = be32_to_cpup ( p ) ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , namelen ) ;
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 )
{
struct kvec * iov = req - > rq_rcv_buf . head ;
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
uint32_t count , eof , recvd , hdrlen ;
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 ) ;
2005-04-17 02:20:36 +04:00
hdrlen = ( u8 * ) p - ( u8 * ) iov - > iov_base ;
recvd = req - > rq_rcv_buf . len - hdrlen ;
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 ;
}
xdr_read_pages ( xdr , count ) ;
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 )
{
struct xdr_buf * rcvbuf = & req - > rq_rcv_buf ;
struct page * page = * rcvbuf - > pages ;
struct kvec * iov = rcvbuf - > head ;
2007-10-26 21:32:03 +04:00
size_t hdrlen ;
u32 recvd , pglen = rcvbuf - > page_len ;
2006-10-20 10:28:48 +04:00
__be32 * end , * entry , * p , * kaddr ;
2008-02-22 22:50:01 +03:00
unsigned int nr = 0 ;
2007-10-26 21:32:03 +04:00
int status ;
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 ;
2008-04-02 16:21:15 +04:00
dprintk ( " %s: verifier = %08x:%08x \n " ,
__func__ ,
2005-06-22 21:16:39 +04:00
( ( u32 * ) readdir - > verifier . data ) [ 0 ] ,
( ( u32 * ) readdir - > verifier . data ) [ 1 ] ) ;
2005-04-17 02:20:36 +04:00
2009-08-14 18:19:56 +04:00
hdrlen = ( char * ) xdr - > p - ( char * ) iov - > iov_base ;
2005-04-17 02:20:36 +04:00
recvd = rcvbuf - > len - hdrlen ;
if ( pglen > recvd )
pglen = recvd ;
xdr_read_pages ( xdr , pglen ) ;
BUG_ON ( pglen + readdir - > pgbase > PAGE_CACHE_SIZE ) ;
2006-10-20 10:28:48 +04:00
kaddr = p = kmap_atomic ( page , KM_USER0 ) ;
2006-08-24 23:44:19 +04:00
end = p + ( ( pglen + readdir - > pgbase ) > > 2 ) ;
2005-04-17 02:20:36 +04:00
entry = p ;
2008-02-22 22:50:01 +03:00
/* Make sure the packet actually has a value_follows and EOF entry */
if ( ( entry + 1 ) > end )
goto short_pkt ;
for ( ; * p + + ; nr + + ) {
2007-10-26 21:32:03 +04:00
u32 len , attrlen , xlen ;
2006-08-24 23:44:19 +04:00
if ( end - p < 3 )
2005-04-17 02:20:36 +04:00
goto short_pkt ;
2005-06-22 21:16:39 +04:00
dprintk ( " cookie = %Lu, " , * ( ( unsigned long long * ) p ) ) ;
2005-04-17 02:20:36 +04:00
p + = 2 ; /* cookie */
len = ntohl ( * p + + ) ; /* filename length */
if ( len > NFS4_MAXNAMLEN ) {
2007-09-12 02:01:10 +04:00
dprintk ( " NFS: giant filename in readdir (len 0x%x) \n " ,
len ) ;
2005-04-17 02:20:36 +04:00
goto err_unmap ;
}
2006-08-24 23:44:19 +04:00
xlen = XDR_QUADLEN ( len ) ;
if ( end - p < xlen + 1 )
2005-04-17 02:20:36 +04:00
goto short_pkt ;
2006-08-24 23:44:19 +04:00
dprintk ( " filename = %*s \n " , len , ( char * ) p ) ;
p + = xlen ;
2005-04-17 02:20:36 +04:00
len = ntohl ( * p + + ) ; /* bitmap length */
2006-08-24 23:44:19 +04:00
if ( end - p < len + 1 )
2005-04-17 02:20:36 +04:00
goto short_pkt ;
2006-08-24 23:44:19 +04:00
p + = len ;
2005-04-17 02:20:36 +04:00
attrlen = XDR_QUADLEN ( ntohl ( * p + + ) ) ;
2006-08-24 23:44:19 +04:00
if ( end - p < attrlen + 2 )
2005-04-17 02:20:36 +04:00
goto short_pkt ;
2006-08-24 23:44:19 +04:00
p + = attrlen ; /* attributes */
2005-04-17 02:20:36 +04:00
entry = p ;
}
2008-02-22 22:50:01 +03:00
/*
* Apparently some server sends responses that are a valid size , but
* contain no entries , and have value_follows = = 0 and EOF = = 0. For
* those , just set the EOF marker .
*/
if ( ! nr & & entry [ 1 ] = = 0 ) {
dprintk ( " NFS: readdir reply truncated! \n " ) ;
entry [ 1 ] = 1 ;
}
2008-12-24 00:06:15 +03:00
out :
2005-04-17 02:20:36 +04:00
kunmap_atomic ( kaddr , KM_USER0 ) ;
return 0 ;
short_pkt :
2008-02-22 22:50:01 +03:00
/*
* When we get a short packet there are 2 possibilities . We can
* return an error , or fix up the response to look like a valid
* response and return what we have so far . If there are no
* entries and the packet was short , then return - EIO . If there
* are valid entries in the response , return them and pretend that
* the call was successful , but incomplete . The caller can retry the
* readdir starting at the last cookie .
*/
2008-05-03 00:42:44 +04:00
dprintk ( " %s: short packet at entry %d \n " , __func__ , nr ) ;
2005-04-17 02:20:36 +04:00
entry [ 0 ] = entry [ 1 ] = 0 ;
2008-02-22 22:50:01 +03:00
if ( nr )
goto out ;
2005-04-17 02:20:36 +04:00
err_unmap :
kunmap_atomic ( kaddr , KM_USER0 ) ;
return - errno_NFSERR_IO ;
}
static int decode_readlink ( struct xdr_stream * xdr , struct rpc_rqst * req )
{
struct xdr_buf * rcvbuf = & req - > rq_rcv_buf ;
struct kvec * iov = rcvbuf - > head ;
2007-10-26 21:32:03 +04:00
size_t hdrlen ;
u32 len , recvd ;
2006-10-20 10:28:48 +04:00
__be32 * p ;
2005-04-17 02:20:36 +04:00
char * kaddr ;
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 ;
}
hdrlen = ( char * ) xdr - > p - ( char * ) iov - > iov_base ;
recvd = req - > rq_rcv_buf . len - hdrlen ;
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 ;
}
xdr_read_pages ( xdr , len ) ;
/*
* 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 ) .
*/
kaddr = ( char * ) kmap_atomic ( rcvbuf - > pages [ 0 ] , KM_USER0 ) ;
kaddr [ len + rcvbuf - > page_base ] = ' \0 ' ;
kunmap_atomic ( kaddr , KM_USER0 ) ;
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 ,
size_t * acl_len )
{
2006-10-20 10:28:48 +04:00
__be32 * savep ;
2005-06-22 21:16:22 +04:00
uint32_t attrlen ,
bitmap [ 2 ] = { 0 } ;
struct kvec * iov = req - > rq_rcv_buf . head ;
int status ;
* acl_len = 0 ;
if ( ( status = decode_op_hdr ( xdr , OP_GETATTR ) ) ! = 0 )
goto out ;
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 ) ) {
2007-10-26 21:32:03 +04:00
size_t hdrlen ;
u32 recvd ;
2005-06-22 21:16:22 +04:00
/* We ignore &savep and don't do consistency checks on
* the attr length . Let userspace figure it out . . . . */
hdrlen = ( u8 * ) xdr - > p - ( u8 * ) iov - > iov_base ;
recvd = req - > rq_rcv_buf . len - hdrlen ;
if ( attrlen > recvd ) {
2007-09-12 02:01:10 +04:00
dprintk ( " NFS: server cheating in getattr "
2005-06-22 21:16:22 +04:00
" acl reply: attrlen %u > recvd %u \n " ,
attrlen , recvd ) ;
return - EINVAL ;
}
2006-05-31 00:28:58 +04:00
xdr_read_pages ( xdr , attrlen ) ;
2005-06-22 21:16:22 +04:00
* acl_len = attrlen ;
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 ;
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:37 +04:00
res - > count = be32_to_cpup ( p + + ) ;
res - > verf - > committed = be32_to_cpup ( p + + ) ;
2009-08-14 18:20:05 +04:00
memcpy ( res - > verf - > verifier , p , 8 ) ;
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_delegreturn ( struct xdr_stream * xdr )
{
return decode_op_hdr ( xdr , OP_DELEGRETURN ) ;
}
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
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 ;
struct nfs_client * clp = res - > client ;
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 ;
2009-08-14 18:20:19 +04:00
xdr_decode_hyper ( p , & clp - > cl_ex_clid ) ;
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
clp - > cl_seqid = be32_to_cpup ( p + + ) ;
clp - > cl_exchange_flags = be32_to_cpup ( p + + ) ;
2009-04-01 17:22:29 +04:00
/* We ask for SP4_NONE */
2009-08-14 18:20:19 +04:00
dummy = be32_to_cpup ( p ) ;
2009-04-01 17:22:29 +04:00
if ( dummy ! = SP4_NONE )
return - EIO ;
/* Throw away minor_id */
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 8 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-04-01 17:22:29 +04:00
/* Throw away Major id */
2009-08-14 18:20:10 +04:00
status = decode_opaque_inline ( xdr , & dummy , & dummy_str ) ;
if ( unlikely ( status ) )
return status ;
2009-04-01 17:22:29 +04:00
/* Throw away server_scope */
2009-08-14 18:20:10 +04:00
status = decode_opaque_inline ( xdr , & dummy , & dummy_str ) ;
if ( unlikely ( status ) )
return status ;
2009-04-01 17:22:29 +04:00
/* Throw away Implementation id array */
2009-08-14 18:20:10 +04:00
status = decode_opaque_inline ( xdr , & dummy , & dummy_str ) ;
if ( unlikely ( status ) )
return status ;
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 ;
u32 nr_attrs ;
2009-08-14 18:20:14 +04:00
p = xdr_inline_decode ( xdr , 28 ) ;
if ( unlikely ( ! p ) )
goto out_overflow ;
2009-08-14 18:19:37 +04:00
attrs - > headerpadsz = be32_to_cpup ( p + + ) ;
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 ) ) {
printk ( KERN_WARNING " %s: Invalid rdma channel attrs count %u \n " ,
__func__ , nr_attrs ) ;
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
}
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
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)
2009-04-01 17:22:36 +04:00
struct nfs4_slot * slot ;
struct nfs4_sessionid id ;
u32 dummy ;
int status ;
__be32 * p ;
2009-04-01 17:22:11 +04:00
if ( ! res - > sr_session )
return 0 ;
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 ;
2009-04-01 17:22:36 +04:00
if ( memcmp ( id . data , res - > sr_session - > sess_id . data ,
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:20:00 +04:00
slot = & res - > sr_session - > fc_slot_table . slots [ res - > sr_slotid ] ;
2009-08-14 18:19:37 +04:00
dummy = be32_to_cpup ( p + + ) ;
2009-04-01 17:22:36 +04:00
if ( dummy ! = slot - > seq_nr ) {
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 + + ) ;
2009-04-01 17:22:36 +04:00
if ( dummy ! = res - > sr_slotid ) {
dprintk ( " %s Invalid slot id \n " , __func__ ) ;
goto out_err ;
}
/* highest slot id - currently not processed */
2009-08-14 18:19:37 +04:00
dummy = be32_to_cpup ( p + + ) ;
2009-04-01 17:22:36 +04:00
/* target highest slot id - currently not processed */
2009-08-14 18:19:37 +04:00
dummy = 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
}
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
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_open_downgrade ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_closeres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_open_downgrade ( & xdr , res ) ;
2005-10-28 06:12:41 +04:00
if ( status ! = 0 )
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
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
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_access ( struct rpc_rqst * rqstp , __be32 * p , struct nfs4_accessres * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
2009-04-01 17:22:11 +04:00
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2007-08-11 01:45:11 +04:00
status = decode_putfh ( & xdr ) ;
if ( status ! = 0 )
goto out ;
status = decode_access ( & xdr , res ) ;
if ( status ! = 0 )
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode LOOKUP response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_lookup ( struct rpc_rqst * rqstp , __be32 * p , struct nfs4_lookup_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
2009-04-01 17:22:11 +04:00
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
if ( ( status = decode_putfh ( & xdr ) ) ! = 0 )
goto out ;
if ( ( status = decode_lookup ( & xdr ) ) ! = 0 )
goto out ;
if ( ( status = decode_getfh ( & xdr , res - > fh ) ) ! = 0 )
goto out ;
2009-08-09 23:06:19 +04:00
status = decode_getfattr ( & xdr , res - > fattr , res - > server
, ! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode LOOKUP_ROOT response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_lookup_root ( struct rpc_rqst * rqstp , __be32 * p , struct nfs4_lookup_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
2009-04-01 17:22:11 +04:00
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
if ( ( status = decode_putrootfh ( & xdr ) ) ! = 0 )
goto out ;
if ( ( status = decode_getfh ( & xdr , res - > fh ) ) = = 0 )
2009-08-09 23:06:19 +04:00
status = decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode REMOVE response
*/
2007-07-14 23:39:57 +04:00
static int nfs4_xdr_dec_remove ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_removeres * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
2009-04-01 17:22:11 +04:00
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
2005-10-28 06:12:44 +04:00
if ( ( status = decode_putfh ( & xdr ) ) ! = 0 )
goto out ;
if ( ( status = decode_remove ( & xdr , & res - > cinfo ) ) ! = 0 )
goto out ;
2010-04-17 00:22:50 +04:00
decode_getfattr ( & xdr , res - > dir_attr , res - > server ,
2009-08-09 23:06:19 +04:00
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode RENAME response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_rename ( struct rpc_rqst * rqstp , __be32 * p , struct nfs4_rename_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
2009-04-01 17:22:11 +04:00
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
if ( ( status = decode_putfh ( & xdr ) ) ! = 0 )
goto out ;
if ( ( status = decode_savefh ( & xdr ) ) ! = 0 )
goto out ;
if ( ( status = decode_putfh ( & xdr ) ) ! = 0 )
goto out ;
2005-10-28 06:12:43 +04:00
if ( ( status = decode_rename ( & xdr , & res - > old_cinfo , & res - > new_cinfo ) ) ! = 0 )
goto out ;
/* Current FH is target directory */
2009-08-09 23:06:19 +04:00
if ( decode_getfattr ( & xdr , res - > new_fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ! = 0 )
2005-10-28 06:12:43 +04:00
goto out ;
if ( ( status = decode_restorefh ( & xdr ) ) ! = 0 )
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > old_fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode LINK response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_link ( struct rpc_rqst * rqstp , __be32 * p , struct nfs4_link_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
2009-04-01 17:22:11 +04:00
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
if ( ( status = decode_putfh ( & xdr ) ) ! = 0 )
goto out ;
if ( ( status = decode_savefh ( & xdr ) ) ! = 0 )
goto out ;
if ( ( status = decode_putfh ( & xdr ) ) ! = 0 )
goto out ;
2005-10-28 06:12:42 +04:00
if ( ( status = decode_link ( & xdr , & res - > cinfo ) ) ! = 0 )
goto out ;
/*
* Note order : OP_LINK leaves the directory as the current
* filehandle .
*/
2009-08-09 23:06:19 +04:00
if ( decode_getfattr ( & xdr , res - > dir_attr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ! = 0 )
2005-10-28 06:12:42 +04:00
goto out ;
if ( ( status = decode_restorefh ( & xdr ) ) ! = 0 )
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode CREATE response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_create ( struct rpc_rqst * rqstp , __be32 * p , struct nfs4_create_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
2009-04-01 17:22:11 +04:00
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
if ( ( status = decode_putfh ( & xdr ) ) ! = 0 )
goto out ;
2005-10-28 06:12:40 +04:00
if ( ( status = decode_savefh ( & xdr ) ) ! = 0 )
goto out ;
2005-04-17 02:20:36 +04:00
if ( ( status = decode_create ( & xdr , & res - > dir_cinfo ) ) ! = 0 )
goto out ;
if ( ( status = decode_getfh ( & xdr , res - > fh ) ) ! = 0 )
goto out ;
2009-08-09 23:06:19 +04:00
if ( decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ! = 0 )
2005-10-28 06:12:40 +04:00
goto out ;
if ( ( status = decode_restorefh ( & xdr ) ) ! = 0 )
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > dir_fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
/*
* Decode SYMLINK response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_symlink ( struct rpc_rqst * rqstp , __be32 * p , struct nfs4_create_res * res )
2005-04-17 02:20:36 +04:00
{
return nfs4_xdr_dec_create ( rqstp , p , res ) ;
}
/*
* Decode GETATTR response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_getattr ( struct rpc_rqst * rqstp , __be32 * p , struct nfs4_getattr_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
2008-12-24 00:06:15 +03:00
2005-04-17 02:20:36 +04:00
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
2009-08-09 23:06:19 +04:00
status = decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
2005-04-17 02:20:36 +04:00
out :
return status ;
}
2005-06-22 21:16:22 +04:00
/*
* Encode an SETACL request
*/
static int
2006-10-20 10:28:48 +04:00
nfs4_xdr_enc_setacl ( struct rpc_rqst * req , __be32 * p , struct nfs_setaclargs * args )
2005-06-22 21:16:22 +04:00
{
2008-12-24 00:06:15 +03:00
struct xdr_stream xdr ;
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
} ;
int status ;
xdr_init_encode ( & xdr , & req - > rq_snd_buf , p ) ;
2009-04-01 17:22:07 +04:00
encode_compound_hdr ( & xdr , req , & hdr ) ;
2009-04-01 17:22:11 +04:00
encode_sequence ( & xdr , & args - > seq_args , & hdr ) ;
2008-12-24 00:06:18 +03:00
encode_putfh ( & xdr , args - > fh , & hdr ) ;
2008-12-24 00:06:17 +03:00
status = encode_setacl ( & xdr , args , & hdr ) ;
encode_nops ( & hdr ) ;
2008-12-24 00:06:15 +03:00
return status ;
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
2009-04-01 17:22:01 +04:00
nfs4_xdr_dec_setacl ( struct rpc_rqst * rqstp , __be32 * p ,
struct nfs_setaclres * res )
2005-06-22 21:16:22 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-06-22 21:16:22 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
2009-04-01 17:22:00 +04: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
2009-04-01 17:21:59 +04:00
nfs4_xdr_dec_getacl ( struct rpc_rqst * rqstp , __be32 * p ,
struct nfs_getaclres * res )
2005-06-22 21:16:22 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-06-22 21:16:22 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
2009-04-01 17:21:59 +04:00
status = decode_getacl ( & xdr , rqstp , & res - > acl_len ) ;
2005-06-22 21:16:22 +04:00
out :
return status ;
}
2005-04-17 02:20:36 +04:00
/*
* Decode CLOSE response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_close ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_closeres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
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 .
*/
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
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
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_open ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_openres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_savefh ( & xdr ) ;
if ( status )
goto out ;
status = decode_open ( & xdr , res ) ;
2005-10-28 06:12:40 +04:00
if ( status )
goto out ;
2007-07-18 05:52:41 +04:00
if ( decode_getfh ( & xdr , & res - > fh ) ! = 0 )
2005-04-17 02:20:36 +04:00
goto out ;
2009-08-09 23:06:19 +04:00
if ( decode_getfattr ( & xdr , res - > f_attr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ! = 0 )
2005-10-28 06:12:40 +04:00
goto out ;
2007-07-18 05:52:37 +04:00
if ( decode_restorefh ( & xdr ) ! = 0 )
2005-10-28 06:12:40 +04:00
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > dir_attr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
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
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_open_confirm ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_open_confirmres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
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
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_open_noattr ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_openres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_open ( & xdr , res ) ;
if ( status )
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > f_attr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
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
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_setattr ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_setattrres * res )
2005-04-17 02:20:36 +04:00
{
2008-12-24 00:06:15 +03:00
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
2009-04-01 17:22:00 +04:00
status = decode_setattr ( & xdr ) ;
2008-12-24 00:06:15 +03:00
if ( status )
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
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
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_lock ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_lock_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_lock ( & xdr , res ) ;
out :
return status ;
}
/*
* Decode LOCKT response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_lockt ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_lockt_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_lockt ( & xdr , res ) ;
out :
return status ;
}
/*
* Decode LOCKU response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_locku ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_locku_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_locku ( & xdr , res ) ;
out :
return status ;
}
2010-07-01 20:49:01 +04:00
static int nfs4_xdr_dec_release_lockowner ( struct rpc_rqst * rqstp , __be32 * p , void * dummy )
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( ! status )
status = decode_release_lockowner ( & xdr ) ;
return status ;
}
2005-04-17 02:20:36 +04:00
/*
* Decode READLINK response
*/
2009-04-01 17:21:55 +04:00
static int nfs4_xdr_dec_readlink ( struct rpc_rqst * rqstp , __be32 * p ,
struct nfs4_readlink_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_readlink ( & xdr , rqstp ) ;
out :
return status ;
}
/*
* Decode READDIR response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_readdir ( struct rpc_rqst * rqstp , __be32 * p , struct nfs4_readdir_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_readdir ( & xdr , rqstp , res ) ;
out :
return status ;
}
/*
* Decode Read response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_read ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_readres * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_read ( & xdr , rqstp , res ) ;
if ( ! status )
status = res - > count ;
out :
return status ;
}
/*
* Decode WRITE response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_write ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_writeres * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_write ( & xdr , res ) ;
2005-10-28 06:12:44 +04:00
if ( status )
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
status = res - > count ;
out :
return status ;
}
/*
* Decode COMMIT response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_commit ( struct rpc_rqst * rqstp , __be32 * p , struct nfs_writeres * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
2005-04-17 02:20:36 +04:00
if ( status )
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status )
goto out ;
status = decode_commit ( & xdr , res ) ;
2005-10-28 06:12:44 +04:00
if ( status )
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
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
*/
2009-04-01 17:21:57 +04:00
static int nfs4_xdr_dec_fsinfo ( struct rpc_rqst * req , __be32 * p ,
struct nfs4_fsinfo_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & req - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( ! status )
status = decode_sequence ( & xdr , & res - > seq_res , req ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
status = decode_putfh ( & xdr ) ;
if ( ! status )
2009-04-01 17:21:57 +04: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
*/
2009-04-01 17:21:58 +04:00
static int nfs4_xdr_dec_pathconf ( struct rpc_rqst * req , __be32 * p ,
struct nfs4_pathconf_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & req - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( ! status )
status = decode_sequence ( & xdr , & res - > seq_res , req ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
status = decode_putfh ( & xdr ) ;
if ( ! status )
2009-04-01 17:21:58 +04: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
*/
2009-04-01 17:21:56 +04:00
static int nfs4_xdr_dec_statfs ( struct rpc_rqst * req , __be32 * p ,
struct nfs4_statfs_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & req - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( ! status )
status = decode_sequence ( & xdr , & res - > seq_res , req ) ;
2005-04-17 02:20:36 +04:00
if ( ! status )
status = decode_putfh ( & xdr ) ;
if ( ! status )
2009-04-01 17:21:56 +04: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
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_server_caps ( struct rpc_rqst * req , __be32 * p , struct nfs4_server_caps_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & req - > rq_rcv_buf , p ) ;
2009-04-01 17:22:11 +04:00
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , req ) ;
if ( status )
2005-04-17 02:20:36 +04:00
goto out ;
if ( ( status = decode_putfh ( & xdr ) ) ! = 0 )
goto out ;
status = decode_server_caps ( & xdr , res ) ;
out :
return status ;
}
/*
* Decode RENEW response
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_renew ( struct rpc_rqst * rqstp , __be32 * p , void * dummy )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( ! status )
status = decode_renew ( & xdr ) ;
return status ;
}
/*
2009-12-06 00:08:39 +03:00
* Decode SETCLIENTID response
2005-04-17 02:20:36 +04:00
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_setclientid ( struct rpc_rqst * req , __be32 * p ,
2010-04-17 00:43:06 +04:00
struct nfs4_setclientid_res * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & req - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( ! status )
2010-04-17 00:43:06 +04: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
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_setclientid_confirm ( struct rpc_rqst * req , __be32 * p , struct nfs_fsinfo * fsinfo )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & req - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( ! status )
status = decode_setclientid_confirm ( & xdr ) ;
if ( ! status )
status = decode_putrootfh ( & xdr ) ;
if ( ! status )
status = decode_fsinfo ( & xdr , fsinfo ) ;
return status ;
}
/*
2009-12-06 00:08:39 +03:00
* Decode DELEGRETURN response
2005-04-17 02:20:36 +04:00
*/
2006-10-20 10:28:48 +04:00
static int nfs4_xdr_dec_delegreturn ( struct rpc_rqst * rqstp , __be32 * p , struct nfs4_delegreturnres * res )
2005-04-17 02:20:36 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
if ( status )
2006-01-03 11:55:38 +03:00
goto out ;
status = decode_putfh ( & xdr ) ;
if ( status ! = 0 )
goto out ;
status = decode_delegreturn ( & xdr ) ;
2010-03-21 19:10:36 +03:00
if ( status ! = 0 )
goto out ;
2009-08-09 23:06:19 +04:00
decode_getfattr ( & xdr , res - > fattr , res - > server ,
! RPC_IS_ASYNC ( rqstp - > rq_task ) ) ;
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
*/
2009-04-01 17:22:02 +04:00
static int nfs4_xdr_dec_fs_locations ( struct rpc_rqst * req , __be32 * p ,
struct nfs4_fs_locations_res * res )
2006-06-09 17:34:22 +04:00
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & req - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
2009-04-01 17:22:11 +04:00
if ( status )
goto out ;
status = decode_sequence ( & xdr , & res - > seq_res , req ) ;
if ( status )
2006-06-09 17:34:22 +04:00
goto out ;
if ( ( status = decode_putfh ( & xdr ) ) ! = 0 )
goto out ;
if ( ( status = decode_lookup ( & xdr ) ) ! = 0 )
goto out ;
xdr_enter_page ( & xdr , PAGE_SIZE ) ;
2009-04-01 17:22:02 +04:00
status = decode_getfattr ( & xdr , & res - > fs_locations - > fattr ,
2009-08-09 23:06:19 +04:00
res - > fs_locations - > server ,
! RPC_IS_ASYNC ( req - > rq_task ) ) ;
2006-06-09 17:34:22 +04:00
out :
return status ;
}
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
/*
2009-12-06 00:08:39 +03:00
* Decode EXCHANGE_ID response
2009-04-01 17:22:29 +04:00
*/
static int nfs4_xdr_dec_exchange_id ( struct rpc_rqst * rqstp , uint32_t * p ,
void * res )
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( ! status )
status = decode_exchange_id ( & xdr , res ) ;
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
*/
static int nfs4_xdr_dec_create_session ( struct rpc_rqst * rqstp , uint32_t * p ,
struct nfs41_create_session_res * res )
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( ! status )
status = decode_create_session ( & xdr , res ) ;
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
*/
static int nfs4_xdr_dec_destroy_session ( struct rpc_rqst * rqstp , uint32_t * p ,
void * dummy )
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( ! status )
status = decode_destroy_session ( & xdr , dummy ) ;
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
*/
static int nfs4_xdr_dec_sequence ( struct rpc_rqst * rqstp , uint32_t * p ,
struct nfs4_sequence_res * res )
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( ! status )
status = decode_sequence ( & xdr , res , rqstp ) ;
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
*/
static int nfs4_xdr_dec_get_lease_time ( struct rpc_rqst * rqstp , uint32_t * p ,
struct nfs4_get_lease_time_res * res )
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( ! status )
status = decode_sequence ( & xdr , & res - > lr_seq_res , rqstp ) ;
if ( ! status )
status = decode_putrootfh ( & xdr ) ;
if ( ! status )
status = decode_fsinfo ( & xdr , res - > lr_fsinfo ) ;
return status ;
}
2009-12-06 00:08:40 +03:00
/*
* Decode RECLAIM_COMPLETE response
*/
static int nfs4_xdr_dec_reclaim_complete ( struct rpc_rqst * rqstp , uint32_t * p ,
struct nfs41_reclaim_complete_res * res )
{
struct xdr_stream xdr ;
struct compound_hdr hdr ;
int status ;
xdr_init_decode ( & xdr , & rqstp - > rq_rcv_buf , p ) ;
status = decode_compound_hdr ( & xdr , & hdr ) ;
if ( ! status )
status = decode_sequence ( & xdr , & res - > seq_res , rqstp ) ;
if ( ! status )
status = decode_reclaim_complete ( & xdr , ( void * ) NULL ) ;
return status ;
}
2009-04-01 17:22:29 +04:00
# endif /* CONFIG_NFS_V4_1 */
2006-10-20 10:28:49 +04:00
__be32 * nfs4_decode_dirent ( __be32 * p , struct nfs_entry * entry , int plus )
2005-04-17 02:20:36 +04:00
{
uint32_t bitmap [ 2 ] = { 0 } ;
uint32_t len ;
if ( ! * p + + ) {
if ( ! * p )
return ERR_PTR ( - EAGAIN ) ;
entry - > eof = 1 ;
return ERR_PTR ( - EBADCOOKIE ) ;
}
entry - > prev_cookie = entry - > cookie ;
p = xdr_decode_hyper ( p , & entry - > cookie ) ;
entry - > len = ntohl ( * p + + ) ;
entry - > name = ( const char * ) p ;
p + = XDR_QUADLEN ( entry - > len ) ;
/*
* 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 ;
len = ntohl ( * p + + ) ; /* bitmap length */
if ( len - - > 0 ) {
bitmap [ 0 ] = ntohl ( * p + + ) ;
if ( len - - > 0 ) {
bitmap [ 1 ] = ntohl ( * p + + ) ;
p + = len ;
}
}
len = XDR_QUADLEN ( ntohl ( * p + + ) ) ; /* attribute buffer length */
if ( len > 0 ) {
2005-06-22 21:16:39 +04:00
if ( bitmap [ 0 ] & FATTR4_WORD0_RDATTR_ERROR ) {
bitmap [ 0 ] & = ~ FATTR4_WORD0_RDATTR_ERROR ;
/* Ignore the return value of rdattr_error for now */
p + + ;
len - - ;
}
2005-04-17 02:20:36 +04:00
if ( bitmap [ 0 ] = = 0 & & bitmap [ 1 ] = = FATTR4_WORD1_MOUNTED_ON_FILEID )
xdr_decode_hyper ( p , & entry - > ino ) ;
else if ( bitmap [ 0 ] = = FATTR4_WORD0_FILEID )
xdr_decode_hyper ( p , & entry - > ino ) ;
p + = len ;
}
entry - > eof = ! p [ 0 ] & & p [ 1 ] ;
return p ;
}
/*
* 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_BADOWNER , - EINVAL } ,
{ NFS4ERR_BADNAME , - EINVAL } ,
{ 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 } ,
{ NFS4ERR_WRONGSEC , - EPERM } , /* FIXME: this needs
2005-04-17 02:20:36 +04:00
* to be handled by a
* middle - layer .
*/
2008-03-31 18:39:06 +04:00
{ - 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 , \
. p_encode = ( kxdrproc_t ) nfs4_xdr_ # # argtype , \
. p_decode = ( kxdrproc_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 [ ] = {
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 ) ,
2005-06-22 21:16:22 +04:00
PROC ( GETACL , enc_getacl , dec_getacl ) ,
2005-06-22 21:16:22 +04:00
PROC ( SETACL , enc_setacl , dec_setacl ) ,
2006-06-09 17:34:22 +04:00
PROC ( FS_LOCATIONS , enc_fs_locations , dec_fs_locations ) ,
2010-07-01 20:49:01 +04:00
PROC ( RELEASE_LOCKOWNER , enc_release_lockowner , dec_release_lockowner ) ,
2009-04-01 17:22:29 +04:00
# if defined(CONFIG_NFS_V4_1)
PROC ( EXCHANGE_ID , enc_exchange_id , dec_exchange_id ) ,
2009-04-01 17:22:31 +04:00
PROC ( CREATE_SESSION , enc_create_session , dec_create_session ) ,
2009-04-01 17:22:34 +04:00
PROC ( DESTROY_SESSION , enc_destroy_session , dec_destroy_session ) ,
2009-04-01 17:22:36 +04:00
PROC ( SEQUENCE , enc_sequence , dec_sequence ) ,
2009-04-01 17:22:30 +04:00
PROC ( GET_LEASE_TIME , enc_get_lease_time , dec_get_lease_time ) ,
2009-12-06 00:08:40 +03:00
PROC ( RECLAIM_COMPLETE , enc_reclaim_complete , dec_reclaim_complete ) ,
2009-04-01 17:22:29 +04:00
# endif /* CONFIG_NFS_V4_1 */
2005-04-17 02:20:36 +04:00
} ;
struct rpc_version nfs_version4 = {
. 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 :
*/