2019-02-18 10:04:14

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 00/10] Consolidate Post read processing code

This patchset moves the "post read processing" code into a file of its
own and gets the generic do_mpage_readpge() to make use of the
functionality provided. With these changes in place, the patchset
changes Ext4 to use mpage_readpage[s] instead of its own custom
ext4_readpages() function. This is done to reduce duplicity of code
across filesystems. Based on the reviews provided for this patchset, I
will change F2FS to use mpage_readpage[s] and post the next version of
this patchset to linux-fsdevel mailing list.

The patchset also includes patches from previous postings i.e.
patches to replace per-filesystem encryption config options with a
single config option that affects all filesystems making use of
fscrypt code.

Chandan Rajendra (10):
ext4: use IS_ENCRYPTED() to check encryption status
f2fs: use IS_ENCRYPTED() to check encryption status
fscrypt: remove filesystem specific build config option
Consolidate "post read processing" into a new file
fsverity: Add call back to decide if verity check has to be performed
Introduce REQ_POST_READ_PROC bio flag
fsverity: Add call back to determine readpage limit
fsverity: Add call back to verify file holes
fs/mpage.c: Integrate post read processing
ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]

Documentation/filesystems/fscrypt.rst | 4 +-
arch/mips/configs/generic_defconfig | 2 +-
arch/nds32/configs/defconfig | 2 +-
arch/s390/configs/debug_defconfig | 2 +-
arch/s390/configs/performance_defconfig | 2 +-
fs/Makefile | 3 +-
fs/crypto/Kconfig | 5 +-
fs/crypto/bio.c | 21 +-
fs/crypto/crypto.c | 1 +
fs/crypto/fscrypt_private.h | 4 +-
fs/ext4/Kconfig | 15 -
fs/ext4/Makefile | 2 +-
fs/ext4/dir.c | 10 +-
fs/ext4/ext4.h | 14 +-
fs/ext4/ext4_jbd2.h | 2 +-
fs/ext4/extents.c | 4 +-
fs/ext4/ialloc.c | 2 +-
fs/ext4/inode.c | 29 +-
fs/ext4/ioctl.c | 4 +-
fs/ext4/move_extent.c | 3 +-
fs/ext4/namei.c | 18 +-
fs/ext4/page-io.c | 9 +-
fs/ext4/readpage.c | 444 ------------------------
fs/ext4/super.c | 43 ++-
fs/ext4/sysfs.c | 4 +-
fs/f2fs/Kconfig | 12 +-
fs/f2fs/data.c | 4 +-
fs/f2fs/dir.c | 10 +-
fs/f2fs/f2fs.h | 14 +-
fs/f2fs/file.c | 10 +-
fs/f2fs/inode.c | 4 +-
fs/f2fs/namei.c | 6 +-
fs/f2fs/super.c | 8 +-
fs/f2fs/sysfs.c | 4 +-
fs/mpage.c | 77 +++-
fs/post_read_process.c | 128 +++++++
fs/ubifs/Kconfig | 12 +-
fs/ubifs/Makefile | 2 +-
fs/ubifs/ioctl.c | 4 +-
fs/ubifs/sb.c | 2 +-
fs/ubifs/super.c | 2 +-
fs/ubifs/ubifs.h | 5 +-
fs/verity/verify.c | 12 +
include/linux/blk_types.h | 2 +
include/linux/fs.h | 4 +-
include/linux/fscrypt.h | 405 ++++++++++++++++++++-
include/linux/fscrypt_notsupp.h | 231 ------------
include/linux/fscrypt_supp.h | 204 -----------
include/linux/fsverity.h | 3 +
include/linux/post_read_process.h | 21 ++
50 files changed, 757 insertions(+), 1078 deletions(-)
delete mode 100644 fs/ext4/readpage.c
create mode 100644 fs/post_read_process.c
delete mode 100644 include/linux/fscrypt_notsupp.h
delete mode 100644 include/linux/fscrypt_supp.h
create mode 100644 include/linux/post_read_process.h

--
2.19.1



2019-02-18 10:04:13

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 01/10] ext4: use IS_ENCRYPTED() to check encryption status

This commit removes the ext4 specific ext4_encrypted_inode() and makes
use of the generic IS_ENCRYPTED() macro to check for the encryption
status of an inode.

Reviewed-by: Eric Biggers <[email protected]>
Signed-off-by: Chandan Rajendra <[email protected]>
---
fs/ext4/dir.c | 8 ++++----
fs/ext4/ext4.h | 5 -----
fs/ext4/ext4_jbd2.h | 2 +-
fs/ext4/extents.c | 4 ++--
fs/ext4/ialloc.c | 2 +-
fs/ext4/inode.c | 16 +++++++---------
fs/ext4/move_extent.c | 3 +--
fs/ext4/namei.c | 8 ++++----
fs/ext4/page-io.c | 3 +--
fs/ext4/readpage.c | 2 +-
10 files changed, 22 insertions(+), 31 deletions(-)

diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index f93f9881ec18..fb7a64ea5679 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -111,7 +111,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
int dir_has_error = 0;
struct fscrypt_str fstr = FSTR_INIT(NULL, 0);

