fscrypt: allow synchronous bio decryption
authorEric Biggers <ebiggers@google.com>
Wed, 18 Apr 2018 18:09:47 +0000 (11:09 -0700)
committerJaegeuk Kim <jaegeuk@google.com>
Sat, 21 Apr 2018 05:33:42 +0000 (22:33 -0700)
Cherry-pick from origin/upstream-f2fs-stable-linux-4.14.y:
  fac0e4a8acde ("fscrypt: allow synchronous bio decryption")

Currently, fscrypt provides fscrypt_decrypt_bio_pages() which decrypts a
bio's pages asynchronously, then unlocks them afterwards.  But, this
assumes that decryption is the last "postprocessing step" for the bio,
so it's incompatible with additional postprocessing steps such as
authenticity verification after decryption.

Therefore, rename the existing fscrypt_decrypt_bio_pages() to
fscrypt_enqueue_decrypt_bio().  Then, add fscrypt_decrypt_bio() which
decrypts the pages in the bio synchronously without unlocking the pages,
nor setting them Uptodate; and add fscrypt_enqueue_decrypt_work(), which
enqueues work on the fscrypt_read_workqueue.  The new functions will be
used by filesystems that support both fscrypt and fs-verity.

Change-Id: I87514f59bcf1d2cec858bb44f6e27652ba0e93eb
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/crypto/bio.c
fs/crypto/crypto.c
fs/crypto/fscrypt_private.h
fs/ext4/readpage.c
fs/f2fs/data.c
include/linux/fscrypt_notsupp.h
include/linux/fscrypt_supp.h

index 0d5e6a569d58ae2c775aad617200ca4fd1b88518..0959044c5ceecb37168743784df8d6d269f6301b 100644 (file)
 #include <linux/namei.h>
 #include "fscrypt_private.h"
 
-/*
- * Call fscrypt_decrypt_page on every single page, reusing the encryption
- * context.
- */
-static void completion_pages(struct work_struct *work)
+static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
 {
-       struct fscrypt_ctx *ctx =
-               container_of(work, struct fscrypt_ctx, r.work);
-       struct bio *bio = ctx->r.bio;
        struct bio_vec *bv;
        int i;
 
@@ -46,22 +39,38 @@ static void completion_pages(struct work_struct *work)
                if (ret) {
                        WARN_ON_ONCE(1);
                        SetPageError(page);
-               } else {
+               } else if (done) {
                        SetPageUptodate(page);
                }
-               unlock_page(page);
+               if (done)
+                       unlock_page(page);
        }
+}
+
+void fscrypt_decrypt_bio(struct bio *bio)
+{
+       __fscrypt_decrypt_bio(bio, false);
+}
+EXPORT_SYMBOL(fscrypt_decrypt_bio);
+
+static void completion_pages(struct work_struct *work)
+{
+       struct fscrypt_ctx *ctx =
+               container_of(work, struct fscrypt_ctx, r.work);
+       struct bio *bio = ctx->r.bio;
+
+       __fscrypt_decrypt_bio(bio, true);
        fscrypt_release_ctx(ctx);
        bio_put(bio);
 }
 
-void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *ctx, struct bio *bio)
+void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio)
 {
        INIT_WORK(&ctx->r.work, completion_pages);
        ctx->r.bio = bio;
-       queue_work(fscrypt_read_workqueue, &ctx->r.work);
+       fscrypt_enqueue_decrypt_work(&ctx->r.work);
 }
-EXPORT_SYMBOL(fscrypt_decrypt_bio_pages);
+EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
 
 void fscrypt_pullback_bio_page(struct page **page, bool restore)
 {
index ce654526c0fb0d48750be1f2ab306c5be4cc8dd1..0758d32ad01bc284bb7aeb1ae4ced74000cb6195 100644 (file)
@@ -45,12 +45,18 @@ static mempool_t *fscrypt_bounce_page_pool = NULL;
 static LIST_HEAD(fscrypt_free_ctxs);
 static DEFINE_SPINLOCK(fscrypt_ctx_lock);
 
-struct workqueue_struct *fscrypt_read_workqueue;
+static struct workqueue_struct *fscrypt_read_workqueue;
 static DEFINE_MUTEX(fscrypt_init_mutex);
 
 static struct kmem_cache *fscrypt_ctx_cachep;
 struct kmem_cache *fscrypt_info_cachep;
 
+void fscrypt_enqueue_decrypt_work(struct work_struct *work)
+{
+       queue_work(fscrypt_read_workqueue, work);
+}
+EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work);
+
 /**
  * fscrypt_release_ctx() - Releases an encryption context
  * @ctx: The encryption context to release.
index ad6722bae8b7499b8128224cef436898043afc3d..4012558f611530a9ed644e3282efff31d6fde534 100644 (file)
@@ -97,7 +97,6 @@ static inline bool fscrypt_valid_enc_modes(u32 contents_mode,
 /* crypto.c */
 extern struct kmem_cache *fscrypt_info_cachep;
 extern int fscrypt_initialize(unsigned int cop_flags);
-extern struct workqueue_struct *fscrypt_read_workqueue;
 extern int fscrypt_do_page_crypto(const struct inode *inode,
                                  fscrypt_direction_t rw, u64 lblk_num,
                                  struct page *src_page,
index df22fcb3c41c2922fdf94602f3e412290fbb932b..039aa698159aea57d1f4f0a8f05fb1d4ea1537b4 100644 (file)
@@ -92,7 +92,7 @@ static void mpage_end_io(struct bio *bio)
                if (bio->bi_status) {
                        fscrypt_release_ctx(bio->bi_private);
                } else {
-                       fscrypt_decrypt_bio_pages(bio->bi_private, bio);
+                       fscrypt_enqueue_decrypt_bio(bio->bi_private, bio);
                        return;
                }
        }
index b42e8d3539e8d719a64a35d4a3a386172aff7fda..2a7b8dcd07d10d9a4d979ab84111d4e841655f6e 100644 (file)
@@ -67,7 +67,7 @@ static void f2fs_read_end_io(struct bio *bio)
                if (bio->bi_status) {
                        fscrypt_release_ctx(bio->bi_private);
                } else {
-                       fscrypt_decrypt_bio_pages(bio->bi_private, bio);
+                       fscrypt_enqueue_decrypt_bio(bio->bi_private, bio);
                        return;
                }
        }
index 44b50c04bae9a3ad31cb319635c683dfa1899c6b..9770be37c9d421fedce25fb534b6408362c10cbe 100644 (file)
@@ -25,6 +25,10 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
 }
 
 /* crypto.c */
+static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
+{
+}
+
 static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode,
                                                  gfp_t gfp_flags)
 {
@@ -160,10 +164,13 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
 }
 
 /* bio.c */
-static inline void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *ctx,
-                                            struct bio *bio)
+static inline void fscrypt_decrypt_bio(struct bio *bio)
+{
+}
+
+static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
+                                              struct bio *bio)
 {
-       return;
 }
 
 static inline void fscrypt_pullback_bio_page(struct page **page, bool restore)
index 477a7a6504d214aa80b994106943d7ef6878ee34..2c9a86ac5e83b9b63f1b95680d9a711d57e0b659 100644 (file)
@@ -59,6 +59,7 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
 }
 
 /* crypto.c */
+extern void fscrypt_enqueue_decrypt_work(struct work_struct *);
 extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
 extern void fscrypt_release_ctx(struct fscrypt_ctx *);
 extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
@@ -188,7 +189,9 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
 }
 
 /* bio.c */
-extern void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *, struct bio *);
+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);