Skip to content

Commit ff7afae

Browse files
committed
Merge tag 'nfs-for-6.12-3' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS client fixes from Anna Schumaker: "These are mostly fixes that came up during the nfs bakeathon the other week. Stable Fixes: - Fix KMSAN warning in decode_getfattr_attrs() Other Bugfixes: - Handle -ENOTCONN in xs_tcp_setup_socked() - NFSv3: only use NFS timeout for MOUNT when protocols are compatible - Fix attribute delegation behavior on exclusive create and a/mtime changes - Fix localio to cope with racing nfs_local_probe() - Avoid i_lock contention in fs_clear_invalid_mapping()" * tag 'nfs-for-6.12-3' of git://git.linux-nfs.org/projects/anna/linux-nfs: nfs: avoid i_lock contention in nfs_clear_invalid_mapping nfs_common: fix localio to cope with racing nfs_local_probe() NFS: Further fixes to attribute delegation a/mtime changes NFS: Fix attribute delegation behaviour on exclusive create nfs: Fix KMSAN warning in decode_getfattr_attrs() NFSv3: only use NFS timeout for MOUNT when protocols are compatible sunrpc: handle -ENOTCONN in xs_tcp_setup_socket()
2 parents f43b156 + 867da60 commit ff7afae

File tree

8 files changed

+84
-33
lines changed

8 files changed

+84
-33
lines changed

fs/nfs/client.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
181181
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
182182
seqlock_init(&clp->cl_boot_lock);
183183
ktime_get_real_ts64(&clp->cl_nfssvc_boot);
184-
clp->cl_uuid.net = NULL;
185-
clp->cl_uuid.dom = NULL;
184+
nfs_uuid_init(&clp->cl_uuid);
186185
spin_lock_init(&clp->cl_localio_lock);
187186
#endif /* CONFIG_NFS_LOCALIO */
188187

fs/nfs/inode.c

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,15 @@ void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
205205
nfs_fscache_invalidate(inode, 0);
206206
flags &= ~NFS_INO_REVAL_FORCED;
207207

208-
nfsi->cache_validity |= flags;
208+
flags |= nfsi->cache_validity;
209+
if (inode->i_mapping->nrpages == 0)
210+
flags &= ~NFS_INO_INVALID_DATA;
209211

210-
if (inode->i_mapping->nrpages == 0) {
211-
nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
212-
nfs_ooo_clear(nfsi);
213-
} else if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
212+
/* pairs with nfs_clear_invalid_mapping()'s smp_load_acquire() */
213+
smp_store_release(&nfsi->cache_validity, flags);
214+
215+
if (inode->i_mapping->nrpages == 0 ||
216+
nfsi->cache_validity & NFS_INO_INVALID_DATA) {
214217
nfs_ooo_clear(nfsi);
215218
}
216219
trace_nfs_set_cache_invalid(inode, 0);
@@ -628,23 +631,35 @@ nfs_fattr_fixup_delegated(struct inode *inode, struct nfs_fattr *fattr)
628631
}
629632
}
630633

634+
static void nfs_update_timestamps(struct inode *inode, unsigned int ia_valid)
635+
{
636+
enum file_time_flags time_flags = 0;
637+
unsigned int cache_flags = 0;
638+
639+
if (ia_valid & ATTR_MTIME) {
640+
time_flags |= S_MTIME | S_CTIME;
641+
cache_flags |= NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME;
642+
}
643+
if (ia_valid & ATTR_ATIME) {
644+
time_flags |= S_ATIME;
645+
cache_flags |= NFS_INO_INVALID_ATIME;
646+
}
647+
inode_update_timestamps(inode, time_flags);
648+
NFS_I(inode)->cache_validity &= ~cache_flags;
649+
}
650+
631651
void nfs_update_delegated_atime(struct inode *inode)
632652
{
633653
spin_lock(&inode->i_lock);
634-
if (nfs_have_delegated_atime(inode)) {
635-
inode_update_timestamps(inode, S_ATIME);
636-
NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ATIME;
637-
}
654+
if (nfs_have_delegated_atime(inode))
655+
nfs_update_timestamps(inode, ATTR_ATIME);
638656
spin_unlock(&inode->i_lock);
639657
}
640658

