[f2fs-dev] [RFC PATCH V2 10/14] ext4: Decrypt the block that needs to be partially zeroed

2019-04-14 Thread Chandan Rajendra
__ext4_block_zero_page_range decrypts the entire page. This commit
decrypts the block to be partially zeroed instead of the whole page.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/inode.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 51744a3c3964..ade1816697a8 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4080,9 +4080,10 @@ static int __ext4_block_zero_page_range(handle_t *handle,
if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) {
/* We expect the key to be set. */
BUG_ON(!fscrypt_has_encryption_key(inode));
-   BUG_ON(blocksize != PAGE_SIZE);
WARN_ON_ONCE(fscrypt_decrypt_page(page->mapping->host,
-   page, PAGE_SIZE, 0, 
page->index));
+   page, blocksize,
+   round_down(offset, 
blocksize),
+   iblock));
}
}
if (ext4_should_journal_data(inode)) {
-- 
2.19.1



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


[f2fs-dev] [RFC PATCH V2 12/14] ext4: Compute logical block and the page range to be encrypted

2019-04-14 Thread Chandan Rajendra
For subpage-sized blocks, the initial logical block number mapped by a
page can be different from page->index. Hence this commit adds code to
compute the first logical block mapped by the page and also the page
range to be encrypted.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/page-io.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 3e9298e6a705..75485ee9e800 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -418,6 +418,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
 {
struct page *data_page = NULL;
struct inode *inode = page->mapping->host;
+   u64 page_blk;
unsigned block_start;
struct buffer_head *bh, *head;
int ret = 0;
@@ -478,10 +479,14 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
 
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) {
gfp_t gfp_flags = GFP_NOFS;
+   unsigned int page_bytes;
+
+   page_bytes = round_up(len, i_blocksize(inode));
+   page_blk = page->index << (PAGE_SHIFT - inode->i_blkbits);
 
retry_encrypt:
-   data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0,
-   page->index, gfp_flags);
+   data_page = fscrypt_encrypt_page(inode, page, page_bytes, 0,
+   page_blk, gfp_flags);
if (IS_ERR(data_page)) {
ret = PTR_ERR(data_page);
if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
-- 
2.19.1



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


[f2fs-dev] [RFC PATCH V2 09/14] ext4: Decrypt all boundary blocks when doing buffered write

2019-04-14 Thread Chandan Rajendra
With subpage sized blocks, ext4_block_write_begin() can have up to two
blocks to decrypt. Hence this commit invokes fscrypt_decrypt_page() for
each of those blocks.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/inode.c | 33 +++--
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1327e04334df..51744a3c3964 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1156,12 +1156,14 @@ static int ext4_block_write_begin(struct page *page, 
loff_t pos, unsigned len,
unsigned to = from + len;
struct inode *inode = page->mapping->host;
unsigned block_start, block_end;
-   sector_t block;
+   sector_t block, page_blk_nr;
int err = 0;
unsigned blocksize = inode->i_sb->s_blocksize;
unsigned bbits;
-   struct buffer_head *bh, *head, *wait[2], **wait_bh = wait;
+   struct buffer_head *bh, *head, *wait[2];
+   int nr_wait = 0;
bool decrypt = false;
+   int i;
 
BUG_ON(!PageLocked(page));
BUG_ON(from > PAGE_SIZE);
@@ -1213,25 +1215,36 @@ static int ext4_block_write_begin(struct page *page, 
loff_t pos, unsigned len,
!buffer_unwritten(bh) &&
(block_start < from || block_end > to)) {
ll_rw_block(REQ_OP_READ, 0, 1, );
-   *wait_bh++ = bh;
+   wait[nr_wait++] = bh;
decrypt = IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
}
}
/*
 * If we issued read requests, let them complete.
 */
-   while (wait_bh > wait) {
-   wait_on_buffer(*--wait_bh);
-   if (!buffer_uptodate(*wait_bh))
+   for (i = 0; i < nr_wait; i++) {
+   wait_on_buffer(wait[i]);
+   if (!buffer_uptodate(wait[i]))
err = -EIO;
}
if (unlikely(err)) {
page_zero_new_buffers(page, from, to);
} else if (decrypt) {
-   err = fscrypt_decrypt_page(page->mapping->host, page,
-   PAGE_SIZE, 0, page->index);
-   if (err)
-   clear_buffer_uptodate(*wait_bh);
+   page_blk_nr = (sector_t)page->index << (PAGE_SHIFT - bbits);
+
+   for (i = 0; i < nr_wait; i++) {
+   int err2;
+
+   block = page_blk_nr + (bh_offset(wait[i]) >> bbits);
+   err2 = fscrypt_decrypt_page(page->mapping->host, page,
+   wait[i]->b_size,
+   bh_offset(wait[i]),
+   block);
+   if (err2) {
+   clear_buffer_uptodate(wait[i]);
+   err = err2;
+   }
+   }
}
 
return err;
-- 
2.19.1



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


[f2fs-dev] [PATCH V3 5/7] ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]

2019-06-16 Thread Chandan Rajendra
Now that do_mpage_readpage() is "post read process" aware, this commit
gets ext4_readpage[s] to use mpage_readpage[s] and deletes ext4's
readpage.c since the associated functionality is not required anymore.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/Makefile   |   2 +-
 fs/ext4/inode.c|   5 +-
 fs/ext4/readpage.c | 286 -
 3 files changed, 3 insertions(+), 290 deletions(-)
 delete mode 100644 fs/ext4/readpage.c

diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 8fdfcd3c3e04..7c38803a808d 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
 ext4-y := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \
indirect.o inline.o inode.o ioctl.o mballoc.o migrate.o \
-   mmp.o move_extent.o namei.o page-io.o readpage.o resize.o \
+   mmp.o move_extent.o namei.o page-io.o resize.o \
super.o symlink.o sysfs.o xattr.o xattr_trusted.o xattr_user.o
 
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)   += acl.o
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index f65357735a1a..60010b76b566 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3363,8 +3363,7 @@ static int ext4_readpage(struct file *file, struct page 
*page)
ret = ext4_readpage_inline(inode, page);
 
if (ret == -EAGAIN)
-   return ext4_mpage_readpages(page->mapping, NULL, page, 1,
-   false);
+   return mpage_readpage(page, ext4_get_block);
 
return ret;
 }
@@ -3379,7 +3378,7 @@ ext4_readpages(struct file *file, struct address_space 
*mapping,
if (ext4_has_inline_data(inode))
return 0;
 
-   return ext4_mpage_readpages(mapping, pages, NULL, nr_pages, true);
+   return mpage_readpages(mapping, pages, nr_pages, ext4_get_block);
 }
 
 static void ext4_invalidatepage(struct page *page, unsigned int offset,
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
deleted file mode 100644
index 652796b95545..
--- a/fs/ext4/readpage.c
+++ /dev/null
@@ -1,286 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/fs/ext4/readpage.c
- *
- * Copyright (C) 2002, Linus Torvalds.
- * Copyright (C) 2015, Google, Inc.
- *
- * This was originally taken from fs/mpage.c
- *
- * The intent is the ext4_mpage_readpages() function here is intended
- * to replace mpage_readpages() in the general case, not just for
- * encrypted files.  It has some limitations (see below), where it
- * will fall back to read_block_full_page(), but these limitations
- * should only be hit when page_size != block_size.
- *
- * This will allow us to attach a callback function to support ext4
- * encryption.
- *
- * If anything unusual happens, such as:
- *
- * - encountering a page which has buffers
- * - encountering a page which has a non-hole after a hole
- * - encountering a page with non-contiguous blocks
- *
- * then this code just gives up and calls the buffer_head-based read function.
- * It does handle a page which has holes at the end - that is a common case:
- * the end-of-file on blocksize < PAGE_SIZE setups.
- *
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "ext4.h"
-
-static inline bool ext4_bio_encrypted(struct bio *bio)
-{
-#ifdef CONFIG_FS_ENCRYPTION
-   return unlikely(bio->bi_private != NULL);
-#else
-   return false;
-#endif
-}
-
-/*
- * I/O completion handler for multipage BIOs.
- *
- * The mpage code never puts partial pages into a BIO (except for end-of-file).
- * If a page does not map to a contiguous run of blocks then it simply falls
- * back to block_read_full_page().
- *
- * Why is this?  If a page's completion depends on a number of different BIOs
- * which can complete in any order (or at the same time) then determining the
- * status of that page is hard.  See end_buffer_async_read() for the details.
- * There is no point in duplicating all that complexity.
- */
-static void mpage_end_io(struct bio *bio)
-{
-   struct bio_vec *bv;
-   struct bvec_iter_all iter_all;
-
-   if (read_callbacks_end_bio(bio))
-   return;
-
-   bio_for_each_segment_all(bv, bio, iter_all) {
-   struct page *page = bv->bv_page;
-
-   if (!bio->bi_status) {
-   SetPageUptodate(page);
-   } else {
-   ClearPageUptodate(page);
-   SetPageError(page);
-   }
-   unlock_page(page);
-   }
-
-   bio_put(bio);
-}
-
-int ext4_mpage_readpages(struct address_space *mapping,
-struct list_head *pages, struct page *page,
-u

[f2fs-dev] [PATCH V3 6/7] Add decryption support for sub-pagesized blocks

2019-06-16 Thread Chandan Rajendra
To support decryption of sub-pagesized blocks this commit adds code to,
1. Track buffer head in "struct read_callbacks_ctx".
2. Pass buffer head argument to all read callbacks.
3. Add new fscrypt helper to decrypt the file data referred to by a
   buffer head.

Signed-off-by: Chandan Rajendra 
---
 fs/buffer.c|  55 +--
 fs/crypto/bio.c|  21 +-
 fs/f2fs/data.c |   2 +-
 fs/mpage.c |   2 +-
 fs/read_callbacks.c| 118 +
 include/linux/buffer_head.h|   1 +
 include/linux/read_callbacks.h |  13 +++-
 7 files changed, 158 insertions(+), 54 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index e450c55f6434..dcb67525dac9 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -46,6 +46,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
@@ -246,11 +247,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t 
block)
return ret;
 }
 
-/*
- * I/O completion handler for block_read_full_page() - pages
- * which come unlocked at the end of I/O.
- */
-static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
+void end_buffer_async_read(struct buffer_head *bh)
 {
unsigned long flags;
struct buffer_head *first;
@@ -258,17 +255,7 @@ static void end_buffer_async_read(struct buffer_head *bh, 
int uptodate)
struct page *page;
int page_uptodate = 1;
 
-   BUG_ON(!buffer_async_read(bh));
-
page = bh->b_page;
-   if (uptodate) {
-   set_buffer_uptodate(bh);
-   } else {
-   clear_buffer_uptodate(bh);
-   buffer_io_error(bh, ", async page read");
-   SetPageError(page);
-   }
-
/*
 * Be _very_ careful from here on. Bad things can happen if
 * two buffer heads end IO at almost the same time and both
@@ -307,6 +294,31 @@ static void end_buffer_async_read(struct buffer_head *bh, 
int uptodate)
return;
 }
 
+/*
+ * I/O completion handler for block_read_full_page().  Pages are unlocked
+ * after the I/O completes and the read callbacks (if any) have executed.
+ */
+static void __end_buffer_async_read(struct buffer_head *bh, int uptodate)
+{
+   struct page *page;
+
+   BUG_ON(!buffer_async_read(bh));
+
+   if (read_callbacks_end_bh(bh, uptodate))
+   return;
+
+   page = bh->b_page;
+   if (uptodate) {
+   set_buffer_uptodate(bh);
+   } else {
+   clear_buffer_uptodate(bh);
+   buffer_io_error(bh, ", async page read");
+   SetPageError(page);
+   }
+
+   end_buffer_async_read(bh);
+}
+
 /*
  * Completion handler for block_write_full_page() - pages which are unlocked
  * during I/O, and which have PageWriteback cleared upon I/O completion.
@@ -379,7 +391,7 @@ EXPORT_SYMBOL(end_buffer_async_write);
  */
 static void mark_buffer_async_read(struct buffer_head *bh)
 {
-   bh->b_end_io = end_buffer_async_read;
+   bh->b_end_io = __end_buffer_async_read;
set_buffer_async_read(bh);
 }
 
@@ -2294,10 +2306,15 @@ int block_read_full_page(struct page *page, get_block_t 
*get_block)
 */
for (i = 0; i < nr; i++) {
bh = arr[i];
-   if (buffer_uptodate(bh))
-   end_buffer_async_read(bh, 1);
-   else
+   if (buffer_uptodate(bh)) {
+   __end_buffer_async_read(bh, 1);
+   } else {
+   if (WARN_ON(read_callbacks_setup(inode, NULL, bh, 
NULL))) {
+   __end_buffer_async_read(bh, 0);
+   continue;
+   }
submit_bh(REQ_OP_READ, 0, bh);
+   }
}
return 0;
 }
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 4076d704e2e4..b836d648fd27 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "fscrypt_private.h"
 
@@ -41,12 +42,30 @@ static void fscrypt_decrypt_bio(struct bio *bio)
}
 }
 
+static void fscrypt_decrypt_bh(struct buffer_head *bh)
+{
+   struct page *page;
+   int ret;
+
+   page = bh->b_page;
+
+   ret = fscrypt_decrypt_pagecache_blocks(page, bh->b_size,
+   bh_offset(bh));
+   if (ret)
+   SetPageError(page);
+}
+
 void fscrypt_decrypt_work(struct work_struct *work)
 {
struct read_callbacks_ctx *ctx =
container_of(work, struct read_callbacks_ctx, work);
 
-   fscrypt_decrypt_bio(ctx->bio);
+   WARN_ON(!ctx->bh && !ctx->bio);
+
+   if (ctx->bio)
+   fscrypt_decrypt_bio(ctx->bio);
+   else
+   fscrypt_decrypt_

[f2fs-dev] [PATCH V3 2/7] Integrate read callbacks into Ext4 and F2FS

2019-06-16 Thread Chandan Rajendra
This commit gets Ext4 and F2FS to make use of read callbacks API to
perform decryption of file data read from the disk.
---
 fs/crypto/bio.c |  30 +
 fs/crypto/crypto.c  |   1 +
 fs/crypto/fscrypt_private.h |   3 +
 fs/ext4/readpage.c  |  29 +++--
 fs/f2fs/data.c  | 124 +++-
 fs/f2fs/super.c |   9 +--
 fs/read_callbacks.c |   1 -
 include/linux/fscrypt.h |  18 --
 8 files changed, 40 insertions(+), 175 deletions(-)

diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index f677ff93d464..4076d704e2e4 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -27,7 +27,7 @@
 #include 
 #include "fscrypt_private.h"
 
-static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
+static void fscrypt_decrypt_bio(struct bio *bio)
 {
struct bio_vec *bv;
struct bvec_iter_all iter_all;
@@ -38,37 +38,9 @@ static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
   bv->bv_offset);
if (ret)
SetPageError(page);
-   else if (done)
-   SetPageUptodate(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, work);
-   struct bio *bio = ctx->bio;
-
-   __fscrypt_decrypt_bio(bio, true);
-   fscrypt_release_ctx(ctx);
-   bio_put(bio);
-}
-
-void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio)
-{
-   INIT_WORK(>work, completion_pages);
-   ctx->bio = bio;
-   fscrypt_enqueue_decrypt_work(>work);
-}
-EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
-
 void fscrypt_decrypt_work(struct work_struct *work)
 {
struct read_callbacks_ctx *ctx =
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index 45c3d0427fb2..e0aa20cfcaa7 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -54,6 +54,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 8978eec9d766..0bd65921efbf 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -113,6 +113,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/readpage.c b/fs/ext4/readpage.c
index c916017db334..652796b95545 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -44,6 +44,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ext4.h"
 
@@ -73,14 +74,9 @@ static void mpage_end_io(struct bio *bio)
struct bio_vec *bv;
struct bvec_iter_all iter_all;
 
-   if (ext4_bio_encrypted(bio)) {
-   if (bio->bi_status) {
-   fscrypt_release_ctx(bio->bi_private);
-   } else {
-   fscrypt_enqueue_decrypt_bio(bio->bi_private, bio);
-   return;
-   }
-   }
+   if (read_callbacks_end_bio(bio))
+   return;
+
bio_for_each_segment_all(bv, bio, iter_all) {
struct page *page = bv->bv_page;
 
@@ -241,24 +237,19 @@ int ext4_mpage_readpages(struct address_space *mapping,
bio = NULL;
}
if (bio == NULL) {
-   struct fscrypt_ctx *ctx = NULL;
-
-   if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) {
-   ctx = fscrypt_get_ctx(GFP_NOFS);
-   if (IS_ERR(ctx))
-   goto set_error_page;
-   }
bio = bio_alloc(GFP_KERNEL,
min_t(int, nr_pages, BIO_MAX_PAGES));
-   if (!bio) {
-   if (ctx)
-   fscrypt_release_ctx(ctx);
+   if (!bio)
+   goto set_error_page;
+
+   if (read_callbacks_setup(inode, bio, NULL)) {
+   bio_put(bio);
goto set_error_page;
}
+
bio_set_dev(bio, bdev);
bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9);
bio->bi_end_io = mpage_end_io;

[f2fs-dev] [PATCH V3 1/7] FS: Introduce read callbacks

2019-06-16 Thread Chandan Rajendra
Read callbacks implements a state machine to be executed after a
buffered read I/O is completed. They help in further processing the file
data read from the backing store. Currently, decryption is the only post
processing step to be supported.

The execution of the state machine is to be initiated by the endio
function associated with the read operation.

Signed-off-by: Chandan Rajendra 
---
 fs/Kconfig |   3 +
 fs/Makefile|   2 +
 fs/crypto/Kconfig  |   1 +
 fs/crypto/bio.c|  11 +++
 fs/read_callbacks.c| 174 +
 include/linux/fscrypt.h|   5 +
 include/linux/read_callbacks.h |  38 +++
 7 files changed, 234 insertions(+)
 create mode 100644 fs/read_callbacks.c
 create mode 100644 include/linux/read_callbacks.h

diff --git a/fs/Kconfig b/fs/Kconfig
index f1046cf6ad85..d869859c88da 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -21,6 +21,9 @@ if BLOCK
 config FS_IOMAP
bool
 
+config FS_READ_CALLBACKS
+   bool
+
 source "fs/ext2/Kconfig"
 source "fs/ext4/Kconfig"
 source "fs/jbd2/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index c9aea23aba56..a1a06f0db5c1 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -21,6 +21,8 @@ else
 obj-y +=   no-block.o
 endif
 
+obj-$(CONFIG_FS_READ_CALLBACKS) += read_callbacks.o
+
 obj-$(CONFIG_PROC_FS) += proc_namespace.o
 
 obj-y  += notify/
diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
index 24ed99e2eca0..7752f9964280 100644
--- a/fs/crypto/Kconfig
+++ b/fs/crypto/Kconfig
@@ -9,6 +9,7 @@ config FS_ENCRYPTION
select CRYPTO_CTS
select CRYPTO_SHA256
select KEYS
+   select FS_READ_CALLBACKS if BLOCK
help
  Enable encryption of files and directories.  This
  feature is similar to ecryptfs, but it is more memory
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 82da2510721f..f677ff93d464 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "fscrypt_private.h"
 
 static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
@@ -68,6 +69,16 @@ void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, 
struct bio *bio)
 }
 EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
 
