mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
More NFS Client Bugfixes for Linux 6.12-rc
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() -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAmcr1HUACgkQ18tUv7Cl QOtdYBAA0YohWDHflcHPbltJu0UyCyDDtowvpVacSDJwZwVEXnLQRTTqrdUnWVxx Bc2Ae8tGsfcwo10yZ6LUIPjcyEqLQeYvKoKv2Awf0j7eubjRYZrQVypIKtmy8aC2 H5ETCyrbIubE06jX8EPO8LFxQ+T6nGD7kC8qJZL8z/aNVXGA2nRRCi7AzdE4o6Ht 0t6fC+W5vxJ4hQHYKb59nGvREMwpKSLg2U4wo1lyFvkDxEJ06DobGOKEtD333cI8 Mou/1UlSZ6RzgfwJNIPMMpCepIp2spaDeet0XVN+zqzxg55Jmk7LqpxP5pswTjLb WsxErV9ZRXtwutCCf+IDoMCv/YS4g4ZG7CLKXQ4felKJVYIuiS4z0n659xRqLyyi nW71vrRUdOBE3rCXUW6crZYwX/fHDvl6bsq9/h7cy2ZPnbGkVvXx+LIm0dJRenfb MaxVM3CyrMnzL3UUk/caK/rVCOHrDD5q/dAtSNfizMWnqoX+gXby3ho6Zwn0Wj89 NiUZJIRI/s4V1WzMw4g+Daz7LUUwGblODTtphH2nnKRDfTiYXeT/r/waU6zUOVcS 7Jd285DF/tkQp2SJ3nvsM/ni7TD2UuG2BsKA3Urlht9i32lwyENeS3nNcx6aHo3i blNpD+9mp3vZfWWZNVvLM/JldcIqEvd30+P6GWwS/Td8Zz4PYIM= =9mwu -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
ff7afaeca1
@ -181,8 +181,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
|
||||
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
|
||||
seqlock_init(&clp->cl_boot_lock);
|
||||
ktime_get_real_ts64(&clp->cl_nfssvc_boot);
|
||||
clp->cl_uuid.net = NULL;
|
||||
clp->cl_uuid.dom = NULL;
|
||||
nfs_uuid_init(&clp->cl_uuid);
|
||||
spin_lock_init(&clp->cl_localio_lock);
|
||||
#endif /* CONFIG_NFS_LOCALIO */
|
||||
|
||||
|
@ -205,12 +205,15 @@ void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
|
||||
nfs_fscache_invalidate(inode, 0);
|
||||
flags &= ~NFS_INO_REVAL_FORCED;
|
||||
|
||||
nfsi->cache_validity |= flags;
|
||||
flags |= nfsi->cache_validity;
|
||||
if (inode->i_mapping->nrpages == 0)
|
||||
flags &= ~NFS_INO_INVALID_DATA;
|
||||
|
||||
if (inode->i_mapping->nrpages == 0) {
|
||||
nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
|
||||
nfs_ooo_clear(nfsi);
|
||||
} else if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
|
||||
/* pairs with nfs_clear_invalid_mapping()'s smp_load_acquire() */
|
||||
smp_store_release(&nfsi->cache_validity, flags);
|
||||
|
||||
if (inode->i_mapping->nrpages == 0 ||
|
||||
nfsi->cache_validity & NFS_INO_INVALID_DATA) {
|
||||
nfs_ooo_clear(nfsi);
|
||||
}
|
||||
trace_nfs_set_cache_invalid(inode, 0);
|
||||
@ -628,23 +631,35 @@ nfs_fattr_fixup_delegated(struct inode *inode, struct nfs_fattr *fattr)
|
||||
}
|
||||
}
|
||||
|
||||
static void nfs_update_timestamps(struct inode *inode, unsigned int ia_valid)
|
||||
{
|
||||
enum file_time_flags time_flags = 0;
|
||||
unsigned int cache_flags = 0;
|
||||
|
||||
if (ia_valid & ATTR_MTIME) {
|
||||
time_flags |= S_MTIME | S_CTIME;
|
||||
cache_flags |= NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME;
|
||||
}
|
||||
if (ia_valid & ATTR_ATIME) {
|
||||
time_flags |= S_ATIME;
|
||||
cache_flags |= NFS_INO_INVALID_ATIME;
|
||||
}
|
||||
inode_update_timestamps(inode, time_flags);
|
||||
NFS_I(inode)->cache_validity &= ~cache_flags;
|
||||
}
|
||||
|
||||
void nfs_update_delegated_atime(struct inode *inode)
|
||||
{
|
||||
spin_lock(&inode->i_lock);
|
||||
if (nfs_have_delegated_atime(inode)) {
|
||||
inode_update_timestamps(inode, S_ATIME);
|
||||
NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ATIME;
|
||||
}
|
||||
if (nfs_have_delegated_atime(inode))
|
||||
nfs_update_timestamps(inode, ATTR_ATIME);
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
|
||||
void nfs_update_delegated_mtime_locked(struct inode *inode)
|
||||
{
|
||||
if (nfs_have_delegated_mtime(inode)) {
|
||||
inode_update_timestamps(inode, S_CTIME | S_MTIME);
|
||||
NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_CTIME |
|
||||
NFS_INO_INVALID_MTIME);
|
||||
}
|
||||
if (nfs_have_delegated_mtime(inode))
|
||||
nfs_update_timestamps(inode, ATTR_MTIME);
|
||||
}
|
||||
|
||||
void nfs_update_delegated_mtime(struct inode *inode)
|
||||
@ -682,15 +697,16 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
attr->ia_valid &= ~ATTR_SIZE;
|
||||
}
|
||||
|
||||
if (nfs_have_delegated_mtime(inode)) {
|
||||
if (attr->ia_valid & ATTR_MTIME) {
|
||||
nfs_update_delegated_mtime(inode);
|
||||
attr->ia_valid &= ~ATTR_MTIME;
|
||||
}
|
||||
if (attr->ia_valid & ATTR_ATIME) {
|
||||
nfs_update_delegated_atime(inode);
|
||||
attr->ia_valid &= ~ATTR_ATIME;
|
||||
}
|
||||
if (nfs_have_delegated_mtime(inode) && attr->ia_valid & ATTR_MTIME) {
|
||||
spin_lock(&inode->i_lock);
|
||||
nfs_update_timestamps(inode, attr->ia_valid);
|
||||
spin_unlock(&inode->i_lock);
|
||||
attr->ia_valid &= ~(ATTR_MTIME | ATTR_ATIME);
|
||||
} else if (nfs_have_delegated_atime(inode) &&
|
||||
attr->ia_valid & ATTR_ATIME &&
|
||||
!(attr->ia_valid & ATTR_MTIME)) {
|
||||
nfs_update_delegated_atime(inode);
|
||||
attr->ia_valid &= ~ATTR_ATIME;
|
||||
}
|
||||
|
||||
/* Optimization: if the end result is no change, don't RPC */
|
||||
@ -1408,6 +1424,13 @@ int nfs_clear_invalid_mapping(struct address_space *mapping)
|
||||
TASK_KILLABLE|TASK_FREEZABLE_UNSAFE);
|
||||
if (ret)
|
||||
goto out;
|
||||
smp_rmb(); /* pairs with smp_wmb() below */
|
||||
if (test_bit(NFS_INO_INVALIDATING, bitlock))
|
||||
continue;
|
||||
/* pairs with nfs_set_cache_invalid()'s smp_store_release() */
|
||||
if (!(smp_load_acquire(&nfsi->cache_validity) & NFS_INO_INVALID_DATA))
|
||||
goto out;
|
||||
/* Slow-path that double-checks with spinlock held */
|
||||
spin_lock(&inode->i_lock);
|
||||
if (test_bit(NFS_INO_INVALIDATING, bitlock)) {
|
||||
spin_unlock(&inode->i_lock);
|
||||
@ -1633,6 +1656,7 @@ void nfs_fattr_init(struct nfs_fattr *fattr)
|
||||
fattr->gencount = nfs_inc_attr_generation_counter();
|
||||
fattr->owner_name = NULL;
|
||||
fattr->group_name = NULL;
|
||||
fattr->mdsthreshold = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_fattr_init);
|
||||
|
||||
|
@ -205,7 +205,8 @@ void nfs_local_probe(struct nfs_client *clp)
|
||||
nfs_local_disable(clp);
|
||||
}
|
||||
|
||||
nfs_uuid_begin(&clp->cl_uuid);
|
||||
if (!nfs_uuid_begin(&clp->cl_uuid))
|
||||
return;
|
||||
if (nfs_server_uuid_is_local(clp))
|
||||
nfs_local_enable(clp);
|
||||
nfs_uuid_end(&clp->cl_uuid);
|
||||
|
@ -3452,6 +3452,10 @@ static int nfs4_do_setattr(struct inode *inode, const struct cred *cred,
|
||||
adjust_flags |= NFS_INO_INVALID_MODE;
|
||||
if (sattr->ia_valid & (ATTR_UID | ATTR_GID))
|
||||
adjust_flags |= NFS_INO_INVALID_OTHER;
|
||||
if (sattr->ia_valid & ATTR_ATIME)
|
||||
adjust_flags |= NFS_INO_INVALID_ATIME;
|
||||
if (sattr->ia_valid & ATTR_MTIME)
|
||||
adjust_flags |= NFS_INO_INVALID_MTIME;
|
||||
|
||||
do {
|
||||
nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, fattr->label),
|
||||
|
@ -885,7 +885,15 @@ static int nfs_request_mount(struct fs_context *fc,
|
||||
* Now ask the mount server to map our export path
|
||||
* to a file handle.
|
||||
*/
|
||||
status = nfs_mount(&request, ctx->timeo, ctx->retrans);
|
||||
if ((request.protocol == XPRT_TRANSPORT_UDP) ==
|
||||
!(ctx->flags & NFS_MOUNT_TCP))
|
||||
/*
|
||||
* NFS protocol and mount protocol are both UDP or neither UDP
|
||||
* so timeouts are compatible. Use NFS timeouts for MOUNT
|
||||
*/
|
||||
status = nfs_mount(&request, ctx->timeo, ctx->retrans);
|
||||
else
|
||||
status = nfs_mount(&request, NFS_UNSPEC_TIMEO, NFS_UNSPEC_RETRANS);
|
||||
if (status != 0) {
|
||||
dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n",
|
||||
request.hostname, status);
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/nfslocalio.h>
|
||||
#include <net/netns/generic.h>
|
||||
|
||||
@ -20,15 +20,27 @@ static DEFINE_SPINLOCK(nfs_uuid_lock);
|
||||
*/
|
||||
static LIST_HEAD(nfs_uuids);
|
||||
|
||||
void nfs_uuid_begin(nfs_uuid_t *nfs_uuid)
|
||||
void nfs_uuid_init(nfs_uuid_t *nfs_uuid)
|
||||
{
|
||||
nfs_uuid->net = NULL;
|
||||
nfs_uuid->dom = NULL;
|
||||
uuid_gen(&nfs_uuid->uuid);
|
||||
INIT_LIST_HEAD(&nfs_uuid->list);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_uuid_init);
|
||||
|
||||
bool nfs_uuid_begin(nfs_uuid_t *nfs_uuid)
|
||||
{
|
||||
spin_lock(&nfs_uuid_lock);
|
||||
list_add_tail_rcu(&nfs_uuid->list, &nfs_uuids);
|
||||
/* Is this nfs_uuid already in use? */
|
||||
if (!list_empty(&nfs_uuid->list)) {
|
||||
spin_unlock(&nfs_uuid_lock);
|
||||
return false;
|
||||
}
|
||||
uuid_gen(&nfs_uuid->uuid);
|
||||
list_add_tail(&nfs_uuid->list, &nfs_uuids);
|
||||
spin_unlock(&nfs_uuid_lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_uuid_begin);
|
||||
|
||||
@ -36,7 +48,8 @@ void nfs_uuid_end(nfs_uuid_t *nfs_uuid)
|
||||
{
|
||||
if (nfs_uuid->net == NULL) {
|
||||
spin_lock(&nfs_uuid_lock);
|
||||
list_del_init(&nfs_uuid->list);
|
||||
if (nfs_uuid->net == NULL)
|
||||
list_del_init(&nfs_uuid->list);
|
||||
spin_unlock(&nfs_uuid_lock);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,8 @@ typedef struct {
|
||||
struct auth_domain *dom; /* auth_domain for localio */
|
||||
} nfs_uuid_t;
|
||||
|
||||
void nfs_uuid_begin(nfs_uuid_t *);
|
||||
void nfs_uuid_init(nfs_uuid_t *);
|
||||
bool nfs_uuid_begin(nfs_uuid_t *);
|
||||
void nfs_uuid_end(nfs_uuid_t *);
|
||||
void nfs_uuid_is_local(const uuid_t *, struct list_head *,
|
||||
struct net *, struct auth_domain *, struct module *);
|
||||
|
@ -2459,6 +2459,7 @@ static void xs_tcp_setup_socket(struct work_struct *work)
|
||||
case -EHOSTUNREACH:
|
||||
case -EADDRINUSE:
|
||||
case -ENOBUFS:
|
||||
case -ENOTCONN:
|
||||
break;
|
||||
default:
|
||||
printk("%s: connect returned unhandled error %d\n",
|
||||
|
Loading…
Reference in New Issue
Block a user