Commit 7a6b6044 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS server updates from Chuck Lever:
 "Highlights:
   - Support for user extended attributes on NFS (RFC 8276)
   - Further reduce unnecessary NFSv4 delegation recalls

  Notable fixes:
   - Fix recent krb5p regression
   - Address a few resource leaks and a rare NULL dereference

  Other:
   - De-duplicate RPC/RDMA error handling and other utility functions
   - Replace storage and display of kernel memory addresses by tracepoints"

* tag 'nfsd-5.9' of git://git.linux-nfs.org/projects/cel/cel-2.6: (38 commits)
  svcrdma: CM event handler clean up
  svcrdma: Remove transport reference counting
  svcrdma: Fix another Receive buffer leak
  SUNRPC: Refresh the show_rqstp_flags() macro
  nfsd: netns.h: delete a duplicated word
  SUNRPC: Fix ("SUNRPC: Add "@len" parameter to gss_unwrap()")
  nfsd: avoid a NULL dereference in __cld_pipe_upcall()
  nfsd4: a client's own opens needn't prevent delegations
  nfsd: Use seq_putc() in two functions
  svcrdma: Display chunk completion ID when posting a rw_ctxt
  svcrdma: Record send_ctxt completion ID in trace_svcrdma_post_send()
  svcrdma: Introduce Send completion IDs
  svcrdma: Record Receive completion ID in svc_rdma_decode_rqst
  svcrdma: Introduce Receive completion IDs
  svcrdma: Introduce infrastructure to support completion IDs
  svcrdma: Add common XDR encoders for RDMA and Read segments
  svcrdma: Add common XDR decoders for RDMA and Read segments
  SUNRPC: Add helpers for decoding list discriminators symbolically
  svcrdma: Remove declarations for functions long removed
  svcrdma: Clean up trace_svcrdma_send_failed() tracepoint
  ...
parents 8d3e09b4 b297fed6
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1808,6 +1808,9 @@ check_conflicting_open(struct file *filp, const long arg, int flags)

	if (flags & FL_LAYOUT)
		return 0;
	if (flags & FL_DELEG)
		/* We leave these checks to the caller. */
		return 0;

	if (arg == F_RDLCK)
		return inode_is_open_for_write(inode) ? -EAGAIN : 0;
+1 −1
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ struct nfsd_net {
	unsigned int             longest_chain_cachesize;

	struct shrinker		nfsd_reply_cache_shrinker;
	/* utsname taken from the the process that starts the server */
	/* utsname taken from the process that starts the server */
	char			nfsd_name[UNX_MAXNODENAME+1];
};

+2 −2
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@ idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
			ent->id);
	if (test_bit(CACHE_VALID, &h->flags))
		seq_printf(m, " %s", ent->name);
	seq_printf(m, "\n");
	seq_putc(m, '\n');
	return 0;
}

@@ -346,7 +346,7 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
			ent->name);
	if (test_bit(CACHE_VALID, &h->flags))
		seq_printf(m, " %u", ent->id);
	seq_printf(m, "\n");
	seq_putc(m, '\n');
	return 0;
}

+127 −1
Original line number Diff line number Diff line
@@ -566,8 +566,14 @@ nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	     union nfsd4_op_u *u)
{
	struct nfsd4_access *access = &u->access;
	u32 access_full;

	if (access->ac_req_access & ~NFS3_ACCESS_FULL)
	access_full = NFS3_ACCESS_FULL;
	if (cstate->minorversion >= 2)
		access_full |= NFS4_ACCESS_XALIST | NFS4_ACCESS_XAREAD |
			       NFS4_ACCESS_XAWRITE;

	if (access->ac_req_access & ~access_full)
		return nfserr_inval;

	access->ac_resp_access = access->ac_req_access;
@@ -2091,6 +2097,68 @@ out:
}
#endif /* CONFIG_NFSD_PNFS */

static __be32
nfsd4_getxattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	       union nfsd4_op_u *u)
{
	struct nfsd4_getxattr *getxattr = &u->getxattr;

	return nfsd_getxattr(rqstp, &cstate->current_fh,
			     getxattr->getxa_name, &getxattr->getxa_buf,
			     &getxattr->getxa_len);
}

static __be32
nfsd4_setxattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	   union nfsd4_op_u *u)
{
	struct nfsd4_setxattr *setxattr = &u->setxattr;
	__be32 ret;

	if (opens_in_grace(SVC_NET(rqstp)))
		return nfserr_grace;

	ret = nfsd_setxattr(rqstp, &cstate->current_fh, setxattr->setxa_name,
			    setxattr->setxa_buf, setxattr->setxa_len,
			    setxattr->setxa_flags);

	if (!ret)
		set_change_info(&setxattr->setxa_cinfo, &cstate->current_fh);

	return ret;
}

static __be32
nfsd4_listxattrs(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	   union nfsd4_op_u *u)
{
	/*
	 * Get the entire list, then copy out only the user attributes
	 * in the encode function.
	 */
	return nfsd_listxattr(rqstp, &cstate->current_fh,
			     &u->listxattrs.lsxa_buf, &u->listxattrs.lsxa_len);
}

static __be32
nfsd4_removexattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	   union nfsd4_op_u *u)
{
	struct nfsd4_removexattr *removexattr = &u->removexattr;
	__be32 ret;

	if (opens_in_grace(SVC_NET(rqstp)))
		return nfserr_grace;

	ret = nfsd_removexattr(rqstp, &cstate->current_fh,
	    removexattr->rmxa_name);

	if (!ret)
		set_change_info(&removexattr->rmxa_cinfo, &cstate->current_fh);

	return ret;
}

/*
 * NULL call.
 */
