Commit 30e388d5 authored by Andreas Gruenbacher's avatar Andreas Gruenbacher

gfs2: Switch to a per-filesystem glock workqueue

Switch to a per-filesystem glock workqueue.  Additional workqueues are
cheap nowadays, and keeping separate workqueues allows to flush the work
of each filesystem without affecting the others.
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
parent 51568ac2
...@@ -65,7 +65,6 @@ static void request_demote(struct gfs2_glock *gl, unsigned int state, ...@@ -65,7 +65,6 @@ static void request_demote(struct gfs2_glock *gl, unsigned int state,
unsigned long delay, bool remote); unsigned long delay, bool remote);
static struct dentry *gfs2_root; static struct dentry *gfs2_root;
static struct workqueue_struct *glock_workqueue;
static LIST_HEAD(lru_list); static LIST_HEAD(lru_list);
static atomic_t lru_count = ATOMIC_INIT(0); static atomic_t lru_count = ATOMIC_INIT(0);
static DEFINE_SPINLOCK(lru_lock); static DEFINE_SPINLOCK(lru_lock);
...@@ -274,7 +273,9 @@ static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl) ...@@ -274,7 +273,9 @@ static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl)
* work queue. * work queue.
*/ */
static void gfs2_glock_queue_work(struct gfs2_glock *gl, unsigned long delay) { static void gfs2_glock_queue_work(struct gfs2_glock *gl, unsigned long delay) {
if (!queue_delayed_work(glock_workqueue, &gl->gl_work, delay)) { struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
if (!queue_delayed_work(sdp->sd_glock_wq, &gl->gl_work, delay)) {
/* /*
* We are holding the lockref spinlock, and the work was still * We are holding the lockref spinlock, and the work was still
* queued above. The queued work (glock_work_func) takes that * queued above. The queued work (glock_work_func) takes that
...@@ -2252,9 +2253,10 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) ...@@ -2252,9 +2253,10 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
bool timed_out = false; bool timed_out = false;
set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags); set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
flush_workqueue(glock_workqueue); flush_workqueue(sdp->sd_glock_wq);
glock_hash_walk(clear_glock, sdp); glock_hash_walk(clear_glock, sdp);
flush_workqueue(glock_workqueue); flush_workqueue(sdp->sd_glock_wq);
while (!timed_out) { while (!timed_out) {
wait_event_timeout(sdp->sd_kill_wait, wait_event_timeout(sdp->sd_kill_wait,
!atomic_read(&sdp->sd_glock_disposal), !atomic_read(&sdp->sd_glock_disposal),
...@@ -2270,6 +2272,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) ...@@ -2270,6 +2272,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
gfs2_lm_unmount(sdp); gfs2_lm_unmount(sdp);
gfs2_free_dead_glocks(sdp); gfs2_free_dead_glocks(sdp);
glock_hash_walk(dump_glock_func, sdp); glock_hash_walk(dump_glock_func, sdp);
destroy_workqueue(sdp->sd_glock_wq);
} }
static const char *state2str(unsigned state) static const char *state2str(unsigned state)
...@@ -2534,16 +2537,8 @@ int __init gfs2_glock_init(void) ...@@ -2534,16 +2537,8 @@ int __init gfs2_glock_init(void)
if (ret < 0) if (ret < 0)
return ret; return ret;
glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
WQ_HIGHPRI | WQ_FREEZABLE, 0);
if (!glock_workqueue) {
rhashtable_destroy(&gl_hash_table);
return -ENOMEM;
}
glock_shrinker = shrinker_alloc(0, "gfs2-glock"); glock_shrinker = shrinker_alloc(0, "gfs2-glock");
if (!glock_shrinker) { if (!glock_shrinker) {
destroy_workqueue(glock_workqueue);
rhashtable_destroy(&gl_hash_table); rhashtable_destroy(&gl_hash_table);
return -ENOMEM; return -ENOMEM;
} }
...@@ -2563,7 +2558,6 @@ void gfs2_glock_exit(void) ...@@ -2563,7 +2558,6 @@ void gfs2_glock_exit(void)
{ {
shrinker_free(glock_shrinker); shrinker_free(glock_shrinker);
rhashtable_destroy(&gl_hash_table); rhashtable_destroy(&gl_hash_table);
destroy_workqueue(glock_workqueue);
} }
static void gfs2_glock_iter_next(struct gfs2_glock_iter *gi, loff_t n) static void gfs2_glock_iter_next(struct gfs2_glock_iter *gi, loff_t n)
......
...@@ -772,6 +772,7 @@ struct gfs2_sbd { ...@@ -772,6 +772,7 @@ struct gfs2_sbd {
/* Workqueue stuff */ /* Workqueue stuff */
struct workqueue_struct *sd_glock_wq;
struct workqueue_struct *sd_delete_wq; struct workqueue_struct *sd_delete_wq;
/* Daemon stuff */ /* Daemon stuff */
......
...@@ -1188,11 +1188,17 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -1188,11 +1188,17 @@ 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); snprintf(sdp->sd_fsname, sizeof(sdp->sd_fsname), "%s", sdp->sd_table_name);
error = -ENOMEM;
sdp->sd_glock_wq = alloc_workqueue("gfs2-glock/%s",
WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_FREEZABLE, 0,
sdp->sd_fsname);
if (!sdp->sd_glock_wq)
goto fail_free;
sdp->sd_delete_wq = alloc_workqueue("gfs2-delete/%s", sdp->sd_delete_wq = alloc_workqueue("gfs2-delete/%s",
WQ_MEM_RECLAIM | WQ_FREEZABLE, 0, sdp->sd_fsname); WQ_MEM_RECLAIM | WQ_FREEZABLE, 0, sdp->sd_fsname);
error = -ENOMEM;
if (!sdp->sd_delete_wq) if (!sdp->sd_delete_wq)
goto fail_free; goto fail_glock_wq;
error = gfs2_sys_fs_add(sdp); error = gfs2_sys_fs_add(sdp);
if (error) if (error)
...@@ -1301,6 +1307,8 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -1301,6 +1307,8 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
gfs2_sys_fs_del(sdp); gfs2_sys_fs_del(sdp);
fail_delete_wq: fail_delete_wq:
destroy_workqueue(sdp->sd_delete_wq); destroy_workqueue(sdp->sd_delete_wq);
fail_glock_wq:
destroy_workqueue(sdp->sd_glock_wq);
fail_free: fail_free:
free_sbd(sdp); free_sbd(sdp);
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment