Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+36 -3
+6 -1
fs/nfs/dir.c
··· 2957 2957 const struct cred *cred) 2958 2958 { 2959 2959 const struct task_struct *parent; 2960 + const struct cred *pcred; 2960 2961 u64 ret; 2961 2962 2962 2963 rcu_read_lock(); 2963 2964 for (;;) { 2964 2965 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) 2966 2968 break; 2967 2969 task = parent; 2968 2970 } ··· 3025 3023 * but do it without locking. 3026 3024 */ 3027 3025 struct nfs_inode *nfsi = NFS_I(inode); 3026 + u64 login_time = nfs_access_login_time(current, cred); 3028 3027 struct nfs_access_entry *cache; 3029 3028 int err = -ECHILD; 3030 3029 struct list_head *lh; ··· 3039 3036 access_cmp(cred, cache) != 0) 3040 3037 cache = NULL; 3041 3038 if (cache == NULL) 3039 + goto out; 3040 + if ((s64)(login_time - cache->timestamp) > 0) 3042 3041 goto out; 3043 3042 if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) 3044 3043 goto out;
+8
fs/nfs/filelayout/filelayout.c
··· 783 783 return &fl->generic_hdr; 784 784 } 785 785 786 + static bool 787 + filelayout_lseg_is_striped(const struct nfs4_filelayout_segment *flseg) 788 + { 789 + return flseg->num_fh > 1; 790 + } 791 + 786 792 /* 787 793 * filelayout_pg_test(). Called by nfs_can_coalesce_requests() 788 794 * ··· 809 803 size = pnfs_generic_pg_test(pgio, prev, req); 810 804 if (!size) 811 805 return 0; 806 + else if (!filelayout_lseg_is_striped(FILELAYOUT_LSEG(pgio->pg_lseg))) 807 + return size; 812 808 813 809 /* see if req and prev are in the same stripe */ 814 810 if (prev) {
+5
include/linux/sunrpc/rpc_pipe_fs.h
··· 92 92 char __user *, size_t); 93 93 extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *); 94 94 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 + 95 100 struct rpc_clnt; 96 101 extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *); 97 102 extern int rpc_remove_client_dir(struct rpc_clnt *);
+17 -2
net/sunrpc/auth_gss/auth_gss.c
··· 302 302 list_for_each_entry(pos, &pipe->in_downcall, list) { 303 303 if (!uid_eq(pos->uid, uid)) 304 304 continue; 305 - if (auth && pos->auth->service != auth->service) 305 + if (pos->auth->service != auth->service) 306 306 continue; 307 307 refcount_inc(&pos->count); 308 308 return pos; ··· 686 686 return err; 687 687 } 688 688 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 + 689 704 #define MSG_BUF_MAXSIZE 1024 690 705 691 706 static ssize_t ··· 747 732 err = -ENOENT; 748 733 /* Find a matching upcall */ 749 734 spin_lock(&pipe->lock); 750 - gss_msg = __gss_find_upcall(pipe, uid, NULL); 735 + gss_msg = gss_find_downcall(pipe, uid); 751 736 if (gss_msg == NULL) { 752 737 spin_unlock(&pipe->lock); 753 738 goto err_put_ctx;