Commit 9b43a525 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS client fixes from Trond Myklebust:

 - Fix a race in the RPCSEC_GSS upcall code that causes hung RPC calls

 - Fix a broken coalescing test in the pNFS file layout driver

 - Ensure that the access cache rcu path also applies the login test

 - Fix up for a sparse warning

* tag 'nfs-for-6.2-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  NFS: Fix up a sparse warning
  NFS: Judge the file access cache's timestamp in rcu path
  pNFS/filelayout: Fix coalescing test for single DS
  SUNRPC: ensure the matching upcall is in-flight upon downcall
parents f18fca98 5e9a7b9c
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -2957,12 +2957,14 @@ static u64 nfs_access_login_time(const struct task_struct *task,
				 const struct cred *cred)
{
	const struct task_struct *parent;
	const struct cred *pcred;
	u64 ret;

	rcu_read_lock();
	for (;;) {
		parent = rcu_dereference(task->real_parent);
		if (parent == task || cred_fscmp(parent->cred, cred) != 0)
		pcred = rcu_dereference(parent->cred);
		if (parent == task || cred_fscmp(pcred, cred) != 0)
			break;
		task = parent;
	}
@@ -3023,6 +3025,7 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre
	 * but do it without locking.
	 */
	struct nfs_inode *nfsi = NFS_I(inode);
	u64 login_time = nfs_access_login_time(current, cred);
	struct nfs_access_entry *cache;
	int err = -ECHILD;
	struct list_head *lh;
@@ -3037,6 +3040,8 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre
		cache = NULL;
	if (cache == NULL)
		goto out;
	if ((s64)(login_time - cache->timestamp) > 0)
		goto out;
	if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS))
		goto out;
	*mask = cache->mask;
+8 −0
Original line number Diff line number Diff line
@@ -783,6 +783,12 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
	return &fl->generic_hdr;
}

static bool
filelayout_lseg_is_striped(const struct nfs4_filelayout_segment *flseg)
{
	return flseg->num_fh > 1;
}

/*
 * filelayout_pg_test(). Called by nfs_can_coalesce_requests()
 *
@@ -803,6 +809,8 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
	size = pnfs_generic_pg_test(pgio, prev, req);
	if (!size)
		return 0;
	else if (!filelayout_lseg_is_striped(FILELAYOUT_LSEG(pgio->pg_lseg)))
		return size;

	/* see if req and prev are in the same stripe */
	if (prev) {
+5 −0
Original line number Diff line number Diff line
@@ -92,6 +92,11 @@ extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *,
				       char __user *, size_t);
extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *);

/* returns true if the msg is in-flight, i.e., already eaten by the peer */
static inline bool rpc_msg_is_inflight(const struct rpc_pipe_msg *msg) {
	return (msg->copied != 0 && list_empty(&msg->list));
}

struct rpc_clnt;
extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *);
extern int rpc_remove_client_dir(struct rpc_clnt *);
+17 −2
Original line number Diff line number Diff line
@@ -302,7 +302,7 @@ __gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth
	list_for_each_entry(pos, &pipe->in_downcall, list) {
		if (!uid_eq(pos->uid, uid))
			continue;
		if (auth && pos->auth->service != auth->service)
		if (pos->auth->service != auth->service)
			continue;
		refcount_inc(&pos->count);
		return pos;
@@ -686,6 +686,21 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
	return err;
}

static struct gss_upcall_msg *
gss_find_downcall(struct rpc_pipe *pipe, kuid_t uid)
{
	struct gss_upcall_msg *pos;
	list_for_each_entry(pos, &pipe->in_downcall, list) {
		if (!uid_eq(pos->uid, uid))
			continue;
		if (!rpc_msg_is_inflight(&pos->msg))
			continue;
		refcount_inc(&pos->count);
		return pos;
	}
	return NULL;
}

#define MSG_BUF_MAXSIZE 1024

static ssize_t
@@ -732,7 +747,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
	err = -ENOENT;
	/* Find a matching upcall */
	spin_lock(&pipe->lock);
	gss_msg = __gss_find_upcall(pipe, uid, NULL);
	gss_msg = gss_find_downcall(pipe, uid);
	if (gss_msg == NULL) {
		spin_unlock(&pipe->lock);
		goto err_put_ctx;