641659
void nfs_update_delegated_mtime_locked(struct inode *inode)
642660
{
643-
if (nfs_have_delegated_mtime(inode)) {
644-
inode_update_timestamps(inode, S_CTIME | S_MTIME);
645-
NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_CTIME |
646-
NFS_INO_INVALID_MTIME);
647-
}
661+
if (nfs_have_delegated_mtime(inode))
662+
nfs_update_timestamps(inode, ATTR_MTIME);
648663
}
649664

650665
void nfs_update_delegated_mtime(struct inode *inode)
@@ -682,15 +697,16 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
682697
attr->ia_valid &= ~ATTR_SIZE;
683698
}
684699

685-
if (nfs_have_delegated_mtime(inode)) {
686-
if (attr->ia_valid & ATTR_MTIME) {
687-
nfs_update_delegated_mtime(inode);
688-
attr->ia_valid &= ~ATTR_MTIME;
689-
}
690-
if (attr->ia_valid & ATTR_ATIME) {
691-
nfs_update_delegated_atime(inode);
692-
attr->ia_valid &= ~ATTR_ATIME;
693-
}
700+
if (nfs_have_delegated_mtime(inode) && attr->ia_valid & ATTR_MTIME) {
701+
spin_lock(&inode->i_lock);
702+
nfs_update_timestamps(inode, attr->ia_valid);
703+
spin_unlock(&inode->i_lock);
704+
attr->ia_valid &= ~(ATTR_MTIME | ATTR_ATIME);
705+
} else if (nfs_have_delegated_atime(inode) &&
706+
attr->ia_valid & ATTR_ATIME &&
707+
!(attr->ia_valid & ATTR_MTIME)) {
708+
nfs_update_delegated_atime(inode);
709+
attr->ia_valid &= ~ATTR_ATIME;
694710
}
695711

696712
/* Optimization: if the end result is no change, don't RPC */
@@ -1408,6 +1424,13 @@ int nfs_clear_invalid_mapping(struct address_space *mapping)
14081424
TASK_KILLABLE|TASK_FREEZABLE_UNSAFE);
14091425
if (ret)
14101426
goto out;
1427+
smp_rmb(); /* pairs with smp_wmb() below */
1428+
if (test_bit(NFS_INO_INVALIDATING, bitlock))
1429+
continue;
1430+
/* pairs with nfs_set_cache_invalid()'s smp_store_release() */
1431+
if (!(smp_load_acquire(&nfsi->cache_validity) & NFS_INO_INVALID_DATA))
1432+
goto out;
1433+
/* Slow-path that double-checks with spinlock held */
14111434
spin_lock(&inode->i_lock);
14121435
if (test_bit(NFS_INO_INVALIDATING, bitlock)) {
14131436
spin_unlock(&inode->i_lock);
@@ -1633,6 +1656,7 @@ void nfs_fattr_init(struct nfs_fattr *fattr)
16331656
fattr->gencount = nfs_inc_attr_generation_counter();
16341657
fattr->owner_name = NULL;
16351658
fattr->group_name = NULL;
1659+
fattr->mdsthreshold = NULL;
16361660
}
16371661
EXPORT_SYMBOL_GPL(nfs_fattr_init);
16381662

fs/nfs/localio.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ void nfs_local_probe(struct nfs_client *clp)
205205
nfs_local_disable(clp);
206206
}
207207

208-
nfs_uuid_begin(&clp->cl_uuid);
208+
if (!nfs_uuid_begin(&clp->cl_uuid))
209+
return;
209210
if (nfs_server_uuid_is_local(clp))
210211
nfs_local_enable(clp);
211212
nfs_uuid_end(&clp->cl_uuid);