- if (ext4_encrypted_inode(inode)) {
+ if (IS_ENCRYPTED(inode)) {
err = fscrypt_get_encryption_info(inode);
if (err && err != -ENOKEY)
return err;
@@ -138,7 +138,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
return err;
}

- if (ext4_encrypted_inode(inode)) {
+ if (IS_ENCRYPTED(inode)) {
err = fscrypt_fname_alloc_buffer(inode, EXT4_NAME_LEN, &fstr);
if (err < 0)
return err;
@@ -245,7 +245,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
offset += ext4_rec_len_from_disk(de->rec_len,
sb->s_blocksize);
if (le32_to_cpu(de->inode)) {
- if (!ext4_encrypted_inode(inode)) {
+ if (!IS_ENCRYPTED(inode)) {
if (!dir_emit(ctx, de->name,
de->name_len,
le32_to_cpu(de->inode),
@@ -613,7 +613,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)

static int ext4_dir_open(struct inode * inode, struct file * filp)
{
- if (ext4_encrypted_inode(inode))
+ if (IS_ENCRYPTED(inode))
return fscrypt_get_encryption_info(inode) ? -EACCES : 0;
return 0;
}
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 5323ba097b03..216efeac53ea 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2286,11 +2286,6 @@ extern unsigned ext4_free_clusters_after_init(struct super_block *sb,
struct ext4_group_desc *gdp);
ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);

-static inline bool ext4_encrypted_inode(struct inode *inode)
-{
- return ext4_test_inode_flag(inode, EXT4_INODE_ENCRYPT);
-}
-
#ifdef CONFIG_EXT4_FS_ENCRYPTION
static inline int ext4_fname_setup_filename(struct inode *dir,
const struct qstr *iname,
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 15b6dd733780..a1ac7e9245ec 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -411,7 +411,7 @@ static inline int ext4_inode_journal_mode(struct inode *inode)
(ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
!test_opt(inode->i_sb, DELALLOC))) {
/* We do not support data journalling for encrypted data */
- if (S_ISREG(inode->i_mode) && ext4_encrypted_inode(inode))
+ if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode))
return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */
return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */
}
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 240b6dea5441..79d986dbf5af 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3631,7 +3631,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
max_zeroout = sbi->s_extent_max_zeroout_kb >>
(inode->i_sb->s_blocksize_bits - 10);

- if (ext4_encrypted_inode(inode))
+ if (IS_ENCRYPTED(inode))
max_zeroout = 0;

/*
@@ -4818,7 +4818,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
* leave it disabled for encrypted inodes for now. This is a
* bug we should fix....
*/
- if (ext4_encrypted_inode(inode) &&
+ if (IS_ENCRYPTED(inode) &&
(mode & (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE |
FALLOC_FL_ZERO_RANGE)))
return -EOPNOTSUPP;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 7ff14a1adba3..f3e17a8c84b4 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -771,7 +771,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
if (unlikely(ext4_forced_shutdown(sbi)))
return ERR_PTR(-EIO);

- if ((ext4_encrypted_inode(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) &&
+ if ((IS_ENCRYPTED(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) &&
!(i_flags & EXT4_EA_INODE_FL)) {
err = fscrypt_get_encryption_info(dir);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 6c21df83425d..1dcf44a865cb 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -415,7 +415,7 @@ int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk,
{
int ret;

- if (ext4_encrypted_inode(inode))
+ if (IS_ENCRYPTED(inode))
return fscrypt_zeroout_range(inode, lblk, pblk, len);

ret = sb_issue_zeroout(inode->i_sb, pblk, len, GFP_NOFS);
@@ -1217,8 +1217,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
(block_start < from || block_end > to)) {
ll_rw_block(REQ_OP_READ, 0, 1, &bh);
*wait_bh++ = bh;
- decrypt = ext4_encrypted_inode(inode) &&
- S_ISREG(inode->i_mode);
+ decrypt = IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
}
}
/*
@@ -3881,7 +3880,7 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
ssize_t ret;

#ifdef CONFIG_EXT4_FS_ENCRYPTION
- if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode))
+ if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
return 0;
#endif

@@ -4068,8 +4067,7 @@ static int __ext4_block_zero_page_range(handle_t *handle,
/* Uhhuh. Read error. Complain and punt. */
if (!buffer_uptodate(bh))
goto unlock;
- if (S_ISREG(inode->i_mode) &&
- ext4_encrypted_inode(inode)) {
+ 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);
@@ -4145,7 +4143,7 @@ static int ext4_block_truncate_page(handle_t *handle,
struct inode *inode = mapping->host;

/* If we are processing an encrypted inode during orphan list handling */
- if (ext4_encrypted_inode(inode) && !fscrypt_has_encryption_key(inode))
+ if (IS_ENCRYPTED(inode) && !fscrypt_has_encryption_key(inode))
return 0;

blocksize = inode->i_sb->s_blocksize;
@@ -4725,7 +4723,7 @@ static bool ext4_should_use_dax(struct inode *inode)
return false;
if (ext4_has_inline_data(inode))
return false;
- if (ext4_encrypted_inode(inode))
+ if (ext4_test_inode_flag(inode, EXT4_INODE_ENCRYPT))
return false;
if (ext4_test_inode_flag(inode, EXT4_INODE_VERITY))
return false;
@@ -5079,7 +5077,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
ret = -EFSCORRUPTED;
goto bad_inode;
}
- if (ext4_encrypted_inode(inode)) {
+ if (IS_ENCRYPTED(inode)) {
inode->i_op = &ext4_encrypted_symlink_inode_operations;
ext4_set_aops(inode);
} else if (ext4_inode_is_fast_symlink(inode)) {
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 2f5be02fc6f6..1083a9f3f16a 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -592,8 +592,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
return -EOPNOTSUPP;
}

- if (ext4_encrypted_inode(orig_inode) ||
- ext4_encrypted_inode(donor_inode)) {
+ if (IS_ENCRYPTED(orig_inode) || IS_ENCRYPTED(donor_inode)) {
ext4_msg(orig_inode->i_sb, KERN_ERR,
"Online defrag not supported for encrypted files");
return -EOPNOTSUPP;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 2b928eb07fa2..be6cb69beb12 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -621,7 +621,7 @@ static struct stats dx_show_leaf(struct inode *dir,

name = de->name;
len = de->name_len;
- if (ext4_encrypted_inode(dir))
+ if (IS_ENCRYPTED(dir))
res = fscrypt_get_encryption_info(dir);
if (res) {
printk(KERN_WARNING "Error setting up"
@@ -986,7 +986,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
EXT4_DIR_REC_LEN(0));
#ifdef CONFIG_EXT4_FS_ENCRYPTION
/* Check if the directory is encrypted */
- if (ext4_encrypted_inode(dir)) {
+ if (IS_ENCRYPTED(dir)) {
err = fscrypt_get_encryption_info(dir);
if (err < 0) {
brelse(bh);
@@ -1015,7 +1015,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
continue;
if (de->inode == 0)
continue;
- if (!ext4_encrypted_inode(dir)) {
+ if (!IS_ENCRYPTED(dir)) {
tmp_str.name = de->name;
tmp_str.len = de->name_len;
err = ext4_htree_store_dirent(dir_file,
@@ -1578,7 +1578,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
ino);
return ERR_PTR(-EFSCORRUPTED);
}
- if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
+ if (!IS_ERR(inode) && IS_ENCRYPTED(dir) &&
(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
!fscrypt_has_permitted_context(dir, inode)) {
ext4_warning(inode->i_sb,
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 2aa62d58d8dd..c398b55da854 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -477,8 +477,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,

bh = head = page_buffers(page);

- if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) &&
- nr_to_submit) {
+ if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) {
gfp_t gfp_flags = GFP_NOFS;

retry_encrypt:
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 6a163bfdc95d..92488df87135 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -156,7 +156,7 @@ static struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
unsigned int post_read_steps = 0;
struct bio_post_read_ctx *ctx = NULL;

- if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode))
+ if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
post_read_steps |= 1 << STEP_DECRYPT;
#ifdef CONFIG_FS_VERITY
if (inode->i_verity_info != NULL &&
--
2.19.1


2019-02-18 10:04:16

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 02/10] f2fs: use IS_ENCRYPTED() to check encryption status

From: Chandan Rajendra <[email protected]>

This commit removes the f2fs specific f2fs_encrypted_inode() and makes
use of the generic IS_ENCRYPTED() macro to check for the encryption
status of an inode.

Acked-by: Chao Yu <[email protected]>
Reviewed-by: Eric Biggers <[email protected]>
Signed-off-by: Chandan Rajendra <[email protected]>
---
fs/f2fs/data.c | 4 ++--
fs/f2fs/dir.c | 10 +++++-----
fs/f2fs/f2fs.h | 7 +------
fs/f2fs/file.c | 10 +++++-----
fs/f2fs/inode.c | 4 ++--
fs/f2fs/namei.c | 6 +++---
6 files changed, 18 insertions(+), 23 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 2cba513b7b8c..dca01fbe9c21 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1495,7 +1495,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
}

if (size) {
- if (f2fs_encrypted_inode(inode))
+ if (IS_ENCRYPTED(inode))
flags |= FIEMAP_EXTENT_DATA_ENCRYPTED;

ret = fiemap_fill_next_extent(fieinfo, logical,
@@ -1769,7 +1769,7 @@ static inline bool check_inplace_update_policy(struct inode *inode,
if (policy & (0x1 << F2FS_IPU_ASYNC) &&
fio && fio->op == REQ_OP_WRITE &&
!(fio->op_flags & REQ_SYNC) &&
- !f2fs_encrypted_inode(inode))
+ !IS_ENCRYPTED(inode))
return true;

/* this is only set during fdatasync */
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 50d0d36280fa..713b36a10a79 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -385,7 +385,7 @@ struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,
if (err)
goto put_error;

- if ((f2fs_encrypted_inode(dir) || dummy_encrypt) &&
+ if ((IS_ENCRYPTED(dir) || dummy_encrypt) &&
f2fs_may_encrypt(inode)) {
err = fscrypt_inherit_context(dir, inode, page, false);
if (err)
@@ -399,7 +399,7 @@ struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,

if (new_name) {
init_dent_inode(new_name, page);
- if (f2fs_encrypted_inode(dir))
+ if (IS_ENCRYPTED(dir))
file_set_enc_name(inode);
}

@@ -819,7 +819,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
goto out;
}

- if (f2fs_encrypted_inode(d->inode)) {
+ if (IS_ENCRYPTED(d->inode)) {
int save_len = fstr->len;

err = fscrypt_fname_disk_to_usr(d->inode,
@@ -862,7 +862,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
struct fscrypt_str fstr = FSTR_INIT(NULL, 0);
int err = 0;

- if (f2fs_encrypted_inode(inode)) {
+ if (IS_ENCRYPTED(inode)) {
err = fscrypt_get_encryption_info(inode);
if (err && err != -ENOKEY)
goto out;
@@ -924,7 +924,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)

static int f2fs_dir_open(struct inode *inode, struct file *filp)
{
- if (f2fs_encrypted_inode(inode))
+ if (IS_ENCRYPTED(inode))
return fscrypt_get_encryption_info(inode) ? -EACCES : 0;
return 0;
}
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 0634b10697f0..520558a3fb63 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -3466,14 +3466,9 @@ void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi);
/*
* crypto support
*/
-static inline bool f2fs_encrypted_inode(struct inode *inode)
-{
- return file_is_encrypt(inode);
-}
-
static inline bool f2fs_encrypted_file(struct inode *inode)
{
- return f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode);
+ return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
}

static inline void f2fs_set_encrypted_inode(struct inode *inode)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 07ebbf4e492d..dd8f1c38b436 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -586,7 +586,7 @@ static int truncate_partial_data_page(struct inode *inode, u64 from,
zero_user(page, offset, PAGE_SIZE - offset);

/* An encrypted inode should have a key and truncate the last page. */
- f2fs_bug_on(F2FS_I_SB(inode), cache_only && f2fs_encrypted_inode(inode));
+ f2fs_bug_on(F2FS_I_SB(inode), cache_only && IS_ENCRYPTED(inode));
if (!cache_only)
set_page_dirty(page);
f2fs_put_page(page, 1);
@@ -731,7 +731,7 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
stat->attributes |= STATX_ATTR_APPEND;
if (flags & F2FS_COMPR_FL)
stat->attributes |= STATX_ATTR_COMPRESSED;
- if (f2fs_encrypted_inode(inode))
+ if (IS_ENCRYPTED(inode))
stat->attributes |= STATX_ATTR_ENCRYPTED;
if (flags & F2FS_IMMUTABLE_FL)
stat->attributes |= STATX_ATTR_IMMUTABLE;
@@ -1587,7 +1587,7 @@ static long f2fs_fallocate(struct file *file, int mode,
if (!S_ISREG(inode->i_mode))
return -EINVAL;

- if (f2fs_encrypted_inode(inode) &&
+ if (IS_ENCRYPTED(inode) &&
(mode & (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE)))
return -EOPNOTSUPP;

@@ -1671,7 +1671,7 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
struct f2fs_inode_info *fi = F2FS_I(inode);
unsigned int flags = fi->i_flags;

- if (f2fs_encrypted_inode(inode))
+ if (IS_ENCRYPTED(inode))
flags |= F2FS_ENCRYPT_FL;
if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode))
flags |= F2FS_INLINE_DATA_FL;
@@ -2438,7 +2438,7 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
if (!S_ISREG(src->i_mode) || !S_ISREG(dst->i_mode))
return -EINVAL;

- if (f2fs_encrypted_inode(src) || f2fs_encrypted_inode(dst))
+ if (IS_ENCRYPTED(src) || IS_ENCRYPTED(dst))
return -EOPNOTSUPP;

if (src == dst) {
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index fe702cb3f4ec..5053944ed221 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -43,7 +43,7 @@ void f2fs_set_inode_flags(struct inode *inode)
new_fl |= S_NOATIME;
if (flags & F2FS_DIRSYNC_FL)
new_fl |= S_DIRSYNC;
- if (f2fs_encrypted_inode(inode))
+ if (file_is_encrypt(inode))
new_fl |= S_ENCRYPTED;
if (file_is_verity(inode))
new_fl |= S_VERITY;
@@ -455,7 +455,7 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
inode->i_mapping->a_ops = &f2fs_dblock_aops;
inode_nohighmem(inode);
} else if (S_ISLNK(inode->i_mode)) {
- if (f2fs_encrypted_inode(inode))
+ if (file_is_encrypt(inode))
inode->i_op = &f2fs_encrypted_symlink_inode_operations;
else
inode->i_op = &f2fs_symlink_inode_operations;
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 62d9829f3a6a..e967d27c1a89 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -75,7 +75,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
set_inode_flag(inode, FI_NEW_INODE);

/* If the directory encrypted, then we should encrypt the inode. */
- if ((f2fs_encrypted_inode(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) &&
+ if ((IS_ENCRYPTED(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) &&
f2fs_may_encrypt(inode))
f2fs_set_encrypted_inode(inode);

@@ -476,7 +476,7 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
if (err)
goto out_iput;
}
- if (f2fs_encrypted_inode(dir) &&
+ if (IS_ENCRYPTED(dir) &&
(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
!fscrypt_has_permitted_context(dir, inode)) {
f2fs_msg(inode->i_sb, KERN_WARNING,
@@ -803,7 +803,7 @@ static int f2fs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
if (unlikely(f2fs_cp_error(sbi)))
return -EIO;

- if (f2fs_encrypted_inode(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) {
+ if (IS_ENCRYPTED(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) {
int err = fscrypt_get_encryption_info(dir);
if (err)
return err;
--
2.19.1


2019-02-18 10:04:27

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 04/10] Consolidate "post read processing" into a new file

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 <[email protected]>
---
fs/Makefile | 3 +-
fs/crypto/bio.c | 21 ++--
fs/crypto/crypto.c | 1 +
fs/crypto/fscrypt_private.h | 3 +
fs/ext4/ext4.h | 2 -
fs/ext4/readpage.c | 153 +-----------------------------
fs/ext4/super.c | 9 +-
fs/post_read_process.c | 127 +++++++++++++++++++++++++
fs/verity/verify.c | 12 +++
include/linux/fscrypt.h | 11 ---
include/linux/post_read_process.h | 21 ++++
11 files changed, 176 insertions(+), 187 deletions(-)
create mode 100644 fs/post_read_process.c
create mode 100644 include/linux/post_read_process.h

diff --git a/fs/Makefile b/fs/Makefile
index 10b37f651ffd..5f6c0cba102b 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -12,7 +12,8 @@ obj-y := open.o read_write.o file_table.o super.o \
attr.o bad_inode.o file.o filesystems.o namespace.o \
seq_file.o xattr.o libfs.o fs-writeback.o \
pnode.o splice.o sync.o utimes.o d_path.o \
- stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
+ stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
+ post_read_process.o

ifeq ($(CONFIG_BLOCK),y)
obj-y += buffer.o block_dev.o direct-io.o mpage.o
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 0959044c5cee..a659a76c05e4 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -24,6 +24,8 @@
#include <linux/module.h>
#include <linux/bio.h>
#include <linux/namei.h>
+#include <linux/post_read_process.h>
+
#include "fscrypt_private.h"

static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
@@ -53,24 +55,15 @@ void fscrypt_decrypt_bio(struct bio *bio)
}
EXPORT_SYMBOL(fscrypt_decrypt_bio);

-static void completion_pages(struct work_struct *work)
+void fscrypt_decrypt_work(struct work_struct *work)
{
- struct fscrypt_ctx *ctx =
- container_of(work, struct fscrypt_ctx, r.work);
- struct bio *bio = ctx->r.bio;
+ struct bio_post_read_ctx *ctx =
+ container_of(work, struct bio_post_read_ctx, work);

- __fscrypt_decrypt_bio(bio, true);
- fscrypt_release_ctx(ctx);
- bio_put(bio);
-}
+ fscrypt_decrypt_bio(ctx->bio);

-void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio)
-{
- INIT_WORK(&ctx->r.work, completion_pages);
- ctx->r.bio = bio;
- fscrypt_enqueue_decrypt_work(&ctx->r.work);
+ bio_post_read_processing(ctx);
}
-EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);

void fscrypt_pullback_bio_page(struct page **page, bool restore)
{
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index 4dc788e3bc96..36d599784e5a 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -53,6 +53,7 @@ struct kmem_cache *fscrypt_info_cachep;

void fscrypt_enqueue_decrypt_work(struct work_struct *work)
{
+ INIT_WORK(work, fscrypt_decrypt_work);
queue_work(fscrypt_read_workqueue, work);
}
EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work);
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 7da276159593..412a3bcf9efd 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -114,6 +114,9 @@ static inline bool fscrypt_valid_enc_modes(u32 contents_mode,
return false;
}

+/* bio.c */
+void fscrypt_decrypt_work(struct work_struct *work);
+
/* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep;
extern int fscrypt_initialize(unsigned int cop_flags);
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 0ffa84772667..c0245820bafe 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -3088,8 +3088,6 @@ static inline void ext4_set_de_type(struct super_block *sb,
extern int ext4_mpage_readpages(struct address_space *mapping,
struct list_head *pages, struct page *page,
unsigned nr_pages, bool is_readahead);
-extern int __init ext4_init_post_read_processing(void);
-extern void ext4_exit_post_read_processing(void);

/* symlink.c */
extern const struct inode_operations ext4_encrypted_symlink_inode_operations;
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 93fbc15177a3..8943fc41fd33 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -44,14 +44,10 @@
#include <linux/backing-dev.h>
#include <linux/pagevec.h>
#include <linux/cleancache.h>
+#include <linux/post_read_process.h>

#include "ext4.h"

-#define NUM_PREALLOC_POST_READ_CTXS 128
-
-static struct kmem_cache *bio_post_read_ctx_cache;
-static mempool_t *bio_post_read_ctx_pool;
-
static inline bool ext4_bio_encrypted(struct bio *bio)
{
#ifdef CONFIG_FS_ENCRYPTION
@@ -61,124 +57,6 @@ static inline bool ext4_bio_encrypted(struct bio *bio)
#endif
}

-/* postprocessing steps for read bios */
-enum bio_post_read_step {
- STEP_INITIAL = 0,
- STEP_DECRYPT,
- STEP_VERITY,
-};
-
-struct bio_post_read_ctx {
- struct bio *bio;
- struct work_struct work;
- unsigned int cur_step;
- unsigned int enabled_steps;
-};
-
-static void __read_end_io(struct bio *bio)
-{
- struct page *page;
- struct bio_vec *bv;
- int i;
-
- bio_for_each_segment_all(bv, bio, i) {
- page = bv->bv_page;
-
- /* PG_error was set if any post_read step failed */
- if (bio->bi_status || PageError(page)) {
- ClearPageUptodate(page);
- SetPageError(page);
- } else {
- SetPageUptodate(page);
- }
- unlock_page(page);
- }
- if (bio->bi_private)
- mempool_free(bio->bi_private, bio_post_read_ctx_pool);
- bio_put(bio);
-}
-
-static void bio_post_read_processing(struct bio_post_read_ctx *ctx);
-
-static void decrypt_work(struct work_struct *work)
-{
- struct bio_post_read_ctx *ctx =
- container_of(work, struct bio_post_read_ctx, work);
-
- fscrypt_decrypt_bio(ctx->bio);
-
- bio_post_read_processing(ctx);
-}
-
-static void verity_work(struct work_struct *work)
-{
- struct bio_post_read_ctx *ctx =
- container_of(work, struct bio_post_read_ctx, work);
-
- fsverity_verify_bio(ctx->bio);
-
- bio_post_read_processing(ctx);
-}
-
-static void bio_post_read_processing(struct bio_post_read_ctx *ctx)
-{
- /*
- * We use different work queues for decryption and for verity because
- * verity may require reading metadata pages that need decryption, and
- * we shouldn't recurse to the same workqueue.
- */
- switch (++ctx->cur_step) {
- case STEP_DECRYPT:
- if (ctx->enabled_steps & (1 << STEP_DECRYPT)) {
- INIT_WORK(&ctx->work, decrypt_work);
- fscrypt_enqueue_decrypt_work(&ctx->work);
- return;
- }
- ctx->cur_step++;
- /* fall-through */
- case STEP_VERITY:
- if (ctx->enabled_steps & (1 << STEP_VERITY)) {
- INIT_WORK(&ctx->work, verity_work);
- fsverity_enqueue_verify_work(&ctx->work);
- return;
- }
- ctx->cur_step++;
- /* fall-through */
- default:
- __read_end_io(ctx->bio);
- }
-}
-
-static struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
- struct bio *bio,
- pgoff_t index)
-{
- unsigned int post_read_steps = 0;
- struct bio_post_read_ctx *ctx = NULL;
-
- if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
- post_read_steps |= 1 << STEP_DECRYPT;
-#ifdef CONFIG_FS_VERITY
- if (inode->i_verity_info != NULL &&
- (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
- post_read_steps |= 1 << STEP_VERITY;
-#endif
- if (post_read_steps) {
- ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
- if (!ctx)
- return ERR_PTR(-ENOMEM);
- ctx->bio = bio;
- ctx->enabled_steps = post_read_steps;
- bio->bi_private = ctx;
- }
- return ctx;
-}
-
-static bool bio_post_read_required(struct bio *bio)
-{
- return bio->bi_private && !bio->bi_status;
-}
-
/*
* I/O completion handler for multipage BIOs.
*
@@ -196,11 +74,10 @@ static void mpage_end_io(struct bio *bio)
if (bio_post_read_required(bio)) {
struct bio_post_read_ctx *ctx = bio->bi_private;

- ctx->cur_step = STEP_INITIAL;
bio_post_read_processing(ctx);
return;
}
- __read_end_io(bio);
+ end_bio_post_read_processing(bio);
}

static inline loff_t ext4_readpage_limit(struct inode *inode)
@@ -416,29 +293,3 @@ int ext4_mpage_readpages(struct address_space *mapping,
submit_bio(bio);
return 0;
}
-
-int __init ext4_init_post_read_processing(void)
-{
- bio_post_read_ctx_cache =
- kmem_cache_create("ext4_bio_post_read_ctx",
- sizeof(struct bio_post_read_ctx), 0, 0, NULL);
- if (!bio_post_read_ctx_cache)
- goto fail;
- bio_post_read_ctx_pool =
- mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS,
- bio_post_read_ctx_cache);
- if (!bio_post_read_ctx_pool)
- goto fail_free_cache;
- return 0;
-
-fail_free_cache:
- kmem_cache_destroy(bio_post_read_ctx_cache);
-fail:
- return -ENOMEM;
-}
-
-void ext4_exit_post_read_processing(void)
-{
- mempool_destroy(bio_post_read_ctx_pool);
- kmem_cache_destroy(bio_post_read_ctx_cache);
-}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 95a5d9fbbb9f..9314dddfbf34 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -6102,10 +6102,6 @@ static int __init ext4_init_fs(void)
return err;

err = ext4_init_pending();
- if (err)
- goto out7;
-
- err = ext4_init_post_read_processing();
if (err)
goto out6;

@@ -6147,10 +6143,8 @@ static int __init ext4_init_fs(void)
out4:
ext4_exit_pageio();
out5:
- ext4_exit_post_read_processing();
-out6:
ext4_exit_pending();
-out7:
+out6:
ext4_exit_es();

return err;
@@ -6167,7 +6161,6 @@ static void __exit ext4_exit_fs(void)
ext4_exit_sysfs();
ext4_exit_system_zone();
ext4_exit_pageio();
- ext4_exit_post_read_processing();
ext4_exit_es();
ext4_exit_pending();
}
diff --git a/fs/post_read_process.c b/fs/post_read_process.c
new file mode 100644
index 000000000000..9720eeff0160
--- /dev/null
+++ b/fs/post_read_process.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/bio.h>
+#include <linux/fscrypt.h>
+#include <linux/fsverity.h>
+#include <linux/post_read_process.h>
+
+#define NUM_PREALLOC_POST_READ_CTXS 128
+
+static struct kmem_cache *bio_post_read_ctx_cache;
+static mempool_t *bio_post_read_ctx_pool;
+
+/* postprocessing steps for read bios */
+enum bio_post_read_step {
+ STEP_INITIAL = 0,
+ STEP_DECRYPT,
+ STEP_VERITY,
+};
+
+void end_bio_post_read_processing(struct bio *bio)
+{
+ struct page *page;
+ struct bio_vec *bv;
+ int i;
+
+ bio_for_each_segment_all(bv, bio, i) {
+ page = bv->bv_page;
+
+ /* PG_error was set if any post_read step failed */
+ if (bio->bi_status || PageError(page)) {
+ ClearPageUptodate(page);
+ SetPageError(page);
+ } else {
+ SetPageUptodate(page);
+ }
+ unlock_page(page);
+ }
+ if (bio->bi_private)
+ put_bio_post_read_ctx(bio->bi_private);
+ bio_put(bio);
+}
+
+void bio_post_read_processing(struct bio_post_read_ctx *ctx)
+{
+ /*
+ * We use different work queues for decryption and for verity because
+ * verity may require reading metadata pages that need decryption, and
+ * we shouldn't recurse to the same workqueue.
+ */
+ switch (++ctx->cur_step) {
+ case STEP_DECRYPT:
+ if (ctx->enabled_steps & (1 << STEP_DECRYPT)) {
+ fscrypt_enqueue_decrypt_work(&ctx->work);
+ return;
+ }
+ ctx->cur_step++;
+ /* fall-through */
+ case STEP_VERITY:
+ if (ctx->enabled_steps & (1 << STEP_VERITY)) {
+ fsverity_enqueue_verify_work(&ctx->work);
+ return;
+ }
+ ctx->cur_step++;
+ /* fall-through */
+ default:
+ end_bio_post_read_processing(ctx->bio);
+ }
+}
+
+struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
+ struct bio *bio,
+ pgoff_t index)
+{
+ unsigned int post_read_steps = 0;
+ struct bio_post_read_ctx *ctx = NULL;
+
+ if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
+ post_read_steps |= 1 << STEP_DECRYPT;
+#ifdef CONFIG_FS_VERITY
+ if (inode->i_verity_info != NULL &&
+ (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
+ post_read_steps |= 1 << STEP_VERITY;
+#endif
+ if (post_read_steps) {
+ ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
+ ctx->bio = bio;
+ ctx->inode = inode;
+ ctx->enabled_steps = post_read_steps;
+ ctx->cur_step = STEP_INITIAL;
+ bio->bi_private = ctx;
+ }
+ return ctx;
+}
+
+void put_bio_post_read_ctx(struct bio_post_read_ctx *ctx)
+{
+ mempool_free(ctx, bio_post_read_ctx_pool);
+}
+
+bool bio_post_read_required(struct bio *bio)
+{
+ return bio->bi_private && !bio->bi_status;
+}
+
+static int __init bio_init_post_read_processing(void)
+{
+ bio_post_read_ctx_cache = KMEM_CACHE(bio_post_read_ctx, 0);
+ if (!bio_post_read_ctx_cache)
+ goto fail;
+ bio_post_read_ctx_pool =
+ mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS,
+ bio_post_read_ctx_cache);
+ if (!bio_post_read_ctx_pool)
+ goto fail_free_cache;
+ return 0;
+
+fail_free_cache:
+ kmem_cache_destroy(bio_post_read_ctx_cache);
+fail:
+ return -ENOMEM;
+}
+
+fs_initcall(bio_init_post_read_processing);
diff --git a/fs/verity/verify.c b/fs/verity/verify.c
index fbfb68eff358..4f7cd2269e83 100644
--- a/fs/verity/verify.c
+++ b/fs/verity/verify.c
@@ -13,6 +13,7 @@
#include <linux/pagemap.h>
#include <linux/ratelimit.h>
#include <linux/scatterlist.h>
+#include <linux/post_read_process.h>

struct workqueue_struct *fsverity_read_workqueue;

@@ -283,6 +284,16 @@ void fsverity_verify_bio(struct bio *bio)
EXPORT_SYMBOL_GPL(fsverity_verify_bio);
#endif /* CONFIG_BLOCK */

+static void fsverity_verify_work(struct work_struct *work)
+{
+ struct bio_post_read_ctx *ctx =
+ container_of(work, struct bio_post_read_ctx, work);
+
+ fsverity_verify_bio(ctx->bio);
+
+ bio_post_read_processing(ctx);
+}
+
/**
* fsverity_enqueue_verify_work - enqueue work on the fs-verity workqueue
*
@@ -290,6 +301,7 @@ EXPORT_SYMBOL_GPL(fsverity_verify_bio);
*/
void fsverity_enqueue_verify_work(struct work_struct *work)
{
+ INIT_WORK(work, fsverity_verify_work);
queue_work(fsverity_read_workqueue, work);
}
EXPORT_SYMBOL_GPL(fsverity_enqueue_verify_work);
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 6ba193c23f37..13f70e22aff2 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -68,10 +68,6 @@ struct fscrypt_ctx {
struct page *bounce_page; /* Ciphertext page */
struct page *control_page; /* Original page */
} w;
- struct {
- struct bio *bio;
- struct work_struct work;
- } r;
struct list_head free_list; /* Free list */
};
u8 flags; /* Flags */
@@ -206,8 +202,6 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname,

/* bio.c */
extern void fscrypt_decrypt_bio(struct bio *);
-extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
- struct bio *bio);
extern void fscrypt_pullback_bio_page(struct page **, bool);
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
unsigned int);
@@ -376,11 +370,6 @@ static inline void fscrypt_decrypt_bio(struct bio *bio)
{
}

-static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
- struct bio *bio)
-{
-}
-
static inline void fscrypt_pullback_bio_page(struct page **page, bool restore)
{
return;
diff --git a/include/linux/post_read_process.h b/include/linux/post_read_process.h
new file mode 100644
index 000000000000..09e52928f861
--- /dev/null
+++ b/include/linux/post_read_process.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _POST_READ_PROCESS_H
+#define _POST_READ_PROCESS_H
+
+struct bio_post_read_ctx {
+ struct bio *bio;
+ struct inode *inode;
+ struct work_struct work;
+ unsigned int cur_step;
+ unsigned int enabled_steps;
+};
+
+void end_bio_post_read_processing(struct bio *bio);
+void bio_post_read_processing(struct bio_post_read_ctx *ctx);
+struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
+ struct bio *bio,
+ pgoff_t index);
+void put_bio_post_read_ctx(struct bio_post_read_ctx *ctx);
+bool bio_post_read_required(struct bio *bio);
+
+#endif /* _POST_READ_PROCESS_H */
--
2.19.1


2019-02-18 10:04:30

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 05/10] fsverity: Add call back to decide if verity check has to be performed

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 <[email protected]>
---
fs/ext4/super.c | 9 +++++++++
fs/post_read_process.c | 5 +++--
include/linux/fsverity.h | 1 +
3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 9314dddfbf34..2d7781ab6824 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1428,10 +1428,19 @@ 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)
+{
+ if (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT))
+ return true;
+ else
+ return false;
+}
+
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/post_read_process.c b/fs/post_read_process.c
index 9720eeff0160..1f8663d70247 100644
--- a/fs/post_read_process.c
+++ b/fs/post_read_process.c
@@ -79,8 +79,9 @@ struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
post_read_steps |= 1 << STEP_DECRYPT;
#ifdef CONFIG_FS_VERITY
- if (inode->i_verity_info != NULL &&
- (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
+ if (inode->i_verity_info != NULL
+ && inode->i_sb->s_vop->verity_required
+ && inode->i_sb->s_vop->verity_required(inode, index))
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


2019-02-18 10:04:36

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 07/10] fsverity: Add call back to determine readpage limit

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 <[email protected]>
---
fs/ext4/super.c | 18 ++++++++++++++++++
include/linux/fsverity.h | 1 +
2 files changed, 19 insertions(+)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2d7781ab6824..4493ddc357c6 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1428,6 +1428,23 @@ 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)
+{
+#ifdef CONFIG_FS_VERITY
+ 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;
+ }
+#endif
+ return i_size_read(inode);
+}
+
static bool ext4_verity_required(struct inode *inode, pgoff_t index)
{
if (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT))
@@ -1441,6 +1458,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


2019-02-18 10:04:37

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 06/10] Introduce REQ_POST_READ_PROC bio flag

Ext4 and F2FS currently use a non-NULL value stored at bio->bi_private
to determine if the contents of the bio need to be "post processed"
i.e. whether its contents need to be decrypted and/or verified. For
block size < page size scenario, bio->bi_private would hold a pointer to
buffer_head. Hence, this commit adds the new flag REQ_POST_READ_PROC to
be able to decisively check for post process requirement for a bio.

Signed-off-by: Chandan Rajendra <[email protected]>
---
fs/ext4/readpage.c | 11 +++++++++--
fs/post_read_process.c | 2 +-
include/linux/blk_types.h | 2 ++
3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 8943fc41fd33..c7dbab35deaa 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -245,6 +245,7 @@ int ext4_mpage_readpages(struct address_space *mapping,
}
if (bio == NULL) {
struct bio_post_read_ctx *ctx;
+ unsigned int op_flags = 0;

bio = bio_alloc(GFP_KERNEL,
min_t(int, nr_pages, BIO_MAX_PAGES));
@@ -259,8 +260,14 @@ int ext4_mpage_readpages(struct address_space *mapping,
bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9);
bio->bi_end_io = mpage_end_io;
bio->bi_private = ctx;
- bio_set_op_attrs(bio, REQ_OP_READ,
- is_readahead ? REQ_RAHEAD : 0);
+
+ if (is_readahead)
+ op_flags |= REQ_RAHEAD;
+
+ if (ctx)
+ op_flags |= REQ_POST_READ_PROC;
+
+ bio_set_op_attrs(bio, REQ_OP_READ, op_flags);
}

length = first_hole << blkbits;
diff --git a/fs/post_read_process.c b/fs/post_read_process.c
index 1f8663d70247..66c1c6e57e70 100644
--- a/fs/post_read_process.c
+++ b/fs/post_read_process.c
@@ -104,7 +104,7 @@ void put_bio_post_read_ctx(struct bio_post_read_ctx *ctx)

bool bio_post_read_required(struct bio *bio)
{
- return bio->bi_private && !bio->bi_status;
+ return bio->bi_opf & REQ_POST_READ_PROC;
}

static int __init bio_init_post_read_processing(void)
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 5c7e7f859a24..6904945c8c40 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -320,6 +320,7 @@ enum req_flag_bits {
__REQ_RAHEAD, /* read ahead, can fail anytime */
__REQ_BACKGROUND, /* background IO */
__REQ_NOWAIT, /* Don't wait if request will block */
+ __REQ_POST_READ_PROC,

/* command specific flags for REQ_OP_WRITE_ZEROES: */
__REQ_NOUNMAP, /* do not free blocks when zeroing */
@@ -346,6 +347,7 @@ enum req_flag_bits {
#define REQ_RAHEAD (1ULL << __REQ_RAHEAD)
#define REQ_BACKGROUND (1ULL << __REQ_BACKGROUND)
#define REQ_NOWAIT (1ULL << __REQ_NOWAIT)
+#define REQ_POST_READ_PROC (1ULL << __REQ_POST_READ_PROC)
#define REQ_NOUNMAP (1ULL << __REQ_NOUNMAP)
#define REQ_HIPRI (1ULL << __REQ_HIPRI)

--
2.19.1


2019-02-18 10:04:46

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 09/10] fs/mpage.c: Integrate post read processing

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 marks the bio
with a flag to indicate that after 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 <[email protected]>
---
fs/mpage.c | 77 +++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 59 insertions(+), 18 deletions(-)

diff --git a/fs/mpage.c b/fs/mpage.c
index c820dc9bebab..09f0491e6260 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -30,6 +30,8 @@
#include <linux/backing-dev.h>
#include <linux/pagevec.h>
#include <linux/cleancache.h>
+#include <linux/fsverity.h>
+#include <linux/post_read_process.h>
#include "internal.h"

/*
@@ -49,6 +51,13 @@ static void mpage_end_io(struct bio *bio)
struct bio_vec *bv;
int i;

+ if (bio_post_read_required(bio)) {
+ struct bio_post_read_ctx *ctx = bio->bi_private;
+
+ bio_post_read_processing(ctx);
+ return;
+ }
+
bio_for_each_segment_all(bv, bio, i) {
struct page *page = bv->bv_page;
page_endio(page, bio_op(bio),
@@ -142,6 +151,7 @@ struct mpage_readpage_args {
struct buffer_head map_bh;
unsigned long first_logical_block;
get_block_t *get_block;
+ int op_flags;
};

/*
@@ -170,25 +180,22 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
struct block_device *bdev = NULL;
int length;
int fully_mapped = 1;
- int op_flags;
unsigned nblocks;
unsigned relative_block;
gfp_t gfp;

- if (args->is_readahead) {
- op_flags = REQ_RAHEAD;
- gfp = readahead_gfp_mask(page->mapping);
- } else {
- op_flags = 0;
- gfp = mapping_gfp_constraint(page->mapping, GFP_KERNEL);
- }
-
if (page_has_buffers(page))
goto confused;

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;
@@ -276,6 +283,10 @@ 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) && inode->i_sb->s_vop->check_hole)
+ inode->i_sb->s_vop->check_hole(inode, page);
+#endif
SetPageUptodate(page);
unlock_page(page);
goto out;
@@ -294,26 +305,54 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
* This page will go to BIO. Do we need to send this BIO off first?
*/
if (args->bio && (args->last_block_in_bio != blocks[0] - 1))
- args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
+ args->bio = mpage_bio_submit(REQ_OP_READ, args->op_flags,
+ args->bio);

alloc_new:
if (args->bio == NULL) {
- if (first_hole == blocks_per_page) {
+ struct bio_post_read_ctx *ctx;
+
+ if (first_hole == blocks_per_page
+ && !(IS_ENCRYPTED(inode) || IS_VERITY(inode))) {
if (!bdev_read_page(bdev, blocks[0] << (blkbits - 9),
page))
goto out;
}
+
+ args->op_flags = 0;
+
+ if (args->is_readahead) {
+ args->op_flags = REQ_RAHEAD;
+ gfp = readahead_gfp_mask(page->mapping);
+ } else {
+ gfp = mapping_gfp_constraint(page->mapping, GFP_KERNEL);
+ }
+
args->bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9),
min_t(int, args->nr_pages,
BIO_MAX_PAGES),
gfp);
- if (args->bio == NULL)
+ if (args->bio == NULL) {
+ args->op_flags = 0;
goto confused;
+ }
+
+ ctx = get_bio_post_read_ctx(inode, args->bio, page->index);
+ if (IS_ERR(ctx)) {
+ args->op_flags = 0;
+ bio_put(args->bio);
+ args->bio = NULL;
+ goto confused;
+ }
+
+ if (ctx)
+ args->op_flags |= REQ_POST_READ_PROC;
}

length = first_hole << blkbits;
if (bio_add_page(args->bio, page, length, 0) < length) {
- args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
+ args->bio = mpage_bio_submit(REQ_OP_READ, args->op_flags,
+ args->bio);
goto alloc_new;
}

@@ -321,7 +360,8 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
nblocks = map_bh->b_size >> blkbits;
if ((buffer_boundary(map_bh) && relative_block == nblocks) ||
(first_hole != blocks_per_page))
- args->bio = mpage_bio_submit(REQ_OP_READ, op_flags, args->bio);
+ args->bio = mpage_bio_submit(REQ_OP_READ, args->op_flags,
+ args->bio);
else
args->last_block_in_bio = blocks[blocks_per_page - 1];
out:
@@ -329,7 +369,8 @@ 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);
+ args->bio = mpage_bio_submit(REQ_OP_READ, args->op_flags,
+ args->bio);
if (!PageUptodate(page))
block_read_full_page(page, args->get_block);
else
@@ -407,7 +448,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
}
BUG_ON(!list_empty(pages));
if (args.bio)
- mpage_bio_submit(REQ_OP_READ, REQ_RAHEAD, args.bio);
+ mpage_bio_submit(REQ_OP_READ, args.op_flags, args.bio);
return 0;
}
EXPORT_SYMBOL(mpage_readpages);
@@ -425,7 +466,7 @@ int mpage_readpage(struct page *page, get_block_t get_block)

args.bio = do_mpage_readpage(&args);
if (args.bio)
- mpage_bio_submit(REQ_OP_READ, 0, args.bio);
+ mpage_bio_submit(REQ_OP_READ, args.op_flags, args.bio);
return 0;
}
EXPORT_SYMBOL(mpage_readpage);
--
2.19.1


2019-02-18 10:04:48

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 08/10] fsverity: Add call back to verify file holes

readpage() implmentations zero out part of the page-cache page mapping a
file hole. This commit adds a call back to "struct fsverity_operations"
which readpage() can invoke to verify the file hole.

Signed-off-by: Chandan Rajendra <[email protected]>
---
fs/ext4/super.c | 1 +
include/linux/fsverity.h | 1 +
2 files changed, 2 insertions(+)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 4493ddc357c6..94e0d4b56653 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1459,6 +1459,7 @@ static const struct fsverity_operations ext4_verityops = {
.read_metadata_page = ext4_read_verity_metadata_page,
.verity_required = ext4_verity_required,
.readpage_limit = ext4_readpage_limit,
+ .check_hole = fsverity_check_hole,
};
#endif /* CONFIG_FS_VERITY */

diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index fc8113acbbfe..8bc28b07d550 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -20,6 +20,7 @@ struct fsverity_operations {
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);
+ bool (*check_hole)(struct inode *inode, struct page *page);
};

#ifdef CONFIG_FS_VERITY
--
2.19.1


2019-02-18 10:04:50

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 10/10] ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]

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 <[email protected]>
---
fs/ext4/Makefile | 2 +-
fs/ext4/inode.c | 5 +-
fs/ext4/readpage.c | 302 ---------------------------------------------
3 files changed, 3 insertions(+), 306 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 b1d7ddd70eee..777118d7b3cd 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3355,8 +3355,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;
}
@@ -3371,7 +3370,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 c7dbab35deaa..000000000000
--- a/fs/ext4/readpage.c
+++ /dev/null
@@ -1,302 +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 <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/mm.h>
-#include <linux/kdev_t.h>
-#include <linux/gfp.h>
-#include <linux/bio.h>
-#include <linux/fs.h>
-#include <linux/buffer_head.h>
-#include <linux/blkdev.h>
-#include <linux/highmem.h>
-#include <linux/prefetch.h>
-#include <linux/mpage.h>
-#include <linux/writeback.h>
-#include <linux/backing-dev.h>
-#include <linux/pagevec.h>
-#include <linux/cleancache.h>
-#include <linux/post_read_process.h>
-
-#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)
-{
- if (bio_post_read_required(bio)) {
- struct bio_post_read_ctx *ctx = bio->bi_private;
-
- bio_post_read_processing(ctx);
- return;
- }
- end_bio_post_read_processing(bio);
-}
-
-static inline loff_t ext4_readpage_limit(struct inode *inode)
-{
-#ifdef CONFIG_FS_VERITY
- 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;
- }
-#endif
- return i_size_read(inode);
-}
-
-int ext4_mpage_readpages(struct address_space *mapping,
- struct list_head *pages, struct page *page,
- unsigned nr_pages, bool is_readahead)
-{
- struct bio *bio = NULL;
- sector_t last_block_in_bio = 0;
-
- struct inode *inode = mapping->host;
- const unsigned blkbits = inode->i_blkbits;
- const unsigned blocks_per_page = PAGE_SIZE >> blkbits;
- const unsigned blocksize = 1 << blkbits;
- sector_t block_in_file;
- sector_t last_block;
- sector_t last_block_in_file;
- sector_t blocks[MAX_BUF_PER_PAGE];
- unsigned page_block;
- struct block_device *bdev = inode->i_sb->s_bdev;
- int length;
- unsigned relative_block = 0;
- struct ext4_map_blocks map;
-
- map.m_pblk = 0;
- map.m_lblk = 0;
- map.m_len = 0;
- map.m_flags = 0;
-
- for (; nr_pages; nr_pages--) {
- int fully_mapped = 1;
- unsigned first_hole = blocks_per_page;
-
- prefetchw(&page->flags);
- if (pages) {
- page = lru_to_page(pages);
- list_del(&page->lru);
- if (add_to_page_cache_lru(page, mapping, page->index,
- readahead_gfp_mask(mapping)))
- goto next_page;
- }
-
- if (page_has_buffers(page))
- goto confused;
-
- block_in_file = (sector_t)page->index << (PAGE_SHIFT - blkbits);
- last_block = block_in_file + nr_pages * blocks_per_page;
- last_block_in_file = (ext4_readpage_limit(inode) +
- blocksize - 1) >> blkbits;
- if (last_block > last_block_in_file)
- last_block = last_block_in_file;
- page_block = 0;
-
- /*
- * Map blocks using the previous result first.
- */
- if ((map.m_flags & EXT4_MAP_MAPPED) &&
- block_in_file > map.m_lblk &&
- block_in_file < (map.m_lblk + map.m_len)) {
- unsigned map_offset = block_in_file - map.m_lblk;
- unsigned last = map.m_len - map_offset;
-
- for (relative_block = 0; ; relative_block++) {
- if (relative_block == last) {
- /* needed? */
- map.m_flags &= ~EXT4_MAP_MAPPED;
- break;
- }
- if (page_block == blocks_per_page)
- break;
- blocks[page_block] = map.m_pblk + map_offset +
- relative_block;
- page_block++;
- block_in_file++;
- }
- }
-
- /*
- * Then do more ext4_map_blocks() calls until we are
- * done with this page.
- */
- while (page_block < blocks_per_page) {
- if (block_in_file < last_block) {
- map.m_lblk = block_in_file;
- map.m_len = last_block - block_in_file;
-
- if (ext4_map_blocks(NULL, inode, &map, 0) < 0) {
- set_error_page:
- SetPageError(page);
- zero_user_segment(page, 0,
- PAGE_SIZE);
- unlock_page(page);
- goto next_page;
- }
- }
- if ((map.m_flags & EXT4_MAP_MAPPED) == 0) {
- fully_mapped = 0;
- if (first_hole == blocks_per_page)
- first_hole = page_block;
- page_block++;
- block_in_file++;
- continue;
- }
- if (first_hole != blocks_per_page)
- goto confused; /* hole -> non-hole */
-
- /* Contiguous blocks? */
- if (page_block && blocks[page_block-1] != map.m_pblk-1)
- goto confused;
- for (relative_block = 0; ; relative_block++) {
- if (relative_block == map.m_len) {
- /* needed? */
- map.m_flags &= ~EXT4_MAP_MAPPED;
- break;
- } else if (page_block == blocks_per_page)
- break;
- blocks[page_block] = map.m_pblk+relative_block;
- page_block++;
- block_in_file++;
- }
- }
- if (first_hole != blocks_per_page) {
- zero_user_segment(page, first_hole << blkbits,
- PAGE_SIZE);
- if (first_hole == 0) {
- if (!fsverity_check_hole(inode, page))
- goto set_error_page;
- SetPageUptodate(page);
- unlock_page(page);
- goto next_page;
- }
- } else if (fully_mapped) {
- SetPageMappedToDisk(page);
- }
- if (fully_mapped && blocks_per_page == 1 &&
- !PageUptodate(page) && cleancache_get_page(page) == 0) {
- SetPageUptodate(page);
- goto confused;
- }
-
- /*
- * This page will go to BIO. Do we need to send this
- * BIO off first?
- */
- if (bio && (last_block_in_bio != blocks[0] - 1)) {
- submit_and_realloc:
- submit_bio(bio);
- bio = NULL;
- }
- if (bio == NULL) {
- struct bio_post_read_ctx *ctx;
- unsigned int op_flags = 0;
-
- bio = bio_alloc(GFP_KERNEL,
- min_t(int, nr_pages, BIO_MAX_PAGES));
- if (!bio)
- goto set_error_page;
- ctx = get_bio_post_read_ctx(inode, bio, page->index);
- if (IS_ERR(ctx)) {
- 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;
- bio->bi_private = ctx;
-
- if (is_readahead)
- op_flags |= REQ_RAHEAD;
-
- if (ctx)
- op_flags |= REQ_POST_READ_PROC;
-
- bio_set_op_attrs(bio, REQ_OP_READ, op_flags);
- }
-
- length = first_hole << blkbits;
- if (bio_add_page(bio, page, length, 0) < length)
- goto submit_and_realloc;
-
- if (((map.m_flags & EXT4_MAP_BOUNDARY) &&
- (relative_block == map.m_len)) ||
- (first_hole != blocks_per_page)) {
- submit_bio(bio);
- bio = NULL;
- } else
- last_block_in_bio = blocks[blocks_per_page - 1];
- goto next_page;
- confused:
- if (bio) {
- submit_bio(bio);
- bio = NULL;
- }
- if (!PageUptodate(page))
- block_read_full_page(page, ext4_get_block);
- else
- unlock_page(page);
- next_page:
- if (pages)
- put_page(page);
- }
- BUG_ON(pages && !list_empty(pages));
- if (bio)
- submit_bio(bio);
- return 0;
-}
--
2.19.1


2019-02-18 10:09:26

by Chandan Rajendra

[permalink] [raw]
Subject: [RFC PATCH 03/10] fscrypt: remove filesystem specific build config option

From: Chandan Rajendra <[email protected]>

In order to have a common code base for fscrypt "post read" processing
for all filesystems which support encryption, this commit removes
filesystem specific build config option (e.g. CONFIG_EXT4_FS_ENCRYPTION)
and replaces it with a build option (i.e. CONFIG_FS_ENCRYPTION) whose
value affects all the filesystems making use of fscrypt.

Reviewed-by: Eric Biggers <[email protected]>
Signed-off-by: Chandan Rajendra <[email protected]>
---
Documentation/filesystems/fscrypt.rst | 4 +-
arch/mips/configs/generic_defconfig | 2 +-
arch/nds32/configs/defconfig | 2 +-
arch/s390/configs/debug_defconfig | 2 +-
arch/s390/configs/performance_defconfig | 2 +-
fs/crypto/Kconfig | 5 +-
fs/crypto/fscrypt_private.h | 1 -
fs/ext4/Kconfig | 15 -
fs/ext4/dir.c | 2 -
fs/ext4/ext4.h | 7 +-
fs/ext4/inode.c | 8 +-
fs/ext4/ioctl.c | 4 +-
fs/ext4/namei.c | 10 +-
fs/ext4/page-io.c | 6 +-
fs/ext4/readpage.c | 2 +-
fs/ext4/super.c | 6 +-
fs/ext4/sysfs.c | 4 +-
fs/f2fs/Kconfig | 12 +-
fs/f2fs/f2fs.h | 7 +-
fs/f2fs/super.c | 8 +-
fs/f2fs/sysfs.c | 4 +-
fs/ubifs/Kconfig | 12 +-
fs/ubifs/Makefile | 2 +-
fs/ubifs/ioctl.c | 4 +-
fs/ubifs/sb.c | 2 +-
fs/ubifs/super.c | 2 +-
fs/ubifs/ubifs.h | 5 +-
include/linux/fs.h | 4 +-
include/linux/fscrypt.h | 416 +++++++++++++++++++++++-
include/linux/fscrypt_notsupp.h | 231 -------------
include/linux/fscrypt_supp.h | 204 ------------
31 files changed, 460 insertions(+), 535 deletions(-)
delete mode 100644 include/linux/fscrypt_notsupp.h
delete mode 100644 include/linux/fscrypt_supp.h

diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst
index 3a7b60521b94..43dd989e2a3f 100644
--- a/Documentation/filesystems/fscrypt.rst
+++ b/Documentation/filesystems/fscrypt.rst
@@ -343,9 +343,9 @@ FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors:
- ``ENOTEMPTY``: the file is unencrypted and is a nonempty directory
- ``ENOTTY``: this type of filesystem does not implement encryption
- ``EOPNOTSUPP``: the kernel was not configured with encryption
- support for this filesystem, or the filesystem superblock has not
+ support for filesystems, or the filesystem superblock has not
had encryption enabled on it. (For example, to use encryption on an
- ext4 filesystem, CONFIG_EXT4_ENCRYPTION must be enabled in the
+ ext4 filesystem, CONFIG_FS_ENCRYPTION must be enabled in the
kernel config, and the superblock must have had the "encrypt"
feature flag enabled using ``tune2fs -O encrypt`` or ``mkfs.ext4 -O
encrypt``.)
diff --git a/arch/mips/configs/generic_defconfig b/arch/mips/configs/generic_defconfig
index 7c138dab87df..5d80521e5d5a 100644
--- a/arch/mips/configs/generic_defconfig
+++ b/arch/mips/configs/generic_defconfig
@@ -59,7 +59,7 @@ CONFIG_HID_MONTEREY=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
-CONFIG_EXT4_ENCRYPTION=y
+CONFIG_FS_ENCRYPTION=y
CONFIG_FANOTIFY=y
CONFIG_FUSE_FS=y
CONFIG_CUSE=y
diff --git a/arch/nds32/configs/defconfig b/arch/nds32/configs/defconfig
index 2546d8770785..65ce9259081b 100644
--- a/arch/nds32/configs/defconfig
+++ b/arch/nds32/configs/defconfig
@@ -74,7 +74,7 @@ CONFIG_GENERIC_PHY=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
-CONFIG_EXT4_ENCRYPTION=y
+CONFIG_FS_ENCRYPTION=y
CONFIG_FUSE_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig
index c69cb04b7a59..9824c7bad9d4 100644
--- a/arch/s390/configs/debug_defconfig
+++ b/arch/s390/configs/debug_defconfig
@@ -500,7 +500,6 @@ CONFIG_S390_AP_IOMMU=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
-CONFIG_EXT4_ENCRYPTION=y
CONFIG_JBD2_DEBUG=y
CONFIG_JFS_FS=m
CONFIG_JFS_POSIX_ACL=y
@@ -520,6 +519,7 @@ CONFIG_BTRFS_DEBUG=y
CONFIG_NILFS2_FS=m
CONFIG_FS_DAX=y
CONFIG_EXPORTFS_BLOCK_OPS=y
+CONFIG_FS_ENCRYPTION=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig
index 32f539dc9c19..4fcbe5792744 100644
--- a/arch/s390/configs/performance_defconfig
+++ b/arch/s390/configs/performance_defconfig
@@ -497,7 +497,6 @@ CONFIG_S390_AP_IOMMU=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
-CONFIG_EXT4_ENCRYPTION=y
CONFIG_JBD2_DEBUG=y
CONFIG_JFS_FS=m
CONFIG_JFS_POSIX_ACL=y
@@ -515,6 +514,7 @@ CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_NILFS2_FS=m
CONFIG_FS_DAX=y
CONFIG_EXPORTFS_BLOCK_OPS=y
+CONFIG_FS_ENCRYPTION=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
index 02b7d91c9231..9a639da0464f 100644
--- a/fs/crypto/Kconfig
+++ b/fs/crypto/Kconfig
@@ -1,5 +1,5 @@
config FS_ENCRYPTION
- tristate "FS Encryption (Per-file encryption)"
+ bool "FS Encryption (Per-file encryption)"
select CRYPTO
select CRYPTO_AES
select CRYPTO_CBC
@@ -13,4 +13,5 @@ config FS_ENCRYPTION
Enable encryption of files and directories. This
feature is similar to ecryptfs, but it is more memory
efficient since it avoids caching the encrypted and
- decrypted pages in the page cache.
+ decrypted pages in the page cache. Currently Ext4,
+ F2FS and UBIFS make use of this feature.
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 7424f851eb5c..7da276159593 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -12,7 +12,6 @@
#ifndef _FSCRYPT_PRIVATE_H
#define _FSCRYPT_PRIVATE_H

-#define __FS_HAS_ENCRYPTION 1
#include <linux/fscrypt.h>
#include <crypto/hash.h>

diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index a453cc87082b..031e5a82d556 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -96,21 +96,6 @@ config EXT4_FS_SECURITY
If you are not using a security module that requires using
extended attributes for file security labels, say N.

-config EXT4_ENCRYPTION
- bool "Ext4 Encryption"
- depends on EXT4_FS
- select FS_ENCRYPTION
- help
- Enable encryption of ext4 files and directories. This
- feature is similar to ecryptfs, but it is more memory
- efficient since it avoids caching the encrypted and
- decrypted pages in the page cache.
-
-config EXT4_FS_ENCRYPTION
- bool
- default y
- depends on EXT4_ENCRYPTION
-
config EXT4_DEBUG
bool "EXT4 debugging support"
depends on EXT4_FS
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index fb7a64ea5679..0ccd51f72048 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -283,9 +283,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
done:
err = 0;
errout:
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
fscrypt_fname_free_buffer(&fstr);
-#endif
brelse(bh);
return err;
}
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 216efeac53ea..0ffa84772667 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -40,7 +40,6 @@
#include <linux/compat.h>
#endif

-#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_EXT4_FS_ENCRYPTION)
#include <linux/fscrypt.h>
#include <linux/fsverity.h>

@@ -1330,7 +1329,7 @@ struct ext4_super_block {
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
#define EXT4_MF_TEST_DUMMY_ENCRYPTION 0x0004

-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
#define DUMMY_ENCRYPTION_ENABLED(sbi) (unlikely((sbi)->s_mount_flags & \
EXT4_MF_TEST_DUMMY_ENCRYPTION))
#else
@@ -2058,7 +2057,7 @@ struct ext4_filename {
const struct qstr *usr_fname;
struct fscrypt_str disk_name;
struct dx_hash_info hinfo;
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
struct fscrypt_str crypto_buf;
#endif
};
@@ -2286,7 +2285,7 @@ extern unsigned ext4_free_clusters_after_init(struct super_block *sb,
struct ext4_group_desc *gdp);
ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);

-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
static inline int ext4_fname_setup_filename(struct inode *dir,
const struct qstr *iname,
int lookup, struct ext4_filename *fname)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1dcf44a865cb..b1d7ddd70eee 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1150,7 +1150,7 @@ int do_journal_get_write_access(handle_t *handle,
return ret;
}

-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
get_block_t *get_block)
{
@@ -1302,7 +1302,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
/* In case writeback began while the page was unlocked */
wait_for_stable_page(page);

-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
if (ext4_should_dioread_nolock(inode))
ret = ext4_block_write_begin(page, pos, len,
ext4_get_block_unwritten);
@@ -3104,7 +3104,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
/* In case writeback began while the page was unlocked */
wait_for_stable_page(page);

-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
ret = ext4_block_write_begin(page, pos, len,
ext4_da_get_block_prep);
#else
@@ -3879,7 +3879,7 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
loff_t offset = iocb->ki_pos;
ssize_t ret;

-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
return 0;
#endif
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 4cc87f831f9a..ede07d233f21 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -210,7 +210,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
return err;
}

-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
static int uuid_is_zero(__u8 u[16])
{
int i;
@@ -978,7 +978,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);

case EXT4_IOC_GET_ENCRYPTION_PWSALT: {
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
int err, err2;
struct ext4_sb_info *sbi = EXT4_SB(sb);
handle_t *handle;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index be6cb69beb12..980166a8122a 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -612,7 +612,7 @@ static struct stats dx_show_leaf(struct inode *dir,
{
if (show_names)
{
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
int len;
char *name;
struct fscrypt_str fname_crypto_str =
@@ -984,7 +984,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
top = (struct ext4_dir_entry_2 *) ((char *) de +
dir->i_sb->s_blocksize -
EXT4_DIR_REC_LEN(0));
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
/* Check if the directory is encrypted */
if (IS_ENCRYPTED(dir)) {
err = fscrypt_get_encryption_info(dir);
@@ -1047,7 +1047,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
}
errout:
brelse(bh);
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
fscrypt_fname_free_buffer(&fname_crypto_str);
#endif
return count;
@@ -1267,7 +1267,7 @@ static inline bool ext4_match(const struct ext4_filename *fname,

f.usr_fname = fname->usr_fname;
f.disk_name = fname->disk_name;
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
f.crypto_buf = fname->crypto_buf;
#endif
return fscrypt_match_name(&f, de->name, de->name_len);
@@ -1498,7 +1498,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
ext4_lblk_t block;
int retval;

-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
*res_dir = NULL;
#endif
frame = dx_probe(fname, dir, NULL, frames);
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index c398b55da854..b9d6cabe2ea8 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -66,7 +66,7 @@ static void ext4_finish_bio(struct bio *bio)

bio_for_each_segment_all(bvec, bio, i) {
struct page *page = bvec->bv_page;
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
struct page *data_page = NULL;
#endif
struct buffer_head *bh, *head;
@@ -78,7 +78,7 @@ static void ext4_finish_bio(struct bio *bio)
if (!page)
continue;

-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
if (!page->mapping) {
/* The bounce data pages are unmapped. */
data_page = page;
@@ -111,7 +111,7 @@ static void ext4_finish_bio(struct bio *bio)
bit_spin_unlock(BH_Uptodate_Lock, &head->b_state);
local_irq_restore(flags);
if (!under_io) {
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
if (data_page)
fscrypt_restore_control_page(data_page);
#endif
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 92488df87135..93fbc15177a3 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -54,7 +54,7 @@ static mempool_t *bio_post_read_ctx_pool;

static inline bool ext4_bio_encrypted(struct bio *bio)
{
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
return unlikely(bio->bi_private != NULL);
#else
return false;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 0f69445f1da4..95a5d9fbbb9f 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1233,7 +1233,7 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
return try_to_free_buffers(page);
}

-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
static int ext4_get_context(struct inode *inode, void *ctx, size_t len)
{
return ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
@@ -2019,7 +2019,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
*journal_ioprio =
IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
} else if (token == Opt_test_dummy_encryption) {
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION;
ext4_msg(sb, KERN_WARNING,
"Test dummy encryption mode enabled");
@@ -4264,7 +4264,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sb->s_op = &ext4_sops;
sb->s_export_op = &ext4_export_ops;
sb->s_xattr = ext4_xattr_handlers;
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
sb->s_cop = &ext4_cryptops;
#endif
#ifdef CONFIG_FS_VERITY
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
index 07b986881d22..6fa0f47c3180 100644
--- a/fs/ext4/sysfs.c
+++ b/fs/ext4/sysfs.c
@@ -224,7 +224,7 @@ static struct attribute *ext4_attrs[] = {
EXT4_ATTR_FEATURE(lazy_itable_init);
EXT4_ATTR_FEATURE(batched_discard);
EXT4_ATTR_FEATURE(meta_bg_resize);
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
EXT4_ATTR_FEATURE(encryption);
#endif
#ifdef CONFIG_FS_VERITY
@@ -236,7 +236,7 @@ static struct attribute *ext4_feat_attrs[] = {
ATTR_LIST(lazy_itable_init),
ATTR_LIST(batched_discard),
ATTR_LIST(meta_bg_resize),
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
ATTR_LIST(encryption),
#endif
#ifdef CONFIG_FS_VERITY
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
index 9a20ef42fadd..e57cc754d543 100644
--- a/fs/f2fs/Kconfig
+++ b/fs/f2fs/Kconfig
@@ -3,6 +3,7 @@ config F2FS_FS
depends on BLOCK
select CRYPTO
select CRYPTO_CRC32
+ select F2FS_FS_XATTR 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
@@ -70,17 +71,6 @@ config F2FS_CHECK_FS

If you want to improve the performance, say N.

-config F2FS_FS_ENCRYPTION
- bool "F2FS Encryption"
- depends on F2FS_FS
- depends on F2FS_FS_XATTR
- select FS_ENCRYPTION
- help
- Enable encryption of f2fs files and directories. This
- feature is similar to ecryptfs, but it is more memory
- efficient since it avoids caching the encrypted and
- decrypted pages in the page cache.
-
config F2FS_IO_TRACE
bool "F2FS IO tracer"
depends on F2FS_FS
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 520558a3fb63..78d2c7c9f517 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -24,7 +24,6 @@
#include <linux/quotaops.h>
#include <crypto/hash.h>

-#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_F2FS_FS_ENCRYPTION)
#include <linux/fscrypt.h>
#include <linux/fsverity.h>

@@ -1140,7 +1139,7 @@ enum fsync_mode {
FSYNC_MODE_NOBARRIER, /* fsync behaves nobarrier based on posix */
};

-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
#define DUMMY_ENCRYPTION_ENABLED(sbi) \
(unlikely(F2FS_OPTION(sbi).test_dummy_encryption))
#else
@@ -3473,7 +3472,7 @@ static inline bool f2fs_encrypted_file(struct inode *inode)

static inline void f2fs_set_encrypted_inode(struct inode *inode)
{
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
file_set_encrypt(inode);
f2fs_set_inode_flags(inode);
#endif
@@ -3553,7 +3552,7 @@ static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt)

static inline bool f2fs_may_encrypt(struct inode *inode)
{
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
umode_t mode = inode->i_mode;

return (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode));
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 137d356b878b..6b04662a90d0 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -757,7 +757,7 @@ static int parse_options(struct super_block *sb, char *options)
kvfree(name);
break;
case Opt_test_dummy_encryption:
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
if (!f2fs_sb_has_encrypt(sbi)) {
f2fs_msg(sb, KERN_ERR, "Encrypt feature is off");
return -EINVAL;
@@ -1390,7 +1390,7 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
seq_printf(seq, ",whint_mode=%s", "user-based");
else if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_FS)
seq_printf(seq, ",whint_mode=%s", "fs-based");
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
if (F2FS_OPTION(sbi).test_dummy_encryption)
seq_puts(seq, ",test_dummy_encryption");
#endif
@@ -2154,7 +2154,7 @@ static const struct super_operations f2fs_sops = {
.remount_fs = f2fs_remount,
};

-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
static int f2fs_get_context(struct inode *inode, void *ctx, size_t len)
{
return f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION,
@@ -3152,7 +3152,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
#endif

sb->s_op = &f2fs_sops;
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
sb->s_cop = &f2fs_cryptops;
#endif
#ifdef CONFIG_FS_VERITY
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index a6056f23d56d..7ce160973cdd 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -436,7 +436,7 @@ F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes);
F2FS_GENERAL_RO_ATTR(features);
F2FS_GENERAL_RO_ATTR(current_reserved_blocks);

-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
F2FS_FEATURE_RO_ATTR(encryption, FEAT_CRYPTO);
#endif
#ifdef CONFIG_BLK_DEV_ZONED
@@ -500,7 +500,7 @@ static struct attribute *f2fs_attrs[] = {
};

static struct attribute *f2fs_feat_attrs[] = {
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
ATTR_LIST(encryption),
#endif
#ifdef CONFIG_BLK_DEV_ZONED
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig
index bc1e082d921d..9da2f135121b 100644
--- a/fs/ubifs/Kconfig
+++ b/fs/ubifs/Kconfig
@@ -8,6 +8,7 @@ config UBIFS_FS
select CRYPTO_LZO if UBIFS_FS_LZO
select CRYPTO_DEFLATE if UBIFS_FS_ZLIB
select CRYPTO_HASH_INFO
+ select UBIFS_FS_XATTR if FS_ENCRYPTION
depends on MTD_UBI
help
UBIFS is a file system for flash devices which works on top of UBI.
@@ -60,17 +61,6 @@ config UBIFS_FS_XATTR

If unsure, say Y.

-config UBIFS_FS_ENCRYPTION
- bool "UBIFS Encryption"
- depends on UBIFS_FS_XATTR && BLOCK
- select FS_ENCRYPTION
- default n
- help
- Enable encryption of UBIFS files and directories. This
- feature is similar to ecryptfs, but it is more memory
- efficient since it avoids caching the encrypted and
- decrypted pages in the page cache.
-
config UBIFS_FS_SECURITY
bool "UBIFS Security Labels"
depends on UBIFS_FS_XATTR
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
index 5f838319c8d5..5c4b845754a7 100644
--- a/fs/ubifs/Makefile
+++ b/fs/ubifs/Makefile
@@ -6,6 +6,6 @@ ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o debug.o
ubifs-y += misc.o
-ubifs-$(CONFIG_UBIFS_FS_ENCRYPTION) += crypto.o
+ubifs-$(CONFIG_FS_ENCRYPTION) += crypto.o
ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
ubifs-$(CONFIG_UBIFS_FS_AUTHENTICATION) += auth.o
diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
index 0164bcc827f8..0f9c362a3402 100644
--- a/fs/ubifs/ioctl.c
+++ b/fs/ubifs/ioctl.c
@@ -185,7 +185,7 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return err;
}
case FS_IOC_SET_ENCRYPTION_POLICY: {
-#ifdef CONFIG_UBIFS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
struct ubifs_info *c = inode->i_sb->s_fs_info;

err = ubifs_enable_encryption(c);
@@ -198,7 +198,7 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
#endif
}
case FS_IOC_GET_ENCRYPTION_POLICY: {
-#ifdef CONFIG_UBIFS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
return fscrypt_ioctl_get_policy(file, (void __user *)arg);
#else
return -EOPNOTSUPP;
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index 3da90c951c23..67fac1e8adfb 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -748,7 +748,7 @@ int ubifs_read_superblock(struct ubifs_info *c)
goto out;
}

-#ifndef CONFIG_UBIFS_FS_ENCRYPTION
+#ifndef CONFIG_FS_ENCRYPTION
if (c->encrypted) {
ubifs_err(c, "file system contains encrypted files but UBIFS"
" was built without crypto support.");
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 1fac1133dadd..8dc2818fdd84 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -2146,7 +2146,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_UBIFS_FS_XATTR
sb->s_xattr = ubifs_xattr_handlers;
#endif
-#ifdef CONFIG_UBIFS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
sb->s_cop = &ubifs_crypt_operations;
#endif

diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 38401adaa00d..1ae12900e01d 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -43,7 +43,6 @@
#include <crypto/hash.h>
#include <crypto/algapi.h>

-#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_UBIFS_FS_ENCRYPTION)
#include <linux/fscrypt.h>

#include "ubifs-media.h"
@@ -142,7 +141,7 @@
*/
#define WORST_COMPR_FACTOR 2

-#ifdef CONFIG_UBIFS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
#define UBIFS_CIPHER_BLOCK_SIZE FS_CRYPTO_BLOCK_SIZE
#else
#define UBIFS_CIPHER_BLOCK_SIZE 0
@@ -2072,7 +2071,7 @@ int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len,
#include "misc.h"
#include "key.h"

-#ifndef CONFIG_UBIFS_FS_ENCRYPTION
+#ifndef CONFIG_FS_ENCRYPTION
static inline int ubifs_encrypt(const struct inode *inode,
struct ubifs_data_node *dn,
unsigned int in_len, unsigned int *out_len,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8bf61c851a79..e64da9c16e0d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -700,7 +700,7 @@ struct inode {
struct fsnotify_mark_connector __rcu *i_fsnotify_marks;
#endif

-#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
+#ifdef CONFIG_FS_ENCRYPTION
struct fscrypt_info *i_crypt_info;
#endif

@@ -1409,7 +1409,7 @@ struct super_block {
void *s_security;
#endif
const struct xattr_handler **s_xattr;
-#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
+#ifdef CONFIG_FS_ENCRYPTION
const struct fscrypt_operations *s_cop;
#endif
#ifdef CONFIG_FS_VERITY
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 952ab97af325..6ba193c23f37 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -2,9 +2,8 @@
/*
* fscrypt.h: declarations for per-file encryption
*
- * Filesystems that implement per-file encryption include this header
- * file with the __FS_HAS_ENCRYPTION set according to whether that filesystem
- * is being built with encryption support or not.
+ * Filesystems that implement per-file encryption must include this header
+ * file.
*
* Copyright (C) 2015, Google, Inc.
*
@@ -15,6 +14,8 @@
#define _LINUX_FSCRYPT_H

#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>

#define FS_CRYPTO_BLOCK_SIZE 16

@@ -42,11 +43,410 @@ struct fscrypt_name {
/* Maximum value for the third parameter of fscrypt_operations.set_context(). */
#define FSCRYPT_SET_CONTEXT_MAX_SIZE 28

-#if __FS_HAS_ENCRYPTION
-#include <linux/fscrypt_supp.h>
-#else
-#include <linux/fscrypt_notsupp.h>
-#endif
+#ifdef CONFIG_FS_ENCRYPTION
+/*
+ * fscrypt superblock flags
+ */
+#define FS_CFLG_OWN_PAGES (1U << 1)
+
+/*
+ * crypto operations for filesystems
+ */
+struct fscrypt_operations {
+ unsigned int flags;
+ const char *key_prefix;
+ int (*get_context)(struct inode *, void *, size_t);
+ int (*set_context)(struct inode *, const void *, size_t, void *);
+ bool (*dummy_context)(struct inode *);
+ bool (*empty_dir)(struct inode *);
+ unsigned int max_namelen;
+};
+
+struct fscrypt_ctx {
+ union {
+ struct {
+ struct page *bounce_page; /* Ciphertext page */
+ struct page *control_page; /* Original page */
+ } w;
+ struct {
+ struct bio *bio;
+ struct work_struct work;
+ } r;
+ struct list_head free_list; /* Free list */
+ };
+ u8 flags; /* Flags */
+};
+
+static inline bool fscrypt_has_encryption_key(const struct inode *inode)
+{
+ return (inode->i_crypt_info != NULL);
+}
+
+static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
+{
+ return inode->i_sb->s_cop->dummy_context &&
+ inode->i_sb->s_cop->dummy_context(inode);
+}
+
+/* crypto.c */
+extern void fscrypt_enqueue_decrypt_work(struct work_struct *);
+extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
+extern void fscrypt_release_ctx(struct fscrypt_ctx *);
+extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
+ unsigned int, unsigned int,
+ u64, gfp_t);
+extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int,
+ unsigned int, u64);
+
+static inline struct page *fscrypt_control_page(struct page *page)
+{
+ return ((struct fscrypt_ctx *)page_private(page))->w.control_page;
+}
+
+extern void fscrypt_restore_control_page(struct page *);
+
+/* policy.c */
+extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
+extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
+extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
+extern int fscrypt_inherit_context(struct inode *, struct inode *,
+ void *, bool);
+/* keyinfo.c */
+extern int fscrypt_get_encryption_info(struct inode *);
+extern void fscrypt_put_encryption_info(struct inode *);
+
+/* fname.c */
+extern int fscrypt_setup_filename(struct inode *, const struct qstr *,
+ int lookup, struct fscrypt_name *);
+
+static inline void fscrypt_free_filename(struct fscrypt_name *fname)
+{
+ kfree(fname->crypto_buf.name);
+}
+
+extern int fscrypt_fname_alloc_buffer(const struct inode *, u32,
+ struct fscrypt_str *);
+extern void fscrypt_fname_free_buffer(struct fscrypt_str *);
+extern int fscrypt_fname_disk_to_usr(struct inode *, u32, u32,
+ const struct fscrypt_str *, struct fscrypt_str *);
+
+#define FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE 32
+
+/* Extracts the second-to-last ciphertext block; see explanation below */
+#define FSCRYPT_FNAME_DIGEST(name, len) \
+ ((name) + round_down((len) - FS_CRYPTO_BLOCK_SIZE - 1, \
+ FS_CRYPTO_BLOCK_SIZE))
+
+#define FSCRYPT_FNAME_DIGEST_SIZE FS_CRYPTO_BLOCK_SIZE
+
+/**
+ * fscrypt_digested_name - alternate identifier for an on-disk filename
+ *
+ * When userspace lists an encrypted directory without access to the key,
+ * filenames whose ciphertext is longer than FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE
+ * bytes are shown in this abbreviated form (base64-encoded) rather than as the
+ * full ciphertext (base64-encoded). This is necessary to allow supporting
+ * filenames up to NAME_MAX bytes, since base64 encoding expands the length.
+ *
+ * To make it possible for filesystems to still find the correct directory entry
+ * despite not knowing the full on-disk name, we encode any filesystem-specific
+ * 'hash' and/or 'minor_hash' which the filesystem may need for its lookups,
+ * followed by the second-to-last ciphertext block of the filename. Due to the
+ * use of the CBC-CTS encryption mode, the second-to-last ciphertext block
+ * depends on the full plaintext. (Note that ciphertext stealing causes the
+ * last two blocks to appear "flipped".) This makes accidental collisions very
+ * unlikely: just a 1 in 2^128 chance for two filenames to collide even if they
+ * share the same filesystem-specific hashes.
+ *
+ * However, this scheme isn't immune to intentional collisions, which can be
+ * created by anyone able to create arbitrary plaintext filenames and view them
+ * without the key. Making the "digest" be a real cryptographic hash like
+ * SHA-256 over the full ciphertext would prevent this, although it would be
+ * less efficient and harder to implement, especially since the filesystem would
+ * need to calculate it for each directory entry examined during a search.
+ */
+struct fscrypt_digested_name {
+ u32 hash;
+ u32 minor_hash;
+ u8 digest[FSCRYPT_FNAME_DIGEST_SIZE];
+};
+
+/**
+ * fscrypt_match_name() - test whether the given name matches a directory entry
+ * @fname: the name being searched for
+ * @de_name: the name from the directory entry
+ * @de_name_len: the length of @de_name in bytes
+ *
+ * Normally @fname->disk_name will be set, and in that case we simply compare
+ * that to the name stored in the directory entry. The only exception is that
+ * if we don't have the key for an encrypted directory and a filename in it is
+ * very long, then we won't have the full disk_name and we'll instead need to
+ * match against the fscrypt_digested_name.
+ *
+ * Return: %true if the name matches, otherwise %false.
+ */
+static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
+ const u8 *de_name, u32 de_name_len)
+{
+ if (unlikely(!fname->disk_name.name)) {
+ const struct fscrypt_digested_name *n =
+ (const void *)fname->crypto_buf.name;
+ if (WARN_ON_ONCE(fname->usr_fname->name[0] != '_'))
+ return false;
+ if (de_name_len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE)
+ return false;
+ return !memcmp(FSCRYPT_FNAME_DIGEST(de_name, de_name_len),
+ n->digest, FSCRYPT_FNAME_DIGEST_SIZE);
+ }
+
+ if (de_name_len != fname->disk_name.len)
+ return false;
+ return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
+}
+
+/* bio.c */
+extern void fscrypt_decrypt_bio(struct bio *);
+extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
+ struct bio *bio);
+extern void fscrypt_pullback_bio_page(struct page **, bool);
+extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
+ unsigned int);
+
+/* hooks.c */
+extern int fscrypt_file_open(struct inode *inode, struct file *filp);
+extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir);
+extern int __fscrypt_prepare_rename(struct inode *old_dir,
+ struct dentry *old_dentry,
+ struct inode *new_dir,
+ struct dentry *new_dentry,
+ unsigned int flags);
+extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry);
+extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
+ unsigned int max_len,
+ struct fscrypt_str *disk_link);
+extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
+ unsigned int len,
+ struct fscrypt_str *disk_link);
+extern const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
+ unsigned int max_size,
+ struct delayed_call *done);
+#else /* ! CONFIG_FS_ENCRYPTION */
+
+static inline bool fscrypt_has_encryption_key(const struct inode *inode)
+{
+ return false;
+}
+
+static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
+{
+ return false;
+}
+
+/* crypto.c */
+static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
+{
+}
+
+static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode,
+ gfp_t gfp_flags)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
+{
+ return;
+}
+
+static inline struct page *fscrypt_encrypt_page(const struct inode *inode,
+ struct page *page,
+ unsigned int len,
+ unsigned int offs,
+ u64 lblk_num, gfp_t gfp_flags)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline int fscrypt_decrypt_page(const struct inode *inode,
+ struct page *page,
+ unsigned int len, unsigned int offs,
+ u64 lblk_num)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline struct page *fscrypt_control_page(struct page *page)
+{
+ WARN_ON_ONCE(1);
+ return ERR_PTR(-EINVAL);
+}
+
+static inline void fscrypt_restore_control_page(struct page *page)
+{
+ return;
+}
+
+/* policy.c */
+static inline int fscrypt_ioctl_set_policy(struct file *filp,
+ const void __user *arg)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int fscrypt_has_permitted_context(struct inode *parent,
+ struct inode *child)
+{
+ return 0;
+}
+
+static inline int fscrypt_inherit_context(struct inode *parent,
+ struct inode *child,
+ void *fs_data, bool preload)
+{
+ return -EOPNOTSUPP;
+}
+
+/* keyinfo.c */
+static inline int fscrypt_get_encryption_info(struct inode *inode)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void fscrypt_put_encryption_info(struct inode *inode)
+{
+ return;
+}
+
+ /* fname.c */
+static inline int fscrypt_setup_filename(struct inode *dir,
+ const struct qstr *iname,
+ int lookup, struct fscrypt_name *fname)
+{
+ if (IS_ENCRYPTED(dir))
+ return -EOPNOTSUPP;
+
+ memset(fname, 0, sizeof(struct fscrypt_name));
+ fname->usr_fname = iname;
+ fname->disk_name.name = (unsigned char *)iname->name;
+ fname->disk_name.len = iname->len;
+ return 0;
+}
+
+static inline void fscrypt_free_filename(struct fscrypt_name *fname)
+{
+ return;
+}
+
+static inline int fscrypt_fname_alloc_buffer(const struct inode *inode,
+ u32 max_encrypted_len,
+ struct fscrypt_str *crypto_str)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
+{
+ return;
+}
+
+static inline int fscrypt_fname_disk_to_usr(struct inode *inode,
+ u32 hash, u32 minor_hash,
+ const struct fscrypt_str *iname,
+ struct fscrypt_str *oname)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
+ const u8 *de_name, u32 de_name_len)
+{
+ /* Encryption support disabled; use standard comparison */
+ if (de_name_len != fname->disk_name.len)
+ return false;
+ return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
+}
+
+/* bio.c */
+static inline void fscrypt_decrypt_bio(struct bio *bio)
+{
+}
+
+static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
+ struct bio *bio)
+{
+}
+
+static inline void fscrypt_pullback_bio_page(struct page **page, bool restore)
+{
+ return;
+}
+
+static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
+ sector_t pblk, unsigned int len)
+{
+ return -EOPNOTSUPP;
+}
+
+/* hooks.c */
+
+static inline int fscrypt_file_open(struct inode *inode, struct file *filp)
+{
+ if (IS_ENCRYPTED(inode))
+ return -EOPNOTSUPP;
+ return 0;
+}
+
+static inline int __fscrypt_prepare_link(struct inode *inode,
+ struct inode *dir)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int __fscrypt_prepare_rename(struct inode *old_dir,
+ struct dentry *old_dentry,
+ struct inode *new_dir,
+ struct dentry *new_dentry,
+ unsigned int flags)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int __fscrypt_prepare_lookup(struct inode *dir,
+ struct dentry *dentry)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int __fscrypt_prepare_symlink(struct inode *dir,
+ unsigned int len,
+ unsigned int max_len,
+ struct fscrypt_str *disk_link)
+{
+ return -EOPNOTSUPP;
+}
+
+
+static inline int __fscrypt_encrypt_symlink(struct inode *inode,
+ const char *target,
+ unsigned int len,
+ struct fscrypt_str *disk_link)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline const char *fscrypt_get_symlink(struct inode *inode,
+ const void *caddr,
+ unsigned int max_size,
+ struct delayed_call *done)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+#endif /* ! CONFIG_FS_ENCRYPTION */

/**
* fscrypt_require_key - require an inode's encryption key
diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
deleted file mode 100644
index ee8b43e4c15a..000000000000
--- a/include/linux/fscrypt_notsupp.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * fscrypt_notsupp.h
- *
- * This stubs out the fscrypt functions for filesystems configured without
- * encryption support.
- *
- * Do not include this file directly. Use fscrypt.h instead!
- */
-#ifndef _LINUX_FSCRYPT_H
-#error "Incorrect include of linux/fscrypt_notsupp.h!"
-#endif
-
-#ifndef _LINUX_FSCRYPT_NOTSUPP_H
-#define _LINUX_FSCRYPT_NOTSUPP_H
-
-static inline bool fscrypt_has_encryption_key(const struct inode *inode)
-{
- return false;
-}
-
-static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
-{
- return false;
-}
-
-/* crypto.c */
-static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
-{
-}
-
-static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode,
- gfp_t gfp_flags)
-{
- return ERR_PTR(-EOPNOTSUPP);
-}
-
-static inline void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
-{
- return;
-}
-
-static inline struct page *fscrypt_encrypt_page(const struct inode *inode,
- struct page *page,
- unsigned int len,
- unsigned int offs,
- u64 lblk_num, gfp_t gfp_flags)
-{
- return ERR_PTR(-EOPNOTSUPP);
-}
-
-static inline int fscrypt_decrypt_page(const struct inode *inode,
- struct page *page,
- unsigned int len, unsigned int offs,
- u64 lblk_num)
-{
- return -EOPNOTSUPP;
-}
-
-static inline struct page *fscrypt_control_page(struct page *page)
-{
- WARN_ON_ONCE(1);
- return ERR_PTR(-EINVAL);
-}
-
-static inline void fscrypt_restore_control_page(struct page *page)
-{
- return;
-}
-
-/* policy.c */
-static inline int fscrypt_ioctl_set_policy(struct file *filp,
- const void __user *arg)
-{
- return -EOPNOTSUPP;
-}
-
-static inline int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
-{
- return -EOPNOTSUPP;
-}
-
-static inline int fscrypt_has_permitted_context(struct inode *parent,
- struct inode *child)
-{
- return 0;
-}
-
-static inline int fscrypt_inherit_context(struct inode *parent,
- struct inode *child,
- void *fs_data, bool preload)
-{
- return -EOPNOTSUPP;
-}
-
-/* keyinfo.c */
-static inline int fscrypt_get_encryption_info(struct inode *inode)
-{
- return -EOPNOTSUPP;
-}
-
-static inline void fscrypt_put_encryption_info(struct inode *inode)
-{
- return;
-}
-
- /* fname.c */
-static inline int fscrypt_setup_filename(struct inode *dir,
- const struct qstr *iname,
- int lookup, struct fscrypt_name *fname)
-{
- if (IS_ENCRYPTED(dir))
- return -EOPNOTSUPP;
-
- memset(fname, 0, sizeof(struct fscrypt_name));
- fname->usr_fname = iname;
- fname->disk_name.name = (unsigned char *)iname->name;
- fname->disk_name.len = iname->len;
- return 0;
-}
-
-static inline void fscrypt_free_filename(struct fscrypt_name *fname)
-{
- return;
-}
-
-static inline int fscrypt_fname_alloc_buffer(const struct inode *inode,
- u32 max_encrypted_len,
- struct fscrypt_str *crypto_str)
-{
- return -EOPNOTSUPP;
-}
-
-static inline void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
-{
- return;
-}
-
-static inline int fscrypt_fname_disk_to_usr(struct inode *inode,
- u32 hash, u32 minor_hash,
- const struct fscrypt_str *iname,
- struct fscrypt_str *oname)
-{
- return -EOPNOTSUPP;
-}
-
-static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
- const u8 *de_name, u32 de_name_len)
-{
- /* Encryption support disabled; use standard comparison */
- if (de_name_len != fname->disk_name.len)
- return false;
- return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
-}
-
-/* bio.c */
-static inline void fscrypt_decrypt_bio(struct bio *bio)
-{
-}
-
-static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
- struct bio *bio)
-{
-}
-
-static inline void fscrypt_pullback_bio_page(struct page **page, bool restore)
-{
- return;
-}
-
-static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
- sector_t pblk, unsigned int len)
-{
- return -EOPNOTSUPP;
-}
-
-/* hooks.c */
-
-static inline int fscrypt_file_open(struct inode *inode, struct file *filp)
-{
- if (IS_ENCRYPTED(inode))
- return -EOPNOTSUPP;
- return 0;
-}
-
-static inline int __fscrypt_prepare_link(struct inode *inode,
- struct inode *dir)
-{
- return -EOPNOTSUPP;
-}
-
-static inline int __fscrypt_prepare_rename(struct inode *old_dir,
- struct dentry *old_dentry,
- struct inode *new_dir,
- struct dentry *new_dentry,
- unsigned int flags)
-{
- return -EOPNOTSUPP;
-}
-
-static inline int __fscrypt_prepare_lookup(struct inode *dir,
- struct dentry *dentry)
-{
- return -EOPNOTSUPP;
-}
-
-static inline int __fscrypt_prepare_symlink(struct inode *dir,
- unsigned int len,
- unsigned int max_len,
- struct fscrypt_str *disk_link)
-{
- return -EOPNOTSUPP;
-}
-
-static inline int __fscrypt_encrypt_symlink(struct inode *inode,
- const char *target,
- unsigned int len,
- struct fscrypt_str *disk_link)
-{
- return -EOPNOTSUPP;
-}
-
-static inline const char *fscrypt_get_symlink(struct inode *inode,
- const void *caddr,
- unsigned int max_size,
- struct delayed_call *done)
-{
- return ERR_PTR(-EOPNOTSUPP);
-}
-
-#endif /* _LINUX_FSCRYPT_NOTSUPP_H */
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
deleted file mode 100644
index 6456c6b2005f..000000000000
--- a/include/linux/fscrypt_supp.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * fscrypt_supp.h
- *
- * Do not include this file directly. Use fscrypt.h instead!
- */
-#ifndef _LINUX_FSCRYPT_H
-#error "Incorrect include of linux/fscrypt_supp.h!"
-#endif
-
-#ifndef _LINUX_FSCRYPT_SUPP_H
-#define _LINUX_FSCRYPT_SUPP_H
-
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-/*
- * fscrypt superblock flags
- */
-#define FS_CFLG_OWN_PAGES (1U << 1)
-
-/*
- * crypto operations for filesystems
- */
-struct fscrypt_operations {
- unsigned int flags;
- const char *key_prefix;
- int (*get_context)(struct inode *, void *, size_t);
- int (*set_context)(struct inode *, const void *, size_t, void *);
- bool (*dummy_context)(struct inode *);
- bool (*empty_dir)(struct inode *);
- unsigned int max_namelen;
-};
-
-struct fscrypt_ctx {
- union {
- struct {
- struct page *bounce_page; /* Ciphertext page */
- struct page *control_page; /* Original page */
- } w;
- struct {
- struct bio *bio;
- struct work_struct work;
- } r;
- struct list_head free_list; /* Free list */
- };
- u8 flags; /* Flags */
-};
-
-static inline bool fscrypt_has_encryption_key(const struct inode *inode)
-{
- return (inode->i_crypt_info != NULL);
-}
-
-static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
-{
- return inode->i_sb->s_cop->dummy_context &&
- inode->i_sb->s_cop->dummy_context(inode);
-}
-
-/* crypto.c */
-extern void fscrypt_enqueue_decrypt_work(struct work_struct *);
-extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
-extern void fscrypt_release_ctx(struct fscrypt_ctx *);
-extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
- unsigned int, unsigned int,
- u64, gfp_t);
-extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int,
- unsigned int, u64);
-
-static inline struct page *fscrypt_control_page(struct page *page)
-{
- return ((struct fscrypt_ctx *)page_private(page))->w.control_page;
-}
-
-extern void fscrypt_restore_control_page(struct page *);
-
-/* policy.c */
-extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
-extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
-extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
-extern int fscrypt_inherit_context(struct inode *, struct inode *,
- void *, bool);
-/* keyinfo.c */
-extern int fscrypt_get_encryption_info(struct inode *);
-extern void fscrypt_put_encryption_info(struct inode *);
-
-/* fname.c */
-extern int fscrypt_setup_filename(struct inode *, const struct qstr *,
- int lookup, struct fscrypt_name *);
-
-static inline void fscrypt_free_filename(struct fscrypt_name *fname)
-{
- kfree(fname->crypto_buf.name);
-}
-
-extern int fscrypt_fname_alloc_buffer(const struct inode *, u32,
- struct fscrypt_str *);
-extern void fscrypt_fname_free_buffer(struct fscrypt_str *);
-extern int fscrypt_fname_disk_to_usr(struct inode *, u32, u32,
- const struct fscrypt_str *, struct fscrypt_str *);
-
-#define FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE 32
-
-/* Extracts the second-to-last ciphertext block; see explanation below */
-#define FSCRYPT_FNAME_DIGEST(name, len) \
- ((name) + round_down((len) - FS_CRYPTO_BLOCK_SIZE - 1, \
- FS_CRYPTO_BLOCK_SIZE))
-
-#define FSCRYPT_FNAME_DIGEST_SIZE FS_CRYPTO_BLOCK_SIZE
-
-/**
- * fscrypt_digested_name - alternate identifier for an on-disk filename
- *
- * When userspace lists an encrypted directory without access to the key,
- * filenames whose ciphertext is longer than FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE
- * bytes are shown in this abbreviated form (base64-encoded) rather than as the
- * full ciphertext (base64-encoded). This is necessary to allow supporting
- * filenames up to NAME_MAX bytes, since base64 encoding expands the length.
- *
- * To make it possible for filesystems to still find the correct directory entry
- * despite not knowing the full on-disk name, we encode any filesystem-specific
- * 'hash' and/or 'minor_hash' which the filesystem may need for its lookups,
- * followed by the second-to-last ciphertext block of the filename. Due to the
- * use of the CBC-CTS encryption mode, the second-to-last ciphertext block
- * depends on the full plaintext. (Note that ciphertext stealing causes the
- * last two blocks to appear "flipped".) This makes accidental collisions very
- * unlikely: just a 1 in 2^128 chance for two filenames to collide even if they
- * share the same filesystem-specific hashes.
- *
- * However, this scheme isn't immune to intentional collisions, which can be
- * created by anyone able to create arbitrary plaintext filenames and view them
- * without the key. Making the "digest" be a real cryptographic hash like
- * SHA-256 over the full ciphertext would prevent this, although it would be
- * less efficient and harder to implement, especially since the filesystem would
- * need to calculate it for each directory entry examined during a search.
- */
-struct fscrypt_digested_name {
- u32 hash;
- u32 minor_hash;
- u8 digest[FSCRYPT_FNAME_DIGEST_SIZE];
-};
-
-/**
- * fscrypt_match_name() - test whether the given name matches a directory entry
- * @fname: the name being searched for
- * @de_name: the name from the directory entry
- * @de_name_len: the length of @de_name in bytes
- *
- * Normally @fname->disk_name will be set, and in that case we simply compare
- * that to the name stored in the directory entry. The only exception is that
- * if we don't have the key for an encrypted directory and a filename in it is
- * very long, then we won't have the full disk_name and we'll instead need to
- * match against the fscrypt_digested_name.
- *
- * Return: %true if the name matches, otherwise %false.
- */
-static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
- const u8 *de_name, u32 de_name_len)
-{
- if (unlikely(!fname->disk_name.name)) {
- const struct fscrypt_digested_name *n =
- (const void *)fname->crypto_buf.name;
- if (WARN_ON_ONCE(fname->usr_fname->name[0] != '_'))
- return false;
- if (de_name_len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE)
- return false;
- return !memcmp(FSCRYPT_FNAME_DIGEST(de_name, de_name_len),
- n->digest, FSCRYPT_FNAME_DIGEST_SIZE);
- }
-
- if (de_name_len != fname->disk_name.len)
- return false;
- return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
-}
-
-/* bio.c */
-extern void fscrypt_decrypt_bio(struct bio *);
-extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
- struct bio *bio);
-extern void fscrypt_pullback_bio_page(struct page **, bool);
-extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
- unsigned int);
-
-/* hooks.c */
-extern int fscrypt_file_open(struct inode *inode, struct file *filp);
-extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir);
-extern int __fscrypt_prepare_rename(struct inode *old_dir,
- struct dentry *old_dentry,
- struct inode *new_dir,
- struct dentry *new_dentry,
- unsigned int flags);
-extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry);
-extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
- unsigned int max_len,
- struct fscrypt_str *disk_link);
-extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
- unsigned int len,
- struct fscrypt_str *disk_link);
-extern const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
- unsigned int max_size,
- struct delayed_call *done);
-
-#endif /* _LINUX_FSCRYPT_SUPP_H */
--
2.19.1