+void fscrypt_decrypt_work(struct work_struct *work)
+{
+   struct read_callbacks_ctx *ctx =
+   container_of(work, struct read_callbacks_ctx, work);
+
+   fscrypt_decrypt_bio(ctx->bio);
+
+   read_callbacks(ctx);
+}
+
 int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len)
 {
diff --git a/fs/read_callbacks.c b/fs/read_callbacks.c
new file mode 100644
index ..a4196e3de05f
--- /dev/null
+++ b/fs/read_callbacks.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file tracks the state machine that needs to be executed after reading
+ * data from files that are encrypted and/or have verity metadata associated
+ * with them.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define NUM_PREALLOC_READ_CALLBACK_CTXS128
+
+static struct kmem_cache *read_callbacks_ctx_cache;
+static mempool_t *read_callbacks_ctx_pool;
+
+/* Read callback state machine steps */
+enum read_callbacks_step {
+   STEP_INITIAL = 0,
+   STEP_DECRYPT,
+};
+
+static void put_read_callbacks_ctx(struct read_callbacks_ctx *ctx)
+{
+   mempool_free(ctx, read_callbacks_ctx_pool);
+}
+
+static void end_read_callbacks_bio(struct bio *bio)
+{
+   struct read_callbacks_ctx *ctx;
+   struct page *page;
+   struct bio_vec *bv;
+   struct bvec_iter_all iter_all;
+
+   ctx = bio->bi_private;
+
+   bio_for_each_segment_all(bv, bio, iter_all) {
+   page = bv->bv_page;
+
+   if (bio->bi_status || PageError(page)) {
+   ClearPageUptodate(page);
+   SetPageError(page);
+   } else {
+   SetPageUptodate(page);
+   }
+
+   if (ctx->page_op)
+   ctx->page_op(bio, page);
+
+   unlock_page(page);
+   }
+
+   put_read_callbacks_ctx(ctx);
+
+   bio_put(bio);
+}
+
+/**
+ * read_callbacks() - Execute the read callbacks state machine.
+ * @ctx: The context structure tracking the current state.
+ *
+ * For each state, this function enqueues a work into appropriate subsystem's
+ * work queue. After performing further processing of the data in the bio's
+ * pages, the subsystem should invoke read_calbacks() to continue with the next
+ * state in the state machine.
+ */
+void read_callbacks(struct read_callbacks_ctx *ctx)
+{
+   /*
+* We use different work queues for decryption and for verity because
+* verity may require reading metadata pages that need decryption,

[f2fs-dev] [PATCH V3 4/7] fs/mpage.c: Integrate read callbacks

2019-06-16 Thread Chandan Rajendra
This commit adds code to make do_mpage_readpage() to be "read callbacks"
aware i.e. for files requiring decryption, do_mpage_readpage() now
sets up the read callbacks state machine when allocating a bio and later
starts execution of the state machine after file data is read from the
underlying disk.

Signed-off-by: Chandan Rajendra 
---
 fs/mpage.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/fs/mpage.c b/fs/mpage.c
index 436a85260394..611ad122fc92 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "internal.h"
 
 /*
@@ -49,6 +50,8 @@ static void mpage_end_io(struct bio *bio)
struct bio_vec *bv;
struct bvec_iter_all iter_all;
 
+   if (read_callbacks_end_bio(bio))
+   return;
bio_for_each_segment_all(bv, bio, iter_all) {
struct page *page = bv->bv_page;
page_endio(page, bio_op(bio),
@@ -309,6 +312,12 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
gfp);
if (args->bio == NULL)
goto confused;
+
+   if (read_callbacks_setup(inode, args->bio, NULL)) {
+   bio_put(args->bio);
+   args->bio = NULL;
+   goto confused;
+   }
}
 
length = first_hole << blkbits;
@@ -330,7 +339,7 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
 confused:
if (args->bio)
args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
-   if (!PageUptodate(page))
+   if (!PageUptodate(page) && !PageError(page))
block_read_full_page(page, args->get_block);
else
unlock_page(page);
-- 
2.19.1



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


[f2fs-dev] [PATCH V3 0/7] Consolidate FS read I/O callbacks code

2019-06-16 Thread Chandan Rajendra
This patchset moves the "FS read I/O callbacks" code into a file of its
own (i.e. fs/read_callbacks.c) and modifies the generic
do_mpage_readpge() to make use of the functionality provided.

"FS read I/O callbacks" code implements the state machine that needs
to be executed after reading data from files that are encrypted and/or
have verity metadata associated with them.

With these changes in place, the patchset changes Ext4 to use
mpage_readpage[s] instead of its own custom ext4_readpage[s]()
functions. This is done to reduce duplication of code across
filesystems. Also, "FS read I/O callbacks" source files will be built
only if CONFIG_FS_ENCRYPTION is enabled.

The patchset also modifies fs/buffer.c to get file
encryption/decryption to work with subpage-sized blocks.

The patches can also be obtained from
https://github.com/chandanr/linux.git at branch subpage-encryption-v3.

Changelog:
V2 -> V3:
1. Split the V2 patch "Consolidate 'read callbacks' into a new file" into
   three patches,
   - Introduce the read_callbacks functionality.
   - Convert encryption to use read_callbacks.
   - Remove union from struct fscrypt_context.
2. fs/Kconfig
   Do not explicitly set the default value of 'n' for FS_READ_CALLBACKS.
3. fs/crypto/Kconfig
   Select CONFIG_FS_READ_CALLBACKS only if CONFIG_BLOCK is selected.
4. Remove verity associated code in read_callbacks code.
5. Introduce a callback argument to read_callbacks_setup() function
   which gets invoked for each page for bio. F2FS uses this to perform
   custom operations like decrementing the value of f2fs_sb_info->nr_pages[].
6. Encapsulate the details of "read callbacks" (e.g. Usage of "struct
   read_callbacks *ctx") within its own functions. When CONFIG_FS_READ_CALLBACKS
   is set to 'n', the corresponding stub functions return approriate error
   values.
7. Split fscrypt_decrypt() function into fscrypt_decrypt_bio() and
   fscrypt_decrypt_bh().
8. Split end_read_callbacks() function into end_read_callbacks_bio() and
   end_read_callbacks_bh().

V1 -> V2:
1. Removed the phrase "post_read_process" from file names and
   functions. Instead we now use the phrase "read_callbacks" in its
   place.
2. When performing changes associated with (1), the changes made by
   the patch "Remove the term 'bio' from post read processing" are
   made in the earlier patch "Consolidate 'read callbacks' into a new
   file". Hence the patch "Remove the term 'bio' from post read
   processing" is removed from the patchset.

RFC V2 -> V1:
1. Test and verify FS_CFLG_OWN_PAGES subset of fscrypt_encrypt_page()
   code by executing fstests on UBIFS.
2. Implement F2fs function call back to check if the contents of a
   page holding a verity file's data needs to be verified.

RFC V1 -> RFC V2:
1. Describe the purpose of "Post processing code" in the cover letter.
2. Fix build errors when CONFIG_FS_VERITY is enabled.

Chandan Rajendra (7):
  FS: Introduce read callbacks
  Integrate read callbacks into Ext4 and F2FS
  fscrypt: remove struct fscrypt_ctx
  fs/mpage.c: Integrate read callbacks
  ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]
  Add decryption support for sub-pagesized blocks
  ext4: Enable encryption for subpage-sized blocks

 Documentation/filesystems/fscrypt.rst |   4 +-
 fs/Kconfig|   3 +
 fs/Makefile   |   2 +
 fs/buffer.c   |  55 +++--
 fs/crypto/Kconfig |   1 +
 fs/crypto/bio.c   |  44 ++--
 fs/crypto/crypto.c|  90 +---
 fs/crypto/fscrypt_private.h   |   3 +
 fs/ext4/Makefile  |   2 +-
 fs/ext4/inode.c   |   5 +-
 fs/ext4/readpage.c| 295 --
 fs/ext4/super.c   |   7 -
 fs/f2fs/data.c| 124 ++-
 fs/f2fs/super.c   |   9 +-
 fs/mpage.c|  11 +-
 fs/read_callbacks.c   | 233 
 include/linux/buffer_head.h   |   1 +
 include/linux/fscrypt.h   |  38 
 include/linux/read_callbacks.h|  45 
 19 files changed, 390 insertions(+), 582 deletions(-)
 delete mode 100644 fs/ext4/readpage.c
 create mode 100644 fs/read_callbacks.c
 create mode 100644 include/linux/read_callbacks.h

-- 
2.19.1



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


[f2fs-dev] [PATCH V3 3/7] fscrypt: remove struct fscrypt_ctx

2019-06-16 Thread Chandan Rajendra
Commit "fscrypt: remove the 'write' part of struct fscrypt_ctx" reduced
"struct fscrypt_ctx" to be used only for decryption. With "read
callbacks" being integrated into Ext4 and F2FS, we don't use "struct
fscrypt_ctx" anymore. Hence this commit removes the structure and the
associated code.

Signed-off-by: Chandan Rajendra 
---
 fs/crypto/crypto.c  | 89 +
 include/linux/fscrypt.h | 25 
 2 files changed, 2 insertions(+), 112 deletions(-)

diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index e0aa20cfcaa7..18c6b664b042 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -32,24 +32,16 @@
 #include "fscrypt_private.h"
 
 static unsigned int num_prealloc_crypto_pages = 32;
-static unsigned int num_prealloc_crypto_ctxs = 128;
 
 module_param(num_prealloc_crypto_pages, uint, 0444);
 MODULE_PARM_DESC(num_prealloc_crypto_pages,
"Number of crypto pages to preallocate");
-module_param(num_prealloc_crypto_ctxs, uint, 0444);
-MODULE_PARM_DESC(num_prealloc_crypto_ctxs,
-   "Number of crypto contexts to preallocate");
 
 static mempool_t *fscrypt_bounce_page_pool = NULL;
 
-static LIST_HEAD(fscrypt_free_ctxs);
-static DEFINE_SPINLOCK(fscrypt_ctx_lock);
-
 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)
@@ -59,62 +51,6 @@ void fscrypt_enqueue_decrypt_work(struct work_struct *work)
 }
 EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work);
 
-/**
- * fscrypt_release_ctx() - Release a decryption context
- * @ctx: The decryption context to release.
- *
- * If the decryption context was allocated from the pre-allocated pool, return
- * it to that pool.  Else, free it.
- */
-void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
-{
-   unsigned long flags;
-
-   if (ctx->flags & FS_CTX_REQUIRES_FREE_ENCRYPT_FL) {
-   kmem_cache_free(fscrypt_ctx_cachep, ctx);
-   } else {
-   spin_lock_irqsave(_ctx_lock, flags);
-   list_add(>free_list, _free_ctxs);
-   spin_unlock_irqrestore(_ctx_lock, flags);
-   }
-}
-EXPORT_SYMBOL(fscrypt_release_ctx);
-
-/**
- * fscrypt_get_ctx() - Get a decryption context
- * @gfp_flags:   The gfp flag for memory allocation
- *
- * Allocate and initialize a decryption context.
- *
- * Return: A new decryption context on success; an ERR_PTR() otherwise.
- */
-struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags)
-{
-   struct fscrypt_ctx *ctx;
-   unsigned long flags;
-
-   /*
-* First try getting a ctx from the free list so that we don't have to
-* call into the slab allocator.
-*/
-   spin_lock_irqsave(_ctx_lock, flags);
-   ctx = list_first_entry_or_null(_free_ctxs,
-   struct fscrypt_ctx, free_list);
-   if (ctx)
-   list_del(>free_list);
-   spin_unlock_irqrestore(_ctx_lock, flags);
-   if (!ctx) {
-   ctx = kmem_cache_zalloc(fscrypt_ctx_cachep, gfp_flags);
-   if (!ctx)
-   return ERR_PTR(-ENOMEM);
-   ctx->flags |= FS_CTX_REQUIRES_FREE_ENCRYPT_FL;
-   } else {
-   ctx->flags &= ~FS_CTX_REQUIRES_FREE_ENCRYPT_FL;
-   }
-   return ctx;
-}
-EXPORT_SYMBOL(fscrypt_get_ctx);
-
 struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags)
 {
return mempool_alloc(fscrypt_bounce_page_pool, gfp_flags);
@@ -401,11 +337,6 @@ const struct dentry_operations fscrypt_d_ops = {
 
 static void fscrypt_destroy(void)
 {
-   struct fscrypt_ctx *pos, *n;
-
-   list_for_each_entry_safe(pos, n, _free_ctxs, free_list)
-   kmem_cache_free(fscrypt_ctx_cachep, pos);
-   INIT_LIST_HEAD(_free_ctxs);
mempool_destroy(fscrypt_bounce_page_pool);
fscrypt_bounce_page_pool = NULL;
 }
@@ -421,7 +352,7 @@ static void fscrypt_destroy(void)
  */
 int fscrypt_initialize(unsigned int cop_flags)
 {
-   int i, res = -ENOMEM;
+   int res = -ENOMEM;
 
/* No need to allocate a bounce page pool if this FS won't use it. */
if (cop_flags & FS_CFLG_OWN_PAGES)
@@ -431,15 +362,6 @@ int fscrypt_initialize(unsigned int cop_flags)
if (fscrypt_bounce_page_pool)
goto already_initialized;
 
-   for (i = 0; i < num_prealloc_crypto_ctxs; i++) {
-   struct fscrypt_ctx *ctx;
-
-   ctx = kmem_cache_zalloc(fscrypt_ctx_cachep, GFP_NOFS);
-   if (!ctx)
-   goto fail;
-   list_add(>free_list, _free_ctxs);
-   }
-
fscrypt_bounce_page_pool =
mempool_create_page_pool(num_prealloc_crypto_pages, 0);
if (!fscrypt_bounce_page_pool)
@@ -494,18 +416,12

Re: [f2fs-dev] [PATCH V3 0/7] Consolidate FS read I/O callbacks code

2019-06-25 Thread Chandan Rajendra
On Saturday, June 22, 2019 3:45:51 AM IST Eric Biggers wrote:
> On Sun, Jun 16, 2019 at 09:38:06PM +0530, Chandan Rajendra wrote:
> > This patchset moves the "FS read I/O callbacks" code into a file of its
> > own (i.e. fs/read_callbacks.c) and modifies the generic
> > do_mpage_readpge() to make use of the functionality provided.
> > 
> > "FS read I/O callbacks" code implements the state machine that needs
> > to be executed after reading data from files that are encrypted and/or
> > have verity metadata associated with them.
> > 
> > With these changes in place, the patchset changes Ext4 to use
> > mpage_readpage[s] instead of its own custom ext4_readpage[s]()
> > functions. This is done to reduce duplication of code across
> > filesystems. Also, "FS read I/O callbacks" source files will be built
> > only if CONFIG_FS_ENCRYPTION is enabled.
> > 
> > The patchset also modifies fs/buffer.c to get file
> > encryption/decryption to work with subpage-sized blocks.
> > 
> > The patches can also be obtained from
> > https://github.com/chandanr/linux.git at branch subpage-encryption-v3.
> > 
> 
> FWIW: while doing my review I put together an (untested) incremental patch 
> that
> addresses my comments on the code, so I've provided it below in case you want 
> to
> start with it when addressing my comments.
> 
> This is just a single diff against your subpage-encryption-v3 branch, so of
> course it would still need to be folded into the appropriate patches.  Also 
> see
> my suggestions in reply to patch 2 about how to better organize the series.  I
> also left TODOs in kerneldoc comments that still need to be updated.
> 

Thanks for all your help. I will post the next version of the patchset
addressing all your review comments.

-- 
chandan





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


Re: [f2fs-dev] [PATCH V3 2/7] Integrate read callbacks into Ext4 and F2FS

2019-06-25 Thread Chandan Rajendra
On Saturday, June 22, 2019 2:38:01 AM IST Eric Biggers wrote:
> Hi Chandan,
> 
> On Sun, Jun 16, 2019 at 09:38:08PM +0530, Chandan Rajendra wrote:
> > This commit gets Ext4 and F2FS to make use of read callbacks API to
> > perform decryption of file data read from the disk.
> > ---
> >  fs/crypto/bio.c |  30 +
> >  fs/crypto/crypto.c  |   1 +
> >  fs/crypto/fscrypt_private.h |   3 +
> >  fs/ext4/readpage.c  |  29 +++--
> >  fs/f2fs/data.c  | 124 +++-
> >  fs/f2fs/super.c |   9 +--
> >  fs/read_callbacks.c |   1 -
> >  include/linux/fscrypt.h |  18 --
> >  8 files changed, 40 insertions(+), 175 deletions(-)
> > 
> 
> This patch changes many different components.  It would be much easier to
> review, and might get more attention from the other ext4 and f2fs developers, 
> if
> it were split into 3 patches:
> 
> a. Convert ext4 to use read_callbacks.
> b. Convert f2fs to use read_callbacks.
> c. Remove the functions from fs/crypto/ that became unused as a result of
>patches (a) and (b).  (Actually, this part probably should be merged with 
> the
>patch that removes the fscrypt_ctx, and the patch renamed to something like
>"fscrypt: remove decryption I/O path helpers")
> 
> Any reason why this wouldn't work?  AFAICS, you couldn't do it only because 
> you
> made this patch change fscrypt_enqueue_decrypt_work() to be responsible for
> initializing the work function.  But as per my comments on patch 1, I don't
> think we should do that, since it would make much more sense to put the work
> function in read_callbacks.c.

Yes, you are right about that. I will make the changes suggested by you.

> 
> However, since you're converting ext4 to use mpage_readpages() anyway, I don't
> think we should bother with the intermediate change to ext4_mpage_readpages().
> It's useless, and that intermediate state of the ext4 code inevitably won't 
> get
> tested very well.  So perhaps order the whole series as:
> 
> - fs: introduce read_callbacks
> - fs/mpage.c: add decryption support via read_callbacks
> - fs/buffer.c: add decryption support via read_callbacks
> - f2fs: convert to use read_callbacks
> - ext4: convert to use mpage_readpages[s]
> - ext4: support encryption with subpage-sized blocks
> - fscrypt: remove decryption I/O path helpers
> 
> That order would also give the flexibility to possibly apply the fs/ changes
> first, without having to update both ext4 and f2fs simultaneously with them.
> 
> > @@ -557,8 +511,7 @@ static struct bio *f2fs_grab_read_bio(struct inode 
> > *inode, block_t blkaddr,
> >  {
> > struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> > struct bio *bio;
> > -   struct bio_post_read_ctx *ctx;
> > -   unsigned int post_read_steps = 0;
> > +   int ret;
> 
> Nit: 'err' rather than 'ret', since this is 0 or a -errno value.
> 
> > -int __init f2fs_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;
> > -}
> > -
> > -void __exit f2fs_destroy_post_read_processing(void)
> > -{
> > -   mempool_destroy(bio_post_read_ctx_pool);
> > -   kmem_cache_destroy(bio_post_read_ctx_cache);
> > -}
> 
> Need to remove the declarations of these functions from fs/f2fs/f2fs.h to.
> 
> > diff --git a/fs/read_callbacks.c b/fs/read_callbacks.c
> > index a4196e3de05f..4b7fc2a349cd 100644
> > --- a/fs/read_callbacks.c
> > +++ b/fs/read_callbacks.c
> > @@ -76,7 +76,6 @@ void read_callbacks(struct read_callbacks_ctx *ctx)
> > switch (++ctx->cur_step) {
> > case STEP_DECRYPT:
> > if (ctx->enabled_steps & (1 << STEP_DECRYPT)) {
> > -   INIT_WORK(>work, fscrypt_decrypt_work);
> > fscrypt_enqueue_decrypt_work(>work);
> > return;
> > }
> 
> Again, I think the work initialization should remain here as:
> 
>   INIT_WORK(>work, decrypt_work);
> 
> rather than moving it to fs/crypto/.
> 
> Thanks!
> 
> - Eric
> 


-- 
chandan





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


Re: [f2fs-dev] [PATCH V3 4/7] fs/mpage.c: Integrate read callbacks

2019-06-25 Thread Chandan Rajendra
On Saturday, June 22, 2019 2:44:55 AM IST Eric Biggers wrote:
> On Sun, Jun 16, 2019 at 09:38:10PM +0530, Chandan Rajendra wrote:
> > This commit adds code to make do_mpage_readpage() to be "read callbacks"
> > aware i.e. for files requiring decryption, do_mpage_readpage() now
> > sets up the read callbacks state machine when allocating a bio and later
> > starts execution of the state machine after file data is read from the
> > underlying disk.
> > 
> > Signed-off-by: Chandan Rajendra 
> > ---
> >  fs/mpage.c | 11 ++-
> >  1 file changed, 10 insertions(+), 1 deletion(-)
> > 
> > diff --git a/fs/mpage.c b/fs/mpage.c
> > index 436a85260394..611ad122fc92 100644
> > --- a/fs/mpage.c
> > +++ b/fs/mpage.c
> > @@ -30,6 +30,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include "internal.h"
> >  
> >  /*
> > @@ -49,6 +50,8 @@ static void mpage_end_io(struct bio *bio)
> > struct bio_vec *bv;
> > struct bvec_iter_all iter_all;
> >  
> > +   if (read_callbacks_end_bio(bio))
> > +   return;
> > bio_for_each_segment_all(bv, bio, iter_all) {
> > struct page *page = bv->bv_page;
> > page_endio(page, bio_op(bio),
> > @@ -309,6 +312,12 @@ static struct bio *do_mpage_readpage(struct 
> > mpage_readpage_args *args)
> > gfp);
> > if (args->bio == NULL)
> > goto confused;
> > +
> > +   if (read_callbacks_setup(inode, args->bio, NULL)) {
> > +   bio_put(args->bio);
> > +   args->bio = NULL;
> > +   goto confused;
> > +   }
> > }
> >  
> > length = first_hole << blkbits;
> > @@ -330,7 +339,7 @@ static struct bio *do_mpage_readpage(struct 
> > mpage_readpage_args *args)
> >  confused:
> > if (args->bio)
> > args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
> > -   if (!PageUptodate(page))
> > +   if (!PageUptodate(page) && !PageError(page))
> > block_read_full_page(page, args->get_block);
> > else
> > unlock_page(page);
> 
> Why is the !PageError() check needed here?
> 

Sorry, Its a remnant from when I was debugging the patchset. I will remove
this.

-- 
chandan





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


Re: [f2fs-dev] [PATCH V3 6/7] Add decryption support for sub-pagesized blocks

2019-06-25 Thread Chandan Rajendra
On Saturday, June 22, 2019 2:59:17 AM IST Eric Biggers wrote:
> On Sun, Jun 16, 2019 at 09:38:12PM +0530, Chandan Rajendra wrote:
> > To support decryption of sub-pagesized blocks this commit adds code to,
> > 1. Track buffer head in "struct read_callbacks_ctx".
> > 2. Pass buffer head argument to all read callbacks.
> > 3. Add new fscrypt helper to decrypt the file data referred to by a
> >buffer head.
> > 
> > Signed-off-by: Chandan Rajendra 
> > ---
> >  fs/buffer.c|  55 +--
> >  fs/crypto/bio.c|  21 +-
> >  fs/f2fs/data.c |   2 +-
> >  fs/mpage.c |   2 +-
> >  fs/read_callbacks.c| 118 +
> >  include/linux/buffer_head.h|   1 +
> >  include/linux/read_callbacks.h |  13 +++-
> >  7 files changed, 158 insertions(+), 54 deletions(-)
> > 
> 
> This is another patch that unnecessarily changes way too many components at
> once.  My suggestions elsewhere would resolve this, though:
> 
> - This patch changes fs/f2fs/data.c and fs/mpage.c only to pass a NULL
>   buffer_head to read_callbacks_setup().  But as per my comments on patch 1,
>   read_callbacks_setup() should be split into read_callbacks_setup_bio() and
>   read_callbacks_end_bh().
> 
> - This patch changes fs/crypto/ only to add support for the buffer_head
>   decryption work.  But as per my comments on patch 1, that should be in
>   read_callbacks.c instead.
> 
> And adding buffer_head support to fs/read_callbacks.c should be its own patch,
> *or* should simply be folded into the patch that adds fs/read_callbacks.c.
> 
> Then the only thing remaining in this patch would be updating fs/buffer.c to
> make it use the read_callbacks, which should be retitled to something like
> "fs/buffer.c: add decryption support via read_callbacks".
> 

I agree.

-- 
chandan





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


Re: [f2fs-dev] [PATCH V3 1/7] FS: Introduce read callbacks

2019-06-25 Thread Chandan Rajendra
On Saturday, June 22, 2019 1:33:57 AM IST Eric Biggers wrote:
> Hi Chandan,
> 
> On Sun, Jun 16, 2019 at 09:38:07PM +0530, Chandan Rajendra wrote:
> > Read callbacks implements a state machine to be executed after a
> > buffered read I/O is completed. They help in further processing the file
> > data read from the backing store. Currently, decryption is the only post
> > processing step to be supported.
> > 
> > The execution of the state machine is to be initiated by the endio
> > function associated with the read operation.
> > 
> > Signed-off-by: Chandan Rajendra 
> > ---
> >  fs/Kconfig |   3 +
> >  fs/Makefile|   2 +
> >  fs/crypto/Kconfig  |   1 +
> >  fs/crypto/bio.c|  11 +++
> >  fs/read_callbacks.c| 174 +
> >  include/linux/fscrypt.h|   5 +
> >  include/linux/read_callbacks.h |  38 +++
> >  7 files changed, 234 insertions(+)
> >  create mode 100644 fs/read_callbacks.c
> >  create mode 100644 include/linux/read_callbacks.h
> > 
> > diff --git a/fs/Kconfig b/fs/Kconfig
> > index f1046cf6ad85..d869859c88da 100644
> > --- a/fs/Kconfig
> > +++ b/fs/Kconfig
> > @@ -21,6 +21,9 @@ if BLOCK
> >  config FS_IOMAP
> > bool
> >  
> > +config FS_READ_CALLBACKS
> > +   bool
> 
> This should be intended with a tab, not spaces.
> 
> > +
> >  source "fs/ext2/Kconfig"
> >  source "fs/ext4/Kconfig"
> >  source "fs/jbd2/Kconfig"
> > diff --git a/fs/Makefile b/fs/Makefile
> > index c9aea23aba56..a1a06f0db5c1 100644
> > --- a/fs/Makefile
> > +++ b/fs/Makefile
> > @@ -21,6 +21,8 @@ else
> >  obj-y +=   no-block.o
> >  endif
> >  
> > +obj-$(CONFIG_FS_READ_CALLBACKS) += read_callbacks.o
> > +
> >  obj-$(CONFIG_PROC_FS) += proc_namespace.o
> 
> Nit: maybe move this to just below the line for iomap.o, to be consistent with
> where FS_READ_CALLBACKS is in the Kconfig file.
> 
> >  
> >  obj-y  += notify/
> > diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
> > index 24ed99e2eca0..7752f9964280 100644
> > --- a/fs/crypto/Kconfig
> > +++ b/fs/crypto/Kconfig
> > @@ -9,6 +9,7 @@ config FS_ENCRYPTION
> > select CRYPTO_CTS
> > select CRYPTO_SHA256
> > select KEYS
> > +   select FS_READ_CALLBACKS if BLOCK
> > help
> >   Enable encryption of files and directories.  This
> >   feature is similar to ecryptfs, but it is more memory
> > diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
> > index 82da2510721f..f677ff93d464 100644
> > --- a/fs/crypto/bio.c
> > +++ b/fs/crypto/bio.c
> > @@ -24,6 +24,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include "fscrypt_private.h"
> >  
> >  static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
> > @@ -68,6 +69,16 @@ void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx 
> > *ctx, struct bio *bio)
> >  }
> >  EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
> >  
> > +void fscrypt_decrypt_work(struct work_struct *work)
> > +{
> > +   struct read_callbacks_ctx *ctx =
> > +   container_of(work, struct read_callbacks_ctx, work);
> > +
> > +   fscrypt_decrypt_bio(ctx->bio);
> > +
> > +   read_callbacks(ctx);
> > +}
> > +
> 
> This seems like a layering violation, since it means that read_callbacks.c 
> calls
> fs/crypto/ *and* fs/crypto/ calls read_callbacks.c.  I don't think fs/crypto/
> should be aware of read_callbacks at all.  Instead we should have a clear
> ordering between the components: the filesystem uses read_callbacks.c and
> fs/crypto/, and read_callbacks.c uses fs/crypto/.  So how about:
> 
> - Move fscrypt_decrypt_work(), fscrypt_decrypt_bh(), and fscrypt_decrypt_bio()
>   into fs/read_callbacks.c and remove the "fscrypt_" prefix from them.
> 
> - Instead of selecting FS_READ_CALLBACKS from FS_ENCRYPTION, select it from
>   EXT4_FS and F2FS_FS (if FS_ENCRYPTION).  I.e., it's really the *filesystems*
>   themselves that use read_callbacks, not fs/crypto/.
> 
> - Move the definition of read_callbacks_ctx into fs/read_callbacks.c, and make
>   read_callbacks() static, so these are private to the read_callbacks 
> component.
> 
> >  int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
> > sector_t pblk, unsigned int len)
> >  {
> > diff --git a/fs/read_callbacks

Re: [f2fs-dev] [PATCH V2 12/13] fscrypt_zeroout_range: Encrypt all zeroed out blocks of a page

2019-05-01 Thread Chandan Rajendra
On Tuesday, April 30, 2019 10:21:15 PM IST Eric Biggers wrote:
> On Sun, Apr 28, 2019 at 10:01:20AM +0530, Chandan Rajendra wrote:
> > For subpage-sized blocks, this commit adds code to encrypt all zeroed
> > out blocks mapped by a page.
> > 
> > Signed-off-by: Chandan Rajendra 
> > ---
> >  fs/crypto/bio.c | 40 ++--
> >  1 file changed, 18 insertions(+), 22 deletions(-)
> > 
> > diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
> > index 856f4694902d..46dd2ec50c7d 100644
> > --- a/fs/crypto/bio.c
> > +++ b/fs/crypto/bio.c
> > @@ -108,29 +108,23 @@ EXPORT_SYMBOL(fscrypt_pullback_bio_page);
> >  int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
> > sector_t pblk, unsigned int len)
> >  {
> > -   struct fscrypt_ctx *ctx;
> > struct page *ciphertext_page = NULL;
> > struct bio *bio;
> > +   u64 total_bytes, page_bytes;
> 
> page_bytes should be 'unsigned int', since it's <= PAGE_SIZE.
> 
> > int ret, err = 0;
> >  
> > -   BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE);
> > -
> > -   ctx = fscrypt_get_ctx(inode, GFP_NOFS);
> > -   if (IS_ERR(ctx))
> > -   return PTR_ERR(ctx);
> > +   total_bytes = len << inode->i_blkbits;
> 
> Should cast len to 'u64' here, in case it's greater than UINT_MAX / blocksize.
> 
> >  
> > -   ciphertext_page = fscrypt_alloc_bounce_page(ctx, GFP_NOWAIT);
> > -   if (IS_ERR(ciphertext_page)) {
> > -   err = PTR_ERR(ciphertext_page);
> > -   goto errout;
> > -   }
> > +   while (total_bytes) {
> > +   page_bytes = min_t(u64, total_bytes, PAGE_SIZE);
> >  
> > -   while (len--) {
> > -   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk,
> > -ZERO_PAGE(0), ciphertext_page,
> > -PAGE_SIZE, 0, GFP_NOFS);
> > -   if (err)
> > +   ciphertext_page = fscrypt_encrypt_page(inode, ZERO_PAGE(0),
> > +   page_bytes, 0, lblk, GFP_NOFS);
> > +   if (IS_ERR(ciphertext_page)) {
> > +   err = PTR_ERR(ciphertext_page);
> > +   ciphertext_page = NULL;
> > goto errout;
> > +   }
> 
> 'ciphertext_page' is leaked after each loop iteration.  Did you mean to free 
> it,
> or did you mean to reuse it for subsequent iterations?

Thanks for pointing this out. I actually meant to free it. I will see if I can
reuse ciphertext_page in my next patchset rather than freeing and allocating
it each time the loop is executed.

> 
> >  
> > bio = bio_alloc(GFP_NOWAIT, 1);
> > if (!bio) {
> > @@ -141,9 +135,8 @@ int fscrypt_zeroout_range(const struct inode *inode, 
> > pgoff_t lblk,
> > bio->bi_iter.bi_sector =
> > pblk << (inode->i_sb->s_blocksize_bits - 9);
> 
> This line uses ->s_blocksize_bits, but your new code uses ->i_blkbits.  AFAIK
> they'll always be the same, but please pick one or the other to use.

I will fix this.

> 
> > bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
> > -   ret = bio_add_page(bio, ciphertext_page,
> > -   inode->i_sb->s_blocksize, 0);
> > -   if (ret != inode->i_sb->s_blocksize) {
> > +   ret = bio_add_page(bio, ciphertext_page, page_bytes, 0);
> > +   if (ret != page_bytes) {
> > /* should never happen! */
> > WARN_ON(1);
> > bio_put(bio);
> > @@ -156,12 +149,15 @@ int fscrypt_zeroout_range(const struct inode *inode, 
> > pgoff_t lblk,
> > bio_put(bio);
> > if (err)
> > goto errout;
> > -   lblk++;
> > -   pblk++;
> > +
> > +   lblk += page_bytes >> inode->i_blkbits;
> > +   pblk += page_bytes >> inode->i_blkbits;
> > +   total_bytes -= page_bytes;
> > }
> > err = 0;
> >  errout:
> > -   fscrypt_release_ctx(ctx);
> > +   if (!IS_ERR_OR_NULL(ciphertext_page))
> > +   fscrypt_restore_control_page(ciphertext_page);
> > return err;
> >  }
> >  EXPORT_SYMBOL(fscrypt_zeroout_range);
> 
> 


-- 
chandan





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


Re: [f2fs-dev] [PATCH V2 02/13] Consolidate "read callbacks" into a new file

2019-05-01 Thread Chandan Rajendra
On Tuesday, April 30, 2019 7:07:28 AM IST Chao Yu wrote:
> On 2019/4/28 12:31, Chandan Rajendra wrote:
> > The "read callbacks" code is used by both Ext4 and F2FS. Hence to
> > remove duplicity, this commit moves the code into
> > include/linux/read_callbacks.h and fs/read_callbacks.c.
> > 
> > The corresponding decrypt and verity "work" functions have been moved
> > inside fscrypt and fsverity sources. With these in place, the read
> > callbacks code now has to just invoke enqueue functions provided by
> > fscrypt and fsverity.
> > 
> > Signed-off-by: Chandan Rajendra 
> > ---
> >  fs/Kconfig |   4 +
> >  fs/Makefile|   4 +
> >  fs/crypto/Kconfig  |   1 +
> >  fs/crypto/bio.c|  23 ++---
> >  fs/crypto/crypto.c |  17 +--
> >  fs/crypto/fscrypt_private.h|   3 +
> >  fs/ext4/ext4.h |   2 -
> >  fs/ext4/readpage.c | 183 +
> >  fs/ext4/super.c|   9 +-
> >  fs/f2fs/data.c | 148 --
> >  fs/f2fs/super.c|   9 +-
> >  fs/read_callbacks.c| 136 
> >  fs/verity/Kconfig  |   1 +
> >  fs/verity/verify.c |  12 +++
> >  include/linux/fscrypt.h|  20 +---
> >  include/linux/read_callbacks.h |  21 
> >  16 files changed, 251 insertions(+), 342 deletions(-)
> >  create mode 100644 fs/read_callbacks.c
> >  create mode 100644 include/linux/read_callbacks.h
> > 
> > diff --git a/fs/Kconfig b/fs/Kconfig
> > index 97f9eb8df713..03084f2dbeaf 100644
> > --- a/fs/Kconfig
> > +++ b/fs/Kconfig
> > @@ -308,6 +308,10 @@ config NFS_COMMON
> > depends on NFSD || NFS_FS || LOCKD
> > default y
> >  
> > +config FS_READ_CALLBACKS
> > +   bool
> > +   default n
> > +
> >  source "net/sunrpc/Kconfig"
> >  source "fs/ceph/Kconfig"
> >  source "fs/cifs/Kconfig"
> > diff --git a/fs/Makefile b/fs/Makefile
> > index 9dd2186e74b5..e0c0fce8cf40 100644
> > --- a/fs/Makefile
> > +++ b/fs/Makefile
> > @@ -21,6 +21,10 @@ else
> >  obj-y +=   no-block.o
> >  endif
> >  
> > +ifeq ($(CONFIG_FS_READ_CALLBACKS),y)
> > +obj-y +=   read_callbacks.o
> > +endif
> > +
> >  obj-$(CONFIG_PROC_FS) += proc_namespace.o
> >  
> >  obj-y  += notify/
> > diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
> > index f0de238000c0..163c328bcbd4 100644
> > --- a/fs/crypto/Kconfig
> > +++ b/fs/crypto/Kconfig
> > @@ -8,6 +8,7 @@ config FS_ENCRYPTION
> > select CRYPTO_CTS
> > select CRYPTO_SHA256
> > select KEYS
> > +   select FS_READ_CALLBACKS
> > help
> >   Enable encryption of files and directories.  This
> >   feature is similar to ecryptfs, but it is more memory
> > diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
> > index 5759bcd018cd..27f5618174f2 100644
> > --- a/fs/crypto/bio.c
> > +++ b/fs/crypto/bio.c
> > @@ -24,6 +24,8 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> > +
> >  #include "fscrypt_private.h"
> >  
> >  static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
> > @@ -54,24 +56,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 read_callbacks_ctx *ctx =
> > +   container_of(work, struct read_callbacks_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(>r.work, completion_pages);
> > -   ctx->r.bio = bio;
> > -   fscrypt_enqueue_decrypt_work(>r.work);
> > +   read_callbacks(ctx);
> >  }
> > -EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
> >  
> >  void fscrypt_pullback_bio_page(struct page **page, bool restore)
> >  {
> > @@ -87,7 +80,7 @@ void fscrypt_pullback_bio_page(st

Re: [f2fs-dev] [PATCH V2 02/13] Consolidate "read callbacks" into a new file

2019-05-01 Thread Chandan Rajendra
On Tuesday, April 30, 2019 5:30:28 AM IST Eric Biggers wrote:
> Hi Chandan,
> 
> On Sun, Apr 28, 2019 at 10:01:10AM +0530, Chandan Rajendra wrote:
> > The "read callbacks" code is used by both Ext4 and F2FS. Hence to
> > remove duplicity, this commit moves the code into
> > include/linux/read_callbacks.h and fs/read_callbacks.c.
> > 
> > The corresponding decrypt and verity "work" functions have been moved
> > inside fscrypt and fsverity sources. With these in place, the read
> > callbacks code now has to just invoke enqueue functions provided by
> > fscrypt and fsverity.
> > 
> > Signed-off-by: Chandan Rajendra 
> > ---
> >  fs/Kconfig |   4 +
> >  fs/Makefile|   4 +
> >  fs/crypto/Kconfig  |   1 +
> >  fs/crypto/bio.c|  23 ++---
> >  fs/crypto/crypto.c |  17 +--
> >  fs/crypto/fscrypt_private.h|   3 +
> >  fs/ext4/ext4.h |   2 -
> >  fs/ext4/readpage.c | 183 +
> >  fs/ext4/super.c|   9 +-
> >  fs/f2fs/data.c | 148 --
> >  fs/f2fs/super.c|   9 +-
> >  fs/read_callbacks.c| 136 
> >  fs/verity/Kconfig  |   1 +
> >  fs/verity/verify.c |  12 +++
> >  include/linux/fscrypt.h|  20 +---
> >  include/linux/read_callbacks.h |  21 
> >  16 files changed, 251 insertions(+), 342 deletions(-)
> >  create mode 100644 fs/read_callbacks.c
> >  create mode 100644 include/linux/read_callbacks.h
> > 
> 
> For easier review, can you split this into multiple patches?  Ideally the ext4
> and f2fs patches would be separate, but if that's truly not possible due to
> interdependencies it seems you could at least do:
> 
> 1. Introduce the read_callbacks.
> 2. Convert encryption to use the read_callbacks.
> 3. Remove union from struct fscrypt_context.
> 
> Also: just FYI, fs-verity isn't upstream yet, and in the past few months I
> haven't had much time to work on it.  So you might consider arranging your
> series so that initially just fscrypt is supported.  That will be useful on 
> its
> own, for block_size < PAGE_SIZE support.  Then fsverity can be added later.
> 
> > diff --git a/fs/Kconfig b/fs/Kconfig
> > index 97f9eb8df713..03084f2dbeaf 100644
> > --- a/fs/Kconfig
> > +++ b/fs/Kconfig
> > @@ -308,6 +308,10 @@ config NFS_COMMON
> > depends on NFSD || NFS_FS || LOCKD
> > default y
> >  
> > +config FS_READ_CALLBACKS
> > +   bool
> > +   default n
> 
> 'default n' is unnecesary, since 'n' is already the default.
> 
> > +
> >  source "net/sunrpc/Kconfig"
> >  source "fs/ceph/Kconfig"
> >  source "fs/cifs/Kconfig"
> > diff --git a/fs/Makefile b/fs/Makefile
> > index 9dd2186e74b5..e0c0fce8cf40 100644
> > --- a/fs/Makefile
> > +++ b/fs/Makefile
> > @@ -21,6 +21,10 @@ else
> >  obj-y +=   no-block.o
> >  endif
> >  
> > +ifeq ($(CONFIG_FS_READ_CALLBACKS),y)
> > +obj-y +=   read_callbacks.o
> > +endif
> > +
> 
> This can be simplified to:
> 
> obj-$(CONFIG_FS_READ_CALLBACKS) += read_callbacks.o
> 
> > diff --git a/fs/read_callbacks.c b/fs/read_callbacks.c
> > new file mode 100644
> > index ..b6d5b95e67d7
> > --- /dev/null
> > +++ b/fs/read_callbacks.c
> > @@ -0,0 +1,136 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * This file tracks the state machine that needs to be executed after 
> > reading
> > + * data from files that are encrypted and/or have verity metadata 
> > associated
> > + * with them.
> > + */
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#define NUM_PREALLOC_POST_READ_CTXS128
> > +
> > +static struct kmem_cache *read_callbacks_ctx_cache;
> > +static mempool_t *read_callbacks_ctx_pool;
> > +
> > +/* Read callback state machine steps */
> > +enum read_callbacks_step {
> > +   STEP_INITIAL = 0,
> > +   STEP_DECRYPT,
> > +   STEP_VERITY,
> > +};
> > +
> > +void end_read_callbacks(struct bio *bio)
> > +{
> > +   struct page *page;
> > +   struct bio_vec *bv;
> > +   int i;
> > +   struct bvec_iter_all iter_all;
> > +
> > +   bio_for_each_segment_all(bv, bio, i, iter_all) {
> > +   page = b

Re: [f2fs-dev] [PATCH V2 07/13] Add decryption support for sub-pagesized blocks

2019-05-01 Thread Chandan Rajendra
Hi Eric,

On Tuesday, April 30, 2019 6:08:18 AM IST Eric Biggers wrote:
> On Sun, Apr 28, 2019 at 10:01:15AM +0530, Chandan Rajendra wrote:
> > To support decryption of sub-pagesized blocks this commit adds code to,
> > 1. Track buffer head in "struct read_callbacks_ctx".
> > 2. Pass buffer head argument to all read callbacks.
> > 3. In the corresponding endio, loop across all the blocks mapped by the
> >page, decrypting each block in turn.
> > 
> > Signed-off-by: Chandan Rajendra 
> > ---
> >  fs/buffer.c| 83 +-
> >  fs/crypto/bio.c| 50 +---
> >  fs/crypto/crypto.c | 19 +++-
> >  fs/f2fs/data.c |  2 +-
> >  fs/mpage.c |  2 +-
> >  fs/read_callbacks.c| 53 ++
> >  include/linux/buffer_head.h|  1 +
> >  include/linux/read_callbacks.h |  5 +-
> >  8 files changed, 154 insertions(+), 61 deletions(-)
> > 
> > diff --git a/fs/buffer.c b/fs/buffer.c
> > index ce357602f471..f324727e24bb 100644
> > --- a/fs/buffer.c
> > +++ b/fs/buffer.c
> > @@ -45,6 +45,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  
> >  static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
> > @@ -245,11 +246,7 @@ __find_get_block_slow(struct block_device *bdev, 
> > sector_t block)
> > return ret;
> >  }
> >  
> > -/*
> > - * I/O completion handler for block_read_full_page() - pages
> > - * which come unlocked at the end of I/O.
> > - */
> > -static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
> > +void end_buffer_page_read(struct buffer_head *bh)
> 
> I think __end_buffer_async_read() would be a better name, since the *page* 
> isn't
> necessarily done yet.
> 
> >  {
> > unsigned long flags;
> > struct buffer_head *first;
> > @@ -257,17 +254,7 @@ static void end_buffer_async_read(struct buffer_head 
> > *bh, int uptodate)
> > struct page *page;
> > int page_uptodate = 1;
> >  
> > -   BUG_ON(!buffer_async_read(bh));
> > -
> > page = bh->b_page;
> > -   if (uptodate) {
> > -   set_buffer_uptodate(bh);
> > -   } else {
> > -   clear_buffer_uptodate(bh);
> > -   buffer_io_error(bh, ", async page read");
> > -   SetPageError(page);
> > -   }
> > -
> > /*
> >  * Be _very_ careful from here on. Bad things can happen if
> >  * two buffer heads end IO at almost the same time and both
> > @@ -305,6 +292,44 @@ static void end_buffer_async_read(struct buffer_head 
> > *bh, int uptodate)
> > local_irq_restore(flags);
> > return;
> >  }
> > +EXPORT_SYMBOL(end_buffer_page_read);
> 
> No need for EXPORT_SYMBOL() here, as this is only called by built-in code.
> 
> > +
> > +/*
> > + * I/O completion handler for block_read_full_page() - pages
> > + * which come unlocked at the end of I/O.
> > + */
> 
> This comment is no longer correct.  Change to something like:
> 
> /*
>  * I/O completion handler for block_read_full_page().  Pages are unlocked 
> after
>  * the I/O completes and the read callbacks (if any) have executed.
>  */
> 
> > +static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
> > +{
> > +   struct page *page;
> > +
> > +   BUG_ON(!buffer_async_read(bh));
> > +
> > +#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
> > +   if (uptodate && bh->b_private) {
> > +   struct read_callbacks_ctx *ctx = bh->b_private;
> > +
> > +   read_callbacks(ctx);
> > +   return;
> > +   }
> > +
> > +   if (bh->b_private) {
> > +   struct read_callbacks_ctx *ctx = bh->b_private;
> > +
> > +   WARN_ON(uptodate);
> > +   put_read_callbacks_ctx(ctx);
> > +   }
> > +#endif
> 
> These details should be handled in read_callbacks code, not here.  AFAICS, all
> you need is a function read_callbacks_end_bh() that returns a bool indicating
> whether it handled the buffer_head or not:
> 
> static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
> {
>   BUG_ON(!buffer_async_read(bh));
> 
>   if (read_callbacks_end_bh(bh, uptodate))
>   return;
> 
>   page = bh->b_page;
>   ...
> }
> 
> Then read_callbacks_end_bh() 

Re: [f2fs-dev] [PATCH V2 02/13] Consolidate "read callbacks" into a new file

2019-05-01 Thread Chandan Rajendra
On Tuesday, April 30, 2019 11:35:08 PM IST Eric Biggers wrote:
> On Sun, Apr 28, 2019 at 10:01:10AM +0530, Chandan Rajendra wrote:
> > The "read callbacks" code is used by both Ext4 and F2FS. Hence to
> > remove duplicity, this commit moves the code into
> > include/linux/read_callbacks.h and fs/read_callbacks.c.
> > 
> > The corresponding decrypt and verity "work" functions have been moved
> > inside fscrypt and fsverity sources. With these in place, the read
> > callbacks code now has to just invoke enqueue functions provided by
> > fscrypt and fsverity.
> > 
> > Signed-off-by: Chandan Rajendra 
> > ---
> >  fs/Kconfig |   4 +
> >  fs/Makefile|   4 +
> >  fs/crypto/Kconfig  |   1 +
> >  fs/crypto/bio.c|  23 ++---
> >  fs/crypto/crypto.c |  17 +--
> >  fs/crypto/fscrypt_private.h|   3 +
> >  fs/ext4/ext4.h |   2 -
> >  fs/ext4/readpage.c | 183 +
> >  fs/ext4/super.c|   9 +-
> >  fs/f2fs/data.c | 148 --
> >  fs/f2fs/super.c|   9 +-
> >  fs/read_callbacks.c| 136 
> >  fs/verity/Kconfig  |   1 +
> >  fs/verity/verify.c |  12 +++
> >  include/linux/fscrypt.h|  20 +---
> >  include/linux/read_callbacks.h |  21 
> >  16 files changed, 251 insertions(+), 342 deletions(-)
> >  create mode 100644 fs/read_callbacks.c
> >  create mode 100644 include/linux/read_callbacks.h
> > 
> > diff --git a/fs/Kconfig b/fs/Kconfig
> > index 97f9eb8df713..03084f2dbeaf 100644
> > --- a/fs/Kconfig
> > +++ b/fs/Kconfig
> > @@ -308,6 +308,10 @@ config NFS_COMMON
> > depends on NFSD || NFS_FS || LOCKD
> > default y
> >  
> > +config FS_READ_CALLBACKS
> > +   bool
> > +   default n
> > +
> >  source "net/sunrpc/Kconfig"
> >  source "fs/ceph/Kconfig"
> >  source "fs/cifs/Kconfig"
> 
> This shouldn't be under the 'if NETWORK_FILESYSTEMS' block, since it has 
> nothing
> to do with network filesystems.  When trying to compile this I got:
> 
>   WARNING: unmet direct dependencies detected for FS_READ_CALLBACKS
> Depends on [n]: NETWORK_FILESYSTEMS [=n]
> Selected by [y]:
> - FS_ENCRYPTION [=y]
> - FS_VERITY [=y]
> 
> Perhaps put it just below FS_IOMAP?
> 
> > diff --git a/fs/Makefile b/fs/Makefile
> > index 9dd2186e74b5..e0c0fce8cf40 100644
> > --- a/fs/Makefile
> > +++ b/fs/Makefile
> > @@ -21,6 +21,10 @@ else
> >  obj-y +=   no-block.o
> >  endif
> >  
> > +ifeq ($(CONFIG_FS_READ_CALLBACKS),y)
> > +obj-y +=   read_callbacks.o
> > +endif
> > +
> >  obj-$(CONFIG_PROC_FS) += proc_namespace.o
> >  
> >  obj-y  += notify/
> > diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
> > index f0de238000c0..163c328bcbd4 100644
> > --- a/fs/crypto/Kconfig
> > +++ b/fs/crypto/Kconfig
> > @@ -8,6 +8,7 @@ config FS_ENCRYPTION
> > select CRYPTO_CTS
> > select CRYPTO_SHA256
> > select KEYS
> > +   select FS_READ_CALLBACKS
> > help
> >   Enable encryption of files and directories.  This
> >   feature is similar to ecryptfs, but it is more memory
> 
> This selection needs to be conditional on BLOCK.
> 
>   select FS_READ_CALLBACKS if BLOCK
> 
> Otherwise, building without BLOCK and with UBIFS encryption support fails.
> 
>   fs/read_callbacks.c: In function ‘end_read_callbacks’:
>   fs/read_callbacks.c:34:23: error: storage size of ‘iter_all’ isn’t known
> struct bvec_iter_all iter_all;
>  ^~~~
>   fs/read_callbacks.c:37:20: error: dereferencing pointer to incomplete 
> type ‘struct buffer_head’
>  if (!PageError(bh->b_page))
> 
>   [...]
>

I will fix this in the next version of this patchset.

-- 
chandan





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


Re: [f2fs-dev] [PATCH V2 03/13] fsverity: Add call back to decide if verity check has to be performed

2019-05-01 Thread Chandan Rajendra
On Wednesday, May 1, 2019 2:40:38 AM IST Jeremy Sowden wrote:
> On 2019-04-28, at 10:01:11 +0530, Chandan Rajendra wrote:
> > Ext4 and F2FS store verity metadata in data extents (beyond
> > inode->i_size) associated with a file. But other filesystems might
> > choose alternative means to store verity metadata. Hence this commit
> > adds a callback function pointer to 'struct fsverity_operations' to
> > help in deciding if verity operation needs to performed against a
> > page-cache page holding file data.
> > 
> > Signed-off-by: Chandan Rajendra 
> > ---
> >  fs/ext4/super.c  | 6 ++
> >  fs/f2fs/super.c  | 6 ++
> >  fs/read_callbacks.c  | 4 +++-
> >  include/linux/fsverity.h | 1 +
> >  4 files changed, 16 insertions(+), 1 deletion(-)
> > 
> > diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> > index aba724f82cc3..63d73b360f1d 100644
> > --- a/fs/ext4/super.c
> > +++ b/fs/ext4/super.c
> > @@ -1428,10 +1428,16 @@ static struct page 
> > *ext4_read_verity_metadata_page(struct inode *inode,
> > return read_mapping_page(inode->i_mapping, index, NULL);
> >  }
> >  
> > +static bool ext4_verity_required(struct inode *inode, pgoff_t index)
> > +{
> > +   return index < (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
> > +}
> > +
> >  static const struct fsverity_operations ext4_verityops = {
> > .set_verity = ext4_set_verity,
> > .get_metadata_end   = ext4_get_verity_metadata_end,
> > .read_metadata_page = ext4_read_verity_metadata_page,
> > +   .verity_required= ext4_verity_required,
> >  };
> >  #endif /* CONFIG_FS_VERITY */
> >  
> > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > index 2f75f06c784a..cd1299e1f92d 100644
> > --- a/fs/f2fs/super.c
> > +++ b/fs/f2fs/super.c
> > @@ -2257,10 +2257,16 @@ static struct page 
> > *f2fs_read_verity_metadata_page(struct inode *inode,
> > return read_mapping_page(inode->i_mapping, index, NULL);
> >  }
> >  
> > +static bool f2fs_verity_required(struct inode *inode, pgoff_t index)
> > +{
> > +   return index < (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
> > +}
> > +
> >  static const struct fsverity_operations f2fs_verityops = {
> > .set_verity = f2fs_set_verity,
> > .get_metadata_end   = f2fs_get_verity_metadata_end,
> > .read_metadata_page = f2fs_read_verity_metadata_page,
> > +   .verity_required= f2fs_verity_required,
> >  };
> >  #endif /* CONFIG_FS_VERITY */
> >  
> > diff --git a/fs/read_callbacks.c b/fs/read_callbacks.c
> > index b6d5b95e67d7..6dea54b0baa9 100644
> > --- a/fs/read_callbacks.c
> > +++ b/fs/read_callbacks.c
> > @@ -86,7 +86,9 @@ struct read_callbacks_ctx *get_read_callbacks_ctx(struct 
> > inode *inode,
> > read_callbacks_steps |= 1 << STEP_DECRYPT;
> >  #ifdef CONFIG_FS_VERITY
> > if (inode->i_verity_info != NULL &&
> > -   (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
> > +   ((inode->i_sb->s_vop->verity_required
> > +   && inode->i_sb->s_vop->verity_required(inode, index))
> > +   || (inode->i_sb->s_vop->verity_required == NULL)))
> 
> I think this is a bit easier to follow:
> 
>   (inode->i_sb->s_vop->verity_required == NULL || 
>   inode->i_sb->s_vop->verity_required(inode, index)))

Yes, you are right. I will implement the changes suggested by you.

-- 
chandan





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


Re: [f2fs-dev] [PATCH V2 11/13] ext4: Compute logical block and the page range to be encrypted

2019-05-01 Thread Chandan Rajendra
On Tuesday, April 30, 2019 10:31:51 PM IST Eric Biggers wrote:
> On Sun, Apr 28, 2019 at 10:01:19AM +0530, Chandan Rajendra wrote:
> > For subpage-sized blocks, the initial logical block number mapped by a
> > page can be different from page->index. Hence this commit adds code to
> > compute the first logical block mapped by the page and also the page
> > range to be encrypted.
> > 
> > Signed-off-by: Chandan Rajendra 
> > ---
> >  fs/ext4/page-io.c | 9 +++--
> >  1 file changed, 7 insertions(+), 2 deletions(-)
> > 
> > diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
> > index 3e9298e6a705..75485ee9e800 100644
> > --- a/fs/ext4/page-io.c
> > +++ b/fs/ext4/page-io.c
> > @@ -418,6 +418,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
> >  {
> > struct page *data_page = NULL;
> > struct inode *inode = page->mapping->host;
> > +   u64 page_blk;
> > unsigned block_start;
> > struct buffer_head *bh, *head;
> > int ret = 0;
> > @@ -478,10 +479,14 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
> >  
> > if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) {
> > gfp_t gfp_flags = GFP_NOFS;
> > +   unsigned int page_bytes;
> > +
> 
> page_blk should be declared here, just after page_bytes.
> 
> > +   page_bytes = round_up(len, i_blocksize(inode));
> > +   page_blk = page->index << (PAGE_SHIFT - inode->i_blkbits);
> 
> Although block numbers are 32-bit in ext4, if you're going to make 'page_blk' 
> a
> u64 anyway, then for consistency page->index should be cast to u64 here.
> 
> >  
> > retry_encrypt:
> > -   data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0,
> > -   page->index, gfp_flags);
> > +   data_page = fscrypt_encrypt_page(inode, page, page_bytes, 0,
> > +   page_blk, gfp_flags);
> > if (IS_ERR(data_page)) {
> > ret = PTR_ERR(data_page);
> > if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
> 
> 

I will implement the changes that have been suggested here.

-- 
chandan





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


Re: [f2fs-dev] [PATCH V2 10/13] fscrypt_encrypt_page: Loop across all blocks mapped by a page range

2019-05-01 Thread Chandan Rajendra
On Wednesday, May 1, 2019 4:38:41 AM IST Eric Biggers wrote:
> On Tue, Apr 30, 2019 at 10:11:35AM -0700, Eric Biggers wrote:
> > On Sun, Apr 28, 2019 at 10:01:18AM +0530, Chandan Rajendra wrote:
> > > For subpage-sized blocks, this commit now encrypts all blocks mapped by
> > > a page range.
> > > 
> > > Signed-off-by: Chandan Rajendra 
> > > ---
> > >  fs/crypto/crypto.c | 37 +
> > >  1 file changed, 25 insertions(+), 12 deletions(-)
> > > 
> > > diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
> > > index 4f0d832cae71..2d65b431563f 100644
> > > --- a/fs/crypto/crypto.c
> > > +++ b/fs/crypto/crypto.c
> > > @@ -242,18 +242,26 @@ struct page *fscrypt_encrypt_page(const struct 
> > > inode *inode,
> > 
> > Need to update the function comment to clearly explain what this function
> > actually does now.
> > 
> > >  {
> > >   struct fscrypt_ctx *ctx;
> > >   struct page *ciphertext_page = page;
> > > + int i, page_nr_blks;
> > >   int err;
> > >  
> > >   BUG_ON(len % FS_CRYPTO_BLOCK_SIZE != 0);
> > >  
> > 
> > Make a 'blocksize' variable so you don't have to keep calling i_blocksize().
> > 
> > Also, you need to check whether 'len' and 'offs' are 
> > filesystem-block-aligned,
> > since the code now assumes it.
> > 
> > const unsigned int blocksize = i_blocksize(inode);
> > 
> > if (!IS_ALIGNED(len | offs, blocksize))
> > return -EINVAL;
> > 
> > However, did you check whether that's always true for ubifs?  It looks like 
> > it
> > may expect to encrypt a prefix of a block, that is only padded to the next
> > 16-byte boundary.
> > 
> > > + page_nr_blks = len >> inode->i_blkbits;
> > > +
> > >   if (inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES) {
> > >   /* with inplace-encryption we just encrypt the page */
> > > - err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num, page,
> > > -  ciphertext_page, len, offs,
> > > -  gfp_flags);
> > > - if (err)
> > > - return ERR_PTR(err);
> > > -
> > > + for (i = 0; i < page_nr_blks; i++) {
> > > + err = fscrypt_do_page_crypto(inode, FS_ENCRYPT,
> > > + lblk_num, page,
> > > + ciphertext_page,
> > > + i_blocksize(inode), offs,
> > > + gfp_flags);
> > > + if (err)
> > > + return ERR_PTR(err);
> 
> Apparently ubifs does encrypt data shorter than the filesystem block size, so
> this part is wrong.
> 
> I suggest we split this into two functions, fscrypt_encrypt_block_inplace() 
> and
> fscrypt_encrypt_blocks(), so that it's conceptually simpler what each function
> does.  Currently this works completely differently depending on whether the
> filesystem set FS_CFLG_OWN_PAGES in its fscrypt_operations, which is weird.
> 
> I also noticed that using fscrypt_ctx for writes seems to be unnecessary.
> AFAICS, page_private(bounce_page) could point directly to the pagecache page.
> That would simplify things a lot, especially since then fscrypt_ctx could be
> removed entirely after you convert reads to use read_callbacks_ctx.
> 
> IMO, these would be worthwhile cleanups for fscrypt by themselves, without
> waiting for the read_callbacks stuff to be finalized.  Finalizing the
> read_callbacks stuff will probably require reaching a consensus about how they
> should work with future filesystem features like fsverity and compression.
> 
> So to move things forward, I'm considering sending out a series with the above
> cleanups for fscrypt, plus the equivalent of your patches:
> 
>   "fscrypt_encrypt_page: Loop across all blocks mapped by a page range"
>   "fscrypt_zeroout_range: Encrypt all zeroed out blocks of a page"
>   "Add decryption support for sub-pagesized blocks" (fs/crypto/ part only)
> 
> Then hopefully we can get all that applied for 5.3 so that fs/crypto/ itself 
> is
> ready for blocksize != PAGE_SIZE; and get your changes to 
> ext4_bio_write_page(),
> __ext4_block_zero_page_range(), and ext4_block_write_begin() applied too, so
> that ext4 is partially ready for encryption with blocksize != PAGE_SIZE.
> 
> Then only the read_callbacks stuff will remain, to get encryption support into
> fs/mpage.c and fs/buffer.c.  Do you think that's a good plan?

Hi Eric,

IMHO, I will continue posting the next version of the current patchset and if
there are no serious reservations from FS maintainers the "read callbacks"
patchset can be merged. In such a scenario, the cleanups being
non-complicated, can be merged later.

-- 
chandan





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


Re: [f2fs-dev] [PATCH V2 10/13] fscrypt_encrypt_page: Loop across all blocks mapped by a page range

2019-05-01 Thread Chandan Rajendra
On Thursday, May 2, 2019 3:59:01 AM IST Eric Biggers wrote:
> Hi Chandan,
> 
> On Wed, May 01, 2019 at 08:19:35PM +0530, Chandan Rajendra wrote:
> > On Wednesday, May 1, 2019 4:38:41 AM IST Eric Biggers wrote:
> > > On Tue, Apr 30, 2019 at 10:11:35AM -0700, Eric Biggers wrote:
> > > > On Sun, Apr 28, 2019 at 10:01:18AM +0530, Chandan Rajendra wrote:
> > > > > For subpage-sized blocks, this commit now encrypts all blocks mapped 
> > > > > by
> > > > > a page range.
> > > > > 
> > > > > Signed-off-by: Chandan Rajendra 
> > > > > ---
> > > > >  fs/crypto/crypto.c | 37 +
> > > > >  1 file changed, 25 insertions(+), 12 deletions(-)
> > > > > 
> > > > > diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
> > > > > index 4f0d832cae71..2d65b431563f 100644
> > > > > --- a/fs/crypto/crypto.c
> > > > > +++ b/fs/crypto/crypto.c
> > > > > @@ -242,18 +242,26 @@ struct page *fscrypt_encrypt_page(const struct 
> > > > > inode *inode,
> > > > 
> > > > Need to update the function comment to clearly explain what this 
> > > > function
> > > > actually does now.
> > > > 
> > > > >  {
> > > > >   struct fscrypt_ctx *ctx;
> > > > >   struct page *ciphertext_page = page;
> > > > > + int i, page_nr_blks;
> > > > >   int err;
> > > > >  
> > > > >   BUG_ON(len % FS_CRYPTO_BLOCK_SIZE != 0);
> > > > >  
> > > > 
> > > > Make a 'blocksize' variable so you don't have to keep calling 
> > > > i_blocksize().
> > > > 
> > > > Also, you need to check whether 'len' and 'offs' are 
> > > > filesystem-block-aligned,
> > > > since the code now assumes it.
> > > > 
> > > > const unsigned int blocksize = i_blocksize(inode);
> > > > 
> > > > if (!IS_ALIGNED(len | offs, blocksize))
> > > > return -EINVAL;
> > > > 
> > > > However, did you check whether that's always true for ubifs?  It looks 
> > > > like it
> > > > may expect to encrypt a prefix of a block, that is only padded to the 
> > > > next
> > > > 16-byte boundary.
> > > > 
> > > > > + page_nr_blks = len >> inode->i_blkbits;
> > > > > +
> > > > >   if (inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES) {
> > > > >   /* with inplace-encryption we just encrypt the page */
> > > > > - err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, 
> > > > > lblk_num, page,
> > > > > -  ciphertext_page, len, offs,
> > > > > -  gfp_flags);
> > > > > - if (err)
> > > > > - return ERR_PTR(err);
> > > > > -
> > > > > + for (i = 0; i < page_nr_blks; i++) {
> > > > > + err = fscrypt_do_page_crypto(inode, FS_ENCRYPT,
> > > > > + lblk_num, page,
> > > > > + ciphertext_page,
> > > > > + i_blocksize(inode), 
> > > > > offs,
> > > > > + gfp_flags);
> > > > > + if (err)
> > > > > + return ERR_PTR(err);
> > > 
> > > Apparently ubifs does encrypt data shorter than the filesystem block 
> > > size, so
> > > this part is wrong.
> > > 
> > > I suggest we split this into two functions, 
> > > fscrypt_encrypt_block_inplace() and
> > > fscrypt_encrypt_blocks(), so that it's conceptually simpler what each 
> > > function
> > > does.  Currently this works completely differently depending on whether 
> > > the
> > > filesystem set FS_CFLG_OWN_PAGES in its fscrypt_operations, which is 
> > > weird.
> > > 
> > > I also noticed that using fscrypt_ctx for writes seems to be unnecessary.
> > > AFAICS, page_private(bounce_page) could point directly to the pagecache 
> > > page.
> > > That would simplify thing

Re: [f2fs-dev] [PATCH 08/13] fscrypt: introduce fscrypt_decrypt_block_inplace()

2019-05-06 Thread Chandan Rajendra
On Thursday, May 2, 2019 4:15:10 AM IST Eric Biggers wrote:
> From: Eric Biggers 
> 
> fscrypt_decrypt_page() behaves very differently depending on whether the
> filesystem set FS_CFLG_OWN_PAGES in its fscrypt_operations.  This makes
> the function difficult to understand and document.  It also makes it so
> that all callers have to provide inode and lblk_num, when fscrypt could
> determine these itself for pagecache pages.
> 
> Therefore, move the FS_CFLG_OWN_PAGES behavior into a new function
> fscrypt_decrypt_block_inplace().
>

Looks good to me,

Reviewed-by: Chandan Rajendra 

-- 
chandan





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


Re: [f2fs-dev] [PATCH 07/13] fscrypt: handle blocksize < PAGE_SIZE in fscrypt_zeroout_range()

2019-05-06 Thread Chandan Rajendra
On Thursday, May 2, 2019 4:15:09 AM IST Eric Biggers wrote:
> From: Eric Biggers 
> 
> Adjust fscrypt_zeroout_range() to encrypt a block at a time rather than
> a page at a time, so that it works when blocksize < PAGE_SIZE.
> 
> This isn't optimized for performance, but then again this function
> already wasn't optimized for performance.  As a future optimization, we
> could submit much larger bios here.
> 
> This is in preparation for allowing encryption on ext4 filesystems with
> blocksize != PAGE_SIZE.
> 
> This is based on work by Chandan Rajendra.


Looks good to me,

Reviewed-by: Chandan Rajendra 

-- 
chandan





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


Re: [f2fs-dev] [PATCH 13/13] ext4: encrypt only up to last block in ext4_bio_write_page()

2019-05-06 Thread Chandan Rajendra
On Thursday, May 2, 2019 4:15:15 AM IST Eric Biggers wrote:
> From: Eric Biggers 
> 
> As an optimization, don't encrypt blocks fully beyond i_size, since
> those definitely won't need to be written out.  Also add a comment.
> 
> This is in preparation for allowing encryption on ext4 filesystems with
> blocksize != PAGE_SIZE.
> 
> This is based on work by Chandan Rajendra.
>

Looks good to me,

Reviewed-by: Chandan Rajendra 

-- 
chandan





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


Re: [f2fs-dev] [PATCH 09/13] fscrypt: support decrypting multiple filesystem blocks per page

2019-05-06 Thread Chandan Rajendra
On Thursday, May 2, 2019 4:15:11 AM IST Eric Biggers wrote:
> From: Eric Biggers 
> 
> Rename fscrypt_decrypt_page() to fscrypt_decrypt_pagecache_blocks() and
> redefine its behavior to decrypt all filesystem blocks in the given
> region of the given page, rather than assuming that the region consists
> of just one filesystem block.  Also remove the 'inode' and 'lblk_num'
> parameters, since they can be retrieved from the page as it's already
> assumed to be a pagecache page.
> 
> This is in preparation for allowing encryption on ext4 filesystems with
> blocksize != PAGE_SIZE.
> 
> This is based on work by Chandan Rajendra.

Looks good to me,

Reviewed-by: Chandan Rajendra 

-- 
chandan





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


Re: [f2fs-dev] [PATCH 05/13] fscrypt: introduce fscrypt_encrypt_block_inplace()

2019-05-06 Thread Chandan Rajendra
On Thursday, May 2, 2019 4:15:07 AM IST Eric Biggers wrote:
> From: Eric Biggers 
> 
> fscrypt_encrypt_page() behaves very differently depending on whether the
> filesystem set FS_CFLG_OWN_PAGES in its fscrypt_operations.  This makes
> the function difficult to understand and document.  It also makes it so
> that all callers have to provide inode and lblk_num, when fscrypt could
> determine these itself for pagecache pages.
> 
> Therefore, move the FS_CFLG_OWN_PAGES behavior into a new function
> fscrypt_encrypt_block_inplace().

Looks good to me,

Reviewed-by: Chandan Rajendra 

-- 
chandan





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


Re: [f2fs-dev] [PATCH 06/13] fscrypt: support encrypting multiple filesystem blocks per page

2019-05-06 Thread Chandan Rajendra
On Thursday, May 2, 2019 4:15:08 AM IST Eric Biggers wrote:
> From: Eric Biggers 
> 
> Rename fscrypt_encrypt_page() to fscrypt_encrypt_pagecache_blocks() and
> redefine its behavior to encrypt all filesystem blocks from the given
> region of the given page, rather than assuming that the region consists
> of just one filesystem block.  Also remove the 'inode' and 'lblk_num'
> parameters, since they can be retrieved from the page as it's already
> assumed to be a pagecache page.
> 
> This is in preparation for allowing encryption on ext4 filesystems with
> blocksize != PAGE_SIZE.
> 
> This is based on work by Chandan Rajendra.

Looks good to me,

Reviewed-by: Chandan Rajendra 

-- 
chandan





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


Re: [f2fs-dev] [PATCH 04/13] fscrypt: clean up some BUG_ON()s in block encryption/decryption

2019-05-06 Thread Chandan Rajendra
On Thursday, May 2, 2019 4:15:06 AM IST Eric Biggers wrote:
> From: Eric Biggers 
> 
> Replace some BUG_ON()s with WARN_ON_ONCE() and returning an error code,
> and move the check for len divisible by FS_CRYPTO_BLOCK_SIZE into
> fscrypt_crypt_block() so that it's done for both encryption and
> decryption, not just encryption.

Looks good to me,

Reviewed-by: Chandan Rajendra 

-- 
chandan





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


Re: [f2fs-dev] [PATCH 02/13] fscrypt: remove the "write" part of struct fscrypt_ctx

2019-05-02 Thread Chandan Rajendra
On Thursday, May 2, 2019 4:15:04 AM IST Eric Biggers wrote:
> From: Eric Biggers 
> 
> Now that fscrypt_ctx is not used for writes, remove the 'w' fields.
>

Looks good to me,

Reviewed-by: Chandan Rajendra 

-- 
chandan





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


Re: [f2fs-dev] [PATCH 01/13] fscrypt: simplify bounce page handling

2019-05-02 Thread Chandan Rajendra
On Thursday, May 2, 2019 4:15:03 AM IST Eric Biggers wrote:
> From: Eric Biggers 
> 
> Currently, bounce page handling for writes to encrypted files is
> unnecessarily complicated.  A fscrypt_ctx is allocated along with each
> bounce page, page_private(bounce_page) points to this fscrypt_ctx, and
> fscrypt_ctx::w::control_page points to the original pagecache page.
> 
> However, because writes don't use the fscrypt_ctx for anything else,
> there's no reason why page_private(bounce_page) can't just point to the
> original pagecache page directly.
> 
> Therefore, this patch makes this change.  In the process, it also cleans
> up the API exposed to filesystems that allows testing whether a page is
> a bounce page, getting the pagecache page from a bounce page, and
> freeing a bounce page.

Looks good to me,

Reviewed-by: Chandan Rajendra 

-- 
chandan





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


Re: [f2fs-dev] [PATCH 03/13] fscrypt: rename fscrypt_do_page_crypto() to fscrypt_crypt_block()

2019-05-02 Thread Chandan Rajendra
On Thursday, May 2, 2019 4:15:05 AM IST Eric Biggers wrote:
> From: Eric Biggers 
> 
> fscrypt_do_page_crypto() only does a single encryption or decryption
> operation, with a single logical block number (single IV).  So it
> actually operates on a filesystem block, not a "page" per se.  To
> reflect this, rename it to fscrypt_crypt_block().
>

Looks good to me,

Reviewed-by: Chandan Rajendra 

-- 
chandan





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


[f2fs-dev] [PATCH V2 06/13] ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]

2019-04-27 Thread Chandan Rajendra
Now that do_mpage_readpage() is "post read process" aware, this commit
gets ext4_readpage[s] to use mpage_readpage[s] and deletes ext4's
readpage.c since the associated functionality is not required anymore.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/Makefile   |   2 +-
 fs/ext4/inode.c|   5 +-
 fs/ext4/readpage.c | 314 -
 3 files changed, 3 insertions(+), 318 deletions(-)
 delete mode 100644 fs/ext4/readpage.c

diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 8fdfcd3c3e04..7c38803a808d 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
 ext4-y := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \
indirect.o inline.o inode.o ioctl.o mballoc.o migrate.o \
-   mmp.o move_extent.o namei.o page-io.o readpage.o resize.o \
+   mmp.o move_extent.o namei.o page-io.o resize.o \
super.o symlink.o sysfs.o xattr.o xattr_trusted.o xattr_user.o
 
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)   += acl.o
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 05b258db8673..1327e04334df 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3353,8 +3353,7 @@ static int ext4_readpage(struct file *file, struct page 
*page)
ret = ext4_readpage_inline(inode, page);
 
if (ret == -EAGAIN)
-   return ext4_mpage_readpages(page->mapping, NULL, page, 1,
-   false);
+   return mpage_readpage(page, ext4_get_block);
 
return ret;
 }
@@ -3369,7 +3368,7 @@ ext4_readpages(struct file *file, struct address_space 
*mapping,
if (ext4_has_inline_data(inode))
return 0;
 
-   return ext4_mpage_readpages(mapping, pages, NULL, nr_pages, true);
+   return mpage_readpages(mapping, pages, nr_pages, ext4_get_block);
 }
 
 static void ext4_invalidatepage(struct page *page, unsigned int offset,
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
deleted file mode 100644
index e363dededc21..
--- a/fs/ext4/readpage.c
+++ /dev/null
@@ -1,314 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/fs/ext4/readpage.c
- *
- * Copyright (C) 2002, Linus Torvalds.
- * Copyright (C) 2015, Google, Inc.
- *
- * This was originally taken from fs/mpage.c
- *
- * The intent is the ext4_mpage_readpages() function here is intended
- * to replace mpage_readpages() in the general case, not just for
- * encrypted files.  It has some limitations (see below), where it
- * will fall back to read_block_full_page(), but these limitations
- * should only be hit when page_size != block_size.
- *
- * This will allow us to attach a callback function to support ext4
- * encryption.
- *
- * If anything unusual happens, such as:
- *
- * - encountering a page which has buffers
- * - encountering a page which has a non-hole after a hole
- * - encountering a page with non-contiguous blocks
- *
- * then this code just gives up and calls the buffer_head-based read function.
- * It does handle a page which has holes at the end - that is a common case:
- * the end-of-file on blocksize < PAGE_SIZE setups.
- *
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "ext4.h"
-
-static inline bool ext4_bio_encrypted(struct bio *bio)
-{
-#ifdef CONFIG_FS_ENCRYPTION
-   return unlikely(bio->bi_private != NULL);
-#else
-   return false;
-#endif
-}
-
-/*
- * I/O completion handler for multipage BIOs.
- *
- * The mpage code never puts partial pages into a BIO (except for end-of-file).
- * If a page does not map to a contiguous run of blocks then it simply falls
- * back to block_read_full_page().
- *
- * Why is this?  If a page's completion depends on a number of different BIOs
- * which can complete in any order (or at the same time) then determining the
- * status of that page is hard.  See end_buffer_async_read() for the details.
- * There is no point in duplicating all that complexity.
- */
-static void mpage_end_io(struct bio *bio)
-{
-   struct bio_vec *bv;
-   int i;
-   struct bvec_iter_all iter_all;
-#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
-   if (read_callbacks_required(bio)) {
-   struct read_callbacks_ctx *ctx = bio->bi_private;
-
-   read_callbacks(ctx);
-   return;
-   }
-#endif
-   bio_for_each_segment_all(bv, bio, i, iter_all) {
-   struct page *page = bv->bv_page;
-
-   if (!bio->bi_status) {
-   SetPageUptodate(page);
-   } else {
-   ClearPageUptodate(page);
-   SetPageError(page);
-   }
-   unlock_page(

[f2fs-dev] [PATCH V2 01/13] ext4: Clear BH_Uptodate flag on decryption error

2019-04-27 Thread Chandan Rajendra
On an error return from fscrypt_decrypt_page(), ext4_block_write_begin()
can return with the page's buffer_head marked with BH_Uptodate
flag. This commit clears the BH_Uptodate flag in such cases.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/inode.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 3c2e7f5a6c84..05b258db8673 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1225,11 +1225,15 @@ static int ext4_block_write_begin(struct page *page, 
loff_t pos, unsigned len,
if (!buffer_uptodate(*wait_bh))
err = -EIO;
}
-   if (unlikely(err))
+   if (unlikely(err)) {
page_zero_new_buffers(page, from, to);
-   else if (decrypt)
+   } else if (decrypt) {
err = fscrypt_decrypt_page(page->mapping->host, page,
PAGE_SIZE, 0, page->index);
+   if (err)
+   clear_buffer_uptodate(*wait_bh);
+   }
+
return err;
 }
 #endif
-- 
2.19.1



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


[f2fs-dev] [PATCH V2 02/13] Consolidate "read callbacks" into a new file

2019-04-27 Thread Chandan Rajendra
The "read callbacks" code is used by both Ext4 and F2FS. Hence to
remove duplicity, this commit moves the code into
include/linux/read_callbacks.h and fs/read_callbacks.c.

The corresponding decrypt and verity "work" functions have been moved
inside fscrypt and fsverity sources. With these in place, the read
callbacks code now has to just invoke enqueue functions provided by
fscrypt and fsverity.

Signed-off-by: Chandan Rajendra 
---
 fs/Kconfig |   4 +
 fs/Makefile|   4 +
 fs/crypto/Kconfig  |   1 +
 fs/crypto/bio.c|  23 ++---
 fs/crypto/crypto.c |  17 +--
 fs/crypto/fscrypt_private.h|   3 +
 fs/ext4/ext4.h |   2 -
 fs/ext4/readpage.c | 183 +
 fs/ext4/super.c|   9 +-
 fs/f2fs/data.c | 148 --
 fs/f2fs/super.c|   9 +-
 fs/read_callbacks.c| 136 
 fs/verity/Kconfig  |   1 +
 fs/verity/verify.c |  12 +++
 include/linux/fscrypt.h|  20 +---
 include/linux/read_callbacks.h |  21 
 16 files changed, 251 insertions(+), 342 deletions(-)
 create mode 100644 fs/read_callbacks.c
 create mode 100644 include/linux/read_callbacks.h

diff --git a/fs/Kconfig b/fs/Kconfig
index 97f9eb8df713..03084f2dbeaf 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -308,6 +308,10 @@ config NFS_COMMON
depends on NFSD || NFS_FS || LOCKD
default y
 
+config FS_READ_CALLBACKS
+   bool
+   default n
+
 source "net/sunrpc/Kconfig"
 source "fs/ceph/Kconfig"
 source "fs/cifs/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index 9dd2186e74b5..e0c0fce8cf40 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -21,6 +21,10 @@ else
 obj-y +=   no-block.o
 endif
 
+ifeq ($(CONFIG_FS_READ_CALLBACKS),y)
+obj-y +=   read_callbacks.o
+endif
+
 obj-$(CONFIG_PROC_FS) += proc_namespace.o
 
 obj-y  += notify/
diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
index f0de238000c0..163c328bcbd4 100644
--- a/fs/crypto/Kconfig
+++ b/fs/crypto/Kconfig
@@ -8,6 +8,7 @@ config FS_ENCRYPTION
select CRYPTO_CTS
select CRYPTO_SHA256
select KEYS
+   select FS_READ_CALLBACKS
help
  Enable encryption of files and directories.  This
  feature is similar to ecryptfs, but it is more memory
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 5759bcd018cd..27f5618174f2 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -24,6 +24,8 @@
 #include 
 #include 
 #include 
+#include 
+
 #include "fscrypt_private.h"
 
 static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
@@ -54,24 +56,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 read_callbacks_ctx *ctx =
+   container_of(work, struct read_callbacks_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(>r.work, completion_pages);
-   ctx->r.bio = bio;
-   fscrypt_enqueue_decrypt_work(>r.work);
+   read_callbacks(ctx);
 }
-EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
 
 void fscrypt_pullback_bio_page(struct page **page, bool restore)
 {
@@ -87,7 +80,7 @@ void fscrypt_pullback_bio_page(struct page **page, bool 
restore)
ctx = (struct fscrypt_ctx *)page_private(bounce_page);
 
/* restore control page */
-   *page = ctx->w.control_page;
+   *page = ctx->control_page;
 
if (restore)
fscrypt_restore_control_page(bounce_page);
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index 3fc84bf2b1e5..ffa9302a7351 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);
@@ -70,11 +71,11 @@ void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
 {
unsigned long flags;
 
-   if (ctx->flags & FS_CTX_HAS_BOUNCE_BUFFER_FL && ctx->w.bounce_page) {
-   mempool_free(ctx->w.bounce_page, fscrypt_bounce_page_pool);
-   ctx->w.bounce_page = NULL;
+   if (ctx->flags & FS_CTX_HAS_BOUNCE_BUFFER_FL && ctx->bounce_page) {
+   mempool_free(ctx->bounce_page, fscrypt_bounc

[f2fs-dev] [PATCH V2 08/13] ext4: Decrypt all boundary blocks when doing buffered write

2019-04-27 Thread Chandan Rajendra
With subpage sized blocks, ext4_block_write_begin() can have up to two
blocks to decrypt. Hence this commit invokes fscrypt_decrypt_page() for
each of those blocks.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/inode.c | 33 +++--
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1327e04334df..51744a3c3964 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1156,12 +1156,14 @@ static int ext4_block_write_begin(struct page *page, 
loff_t pos, unsigned len,
unsigned to = from + len;
struct inode *inode = page->mapping->host;
unsigned block_start, block_end;
-   sector_t block;
+   sector_t block, page_blk_nr;
int err = 0;
unsigned blocksize = inode->i_sb->s_blocksize;
unsigned bbits;
-   struct buffer_head *bh, *head, *wait[2], **wait_bh = wait;
+   struct buffer_head *bh, *head, *wait[2];
+   int nr_wait = 0;
bool decrypt = false;
+   int i;
 
BUG_ON(!PageLocked(page));
BUG_ON(from > PAGE_SIZE);
@@ -1213,25 +1215,36 @@ static int ext4_block_write_begin(struct page *page, 
loff_t pos, unsigned len,
!buffer_unwritten(bh) &&
(block_start < from || block_end > to)) {
ll_rw_block(REQ_OP_READ, 0, 1, );
-   *wait_bh++ = bh;
+   wait[nr_wait++] = bh;
decrypt = IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
}
}
/*
 * If we issued read requests, let them complete.
 */
-   while (wait_bh > wait) {
-   wait_on_buffer(*--wait_bh);
-   if (!buffer_uptodate(*wait_bh))
+   for (i = 0; i < nr_wait; i++) {
+   wait_on_buffer(wait[i]);
+   if (!buffer_uptodate(wait[i]))
err = -EIO;
}
if (unlikely(err)) {
page_zero_new_buffers(page, from, to);
} else if (decrypt) {
-   err = fscrypt_decrypt_page(page->mapping->host, page,
-   PAGE_SIZE, 0, page->index);
-   if (err)
-   clear_buffer_uptodate(*wait_bh);
+   page_blk_nr = (sector_t)page->index << (PAGE_SHIFT - bbits);
+
+   for (i = 0; i < nr_wait; i++) {
+   int err2;
+
+   block = page_blk_nr + (bh_offset(wait[i]) >> bbits);
+   err2 = fscrypt_decrypt_page(page->mapping->host, page,
+   wait[i]->b_size,
+   bh_offset(wait[i]),
+   block);
+   if (err2) {
+   clear_buffer_uptodate(wait[i]);
+   err = err2;
+   }
+   }
}
 
return err;
-- 
2.19.1



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


[f2fs-dev] [PATCH V2 04/13] fsverity: Add call back to determine readpage limit

2019-04-27 Thread Chandan Rajendra
Ext4 and F2FS store verity metadata beyond i_size. This commit adds a
call back pointer to "struct fsverity_operations" which helps in
determining the the real file size limit upto which data can be read
from the file.

This call back will be required in order to get do_mpage_readpage()
to read files having verity metadata appended beyond i_size.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/super.c  | 17 +
 include/linux/fsverity.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 63d73b360f1d..8e483afbaa2e 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1428,6 +1428,22 @@ static struct page 
*ext4_read_verity_metadata_page(struct inode *inode,
return read_mapping_page(inode->i_mapping, index, NULL);
 }
 
+static loff_t ext4_readpage_limit(struct inode *inode)
+{
+   if (IS_VERITY(inode)) {
+   if (inode->i_verity_info)
+   /* limit to end of metadata region */
+   return fsverity_full_i_size(inode);
+   /*
+* fsverity_info is currently being set up and no user reads are
+* allowed yet.  It's easiest to just not enforce a limit yet.
+*/
+   return inode->i_sb->s_maxbytes;
+   }
+
+   return i_size_read(inode);
+}
+
 static bool ext4_verity_required(struct inode *inode, pgoff_t index)
 {
return index < (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -1438,6 +1454,7 @@ static const struct fsverity_operations ext4_verityops = {
.get_metadata_end   = ext4_get_verity_metadata_end,
.read_metadata_page = ext4_read_verity_metadata_page,
.verity_required= ext4_verity_required,
+   .readpage_limit = ext4_readpage_limit,
 };
 #endif /* CONFIG_FS_VERITY */
 
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index b83712d6c79a..fc8113acbbfe 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -19,6 +19,7 @@ struct fsverity_operations {
int (*get_metadata_end)(struct inode *inode, loff_t *metadata_end_ret);
struct page *(*read_metadata_page)(struct inode *inode, pgoff_t index);
bool (*verity_required)(struct inode *inode, pgoff_t index);
+   loff_t (*readpage_limit)(struct inode *inode);
 };
 
 #ifdef CONFIG_FS_VERITY
-- 
2.19.1



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


[f2fs-dev] [PATCH V2 00/13] Consolidate FS read I/O callbacks code

2019-04-27 Thread Chandan Rajendra
This patchset moves the "FS read I/O callbacks" code into a file of its
own (i.e. fs/read_callbacks.c) and modifies the generic
do_mpage_readpge() to make use of the functionality provided.

"FS read I/O callbacks" code implements the state machine that needs
to be executed after reading data from files that are encrypted and/or
have verity metadata associated with them.

With these changes in place, the patchset changes Ext4 to use
mpage_readpage[s] instead of its own custom ext4_readpage[s]()
functions. This is done to reduce duplicity of code across
filesystems. Also, "FS read I/O callbacks" source files will be built
only if one of CONFIG_FS_ENCRYPTION and CONFIG_FS_VERITY is enabled.

The patchset also modifies fs/buffer.c and fscrypt functionality to
get file encryption/decryption to work with subpage-sized blocks.

The following fixes from Eric Biggers are prerequisites for this
patchset,
  fscrypt: fix race where ->lookup() marks plaintext dentry as ciphertext
  fscrypt: only set dentry_operations on ciphertext dentries
  fscrypt: clear DCACHE_ENCRYPTED_NAME when unaliasing directory
  fscrypt: fix race allowing rename() and link() of ciphertext dentries
  fscrypt: clean up and improve dentry revalidation

The patches can also be obtained from,
"https://github.com/chandanr/linux.git subpage-encryption-v2"

Changelog:
V1 -> V2:
1. Removed the phrase "post_read_process" from file names and
   functions. Instead we now use the phrase "read_callbacks" in its
   place.
2. When performing changes associated with (1), the changes made by
   the patch "Remove the term 'bio' from post read processing" are
   made in the earlier patch "Consolidate 'read callbacks' into a new
   file". Hence the patch "Remove the term 'bio' from post read
   processing" is removed from the patchset.

RFC V2 -> V1:
1. Test and verify FS_CFLG_OWN_PAGES subset of fscrypt_encrypt_page()
   code by executing fstests on UBIFS.
2. Implement F2fs function call back to check if the contents of a
   page holding a verity file's data needs to be verified.

RFC V1 -> RFC V2:
1. Describe the purpose of "Post processing code" in the cover letter.
2. Fix build errors when CONFIG_FS_VERITY is enabled.

Chandan Rajendra (13):
  ext4: Clear BH_Uptodate flag on decryption error
  Consolidate "read callbacks" into a new file
  fsverity: Add call back to decide if verity check has to be performed
  fsverity: Add call back to determine readpage limit
  fs/mpage.c: Integrate read callbacks
  ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]
  Add decryption support for sub-pagesized blocks
  ext4: Decrypt all boundary blocks when doing buffered write
  ext4: Decrypt the block that needs to be partially zeroed
  fscrypt_encrypt_page: Loop across all blocks mapped by a page range
  ext4: Compute logical block and the page range to be encrypted
  fscrypt_zeroout_range: Encrypt all zeroed out blocks of a page
  ext4: Enable encryption for subpage-sized blocks

 Documentation/filesystems/fscrypt.rst |   4 +-
 fs/Kconfig|   4 +
 fs/Makefile   |   4 +
 fs/buffer.c   |  83 +++--
 fs/crypto/Kconfig |   1 +
 fs/crypto/bio.c   | 111 ---
 fs/crypto/crypto.c|  73 +++--
 fs/crypto/fscrypt_private.h   |   3 +
 fs/ext4/Makefile  |   2 +-
 fs/ext4/ext4.h|   2 -
 fs/ext4/inode.c   |  47 ++-
 fs/ext4/page-io.c |   9 +-
 fs/ext4/readpage.c| 445 --
 fs/ext4/super.c   |  39 ++-
 fs/f2fs/data.c| 148 ++---
 fs/f2fs/super.c   |  15 +-
 fs/mpage.c|  51 ++-
 fs/read_callbacks.c   | 155 +
 fs/verity/Kconfig |   1 +
 fs/verity/verify.c|  12 +
 include/linux/buffer_head.h   |   1 +
 include/linux/fscrypt.h   |  20 +-
 include/linux/fsverity.h  |   2 +
 include/linux/read_callbacks.h|  22 ++
 24 files changed, 522 insertions(+), 732 deletions(-)
 delete mode 100644 fs/ext4/readpage.c
 create mode 100644 fs/read_callbacks.c
 create mode 100644 include/linux/read_callbacks.h

-- 
2.19.1



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


[f2fs-dev] [PATCH V2 05/13] fs/mpage.c: Integrate read callbacks

2019-04-27 Thread Chandan Rajendra
This commit adds code to make do_mpage_readpage() to be "read
callbacks" aware i.e. for files requiring decryption/verification,
do_mpage_readpage() now allocates a context structure and assigns the
corresponding pointer to bio->bi_private. At endio time, a non-zero
bio->bi_private indicates that after the read operation is performed, the
bio's payload needs to be processed further before handing over the data
to user space.

The context structure is used for tracking the state machine associated
with post read processing.

Signed-off-by: Chandan Rajendra 
---
 fs/mpage.c | 51 ---
 1 file changed, 48 insertions(+), 3 deletions(-)

diff --git a/fs/mpage.c b/fs/mpage.c
index 3f19da75178b..e342b859ee44 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -30,6 +30,10 @@
 #include 
 #include 
 #include 
+#include 
+#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
+#include 
+#endif
 #include "internal.h"
 
 /*
@@ -50,6 +54,20 @@ static void mpage_end_io(struct bio *bio)
int i;
struct bvec_iter_all iter_all;
 
+#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
+   if (!bio->bi_status && bio->bi_private) {
+   struct read_callbacks_ctx *ctx;
+
+   ctx = bio->bi_private;
+
+   read_callbacks(ctx);
+   return;
+   }
+
+   if (bio->bi_private)
+   put_read_callbacks_ctx((struct read_callbacks_ctx 
*)(bio->bi_private));
+#endif
+
bio_for_each_segment_all(bv, bio, i, iter_all) {
struct page *page = bv->bv_page;
page_endio(page, bio_op(bio),
@@ -189,7 +207,13 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
 
block_in_file = (sector_t)page->index << (PAGE_SHIFT - blkbits);
last_block = block_in_file + args->nr_pages * blocks_per_page;
-   last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits;
+#ifdef CONFIG_FS_VERITY
+   if (IS_VERITY(inode) && inode->i_sb->s_vop->readpage_limit)
+   last_block_in_file = inode->i_sb->s_vop->readpage_limit(inode);
+   else
+#endif
+   last_block_in_file = (i_size_read(inode) + blocksize - 1)
+   >> blkbits;
if (last_block > last_block_in_file)
last_block = last_block_in_file;
page_block = 0;
@@ -277,6 +301,14 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
if (first_hole != blocks_per_page) {
zero_user_segment(page, first_hole << blkbits, PAGE_SIZE);
if (first_hole == 0) {
+#ifdef CONFIG_FS_VERITY
+   if (IS_VERITY(inode)) {
+   if (!fsverity_check_hole(inode, page)) {
+   SetPageError(page);
+   goto confused;
+   }
+   }
+#endif
SetPageUptodate(page);
unlock_page(page);
goto out;
@@ -299,7 +331,11 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
 
 alloc_new:
if (args->bio == NULL) {
-   if (first_hole == blocks_per_page) {
+#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
+   struct read_callbacks_ctx *ctx;
+#endif
+   if (first_hole == blocks_per_page
+   && !(IS_ENCRYPTED(inode) || IS_VERITY(inode))) {
if (!bdev_read_page(bdev, blocks[0] << (blkbits - 9),
page))
goto out;
@@ -310,6 +346,15 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
gfp);
if (args->bio == NULL)
goto confused;
+
+#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
+   ctx = get_read_callbacks_ctx(inode, args->bio, page->index);
+   if (IS_ERR(ctx)) {
+   bio_put(args->bio);
+   args->bio = NULL;
+   goto confused;
+   }
+#endif
}
 
length = first_hole << blkbits;
@@ -331,7 +376,7 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
 confused:
if (args->bio)
args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
-   if (!PageUptodate(page))
+   if (!PageUptodate(page) && !PageError(page))
block_read_full_page(page, args->get_block);
else
unlock_page(page);
-- 
2.19.1



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


[f2fs-dev] [PATCH V2 13/13] ext4: Enable encryption for subpage-sized blocks

2019-04-27 Thread Chandan Rajendra
Now that we have the code to support encryption for subpage-sized
blocks, this commit removes the conditional check in filesystem mount
code.

The commit also changes the support statement in
Documentation/filesystems/fscrypt.rst to reflect the fact that
encryption of filesystems with blocksize less than page size now works.

Signed-off-by: Chandan Rajendra 
---
 Documentation/filesystems/fscrypt.rst | 4 ++--
 fs/ext4/super.c   | 7 ---
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/Documentation/filesystems/fscrypt.rst 
b/Documentation/filesystems/fscrypt.rst
index 08c23b60e016..ff2fea121da9 100644
--- a/Documentation/filesystems/fscrypt.rst
+++ b/Documentation/filesystems/fscrypt.rst
@@ -213,8 +213,8 @@ Contents encryption
 ---
 
 For file contents, each filesystem block is encrypted independently.
-Currently, only the case where the filesystem block size is equal to
-the system's page size (usually 4096 bytes) is supported.
+Starting from Linux kernel 5.3, encryption of filesystems with block
+size less than system's page size is supported.
 
 Each block's IV is set to the logical block number within the file as
 a little endian number, except that:
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 8e483afbaa2e..4acfefa98ec5 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4432,13 +4432,6 @@ static int ext4_fill_super(struct super_block *sb, void 
*data, int silent)
}
}
 
-   if ((DUMMY_ENCRYPTION_ENABLED(sbi) || ext4_has_feature_encrypt(sb)) &&
-   (blocksize != PAGE_SIZE)) {
-   ext4_msg(sb, KERN_ERR,
-"Unsupported blocksize for fs encryption");
-   goto failed_mount_wq;
-   }
-
if (DUMMY_ENCRYPTION_ENABLED(sbi) && !sb_rdonly(sb) &&
!ext4_has_feature_encrypt(sb)) {
ext4_set_feature_encrypt(sb);
-- 
2.19.1



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


[f2fs-dev] [PATCH V2 11/13] ext4: Compute logical block and the page range to be encrypted

2019-04-27 Thread Chandan Rajendra
For subpage-sized blocks, the initial logical block number mapped by a
page can be different from page->index. Hence this commit adds code to
compute the first logical block mapped by the page and also the page
range to be encrypted.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/page-io.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 3e9298e6a705..75485ee9e800 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -418,6 +418,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
 {
struct page *data_page = NULL;
struct inode *inode = page->mapping->host;
+   u64 page_blk;
unsigned block_start;
struct buffer_head *bh, *head;
int ret = 0;
@@ -478,10 +479,14 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
 
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) {
gfp_t gfp_flags = GFP_NOFS;
+   unsigned int page_bytes;
+
+   page_bytes = round_up(len, i_blocksize(inode));
+   page_blk = page->index << (PAGE_SHIFT - inode->i_blkbits);
 
retry_encrypt:
-   data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0,
-   page->index, gfp_flags);
+   data_page = fscrypt_encrypt_page(inode, page, page_bytes, 0,
+   page_blk, gfp_flags);
if (IS_ERR(data_page)) {
ret = PTR_ERR(data_page);
if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
-- 
2.19.1



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


[f2fs-dev] [PATCH V2 07/13] Add decryption support for sub-pagesized blocks

2019-04-27 Thread Chandan Rajendra
To support decryption of sub-pagesized blocks this commit adds code to,
1. Track buffer head in "struct read_callbacks_ctx".
2. Pass buffer head argument to all read callbacks.
3. In the corresponding endio, loop across all the blocks mapped by the
   page, decrypting each block in turn.

Signed-off-by: Chandan Rajendra 
---
 fs/buffer.c| 83 +-
 fs/crypto/bio.c| 50 +---
 fs/crypto/crypto.c | 19 +++-
 fs/f2fs/data.c |  2 +-
 fs/mpage.c |  2 +-
 fs/read_callbacks.c| 53 ++
 include/linux/buffer_head.h|  1 +
 include/linux/read_callbacks.h |  5 +-
 8 files changed, 154 insertions(+), 61 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index ce357602f471..f324727e24bb 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -45,6 +45,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
@@ -245,11 +246,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t 
block)
return ret;
 }
 
-/*
- * I/O completion handler for block_read_full_page() - pages
- * which come unlocked at the end of I/O.
- */
-static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
+void end_buffer_page_read(struct buffer_head *bh)
 {
unsigned long flags;
struct buffer_head *first;
@@ -257,17 +254,7 @@ static void end_buffer_async_read(struct buffer_head *bh, 
int uptodate)
struct page *page;
int page_uptodate = 1;
 
-   BUG_ON(!buffer_async_read(bh));
-
page = bh->b_page;
-   if (uptodate) {
-   set_buffer_uptodate(bh);
-   } else {
-   clear_buffer_uptodate(bh);
-   buffer_io_error(bh, ", async page read");
-   SetPageError(page);
-   }
-
/*
 * Be _very_ careful from here on. Bad things can happen if
 * two buffer heads end IO at almost the same time and both
@@ -305,6 +292,44 @@ static void end_buffer_async_read(struct buffer_head *bh, 
int uptodate)
local_irq_restore(flags);
return;
 }
+EXPORT_SYMBOL(end_buffer_page_read);
+
+/*
+ * I/O completion handler for block_read_full_page() - pages
+ * which come unlocked at the end of I/O.
+ */
+static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
+{
+   struct page *page;
+
+   BUG_ON(!buffer_async_read(bh));
+
+#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
+   if (uptodate && bh->b_private) {
+   struct read_callbacks_ctx *ctx = bh->b_private;
+
+   read_callbacks(ctx);
+   return;
+   }
+
+   if (bh->b_private) {
+   struct read_callbacks_ctx *ctx = bh->b_private;
+
+   WARN_ON(uptodate);
+   put_read_callbacks_ctx(ctx);
+   }
+#endif
+   page = bh->b_page;
+   if (uptodate) {
+   set_buffer_uptodate(bh);
+   } else {
+   clear_buffer_uptodate(bh);
+   buffer_io_error(bh, ", async page read");
+   SetPageError(page);
+   }
+
+   end_buffer_page_read(bh);
+}
 
 /*
  * Completion handler for block_write_full_page() - pages which are unlocked
@@ -2220,7 +2245,11 @@ int block_read_full_page(struct page *page, get_block_t 
*get_block)
 {
struct inode *inode = page->mapping->host;
sector_t iblock, lblock;
-   struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
+   struct buffer_head *bh, *head;
+   struct {
+   sector_t blk_nr;
+   struct buffer_head *bh;
+   } arr[MAX_BUF_PER_PAGE];
unsigned int blocksize, bbits;
int nr, i;
int fully_mapped = 1;
@@ -2262,7 +2291,9 @@ int block_read_full_page(struct page *page, get_block_t 
*get_block)
if (buffer_uptodate(bh))
continue;
}
-   arr[nr++] = bh;
+   arr[nr].blk_nr = iblock;
+   arr[nr].bh = bh;
+   ++nr;
} while (i++, iblock++, (bh = bh->b_this_page) != head);
 
if (fully_mapped)
@@ -2281,7 +2312,7 @@ int block_read_full_page(struct page *page, get_block_t 
*get_block)
 
/* Stage two: lock the buffers */
for (i = 0; i < nr; i++) {
-   bh = arr[i];
+   bh = arr[i].bh;
lock_buffer(bh);
mark_buffer_async_read(bh);
}
@@ -2292,11 +2323,21 @@ int block_read_full_page(struct page *page, get_block_t 
*get_block)
 * the underlying blockdev brought it uptodate (the sct fix).
 */
for (i = 0; i < nr; i++) {
-   bh = arr[i];
-   if (buffer_uptodate(bh))
+   bh = arr[i].bh;
+   if (buffer_uptodate(bh)) {
   

[f2fs-dev] [PATCH V2 03/13] fsverity: Add call back to decide if verity check has to be performed

2019-04-27 Thread Chandan Rajendra
Ext4 and F2FS store verity metadata in data extents (beyond
inode->i_size) associated with a file. But other filesystems might
choose alternative means to store verity metadata. Hence this commit
adds a callback function pointer to 'struct fsverity_operations' to help
in deciding if verity operation needs to performed against a page-cache
page holding file data.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/super.c  | 6 ++
 fs/f2fs/super.c  | 6 ++
 fs/read_callbacks.c  | 4 +++-
 include/linux/fsverity.h | 1 +
 4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index aba724f82cc3..63d73b360f1d 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1428,10 +1428,16 @@ static struct page 
*ext4_read_verity_metadata_page(struct inode *inode,
return read_mapping_page(inode->i_mapping, index, NULL);
 }
 
+static bool ext4_verity_required(struct inode *inode, pgoff_t index)
+{
+   return index < (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+}
+
 static const struct fsverity_operations ext4_verityops = {
.set_verity = ext4_set_verity,
.get_metadata_end   = ext4_get_verity_metadata_end,
.read_metadata_page = ext4_read_verity_metadata_page,
+   .verity_required= ext4_verity_required,
 };
 #endif /* CONFIG_FS_VERITY */
 
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 2f75f06c784a..cd1299e1f92d 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2257,10 +2257,16 @@ static struct page 
*f2fs_read_verity_metadata_page(struct inode *inode,
return read_mapping_page(inode->i_mapping, index, NULL);
 }
 
+static bool f2fs_verity_required(struct inode *inode, pgoff_t index)
+{
+   return index < (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+}
+
 static const struct fsverity_operations f2fs_verityops = {
.set_verity = f2fs_set_verity,
.get_metadata_end   = f2fs_get_verity_metadata_end,
.read_metadata_page = f2fs_read_verity_metadata_page,
+   .verity_required= f2fs_verity_required,
 };
 #endif /* CONFIG_FS_VERITY */
 
diff --git a/fs/read_callbacks.c b/fs/read_callbacks.c
index b6d5b95e67d7..6dea54b0baa9 100644
--- a/fs/read_callbacks.c
+++ b/fs/read_callbacks.c
@@ -86,7 +86,9 @@ struct read_callbacks_ctx *get_read_callbacks_ctx(struct 
inode *inode,
read_callbacks_steps |= 1 << STEP_DECRYPT;
 #ifdef CONFIG_FS_VERITY
if (inode->i_verity_info != NULL &&
-   (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
+   ((inode->i_sb->s_vop->verity_required
+   && inode->i_sb->s_vop->verity_required(inode, index))
+   || (inode->i_sb->s_vop->verity_required == NULL)))
read_callbacks_steps |= 1 << STEP_VERITY;
 #endif
if (read_callbacks_steps) {
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 7c33b42abf1b..b83712d6c79a 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -18,6 +18,7 @@ struct fsverity_operations {
int (*set_verity)(struct inode *inode, loff_t data_i_size);
int (*get_metadata_end)(struct inode *inode, loff_t *metadata_end_ret);
struct page *(*read_metadata_page)(struct inode *inode, pgoff_t index);
+   bool (*verity_required)(struct inode *inode, pgoff_t index);
 };
 
 #ifdef CONFIG_FS_VERITY
-- 
2.19.1



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


[f2fs-dev] [PATCH V2 10/13] fscrypt_encrypt_page: Loop across all blocks mapped by a page range

2019-04-27 Thread Chandan Rajendra
For subpage-sized blocks, this commit now encrypts all blocks mapped by
a page range.

Signed-off-by: Chandan Rajendra 
---
 fs/crypto/crypto.c | 37 +
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index 4f0d832cae71..2d65b431563f 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -242,18 +242,26 @@ struct page *fscrypt_encrypt_page(const struct inode 
*inode,
 {
struct fscrypt_ctx *ctx;
struct page *ciphertext_page = page;
+   int i, page_nr_blks;
int err;
 
BUG_ON(len % FS_CRYPTO_BLOCK_SIZE != 0);
 
+   page_nr_blks = len >> inode->i_blkbits;
+
if (inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES) {
/* with inplace-encryption we just encrypt the page */
-   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num, page,
-ciphertext_page, len, offs,
-gfp_flags);
-   if (err)
-   return ERR_PTR(err);
-
+   for (i = 0; i < page_nr_blks; i++) {
+   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT,
+   lblk_num, page,
+   ciphertext_page,
+   i_blocksize(inode), offs,
+   gfp_flags);
+   if (err)
+   return ERR_PTR(err);
+   ++lblk_num;
+   offs += i_blocksize(inode);
+   }
return ciphertext_page;
}
 
@@ -269,12 +277,17 @@ struct page *fscrypt_encrypt_page(const struct inode 
*inode,
goto errout;
 
ctx->control_page = page;
-   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num,
-page, ciphertext_page, len, offs,
-gfp_flags);
-   if (err) {
-   ciphertext_page = ERR_PTR(err);
-   goto errout;
+
+   for (i = 0; i < page_nr_blks; i++) {
+   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num,
+   page, ciphertext_page,
+   i_blocksize(inode), offs, gfp_flags);
+   if (err) {
+   ciphertext_page = ERR_PTR(err);
+   goto errout;
+   }
+   ++lblk_num;
+   offs += i_blocksize(inode);
}
SetPagePrivate(ciphertext_page);
set_page_private(ciphertext_page, (unsigned long)ctx);
-- 
2.19.1



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


[f2fs-dev] [PATCH V2 09/13] ext4: Decrypt the block that needs to be partially zeroed

2019-04-27 Thread Chandan Rajendra
__ext4_block_zero_page_range decrypts the entire page. This commit
decrypts the block to be partially zeroed instead of the whole page.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/inode.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 51744a3c3964..ade1816697a8 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4080,9 +4080,10 @@ static int __ext4_block_zero_page_range(handle_t *handle,
if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) {
/* We expect the key to be set. */
BUG_ON(!fscrypt_has_encryption_key(inode));
-   BUG_ON(blocksize != PAGE_SIZE);
WARN_ON_ONCE(fscrypt_decrypt_page(page->mapping->host,
-   page, PAGE_SIZE, 0, 
page->index));
+   page, blocksize,
+   round_down(offset, 
blocksize),
+   iblock));
}
}
if (ext4_should_journal_data(inode)) {
-- 
2.19.1



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


[f2fs-dev] [PATCH V2 12/13] fscrypt_zeroout_range: Encrypt all zeroed out blocks of a page

2019-04-27 Thread Chandan Rajendra
For subpage-sized blocks, this commit adds code to encrypt all zeroed
out blocks mapped by a page.

Signed-off-by: Chandan Rajendra 
---
 fs/crypto/bio.c | 40 ++--
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 856f4694902d..46dd2ec50c7d 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -108,29 +108,23 @@ EXPORT_SYMBOL(fscrypt_pullback_bio_page);
 int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len)
 {
-   struct fscrypt_ctx *ctx;
struct page *ciphertext_page = NULL;
struct bio *bio;
+   u64 total_bytes, page_bytes;
int ret, err = 0;
 
-   BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE);
-
-   ctx = fscrypt_get_ctx(inode, GFP_NOFS);
-   if (IS_ERR(ctx))
-   return PTR_ERR(ctx);
+   total_bytes = len << inode->i_blkbits;
 
-   ciphertext_page = fscrypt_alloc_bounce_page(ctx, GFP_NOWAIT);
-   if (IS_ERR(ciphertext_page)) {
-   err = PTR_ERR(ciphertext_page);
-   goto errout;
-   }
+   while (total_bytes) {
+   page_bytes = min_t(u64, total_bytes, PAGE_SIZE);
 
-   while (len--) {
-   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk,
-ZERO_PAGE(0), ciphertext_page,
-PAGE_SIZE, 0, GFP_NOFS);
-   if (err)
+   ciphertext_page = fscrypt_encrypt_page(inode, ZERO_PAGE(0),
+   page_bytes, 0, lblk, GFP_NOFS);
+   if (IS_ERR(ciphertext_page)) {
+   err = PTR_ERR(ciphertext_page);
+   ciphertext_page = NULL;
goto errout;
+   }
 
bio = bio_alloc(GFP_NOWAIT, 1);
if (!bio) {
@@ -141,9 +135,8 @@ int fscrypt_zeroout_range(const struct inode *inode, 
pgoff_t lblk,
bio->bi_iter.bi_sector =
pblk << (inode->i_sb->s_blocksize_bits - 9);
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
-   ret = bio_add_page(bio, ciphertext_page,
-   inode->i_sb->s_blocksize, 0);
-   if (ret != inode->i_sb->s_blocksize) {
+   ret = bio_add_page(bio, ciphertext_page, page_bytes, 0);
+   if (ret != page_bytes) {
/* should never happen! */
WARN_ON(1);
bio_put(bio);
@@ -156,12 +149,15 @@ int fscrypt_zeroout_range(const struct inode *inode, 
pgoff_t lblk,
bio_put(bio);
if (err)
goto errout;
-   lblk++;
-   pblk++;
+
+   lblk += page_bytes >> inode->i_blkbits;
+   pblk += page_bytes >> inode->i_blkbits;
+   total_bytes -= page_bytes;
}
err = 0;
 errout:
-   fscrypt_release_ctx(ctx);
+   if (!IS_ERR_OR_NULL(ciphertext_page))
+   fscrypt_restore_control_page(ciphertext_page);
return err;
 }
 EXPORT_SYMBOL(fscrypt_zeroout_range);
-- 
2.19.1



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


Re: [f2fs-dev] [PATCH V1 02/14] Consolidate "post read processing" into a new file

2019-04-24 Thread Chandan Rajendra
On Wednesday, April 24, 2019 5:36:46 PM IST Jaegeuk Kim wrote:
> On 04/24, Chandan Rajendra wrote:
> > On Wednesday, April 24, 2019 2:01:26 PM IST Jaegeuk Kim wrote:
> > > Hi Chandan,
> > > 
> > > On 04/24, 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 
> > > > ---
> > > >  fs/Makefile   |   4 +
> > > >  fs/crypto/bio.c   |  23 ++--
> > > >  fs/crypto/crypto.c|  17 +--
> > > >  fs/crypto/fscrypt_private.h   |   3 +
> > > >  fs/ext4/ext4.h|   2 -
> > > >  fs/ext4/readpage.c| 175 --
> > > >  fs/ext4/super.c   |   9 +-
> > > >  fs/f2fs/data.c| 146 -
> > > >  fs/f2fs/super.c   |   9 +-
> > > >  fs/post_read_process.c| 136 +++
> > > >  fs/verity/verify.c|  12 ++
> > > >  include/linux/fscrypt.h   |  20 +---
> > > >  include/linux/post_read_process.h |  21 
> > > >  13 files changed, 240 insertions(+), 337 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 9dd2186e74b5..f9abc3f71d3c 100644
> > > > --- a/fs/Makefile
> > > > +++ b/fs/Makefile
> > > > @@ -21,6 +21,10 @@ else
> > > >  obj-y +=   no-block.o
> > > >  endif
> > > >  
> > > > +ifeq (y, $(firstword $(filter y,$(CONFIG_FS_ENCRYPTION) 
> > > > $(CONFIG_FS_VERITY
> > > > +obj-y +=   post_read_process.o
> > > > +endif
> > > > +
> > > >  obj-$(CONFIG_PROC_FS) += proc_namespace.o
> > > >  
> > > >  obj-y  += notify/
> > > > diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
> > > > index 5759bcd018cd..3e40d65ae6a8 100644
> > > > --- a/fs/crypto/bio.c
> > > > +++ b/fs/crypto/bio.c
> > > > @@ -24,6 +24,8 @@
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > +#include 
> > > > +
> > > >  #include "fscrypt_private.h"
> > > >  
> > > >  static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
> > > > @@ -54,24 +56,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(>r.work, completion_pages);
> > > > -   ctx->r.bio = bio;
> > > > -   fscrypt_enqueue_decrypt_work(>r.work);
> > > > +   bio_post_read_processing(ctx);
> > > >  }
> > > > -EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
> > > >  
> > > >  void fscrypt_pullback_bio_page(struct page **page, bool restore)
> > > >  {
> > > > @@ -87,

Re: [f2fs-dev] [PATCH V1 02/14] Consolidate "post read processing" into a new file

2019-04-24 Thread Chandan Rajendra
On Wednesday, April 24, 2019 7:54:23 PM IST Christoph Hellwig wrote:
> On Wed, Apr 24, 2019 at 03:34:17PM +0530, Chandan Rajendra wrote:
> > To clarify, Are you suggesting that a new kconfig option (say
> > CONFIG_FS_READ_CALLBACKS) be provided to the user so that the following 
> > could
> > occur,
> > 
> > 1. User selects CONFIG_FS_ENCRYPTION and/or CONFIG_FS_VERITY and this causes
> > CONFIG_FS_READ_CALLBACKS to be set to 'y'.
> > 2. User selects CONFIG_FS_READ_CALLBACKS explicitly.
> 
> If you don't add a user description to a Kconfig entry it won't be
> visible to users, but only selectable by other options.  That is what
> I suggest.
> 
> 

Thanks for the clarification. I will make the necessary changes.

-- 
chandan





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


[f2fs-dev] [PATCH V1 01/14] ext4: Clear BH_Uptodate flag on decryption error

2019-04-23 Thread Chandan Rajendra
On an error return from fscrypt_decrypt_page(), ext4_block_write_begin()
can return with the page's buffer_head marked with BH_Uptodate
flag. This commit clears the BH_Uptodate flag in such cases.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/inode.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 3c2e7f5a6c84..05b258db8673 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1225,11 +1225,15 @@ static int ext4_block_write_begin(struct page *page, 
loff_t pos, unsigned len,
if (!buffer_uptodate(*wait_bh))
err = -EIO;
}
-   if (unlikely(err))
+   if (unlikely(err)) {
page_zero_new_buffers(page, from, to);
-   else if (decrypt)
+   } else if (decrypt) {
err = fscrypt_decrypt_page(page->mapping->host, page,
PAGE_SIZE, 0, page->index);
+   if (err)
+   clear_buffer_uptodate(*wait_bh);
+   }
+
return err;
 }
 #endif
-- 
2.19.1



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


[f2fs-dev] [PATCH V1 03/14] fsverity: Add call back to decide if verity check has to be performed

2019-04-23 Thread Chandan Rajendra
Ext4 and F2FS store verity metadata in data extents (beyond
inode->i_size) associated with a file. But other filesystems might
choose alternative means to store verity metadata. Hence this commit
adds a callback function pointer to 'struct fsverity_operations' to help
in deciding if verity operation needs to performed against a page-cache
page holding file data.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/super.c  | 6 ++
 fs/f2fs/super.c  | 6 ++
 fs/post_read_process.c   | 4 +++-
 include/linux/fsverity.h | 1 +
 4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index aba724f82cc3..63d73b360f1d 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1428,10 +1428,16 @@ static struct page 
*ext4_read_verity_metadata_page(struct inode *inode,
return read_mapping_page(inode->i_mapping, index, NULL);
 }
 
+static bool ext4_verity_required(struct inode *inode, pgoff_t index)
+{
+   return index < (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+}
+
 static const struct fsverity_operations ext4_verityops = {
.set_verity = ext4_set_verity,
.get_metadata_end   = ext4_get_verity_metadata_end,
.read_metadata_page = ext4_read_verity_metadata_page,
+   .verity_required= ext4_verity_required,
 };
 #endif /* CONFIG_FS_VERITY */
 
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 2f75f06c784a..cd1299e1f92d 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2257,10 +2257,16 @@ static struct page 
*f2fs_read_verity_metadata_page(struct inode *inode,
return read_mapping_page(inode->i_mapping, index, NULL);
 }
 
+static bool f2fs_verity_required(struct inode *inode, pgoff_t index)
+{
+   return index < (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+}
+
 static const struct fsverity_operations f2fs_verityops = {
.set_verity = f2fs_set_verity,
.get_metadata_end   = f2fs_get_verity_metadata_end,
.read_metadata_page = f2fs_read_verity_metadata_page,
+   .verity_required= f2fs_verity_required,
 };
 #endif /* CONFIG_FS_VERITY */
 
diff --git a/fs/post_read_process.c b/fs/post_read_process.c
index d203fc263091..b60be77c7217 100644
--- a/fs/post_read_process.c
+++ b/fs/post_read_process.c
@@ -86,7 +86,9 @@ struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode 
*inode,
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)))
+   ((inode->i_sb->s_vop->verity_required
+   && inode->i_sb->s_vop->verity_required(inode, index))
+   || (inode->i_sb->s_vop->verity_required == NULL)))
post_read_steps |= 1 << STEP_VERITY;
 #endif
if (post_read_steps) {
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 7c33b42abf1b..b83712d6c79a 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -18,6 +18,7 @@ struct fsverity_operations {
int (*set_verity)(struct inode *inode, loff_t data_i_size);
int (*get_metadata_end)(struct inode *inode, loff_t *metadata_end_ret);
struct page *(*read_metadata_page)(struct inode *inode, pgoff_t index);
+   bool (*verity_required)(struct inode *inode, pgoff_t index);
 };
 
 #ifdef CONFIG_FS_VERITY
-- 
2.19.1



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


[f2fs-dev] [PATCH V1 09/14] ext4: Decrypt all boundary blocks when doing buffered write

2019-04-23 Thread Chandan Rajendra
With subpage sized blocks, ext4_block_write_begin() can have up to two
blocks to decrypt. Hence this commit invokes fscrypt_decrypt_page() for
each of those blocks.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/inode.c | 33 +++--
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1327e04334df..51744a3c3964 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1156,12 +1156,14 @@ static int ext4_block_write_begin(struct page *page, 
loff_t pos, unsigned len,
unsigned to = from + len;
struct inode *inode = page->mapping->host;
unsigned block_start, block_end;
-   sector_t block;
+   sector_t block, page_blk_nr;
int err = 0;
unsigned blocksize = inode->i_sb->s_blocksize;
unsigned bbits;
-   struct buffer_head *bh, *head, *wait[2], **wait_bh = wait;
+   struct buffer_head *bh, *head, *wait[2];
+   int nr_wait = 0;
bool decrypt = false;
+   int i;
 
BUG_ON(!PageLocked(page));
BUG_ON(from > PAGE_SIZE);
@@ -1213,25 +1215,36 @@ static int ext4_block_write_begin(struct page *page, 
loff_t pos, unsigned len,
!buffer_unwritten(bh) &&
(block_start < from || block_end > to)) {
ll_rw_block(REQ_OP_READ, 0, 1, );
-   *wait_bh++ = bh;
+   wait[nr_wait++] = bh;
decrypt = IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
}
}
/*
 * If we issued read requests, let them complete.
 */
-   while (wait_bh > wait) {
-   wait_on_buffer(*--wait_bh);
-   if (!buffer_uptodate(*wait_bh))
+   for (i = 0; i < nr_wait; i++) {
+   wait_on_buffer(wait[i]);
+   if (!buffer_uptodate(wait[i]))
err = -EIO;
}
if (unlikely(err)) {
page_zero_new_buffers(page, from, to);
} else if (decrypt) {
-   err = fscrypt_decrypt_page(page->mapping->host, page,
-   PAGE_SIZE, 0, page->index);
-   if (err)
-   clear_buffer_uptodate(*wait_bh);
+   page_blk_nr = (sector_t)page->index << (PAGE_SHIFT - bbits);
+
+   for (i = 0; i < nr_wait; i++) {
+   int err2;
+
+   block = page_blk_nr + (bh_offset(wait[i]) >> bbits);
+   err2 = fscrypt_decrypt_page(page->mapping->host, page,
+   wait[i]->b_size,
+   bh_offset(wait[i]),
+   block);
+   if (err2) {
+   clear_buffer_uptodate(wait[i]);
+   err = err2;
+   }
+   }
}
 
return err;
-- 
2.19.1



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


[f2fs-dev] [PATCH V1 00/14] Consolidate Post read processing code

2019-04-23 Thread Chandan Rajendra
This patchset moves the "post read processing" code into a file of its
own (i.e. fs/post_read_process.c) and modifies the generic
do_mpage_readpge() to make use of the functionality provided.

"Post read processing" implements code to track the state machine that
needs to be executed after reading data from files that are encrypted
and/or have verity metadata associated with them.

With these changes in place, the patchset changes Ext4 to use
mpage_readpage[s] instead of its own custom ext4_readpage[s]()
functions. This is done to reduce duplicity of code across
filesystems. Also, Post read processing source files will be built
only if one of CONFIG_FS_ENCRYPTION and CONFIG_FS_VERITY is enabled.

The patchset also modifies fs/buffer.c and fscrypt functionality to
get file encryption/decryption to work with subpage-sized blocks.

The following fixes from Eric Biggers are prerequisites for this
patchset,
  fscrypt: fix race where ->lookup() marks plaintext dentry as ciphertext
  fscrypt: only set dentry_operations on ciphertext dentries
  fscrypt: clear DCACHE_ENCRYPTED_NAME when unaliasing directory
  fscrypt: fix race allowing rename() and link() of ciphertext dentries
  fscrypt: clean up and improve dentry revalidation

The patches can also be obtained from,
"https://github.com/chandanr/linux.git subpage-encryption"

Changelog:
RFC V2 -> V1:
1. Test and verify FS_CFLG_OWN_PAGES subset of fscrypt_encrypt_page()
   code by executing fstests on UBIFS.
2. Implement F2fs function call back to check if the contents of a
   page holding a verity file's data needs to be verified.

RFC V1 -> RFC V2:
1. Describe the purpose of "Post processing code" in the cover letter.
2. Fix build errors when CONFIG_FS_VERITY is enabled.

Chandan Rajendra (14):
  ext4: Clear BH_Uptodate flag on decryption error
  Consolidate "post read processing" into a new file
  fsverity: Add call back to decide if verity check has to be performed
  fsverity: Add call back to determine readpage limit
  fs/mpage.c: Integrate post read processing
  ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]
  Remove the term "bio" from post read processing
  Add decryption support for sub-pagesized blocks
  ext4: Decrypt all boundary blocks when doing buffered write
  ext4: Decrypt the block that needs to be partially zeroed
  fscrypt_encrypt_page: Loop across all blocks mapped by a page range
  ext4: Compute logical block and the page range to be encrypted
  fscrypt_zeroout_range: Encrypt all zeroed out blocks of a page
  ext4: Enable encryption for subpage-sized blocks

 Documentation/filesystems/fscrypt.rst |   4 +-
 fs/Makefile   |   4 +
 fs/buffer.c   |  83 +++--
 fs/crypto/bio.c   | 111 ---
 fs/crypto/crypto.c|  73 +++--
 fs/crypto/fscrypt_private.h   |   3 +
 fs/ext4/Makefile  |   2 +-
 fs/ext4/ext4.h|   2 -
 fs/ext4/inode.c   |  47 ++-
 fs/ext4/page-io.c |   9 +-
 fs/ext4/readpage.c| 445 --
 fs/ext4/super.c   |  39 ++-
 fs/f2fs/data.c| 148 ++---
 fs/f2fs/super.c   |  15 +-
 fs/mpage.c|  51 ++-
 fs/post_read_process.c| 155 +
 fs/verity/verify.c|  12 +
 include/linux/buffer_head.h   |   1 +
 include/linux/fscrypt.h   |  20 +-
 include/linux/fsverity.h  |   2 +
 include/linux/post_read_process.h |  22 ++
 21 files changed, 516 insertions(+), 732 deletions(-)
 delete mode 100644 fs/ext4/readpage.c
 create mode 100644 fs/post_read_process.c
 create mode 100644 include/linux/post_read_process.h

-- 
2.19.1



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


[f2fs-dev] [PATCH V1 08/14] Add decryption support for sub-pagesized blocks

2019-04-23 Thread Chandan Rajendra
To support decryption of sub-pagesized blocks this commit adds code to,
1. Track buffer head in "struct post_read_ctx".
2. Pass buffer head argument to all "post read" processing functions.
3. In the corresponding endio, loop across all the blocks mapped by the
   page, decrypting each block in turn.

Signed-off-by: Chandan Rajendra 
---
 fs/buffer.c   | 83 +++
 fs/crypto/bio.c   | 50 +--
 fs/crypto/crypto.c| 19 ++-
 fs/f2fs/data.c|  2 +-
 fs/mpage.c|  2 +-
 fs/post_read_process.c| 53 +---
 include/linux/buffer_head.h   |  1 +
 include/linux/post_read_process.h |  5 +-
 8 files changed, 154 insertions(+), 61 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index ce357602f471..5b693d1992dd 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -45,6 +45,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
@@ -245,11 +246,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t 
block)
return ret;
 }
 
-/*
- * I/O completion handler for block_read_full_page() - pages
- * which come unlocked at the end of I/O.
- */
-static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
+void end_buffer_page_read(struct buffer_head *bh)
 {
unsigned long flags;
struct buffer_head *first;
@@ -257,17 +254,7 @@ static void end_buffer_async_read(struct buffer_head *bh, 
int uptodate)
struct page *page;
int page_uptodate = 1;
 
-   BUG_ON(!buffer_async_read(bh));
-
page = bh->b_page;
-   if (uptodate) {
-   set_buffer_uptodate(bh);
-   } else {
-   clear_buffer_uptodate(bh);
-   buffer_io_error(bh, ", async page read");
-   SetPageError(page);
-   }
-
/*
 * Be _very_ careful from here on. Bad things can happen if
 * two buffer heads end IO at almost the same time and both
@@ -305,6 +292,44 @@ static void end_buffer_async_read(struct buffer_head *bh, 
int uptodate)
local_irq_restore(flags);
return;
 }
+EXPORT_SYMBOL(end_buffer_page_read);
+
+/*
+ * I/O completion handler for block_read_full_page() - pages
+ * which come unlocked at the end of I/O.
+ */
+static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
+{
+   struct page *page;
+
+   BUG_ON(!buffer_async_read(bh));
+
+#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
+   if (uptodate && bh->b_private) {
+   struct post_read_ctx *ctx = bh->b_private;
+
+   post_read_processing(ctx);
+   return;
+   }
+
+   if (bh->b_private) {
+   struct post_read_ctx *ctx = bh->b_private;
+
+   WARN_ON(uptodate);
+   put_post_read_ctx(ctx);
+   }
+#endif
+   page = bh->b_page;
+   if (uptodate) {
+   set_buffer_uptodate(bh);
+   } else {
+   clear_buffer_uptodate(bh);
+   buffer_io_error(bh, ", async page read");
+   SetPageError(page);
+   }
+
+   end_buffer_page_read(bh);
+}
 
 /*
  * Completion handler for block_write_full_page() - pages which are unlocked
@@ -2220,7 +2245,11 @@ int block_read_full_page(struct page *page, get_block_t 
*get_block)
 {
struct inode *inode = page->mapping->host;
sector_t iblock, lblock;
-   struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
+   struct buffer_head *bh, *head;
+   struct {
+   sector_t blk_nr;
+   struct buffer_head *bh;
+   } arr[MAX_BUF_PER_PAGE];
unsigned int blocksize, bbits;
int nr, i;
int fully_mapped = 1;
@@ -2262,7 +2291,9 @@ int block_read_full_page(struct page *page, get_block_t 
*get_block)
if (buffer_uptodate(bh))
continue;
}
-   arr[nr++] = bh;
+   arr[nr].blk_nr = iblock;
+   arr[nr].bh = bh;
+   ++nr;
} while (i++, iblock++, (bh = bh->b_this_page) != head);
 
if (fully_mapped)
@@ -2281,7 +2312,7 @@ int block_read_full_page(struct page *page, get_block_t 
*get_block)
 
/* Stage two: lock the buffers */
for (i = 0; i < nr; i++) {
-   bh = arr[i];
+   bh = arr[i].bh;
lock_buffer(bh);
mark_buffer_async_read(bh);
}
@@ -2292,11 +2323,21 @@ int block_read_full_page(struct page *page, get_block_t 
*get_block)
 * the underlying blockdev brought it uptodate (the sct fix).
 */
for (i = 0; i < nr; i++) {
-   bh = arr[i];
-   if (buffer_uptodate(bh))
+   bh = arr[i].bh;
+

[f2fs-dev] [PATCH V1 11/14] fscrypt_encrypt_page: Loop across all blocks mapped by a page range

2019-04-23 Thread Chandan Rajendra
For subpage-sized blocks, this commit now encrypts all blocks mapped by
a page range.

Signed-off-by: Chandan Rajendra 
---
 fs/crypto/crypto.c | 37 +
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index 4f0d832cae71..2d65b431563f 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -242,18 +242,26 @@ struct page *fscrypt_encrypt_page(const struct inode 
*inode,
 {
struct fscrypt_ctx *ctx;
struct page *ciphertext_page = page;
+   int i, page_nr_blks;
int err;
 
BUG_ON(len % FS_CRYPTO_BLOCK_SIZE != 0);
 
+   page_nr_blks = len >> inode->i_blkbits;
+
if (inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES) {
/* with inplace-encryption we just encrypt the page */
-   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num, page,
-ciphertext_page, len, offs,
-gfp_flags);
-   if (err)
-   return ERR_PTR(err);
-
+   for (i = 0; i < page_nr_blks; i++) {
+   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT,
+   lblk_num, page,
+   ciphertext_page,
+   i_blocksize(inode), offs,
+   gfp_flags);
+   if (err)
+   return ERR_PTR(err);
+   ++lblk_num;
+   offs += i_blocksize(inode);
+   }
return ciphertext_page;
}
 
@@ -269,12 +277,17 @@ struct page *fscrypt_encrypt_page(const struct inode 
*inode,
goto errout;
 
ctx->control_page = page;
-   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num,
-page, ciphertext_page, len, offs,
-gfp_flags);
-   if (err) {
-   ciphertext_page = ERR_PTR(err);
-   goto errout;
+
+   for (i = 0; i < page_nr_blks; i++) {
+   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num,
+   page, ciphertext_page,
+   i_blocksize(inode), offs, gfp_flags);
+   if (err) {
+   ciphertext_page = ERR_PTR(err);
+   goto errout;
+   }
+   ++lblk_num;
+   offs += i_blocksize(inode);
}
SetPagePrivate(ciphertext_page);
set_page_private(ciphertext_page, (unsigned long)ctx);
-- 
2.19.1



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


[f2fs-dev] [PATCH V1 14/14] ext4: Enable encryption for subpage-sized blocks

2019-04-23 Thread Chandan Rajendra
Now that we have the code to support encryption for subpage-sized
blocks, this commit removes the conditional check in filesystem mount
code.

The commit also changes the support statement in
Documentation/filesystems/fscrypt.rst to reflect the fact that
encryption of filesystems with blocksize less than page size now works.

Signed-off-by: Chandan Rajendra 
---
 Documentation/filesystems/fscrypt.rst | 4 ++--
 fs/ext4/super.c   | 7 ---
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/Documentation/filesystems/fscrypt.rst 
b/Documentation/filesystems/fscrypt.rst
index 08c23b60e016..ff2fea121da9 100644
--- a/Documentation/filesystems/fscrypt.rst
+++ b/Documentation/filesystems/fscrypt.rst
@@ -213,8 +213,8 @@ Contents encryption
 ---
 
 For file contents, each filesystem block is encrypted independently.
-Currently, only the case where the filesystem block size is equal to
-the system's page size (usually 4096 bytes) is supported.
+Starting from Linux kernel 5.3, encryption of filesystems with block
+size less than system's page size is supported.
 
 Each block's IV is set to the logical block number within the file as
 a little endian number, except that:
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 8e483afbaa2e..4acfefa98ec5 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4432,13 +4432,6 @@ static int ext4_fill_super(struct super_block *sb, void 
*data, int silent)
}
}
 
-   if ((DUMMY_ENCRYPTION_ENABLED(sbi) || ext4_has_feature_encrypt(sb)) &&
-   (blocksize != PAGE_SIZE)) {
-   ext4_msg(sb, KERN_ERR,
-"Unsupported blocksize for fs encryption");
-   goto failed_mount_wq;
-   }
-
if (DUMMY_ENCRYPTION_ENABLED(sbi) && !sb_rdonly(sb) &&
!ext4_has_feature_encrypt(sb)) {
ext4_set_feature_encrypt(sb);
-- 
2.19.1



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


[f2fs-dev] [PATCH V1 12/14] ext4: Compute logical block and the page range to be encrypted

2019-04-23 Thread Chandan Rajendra
For subpage-sized blocks, the initial logical block number mapped by a
page can be different from page->index. Hence this commit adds code to
compute the first logical block mapped by the page and also the page
range to be encrypted.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/page-io.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 3e9298e6a705..75485ee9e800 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -418,6 +418,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
 {
struct page *data_page = NULL;
struct inode *inode = page->mapping->host;
+   u64 page_blk;
unsigned block_start;
struct buffer_head *bh, *head;
int ret = 0;
@@ -478,10 +479,14 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
 
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) {
gfp_t gfp_flags = GFP_NOFS;
+   unsigned int page_bytes;
+
+   page_bytes = round_up(len, i_blocksize(inode));
+   page_blk = page->index << (PAGE_SHIFT - inode->i_blkbits);
 
retry_encrypt:
-   data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0,
-   page->index, gfp_flags);
+   data_page = fscrypt_encrypt_page(inode, page, page_bytes, 0,
+   page_blk, gfp_flags);
if (IS_ERR(data_page)) {
ret = PTR_ERR(data_page);
if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
-- 
2.19.1



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


[f2fs-dev] [PATCH V1 13/14] fscrypt_zeroout_range: Encrypt all zeroed out blocks of a page

2019-04-23 Thread Chandan Rajendra
For subpage-sized blocks, this commit adds code to encrypt all zeroed
out blocks mapped by a page.

Signed-off-by: Chandan Rajendra 
---
 fs/crypto/bio.c | 40 ++--
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 1fd063082bbb..b521cd862a1c 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -108,29 +108,23 @@ EXPORT_SYMBOL(fscrypt_pullback_bio_page);
 int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len)
 {
-   struct fscrypt_ctx *ctx;
struct page *ciphertext_page = NULL;
struct bio *bio;
+   u64 total_bytes, page_bytes;
int ret, err = 0;
 
-   BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE);
-
-   ctx = fscrypt_get_ctx(inode, GFP_NOFS);
-   if (IS_ERR(ctx))
-   return PTR_ERR(ctx);
+   total_bytes = len << inode->i_blkbits;
 
-   ciphertext_page = fscrypt_alloc_bounce_page(ctx, GFP_NOWAIT);
-   if (IS_ERR(ciphertext_page)) {
-   err = PTR_ERR(ciphertext_page);
-   goto errout;
-   }
+   while (total_bytes) {
+   page_bytes = min_t(u64, total_bytes, PAGE_SIZE);
 
-   while (len--) {
-   err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk,
-ZERO_PAGE(0), ciphertext_page,
-PAGE_SIZE, 0, GFP_NOFS);
-   if (err)
+   ciphertext_page = fscrypt_encrypt_page(inode, ZERO_PAGE(0),
+   page_bytes, 0, lblk, GFP_NOFS);
+   if (IS_ERR(ciphertext_page)) {
+   err = PTR_ERR(ciphertext_page);
+   ciphertext_page = NULL;
goto errout;
+   }
 
bio = bio_alloc(GFP_NOWAIT, 1);
if (!bio) {
@@ -141,9 +135,8 @@ int fscrypt_zeroout_range(const struct inode *inode, 
pgoff_t lblk,
bio->bi_iter.bi_sector =
pblk << (inode->i_sb->s_blocksize_bits - 9);
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
-   ret = bio_add_page(bio, ciphertext_page,
-   inode->i_sb->s_blocksize, 0);
-   if (ret != inode->i_sb->s_blocksize) {
+   ret = bio_add_page(bio, ciphertext_page, page_bytes, 0);
+   if (ret != page_bytes) {
/* should never happen! */
WARN_ON(1);
bio_put(bio);
@@ -156,12 +149,15 @@ int fscrypt_zeroout_range(const struct inode *inode, 
pgoff_t lblk,
bio_put(bio);
if (err)
goto errout;
-   lblk++;
-   pblk++;
+
+   lblk += page_bytes >> inode->i_blkbits;
+   pblk += page_bytes >> inode->i_blkbits;
+   total_bytes -= page_bytes;
}
err = 0;
 errout:
-   fscrypt_release_ctx(ctx);
+   if (!IS_ERR_OR_NULL(ciphertext_page))
+   fscrypt_restore_control_page(ciphertext_page);
return err;
 }
 EXPORT_SYMBOL(fscrypt_zeroout_range);
-- 
2.19.1



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


[f2fs-dev] [PATCH V1 07/14] Remove the term "bio" from post read processing

2019-04-23 Thread Chandan Rajendra
For block size < page size, apart from handling bios, post read
processing needs to handle buffer heads. Hence this commit removes the
term "bio" from the identifiers associated with post read processing.

Signed-off-by: Chandan Rajendra 
---
 fs/crypto/bio.c   |  6 ++--
 fs/f2fs/data.c| 10 +++---
 fs/mpage.c| 10 +++---
 fs/post_read_process.c| 56 +++
 fs/verity/verify.c|  6 ++--
 include/linux/post_read_process.h | 16 -
 6 files changed, 52 insertions(+), 52 deletions(-)

diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 3e40d65ae6a8..bab48dfa3765 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -58,12 +58,12 @@ EXPORT_SYMBOL(fscrypt_decrypt_bio);
 
 void fscrypt_decrypt_work(struct work_struct *work)
 {
-   struct bio_post_read_ctx *ctx =
-   container_of(work, struct bio_post_read_ctx, work);
+   struct post_read_ctx *ctx =
+   container_of(work, struct post_read_ctx, work);
 
fscrypt_decrypt_bio(ctx->bio);
 
-   bio_post_read_processing(ctx);
+   post_read_processing(ctx);
 }
 
 void fscrypt_pullback_bio_page(struct page **page, bool restore)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 2f62244f6d24..f00f018bed27 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -89,10 +89,10 @@ static void __read_end_io(struct bio *bio)
 
 #if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
if (bio->bi_private) {
-   struct bio_post_read_ctx *ctx;
+   struct post_read_ctx *ctx;
 
ctx = bio->bi_private;
-   put_bio_post_read_ctx(ctx);
+   put_post_read_ctx(ctx);
}
 #endif
bio_put(bio);
@@ -108,7 +108,7 @@ static void f2fs_read_end_io(struct bio *bio)
 
 #if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
if (!bio->bi_status && bio->bi_private) {
-   bio_post_read_processing((struct bio_post_read_ctx 
*)(bio->bi_private));
+   post_read_processing((struct post_read_ctx *)(bio->bi_private));
return;
}
 #endif
@@ -514,7 +514,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, 
block_t blkaddr,
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct bio *bio;
 #if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
-   struct bio_post_read_ctx *ctx;
+   struct post_read_ctx *ctx;
 #endif
if (!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC))
return ERR_PTR(-EFAULT);
@@ -527,7 +527,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, 
block_t blkaddr,
bio_set_op_attrs(bio, REQ_OP_READ, op_flag);
 
 #if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
-   ctx = get_bio_post_read_ctx(inode, bio, first_idx);
+   ctx = get_post_read_ctx(inode, bio, first_idx);
if (IS_ERR(ctx)) {
bio_put(bio);
return (struct bio *)ctx;
diff --git a/fs/mpage.c b/fs/mpage.c
index 9c291d6ddab6..938f00984ba1 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -56,16 +56,16 @@ static void mpage_end_io(struct bio *bio)
 
 #if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
if (!bio->bi_status && bio->bi_private) {
-   struct bio_post_read_ctx *ctx;
+   struct post_read_ctx *ctx;
 
ctx = bio->bi_private;
 
-   bio_post_read_processing(ctx);
+   post_read_processing(ctx);
return;
}
 
if (bio->bi_private)
-   put_bio_post_read_ctx((struct bio_post_read_ctx 
*)(bio->bi_private));
+   put_post_read_ctx((struct post_read_ctx *)(bio->bi_private));
 #endif
 
bio_for_each_segment_all(bv, bio, i, iter_all) {
@@ -332,7 +332,7 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
 alloc_new:
if (args->bio == NULL) {
 #if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
-   struct bio_post_read_ctx *ctx;
+   struct post_read_ctx *ctx;
 #endif
if (first_hole == blocks_per_page
&& !(IS_ENCRYPTED(inode) || IS_VERITY(inode))) {
@@ -348,7 +348,7 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
goto confused;
 
 #if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
-   ctx = get_bio_post_read_ctx(inode, args->bio, page->index);
+   ctx = get_post_read_ctx(inode, args->bio, page->index);
if (IS_ERR(ctx)) {
bio_put(args->bio);
args->bio = NULL;
diff --git a/fs/post_read_process.c b/fs/post_read_process.c
index b60be77c7217..a9ea0dca23bc 100644
--- a/fs/post_read_process.c
+++ b/fs/post_read_proces

[f2fs-dev] [PATCH V1 10/14] ext4: Decrypt the block that needs to be partially zeroed

2019-04-23 Thread Chandan Rajendra
__ext4_block_zero_page_range decrypts the entire page. This commit
decrypts the block to be partially zeroed instead of the whole page.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/inode.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 51744a3c3964..ade1816697a8 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4080,9 +4080,10 @@ static int __ext4_block_zero_page_range(handle_t *handle,
if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) {
/* We expect the key to be set. */
BUG_ON(!fscrypt_has_encryption_key(inode));
-   BUG_ON(blocksize != PAGE_SIZE);
WARN_ON_ONCE(fscrypt_decrypt_page(page->mapping->host,
-   page, PAGE_SIZE, 0, 
page->index));
+   page, blocksize,
+   round_down(offset, 
blocksize),
+   iblock));
}
}
if (ext4_should_journal_data(inode)) {
-- 
2.19.1



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


Re: [f2fs-dev] [PATCH V1 02/14] Consolidate "post read processing" into a new file

2019-04-24 Thread Chandan Rajendra
On Wednesday, April 24, 2019 11:05:44 AM IST Christoph Hellwig wrote:
> On Wed, Apr 24, 2019 at 10:07:18AM +0530, Chandan Rajendra wrote:
> > +ifeq (y, $(firstword $(filter y,$(CONFIG_FS_ENCRYPTION) 
> > $(CONFIG_FS_VERITY
> > +obj-y +=   post_read_process.o
> > +endif
> 
> Please just add a new config option selected by the users.
>

Hi Christoph,

To clarify, Are you suggesting that a new kconfig option (say
CONFIG_FS_READ_CALLBACKS) be provided to the user so that the following could
occur,

1. User selects CONFIG_FS_ENCRYPTION and/or CONFIG_FS_VERITY and this causes
CONFIG_FS_READ_CALLBACKS to be set to 'y'.
2. User selects CONFIG_FS_READ_CALLBACKS explicitly.


> Also I find the file name rather cumbersome.  Maybe just
> read-callbacks.[co] ?
> 

I will do this.

-- 
chandan





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


[f2fs-dev] [PATCH V1 04/14] fsverity: Add call back to determine readpage limit

2019-04-23 Thread Chandan Rajendra
Ext4 and F2FS store verity metadata beyond i_size. This commit adds a
call back pointer to "struct fsverity_operations" which helps in
determining the the real file size limit upto which data can be read
from the file.

This call back will be required in order to get do_mpage_readpage()
to read files having verity metadata appended beyond i_size.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/super.c  | 17 +
 include/linux/fsverity.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 63d73b360f1d..8e483afbaa2e 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1428,6 +1428,22 @@ static struct page 
*ext4_read_verity_metadata_page(struct inode *inode,
return read_mapping_page(inode->i_mapping, index, NULL);
 }
 
+static loff_t ext4_readpage_limit(struct inode *inode)
+{
+   if (IS_VERITY(inode)) {
+   if (inode->i_verity_info)
+   /* limit to end of metadata region */
+   return fsverity_full_i_size(inode);
+   /*
+* fsverity_info is currently being set up and no user reads are
+* allowed yet.  It's easiest to just not enforce a limit yet.
+*/
+   return inode->i_sb->s_maxbytes;
+   }
+
+   return i_size_read(inode);
+}
+
 static bool ext4_verity_required(struct inode *inode, pgoff_t index)
 {
return index < (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -1438,6 +1454,7 @@ static const struct fsverity_operations ext4_verityops = {
.get_metadata_end   = ext4_get_verity_metadata_end,
.read_metadata_page = ext4_read_verity_metadata_page,
.verity_required= ext4_verity_required,
+   .readpage_limit = ext4_readpage_limit,
 };
 #endif /* CONFIG_FS_VERITY */
 
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index b83712d6c79a..fc8113acbbfe 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -19,6 +19,7 @@ struct fsverity_operations {
int (*get_metadata_end)(struct inode *inode, loff_t *metadata_end_ret);
struct page *(*read_metadata_page)(struct inode *inode, pgoff_t index);
bool (*verity_required)(struct inode *inode, pgoff_t index);
+   loff_t (*readpage_limit)(struct inode *inode);
 };
 
 #ifdef CONFIG_FS_VERITY
-- 
2.19.1



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


[f2fs-dev] [PATCH V1 02/14] Consolidate "post read processing" into a new file

2019-04-23 Thread Chandan Rajendra
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 
---
 fs/Makefile   |   4 +
 fs/crypto/bio.c   |  23 ++--
 fs/crypto/crypto.c|  17 +--
 fs/crypto/fscrypt_private.h   |   3 +
 fs/ext4/ext4.h|   2 -
 fs/ext4/readpage.c| 175 --
 fs/ext4/super.c   |   9 +-
 fs/f2fs/data.c| 146 -
 fs/f2fs/super.c   |   9 +-
 fs/post_read_process.c| 136 +++
 fs/verity/verify.c|  12 ++
 include/linux/fscrypt.h   |  20 +---
 include/linux/post_read_process.h |  21 
 13 files changed, 240 insertions(+), 337 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 9dd2186e74b5..f9abc3f71d3c 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -21,6 +21,10 @@ else
 obj-y +=   no-block.o
 endif
 
+ifeq (y, $(firstword $(filter y,$(CONFIG_FS_ENCRYPTION) $(CONFIG_FS_VERITY
+obj-y +=   post_read_process.o
+endif
+
 obj-$(CONFIG_PROC_FS) += proc_namespace.o
 
 obj-y  += notify/
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 5759bcd018cd..3e40d65ae6a8 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -24,6 +24,8 @@
 #include 
 #include 
 #include 
+#include 
+
 #include "fscrypt_private.h"
 
 static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
@@ -54,24 +56,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(>r.work, completion_pages);
-   ctx->r.bio = bio;
-   fscrypt_enqueue_decrypt_work(>r.work);
+   bio_post_read_processing(ctx);
 }
-EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
 
 void fscrypt_pullback_bio_page(struct page **page, bool restore)
 {
@@ -87,7 +80,7 @@ void fscrypt_pullback_bio_page(struct page **page, bool 
restore)
ctx = (struct fscrypt_ctx *)page_private(bounce_page);
 
/* restore control page */
-   *page = ctx->w.control_page;
+   *page = ctx->control_page;
 
if (restore)
fscrypt_restore_control_page(bounce_page);
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index 3fc84bf2b1e5..ffa9302a7351 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);
@@ -70,11 +71,11 @@ void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
 {
unsigned long flags;
 
-   if (ctx->flags & FS_CTX_HAS_BOUNCE_BUFFER_FL && ctx->w.bounce_page) {
-   mempool_free(ctx->w.bounce_page, fscrypt_bounce_page_pool);
-   ctx->w.bounce_page = NULL;
+   if (ctx->flags & FS_CTX_HAS_BOUNCE_BUFFER_FL && ctx->bounce_page) {
+   mempool_free(ctx->bounce_page, fscrypt_bounce_page_pool);
+   ctx->bounce_page = NULL;
}
-   ctx->w.control_page = NULL;
+   ctx->control_page = NULL;
if (ctx->flags & FS_CTX_REQUIRES_FREE_ENCRYPT_FL) {
kmem_cache_free(fscrypt_ctx_cachep, ctx);
} else {
@@ -194,11 +195,11 @@ int fscrypt_do_page_crypto(const struct inode *inode, 
fscrypt_direction_t rw,
 struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx,
   gfp_t gfp_flags)
 {
-   ctx->w.bounce_page = mempool_alloc(fscrypt_bounce_page_pool, gfp_flags);
-   if (ctx->w.bounce_page == NULL)
+   ctx->bounce_page = mempool_alloc(fscrypt_bounce_page_pool, gfp_flags);
+   if (ctx->bounce_page == NULL)
return ERR_PTR(-ENOMEM);
ctx->flags |= FS_CTX

[f2fs-dev] [PATCH V1 06/14] ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]

2019-04-23 Thread Chandan Rajendra
Now that do_mpage_readpage() is "post read process" aware, this commit
gets ext4_readpage[s] to use mpage_readpage[s] and deletes ext4's
readpage.c since the associated functionality is not required anymore.

Signed-off-by: Chandan Rajendra 
---
 fs/ext4/Makefile   |   2 +-
 fs/ext4/inode.c|   5 +-
 fs/ext4/readpage.c | 314 -
 3 files changed, 3 insertions(+), 318 deletions(-)
 delete mode 100644 fs/ext4/readpage.c

diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 8fdfcd3c3e04..7c38803a808d 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
 ext4-y := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \
indirect.o inline.o inode.o ioctl.o mballoc.o migrate.o \
-   mmp.o move_extent.o namei.o page-io.o readpage.o resize.o \
+   mmp.o move_extent.o namei.o page-io.o resize.o \
super.o symlink.o sysfs.o xattr.o xattr_trusted.o xattr_user.o
 
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)   += acl.o
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 05b258db8673..1327e04334df 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3353,8 +3353,7 @@ static int ext4_readpage(struct file *file, struct page 
*page)
ret = ext4_readpage_inline(inode, page);
 
if (ret == -EAGAIN)
-   return ext4_mpage_readpages(page->mapping, NULL, page, 1,
-   false);
+   return mpage_readpage(page, ext4_get_block);
 
return ret;
 }
@@ -3369,7 +3368,7 @@ ext4_readpages(struct file *file, struct address_space 
*mapping,
if (ext4_has_inline_data(inode))
return 0;
 
-   return ext4_mpage_readpages(mapping, pages, NULL, nr_pages, true);
+   return mpage_readpages(mapping, pages, nr_pages, ext4_get_block);
 }
 
 static void ext4_invalidatepage(struct page *page, unsigned int offset,
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
deleted file mode 100644
index 319deffbc105..
--- a/fs/ext4/readpage.c
+++ /dev/null
@@ -1,314 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/fs/ext4/readpage.c
- *
- * Copyright (C) 2002, Linus Torvalds.
- * Copyright (C) 2015, Google, Inc.
- *
- * This was originally taken from fs/mpage.c
- *
- * The intent is the ext4_mpage_readpages() function here is intended
- * to replace mpage_readpages() in the general case, not just for
- * encrypted files.  It has some limitations (see below), where it
- * will fall back to read_block_full_page(), but these limitations
- * should only be hit when page_size != block_size.
- *
- * This will allow us to attach a callback function to support ext4
- * encryption.
- *
- * If anything unusual happens, such as:
- *
- * - encountering a page which has buffers
- * - encountering a page which has a non-hole after a hole
- * - encountering a page with non-contiguous blocks
- *
- * then this code just gives up and calls the buffer_head-based read function.
- * It does handle a page which has holes at the end - that is a common case:
- * the end-of-file on blocksize < PAGE_SIZE setups.
- *
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "ext4.h"
-
-static inline bool ext4_bio_encrypted(struct bio *bio)
-{
-#ifdef CONFIG_FS_ENCRYPTION
-   return unlikely(bio->bi_private != NULL);
-#else
-   return false;
-#endif
-}
-
-/*
- * I/O completion handler for multipage BIOs.
- *
- * The mpage code never puts partial pages into a BIO (except for end-of-file).
- * If a page does not map to a contiguous run of blocks then it simply falls
- * back to block_read_full_page().
- *
- * Why is this?  If a page's completion depends on a number of different BIOs
- * which can complete in any order (or at the same time) then determining the
- * status of that page is hard.  See end_buffer_async_read() for the details.
- * There is no point in duplicating all that complexity.
- */
-static void mpage_end_io(struct bio *bio)
-{
-   struct bio_vec *bv;
-   int i;
-   struct bvec_iter_all iter_all;
-#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
-   if (bio_post_read_required(bio)) {
-   struct bio_post_read_ctx *ctx = bio->bi_private;
-
-   bio_post_read_processing(ctx);
-   return;
-   }
-#endif
-   bio_for_each_segment_all(bv, bio, i, iter_all) {
-   struct page *page = bv->bv_page;
-
-   if (!bio->bi_status) {
-   SetPageUptodate(page);
-   } else {
-   ClearPageUptodate(page);
-   SetPageError(page);
-   

[f2fs-dev] [PATCH V1 05/14] fs/mpage.c: Integrate post read processing

2019-04-23 Thread Chandan Rajendra
This commit adds code to make do_mpage_readpage() to be "post read
processing" aware i.e. for files requiring decryption/verification,
do_mpage_readpage() now allocates a context structure and assigns the
corresponding pointer to bio->bi_private. At endio time, a non-zero
bio->bi_private indicates that after the read operation is performed, the
bio's payload needs to be processed further before handing over the data
to user space.

The context structure is used for tracking the state machine associated
with post read processing.

Signed-off-by: Chandan Rajendra 
---
 fs/mpage.c | 51 ---
 1 file changed, 48 insertions(+), 3 deletions(-)

diff --git a/fs/mpage.c b/fs/mpage.c
index 3f19da75178b..9c291d6ddab6 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -30,6 +30,10 @@
 #include 
 #include 
 #include 
+#include 
+#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
+#include 
+#endif
 #include "internal.h"
 
 /*
@@ -50,6 +54,20 @@ static void mpage_end_io(struct bio *bio)
int i;
struct bvec_iter_all iter_all;
 
+#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
+   if (!bio->bi_status && bio->bi_private) {
+   struct bio_post_read_ctx *ctx;
+
+   ctx = bio->bi_private;
+
+   bio_post_read_processing(ctx);
+   return;
+   }
+
+   if (bio->bi_private)
+   put_bio_post_read_ctx((struct bio_post_read_ctx 
*)(bio->bi_private));
+#endif
+
bio_for_each_segment_all(bv, bio, i, iter_all) {
struct page *page = bv->bv_page;
page_endio(page, bio_op(bio),
@@ -189,7 +207,13 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
 
block_in_file = (sector_t)page->index << (PAGE_SHIFT - blkbits);
last_block = block_in_file + args->nr_pages * blocks_per_page;
-   last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits;
+#ifdef CONFIG_FS_VERITY
+   if (IS_VERITY(inode) && inode->i_sb->s_vop->readpage_limit)
+   last_block_in_file = inode->i_sb->s_vop->readpage_limit(inode);
+   else
+#endif
+   last_block_in_file = (i_size_read(inode) + blocksize - 1)
+   >> blkbits;
if (last_block > last_block_in_file)
last_block = last_block_in_file;
page_block = 0;
@@ -277,6 +301,14 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
if (first_hole != blocks_per_page) {
zero_user_segment(page, first_hole << blkbits, PAGE_SIZE);
if (first_hole == 0) {
+#ifdef CONFIG_FS_VERITY
+   if (IS_VERITY(inode)) {
+   if (!fsverity_check_hole(inode, page)) {
+   SetPageError(page);
+   goto confused;
+   }
+   }
+#endif
SetPageUptodate(page);
unlock_page(page);
goto out;
@@ -299,7 +331,11 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
 
 alloc_new:
if (args->bio == NULL) {
-   if (first_hole == blocks_per_page) {
+#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
+   struct bio_post_read_ctx *ctx;
+#endif
+   if (first_hole == blocks_per_page
+   && !(IS_ENCRYPTED(inode) || IS_VERITY(inode))) {
if (!bdev_read_page(bdev, blocks[0] << (blkbits - 9),
page))
goto out;
@@ -310,6 +346,15 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
gfp);
if (args->bio == NULL)
goto confused;
+
+#if defined(CONFIG_FS_ENCRYPTION) || defined(CONFIG_FS_VERITY)
+   ctx = get_bio_post_read_ctx(inode, args->bio, page->index);
+   if (IS_ERR(ctx)) {
+   bio_put(args->bio);
+   args->bio = NULL;
+   goto confused;
+   }
+#endif
}
 
length = first_hole << blkbits;
@@ -331,7 +376,7 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
 confused:
if (args->bio)
args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
-   if (!PageUptodate(page))
+   if (!PageUptodate(page) && !PageError(page))
block_read_full_page(page, args->get_block);
else
unlock_page(page);
-- 
2.19.1



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


[f2fs-dev] [PATCH V4 0/8] Consolidate FS read I/O callbacks code

2019-08-16 Thread Chandan Rajendra
This patchset moves the "FS read I/O callbacks" code into a file of its
own (i.e. fs/read_callbacks.c) and modifies the generic
do_mpage_readpge() to make use of the functionality provided.

"FS read I/O callbacks" code implements the state machine that needs
to be executed after reading data from files that are encrypted and/or
have verity metadata associated with them.

With these changes in place, the patchset changes Ext4 to use
mpage_readpage[s] instead of its own custom ext4_readpage[s]()
functions. This is done to reduce duplication of code across
filesystems. Also, "FS read I/O callbacks" source files will be built
only if CONFIG_FS_ENCRYPTION is enabled.

The patchset also modifies fs/buffer.c to get file
encryption/decryption to work with subpage-sized blocks.

The patches can also be obtained from
https://github.com/chandanr/linux.git at branch subpage-encryption-v4.

Changelog:
V3 -> V4:
   1. A new buffer_head flag (i.e. BH_Read_Cb) is introduced to reliably
  check if a buffer head's content has to be decrypted.
   2. Fix layering violation. Now the code flow for decryption happens as shown 
below,
  FS => read callbacks => fscrypt
   3. Select FS_READ_CALLBACKS from FS specific kconfig file if FS_ENCRYPTION
  is enabled.
   4. Make 'struct read_callbacks_ctx' an opaque structure.
   5. Make use of FS' endio function rather than implementing one in read
  callbacks.
   6. Make read_callbacks.h self-contained.
   7. Split patchset to separate out ext4 and f2fs changes.
   
V2 -> V3:
1. Split the V2 patch "Consolidate 'read callbacks' into a new file" into
   three patches,
   - Introduce the read_callbacks functionality.
   - Convert encryption to use read_callbacks.
   - Remove union from struct fscrypt_context.
2. fs/Kconfig
   Do not explicitly set the default value of 'n' for FS_READ_CALLBACKS.
3. fs/crypto/Kconfig
   Select CONFIG_FS_READ_CALLBACKS only if CONFIG_BLOCK is selected.
4. Remove verity associated code in read_callbacks code.
5. Introduce a callback argument to read_callbacks_setup() function
   which gets invoked for each page for bio. F2FS uses this to perform
   custom operations like decrementing the value of f2fs_sb_info->nr_pages[].
6. Encapsulate the details of "read callbacks" (e.g. Usage of "struct
   read_callbacks *ctx") within its own functions. When CONFIG_FS_READ_CALLBACKS
   is set to 'n', the corresponding stub functions return approriate error
   values.
7. Split fscrypt_decrypt() function into fscrypt_decrypt_bio() and
   fscrypt_decrypt_bh().
8. Split end_read_callbacks() function into end_read_callbacks_bio() and
   end_read_callbacks_bh().

V1 -> V2:
1. Removed the phrase "post_read_process" from file names and
   functions. Instead we now use the phrase "read_callbacks" in its
   place.
2. When performing changes associated with (1), the changes made by
   the patch "Remove the term 'bio' from post read processing" are
   made in the earlier patch "Consolidate 'read callbacks' into a new
   file". Hence the patch "Remove the term 'bio' from post read
   processing" is removed from the patchset.

RFC V2 -> V1:
1. Test and verify FS_CFLG_OWN_PAGES subset of fscrypt_encrypt_page()
   code by executing fstests on UBIFS.
2. Implement F2fs function call back to check if the contents of a
   page holding a verity file's data needs to be verified.

RFC V1 -> RFC V2:
1. Describe the purpose of "Post processing code" in the cover letter.
2. Fix build errors when CONFIG_FS_VERITY is enabled.

Chandan Rajendra (8):
  buffer_head: Introduce BH_Read_Cb flag
  FS: Introduce read callbacks
  fs/mpage.c: Integrate read callbacks
  fs/buffer.c: add decryption support via read_callbacks
  f2fs: Use read_callbacks for decrypting file data
  ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]
  ext4: Enable encryption for subpage-sized blocks
  fscrypt: remove struct fscrypt_ctx

 Documentation/filesystems/fscrypt.rst |   4 +-
 fs/Kconfig|   3 +
 fs/Makefile   |   1 +
 fs/buffer.c   |  33 ++-
 fs/crypto/bio.c   |  43 
 fs/crypto/crypto.c|  89 +---
 fs/crypto/fscrypt_private.h   |   3 -
 fs/ext4/Kconfig   |   1 +
 fs/ext4/Makefile  |   2 +-
 fs/ext4/inode.c   |   5 +-
 fs/ext4/readpage.c| 295 --
 fs/ext4/super.c   |   7 -
 fs/f2fs/Kconfig   |   1 +
 fs/f2fs/data.c| 109 +-
 fs/f2fs/f2fs.h|   2 -
 fs/f2fs/super.c   |   9 +-
 fs/mpage.c|  24 ++-
 fs/read_callbacks.c   | 285 +
 include/linux/buffer_head

[f2fs-dev] [PATCH V4 6/8] ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]

2019-08-16 Thread Chandan Rajendra
Now that do_mpage_readpage() is "post read process" aware, this commit
gets ext4_readpage[s] to use mpage_readpage[s] and deletes ext4's
readpage.c since the associated functionality is not required anymore.
---
 fs/ext4/Makefile   |   2 +-
 fs/ext4/inode.c|   5 +-
 fs/ext4/readpage.c | 295 -
 3 files changed, 3 insertions(+), 299 deletions(-)
 delete mode 100644 fs/ext4/readpage.c

diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 8fdfcd3c3e04..7c38803a808d 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
 ext4-y := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \
indirect.o inline.o inode.o ioctl.o mballoc.o migrate.o \
-   mmp.o move_extent.o namei.o page-io.o readpage.o resize.o \
+   mmp.o move_extent.o namei.o page-io.o resize.o \
super.o symlink.o sysfs.o xattr.o xattr_trusted.o xattr_user.o
 
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)   += acl.o
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 58597db621e1..a1136faed9d3 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3361,8 +3361,7 @@ static int ext4_readpage(struct file *file, struct page 
*page)
ret = ext4_readpage_inline(inode, page);
 
if (ret == -EAGAIN)
-   return ext4_mpage_readpages(page->mapping, NULL, page, 1,
-   false);
+   return mpage_readpage(page, ext4_get_block);
 
return ret;
 }
@@ -3377,7 +3376,7 @@ ext4_readpages(struct file *file, struct address_space 
*mapping,
if (ext4_has_inline_data(inode))
return 0;
 
-   return ext4_mpage_readpages(mapping, pages, NULL, nr_pages, true);
+   return mpage_readpages(mapping, pages, nr_pages, ext4_get_block);
 }
 
 static void ext4_invalidatepage(struct page *page, unsigned int offset,
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
deleted file mode 100644
index 75cef6af6080..
--- a/fs/ext4/readpage.c
+++ /dev/null
@@ -1,295 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/fs/ext4/readpage.c
- *
- * Copyright (C) 2002, Linus Torvalds.
- * Copyright (C) 2015, Google, Inc.
- *
- * This was originally taken from fs/mpage.c
- *
- * The intent is the ext4_mpage_readpages() function here is intended
- * to replace mpage_readpages() in the general case, not just for
- * encrypted files.  It has some limitations (see below), where it
- * will fall back to read_block_full_page(), but these limitations
- * should only be hit when page_size != block_size.
- *
- * This will allow us to attach a callback function to support ext4
- * encryption.
- *
- * If anything unusual happens, such as:
- *
- * - encountering a page which has buffers
- * - encountering a page which has a non-hole after a hole
- * - encountering a page with non-contiguous blocks
- *
- * then this code just gives up and calls the buffer_head-based read function.
- * It does handle a page which has holes at the end - that is a common case:
- * the end-of-file on blocksize < PAGE_SIZE setups.
- *
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "ext4.h"
-
-static inline bool ext4_bio_encrypted(struct bio *bio)
-{
-#ifdef CONFIG_FS_ENCRYPTION
-   return unlikely(bio->bi_private != NULL);
-#else
-   return false;
-#endif
-}
-
-/*
- * I/O completion handler for multipage BIOs.
- *
- * The mpage code never puts partial pages into a BIO (except for end-of-file).
- * If a page does not map to a contiguous run of blocks then it simply falls
- * back to block_read_full_page().
- *
- * Why is this?  If a page's completion depends on a number of different BIOs
- * which can complete in any order (or at the same time) then determining the
- * status of that page is hard.  See end_buffer_async_read() for the details.
- * There is no point in duplicating all that complexity.
- */
-static void mpage_end_io(struct bio *bio)
-{
-   struct bio_vec *bv;
-   int i;
-   struct bvec_iter_all iter_all;
-
-   if (ext4_bio_encrypted(bio)) {
-   if (bio->bi_status) {
-   fscrypt_release_ctx(bio->bi_private);
-   } else {
-   fscrypt_enqueue_decrypt_bio(bio->bi_private, bio);
-   return;
-   }
-   }
-   bio_for_each_segment_all(bv, bio, i, iter_all) {
-   struct page *page = bv->bv_page;
-
-   if (!bio->bi_status) {
-   SetPageUptodate(page);
-   } else {
-   ClearPageUptodate(page);
-   SetPageError(page);
-   }
-   unlock_page(page);
-   }
-
-   bio_put(bio);

[f2fs-dev] [PATCH V4 2/8] FS: Introduce read callbacks

2019-08-16 Thread Chandan Rajendra
Read callbacks implements a state machine to be executed after a
buffered read I/O is completed. They help in further processing the file
data read from the backing store. Currently, decryption is the only post
processing step to be supported.

The execution of the state machine is to be initiated by the endio
function associated with the read operation.

Signed-off-by: Chandan Rajendra 
---
 fs/Kconfig |   3 +
 fs/Makefile|   1 +
 fs/ext4/Kconfig|   1 +
 fs/f2fs/Kconfig|   1 +
 fs/read_callbacks.c| 285 +
 include/linux/read_callbacks.h |  48 ++
 6 files changed, 339 insertions(+)
 create mode 100644 fs/read_callbacks.c
 create mode 100644 include/linux/read_callbacks.h

diff --git a/fs/Kconfig b/fs/Kconfig
index 3e6d3101f3ff..2d96a58d7418 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -20,6 +20,9 @@ if BLOCK
 config FS_IOMAP
bool
 
+config FS_READ_CALLBACKS
+   bool
+
 source "fs/ext2/Kconfig"
 source "fs/ext4/Kconfig"
 source "fs/jbd2/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index 427fec226fae..942808f83472 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_SYSCTL)  += drop_caches.o
 
 obj-$(CONFIG_FHANDLE)  += fhandle.o
 obj-$(CONFIG_FS_IOMAP) += iomap.o
+obj-$(CONFIG_FS_READ_CALLBACKS) += read_callbacks.o
 
 obj-y  += quota/
 
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index 06f77ca7f36e..2e24df67f085 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -38,6 +38,7 @@ config EXT4_FS
select CRYPTO
select CRYPTO_CRC32C
select FS_IOMAP
+   select FS_READ_CALLBACKS if FS_ENCRYPTION
help
  This is the next generation of the ext3 filesystem.
 
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
index e57cc754d543..1e1424940d1b 100644
--- a/fs/f2fs/Kconfig
+++ b/fs/f2fs/Kconfig
@@ -4,6 +4,7 @@ config F2FS_FS
select CRYPTO
select CRYPTO_CRC32
select F2FS_FS_XATTR if FS_ENCRYPTION
+   select FS_READ_CALLBACKS if FS_ENCRYPTION
help
  F2FS is based on Log-structured File System (LFS), which supports
  versatile "flash-friendly" features. The design has been focused on
diff --git a/fs/read_callbacks.c b/fs/read_callbacks.c
new file mode 100644
index ..32d9b8d17964
--- /dev/null
+++ b/fs/read_callbacks.c
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file tracks the state machine that needs to be executed after reading
+ * data from files that are encrypted and/or have verity metadata associated
+ * with them.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define NUM_PREALLOC_READ_CALLBACK_CTXS128
+
+static struct kmem_cache *read_callbacks_ctx_cache;
+static mempool_t *read_callbacks_ctx_pool;
+
+/* Read callback state machine steps */
+enum read_callbacks_step {
+   STEP_INITIAL = 0,
+   STEP_DECRYPT,
+};
+
+struct read_callbacks_ctx {
+   struct inode *inode;
+   struct bio *bio;
+   struct buffer_head *bh;
+   union {
+   end_bio_func_t end_bio;
+
+   struct {
+   end_bh_func_t end_bh;
+   int bh_uptodate;
+   };
+   };
+   struct work_struct work;
+   unsigned int enabled_steps;
+   enum read_callbacks_step cur_step;
+};
+
+static void read_callbacks(struct read_callbacks_ctx *ctx);
+
+static void free_read_callbacks_ctx(struct read_callbacks_ctx *ctx)
+{
+   mempool_free(ctx, read_callbacks_ctx_pool);
+}
+
+static struct read_callbacks_ctx *get_read_callbacks_ctx(struct inode *inode)
+{
+   struct read_callbacks_ctx *ctx = NULL;
+   unsigned int enabled_steps = 0;
+
+   if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
+   enabled_steps |= 1 << STEP_DECRYPT;
+
+   if (enabled_steps) {
+   ctx = mempool_alloc(read_callbacks_ctx_pool, GFP_NOFS);
+   if (!ctx)
+   return ERR_PTR(-ENOMEM);
+
+   ctx->inode = inode;
+   ctx->enabled_steps = enabled_steps;
+   ctx->cur_step = STEP_INITIAL;
+   }
+
+   return ctx;
+}
+
+static void decrypt_bio(struct bio *bio)
+{
+   struct bio_vec *bv;
+   int i;
+   struct bvec_iter_all iter_all;
+
+   bio_for_each_segment_all(bv, bio, i, iter_all) {
+   struct page *page = bv->bv_page;
+   int ret = fscrypt_decrypt_pagecache_blocks(page, bv->bv_len,
+  bv->bv_offset);
+   if (ret)
+   SetPageError(page);
+   }
+}
+
+static void decrypt_bh(struct buffer_head *bh)
+{
+   struct page *page;
+   int ret;
+
+   page = bh

[f2fs-dev] [PATCH V4 4/8] fs/buffer.c: add decryption support via read_callbacks

2019-08-16 Thread Chandan Rajendra
This commit sets up read_callbacks context for buffer heads whose
contents need to be decrypted on endio.

Signed-off-by: Chandan Rajendra 
---
 fs/buffer.c | 33 ++---
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index ce357602f471..96c4c9840746 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -45,6 +45,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
@@ -245,11 +246,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t 
block)
return ret;
 }
 
-/*
- * I/O completion handler for block_read_full_page() - pages
- * which come unlocked at the end of I/O.
- */
-static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
+void end_buffer_async_read(struct buffer_head *bh, int uptodate)
 {
unsigned long flags;
struct buffer_head *first;
@@ -257,8 +254,6 @@ static void end_buffer_async_read(struct buffer_head *bh, 
int uptodate)
struct page *page;
int page_uptodate = 1;
 
-   BUG_ON(!buffer_async_read(bh));
-
page = bh->b_page;
if (uptodate) {
set_buffer_uptodate(bh);
@@ -306,6 +301,17 @@ static void end_buffer_async_read(struct buffer_head *bh, 
int uptodate)
return;
 }
 
+/*
+ * I/O completion handler for block_read_full_page().  Pages are unlocked
+ * after the I/O completes and the read callbacks (if any) have executed.
+ */
+static void __end_buffer_async_read(struct buffer_head *bh, int uptodate)
+{
+   BUG_ON(!buffer_async_read(bh));
+
+   read_callbacks_endio_bh(bh, uptodate, end_buffer_async_read);
+}
+
 /*
  * Completion handler for block_write_full_page() - pages which are unlocked
  * during I/O, and which have PageWriteback cleared upon I/O completion.
@@ -378,7 +384,7 @@ EXPORT_SYMBOL(end_buffer_async_write);
  */
 static void mark_buffer_async_read(struct buffer_head *bh)
 {
-   bh->b_end_io = end_buffer_async_read;
+   bh->b_end_io = __end_buffer_async_read;
set_buffer_async_read(bh);
 }
 
@@ -2293,10 +2299,15 @@ int block_read_full_page(struct page *page, get_block_t 
*get_block)
 */
for (i = 0; i < nr; i++) {
bh = arr[i];
-   if (buffer_uptodate(bh))
-   end_buffer_async_read(bh, 1);
-   else
+   if (buffer_uptodate(bh)) {
+   __end_buffer_async_read(bh, 1);
+   } else {
+   if (WARN_ON(read_callbacks_setup_bh(inode, bh))) {
+   __end_buffer_async_read(bh, 0);
+   continue;
+   }
submit_bh(REQ_OP_READ, 0, bh);
+   }
}
return 0;
 }
-- 
2.19.1



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


[f2fs-dev] [PATCH V4 7/8] ext4: Enable encryption for subpage-sized blocks

2019-08-16 Thread Chandan Rajendra
Now that we have the code to support encryption for subpage-sized
blocks, this commit removes the conditional check in filesystem mount
code.

The commit also changes the support statement in
Documentation/filesystems/fscrypt.rst to reflect the fact that
encryption of filesystems with blocksize less than page size now works.

Signed-off-by: Chandan Rajendra 
---
 Documentation/filesystems/fscrypt.rst | 4 ++--
 fs/ext4/super.c   | 7 ---
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/Documentation/filesystems/fscrypt.rst 
b/Documentation/filesystems/fscrypt.rst
index 08c23b60e016..c3efe86bf2b2 100644
--- a/Documentation/filesystems/fscrypt.rst
+++ b/Documentation/filesystems/fscrypt.rst
@@ -213,8 +213,8 @@ Contents encryption
 ---
 
 For file contents, each filesystem block is encrypted independently.
-Currently, only the case where the filesystem block size is equal to
-the system's page size (usually 4096 bytes) is supported.
+Starting from Linux kernel 5.4, encryption of filesystems with block
+size less than system's page size is supported.
 
 Each block's IV is set to the logical block number within the file as
 a little endian number, except that:
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 5b92054bf8ea..d580e71ad9c7 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4322,13 +4322,6 @@ static int ext4_fill_super(struct super_block *sb, void 
*data, int silent)
}
}
 
-   if ((DUMMY_ENCRYPTION_ENABLED(sbi) || ext4_has_feature_encrypt(sb)) &&
-   (blocksize != PAGE_SIZE)) {
-   ext4_msg(sb, KERN_ERR,
-"Unsupported blocksize for fs encryption");
-   goto failed_mount_wq;
-   }
-
if (DUMMY_ENCRYPTION_ENABLED(sbi) && !sb_rdonly(sb) &&
!ext4_has_feature_encrypt(sb)) {
ext4_set_feature_encrypt(sb);
-- 
2.19.1



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


[f2fs-dev] [PATCH V4 3/8] fs/mpage.c: Integrate read callbacks

2019-08-16 Thread Chandan Rajendra
This commit adds code to make do_mpage_readpage() to be "read callbacks"
aware i.e. for files requiring decryption, do_mpage_readpage() now
sets up the read callbacks state machine when allocating a bio and later
starts execution of the state machine after file data is read from the
underlying disk.

Signed-off-by: Chandan Rajendra 
---
 fs/mpage.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/fs/mpage.c b/fs/mpage.c
index 3f19da75178b..65e7165644e2 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "internal.h"
 
 /*
@@ -44,7 +45,7 @@
  * status of that page is hard.  See end_buffer_async_read() for the details.
  * There is no point in duplicating all that complexity.
  */
-static void mpage_end_io(struct bio *bio)
+static void end_bio(struct bio *bio)
 {
struct bio_vec *bv;
int i;
@@ -52,13 +53,24 @@ static void mpage_end_io(struct bio *bio)
 
bio_for_each_segment_all(bv, bio, i, iter_all) {
struct page *page = bv->bv_page;
-   page_endio(page, bio_op(bio),
-  blk_status_to_errno(bio->bi_status));
+   int err;
+
+   err = blk_status_to_errno(bio->bi_status);
+
+   if (!err && read_callbacks_failed(page))
+   err = -EIO;
+
+   page_endio(page, bio_op(bio), err);
}
 
bio_put(bio);
 }
 
+static void mpage_end_io(struct bio *bio)
+{
+   read_callbacks_endio_bio(bio, end_bio);
+}
+
 static struct bio *mpage_bio_submit(int op, int op_flags, struct bio *bio)
 {
bio->bi_end_io = mpage_end_io;
@@ -310,6 +322,12 @@ static struct bio *do_mpage_readpage(struct 
mpage_readpage_args *args)
gfp);
if (args->bio == NULL)
goto confused;
+
+   if (read_callbacks_setup_bio(inode, args->bio)) {
+   bio_put(args->bio);
+   args->bio = NULL;
+   goto confused;
+   }
}
 
length = first_hole << blkbits;
-- 
2.19.1



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


[f2fs-dev] [PATCH V4 5/8] f2fs: Use read_callbacks for decrypting file data

2019-08-16 Thread Chandan Rajendra
F2FS has a copy of "post read processing" code using which encrypted
file data is decrypted. This commit replaces it to make use of the
generic read_callbacks facility.

Signed-off-by: Chandan Rajendra 
---
 fs/f2fs/data.c  | 109 
 fs/f2fs/f2fs.h  |   2 -
 fs/f2fs/super.c |   9 +---
 3 files changed, 11 insertions(+), 109 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 757f050c650a..3cf1eca2ece9 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "f2fs.h"
 #include "node.h"
@@ -25,11 +26,6 @@
 #include "trace.h"
 #include 
 
-#define NUM_PREALLOC_POST_READ_CTXS128
-
-static struct kmem_cache *bio_post_read_ctx_cache;
-static mempool_t *bio_post_read_ctx_pool;
-
 static bool __is_cp_guaranteed(struct page *page)
 {
struct address_space *mapping = page->mapping;
@@ -69,19 +65,6 @@ static enum count_type __read_io_type(struct page *page)
return F2FS_RD_DATA;
 }
 
-/* postprocessing steps for read bios */
-enum bio_post_read_step {
-   STEP_INITIAL = 0,
-   STEP_DECRYPT,
-};
-
-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;
@@ -93,7 +76,7 @@ static void __read_end_io(struct bio *bio)
page = bv->bv_page;
 
/* PG_error was set if any post_read step failed */
-   if (bio->bi_status || PageError(page)) {
+   if (bio->bi_status || read_callbacks_failed(page)) {
ClearPageUptodate(page);
/* will re-read again later */
ClearPageError(page);
@@ -103,42 +86,8 @@ static void __read_end_io(struct bio *bio)
dec_page_count(F2FS_P_SB(page), __read_io_type(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 bio_post_read_processing(struct bio_post_read_ctx *ctx)
-{
-   switch (++ctx->cur_step) {
-   case STEP_DECRYPT:
-   if (ctx->enabled_steps & (1 << STEP_DECRYPT)) {
-   INIT_WORK(>work, decrypt_work);
-   fscrypt_enqueue_decrypt_work(>work);
-   return;
-   }
-   ctx->cur_step++;
-   /* fall-through */
-   default:
-   __read_end_io(ctx->bio);
-   }
-}
-
-static bool f2fs_bio_post_read_required(struct bio *bio)
-{
-   return bio->bi_private && !bio->bi_status;
+   bio_put(bio);
 }
 
 static void f2fs_read_end_io(struct bio *bio)
@@ -149,15 +98,7 @@ static void f2fs_read_end_io(struct bio *bio)
bio->bi_status = BLK_STS_IOERR;
}
 
-   if (f2fs_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);
+   read_callbacks_endio_bio(bio, __read_end_io);
 }
 
 static void f2fs_write_end_io(struct bio *bio)
@@ -556,8 +497,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, 
block_t blkaddr,
 {
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct bio *bio;
-   struct bio_post_read_ctx *ctx;
-   unsigned int post_read_steps = 0;
+   int err;
 
if (!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC))
return ERR_PTR(-EFAULT);
@@ -569,17 +509,10 @@ static struct bio *f2fs_grab_read_bio(struct inode 
*inode, block_t blkaddr,
bio->bi_end_io = f2fs_read_end_io;
bio_set_op_attrs(bio, REQ_OP_READ, op_flag);
 
-   if (f2fs_encrypted_file(inode))
-   post_read_steps |= 1 << STEP_DECRYPT;
-   if (post_read_steps) {
-   ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
-   if (!ctx) {
-   bio_put(bio);
-   return ERR_PTR(-ENOMEM);
-   }
-   ctx->bio = bio;
-   ctx->enabled_steps = post_read_steps;
-   bio->bi_private = ctx;
+   err = read_callbacks_setup_bio(inode, bio);
+   if (err) {
+   bio_put(bio);
+   

[f2fs-dev] [PATCH V4 8/8] fscrypt: remove struct fscrypt_ctx

2019-08-16 Thread Chandan Rajendra
Commit "fscrypt: remove the 'write' part of struct fscrypt_ctx" reduced
"struct fscrypt_ctx" to be used only for decryption. With "read
callbacks" being integrated into Ext4 and F2FS, we don't use "struct
fscrypt_ctx" anymore. Hence this commit removes the structure and the
associated code.

While at it, this commit also removes definitions of
__fscrypt_decrypt_bio() and fscrypt_decrypt_bio() since we have to now
use the APIs provided by read_callbacks facility.

Signed-off-by: Chandan Rajendra 
---
 fs/crypto/bio.c | 43 --
 fs/crypto/crypto.c  | 89 +
 fs/crypto/fscrypt_private.h |  3 --
 include/linux/fscrypt.h | 38 
 4 files changed, 2 insertions(+), 171 deletions(-)

diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index b4f47b98ee6d..f65cc3059e5c 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -26,49 +26,6 @@
 #include 
 #include "fscrypt_private.h"
 
-static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
-{
-   struct bio_vec *bv;
-   int i;
-   struct bvec_iter_all iter_all;
-
-   bio_for_each_segment_all(bv, bio, i, iter_all) {
-   struct page *page = bv->bv_page;
-   int ret = fscrypt_decrypt_pagecache_blocks(page, bv->bv_len,
-  bv->bv_offset);
-   if (ret)
-   SetPageError(page);
-   else if (done)
-   SetPageUptodate(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, work);
-   struct bio *bio = ctx->bio;
-
-   __fscrypt_decrypt_bio(bio, true);
-   fscrypt_release_ctx(ctx);
-   bio_put(bio);
-}
-
-void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio)
-{
-   INIT_WORK(>work, completion_pages);
-   ctx->bio = bio;
-   fscrypt_enqueue_decrypt_work(>work);
-}
-EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
-
 int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len)
 {
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index dcf630d7e446..2e5245f5639f 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -31,24 +31,16 @@
 #include "fscrypt_private.h"
 
 static unsigned int num_prealloc_crypto_pages = 32;
-static unsigned int num_prealloc_crypto_ctxs = 128;
 
 module_param(num_prealloc_crypto_pages, uint, 0444);
 MODULE_PARM_DESC(num_prealloc_crypto_pages,
"Number of crypto pages to preallocate");
-module_param(num_prealloc_crypto_ctxs, uint, 0444);
-MODULE_PARM_DESC(num_prealloc_crypto_ctxs,
-   "Number of crypto contexts to preallocate");
 
 static mempool_t *fscrypt_bounce_page_pool = NULL;
 
-static LIST_HEAD(fscrypt_free_ctxs);
-static DEFINE_SPINLOCK(fscrypt_ctx_lock);
-
 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)
@@ -57,62 +49,6 @@ void fscrypt_enqueue_decrypt_work(struct work_struct *work)
 }
 EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work);
 
-/**
- * fscrypt_release_ctx() - Release a decryption context
- * @ctx: The decryption context to release.
- *
- * If the decryption context was allocated from the pre-allocated pool, return
- * it to that pool.  Else, free it.
- */
-void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
-{
-   unsigned long flags;
-
-   if (ctx->flags & FS_CTX_REQUIRES_FREE_ENCRYPT_FL) {
-   kmem_cache_free(fscrypt_ctx_cachep, ctx);
-   } else {
-   spin_lock_irqsave(_ctx_lock, flags);
-   list_add(>free_list, _free_ctxs);
-   spin_unlock_irqrestore(_ctx_lock, flags);
-   }
-}
-EXPORT_SYMBOL(fscrypt_release_ctx);
-
-/**
- * fscrypt_get_ctx() - Get a decryption context
- * @gfp_flags:   The gfp flag for memory allocation
- *
- * Allocate and initialize a decryption context.
- *
- * Return: A new decryption context on success; an ERR_PTR() otherwise.
- */
-struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags)
-{
-   struct fscrypt_ctx *ctx;
-   unsigned long flags;
-
-   /*
-* First try getting a ctx from the free list so that we don't have to
-* call into the slab allocator.
-*/
-   spin_lock_irqsave(_ctx_lock, flags);
-   ctx = list_first_entry_or_null(_free_ctxs,
-   struct fscrypt_ctx, free_list);
-   if

[f2fs-dev] [PATCH V4 1/8] buffer_head: Introduce BH_Read_Cb flag

2019-08-16 Thread Chandan Rajendra
Decryption of file content encrypted using fscrypt relies on
bio->bi_private holding a pointer to an encryption context
i.e. Decryption operation is not performed for bios having a NULL value
at bio->bi_private.

The same logic cannot be used on buffer heads because,
1. In Btrfs, write_dev_supers() sets bh->b_private to 'struct
   btrfs_device' pointer and submits the buffer head for a write
   operation.
   1. In btrfs/146 test, the write operation fails and hence the
  endio function clears the BH_Uptodate flag.
   2. A read operation initiated later will submit the buffer head to
  the block layer. During endio processing, bh_>b_private would have a
  non-NULL value.

2. Another instance is when an Ext4 metadata block with BH_Uptodate set and
   also part of the in-memory JBD list undergoes the following,
   1. A sync() syscall is invoked by the userspace and the write
  operation on the metadata block is initiated.
   2. Due to an I/O failure, the BH_Uptodate flag is cleared by
  end_buffer_async_write(). The bh->b_private member would be
  pointing to a journal head structure.
   3. In such a case, a read operation invoked on the block mapped by the
  buffer head will initiate a read from the disk since the buffer head is
  missing the BH_Uptodate flag.
   4. After the read I/O request is submitted, end_buffer_async_read()
  will find a non-NULL value at bh->b_private.
   This scenario was observed when executing generic/475 test case.

Hence this commit introduces a new buffer head flag to reliably check for
decryption of a buffer head's contents after the block has been read
from the disk.

Signed-off-by: Chandan Rajendra 
---
 include/linux/buffer_head.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 7b73ef7f902d..08f217ba8114 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -38,6 +38,7 @@ enum bh_state_bits {
BH_Meta,/* Buffer contains metadata */
BH_Prio,/* Buffer should be submitted with REQ_PRIO */
BH_Defer_Completion, /* Defer AIO completion to workqueue */
+   BH_Read_Cb,  /* Block's contents needs to be decrypted */
 
BH_PrivateStart,/* not a state bit, but the first bit available
 * for private allocation by other entities
@@ -134,6 +135,7 @@ BUFFER_FNS(Unwritten, unwritten)
 BUFFER_FNS(Meta, meta)
 BUFFER_FNS(Prio, prio)
 BUFFER_FNS(Defer_Completion, defer_completion)
+BUFFER_FNS(Read_Cb, read_cb)
 
 #define bh_offset(bh)  ((unsigned long)(bh)->b_data & ~PAGE_MASK)
 
-- 
2.19.1



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


Re: [f2fs-dev] [PATCH V4 5/8] f2fs: Use read_callbacks for decrypting file data

2019-08-19 Thread Chandan Rajendra
On Friday, August 16, 2019 11:48 AM Chandan Rajendra wrote:
> F2FS has a copy of "post read processing" code using which encrypted
> file data is decrypted. This commit replaces it to make use of the
> generic read_callbacks facility.
> 
> Signed-off-by: Chandan Rajendra 

Hi Eric and Ted,

Looks like F2FS requires a lot more flexiblity than what can be offered by
read callbacks i.e.

1. F2FS wants to make use of its own workqueue for decryption, verity and
   decompression.
2. F2FS' decompression code is not an FS independent entity like fscrypt and
   fsverity. Hence they would need Filesystem specific callback functions to
   be invoked from "read callbacks". 

Hence I would suggest that we should drop F2FS changes made in this
patchset. Please let me know your thoughts on this.

-- 
chandan





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


Re: [f2fs-dev] [PATCH V4 5/8] f2fs: Use read_callbacks for decrypting file data

2019-08-19 Thread Chandan Rajendra
On Sunday, August 18, 2019 7:15:42 PM IST Chao Yu wrote:
> Hi Chandan,
> 
> On 2019-8-16 14:18, Chandan Rajendra wrote:
> > F2FS has a copy of "post read processing" code using which encrypted
> > file data is decrypted. This commit replaces it to make use of the
> > generic read_callbacks facility.
> 
> I remember that previously Jaegeuk had mentioned f2fs will support compression
> later, and it needs to reuse 'post read processing' fwk.
> 
> There is very initial version of compression feature in below link:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/chao/linux.git/log/?h=compression
> 
> So my concern is how can we uplift the most common parts of this fwk into vfs,
> and meanwhile keeping the ability and flexibility when introducing private
> feature/step in specified filesytem(now f2fs)?
> 
> According to current f2fs compression's requirement, maybe we can expand to
> 
> - support callback to let filesystem set the function for the flow in
> decompression/verity/decryption step.
> - support to use individual/common workqueue according the parameter.
> 
> Any thoughts?
>

Hi,

F2FS can be made to use fscrypt's queue for decryption and hence can reuse
"read callbacks" code for decrypting data.

For decompression, we could have a STEP_MISC where we invoke a FS provided
callback function for FS specific post read processing? 

Something like the following can be implemented in read_callbacks(),
  case STEP_MISC:
  if (ctx->enabled_steps & (1 << STEP_MISC)) {
  /*
ctx->fs_misc() must process bio in a workqueue
and later invoke read_callbacks() with
bio->bi_private's value as an argument.
  */
  ctx->fs_misc(ctx->bio);
  return;
  }
  ctx->cur_step++;

The fs_misc() callback can be passed in by the filesystem when invoking
read_callbacks_setup_bio().

-- 
chandan





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


Re: [f2fs-dev] [PATCH V4 5/8] f2fs: Use read_callbacks for decrypting file data

2019-08-20 Thread Chandan Rajendra
On Tuesday, August 20, 2019 11:01 PM Jaegeuk Kim wrote:
> Hi Chandan,
> 
> On 08/20, Theodore Y. Ts'o wrote:
> > On Tue, Aug 20, 2019 at 10:35:29AM +0530, Chandan Rajendra wrote:
> > > Looks like F2FS requires a lot more flexiblity than what can be offered by
> > > read callbacks i.e.
> > > 
> > > 1. F2FS wants to make use of its own workqueue for decryption, verity and
> > >decompression.
> > > 2. F2FS' decompression code is not an FS independent entity like fscrypt 
> > > and
> > >fsverity. Hence they would need Filesystem specific callback functions 
> > > to
> > >be invoked from "read callbacks". 
> > > 
> > > Hence I would suggest that we should drop F2FS changes made in this
> > > patchset. Please let me know your thoughts on this.
> > 
> > That's probably the best way to go for now.  My one concern is that it
> > means that only ext4 will be using your framework.  I could imagine
> > that some people might argue that should just move the callback scheme
> > into ext4 code as opposed to leaving it in fscrypt --- at least until
> > we can find other file systems where we can show that it will be
> > useful for those other file systems.
> 
> I also have to raise a flag on this. Doesn't this patch series try to get rid
> of redundant work? What'd be the rationale, if it only supports ext4?

This patchset gets encryption working with subpage blocksize by making
relevant changes in the generic code (i.e. do_mpage_readpage() and
block_read_full_page()) and removing duplicate code from ext4
(i.e. ext4_readpage() and friends). Without these changes the only way to get
subpage blocksize support was to add more duplicate code into Ext4 i.e. import
a copy of block_read_full_page() into Ext4 and make necessary edits to support
encryption.

So this patchset actually does help in removing exiting duplicate code in Ext4
and also prevents addition of more such code.

> 
> How about generalizing the framework to support generic_post_read and per-fs
> post_read for fscrypt/fsverity/... selectively?

Quoting what I had said earlier,
> > > 1. F2FS wants to make use of its own workqueue for decryption, verity and
> > >decompression.
> > > 2. F2FS' decompression code is not an FS independent entity like fscrypt 
> > > and
> > >fsverity. Hence they would need Filesystem specific callback functions 
> > > to
> > >be invoked from "read callbacks". 

I am not sure if read callbacks can be made flexible enough to support the
above use cases. fscrypt and fsverity already provide workqueues and any new
post processing code added should follow the same convention. I see
that F2FS use case is special since,
1. It uses its own workqueues.
2. Decompression code inside F2FS isn't written as an FS independent subsystem
   like how fscrypt and fsverity are implemented.

To summarize, I believe the users of read callbacks should follow the
conventions set by fscrypt/fsverity and new post processing code that needs to
be plugged into read callbacks should provide APIs similar to
fscrypt/fsverity. Otherwise the state machine logic implemented by read
callbacks will get complex/convoluted.

> 
> Thanks,
> 
> > 
> > (Perhaps a useful experiment would be to have someone implement patches
> > to support fscrypt and fsverity in ext2 --- the patch might or might
> > not be accepted for upstream inclusion, but it would be useful to
> > demonstrate how easy it is to add fscrypt and fsverity.)
> > 
> > The other thing to consider is that there has been some discussion
> > about adding generalized support for I/O submission to the iomap
> > library.  It might be that if that work is accepted, support for
> > fscrypt and fsverity would be a requirement for ext4 to use that
> > portion of iomap's functionality.  So in that eventuality, it might be
> > that we'll want to move your read callbacks code into iomap, or we'll
> > need to rework the read callbacks code so it can work with iomap.
> > 
> > But this is all work for the future.  I'm a firm believe that the
> > perfect should not be the enemy of the good, and that none of this
> > should be a fundamental obstacle in having your code upstream.
> > 
> > Cheers,
> > 
> > - Ted
> > 
> 

-- 
chandan





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


<    1   2