staging: erofs: simplify `z_erofs_vle_submit_all'
authorGao Xiang <gaoxiang25@huawei.com>
Fri, 7 Dec 2018 16:19:18 +0000 (00:19 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Dec 2018 16:10:48 +0000 (17:10 +0100)
Previously, there are too many hacked stuffs such as `__FSIO_1',
`lstgrp_noio', `lstgrp_io' out there in `z_erofs_vle_submit_all'.

Revisit the whole process by properly introducing jobqueue to
represent each type of queued workgroups, furthermore hide all of
crazyness behind independent separated functions.

After this patch, 2 independent jobqueues exist if managed cache
is enabled, or 1 jobqueue if disabled.

Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/erofs/unzip_vle.c

index a8cf324f0b9c51faf6e1c4620b3c6a5aec19d99f..500046f271cb01387ec75bd134195327df76c9ec 100644 (file)
@@ -1229,33 +1229,28 @@ out:    /* the only exit (for tracing and debugging) */
        return page;
 }
 
-static inline struct z_erofs_vle_unzip_io *
-prepare_io_handler(struct super_block *sb,
-                  struct z_erofs_vle_unzip_io *io,
-                  bool background)
+static struct z_erofs_vle_unzip_io *
+jobqueue_init(struct super_block *sb,
+             struct z_erofs_vle_unzip_io *io,
+             bool foreground)
 {
        struct z_erofs_vle_unzip_io_sb *iosb;
 
-       if (!background) {
+       if (foreground) {
                /* waitqueue available for foreground io */
-               BUG_ON(!io);
+               DBG_BUGON(!io);
 
                init_waitqueue_head(&io->u.wait);
                atomic_set(&io->pending_bios, 0);
                goto out;
        }
 
-       if (io)
-               BUG();
-       else {
-               /* allocate extra io descriptor for background io */
-               iosb = kvzalloc(sizeof(struct z_erofs_vle_unzip_io_sb),
+       iosb = kvzalloc(sizeof(struct z_erofs_vle_unzip_io_sb),
                        GFP_KERNEL | __GFP_NOFAIL);
-               BUG_ON(!iosb);
-
-               io = &iosb->io;
-       }
+       DBG_BUGON(!iosb);
 
+       /* initialize fields in the allocated descriptor */
+       io = &iosb->io;
        iosb->sb = sb;
        INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq);
 out:
@@ -1263,27 +1258,105 @@ out:
        return io;
 }
 
+/* define workgroup jobqueue types */
+enum {
 #ifdef EROFS_FS_HAS_MANAGED_CACHE
-#define __FSIO_1 1
+       JQ_BYPASS,
+#endif
+       JQ_SUBMIT,
+       NR_JOBQUEUES,
+};
+
+static void *jobqueueset_init(struct super_block *sb,
+                             z_erofs_vle_owned_workgrp_t qtail[],
+                             struct z_erofs_vle_unzip_io *q[],
+                             struct z_erofs_vle_unzip_io *fgq,
+                             bool forcefg)
+{
+#ifdef EROFS_FS_HAS_MANAGED_CACHE
+       /*
+        * if managed cache is enabled, bypass jobqueue is needed,
+        * no need to read from device for all workgroups in this queue.
+        */
+       q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true);
+       qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head;
+#endif
+
+       q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg);
+       qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head;
+
+       return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg));
+}
+
+#ifdef EROFS_FS_HAS_MANAGED_CACHE
+static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp,
+                                   z_erofs_vle_owned_workgrp_t qtail[],
+                                   z_erofs_vle_owned_workgrp_t owned_head)
+{
+       z_erofs_vle_owned_workgrp_t *const submit_qtail = qtail[JQ_SUBMIT];
+       z_erofs_vle_owned_workgrp_t *const bypass_qtail = qtail[JQ_BYPASS];
+
+       DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED);
+       if (owned_head == Z_EROFS_VLE_WORKGRP_TAIL)
+               owned_head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED;
+
+       WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_TAIL_CLOSED);
+
+       WRITE_ONCE(*submit_qtail, owned_head);
+       WRITE_ONCE(*bypass_qtail, &grp->next);
+
+       qtail[JQ_BYPASS] = &grp->next;
+}
+
+static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[],
+                                      unsigned int nr_bios,
+                                      bool force_fg)
+{
+       /*
+        * although background is preferred, no one is pending for submission.
+        * don't issue workqueue for decompression but drop it directly instead.
+        */
+       if (force_fg || nr_bios)
+               return false;
+
+       kvfree(container_of(q[JQ_SUBMIT],
+                           struct z_erofs_vle_unzip_io_sb,
+                           io));
+       return true;
+}
 #else
