Hi Chandan,

On Mon, Feb 18, 2019 at 03:34:27PM +0530, Chandan Rajendra wrote:
> The post read processing code is used by both Ext4 and F2FS. Hence to
> remove duplicity, this commit moves the code into
> include/linux/post_read_process.h and fs/post_read_process.c.
> 
> The corresponding decrypt and verity "work" functions have been moved
> inside fscrypt and fsverity sources. With these in place, the post
> processing code now has to just invoke enqueue functions provided by
> fscrypt and fsverity.
> 
> Signed-off-by: Chandan Rajendra <chan...@linux.ibm.com>
> ---
>  fs/Makefile                       |   3 +-
>  fs/crypto/bio.c                   |  21 ++--
>  fs/crypto/crypto.c                |   1 +
>  fs/crypto/fscrypt_private.h       |   3 +
>  fs/ext4/ext4.h                    |   2 -
>  fs/ext4/readpage.c                | 153 +-----------------------------
>  fs/ext4/super.c                   |   9 +-
>  fs/post_read_process.c            | 127 +++++++++++++++++++++++++
>  fs/verity/verify.c                |  12 +++
>  include/linux/fscrypt.h           |  11 ---
>  include/linux/post_read_process.h |  21 ++++
>  11 files changed, 176 insertions(+), 187 deletions(-)
>  create mode 100644 fs/post_read_process.c
>  create mode 100644 include/linux/post_read_process.h
> 
> diff --git a/fs/Makefile b/fs/Makefile
> index 10b37f651ffd..5f6c0cba102b 100644
> --- a/fs/Makefile
> +++ b/fs/Makefile
> @@ -12,7 +12,8 @@ obj-y :=    open.o read_write.o file_table.o super.o \
>               attr.o bad_inode.o file.o filesystems.o namespace.o \
>               seq_file.o xattr.o libfs.o fs-writeback.o \
>               pnode.o splice.o sync.o utimes.o d_path.o \
> -             stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
> +             stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
> +             post_read_process.o
>  

To avoid bloating every Linux kernel in existence, post_read_process.c should
only be compiled if CONFIG_FS_ENCRYPTION || CONFIG_FS_VERITY.

