Skip to content

Commit 9b43a52

Browse files
committed
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
2 parents f18fca9 + 5e9a7b9 commit 9b43a52

File tree

4 files changed

+36
-3
lines changed

4 files changed

+36
-3
lines changed

fs/nfs/dir.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2957,12 +2957,14 @@ static u64 nfs_access_login_time(const struct task_struct *task,
29572957
const struct cred *cred)
29582958
{
29592959
const struct task_struct *parent;
2960+
const struct cred *pcred;
29602961
u64 ret;
29612962

29622963
rcu_read_lock();
29632964
for (;;) {
29642965
parent = rcu_dereference(task->real_parent);
2965-
if (parent == task || cred_fscmp(parent->cred, cred) != 0)
2966+
pcred = rcu_dereference(parent->cred);
2967+
if (parent == task || cred_fscmp(pcred, cred) != 0)
29662968
break;
29672969
task = parent;
29682970
}
@@ -3023,6 +3025,7 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre
30233025
* but do it without locking.
30243026
*/
30253027
struct nfs_inode *nfsi = NFS_I(inode);
3028+
u64 login_time = nfs_access_login_time(current, cred);
30263029
struct nfs_access_entry *cache;
30273030
int err = -ECHILD;
30283031
struct list_head *lh;
@@ -3037,6 +3040,8 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre
30373040
cache = NULL;
30383041
if (cache == NULL)
30393042
goto out;
3043+
if ((s64)(login_time - cache->timestamp) > 0)
3044+
goto out;
30403045
if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS))
30413046
goto out;
30423047
*mask = cache->mask;

fs/nfs/filelayout/filelayout.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,12 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
783783
return &fl->generic_hdr;
784784
}
785785

786+
static bool
787+
filelayout_lseg_is_striped(const struct nfs4_filelayout_segment *flseg)
788+
{
789+
return flseg->num_fh > 1;
790+
}
791+
786792
/*
787793
* filelayout_pg_test(). Called by nfs_can_coalesce_requests()
788794
*
@@ -803,6 +809,8 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
803809
size = pnfs_generic_pg_test(pgio, prev, req);
804810
if (!size)
805811
return 0;
812+
else if (!filelayout_lseg_is_striped(FILELAYOUT_LSEG(pgio->pg_lseg)))
813+
return size;
806814

807815
/* see if req and prev are in the same stripe */
808816
if (prev) {

include/linux/sunrpc/rpc_pipe_fs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *,
9292
char __user *, size_t);
9393
extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *);
9494

95+
/* returns true if the msg is in-flight, i.e., already eaten by the peer */
96+
static inline bool rpc_msg_is_inflight(const struct rpc_pipe_msg *msg) {
97+
return (msg->copied != 0 && list_empty(&msg->list));
98+
}
99+
95100
struct rpc_clnt;
96101
extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *);
97102
extern int rpc_remove_client_dir(struct rpc_clnt *);

net/sunrpc/auth_gss/auth_gss.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ __gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth
302302
list_for_each_entry(pos, &pipe->in_downcall, list) {
303303
if (!uid_eq(pos->uid, uid))
304304
continue;
305-
if (auth && pos->auth->service != auth->service)
305+
if (pos->auth->service != auth->service)
306306
continue;
307307
refcount_inc(&pos->count);
308308
return pos;
@@ -686,6 +686,21 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
686686
return err;
687687
}
688688

689+
static struct gss_upcall_msg *
690+
gss_find_downcall(struct rpc_pipe *pipe, kuid_t uid)
691+
{
692+
struct gss_upcall_msg *pos;
693+
list_for_each_entry(pos, &pipe->in_downcall, list) {
694+
if (!uid_eq(pos->uid, uid))
695+
continue;
696+
if (!rpc_msg_is_inflight(&pos->msg))
697+
continue;
698+
refcount_inc(&pos->count);
699+
return pos;
700+
}
701+
return NULL;
702+
}
703+
689704
#define MSG_BUF_MAXSIZE 1024
690705

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

0 commit comments

Comments
 (0)