mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-18 10:13:57 +08:00
fs/buffer.c: support fscrypt in block_read_full_page()
After each filesystem block (as represented by a buffer_head) has been read from disk by block_read_full_page(), decrypt it if needed. The decryption is done on the fscrypt_read_workqueue. This is the final change needed to support ext4 encryption with blocksize != PAGE_SIZE, and it's a fairly small change now that CONFIG_FS_ENCRYPTION is a bool and fs/crypto/ exposes functions to decrypt individual blocks and to enqueue work on the fscrypt workqueue. Don't try to add fs-verity support yet, as the fs/verity/ support layer isn't ready for sub-page blocks yet. Just add fscrypt support for now. Almost all the new code is compiled away when CONFIG_FS_ENCRYPTION=n. Cc: Chandan Rajendra <chandan@linux.ibm.com> Signed-off-by: Eric Biggers <ebiggers@google.com> Link: https://lore.kernel.org/r/20191023033312.361355-2-ebiggers@kernel.org Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
4d06bfb97e
commit
31fb992ce6
48
fs/buffer.c
48
fs/buffer.c
@ -47,6 +47,7 @@
|
|||||||
#include <linux/pagevec.h>
|
#include <linux/pagevec.h>
|
||||||
#include <linux/sched/mm.h>
|
#include <linux/sched/mm.h>
|
||||||
#include <trace/events/block.h>
|
#include <trace/events/block.h>
|
||||||
|
#include <linux/fscrypt.h>
|
||||||
|
|
||||||
static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
|
static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
|
||||||
static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
|
static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
|
||||||
@ -246,10 +247,6 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* I/O completion handler for block_read_full_page() - pages
|
|
||||||
* which come unlocked at the end of I/O.
|
|
||||||
*/
|
|
||||||
static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
|
static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -307,6 +304,47 @@ still_busy:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct decrypt_bh_ctx {
|
||||||
|
struct work_struct work;
|
||||||
|
struct buffer_head *bh;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void decrypt_bh(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct decrypt_bh_ctx *ctx =
|
||||||
|
container_of(work, struct decrypt_bh_ctx, work);
|
||||||
|
struct buffer_head *bh = ctx->bh;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = fscrypt_decrypt_pagecache_blocks(bh->b_page, bh->b_size,
|
||||||
|
bh_offset(bh));
|
||||||
|
end_buffer_async_read(bh, err == 0);
|
||||||
|
kfree(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I/O completion handler for block_read_full_page() - pages
|
||||||
|
* which come unlocked at the end of I/O.
|
||||||
|
*/
|
||||||
|
static void end_buffer_async_read_io(struct buffer_head *bh, int uptodate)
|
||||||
|
{
|
||||||
|
/* Decrypt if needed */
|
||||||
|
if (uptodate && IS_ENABLED(CONFIG_FS_ENCRYPTION) &&
|
||||||
|
IS_ENCRYPTED(bh->b_page->mapping->host) &&
|
||||||
|
S_ISREG(bh->b_page->mapping->host->i_mode)) {
|
||||||
|
struct decrypt_bh_ctx *ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
|
||||||
|
|
||||||
|
if (ctx) {
|
||||||
|
INIT_WORK(&ctx->work, decrypt_bh);
|
||||||
|
ctx->bh = bh;
|
||||||
|
fscrypt_enqueue_decrypt_work(&ctx->work);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uptodate = 0;
|
||||||
|
}
|
||||||
|
end_buffer_async_read(bh, uptodate);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Completion handler for block_write_full_page() - pages which are unlocked
|
* Completion handler for block_write_full_page() - pages which are unlocked
|
||||||
* during I/O, and which have PageWriteback cleared upon I/O completion.
|
* during I/O, and which have PageWriteback cleared upon I/O completion.
|
||||||
@ -379,7 +417,7 @@ EXPORT_SYMBOL(end_buffer_async_write);
|
|||||||
*/
|
*/
|
||||||
static void mark_buffer_async_read(struct buffer_head *bh)
|
static void mark_buffer_async_read(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
bh->b_end_io = end_buffer_async_read;
|
bh->b_end_io = end_buffer_async_read_io;
|
||||||
set_buffer_async_read(bh);
|
set_buffer_async_read(bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user