2019-02-18 10:18:43

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [RFC PATCH 00/10] Consolidate Post read processing code

On Monday, February 18, 2019 3:34:23 PM IST Chandan Rajendra wrote:
> This patchset moves the "post read processing" code into a file of its
> own and gets the generic do_mpage_readpge() to make use of the
> functionality provided. With these changes in place, the patchset
> changes Ext4 to use mpage_readpage[s] instead of its own custom
> ext4_readpages() function. This is done to reduce duplicity of code
> across filesystems. Based on the reviews provided for this patchset, I
> will change F2FS to use mpage_readpage[s] and post the next version of
> this patchset to linux-fsdevel mailing list.
>
> The patchset also includes patches from previous postings i.e.
> patches to replace per-filesystem encryption config options with a
> single config option that affects all filesystems making use of
> fscrypt code.

The patchset is based on fsverity_2019-01-30 branch of Eric's git tree. It can
also be obtained from "https://github.com/chandanr/linux.git
use-mpage-readpage-rfc".

>
> Chandan Rajendra (10):
> ext4: use IS_ENCRYPTED() to check encryption status
> f2fs: use IS_ENCRYPTED() to check encryption status
> fscrypt: remove filesystem specific build config option
> Consolidate "post read processing" into a new file
> fsverity: Add call back to decide if verity check has to be performed
> Introduce REQ_POST_READ_PROC bio flag
> fsverity: Add call back to determine readpage limit
> fsverity: Add call back to verify file holes
> fs/mpage.c: Integrate post read processing
> ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]
>
> Documentation/filesystems/fscrypt.rst | 4 +-
> arch/mips/configs/generic_defconfig | 2 +-
> arch/nds32/configs/defconfig | 2 +-
> arch/s390/configs/debug_defconfig | 2 +-
> arch/s390/configs/performance_defconfig | 2 +-
> fs/Makefile | 3 +-
> fs/crypto/Kconfig | 5 +-
> fs/crypto/bio.c | 21 +-
> fs/crypto/crypto.c | 1 +
> fs/crypto/fscrypt_private.h | 4 +-
> fs/ext4/Kconfig | 15 -
> fs/ext4/Makefile | 2 +-
> fs/ext4/dir.c | 10 +-
> fs/ext4/ext4.h | 14 +-
> fs/ext4/ext4_jbd2.h | 2 +-
> fs/ext4/extents.c | 4 +-
> fs/ext4/ialloc.c | 2 +-
> fs/ext4/inode.c | 29 +-
> fs/ext4/ioctl.c | 4 +-
> fs/ext4/move_extent.c | 3 +-
> fs/ext4/namei.c | 18 +-
> fs/ext4/page-io.c | 9 +-
> fs/ext4/readpage.c | 444 ------------------------
> fs/ext4/super.c | 43 ++-
> fs/ext4/sysfs.c | 4 +-
> fs/f2fs/Kconfig | 12 +-
> fs/f2fs/data.c | 4 +-
> fs/f2fs/dir.c | 10 +-
> fs/f2fs/f2fs.h | 14 +-
> fs/f2fs/file.c | 10 +-
> fs/f2fs/inode.c | 4 +-
> fs/f2fs/namei.c | 6 +-
> fs/f2fs/super.c | 8 +-
> fs/f2fs/sysfs.c | 4 +-
> fs/mpage.c | 77 +++-
> fs/post_read_process.c | 128 +++++++
> fs/ubifs/Kconfig | 12 +-
> fs/ubifs/Makefile | 2 +-
> fs/ubifs/ioctl.c | 4 +-
> fs/ubifs/sb.c | 2 +-
> fs/ubifs/super.c | 2 +-
> fs/ubifs/ubifs.h | 5 +-
> fs/verity/verify.c | 12 +
> include/linux/blk_types.h | 2 +
> include/linux/fs.h | 4 +-
> include/linux/fscrypt.h | 405 ++++++++++++++++++++-
> include/linux/fscrypt_notsupp.h | 231 ------------
> include/linux/fscrypt_supp.h | 204 -----------
> include/linux/fsverity.h | 3 +
> include/linux/post_read_process.h | 21 ++
> 50 files changed, 757 insertions(+), 1078 deletions(-)
> delete mode 100644 fs/ext4/readpage.c
> create mode 100644 fs/post_read_process.c
> delete mode 100644 include/linux/fscrypt_notsupp.h
> delete mode 100644 include/linux/fscrypt_supp.h
> create mode 100644 include/linux/post_read_process.h
>
>