-#define __FSIO_1 0
+static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp,
+                                   z_erofs_vle_owned_workgrp_t qtail[],
+                                   z_erofs_vle_owned_workgrp_t owned_head)
+{
+       /* impossible to bypass submission for managed cache disabled */
+       DBG_BUGON(1);
+}
+
+static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[],
+                                      unsigned int nr_bios,
+                                      bool force_fg)
+{
+       /* bios should be >0 if managed cache is disabled */
+       DBG_BUGON(!nr_bios);
+       return false;
+}
 #endif
 
 static bool z_erofs_vle_submit_all(struct super_block *sb,
                                   z_erofs_vle_owned_workgrp_t owned_head,
                                   struct list_head *pagepool,
-                                  struct z_erofs_vle_unzip_io *fg_io,
+                                  struct z_erofs_vle_unzip_io *fgq,
                                   bool force_fg)
 {
        struct erofs_sb_info *const sbi = EROFS_SB(sb);
        const unsigned int clusterpages = erofs_clusterpages(sbi);
        const gfp_t gfp = GFP_NOFS;
-#ifdef EROFS_FS_HAS_MANAGED_CACHE
-       struct z_erofs_vle_workgroup *lstgrp_noio = NULL, *lstgrp_io = NULL;
-#endif
-       struct z_erofs_vle_unzip_io *ios[1 + __FSIO_1];
+
+       z_erofs_vle_owned_workgrp_t qtail[NR_JOBQUEUES];
+       struct z_erofs_vle_unzip_io *q[NR_JOBQUEUES];
        struct bio *bio;
-       tagptr1_t bi_private;
+       void *bi_private;
        /* since bio will be NULL, no need to initialize last_index */
        pgoff_t uninitialized_var(last_index);
        bool force_submit = false;
@@ -1292,28 +1365,13 @@ static bool z_erofs_vle_submit_all(struct super_block *sb,
        if (unlikely(owned_head == Z_EROFS_VLE_WORKGRP_TAIL))
                return false;
 
-       /*
-        * force_fg == 1, (io, fg_io[0]) no io, (io, fg_io[1]) need submit io
-        * force_fg == 0, (io, fg_io[0]) no io; (io[1], bg_io) need submit io
-        */
-#ifdef EROFS_FS_HAS_MANAGED_CACHE
-       ios[0] = prepare_io_handler(sb, fg_io + 0, false);
-#endif
-
-       if (force_fg) {
-               ios[__FSIO_1] = prepare_io_handler(sb, fg_io + __FSIO_1, false);
-               bi_private = tagptr_fold(tagptr1_t, ios[__FSIO_1], 0);
-       } else {
-               ios[__FSIO_1] = prepare_io_handler(sb, NULL, true);
-               bi_private = tagptr_fold(tagptr1_t, ios[__FSIO_1], 1);
-       }
-
-       nr_bios = 0;
        force_submit = false;
        bio = NULL;
+       nr_bios = 0;
+       bi_private = jobqueueset_init(sb, qtail, q, fgq, force_fg);
 
        /* by default, all need io submission */
-       ios[__FSIO_1]->head = owned_head;
+       q[JQ_SUBMIT]->head = owned_head;
 
        do {
                struct z_erofs_vle_workgroup *grp;
@@ -1353,8 +1411,9 @@ submit_bio_retry:
 
                if (!bio) {
                        bio = erofs_grab_bio(sb, first_index + i,
-                               BIO_MAX_PAGES, z_erofs_vle_read_endio, true);
-                       bio->bi_private = tagptr_cast_ptr(bi_private);
+                                            BIO_MAX_PAGES,
+                                            z_erofs_vle_read_endio, true);
+                       bio->bi_private = bi_private;
 
                        ++nr_bios;
                }
@@ -1369,47 +1428,19 @@ skippage:
                if (++i < clusterpages)
                        goto repeat;
 
-#ifdef EROFS_FS_HAS_MANAGED_CACHE
-               if (bypass < clusterpages) {
-                       lstgrp_io = grp;
-               } else {
-                       z_erofs_vle_owned_workgrp_t iogrp_next =
-                               owned_head == Z_EROFS_VLE_WORKGRP_TAIL ?
-                               Z_EROFS_VLE_WORKGRP_TAIL_CLOSED :
-                               owned_head;
-
-                       if (!lstgrp_io)
-                               ios[1]->head = iogrp_next;
-                       else
-                               WRITE_ONCE(lstgrp_io->next, iogrp_next);
-
-                       if (!lstgrp_noio)
-                               ios[0]->head = &grp->next;
-                       else
-                               WRITE_ONCE(lstgrp_noio->next, grp);
-
-                       lstgrp_noio = grp;
-               }
-#endif
+               if (bypass < clusterpages)
+                       qtail[JQ_SUBMIT] = &grp->next;
+               else
+                       move_to_bypass_jobqueue(grp, qtail, owned_head);
        } while (owned_head != Z_EROFS_VLE_WORKGRP_TAIL);
 
        if (bio)
                __submit_bio(bio, REQ_OP_READ, 0);
 
-#ifndef EROFS_FS_HAS_MANAGED_CACHE
-       BUG_ON(!nr_bios);
-#else
-       if (lstgrp_noio)
-               WRITE_ONCE(lstgrp_noio->next, Z_EROFS_VLE_WORKGRP_TAIL_CLOSED);
-
-       if (!force_fg && !nr_bios) {
-               kvfree(container_of(ios[1],
-                       struct z_erofs_vle_unzip_io_sb, io));
+       if (postsubmit_is_all_bypassed(q, nr_bios, force_fg))
                return true;
-       }
-#endif
 
-       z_erofs_vle_unzip_kickoff(tagptr_cast_ptr(bi_private), nr_bios);
+       z_erofs_vle_unzip_kickoff(bi_private, nr_bios);
        return true;
 }
 