fs/nfs/nfs4proc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3452,6 +3452,10 @@ static int nfs4_do_setattr(struct inode *inode, const struct cred *cred,
34523452
adjust_flags |= NFS_INO_INVALID_MODE;
34533453
if (sattr->ia_valid & (ATTR_UID | ATTR_GID))
34543454
adjust_flags |= NFS_INO_INVALID_OTHER;
3455+
if (sattr->ia_valid & ATTR_ATIME)
3456+
adjust_flags |= NFS_INO_INVALID_ATIME;
3457+
if (sattr->ia_valid & ATTR_MTIME)
3458+
adjust_flags |= NFS_INO_INVALID_MTIME;
34553459

34563460
do {
34573461
nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, fattr->label),

fs/nfs/super.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,15 @@ static int nfs_request_mount(struct fs_context *fc,
885885
* Now ask the mount server to map our export path
886886
* to a file handle.
887887
*/
888-
status = nfs_mount(&request, ctx->timeo, ctx->retrans);
888+
if ((request.protocol == XPRT_TRANSPORT_UDP) ==
889+
!(ctx->flags & NFS_MOUNT_TCP))
890+
/*
891+
* NFS protocol and mount protocol are both UDP or neither UDP
892+
* so timeouts are compatible. Use NFS timeouts for MOUNT
893+
*/
894+
status = nfs_mount(&request, ctx->timeo, ctx->retrans);
895+
else
896+
status = nfs_mount(&request, NFS_UNSPEC_TIMEO, NFS_UNSPEC_RETRANS);
889897
if (status != 0) {
890898
dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n",
891899
request.hostname, status);

fs/nfs_common/nfslocalio.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
#include <linux/module.h>
8-
#include <linux/rculist.h>
8+
#include <linux/list.h>
99
#include <linux/nfslocalio.h>
1010
#include <net/netns/generic.h>
1111

@@ -20,23 +20,36 @@ static DEFINE_SPINLOCK(nfs_uuid_lock);
2020
*/
2121
static LIST_HEAD(nfs_uuids);
2222

23-
void nfs_uuid_begin(nfs_uuid_t *nfs_uuid)
23+
void nfs_uuid_init(nfs_uuid_t *nfs_uuid)
2424
{
2525
nfs_uuid->net = NULL;
2626
nfs_uuid->dom = NULL;
27-
uuid_gen(&nfs_uuid->uuid);
27+
INIT_LIST_HEAD(&nfs_uuid->list);
28+
}
29+
EXPORT_SYMBOL_GPL(nfs_uuid_init);
2830

31+
bool nfs_uuid_begin(nfs_uuid_t *nfs_uuid)
32+
{
2933
spin_lock(&nfs_uuid_lock);
30-
list_add_tail_rcu(&nfs_uuid->list, &nfs_uuids);
34+
/* Is this nfs_uuid already in use? */
35+
if (!list_empty(&nfs_uuid->list)) {
36+
spin_unlock(&nfs_uuid_lock);
37+
return false;
38+
}
39+
uuid_gen(&nfs_uuid->uuid);
40+
list_add_tail(&nfs_uuid->list, &nfs_uuids);
3141
spin_unlock(&nfs_uuid_lock);
42+
43+
return true;
3244
}
3345
EXPORT_SYMBOL_GPL(nfs_uuid_begin);
3446

3547
void nfs_uuid_end(nfs_uuid_t *nfs_uuid)
3648
{
3749
if (nfs_uuid->net == NULL) {
3850
spin_lock(&nfs_uuid_lock);
39-
list_del_init(&nfs_uuid->list);
51+
if (nfs_uuid->net == NULL)
52+
list_del_init(&nfs_uuid->list);
4053
spin_unlock(&nfs_uuid_lock);
4154
}
4255
}

include/linux/nfslocalio.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ typedef struct {
3232
struct auth_domain *dom; /* auth_domain for localio */
3333
} nfs_uuid_t;
3434

35-
void nfs_uuid_begin(nfs_uuid_t *);
35+
void nfs_uuid_init(nfs_uuid_t *);
36+
bool nfs_uuid_begin(nfs_uuid_t *);
3637
void nfs_uuid_end(nfs_uuid_t *);
3738
void nfs_uuid_is_local(const uuid_t *, struct list_head *,
3839
struct net *, struct auth_domain *, struct module *);

net/sunrpc/xprtsock.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,6 +2459,7 @@ static void xs_tcp_setup_socket(struct work_struct *work)
24592459
case -EHOSTUNREACH:
24602460
case -EADDRINUSE:
24612461
case -ENOBUFS:
2462+
case -ENOTCONN:
24622463
break;
24632464
default:
24642465
printk("%s: connect returned unhandled error %d\n",

0 commit comments

Comments
 (0)