--
chandan




2019-02-19 21:17:19

by Eric Biggers

[permalink] [raw]
Subject: Re: [RFC PATCH 00/10] Consolidate Post read processing code

Hi Chandan,

On Mon, Feb 18, 2019 at 03:34:23PM +0530, Chandan Rajendra wrote:
> This patchset moves the "post read processing" code into a file of its
> own and gets the generic do_mpage_readpge() to make use of the
> functionality provided. With these changes in place, the patchset
> changes Ext4 to use mpage_readpage[s] instead of its own custom
> ext4_readpages() function. This is done to reduce duplicity of code
> across filesystems. Based on the reviews provided for this patchset, I
> will change F2FS to use mpage_readpage[s] and post the next version of
> this patchset to linux-fsdevel mailing list.
>
> The patchset also includes patches from previous postings i.e.
> patches to replace per-filesystem encryption config options with a
> single config option that affects all filesystems making use of
> fscrypt code.
>
> Chandan Rajendra (10):
> ext4: use IS_ENCRYPTED() to check encryption status
> f2fs: use IS_ENCRYPTED() to check encryption status
> fscrypt: remove filesystem specific build config option
> Consolidate "post read processing" into a new file
> fsverity: Add call back to decide if verity check has to be performed
> Introduce REQ_POST_READ_PROC bio flag
> fsverity: Add call back to determine readpage limit
> fsverity: Add call back to verify file holes
> fs/mpage.c: Integrate post read processing
> ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]
>