@@ -1418,23 +1449,23 @@ static void z_erofs_submit_and_unzip(struct z_erofs_vle_frontend *f,
                                     bool force_fg)
 {
        struct super_block *sb = f->inode->i_sb;
-       struct z_erofs_vle_unzip_io io[1 + __FSIO_1];
+       struct z_erofs_vle_unzip_io io[NR_JOBQUEUES];
 
        if (!z_erofs_vle_submit_all(sb, f->owned_head, pagepool, io, force_fg))
                return;
 
 #ifdef EROFS_FS_HAS_MANAGED_CACHE
-       z_erofs_vle_unzip_all(sb, &io[0], pagepool);
+       z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool);
 #endif
        if (!force_fg)
                return;
 
        /* wait until all bios are completed */
-       wait_event(io[__FSIO_1].u.wait,
-               !atomic_read(&io[__FSIO_1].pending_bios));
+       wait_event(io[JQ_SUBMIT].u.wait,
+                  !atomic_read(&io[JQ_SUBMIT].pending_bios));
 
        /* let's synchronous decompression */
-       z_erofs_vle_unzip_all(sb, &io[__FSIO_1], pagepool);
+       z_erofs_vle_unzip_all(sb, &io[JQ_SUBMIT], pagepool);
 }
 
 static int z_erofs_vle_normalaccess_readpage(struct file *file,