>  ifeq ($(CONFIG_BLOCK),y)
>  obj-y +=     buffer.o block_dev.o direct-io.o mpage.o
> diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
> index 0959044c5cee..a659a76c05e4 100644
> --- a/fs/crypto/bio.c
> +++ b/fs/crypto/bio.c
> @@ -24,6 +24,8 @@
>  #include <linux/module.h>
>  #include <linux/bio.h>
>  #include <linux/namei.h>
> +#include <linux/post_read_process.h>
> +
>  #include "fscrypt_private.h"
>  
>  static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
> @@ -53,24 +55,15 @@ void fscrypt_decrypt_bio(struct bio *bio)
>  }
>  EXPORT_SYMBOL(fscrypt_decrypt_bio);
>  
> -static void completion_pages(struct work_struct *work)
> +void fscrypt_decrypt_work(struct work_struct *work)
>  {
> -     struct fscrypt_ctx *ctx =
> -             container_of(work, struct fscrypt_ctx, r.work);
> -     struct bio *bio = ctx->r.bio;
> +     struct bio_post_read_ctx *ctx =
> +             container_of(work, struct bio_post_read_ctx, work);
>  
> -     __fscrypt_decrypt_bio(bio, true);
> -     fscrypt_release_ctx(ctx);
> -     bio_put(bio);
> -}
> +     fscrypt_decrypt_bio(ctx->bio);
>  
> -void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio)
> -{
> -     INIT_WORK(&ctx->r.work, completion_pages);
> -     ctx->r.bio = bio;
> -     fscrypt_enqueue_decrypt_work(&ctx->r.work);
> +     bio_post_read_processing(ctx);
>  }
> -EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
>  
>  void fscrypt_pullback_bio_page(struct page **page, bool restore)
>  {
> diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
> index 4dc788e3bc96..36d599784e5a 100644
> --- a/fs/crypto/crypto.c
> +++ b/fs/crypto/crypto.c
> @@ -53,6 +53,7 @@ struct kmem_cache *fscrypt_info_cachep;
>  
>  void fscrypt_enqueue_decrypt_work(struct work_struct *work)
>  {
> +     INIT_WORK(work, fscrypt_decrypt_work);
>       queue_work(fscrypt_read_workqueue, work);
>  }
>  EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work);
> diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
> index 7da276159593..412a3bcf9efd 100644
> --- a/fs/crypto/fscrypt_private.h
> +++ b/fs/crypto/fscrypt_private.h
> @@ -114,6 +114,9 @@ static inline bool fscrypt_valid_enc_modes(u32 
> contents_mode,
>       return false;
>  }
>  
> +/* bio.c */
> +void fscrypt_decrypt_work(struct work_struct *work);
> +
>  /* crypto.c */
>  extern struct kmem_cache *fscrypt_info_cachep;
>  extern int fscrypt_initialize(unsigned int cop_flags);
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 0ffa84772667..c0245820bafe 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -3088,8 +3088,6 @@ static inline void ext4_set_de_type(struct super_block 
> *sb,
>  extern int ext4_mpage_readpages(struct address_space *mapping,
>                               struct list_head *pages, struct page *page,
>                               unsigned nr_pages, bool is_readahead);
> -extern int __init ext4_init_post_read_processing(void);
> -extern void ext4_exit_post_read_processing(void);
>  
>  /* symlink.c */
>  extern const struct inode_operations ext4_encrypted_symlink_inode_operations;
> diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
> index 93fbc15177a3..8943fc41fd33 100644
> --- a/fs/ext4/readpage.c
> +++ b/fs/ext4/readpage.c
> @@ -44,14 +44,10 @@
>  #include <linux/backing-dev.h>
>  #include <linux/pagevec.h>
>  #include <linux/cleancache.h>
> +#include <linux/post_read_process.h>
>  
>  #include "ext4.h"
>  
> -#define NUM_PREALLOC_POST_READ_CTXS  128
> -
> -static struct kmem_cache *bio_post_read_ctx_cache;
> -static mempool_t *bio_post_read_ctx_pool;
> -
>  static inline bool ext4_bio_encrypted(struct bio *bio)
>  {
>  #ifdef CONFIG_FS_ENCRYPTION
> @@ -61,124 +57,6 @@ static inline bool ext4_bio_encrypted(struct bio *bio)
>  #endif
>  }
>  
> -/* postprocessing steps for read bios */
> -enum bio_post_read_step {
> -     STEP_INITIAL = 0,
> -     STEP_DECRYPT,
> -     STEP_VERITY,
> -};
> -
> -struct bio_post_read_ctx {
> -     struct bio *bio;
> -     struct work_struct work;
> -     unsigned int cur_step;
> -     unsigned int enabled_steps;
> -};
> -
> -static void __read_end_io(struct bio *bio)
> -{
> -     struct page *page;
> -     struct bio_vec *bv;
> -     int i;
> -
> -     bio_for_each_segment_all(bv, bio, i) {
> -             page = bv->bv_page;
> -
> -             /* PG_error was set if any post_read step failed */
> -             if (bio->bi_status || PageError(page)) {
> -                     ClearPageUptodate(page);
> -                     SetPageError(page);
> -             } else {
> -                     SetPageUptodate(page);
> -             }
> -             unlock_page(page);
> -     }
> -     if (bio->bi_private)
> -             mempool_free(bio->bi_private, bio_post_read_ctx_pool);
> -     bio_put(bio);
> -}
> -
> -static void bio_post_read_processing(struct bio_post_read_ctx *ctx);
> -
> -static void decrypt_work(struct work_struct *work)
> -{
> -     struct bio_post_read_ctx *ctx =
> -             container_of(work, struct bio_post_read_ctx, work);
> -
> -     fscrypt_decrypt_bio(ctx->bio);
> -
> -     bio_post_read_processing(ctx);
> -}
> -
> -static void verity_work(struct work_struct *work)
> -{
> -     struct bio_post_read_ctx *ctx =
> -             container_of(work, struct bio_post_read_ctx, work);
> -
> -     fsverity_verify_bio(ctx->bio);
> -
> -     bio_post_read_processing(ctx);
> -}
> -
> -static void bio_post_read_processing(struct bio_post_read_ctx *ctx)
> -{
> -     /*
> -      * We use different work queues for decryption and for verity because
> -      * verity may require reading metadata pages that need decryption, and
> -      * we shouldn't recurse to the same workqueue.
> -      */
> -     switch (++ctx->cur_step) {
> -     case STEP_DECRYPT:
> -             if (ctx->enabled_steps & (1 << STEP_DECRYPT)) {
> -                     INIT_WORK(&ctx->work, decrypt_work);
> -                     fscrypt_enqueue_decrypt_work(&ctx->work);
> -                     return;
> -             }
> -             ctx->cur_step++;
> -             /* fall-through */
> -     case STEP_VERITY:
> -             if (ctx->enabled_steps & (1 << STEP_VERITY)) {
> -                     INIT_WORK(&ctx->work, verity_work);
> -                     fsverity_enqueue_verify_work(&ctx->work);
> -                     return;
> -             }
> -             ctx->cur_step++;
> -             /* fall-through */
> -     default:
> -             __read_end_io(ctx->bio);
> -     }
> -}
> -
> -static struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
> -                                                    struct bio *bio,
> -                                                    pgoff_t index)
> -{
> -     unsigned int post_read_steps = 0;
> -     struct bio_post_read_ctx *ctx = NULL;
> -
> -     if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
> -             post_read_steps |= 1 << STEP_DECRYPT;
> -#ifdef CONFIG_FS_VERITY
> -     if (inode->i_verity_info != NULL &&
> -         (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
> -             post_read_steps |= 1 << STEP_VERITY;
> -#endif
> -     if (post_read_steps) {
> -             ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
> -             if (!ctx)
> -                     return ERR_PTR(-ENOMEM);
> -             ctx->bio = bio;
> -             ctx->enabled_steps = post_read_steps;
> -             bio->bi_private = ctx;
> -     }
> -     return ctx;
> -}
> -
> -static bool bio_post_read_required(struct bio *bio)
> -{
> -     return bio->bi_private && !bio->bi_status;
> -}
> -
>  /*
>   * I/O completion handler for multipage BIOs.
>   *
> @@ -196,11 +74,10 @@ static void mpage_end_io(struct bio *bio)
>       if (bio_post_read_required(bio)) {
>               struct bio_post_read_ctx *ctx = bio->bi_private;
>  
> -             ctx->cur_step = STEP_INITIAL;
>               bio_post_read_processing(ctx);
>               return;
>       }
> -     __read_end_io(bio);
> +     end_bio_post_read_processing(bio);
>  }
>  
>  static inline loff_t ext4_readpage_limit(struct inode *inode)
> @@ -416,29 +293,3 @@ int ext4_mpage_readpages(struct address_space *mapping,
>               submit_bio(bio);
>       return 0;
>  }
> -
> -int __init ext4_init_post_read_processing(void)
> -{
> -     bio_post_read_ctx_cache =
> -             kmem_cache_create("ext4_bio_post_read_ctx",
> -                               sizeof(struct bio_post_read_ctx), 0, 0, NULL);
> -     if (!bio_post_read_ctx_cache)
> -             goto fail;
> -     bio_post_read_ctx_pool =
> -             mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS,
> -                                      bio_post_read_ctx_cache);
> -     if (!bio_post_read_ctx_pool)
> -             goto fail_free_cache;
> -     return 0;
> -
> -fail_free_cache:
> -     kmem_cache_destroy(bio_post_read_ctx_cache);
> -fail:
> -     return -ENOMEM;
> -}
> -
> -void ext4_exit_post_read_processing(void)
> -{
> -     mempool_destroy(bio_post_read_ctx_pool);
> -     kmem_cache_destroy(bio_post_read_ctx_cache);
> -}
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 95a5d9fbbb9f..9314dddfbf34 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -6102,10 +6102,6 @@ static int __init ext4_init_fs(void)
>               return err;
>  
>       err = ext4_init_pending();
> -     if (err)
> -             goto out7;
> -
> -     err = ext4_init_post_read_processing();
>       if (err)
>               goto out6;
>  
> @@ -6147,10 +6143,8 @@ static int __init ext4_init_fs(void)
>  out4:
>       ext4_exit_pageio();
>  out5:
> -     ext4_exit_post_read_processing();
> -out6:
>       ext4_exit_pending();
> -out7:
> +out6:
>       ext4_exit_es();
>  
>       return err;
> @@ -6167,7 +6161,6 @@ static void __exit ext4_exit_fs(void)
>       ext4_exit_sysfs();
>       ext4_exit_system_zone();
>       ext4_exit_pageio();
> -     ext4_exit_post_read_processing();
>       ext4_exit_es();
>       ext4_exit_pending();
>  }
> diff --git a/fs/post_read_process.c b/fs/post_read_process.c
> new file mode 100644
> index 000000000000..9720eeff0160
> --- /dev/null
> +++ b/fs/post_read_process.c
> @@ -0,0 +1,127 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <linux/module.h>
> +#include <linux/mm.h>
> +#include <linux/pagemap.h>
> +#include <linux/bio.h>
> +#include <linux/fscrypt.h>
> +#include <linux/fsverity.h>
> +#include <linux/post_read_process.h>

To help people who come across this code, please add a comment at the top of
this file that briefly describes what it is.

> +
> +#define NUM_PREALLOC_POST_READ_CTXS  128
> +
> +static struct kmem_cache *bio_post_read_ctx_cache;
> +static mempool_t *bio_post_read_ctx_pool;
> +
> +/* postprocessing steps for read bios */
> +enum bio_post_read_step {
> +     STEP_INITIAL = 0,
> +     STEP_DECRYPT,
> +     STEP_VERITY,
> +};
> +
> +void end_bio_post_read_processing(struct bio *bio)
> +{
> +     struct page *page;
> +     struct bio_vec *bv;
> +     int i;
> +
> +     bio_for_each_segment_all(bv, bio, i) {
> +             page = bv->bv_page;
> +
> +             /* PG_error was set if any post_read step failed */
> +             if (bio->bi_status || PageError(page)) {
> +                     ClearPageUptodate(page);
> +                     SetPageError(page);
> +             } else {
> +                     SetPageUptodate(page);
> +             }
> +             unlock_page(page);
> +     }
> +     if (bio->bi_private)
> +             put_bio_post_read_ctx(bio->bi_private);
> +     bio_put(bio);
> +}
> +
> +void bio_post_read_processing(struct bio_post_read_ctx *ctx)
> +{
> +     /*
> +      * We use different work queues for decryption and for verity because
> +      * verity may require reading metadata pages that need decryption, and
> +      * we shouldn't recurse to the same workqueue.
> +      */
> +     switch (++ctx->cur_step) {
> +     case STEP_DECRYPT:
> +             if (ctx->enabled_steps & (1 << STEP_DECRYPT)) {
> +                     fscrypt_enqueue_decrypt_work(&ctx->work);
> +                     return;
> +             }
> +             ctx->cur_step++;
> +             /* fall-through */
> +     case STEP_VERITY:
> +             if (ctx->enabled_steps & (1 << STEP_VERITY)) {
> +                     fsverity_enqueue_verify_work(&ctx->work);
> +                     return;
> +             }
> +             ctx->cur_step++;
> +             /* fall-through */
> +     default:
> +             end_bio_post_read_processing(ctx->bio);
> +     }
> +}
> +
> +struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
> +                                             struct bio *bio,
> +                                             pgoff_t index)
> +{
> +     unsigned int post_read_steps = 0;
> +     struct bio_post_read_ctx *ctx = NULL;
> +
> +     if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
> +             post_read_steps |= 1 << STEP_DECRYPT;
> +#ifdef CONFIG_FS_VERITY
> +     if (inode->i_verity_info != NULL &&
> +             (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
> +             post_read_steps |= 1 << STEP_VERITY;
> +#endif
> +     if (post_read_steps) {
> +             ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
> +             if (!ctx)
> +                     return ERR_PTR(-ENOMEM);
> +             ctx->bio = bio;
> +             ctx->inode = inode;
> +             ctx->enabled_steps = post_read_steps;
> +             ctx->cur_step = STEP_INITIAL;
> +             bio->bi_private = ctx;
> +     }
> +     return ctx;
> +}
> +
> +void put_bio_post_read_ctx(struct bio_post_read_ctx *ctx)
> +{
> +     mempool_free(ctx, bio_post_read_ctx_pool);
> +}
> +
> +bool bio_post_read_required(struct bio *bio)
> +{
> +     return bio->bi_private && !bio->bi_status;
> +}
> +
> +static int __init bio_init_post_read_processing(void)
> +{
> +     bio_post_read_ctx_cache = KMEM_CACHE(bio_post_read_ctx, 0);
> +     if (!bio_post_read_ctx_cache)
> +             goto fail;
> +     bio_post_read_ctx_pool =
> +             mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS,
> +                                      bio_post_read_ctx_cache);
> +     if (!bio_post_read_ctx_pool)
> +             goto fail_free_cache;
> +     return 0;
> +
> +fail_free_cache:
> +     kmem_cache_destroy(bio_post_read_ctx_cache);
> +fail:
> +     return -ENOMEM;
> +}
> +
> +fs_initcall(bio_init_post_read_processing);
> diff --git a/fs/verity/verify.c b/fs/verity/verify.c
> index fbfb68eff358..4f7cd2269e83 100644
> --- a/fs/verity/verify.c
> +++ b/fs/verity/verify.c
> @@ -13,6 +13,7 @@
>  #include <linux/pagemap.h>
>  #include <linux/ratelimit.h>
>  #include <linux/scatterlist.h>
> +#include <linux/post_read_process.h>
>  
>  struct workqueue_struct *fsverity_read_workqueue;
>  
> @@ -283,6 +284,16 @@ void fsverity_verify_bio(struct bio *bio)
>  EXPORT_SYMBOL_GPL(fsverity_verify_bio);
>  #endif /* CONFIG_BLOCK */
>  
> +static void fsverity_verify_work(struct work_struct *work)
> +{
> +     struct bio_post_read_ctx *ctx =
> +             container_of(work, struct bio_post_read_ctx, work);
> +
> +     fsverity_verify_bio(ctx->bio);
> +
> +     bio_post_read_processing(ctx);
> +}
> +
>  /**
>   * fsverity_enqueue_verify_work - enqueue work on the fs-verity workqueue
>   *
> @@ -290,6 +301,7 @@ EXPORT_SYMBOL_GPL(fsverity_verify_bio);
>   */
>  void fsverity_enqueue_verify_work(struct work_struct *work)
>  {
> +     INIT_WORK(work, fsverity_verify_work);
>       queue_work(fsverity_read_workqueue, work);
>  }
>  EXPORT_SYMBOL_GPL(fsverity_enqueue_verify_work);
> diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
> index 6ba193c23f37..13f70e22aff2 100644
> --- a/include/linux/fscrypt.h
> +++ b/include/linux/fscrypt.h
> @@ -68,10 +68,6 @@ struct fscrypt_ctx {
>                       struct page *bounce_page;       /* Ciphertext page */
>                       struct page *control_page;      /* Original page  */
>               } w;
> -             struct {
> -                     struct bio *bio;
> -                     struct work_struct work;
> -             } r;

Now that 'struct fscrypt_ctx' is only used for writes, the 'w' part should be
changed to an anonymous struct.

>               struct list_head free_list;     /* Free list */
>       };
>       u8 flags;                               /* Flags */
> @@ -206,8 +202,6 @@ static inline bool fscrypt_match_name(const struct 
> fscrypt_name *fname,
>  
>  /* bio.c */
>  extern void fscrypt_decrypt_bio(struct bio *);
> -extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
> -                                     struct bio *bio);
>  extern void fscrypt_pullback_bio_page(struct page **, bool);
>  extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
>                                unsigned int);
> @@ -376,11 +370,6 @@ static inline void fscrypt_decrypt_bio(struct bio *bio)
>  {
>  }
>  
> -static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
> -                                            struct bio *bio)
> -{
> -}
> -
>  static inline void fscrypt_pullback_bio_page(struct page **page, bool 
> restore)
>  {
>       return;
> diff --git a/include/linux/post_read_process.h 
> b/include/linux/post_read_process.h
> new file mode 100644
> index 000000000000..09e52928f861
> --- /dev/null
> +++ b/include/linux/post_read_process.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _POST_READ_PROCESS_H
> +#define _POST_READ_PROCESS_H
> +
> +struct bio_post_read_ctx {
> +     struct bio *bio;
> +     struct inode *inode;
> +     struct work_struct work;
> +     unsigned int cur_step;
> +     unsigned int enabled_steps;
> +};
> +
> +void end_bio_post_read_processing(struct bio *bio);
> +void bio_post_read_processing(struct bio_post_read_ctx *ctx);
> +struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
> +                                             struct bio *bio,
> +                                             pgoff_t index);
> +void put_bio_post_read_ctx(struct bio_post_read_ctx *ctx);
> +bool bio_post_read_required(struct bio *bio);
> +
> +#endif       /* _POST_READ_PROCESS_H */
> -- 
> 2.19.1
> 

- Eric


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to