Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nfsd: use workqueue enable/disable APIs for v4_end_grace sync

"nfsd: provide locking for v4_end_grace" introduced a
client_tracking_active flag protected by nn->client_lock to prevent
the laundromat from being scheduled before client tracking
initialization or after shutdown begins. That commit is suitable for
backporting to LTS kernels that predate commit 86898fa6b8cd
("workqueue: Implement disable/enable for (delayed) work items").

However, the workqueue subsystem in recent kernels provides
enable_delayed_work() and disable_delayed_work_sync() for this
purpose. Using this mechanism enable us to remove the
client_tracking_active flag and associated spinlock operations
while preserving the same synchronization guarantees, which is
a cleaner long-term approach.

Signed-off-by: NeilBrown <neil@brown.name>
Tested-by: Li Lingfeng <lilingfeng3@huawei.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by

NeilBrown and committed by
Chuck Lever
27e383dd 0ac903d1

+9 -14
-1
fs/nfsd/netns.h
··· 67 67 struct lock_manager nfsd4_manager; 68 68 bool grace_ended; 69 69 bool grace_end_forced; 70 - bool client_tracking_active; 71 70 time64_t boot_time; 72 71 73 72 struct dentry *nfsd_client_dir;
+9 -13
fs/nfsd/nfs4state.c
··· 6637 6637 { 6638 6638 if (!nn->client_tracking_ops) 6639 6639 return false; 6640 - spin_lock(&nn->client_lock); 6641 - if (nn->grace_ended || !nn->client_tracking_active) { 6642 - spin_unlock(&nn->client_lock); 6640 + if (READ_ONCE(nn->grace_ended)) 6643 6641 return false; 6644 - } 6642 + /* laundromat_work must be initialised now, though it might be disabled */ 6645 6643 WRITE_ONCE(nn->grace_end_forced, true); 6644 + /* mod_delayed_work() doesn't queue work after 6645 + * nfs4_state_shutdown_net() has called disable_delayed_work_sync() 6646 + */ 6646 6647 mod_delayed_work(laundry_wq, &nn->laundromat_work, 0); 6647 - spin_unlock(&nn->client_lock); 6648 6648 return true; 6649 6649 } 6650 6650 ··· 8980 8980 nn->boot_time = ktime_get_real_seconds(); 8981 8981 nn->grace_ended = false; 8982 8982 nn->grace_end_forced = false; 8983 - nn->client_tracking_active = false; 8984 8983 nn->nfsd4_manager.block_opens = true; 8985 8984 INIT_LIST_HEAD(&nn->nfsd4_manager.list); 8986 8985 INIT_LIST_HEAD(&nn->client_lru); ··· 8994 8995 INIT_LIST_HEAD(&nn->blocked_locks_lru); 8995 8996 8996 8997 INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main); 8998 + /* Make sure this cannot run until client tracking is initialised */ 8999 + disable_delayed_work(&nn->laundromat_work); 8997 9000 INIT_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker); 8998 9001 get_net(net); 8999 9002 ··· 9063 9062 locks_start_grace(net, &nn->nfsd4_manager); 9064 9063 nfsd4_client_tracking_init(net); 9065 9064 /* safe for laundromat to run now */ 9066 - spin_lock(&nn->client_lock); 9067 - nn->client_tracking_active = true; 9068 - spin_unlock(&nn->client_lock); 9065 + enable_delayed_work(&nn->laundromat_work); 9069 9066 if (nn->track_reclaim_completes && nn->reclaim_str_hashtbl_size == 0) 9070 9067 goto skip_grace; 9071 9068 printk(KERN_INFO "NFSD: starting %lld-second grace period (net %x)\n", ··· 9112 9113 9113 9114 shrinker_free(nn->nfsd_client_shrinker); 9114 9115 cancel_work_sync(&nn->nfsd_shrinker_work); 9115 - spin_lock(&nn->client_lock); 9116 - nn->client_tracking_active = false; 9117 - spin_unlock(&nn->client_lock); 9118 - cancel_delayed_work_sync(&nn->laundromat_work); 9116 + disable_delayed_work_sync(&nn->laundromat_work); 9119 9117 locks_end_grace(&nn->nfsd4_manager); 9120 9118 9121 9119 INIT_LIST_HEAD(&reaplist);