NFS client fixes for Linux 6.2
Highlights include: Bugfixes - 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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEESQctxSBg8JpV8KqEZwvnipYKAPIFAmO5s6MACgkQZwvnipYK APJ8PA//aVnu+DqLTxeGnyr4HNIcm0su4TetghQabAf0S8nk69Ly8W+N+xCRwwCR /PvSe8j51tXVInpYQKSOTjDl8/0mq8cybf6N9DzDS0A+hKQfdK8jvPLU0yj/aZ6u D8x17ve7RjzLgw9minltq4eTvVIHpqSh/vVUyQhnj2A8qQlWrboXiQnLQAp5KBbq 7NexvcajgfFHXm7S+edZ8NH5QZ20FNVskvzyrClp46DQLJcdNLHGJLp8tdeD31kE lsNBsLG0LxOFyBY28MbQptXalhBP8RRwYwxdSdIUnExzB7eKTLS6LgHuK9GV+EzL wSfRrnyM023momKmdFn3Fy/cRyeF1RwfQON+KAHo1cQ5fFiQS16p7lTELGkApyLc yOXGpAvaPJuuBJLM+Xi07ovhqpc7SjGmr7cjZslyasNtez60Le06oSihKnrgcKDx ZVh1pTc89O25GqGm161HaQJY9YU4XCtjxPv7rvdrlhO5Dkgxai293R5aXUFBz1dD tssv5a2DqIekrE29YaCi/RjIqkngCXHlwniFw/L3/aFRUyHqN9/MyxH5VeCRDI2T OJQRR056V1FXSBLH6Wuzs2Ixz2HnJCLR7LE0zAoPLm/RwW8CuNmEXu28jfU0Kcmt Hj5VyxYfnqEAGsUO0O2oNhOnxWY9OHvlvpb/9DWcke0ASpeScB4= =N6cT -----END PGP SIGNATURE----- Merge tag 'nfs-for-6.2-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs 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
This commit is contained in:
commit
9b43a525db
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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 *);
|
||||
|
@ -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 @@ out:
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user