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