Thanks for working on this! This will also make it much easier to support
block_size != PAGE_SIZE in ext4 encryption, right? I think this is the best
path forward, but I'll take a closer look at your new patches.

FYI regarding practical matters, merging fs-verity was delayed due to
disagreement about the API. See https://lwn.net/Articles/775872/.

We don't have to wait for fs-verity for your initial fscrypt changes, though:

ext4: use IS_ENCRYPTED() to check encryption status
f2fs: use IS_ENCRYPTED() to check encryption status
fscrypt: remove filesystem specific build config option

So, a couple weeks ago Ted and I already queued those three patches in
fscrypt.git (https://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git
branch "master", though we plan to change the repo soon) for the upcoming merge
window, based on upstream rather than fs-verity. Are you fine with that?

I also suggest adding linux-fsdevel to the Cc given the fs/*.c changes.

Thanks!

- Eric

2019-02-19 23:22:49

by Eric Biggers

[permalink] [raw]
Subject: Re: [RFC PATCH 04/10] Consolidate "post read processing" into a new file

Hi Chandan,

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

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

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

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

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

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

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

- Eric

2019-02-19 23:26:53

by Eric Biggers

[permalink] [raw]
Subject: Re: [f2fs-dev] [RFC PATCH 05/10] fsverity: Add call back to decide if verity check has to be performed

Hi Chandan,

On Mon, Feb 18, 2019 at 03:34:28PM +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 <[email protected]>
> ---
> fs/ext4/super.c | 9 +++++++++
> fs/post_read_process.c | 5 +++--
> include/linux/fsverity.h | 1 +
> 3 files changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 9314dddfbf34..2d7781ab6824 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -1428,10 +1428,19 @@ 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)
> +{
> + if (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT))
> + return true;
> + else
> + return false;
> +}

This can be simplified to:

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 */

