Skip to content

Commit d55a166

Browse files
Jeff LaytonJ. Bruce Fields
authored andcommitted
nfsd: bump dl_time when unhashing delegation
There's a potential race between a lease break and DELEGRETURN call. Suppose a lease break comes in and queues the workqueue job for a delegation, but it doesn't run just yet. Then, a DELEGRETURN comes in finds the delegation and calls destroy_delegation on it to unhash it and put its primary reference. Next, the workqueue job runs and queues the delegation back onto the del_recall_lru list, issues the CB_RECALL and puts the final reference. With that, the final reference to the delegation is put, but it's still on the LRU list. When we go to unhash a delegation, it's because we intend to get rid of it soon afterward, so we don't want lease breaks to mess with it once that occurs. Fix this by bumping the dl_time whenever we unhash a delegation, to ensure that lease breaks don't monkey with it. I believe this is a regression due to commit 02e1215 (nfsd: Avoid taking state_lock while holding inode lock in nfsd_break_one_deleg). Prior to that, the state_lock was held in the lm_break callback itself, and that would have prevented this race. Cc: Trond Myklebust <[email protected]> Signed-off-by: Jeff Layton <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent 72c0b0f commit d55a166

File tree

1 file changed

+2
-0
lines changed

1 file changed

+2
-0
lines changed

fs/nfsd/nfs4state.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,8 @@ unhash_delegation(struct nfs4_delegation *dp)
660660

661661
spin_lock(&state_lock);
662662
dp->dl_stid.sc_type = NFS4_CLOSED_DELEG_STID;
663+
/* Ensure that deleg break won't try to requeue it */
664+
++dp->dl_time;
663665
spin_lock(&fp->fi_lock);
664666
list_del_init(&dp->dl_perclnt);
665667
list_del_init(&dp->dl_recall_lru);

0 commit comments

Comments
 (0)