mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 17:25:38 +00:00
NFS Client Bugfixes for Linux 6.11-rc
Bugfixes: * Fix rpcrdma refcounting in xa_alloc * Fix rpcrdma usage of XA_FLAGS_ALLOC * Fix requesting FATTR4_WORD2_OPEN_ARGUMENTS * Fix attribute bitmap decoder to handle a 3rd word * Add reschedule points when returning delegations to avoid soft lockups * Fix clearing layout segments in layoutreturn * Avoid unnecessary rescanning of the per-server delegation list -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAmbIywQACgkQ18tUv7Cl QOtvHQ//VJO6iTh3kmONCru2ohxgAl7+qX+3HHbMR62S8AWCp0ujId0nir7CuxDa 49c+R03s36lGXkTX5x0d3Idhbv12a5Jdy21oZuJU+RCm6Z7MdNXdDl9HN/gXXqdl 0Z3Wk8r3Pi4/tgejau0i2zN2wXxVNKSQgovETnuI/BQLHupDvDy8Sd8lrIqqoiXY sffCiKSTbCFWg6JLEF1UWZZ1VtLUsDZRBQJD+67l1NbjSX/tiBsY0CquWcHjXAlY 2VGDXdFCZwsQyYuqNdMVh1Cr95hcT0F1YZLOT+vn+6b6rA+UbtmPlURt8iR4gBFo Fadpp5pRziYb9wyg/DgFABihB6PzcboIg5Lm0rx870WEuzxSs8NQeQ9sw5hJC797 At8C4I+cNLOaPU5nUEcG53+svEl9F2jDI2jFc8aa5zAW2hHAtpZhLVre5to0CDb/ hu/H+h2yvjJyfSB7kCdVqlU93PJM96P7F1KEdVYmkuXQQMhkZknntVnu41w7KOst SKy0iU29idlU7SFHvKYyc4URC63kTKLWmTZZn3uDJouwDRYudCRPFQpiwnoDJOY3 wRi3jRPhmZQXn7ArChQSPrHqjRVTu9Y0gUcrtAj4YODv+bkngxmZbG3J3IqZKw21 AkMiDZESyriKVOTurX0Fzaj63zHSrIc+TwyTTXwFCGpCbVCf5/k= =OnQe -----END PGP SIGNATURE----- Merge tag 'nfs-for-6.11-2' of git://git.linux-nfs.org/projects/anna/linux-nfs Pull NFS client fixes from Anna Schumaker: - Fix rpcrdma refcounting in xa_alloc - Fix rpcrdma usage of XA_FLAGS_ALLOC - Fix requesting FATTR4_WORD2_OPEN_ARGUMENTS - Fix attribute bitmap decoder to handle a 3rd word - Add reschedule points when returning delegations to avoid soft lockups - Fix clearing layout segments in layoutreturn - Avoid unnecessary rescanning of the per-server delegation list * tag 'nfs-for-6.11-2' of git://git.linux-nfs.org/projects/anna/linux-nfs: NFS: Avoid unnecessary rescanning of the per-server delegation list NFSv4: Fix clearing of layout segments in layoutreturn NFSv4: Add missing rescheduling points in nfs_client_return_marked_delegations nfs: fix bitmap decoder to handle a 3rd word nfs: fix the fetch of FATTR4_OPEN_ARGUMENTS rpcrdma: Trace connection registration and unregistration rpcrdma: Use XA_FLAGS_ALLOC instead of XA_FLAGS_ALLOC1 rpcrdma: Device kref is over-incremented on error from xa_alloc
This commit is contained in:
commit
60f0560f53
@ -118,7 +118,9 @@ static __be32 decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
|
||||
if (likely(attrlen > 0))
|
||||
bitmap[0] = ntohl(*p++);
|
||||
if (attrlen > 1)
|
||||
bitmap[1] = ntohl(*p);
|
||||
bitmap[1] = ntohl(*p++);
|
||||
if (attrlen > 2)
|
||||
bitmap[2] = ntohl(*p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -446,7 +448,7 @@ static __be32 decode_recallany_args(struct svc_rqst *rqstp,
|
||||
void *argp)
|
||||
{
|
||||
struct cb_recallanyargs *args = argp;
|
||||
uint32_t bitmap[2];
|
||||
uint32_t bitmap[3];
|
||||
__be32 *p, status;
|
||||
|
||||
p = xdr_inline_decode(xdr, 4);
|
||||
|
@ -647,6 +647,9 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server,
|
||||
prev = delegation;
|
||||
continue;
|
||||
}
|
||||
inode = nfs_delegation_grab_inode(delegation);
|
||||
if (inode == NULL)
|
||||
continue;
|
||||
|
||||
if (prev) {
|
||||
struct inode *tmp = nfs_delegation_grab_inode(prev);
|
||||
@ -657,12 +660,6 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server,
|
||||
}
|
||||
}
|
||||
|
||||
inode = nfs_delegation_grab_inode(delegation);
|
||||
if (inode == NULL) {
|
||||
rcu_read_unlock();
|
||||
iput(to_put);
|
||||
goto restart;
|
||||
}
|
||||
delegation = nfs_start_delegation_return_locked(NFS_I(inode));
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -1184,7 +1181,6 @@ static int nfs_server_reap_unclaimed_delegations(struct nfs_server *server,
|
||||
struct inode *inode;
|
||||
restart:
|
||||
rcu_read_lock();
|
||||
restart_locked:
|
||||
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
|
||||
if (test_bit(NFS_DELEGATION_INODE_FREEING,
|
||||
&delegation->flags) ||
|
||||
@ -1195,7 +1191,7 @@ static int nfs_server_reap_unclaimed_delegations(struct nfs_server *server,
|
||||
continue;
|
||||
inode = nfs_delegation_grab_inode(delegation);
|
||||
if (inode == NULL)
|
||||
goto restart_locked;
|
||||
continue;
|
||||
delegation = nfs_start_delegation_return_locked(NFS_I(inode));
|
||||
rcu_read_unlock();
|
||||
if (delegation != NULL) {
|
||||
@ -1318,7 +1314,6 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server,
|
||||
|
||||
restart:
|
||||
rcu_read_lock();
|
||||
restart_locked:
|
||||
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
|
||||
if (test_bit(NFS_DELEGATION_INODE_FREEING,
|
||||
&delegation->flags) ||
|
||||
@ -1330,7 +1325,7 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server,
|
||||
continue;
|
||||
inode = nfs_delegation_grab_inode(delegation);
|
||||
if (inode == NULL)
|
||||
goto restart_locked;
|
||||
continue;
|
||||
spin_lock(&delegation->lock);
|
||||
cred = get_cred_rcu(delegation->cred);
|
||||
nfs4_stateid_copy(&stateid, &delegation->stateid);
|
||||
|
@ -3931,7 +3931,8 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
|
||||
FATTR4_WORD0_CASE_INSENSITIVE |
|
||||
FATTR4_WORD0_CASE_PRESERVING;
|
||||
if (minorversion)
|
||||
bitmask[2] = FATTR4_WORD2_SUPPATTR_EXCLCREAT;
|
||||
bitmask[2] = FATTR4_WORD2_SUPPATTR_EXCLCREAT |
|
||||
FATTR4_WORD2_OPEN_ARGUMENTS;
|
||||
|
||||
status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
|
||||
if (status == 0) {
|
||||
@ -9997,6 +9998,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
|
||||
fallthrough;
|
||||
default:
|
||||
task->tk_status = 0;
|
||||
lrp->res.lrs_present = 0;
|
||||
fallthrough;
|
||||
case 0:
|
||||
break;
|
||||
@ -10010,9 +10012,11 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
|
||||
task->tk_status = 0;
|
||||
break;
|
||||
case -NFS4ERR_DELAY:
|
||||
if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN)
|
||||
break;
|
||||
goto out_restart;
|
||||
if (nfs4_async_handle_error(task, server, NULL, NULL) ==
|
||||
-EAGAIN)
|
||||
goto out_restart;
|
||||
lrp->res.lrs_present = 0;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
out_restart:
|
||||
|
@ -1284,10 +1284,9 @@ void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
|
||||
LIST_HEAD(freeme);
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
if (!pnfs_layout_is_valid(lo) ||
|
||||
!nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid))
|
||||
if (!nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid))
|
||||
goto out_unlock;
|
||||
if (stateid) {
|
||||
if (stateid && pnfs_layout_is_valid(lo)) {
|
||||
u32 seq = be32_to_cpu(arg_stateid->seqid);
|
||||
|
||||
pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq);
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <linux/netdevice.h>
|
||||
@ -228,6 +229,7 @@ static int __nfs_list_for_each_server(struct list_head *head,
|
||||
ret = fn(server, data);
|
||||
if (ret)
|
||||
goto out;
|
||||
cond_resched();
|
||||
rcu_read_lock();
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
@ -2277,6 +2277,42 @@ DEFINE_CLIENT_DEVICE_EVENT(rpcrdma_client_remove_one);
|
||||
DEFINE_CLIENT_DEVICE_EVENT(rpcrdma_client_wait_on);
|
||||
DEFINE_CLIENT_DEVICE_EVENT(rpcrdma_client_remove_one_done);
|
||||
|
||||
DECLARE_EVENT_CLASS(rpcrdma_client_register_class,
|
||||
TP_PROTO(
|
||||
const struct ib_device *device,
|
||||
const struct rpcrdma_notification *rn
|
||||
),
|
||||
|
||||
TP_ARGS(device, rn),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(name, device->name)
|
||||
__field(void *, callback)
|
||||
__field(u32, index)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name);
|
||||
__entry->callback = rn->rn_done;
|
||||
__entry->index = rn->rn_index;
|
||||
),
|
||||
|
||||
TP_printk("device=%s index=%u done callback=%pS\n",
|
||||
__get_str(name), __entry->index, __entry->callback
|
||||
)
|
||||
);
|
||||
|
||||
#define DEFINE_CLIENT_REGISTER_EVENT(name) \
|
||||
DEFINE_EVENT(rpcrdma_client_register_class, name, \
|
||||
TP_PROTO( \
|
||||
const struct ib_device *device, \
|
||||
const struct rpcrdma_notification *rn \
|
||||
), \
|
||||
TP_ARGS(device, rn))
|
||||
|
||||
DEFINE_CLIENT_REGISTER_EVENT(rpcrdma_client_register);
|
||||
DEFINE_CLIENT_REGISTER_EVENT(rpcrdma_client_unregister);
|
||||
|
||||
#endif /* _TRACE_RPCRDMA_H */
|
||||
|
||||
#include <trace/define_trace.h>
|
||||
|
@ -62,10 +62,11 @@ int rpcrdma_rn_register(struct ib_device *device,
|
||||
if (!rd || test_bit(RPCRDMA_RD_F_REMOVING, &rd->rd_flags))
|
||||
return -ENETUNREACH;
|
||||
|
||||
kref_get(&rd->rd_kref);
|
||||
if (xa_alloc(&rd->rd_xa, &rn->rn_index, rn, xa_limit_32b, GFP_KERNEL) < 0)
|
||||
return -ENOMEM;
|
||||
kref_get(&rd->rd_kref);
|
||||
rn->rn_done = done;
|
||||
trace_rpcrdma_client_register(device, rn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -91,6 +92,7 @@ void rpcrdma_rn_unregister(struct ib_device *device,
|
||||
if (!rd)
|
||||
return;
|
||||
|
||||
trace_rpcrdma_client_unregister(device, rn);
|
||||
xa_erase(&rd->rd_xa, rn->rn_index);
|
||||
kref_put(&rd->rd_kref, rpcrdma_rn_release);
|
||||
}
|
||||
@ -111,7 +113,7 @@ static int rpcrdma_add_one(struct ib_device *device)
|
||||
return -ENOMEM;
|
||||
|
||||
kref_init(&rd->rd_kref);
|
||||
xa_init_flags(&rd->rd_xa, XA_FLAGS_ALLOC1);
|
||||
xa_init_flags(&rd->rd_xa, XA_FLAGS_ALLOC);
|
||||
rd->rd_device = device;
|
||||
init_completion(&rd->rd_done);
|
||||
ib_set_client_data(device, &rpcrdma_ib_client, rd);
|
||||
|
Loading…
Reference in New Issue
Block a user