Doesn't f2fs need this too? This patch only changes ext4.

>
> diff --git a/fs/post_read_process.c b/fs/post_read_process.c
> index 9720eeff0160..1f8663d70247 100644
> --- a/fs/post_read_process.c
> +++ b/fs/post_read_process.c
> @@ -79,8 +79,9 @@ struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
> if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
> post_read_steps |= 1 << STEP_DECRYPT;
> #ifdef CONFIG_FS_VERITY
> - if (inode->i_verity_info != NULL &&
> - (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
> + if (inode->i_verity_info != NULL
> + && inode->i_sb->s_vop->verity_required
> + && inode->i_sb->s_vop->verity_required(inode, index))
> post_read_steps |= 1 << STEP_VERITY;

If ->verity_required is NULL, shouldn't that be equivalent to
->verity_required() returning true?

> #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
>

- Eric

2019-02-20 00:21:04

by Eric Biggers

[permalink] [raw]
Subject: Re: [f2fs-dev] [RFC PATCH 06/10] Introduce REQ_POST_READ_PROC bio flag

Hi Chandan,

On Mon, Feb 18, 2019 at 03:34:29PM +0530, Chandan Rajendra wrote:
> Ext4 and F2FS currently use a non-NULL value stored at bio->bi_private
> to determine if the contents of the bio need to be "post processed"
> i.e. whether its contents need to be decrypted and/or verified. For
> block size < page size scenario, bio->bi_private would hold a pointer to
> buffer_head. Hence, this commit adds the new flag REQ_POST_READ_PROC to
> be able to decisively check for post process requirement for a bio.
>
> Signed-off-by: Chandan Rajendra <[email protected]>
> ---
> fs/ext4/readpage.c | 11 +++++++++--
> fs/post_read_process.c | 2 +-
> include/linux/blk_types.h | 2 ++
> 3 files changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
> index 8943fc41fd33..c7dbab35deaa 100644
> --- a/fs/ext4/readpage.c
> +++ b/fs/ext4/readpage.c
> @@ -245,6 +245,7 @@ int ext4_mpage_readpages(struct address_space *mapping,
> }
> if (bio == NULL) {
> struct bio_post_read_ctx *ctx;
> + unsigned int op_flags = 0;
>
> bio = bio_alloc(GFP_KERNEL,
> min_t(int, nr_pages, BIO_MAX_PAGES));
> @@ -259,8 +260,14 @@ int ext4_mpage_readpages(struct address_space *mapping,
> bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9);
> bio->bi_end_io = mpage_end_io;
> bio->bi_private = ctx;
> - bio_set_op_attrs(bio, REQ_OP_READ,
> - is_readahead ? REQ_RAHEAD : 0);
> +
> + if (is_readahead)
> + op_flags |= REQ_RAHEAD;
> +
> + if (ctx)
> + op_flags |= REQ_POST_READ_PROC;
> +
> + bio_set_op_attrs(bio, REQ_OP_READ, op_flags);
> }
>
> length = first_hole << blkbits;
> diff --git a/fs/post_read_process.c b/fs/post_read_process.c
> index 1f8663d70247..66c1c6e57e70 100644
> --- a/fs/post_read_process.c
> +++ b/fs/post_read_process.c
> @@ -104,7 +104,7 @@ void put_bio_post_read_ctx(struct bio_post_read_ctx *ctx)
>
> bool bio_post_read_required(struct bio *bio)
> {
> - return bio->bi_private && !bio->bi_status;
> + return bio->bi_opf & REQ_POST_READ_PROC;
> }
>
> static int __init bio_init_post_read_processing(void)
> diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
> index 5c7e7f859a24..6904945c8c40 100644
> --- a/include/linux/blk_types.h
> +++ b/include/linux/blk_types.h
> @@ -320,6 +320,7 @@ enum req_flag_bits {
> __REQ_RAHEAD, /* read ahead, can fail anytime */
> __REQ_BACKGROUND, /* background IO */
> __REQ_NOWAIT, /* Don't wait if request will block */
> + __REQ_POST_READ_PROC,
>
> /* command specific flags for REQ_OP_WRITE_ZEROES: */
> __REQ_NOUNMAP, /* do not free blocks when zeroing */
> @@ -346,6 +347,7 @@ enum req_flag_bits {
> #define REQ_RAHEAD (1ULL << __REQ_RAHEAD)
> #define REQ_BACKGROUND (1ULL << __REQ_BACKGROUND)
> #define REQ_NOWAIT (1ULL << __REQ_NOWAIT)
> +#define REQ_POST_READ_PROC (1ULL << __REQ_POST_READ_PROC)
> #define REQ_NOUNMAP (1ULL << __REQ_NOUNMAP)
> #define REQ_HIPRI (1ULL << __REQ_HIPRI)
>
> --
> 2.19.1
>
>
>

I don't think this is an appropriate use of a request flag, as request flags are
meant for the block layer.

Also doesn't the bio still need a pointer to the bio_post_read_ctx anyway? So I
don't see how this would solve the problem, if ->bi_private is already used.

- Eric

2019-02-20 00:35:11

by Eric Biggers

[permalink] [raw]
Subject: Re: [RFC PATCH 08/10] fsverity: Add call back to verify file holes

On Mon, Feb 18, 2019 at 03:34:31PM +0530, Chandan Rajendra wrote:
> readpage() implmentations zero out part of the page-cache page mapping a
> file hole. This commit adds a call back to "struct fsverity_operations"
> which readpage() can invoke to verify the file hole.

I don't see why this is needed. Since now CONFIG_FS_VERITY will be a bool,
can't you just call fsverity_verify_hole() directly?

>
> Signed-off-by: Chandan Rajendra <[email protected]>
> ---
> fs/ext4/super.c | 1 +
> include/linux/fsverity.h | 1 +
> 2 files changed, 2 insertions(+)
>
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 4493ddc357c6..94e0d4b56653 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -1459,6 +1459,7 @@ static const struct fsverity_operations ext4_verityops = {
> .read_metadata_page = ext4_read_verity_metadata_page,
> .verity_required = ext4_verity_required,
> .readpage_limit = ext4_readpage_limit,
> + .check_hole = fsverity_check_hole,
> };
> #endif /* CONFIG_FS_VERITY */
>
> diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
> index fc8113acbbfe..8bc28b07d550 100644
> --- a/include/linux/fsverity.h
> +++ b/include/linux/fsverity.h
> @@ -20,6 +20,7 @@ struct fsverity_operations {
> 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);
> + bool (*check_hole)(struct inode *inode, struct page *page);
> };
>
> #ifdef CONFIG_FS_VERITY
> --
> 2.19.1
>

2019-02-20 00:41:11

by Eric Biggers

[permalink] [raw]
Subject: Re: [RFC PATCH 00/10] Consolidate Post read processing code

On Mon, Feb 18, 2019 at 03:34:23PM +0530, Chandan Rajendra wrote:
> Based on the reviews provided for this patchset, I
> will change F2FS to use mpage_readpage[s] and post the next version of
> this patchset to linux-fsdevel mailing list.

Is that really possible? F2FS has other functionality in its ->readpages(),
such as support for filesystems that use multiple block devices.

- Eric

2019-02-21 13:31:43

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [RFC PATCH 00/10] Consolidate Post read processing code

On Wednesday, February 20, 2019 6:11:07 AM IST Eric Biggers wrote:
> On Mon, Feb 18, 2019 at 03:34:23PM +0530, Chandan Rajendra wrote:
> > Based on the reviews provided for this patchset, I
> > will change F2FS to use mpage_readpage[s] and post the next version of
> > this patchset to linux-fsdevel mailing list.
>
> Is that really possible? F2FS has other functionality in its ->readpages(),
> such as support for filesystems that use multiple block devices.
>

Hmm. I didn't know that. Thanks for pointing that out. I will read up that
code and if it isn't really possible to get F2FS to use mpage_readpage[s](),
then I would limit the patchset to Ext4.

--
chandan




2019-02-21 13:31:45

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [RFC PATCH 00/10] Consolidate Post read processing code

On Wednesday, February 20, 2019 2:47:16 AM IST Eric Biggers wrote:
> Hi Chandan,
>
> On Mon, Feb 18, 2019 at 03:34:23PM +0530, Chandan Rajendra wrote:
> > This patchset moves the "post read processing" code into a file of its
> > own and gets the generic do_mpage_readpge() to make use of the
> > functionality provided. With these changes in place, the patchset
> > changes Ext4 to use mpage_readpage[s] instead of its own custom
> > ext4_readpages() function. This is done to reduce duplicity of code
> > across filesystems. Based on the reviews provided for this patchset, I
> > will change F2FS to use mpage_readpage[s] and post the next version of
> > this patchset to linux-fsdevel mailing list.
> >
> > The patchset also includes patches from previous postings i.e.
> > patches to replace per-filesystem encryption config options with a
> > single config option that affects all filesystems making use of
> > fscrypt code.
> >
> > Chandan Rajendra (10):
> > ext4: use IS_ENCRYPTED() to check encryption status
> > f2fs: use IS_ENCRYPTED() to check encryption status
> > fscrypt: remove filesystem specific build config option
> > Consolidate "post read processing" into a new file
> > fsverity: Add call back to decide if verity check has to be performed
> > Introduce REQ_POST_READ_PROC bio flag
> > fsverity: Add call back to determine readpage limit
> > fsverity: Add call back to verify file holes
> > fs/mpage.c: Integrate post read processing
> > ext4: Wire up ext4_readpage[s] to use mpage_readpage[s]
> >
>
> Thanks for working on this! This will also make it much easier to support
> block_size != PAGE_SIZE in ext4 encryption, right? I think this is the best
> path forward, but I'll take a closer look at your new patches.
>
> FYI regarding practical matters, merging fs-verity was delayed due to
> disagreement about the API. See https://lwn.net/Articles/775872/.
>
> We don't have to wait for fs-verity for your initial fscrypt changes, though:
>
> ext4: use IS_ENCRYPTED() to check encryption status
> f2fs: use IS_ENCRYPTED() to check encryption status
> fscrypt: remove filesystem specific build config option
>
> So, a couple weeks ago Ted and I already queued those three patches in
> fscrypt.git (https://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git
> branch "master", though we plan to change the repo soon) for the upcoming merge
> window, based on upstream rather than fs-verity. Are you fine with that?

Yes, the changes looks good. Thanks for queueing them up.

>
> I also suggest adding linux-fsdevel to the Cc given the fs/*.c changes.

Yes, I will do that.

>
> Thanks!
>
> - Eric
>
>


--
chandan




2019-02-21 13:32:03

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [f2fs-dev] [RFC PATCH 05/10] fsverity: Add call back to decide if verity check has to be performed

On Wednesday, February 20, 2019 4:56:49 AM IST Eric Biggers wrote:
> Hi Chandan,
>
> On Mon, Feb 18, 2019 at 03:34:28PM +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 <[email protected]>
> > ---
> > fs/ext4/super.c | 9 +++++++++
> > fs/post_read_process.c | 5 +++--
> > include/linux/fsverity.h | 1 +
> > 3 files changed, 13 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> > index 9314dddfbf34..2d7781ab6824 100644
> > --- a/fs/ext4/super.c
> > +++ b/fs/ext4/super.c
> > @@ -1428,10 +1428,19 @@ 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)
> > +{
> > + if (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT))
> > + return true;
> > + else
> > + return false;
> > +}
>
> This can be simplified to:
>
> return index < (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
>

You are right.

> > +
> > 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 */
>
> Doesn't f2fs need this too? This patch only changes ext4.

Yes, My plan was to get review comments about the current approach and then
make corresponding changes in F2FS.

>
> >
> > diff --git a/fs/post_read_process.c b/fs/post_read_process.c
> > index 9720eeff0160..1f8663d70247 100644
> > --- a/fs/post_read_process.c
> > +++ b/fs/post_read_process.c
> > @@ -79,8 +79,9 @@ struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
> > if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
> > post_read_steps |= 1 << STEP_DECRYPT;
> > #ifdef CONFIG_FS_VERITY
> > - if (inode->i_verity_info != NULL &&
> > - (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
> > + if (inode->i_verity_info != NULL
> > + && inode->i_sb->s_vop->verity_required
> > + && inode->i_sb->s_vop->verity_required(inode, index))
> > post_read_steps |= 1 << STEP_VERITY;
>
> If ->verity_required is NULL, shouldn't that be equivalent to
> ->verity_required() returning true?
>

Yes, you are right about that. I will fix it in the next iteration of the
patchset.

> > #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
>
> - Eric
>
>


--
chandan




2019-02-21 13:32:03

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [RFC PATCH 04/10] Consolidate "post read processing" into a new file

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

Will do.

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

Sure, I will add a header describing the the code's utility.

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

Ok. I will change that.

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


--
chandan




2019-02-21 13:32:29

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [f2fs-dev] [RFC PATCH 06/10] Introduce REQ_POST_READ_PROC bio flag

On Wednesday, February 20, 2019 5:51:00 AM IST Eric Biggers wrote:
> Hi Chandan,
>
> On Mon, Feb 18, 2019 at 03:34:29PM +0530, Chandan Rajendra wrote:
> > Ext4 and F2FS currently use a non-NULL value stored at bio->bi_private
> > to determine if the contents of the bio need to be "post processed"
> > i.e. whether its contents need to be decrypted and/or verified. For
> > block size < page size scenario, bio->bi_private would hold a pointer to
> > buffer_head. Hence, this commit adds the new flag REQ_POST_READ_PROC to
> > be able to decisively check for post process requirement for a bio.
> >
> > Signed-off-by: Chandan Rajendra <[email protected]>
> > ---
> > fs/ext4/readpage.c | 11 +++++++++--
> > fs/post_read_process.c | 2 +-
> > include/linux/blk_types.h | 2 ++
> > 3 files changed, 12 insertions(+), 3 deletions(-)
> >
> > diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
> > index 8943fc41fd33..c7dbab35deaa 100644
> > --- a/fs/ext4/readpage.c
> > +++ b/fs/ext4/readpage.c
> > @@ -245,6 +245,7 @@ int ext4_mpage_readpages(struct address_space *mapping,
> > }
> > if (bio == NULL) {
> > struct bio_post_read_ctx *ctx;
> > + unsigned int op_flags = 0;
> >
> > bio = bio_alloc(GFP_KERNEL,
> > min_t(int, nr_pages, BIO_MAX_PAGES));
> > @@ -259,8 +260,14 @@ int ext4_mpage_readpages(struct address_space *mapping,
> > bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9);
> > bio->bi_end_io = mpage_end_io;
> > bio->bi_private = ctx;
> > - bio_set_op_attrs(bio, REQ_OP_READ,
> > - is_readahead ? REQ_RAHEAD : 0);
> > +
> > + if (is_readahead)
> > + op_flags |= REQ_RAHEAD;
> > +
> > + if (ctx)
> > + op_flags |= REQ_POST_READ_PROC;
> > +
> > + bio_set_op_attrs(bio, REQ_OP_READ, op_flags);
> > }
> >
> > length = first_hole << blkbits;
> > diff --git a/fs/post_read_process.c b/fs/post_read_process.c
> > index 1f8663d70247..66c1c6e57e70 100644
> > --- a/fs/post_read_process.c
> > +++ b/fs/post_read_process.c
> > @@ -104,7 +104,7 @@ void put_bio_post_read_ctx(struct bio_post_read_ctx *ctx)
> >
> > bool bio_post_read_required(struct bio *bio)
> > {
> > - return bio->bi_private && !bio->bi_status;
> > + return bio->bi_opf & REQ_POST_READ_PROC;
> > }
> >
> > static int __init bio_init_post_read_processing(void)
> > diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
> > index 5c7e7f859a24..6904945c8c40 100644
> > --- a/include/linux/blk_types.h
> > +++ b/include/linux/blk_types.h
> > @@ -320,6 +320,7 @@ enum req_flag_bits {
> > __REQ_RAHEAD, /* read ahead, can fail anytime */
> > __REQ_BACKGROUND, /* background IO */
> > __REQ_NOWAIT, /* Don't wait if request will block */
> > + __REQ_POST_READ_PROC,
> >
> > /* command specific flags for REQ_OP_WRITE_ZEROES: */
> > __REQ_NOUNMAP, /* do not free blocks when zeroing */
> > @@ -346,6 +347,7 @@ enum req_flag_bits {
> > #define REQ_RAHEAD (1ULL << __REQ_RAHEAD)
> > #define REQ_BACKGROUND (1ULL << __REQ_BACKGROUND)
> > #define REQ_NOWAIT (1ULL << __REQ_NOWAIT)
> > +#define REQ_POST_READ_PROC (1ULL << __REQ_POST_READ_PROC)
> > #define REQ_NOUNMAP (1ULL << __REQ_NOUNMAP)
> > #define REQ_HIPRI (1ULL << __REQ_HIPRI)
> >
>
> I don't think this is an appropriate use of a request flag, as request flags are
> meant for the block layer.
>
> Also doesn't the bio still need a pointer to the bio_post_read_ctx anyway? So I
> don't see how this would solve the problem, if ->bi_private is already used.

I had glanced across block_read_full_page() function which implements reading
non-contiguous blocks mapped by the page in block size < page size
scenario. Here bio->bi_private would point to the buffer head that represents
the block on which read I/O was performed. In such a case,
bio_post_read_required() would always return true. Hence I decided to add this
request flag.

Now, I believe we can actually save away the ctx pointer in bh->b_private
member and later decide on whether the buffer head requires post processing
based on bh->bi_private's non-NULL value. I will have to read up the code more
thoroughly to confirm this.

--
chandan




2019-02-21 13:32:31

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [RFC PATCH 08/10] fsverity: Add call back to verify file holes

On Wednesday, February 20, 2019 6:05:07 AM IST Eric Biggers wrote:
> On Mon, Feb 18, 2019 at 03:34:31PM +0530, Chandan Rajendra wrote:
> > readpage() implmentations zero out part of the page-cache page mapping a
> > file hole. This commit adds a call back to "struct fsverity_operations"
> > which readpage() can invoke to verify the file hole.
>
> I don't see why this is needed. Since now CONFIG_FS_VERITY will be a bool,
> can't you just call fsverity_verify_hole() directly?

Yes, I will drop this patch and replace the call back invocation (provided in
the next patch) with a call to fsverity_check_hole().

--
chandan




2019-02-21 18:38:31

by Eric Biggers

[permalink] [raw]
Subject: Re: [RFC PATCH 00/10] Consolidate Post read processing code

On Thu, Feb 21, 2019 at 07:02:03PM +0530, Chandan Rajendra wrote:
> On Wednesday, February 20, 2019 6:11:07 AM IST Eric Biggers wrote:
> > On Mon, Feb 18, 2019 at 03:34:23PM +0530, Chandan Rajendra wrote:
> > > Based on the reviews provided for this patchset, I
> > > will change F2FS to use mpage_readpage[s] and post the next version of
> > > this patchset to linux-fsdevel mailing list.
> >
> > Is that really possible? F2FS has other functionality in its ->readpages(),
> > such as support for filesystems that use multiple block devices.
> >
>
> Hmm. I didn't know that. Thanks for pointing that out. I will read up that
> code and if it isn't really possible to get F2FS to use mpage_readpage[s](),
> then I would limit the patchset to Ext4.
>

But we can make F2FS use the shared bio_post_read functions even if it can't use
mpage_readpage[s](), right?

- Eric

2019-02-22 04:29:01

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [RFC PATCH 00/10] Consolidate Post read processing code

On Friday, February 22, 2019 12:08:28 AM IST Eric Biggers wrote:
> On Thu, Feb 21, 2019 at 07:02:03PM +0530, Chandan Rajendra wrote:
> > On Wednesday, February 20, 2019 6:11:07 AM IST Eric Biggers wrote:
> > > On Mon, Feb 18, 2019 at 03:34:23PM +0530, Chandan Rajendra wrote:
> > > > Based on the reviews provided for this patchset, I
> > > > will change F2FS to use mpage_readpage[s] and post the next version of
> > > > this patchset to linux-fsdevel mailing list.
> > >
> > > Is that really possible? F2FS has other functionality in its ->readpages(),
> > > such as support for filesystems that use multiple block devices.
> > >
> >
> > Hmm. I didn't know that. Thanks for pointing that out. I will read up that
> > code and if it isn't really possible to get F2FS to use mpage_readpage[s](),
> > then I would limit the patchset to Ext4.
> >
>
> But we can make F2FS use the shared bio_post_read functions even if it can't use
> mpage_readpage[s](), right?
>

Yes, that should be possible. I will include those changes in the next version
of the patchset.

--
chandan