forked from mirrors/linux
		
	nfs4: add NFSv4 LOOKUPP handlers
This will be needed in order to implement the get_parent export op for nfsd. Signed-off-by: Jeff Layton <jeff.layton@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
		
							parent
							
								
									f174ff7a0a
								
							
						
					
					
						commit
						5b5faaf6df
					
				
					 5 changed files with 170 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -3805,6 +3805,54 @@ nfs4_proc_lookup_mountpoint(struct inode *dir, const struct qstr *name,
 | 
			
		|||
	return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _nfs4_proc_lookupp(struct inode *inode,
 | 
			
		||||
		struct nfs_fh *fhandle, struct nfs_fattr *fattr,
 | 
			
		||||
		struct nfs4_label *label)
 | 
			
		||||
{
 | 
			
		||||
	struct rpc_clnt *clnt = NFS_CLIENT(inode);
 | 
			
		||||
	struct nfs_server *server = NFS_SERVER(inode);
 | 
			
		||||
	int		       status;
 | 
			
		||||
	struct nfs4_lookupp_arg args = {
 | 
			
		||||
		.bitmask = server->attr_bitmask,
 | 
			
		||||
		.fh = NFS_FH(inode),
 | 
			
		||||
	};
 | 
			
		||||
	struct nfs4_lookupp_res res = {
 | 
			
		||||
		.server = server,
 | 
			
		||||
		.fattr = fattr,
 | 
			
		||||
		.label = label,
 | 
			
		||||
		.fh = fhandle,
 | 
			
		||||
	};
 | 
			
		||||
	struct rpc_message msg = {
 | 
			
		||||
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUPP],
 | 
			
		||||
		.rpc_argp = &args,
 | 
			
		||||
		.rpc_resp = &res,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	args.bitmask = nfs4_bitmask(server, label);
 | 
			
		||||
 | 
			
		||||
	nfs_fattr_init(fattr);
 | 
			
		||||
 | 
			
		||||
	dprintk("NFS call  lookupp ino=0x%lx\n", inode->i_ino);
 | 
			
		||||
	status = nfs4_call_sync(clnt, server, &msg, &args.seq_args,
 | 
			
		||||
				&res.seq_res, 0);
 | 
			
		||||
	dprintk("NFS reply lookupp: %d\n", status);
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
 | 
			
		||||
			     struct nfs_fattr *fattr, struct nfs4_label *label)
 | 
			
		||||
{
 | 
			
		||||
	struct nfs4_exception exception = { };
 | 
			
		||||
	int err;
 | 
			
		||||
	do {
 | 
			
		||||
		err = _nfs4_proc_lookupp(inode, fhandle, fattr, label);
 | 
			
		||||
		trace_nfs4_lookupp(inode, err);
 | 
			
		||||
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
 | 
			
		||||
				&exception);
 | 
			
		||||
	} while (exception.retry);
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 | 
			
		||||
{
 | 
			
		||||
	struct nfs_server *server = NFS_SERVER(inode);
 | 
			
		||||
| 
						 | 
				
			
			@ -9314,6 +9362,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
 | 
			
		|||
	.getattr	= nfs4_proc_getattr,
 | 
			
		||||
	.setattr	= nfs4_proc_setattr,
 | 
			
		||||
	.lookup		= nfs4_proc_lookup,
 | 
			
		||||
	.lookupp	= nfs4_proc_lookupp,
 | 
			
		||||
	.access		= nfs4_proc_access,
 | 
			
		||||
	.readlink	= nfs4_proc_readlink,
 | 
			
		||||
	.create		= nfs4_proc_create,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -891,6 +891,35 @@ DEFINE_NFS4_LOOKUP_EVENT(nfs4_remove);
 | 
			
		|||
DEFINE_NFS4_LOOKUP_EVENT(nfs4_get_fs_locations);
 | 
			
		||||
DEFINE_NFS4_LOOKUP_EVENT(nfs4_secinfo);
 | 
			
		||||
 | 
			
		||||
TRACE_EVENT(nfs4_lookupp,
 | 
			
		||||
		TP_PROTO(
 | 
			
		||||
			const struct inode *inode,
 | 
			
		||||
			int error
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		TP_ARGS(inode, error),
 | 
			
		||||
 | 
			
		||||
		TP_STRUCT__entry(
 | 
			
		||||
			__field(dev_t, dev)
 | 
			
		||||
			__field(u64, ino)
 | 
			
		||||
			__field(int, error)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		TP_fast_assign(
 | 
			
		||||
			__entry->dev = inode->i_sb->s_dev;
 | 
			
		||||
			__entry->ino = NFS_FILEID(inode);
 | 
			
		||||
			__entry->error = error;
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		TP_printk(
 | 
			
		||||
			"error=%d (%s) inode=%02x:%02x:%llu",
 | 
			
		||||
			__entry->error,
 | 
			
		||||
			show_nfsv4_errors(__entry->error),
 | 
			
		||||
			MAJOR(__entry->dev), MINOR(__entry->dev),
 | 
			
		||||
			(unsigned long long)__entry->ino
 | 
			
		||||
		)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
TRACE_EVENT(nfs4_rename,
 | 
			
		||||
		TP_PROTO(
 | 
			
		||||
			const struct inode *olddir,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -159,6 +159,8 @@ static int nfs4_stat_to_errno(int);
 | 
			
		|||
				(op_decode_hdr_maxsz)
 | 
			
		||||
#define encode_lookup_maxsz	(op_encode_hdr_maxsz + nfs4_name_maxsz)
 | 
			
		||||
#define decode_lookup_maxsz	(op_decode_hdr_maxsz)
 | 
			
		||||
#define encode_lookupp_maxsz	(op_encode_hdr_maxsz)
 | 
			
		||||
#define decode_lookupp_maxsz	(op_decode_hdr_maxsz)
 | 
			
		||||
#define encode_share_access_maxsz \
 | 
			
		||||
				(2)
 | 
			
		||||
#define encode_createmode_maxsz	(1 + encode_attrs_maxsz + encode_verifier_maxsz)
 | 
			
		||||
| 
						 | 
				
			
			@ -618,6 +620,18 @@ static int nfs4_stat_to_errno(int);
 | 
			
		|||
				decode_lookup_maxsz + \
 | 
			
		||||
				decode_getattr_maxsz + \
 | 
			
		||||
				decode_getfh_maxsz)
 | 
			
		||||
#define NFS4_enc_lookupp_sz	(compound_encode_hdr_maxsz + \
 | 
			
		||||
				encode_sequence_maxsz + \
 | 
			
		||||
				encode_putfh_maxsz + \
 | 
			
		||||
				encode_lookupp_maxsz + \
 | 
			
		||||
				encode_getattr_maxsz + \
 | 
			
		||||
				encode_getfh_maxsz)
 | 
			
		||||
#define NFS4_dec_lookupp_sz	(compound_decode_hdr_maxsz + \
 | 
			
		||||
				decode_sequence_maxsz + \
 | 
			
		||||
				decode_putfh_maxsz + \
 | 
			
		||||
				decode_lookupp_maxsz + \
 | 
			
		||||
				decode_getattr_maxsz + \
 | 
			
		||||
				decode_getfh_maxsz)
 | 
			
		||||
#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
 | 
			
		||||
				encode_sequence_maxsz + \
 | 
			
		||||
				encode_putrootfh_maxsz + \
 | 
			
		||||
| 
						 | 
				
			
			@ -1368,6 +1382,11 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc
 | 
			
		|||
	encode_string(xdr, name->len, name->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void encode_lookupp(struct xdr_stream *xdr, struct compound_hdr *hdr)
 | 
			
		||||
{
 | 
			
		||||
	encode_op_hdr(xdr, OP_LOOKUPP, decode_lookupp_maxsz, hdr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void encode_share_access(struct xdr_stream *xdr, u32 share_access)
 | 
			
		||||
{
 | 
			
		||||
	__be32 *p;
 | 
			
		||||
| 
						 | 
				
			
			@ -2122,6 +2141,26 @@ static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
			
		|||
	encode_nops(&hdr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Encode LOOKUPP request
 | 
			
		||||
 */
 | 
			
		||||
static void nfs4_xdr_enc_lookupp(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
			
		||||
		const void *data)
 | 
			
		||||
{
 | 
			
		||||
	const struct nfs4_lookupp_arg *args = data;
 | 
			
		||||
	struct compound_hdr hdr = {
 | 
			
		||||
		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	encode_compound_hdr(xdr, req, &hdr);
 | 
			
		||||
	encode_sequence(xdr, &args->seq_args, &hdr);
 | 
			
		||||
	encode_putfh(xdr, args->fh, &hdr);
 | 
			
		||||
	encode_lookupp(xdr, &hdr);
 | 
			
		||||
	encode_getfh(xdr, &hdr);
 | 
			
		||||
	encode_getfattr(xdr, args->bitmask, &hdr);
 | 
			
		||||
	encode_nops(&hdr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Encode LOOKUP_ROOT request
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -5058,6 +5097,11 @@ static int decode_lookup(struct xdr_stream *xdr)
 | 
			
		|||
	return decode_op_hdr(xdr, OP_LOOKUP);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int decode_lookupp(struct xdr_stream *xdr)
 | 
			
		||||
{
 | 
			
		||||
	return decode_op_hdr(xdr, OP_LOOKUPP);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is too sick! */
 | 
			
		||||
static int decode_space_limit(struct xdr_stream *xdr,
 | 
			
		||||
		unsigned long *pagemod_limit)
 | 
			
		||||
| 
						 | 
				
			
			@ -6237,6 +6281,36 @@ static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
 | 
			
		|||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Decode LOOKUPP response
 | 
			
		||||
 */
 | 
			
		||||
static int nfs4_xdr_dec_lookupp(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
 | 
			
		||||
		void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct nfs4_lookupp_res *res = data;
 | 
			
		||||
	struct compound_hdr hdr;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	status = decode_compound_hdr(xdr, &hdr);
 | 
			
		||||
	if (status)
 | 
			
		||||
		goto out;
 | 
			
		||||
	status = decode_sequence(xdr, &res->seq_res, rqstp);
 | 
			
		||||
	if (status)
 | 
			
		||||
		goto out;
 | 
			
		||||
	status = decode_putfh(xdr);
 | 
			
		||||
	if (status)
 | 
			
		||||
		goto out;
 | 
			
		||||
	status = decode_lookupp(xdr);
 | 
			
		||||
	if (status)
 | 
			
		||||
		goto out;
 | 
			
		||||
	status = decode_getfh(xdr, res->fh);
 | 
			
		||||
	if (status)
 | 
			
		||||
		goto out;
 | 
			
		||||
	status = decode_getfattr_label(xdr, res->fattr, res->label, res->server);
 | 
			
		||||
out:
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Decode LOOKUP_ROOT response
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -7614,6 +7688,7 @@ const struct rpc_procinfo nfs4_procedures[] = {
 | 
			
		|||
	PROC(ACCESS,		enc_access,		dec_access),
 | 
			
		||||
	PROC(GETATTR,		enc_getattr,		dec_getattr),
 | 
			
		||||
	PROC(LOOKUP,		enc_lookup,		dec_lookup),
 | 
			
		||||
	PROC(LOOKUPP,		enc_lookupp,		dec_lookupp),
 | 
			
		||||
	PROC(LOOKUP_ROOT,	enc_lookup_root,	dec_lookup_root),
 | 
			
		||||
	PROC(REMOVE,		enc_remove,		dec_remove),
 | 
			
		||||
	PROC(RENAME,		enc_rename,		dec_rename),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -479,6 +479,7 @@ enum {
 | 
			
		|||
	NFSPROC4_CLNT_ACCESS,
 | 
			
		||||
	NFSPROC4_CLNT_GETATTR,
 | 
			
		||||
	NFSPROC4_CLNT_LOOKUP,
 | 
			
		||||
	NFSPROC4_CLNT_LOOKUPP,
 | 
			
		||||
	NFSPROC4_CLNT_LOOKUP_ROOT,
 | 
			
		||||
	NFSPROC4_CLNT_REMOVE,
 | 
			
		||||
	NFSPROC4_CLNT_RENAME,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1012,7 +1012,6 @@ struct nfs4_link_res {
 | 
			
		|||
	struct nfs_fattr *		dir_attr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct nfs4_lookup_arg {
 | 
			
		||||
	struct nfs4_sequence_args	seq_args;
 | 
			
		||||
	const struct nfs_fh *		dir_fh;
 | 
			
		||||
| 
						 | 
				
			
			@ -1028,6 +1027,20 @@ struct nfs4_lookup_res {
 | 
			
		|||
	struct nfs4_label		*label;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct nfs4_lookupp_arg {
 | 
			
		||||
	struct nfs4_sequence_args	seq_args;
 | 
			
		||||
	const struct nfs_fh		*fh;
 | 
			
		||||
	const u32			*bitmask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct nfs4_lookupp_res {
 | 
			
		||||
	struct nfs4_sequence_res	seq_res;
 | 
			
		||||
	const struct nfs_server		*server;
 | 
			
		||||
	struct nfs_fattr		*fattr;
 | 
			
		||||
	struct nfs_fh			*fh;
 | 
			
		||||
	struct nfs4_label		*label;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct nfs4_lookup_root_arg {
 | 
			
		||||
	struct nfs4_sequence_args	seq_args;
 | 
			
		||||
	const u32 *			bitmask;
 | 
			
		||||
| 
						 | 
				
			
			@ -1569,6 +1582,8 @@ struct nfs_rpc_ops {
 | 
			
		|||
	int	(*lookup)  (struct inode *, const struct qstr *,
 | 
			
		||||
			    struct nfs_fh *, struct nfs_fattr *,
 | 
			
		||||
			    struct nfs4_label *);
 | 
			
		||||
	int	(*lookupp) (struct inode *, struct nfs_fh *,
 | 
			
		||||
			    struct nfs_fattr *, struct nfs4_label *);
 | 
			
		||||
	int	(*access)  (struct inode *, struct nfs_access_entry *);
 | 
			
		||||
	int	(*readlink)(struct inode *, struct page *, unsigned int,
 | 
			
		||||
			    unsigned int);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue