@@ -47,10 +47,22 @@ static void nfs_mark_delegation_revoked(struct nfs_delegation *delegation)
47
47
}
48
48
}
49
49
50
+ static struct nfs_delegation * nfs_get_delegation (struct nfs_delegation * delegation )
51
+ {
52
+ refcount_inc (& delegation -> refcount );
53
+ return delegation ;
54
+ }
55
+
56
+ static void nfs_put_delegation (struct nfs_delegation * delegation )
57
+ {
58
+ if (refcount_dec_and_test (& delegation -> refcount ))
59
+ __nfs_free_delegation (delegation );
60
+ }
61
+
50
62
static void nfs_free_delegation (struct nfs_delegation * delegation )
51
63
{
52
64
nfs_mark_delegation_revoked (delegation );
53
- __nfs_free_delegation (delegation );
65
+ nfs_put_delegation (delegation );
54
66
}
55
67
56
68
/**
@@ -275,8 +287,10 @@ nfs_start_delegation_return_locked(struct nfs_inode *nfsi)
275
287
if (delegation == NULL )
276
288
goto out ;
277
289
spin_lock (& delegation -> lock );
278
- if (!test_and_set_bit (NFS_DELEGATION_RETURNING , & delegation -> flags ))
279
- ret = delegation ;
290
+ if (!test_and_set_bit (NFS_DELEGATION_RETURNING , & delegation -> flags )) {
291
+ /* Refcount matched in nfs_end_delegation_return() */
292
+ ret = nfs_get_delegation (delegation );
293
+ }
280
294
spin_unlock (& delegation -> lock );
281
295
if (ret )
282
296
nfs_clear_verifier_delegated (& nfsi -> vfs_inode );
@@ -397,6 +411,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
397
411
if (delegation == NULL )
398
412
return - ENOMEM ;
399
413
nfs4_stateid_copy (& delegation -> stateid , stateid );
414
+ refcount_set (& delegation -> refcount , 1 );
400
415
delegation -> type = type ;
401
416
delegation -> pagemod_limit = pagemod_limit ;
402
417
delegation -> change_attr = inode_peek_iversion_raw (inode );
@@ -496,6 +511,8 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
496
511
497
512
err = nfs_do_return_delegation (inode , delegation , issync );
498
513
out :
514
+ /* Refcount matched in nfs_start_delegation_return_locked() */
515
+ nfs_put_delegation (delegation );
499
516
return err ;
500
517
}
501
518
@@ -690,7 +707,8 @@ void nfs4_inode_return_delegation_on_close(struct inode *inode)
690
707
list_empty (& NFS_I (inode )-> open_files ) &&
691
708
!test_and_set_bit (NFS_DELEGATION_RETURNING , & delegation -> flags )) {
692
709
clear_bit (NFS_DELEGATION_RETURN_IF_CLOSED , & delegation -> flags );
693
- ret = delegation ;
710
+ /* Refcount matched in nfs_end_delegation_return() */
711
+ ret = nfs_get_delegation (delegation );
694
712
}
695
713
spin_unlock (& delegation -> lock );
696
714
if (ret )
@@ -1094,10 +1112,11 @@ void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
1094
1112
delegation = nfs_start_delegation_return_locked (NFS_I (inode ));
1095
1113
rcu_read_unlock ();
1096
1114
if (delegation != NULL ) {
1097
- delegation = nfs_detach_delegation (NFS_I (inode ),
1098
- delegation , server );
1099
- if (delegation != NULL )
1115
+ if (nfs_detach_delegation (NFS_I (inode ), delegation ,
1116
+ server ) != NULL )
1100
1117
nfs_free_delegation (delegation );
1118
+ /* Match nfs_start_delegation_return_locked */
1119
+ nfs_put_delegation (delegation );
1101
1120
}
1102
1121
iput (inode );
1103
1122
nfs_sb_deactive (server -> super );
0 commit comments