@@ -2700,6 +2768,42 @@ static inline u32 nfsd4_seek_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
	return (op_encode_hdr_size + 3) * sizeof(__be32);
}

static inline u32 nfsd4_getxattr_rsize(struct svc_rqst *rqstp,
				       struct nfsd4_op *op)
{
	u32 maxcount, rlen;

	maxcount = svc_max_payload(rqstp);
	rlen = min_t(u32, XATTR_SIZE_MAX, maxcount);

	return (op_encode_hdr_size + 1 + XDR_QUADLEN(rlen)) * sizeof(__be32);
}

static inline u32 nfsd4_setxattr_rsize(struct svc_rqst *rqstp,
				       struct nfsd4_op *op)
{
	return (op_encode_hdr_size + op_encode_change_info_maxsz)
		* sizeof(__be32);
}
static inline u32 nfsd4_listxattrs_rsize(struct svc_rqst *rqstp,
					 struct nfsd4_op *op)
{
	u32 maxcount, rlen;

	maxcount = svc_max_payload(rqstp);
	rlen = min(op->u.listxattrs.lsxa_maxcount, maxcount);

	return (op_encode_hdr_size + 4 + XDR_QUADLEN(rlen)) * sizeof(__be32);
}

static inline u32 nfsd4_removexattr_rsize(struct svc_rqst *rqstp,
					  struct nfsd4_op *op)
{
	return (op_encode_hdr_size + op_encode_change_info_maxsz)
		* sizeof(__be32);
}


static const struct nfsd4_operation nfsd4_ops[] = {
	[OP_ACCESS] = {
		.op_func = nfsd4_access,
@@ -3081,6 +3185,28 @@ static const struct nfsd4_operation nfsd4_ops[] = {
		.op_name = "OP_COPY_NOTIFY",
		.op_rsize_bop = nfsd4_copy_notify_rsize,
	},
	[OP_GETXATTR] = {
		.op_func = nfsd4_getxattr,
		.op_name = "OP_GETXATTR",
		.op_rsize_bop = nfsd4_getxattr_rsize,
	},
	[OP_SETXATTR] = {
		.op_func = nfsd4_setxattr,
		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
		.op_name = "OP_SETXATTR",
		.op_rsize_bop = nfsd4_setxattr_rsize,
	},
	[OP_LISTXATTRS] = {
		.op_func = nfsd4_listxattrs,
		.op_name = "OP_LISTXATTRS",
		.op_rsize_bop = nfsd4_listxattrs_rsize,
	},
	[OP_REMOVEXATTR] = {
		.op_func = nfsd4_removexattr,
		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
		.op_name = "OP_REMOVEXATTR",
		.op_rsize_bop = nfsd4_removexattr_rsize,
	},
};

/**
+11 −13
Original line number Diff line number Diff line
@@ -747,13 +747,11 @@ struct cld_upcall {
};

static int
__cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
__cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
{
	int ret;
	struct rpc_pipe_msg msg;
	struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_u);
	struct nfsd_net *nn = net_generic(pipe->dentry->d_sb->s_fs_info,
					  nfsd_net_id);

	memset(&msg, 0, sizeof(msg));
	msg.data = cmsg;
@@ -773,7 +771,7 @@ out:
}

static int
cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
{
	int ret;

@@ -782,7 +780,7 @@ cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
	 *  upcalls queued.
	 */
	do {
		ret = __cld_pipe_upcall(pipe, cmsg);
		ret = __cld_pipe_upcall(pipe, cmsg, nn);
	} while (ret == -EAGAIN);

	return ret;
@@ -1115,7 +1113,7 @@ nfsd4_cld_create(struct nfs4_client *clp)
	memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
			clp->cl_name.len);

	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
	if (!ret) {
		ret = cup->cu_u.cu_msg.cm_status;
		set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -1180,7 +1178,7 @@ nfsd4_cld_create_v2(struct nfs4_client *clp)
	} else
		cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = 0;

	ret = cld_pipe_upcall(cn->cn_pipe, cmsg);
	ret = cld_pipe_upcall(cn->cn_pipe, cmsg, nn);
	if (!ret) {
		ret = cmsg->cm_status;
		set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -1218,7 +1216,7 @@ nfsd4_cld_remove(struct nfs4_client *clp)
	memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
			clp->cl_name.len);

	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
	if (!ret) {
		ret = cup->cu_u.cu_msg.cm_status;
		clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -1261,7 +1259,7 @@ nfsd4_cld_check_v0(struct nfs4_client *clp)
	memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
			clp->cl_name.len);

	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
	if (!ret) {
		ret = cup->cu_u.cu_msg.cm_status;
		set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -1404,7 +1402,7 @@ nfsd4_cld_grace_start(struct nfsd_net *nn)
	}

	cup->cu_u.cu_msg.cm_cmd = Cld_GraceStart;
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
	if (!ret)
		ret = cup->cu_u.cu_msg.cm_status;

@@ -1432,7 +1430,7 @@ nfsd4_cld_grace_done_v0(struct nfsd_net *nn)

	cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
	cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time;
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
	if (!ret)
		ret = cup->cu_u.cu_msg.cm_status;

@@ -1460,7 +1458,7 @@ nfsd4_cld_grace_done(struct nfsd_net *nn)
	}

	cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
	if (!ret)
		ret = cup->cu_u.cu_msg.cm_status;

@@ -1524,7 +1522,7 @@ nfsd4_cld_get_version(struct nfsd_net *nn)
		goto out_err;
	}
	cup->cu_u.cu_msg.cm_cmd = Cld_GetVersion;
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
	if (!ret) {
		ret = cup->cu_u.cu_msg.cm_status;
		if (ret)
Loading