lkml.org 
[lkml]   [2010]   [Feb]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 42/43] gfs2: use workqueue instead of slow-work
    Date
    Workqueue can now handle high concurrency.  Convert gfs to use
    workqueue instead of slow-work.

    * Steven pointed out that recovery path might be run from allocation
    path and thus requires forward progress guarantee without memory
    allocation. Create and use gfs_recovery_wq with rescuer. Please
    note that forward progress wasn't guaranteed with slow-work.

    Signed-off-by: Tejun Heo <tj@kernel.org>
    Cc: Steven Whitehouse <swhiteho@redhat.com>
    ---
    fs/gfs2/Kconfig | 1 -
    fs/gfs2/incore.h | 3 +-
    fs/gfs2/main.c | 14 +++++++-----
    fs/gfs2/ops_fstype.c | 8 +++---
    fs/gfs2/recovery.c | 54 +++++++++++++++++++------------------------------
    fs/gfs2/recovery.h | 6 +++-
    fs/gfs2/sys.c | 3 +-
    7 files changed, 40 insertions(+), 49 deletions(-)

    diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
    index 4dcddf8..f51f1bb 100644
    --- a/fs/gfs2/Kconfig
    +++ b/fs/gfs2/Kconfig
    @@ -7,7 +7,6 @@ config GFS2_FS
    select IP_SCTP if DLM_SCTP
    select FS_POSIX_ACL
    select CRC32
    - select SLOW_WORK
    select QUOTA
    select QUOTACTL
    help
    diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
    index bc0ad15..ab5cb5c 100644
    --- a/fs/gfs2/incore.h
    +++ b/fs/gfs2/incore.h
    @@ -12,7 +12,6 @@

    #include <linux/fs.h>
    #include <linux/workqueue.h>
    -#include <linux/slow-work.h>
    #include <linux/dlm.h>
    #include <linux/buffer_head.h>

    @@ -383,7 +382,7 @@ struct gfs2_journal_extent {
    struct gfs2_jdesc {
    struct list_head jd_list;
    struct list_head extent_list;
    - struct slow_work jd_work;
    + struct work_struct jd_work;
    struct inode *jd_inode;
    unsigned long jd_flags;
    #define JDF_RECOVERY 1
    diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
    index 5b31f77..7ec19c0 100644
    --- a/fs/gfs2/main.c
    +++ b/fs/gfs2/main.c
    @@ -15,7 +15,6 @@
    #include <linux/init.h>
    #include <linux/gfs2_ondisk.h>
    #include <asm/atomic.h>
    -#include <linux/slow-work.h>

    #include "gfs2.h"
    #include "incore.h"
    @@ -24,6 +23,7 @@
    #include "util.h"
    #include "glock.h"
    #include "quota.h"
    +#include "recovery.h"

    static struct shrinker qd_shrinker = {
    .shrink = gfs2_shrink_qd_memory,
    @@ -114,9 +114,11 @@ static int __init init_gfs2_fs(void)
    if (error)
    goto fail_unregister;

    - error = slow_work_register_user(THIS_MODULE);
    - if (error)
    - goto fail_slow;
    + error = -ENOMEM;
    + gfs_recovery_wq = __create_workqueue("gfs_recovery", WQ_RESCUER,
    + WQ_MAX_ACTIVE);
    + if (!gfs_recovery_wq)
    + goto fail_wq;

    gfs2_register_debugfs();

    @@ -124,7 +126,7 @@ static int __init init_gfs2_fs(void)

    return 0;

    -fail_slow:
    +fail_wq:
    unregister_filesystem(&gfs2meta_fs_type);
    fail_unregister:
    unregister_filesystem(&gfs2_fs_type);
    @@ -163,7 +165,7 @@ static void __exit exit_gfs2_fs(void)
    gfs2_unregister_debugfs();
    unregister_filesystem(&gfs2_fs_type);
    unregister_filesystem(&gfs2meta_fs_type);
    - slow_work_unregister_user(THIS_MODULE);
    + destroy_workqueue(gfs_recovery_wq);

    kmem_cache_destroy(gfs2_quotad_cachep);
    kmem_cache_destroy(gfs2_rgrpd_cachep);
    diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
    index a86ed63..9ea1217 100644
    --- a/fs/gfs2/ops_fstype.c
    +++ b/fs/gfs2/ops_fstype.c
    @@ -17,7 +17,6 @@
    #include <linux/namei.h>
    #include <linux/mount.h>
    #include <linux/gfs2_ondisk.h>
    -#include <linux/slow-work.h>
    #include <linux/quotaops.h>

    #include "gfs2.h"
    @@ -675,7 +674,7 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
    break;

    INIT_LIST_HEAD(&jd->extent_list);
    - slow_work_init(&jd->jd_work, &gfs2_recover_ops);
    + INIT_WORK(&jd->jd_work, gfs2_recover_func);
    jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1);
    if (!jd->jd_inode || IS_ERR(jd->jd_inode)) {
    if (!jd->jd_inode)
    @@ -780,7 +779,8 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
    if (sdp->sd_lockstruct.ls_first) {
    unsigned int x;
    for (x = 0; x < sdp->sd_journals; x++) {
    - error = gfs2_recover_journal(gfs2_jdesc_find(sdp, x));
    + error = gfs2_recover_journal(gfs2_jdesc_find(sdp, x),
    + true);
    if (error) {
    fs_err(sdp, "error recovering journal %u: %d\n",
    x, error);
    @@ -790,7 +790,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)

    gfs2_others_may_mount(sdp);
    } else if (!sdp->sd_args.ar_spectator) {
    - error = gfs2_recover_journal(sdp->sd_jdesc);
    + error = gfs2_recover_journal(sdp->sd_jdesc, true);
    if (error) {
    fs_err(sdp, "error recovering my journal: %d\n", error);
    goto fail_jinode_gh;
    diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
    index 4b9bece..f7f89a9 100644
    --- a/fs/gfs2/recovery.c
    +++ b/fs/gfs2/recovery.c
    @@ -14,7 +14,6 @@
    #include <linux/buffer_head.h>
    #include <linux/gfs2_ondisk.h>
    #include <linux/crc32.h>
    -#include <linux/slow-work.h>

    #include "gfs2.h"
    #include "incore.h"
    @@ -28,6 +27,8 @@
    #include "util.h"
    #include "dir.h"

    +struct workqueue_struct *gfs_recovery_wq;
    +
    int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
    struct buffer_head **bh)
    {
    @@ -443,23 +444,7 @@ static void gfs2_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
    kobject_uevent_env(&sdp->sd_kobj, KOBJ_CHANGE, envp);
    }

    -static int gfs2_recover_get_ref(struct slow_work *work)
    -{
    - struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work);
    - if (test_and_set_bit(JDF_RECOVERY, &jd->jd_flags))
    - return -EBUSY;
    - return 0;
    -}
    -
    -static void gfs2_recover_put_ref(struct slow_work *work)
    -{
    - struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work);
    - clear_bit(JDF_RECOVERY, &jd->jd_flags);
    - smp_mb__after_clear_bit();
    - wake_up_bit(&jd->jd_flags, JDF_RECOVERY);
    -}
    -
    -static void gfs2_recover_work(struct slow_work *work)
    +void gfs2_recover_func(struct work_struct *work)
    {
    struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work);
    struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
    @@ -578,7 +563,7 @@ static void gfs2_recover_work(struct slow_work *work)
    gfs2_glock_dq_uninit(&j_gh);

    fs_info(sdp, "jid=%u: Done\n", jd->jd_jid);
    - return;
    + goto done;

    fail_gunlock_tr:
    gfs2_glock_dq_uninit(&t_gh);
    @@ -590,32 +575,35 @@ fail_gunlock_j:
    }

    fs_info(sdp, "jid=%u: %s\n", jd->jd_jid, (error) ? "Failed" : "Done");
    -
    fail:
    gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP);
    +done:
    + clear_bit(JDF_RECOVERY, &jd->jd_flags);
    + smp_mb__after_clear_bit();
    + wake_up_bit(&jd->jd_flags, JDF_RECOVERY);
    }

    -struct slow_work_ops gfs2_recover_ops = {
    - .owner = THIS_MODULE,
    - .get_ref = gfs2_recover_get_ref,
    - .put_ref = gfs2_recover_put_ref,
    - .execute = gfs2_recover_work,
    -};
    -
    -
    static int gfs2_recovery_wait(void *word)
    {
    schedule();
    return 0;
    }

    -int gfs2_recover_journal(struct gfs2_jdesc *jd)
    +int gfs2_recover_journal(struct gfs2_jdesc *jd, bool wait)
    {
    int rv;
    - rv = slow_work_enqueue(&jd->jd_work);
    - if (rv)
    - return rv;
    - wait_on_bit(&jd->jd_flags, JDF_RECOVERY, gfs2_recovery_wait, TASK_UNINTERRUPTIBLE);
    +
    + if (test_and_set_bit(JDF_RECOVERY, &jd->jd_flags))
    + return -EBUSY;
    +
    + /* we have JDF_RECOVERY, queue should always succeed */
    + rv = queue_work(gfs_recovery_wq, &jd->jd_work);
    + BUG_ON(!rv);
    +
    + if (wait)
    + wait_on_bit(&jd->jd_flags, JDF_RECOVERY, gfs2_recovery_wait,
    + TASK_UNINTERRUPTIBLE);
    +
    return 0;
    }

    diff --git a/fs/gfs2/recovery.h b/fs/gfs2/recovery.h
    index 1616ac2..2226136 100644
    --- a/fs/gfs2/recovery.h
    +++ b/fs/gfs2/recovery.h
    @@ -12,6 +12,8 @@

    #include "incore.h"

    +extern struct workqueue_struct *gfs_recovery_wq;
    +
    static inline void gfs2_replay_incr_blk(struct gfs2_sbd *sdp, unsigned int *blk)
    {
    if (++*blk == sdp->sd_jdesc->jd_blocks)
    @@ -27,8 +29,8 @@ extern void gfs2_revoke_clean(struct gfs2_sbd *sdp);

    extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
    struct gfs2_log_header_host *head);
    -extern int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd);
    -extern struct slow_work_ops gfs2_recover_ops;
    +extern int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd, bool wait);
    +extern void gfs2_recover_func(struct work_struct *work);

    #endif /* __RECOVERY_DOT_H__ */

    diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
    index 0dc3462..ee0f3cd 100644
    --- a/fs/gfs2/sys.c
    +++ b/fs/gfs2/sys.c
    @@ -26,6 +26,7 @@
    #include "quota.h"
    #include "util.h"
    #include "glops.h"
    +#include "recovery.h"

    struct gfs2_attr {
    struct attribute attr;
    @@ -351,7 +352,7 @@ static ssize_t recover_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
    list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
    if (jd->jd_jid != jid)
    continue;
    - rv = slow_work_enqueue(&jd->jd_work);
    + rv = gfs2_recover_journal(jd, false);
    break;
    }
    out:
    --
    1.6.4.2


    \
     
     \ /
      Last update: 2010-02-26 13:21    [W:0.092 / U:1.128 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site