diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 8d55616488aa..1565fdf32ac0 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -67,7 +67,6 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state, static struct dentry *gfs2_root; static struct workqueue_struct *glock_workqueue; -struct workqueue_struct *gfs2_delete_workqueue; static LIST_HEAD(lru_list); static atomic_t lru_count = ATOMIC_INIT(0); static DEFINE_SPINLOCK(lru_lock); @@ -2060,7 +2059,9 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp) bool gfs2_queue_delete_work(struct gfs2_glock *gl, unsigned long delay) { - return queue_delayed_work(gfs2_delete_workqueue, + struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; + + return queue_delayed_work(sdp->sd_delete_wq, &gl->gl_delete, delay); } @@ -2073,8 +2074,10 @@ void gfs2_cancel_delete_work(struct gfs2_glock *gl) static void flush_delete_work(struct gfs2_glock *gl) { if (gl->gl_name.ln_type == LM_TYPE_IOPEN) { + struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; + if (cancel_delayed_work(&gl->gl_delete)) { - queue_delayed_work(gfs2_delete_workqueue, + queue_delayed_work(sdp->sd_delete_wq, &gl->gl_delete, 0); } } @@ -2083,7 +2086,7 @@ static void flush_delete_work(struct gfs2_glock *gl) void gfs2_flush_delete_work(struct gfs2_sbd *sdp) { glock_hash_walk(flush_delete_work, sdp); - flush_workqueue(gfs2_delete_workqueue); + flush_workqueue(sdp->sd_delete_wq); } /** @@ -2444,18 +2447,9 @@ int __init gfs2_glock_init(void) rhashtable_destroy(&gl_hash_table); return -ENOMEM; } - gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - 0); - if (!gfs2_delete_workqueue) { - destroy_workqueue(glock_workqueue); - rhashtable_destroy(&gl_hash_table); - return -ENOMEM; - } ret = register_shrinker(&glock_shrinker, "gfs2-glock"); if (ret) { - destroy_workqueue(gfs2_delete_workqueue); destroy_workqueue(glock_workqueue); rhashtable_destroy(&gl_hash_table); return ret; @@ -2472,7 +2466,6 @@ void gfs2_glock_exit(void) unregister_shrinker(&glock_shrinker); rhashtable_destroy(&gl_hash_table); destroy_workqueue(glock_workqueue); - destroy_workqueue(gfs2_delete_workqueue); } static void gfs2_glock_iter_next(struct gfs2_glock_iter *gi, loff_t n) diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 17b05d51977c..b9da61dbe550 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -144,7 +144,6 @@ struct gfs2_glock_aspace { struct address_space mapping; }; -extern struct workqueue_struct *gfs2_delete_workqueue; static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl) { struct gfs2_holder *gh; diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index cd886364b11d..6e8a5f2d6b49 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -770,6 +770,10 @@ struct gfs2_sbd { struct completion sd_journal_ready; + /* Workqueue stuff */ + + struct workqueue_struct *sd_delete_wq; + /* Daemon stuff */ struct task_struct *sd_logd_process; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index c0cf1d2d0ef5..f13a940f99d3 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1197,9 +1197,15 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) snprintf(sdp->sd_fsname, sizeof(sdp->sd_fsname), "%s", sdp->sd_table_name); + sdp->sd_delete_wq = alloc_workqueue("gfs2-delete/%s", + WQ_MEM_RECLAIM | WQ_FREEZABLE, 0, sdp->sd_fsname); + error = -ENOMEM; + if (!sdp->sd_delete_wq) + goto fail_free; + error = gfs2_sys_fs_add(sdp); if (error) - goto fail_free; + goto fail_delete_wq; gfs2_create_debugfs_file(sdp); @@ -1309,6 +1315,8 @@ fail_lm: fail_debug: gfs2_delete_debugfs_file(sdp); gfs2_sys_fs_del(sdp); +fail_delete_wq: + destroy_workqueue(sdp->sd_delete_wq); fail_free: free_sbd(sdp); sb->s_fs_info = NULL; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index a857b99252ae..0b5cda464787 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -630,6 +630,8 @@ restart: /* Unmount the locking protocol */ gfs2_lm_unmount(sdp); + destroy_workqueue(sdp->sd_delete_wq); + /* At this point, we're through participating in the lockspace */ gfs2_sys_fs_del(sdp); free_sbd(sdp);