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

+61 -21
+4 -2
fs/nfs/callback_xdr.c
··· 118 if (likely(attrlen > 0)) 119 bitmap[0] = ntohl(*p++); 120 if (attrlen > 1) 121 - bitmap[1] = ntohl(*p); 122 return 0; 123 } 124 ··· 448 void *argp) 449 { 450 struct cb_recallanyargs *args = argp; 451 - uint32_t bitmap[2]; 452 __be32 *p, status; 453 454 p = xdr_inline_decode(xdr, 4);
··· 118 if (likely(attrlen > 0)) 119 bitmap[0] = ntohl(*p++); 120 if (attrlen > 1) 121 + bitmap[1] = ntohl(*p++); 122 + if (attrlen > 2) 123 + bitmap[2] = ntohl(*p); 124 return 0; 125 } 126 ··· 446 void *argp) 447 { 448 struct cb_recallanyargs *args = argp; 449 + uint32_t bitmap[3]; 450 __be32 *p, status; 451 452 p = xdr_inline_decode(xdr, 4);
+5 -10
fs/nfs/delegation.c
··· 647 prev = delegation; 648 continue; 649 } 650 651 if (prev) { 652 struct inode *tmp = nfs_delegation_grab_inode(prev); ··· 660 } 661 } 662 663 - inode = nfs_delegation_grab_inode(delegation); 664 - if (inode == NULL) { 665 - rcu_read_unlock(); 666 - iput(to_put); 667 - goto restart; 668 - } 669 delegation = nfs_start_delegation_return_locked(NFS_I(inode)); 670 rcu_read_unlock(); 671 ··· 1181 struct inode *inode; 1182 restart: 1183 rcu_read_lock(); 1184 - restart_locked: 1185 list_for_each_entry_rcu(delegation, &server->delegations, super_list) { 1186 if (test_bit(NFS_DELEGATION_INODE_FREEING, 1187 &delegation->flags) || ··· 1191 continue; 1192 inode = nfs_delegation_grab_inode(delegation); 1193 if (inode == NULL) 1194 - goto restart_locked; 1195 delegation = nfs_start_delegation_return_locked(NFS_I(inode)); 1196 rcu_read_unlock(); 1197 if (delegation != NULL) { ··· 1314 1315 restart: 1316 rcu_read_lock(); 1317 - restart_locked: 1318 list_for_each_entry_rcu(delegation, &server->delegations, super_list) { 1319 if (test_bit(NFS_DELEGATION_INODE_FREEING, 1320 &delegation->flags) || ··· 1325 continue; 1326 inode = nfs_delegation_grab_inode(delegation); 1327 if (inode == NULL) 1328 - goto restart_locked; 1329 spin_lock(&delegation->lock); 1330 cred = get_cred_rcu(delegation->cred); 1331 nfs4_stateid_copy(&stateid, &delegation->stateid);
··· 647 prev = delegation; 648 continue; 649 } 650 + inode = nfs_delegation_grab_inode(delegation); 651 + if (inode == NULL) 652 + continue; 653 654 if (prev) { 655 struct inode *tmp = nfs_delegation_grab_inode(prev); ··· 657 } 658 } 659 660 delegation = nfs_start_delegation_return_locked(NFS_I(inode)); 661 rcu_read_unlock(); 662 ··· 1184 struct inode *inode; 1185 restart: 1186 rcu_read_lock(); 1187 list_for_each_entry_rcu(delegation, &server->delegations, super_list) { 1188 if (test_bit(NFS_DELEGATION_INODE_FREEING, 1189 &delegation->flags) || ··· 1195 continue; 1196 inode = nfs_delegation_grab_inode(delegation); 1197 if (inode == NULL) 1198 + continue; 1199 delegation = nfs_start_delegation_return_locked(NFS_I(inode)); 1200 rcu_read_unlock(); 1201 if (delegation != NULL) { ··· 1318 1319 restart: 1320 rcu_read_lock(); 1321 list_for_each_entry_rcu(delegation, &server->delegations, super_list) { 1322 if (test_bit(NFS_DELEGATION_INODE_FREEING, 1323 &delegation->flags) || ··· 1330 continue; 1331 inode = nfs_delegation_grab_inode(delegation); 1332 if (inode == NULL) 1333 + continue; 1334 spin_lock(&delegation->lock); 1335 cred = get_cred_rcu(delegation->cred); 1336 nfs4_stateid_copy(&stateid, &delegation->stateid);
+8 -4
fs/nfs/nfs4proc.c
··· 3931 FATTR4_WORD0_CASE_INSENSITIVE | 3932 FATTR4_WORD0_CASE_PRESERVING; 3933 if (minorversion) 3934 - bitmask[2] = FATTR4_WORD2_SUPPATTR_EXCLCREAT; 3935 3936 status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); 3937 if (status == 0) { ··· 9998 fallthrough; 9999 default: 10000 task->tk_status = 0; 10001 fallthrough; 10002 case 0: 10003 break; ··· 10012 task->tk_status = 0; 10013 break; 10014 case -NFS4ERR_DELAY: 10015 - if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN) 10016 - break; 10017 - goto out_restart; 10018 } 10019 return; 10020 out_restart:
··· 3931 FATTR4_WORD0_CASE_INSENSITIVE | 3932 FATTR4_WORD0_CASE_PRESERVING; 3933 if (minorversion) 3934 + bitmask[2] = FATTR4_WORD2_SUPPATTR_EXCLCREAT | 3935 + FATTR4_WORD2_OPEN_ARGUMENTS; 3936 3937 status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); 3938 if (status == 0) { ··· 9997 fallthrough; 9998 default: 9999 task->tk_status = 0; 10000 + lrp->res.lrs_present = 0; 10001 fallthrough; 10002 case 0: 10003 break; ··· 10010 task->tk_status = 0; 10011 break; 10012 case -NFS4ERR_DELAY: 10013 + if (nfs4_async_handle_error(task, server, NULL, NULL) == 10014 + -EAGAIN) 10015 + goto out_restart; 10016 + lrp->res.lrs_present = 0; 10017 + break; 10018 } 10019 return; 10020 out_restart:
+2 -3
fs/nfs/pnfs.c
··· 1284 LIST_HEAD(freeme); 1285 1286 spin_lock(&inode->i_lock); 1287 - if (!pnfs_layout_is_valid(lo) || 1288 - !nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid)) 1289 goto out_unlock; 1290 - if (stateid) { 1291 u32 seq = be32_to_cpu(arg_stateid->seqid); 1292 1293 pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq);
··· 1284 LIST_HEAD(freeme); 1285 1286 spin_lock(&inode->i_lock); 1287 + if (!nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid)) 1288 goto out_unlock; 1289 + if (stateid && pnfs_layout_is_valid(lo)) { 1290 u32 seq = be32_to_cpu(arg_stateid->seqid); 1291 1292 pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq);
+2
fs/nfs/super.c
··· 47 #include <linux/vfs.h> 48 #include <linux/inet.h> 49 #include <linux/in6.h> 50 #include <linux/slab.h> 51 #include <net/ipv6.h> 52 #include <linux/netdevice.h> ··· 229 ret = fn(server, data); 230 if (ret) 231 goto out; 232 rcu_read_lock(); 233 } 234 rcu_read_unlock();
··· 47 #include <linux/vfs.h> 48 #include <linux/inet.h> 49 #include <linux/in6.h> 50 + #include <linux/sched.h> 51 #include <linux/slab.h> 52 #include <net/ipv6.h> 53 #include <linux/netdevice.h> ··· 228 ret = fn(server, data); 229 if (ret) 230 goto out; 231 + cond_resched(); 232 rcu_read_lock(); 233 } 234 rcu_read_unlock();
+36
include/trace/events/rpcrdma.h
··· 2277 DEFINE_CLIENT_DEVICE_EVENT(rpcrdma_client_wait_on); 2278 DEFINE_CLIENT_DEVICE_EVENT(rpcrdma_client_remove_one_done); 2279 2280 #endif /* _TRACE_RPCRDMA_H */ 2281 2282 #include <trace/define_trace.h>
··· 2277 DEFINE_CLIENT_DEVICE_EVENT(rpcrdma_client_wait_on); 2278 DEFINE_CLIENT_DEVICE_EVENT(rpcrdma_client_remove_one_done); 2279 2280 + DECLARE_EVENT_CLASS(rpcrdma_client_register_class, 2281 + TP_PROTO( 2282 + const struct ib_device *device, 2283 + const struct rpcrdma_notification *rn 2284 + ), 2285 + 2286 + TP_ARGS(device, rn), 2287 + 2288 + TP_STRUCT__entry( 2289 + __string(name, device->name) 2290 + __field(void *, callback) 2291 + __field(u32, index) 2292 + ), 2293 + 2294 + TP_fast_assign( 2295 + __assign_str(name); 2296 + __entry->callback = rn->rn_done; 2297 + __entry->index = rn->rn_index; 2298 + ), 2299 + 2300 + TP_printk("device=%s index=%u done callback=%pS\n", 2301 + __get_str(name), __entry->index, __entry->callback 2302 + ) 2303 + ); 2304 + 2305 + #define DEFINE_CLIENT_REGISTER_EVENT(name) \ 2306 + DEFINE_EVENT(rpcrdma_client_register_class, name, \ 2307 + TP_PROTO( \ 2308 + const struct ib_device *device, \ 2309 + const struct rpcrdma_notification *rn \ 2310 + ), \ 2311 + TP_ARGS(device, rn)) 2312 + 2313 + DEFINE_CLIENT_REGISTER_EVENT(rpcrdma_client_register); 2314 + DEFINE_CLIENT_REGISTER_EVENT(rpcrdma_client_unregister); 2315 + 2316 #endif /* _TRACE_RPCRDMA_H */ 2317 2318 #include <trace/define_trace.h>
+4 -2
net/sunrpc/xprtrdma/ib_client.c
··· 62 if (!rd || test_bit(RPCRDMA_RD_F_REMOVING, &rd->rd_flags)) 63 return -ENETUNREACH; 64 65 - kref_get(&rd->rd_kref); 66 if (xa_alloc(&rd->rd_xa, &rn->rn_index, rn, xa_limit_32b, GFP_KERNEL) < 0) 67 return -ENOMEM; 68 rn->rn_done = done; 69 return 0; 70 } 71 ··· 92 if (!rd) 93 return; 94 95 xa_erase(&rd->rd_xa, rn->rn_index); 96 kref_put(&rd->rd_kref, rpcrdma_rn_release); 97 } ··· 113 return -ENOMEM; 114 115 kref_init(&rd->rd_kref); 116 - xa_init_flags(&rd->rd_xa, XA_FLAGS_ALLOC1); 117 rd->rd_device = device; 118 init_completion(&rd->rd_done); 119 ib_set_client_data(device, &rpcrdma_ib_client, rd);
··· 62 if (!rd || test_bit(RPCRDMA_RD_F_REMOVING, &rd->rd_flags)) 63 return -ENETUNREACH; 64 65 if (xa_alloc(&rd->rd_xa, &rn->rn_index, rn, xa_limit_32b, GFP_KERNEL) < 0) 66 return -ENOMEM; 67 + kref_get(&rd->rd_kref); 68 rn->rn_done = done; 69 + trace_rpcrdma_client_register(device, rn); 70 return 0; 71 } 72 ··· 91 if (!rd) 92 return; 93 94 + trace_rpcrdma_client_unregister(device, rn); 95 xa_erase(&rd->rd_xa, rn->rn_index); 96 kref_put(&rd->rd_kref, rpcrdma_rn_release); 97 } ··· 111 return -ENOMEM; 112 113 kref_init(&rd->rd_kref); 114 + xa_init_flags(&rd->rd_xa, XA_FLAGS_ALLOC); 115 rd->rd_device = device; 116 init_completion(&rd->rd_done); 117 ib_set_client_data(device, &rpcrdma_ib_client, rd);