Commit d2d0727b authored by Eric Biggers's avatar Eric Biggers

fscrypt: simplify bounce page handling

Currently, bounce page handling for writes to encrypted files is
unnecessarily complicated.  A fscrypt_ctx is allocated along with each
bounce page, page_private(bounce_page) points to this fscrypt_ctx, and
fscrypt_ctx::w::control_page points to the original pagecache page.

However, because writes don't use the fscrypt_ctx for anything else,
there's no reason why page_private(bounce_page) can't just point to the
original pagecache page directly.

Therefore, this patch makes this change.  In the process, it also cleans
up the API exposed to filesystems that allows testing whether a page is
a bounce page, getting the pagecache page from a bounce page, and
freeing a bounce page.
Reviewed-by: default avatarChandan Rajendra <chandan@linux.ibm.com>
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
parent cd6c84d8
...@@ -70,46 +70,18 @@ void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio) ...@@ -70,46 +70,18 @@ void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio)
} }
EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio); EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
void fscrypt_pullback_bio_page(struct page **page, bool restore)
{
struct fscrypt_ctx *ctx;
struct page *bounce_page;
/* The bounce data pages are unmapped. */
if ((*page)->mapping)
return;
/* The bounce data page is unmapped. */
bounce_page = *page;
ctx = (struct fscrypt_ctx *)page_private(bounce_page);
/* restore control page */
*page = ctx->w.control_page;
if (restore)
fscrypt_restore_control_page(bounce_page);
}
EXPORT_SYMBOL(fscrypt_pullback_bio_page);
int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len) sector_t pblk, unsigned int len)
{ {
struct fscrypt_ctx *ctx; struct page *ciphertext_page;
struct page *ciphertext_page = NULL;
struct bio *bio; struct bio *bio;
int ret, err = 0; int ret, err = 0;
BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE); BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE);
ctx = fscrypt_get_ctx(GFP_NOFS); ciphertext_page = fscrypt_alloc_bounce_page(GFP_NOWAIT);
if (IS_ERR(ctx)) if (!ciphertext_page)
return PTR_ERR(ctx); return -ENOMEM;
ciphertext_page = fscrypt_alloc_bounce_page(ctx, GFP_NOWAIT);
if (IS_ERR(ciphertext_page)) {
err = PTR_ERR(ciphertext_page);
goto errout;
}
while (len--) { while (len--) {
err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk, err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk,
...@@ -147,7 +119,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, ...@@ -147,7 +119,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
} }
err = 0; err = 0;
errout: errout:
fscrypt_release_ctx(ctx); fscrypt_free_bounce_page(ciphertext_page);
return err; return err;
} }
EXPORT_SYMBOL(fscrypt_zeroout_range); EXPORT_SYMBOL(fscrypt_zeroout_range);
...@@ -64,18 +64,11 @@ EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work); ...@@ -64,18 +64,11 @@ EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work);
* *
* If the encryption context was allocated from the pre-allocated pool, returns * If the encryption context was allocated from the pre-allocated pool, returns
* it to that pool. Else, frees it. * it to that pool. Else, frees it.
*
* If there's a bounce page in the context, this frees that.
*/ */
void fscrypt_release_ctx(struct fscrypt_ctx *ctx) void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
{ {
unsigned long flags; unsigned long flags;
if (ctx->flags & FS_CTX_HAS_BOUNCE_BUFFER_FL && ctx->w.bounce_page) {
mempool_free(ctx->w.bounce_page, fscrypt_bounce_page_pool);
ctx->w.bounce_page = NULL;
}
ctx->w.control_page = NULL;
if (ctx->flags & FS_CTX_REQUIRES_FREE_ENCRYPT_FL) { if (ctx->flags & FS_CTX_REQUIRES_FREE_ENCRYPT_FL) {
kmem_cache_free(fscrypt_ctx_cachep, ctx); kmem_cache_free(fscrypt_ctx_cachep, ctx);
} else { } else {
...@@ -100,14 +93,8 @@ struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags) ...@@ -100,14 +93,8 @@ struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags)
unsigned long flags; unsigned long flags;
/* /*
* We first try getting the ctx from a free list because in * First try getting a ctx from the free list so that we don't have to
* the common case the ctx will have an allocated and * call into the slab allocator.
* initialized crypto tfm, so it's probably a worthwhile
* optimization. For the bounce page, we first try getting it
* from the kernel allocator because that's just about as fast
* as getting it from a list and because a cache of free pages
* should generally be a "last resort" option for a filesystem
* to be able to do its job.
*/ */
spin_lock_irqsave(&fscrypt_ctx_lock, flags); spin_lock_irqsave(&fscrypt_ctx_lock, flags);
ctx = list_first_entry_or_null(&fscrypt_free_ctxs, ctx = list_first_entry_or_null(&fscrypt_free_ctxs,
...@@ -123,11 +110,31 @@ struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags) ...@@ -123,11 +110,31 @@ struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags)
} else { } else {
ctx->flags &= ~FS_CTX_REQUIRES_FREE_ENCRYPT_FL; ctx->flags &= ~FS_CTX_REQUIRES_FREE_ENCRYPT_FL;
} }
ctx->flags &= ~FS_CTX_HAS_BOUNCE_BUFFER_FL;
return ctx; return ctx;
} }
EXPORT_SYMBOL(fscrypt_get_ctx); EXPORT_SYMBOL(fscrypt_get_ctx);
struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags)
{
return mempool_alloc(fscrypt_bounce_page_pool, gfp_flags);
}
/**
* fscrypt_free_bounce_page() - free a ciphertext bounce page
*
* Free a bounce page that was allocated by fscrypt_encrypt_page(), or by
* fscrypt_alloc_bounce_page() directly.
*/
void fscrypt_free_bounce_page(struct page *bounce_page)
{
if (!bounce_page)
return;
set_page_private(bounce_page, (unsigned long)NULL);
ClearPagePrivate(bounce_page);
mempool_free(bounce_page, fscrypt_bounce_page_pool);
}
EXPORT_SYMBOL(fscrypt_free_bounce_page);
void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
const struct fscrypt_info *ci) const struct fscrypt_info *ci)
{ {
...@@ -186,16 +193,6 @@ int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, ...@@ -186,16 +193,6 @@ int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw,
return 0; return 0;
} }
struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx,
gfp_t gfp_flags)
{
ctx->w.bounce_page = mempool_alloc(fscrypt_bounce_page_pool, gfp_flags);
if (ctx->w.bounce_page == NULL)
return ERR_PTR(-ENOMEM);
ctx->flags |= FS_CTX_HAS_BOUNCE_BUFFER_FL;
return ctx->w.bounce_page;
}
/** /**
* fscypt_encrypt_page() - Encrypts a page * fscypt_encrypt_page() - Encrypts a page
* @inode: The inode for which the encryption should take place * @inode: The inode for which the encryption should take place
...@@ -210,22 +207,12 @@ struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, ...@@ -210,22 +207,12 @@ struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx,
* previously written data. * previously written data.
* @gfp_flags: The gfp flag for memory allocation * @gfp_flags: The gfp flag for memory allocation
* *
* Encrypts @page using the ctx encryption context. Performs encryption * Encrypts @page. If the filesystem set FS_CFLG_OWN_PAGES, then the data is
* either in-place or into a newly allocated bounce page. * encrypted in-place and @page is returned. Else, a bounce page is allocated,
* Called on the page write path. * the data is encrypted into the bounce page, and the bounce page is returned.
* * The caller is responsible for calling fscrypt_free_bounce_page().
* Bounce page allocation is the default.
* In this case, the contents of @page are encrypted and stored in an
* allocated bounce page. @page has to be locked and the caller must call
* fscrypt_restore_control_page() on the returned ciphertext page to
* release the bounce buffer and the encryption context.
*
* In-place encryption is used by setting the FS_CFLG_OWN_PAGES flag in
* fscrypt_operations. Here, the input-page is returned with its content
* encrypted.
* *
* Return: A page with the encrypted content on success. Else, an * Return: A page containing the encrypted data on success, else an ERR_PTR()
* error value or NULL.
*/ */
struct page *fscrypt_encrypt_page(const struct inode *inode, struct page *fscrypt_encrypt_page(const struct inode *inode,
struct page *page, struct page *page,
...@@ -234,7 +221,6 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, ...@@ -234,7 +221,6 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
u64 lblk_num, gfp_t gfp_flags) u64 lblk_num, gfp_t gfp_flags)
{ {
struct fscrypt_ctx *ctx;
struct page *ciphertext_page = page; struct page *ciphertext_page = page;
int err; int err;
...@@ -253,30 +239,20 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, ...@@ -253,30 +239,20 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
ctx = fscrypt_get_ctx(gfp_flags);
if (IS_ERR(ctx))
return ERR_CAST(ctx);
/* The encryption operation will require a bounce page. */ /* The encryption operation will require a bounce page. */
ciphertext_page = fscrypt_alloc_bounce_page(ctx, gfp_flags); ciphertext_page = fscrypt_alloc_bounce_page(gfp_flags);
if (IS_ERR(ciphertext_page)) if (!ciphertext_page)
goto errout; return ERR_PTR(-ENOMEM);
ctx->w.control_page = page;
err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num, err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num,
page, ciphertext_page, len, offs, page, ciphertext_page, len, offs,
gfp_flags); gfp_flags);
if (err) { if (err) {
ciphertext_page = ERR_PTR(err); fscrypt_free_bounce_page(ciphertext_page);
goto errout; return ERR_PTR(err);
} }
SetPagePrivate(ciphertext_page); SetPagePrivate(ciphertext_page);
set_page_private(ciphertext_page, (unsigned long)ctx); set_page_private(ciphertext_page, (unsigned long)page);
lock_page(ciphertext_page);
return ciphertext_page;
errout:
fscrypt_release_ctx(ctx);
return ciphertext_page; return ciphertext_page;
} }
EXPORT_SYMBOL(fscrypt_encrypt_page); EXPORT_SYMBOL(fscrypt_encrypt_page);
...@@ -355,18 +331,6 @@ const struct dentry_operations fscrypt_d_ops = { ...@@ -355,18 +331,6 @@ const struct dentry_operations fscrypt_d_ops = {
.d_revalidate = fscrypt_d_revalidate, .d_revalidate = fscrypt_d_revalidate,
}; };
void fscrypt_restore_control_page(struct page *page)
{
struct fscrypt_ctx *ctx;
ctx = (struct fscrypt_ctx *)page_private(page);
set_page_private(page, (unsigned long)NULL);
ClearPagePrivate(page);
unlock_page(page);
fscrypt_release_ctx(ctx);
}
EXPORT_SYMBOL(fscrypt_restore_control_page);
static void fscrypt_destroy(void) static void fscrypt_destroy(void)
{ {
struct fscrypt_ctx *pos, *n; struct fscrypt_ctx *pos, *n;
......
...@@ -94,7 +94,6 @@ typedef enum { ...@@ -94,7 +94,6 @@ typedef enum {
} fscrypt_direction_t; } fscrypt_direction_t;
#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001 #define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001
#define FS_CTX_HAS_BOUNCE_BUFFER_FL 0x00000002
static inline bool fscrypt_valid_enc_modes(u32 contents_mode, static inline bool fscrypt_valid_enc_modes(u32 contents_mode,
u32 filenames_mode) u32 filenames_mode)
...@@ -123,8 +122,7 @@ extern int fscrypt_do_page_crypto(const struct inode *inode, ...@@ -123,8 +122,7 @@ extern int fscrypt_do_page_crypto(const struct inode *inode,
struct page *dest_page, struct page *dest_page,
unsigned int len, unsigned int offs, unsigned int len, unsigned int offs,
gfp_t gfp_flags); gfp_t gfp_flags);
extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, extern struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags);
gfp_t gfp_flags);
extern const struct dentry_operations fscrypt_d_ops; extern const struct dentry_operations fscrypt_d_ops;
extern void __printf(3, 4) __cold extern void __printf(3, 4) __cold
......
...@@ -66,9 +66,7 @@ static void ext4_finish_bio(struct bio *bio) ...@@ -66,9 +66,7 @@ static void ext4_finish_bio(struct bio *bio)
bio_for_each_segment_all(bvec, bio, iter_all) { bio_for_each_segment_all(bvec, bio, iter_all) {
struct page *page = bvec->bv_page; struct page *page = bvec->bv_page;
#ifdef CONFIG_FS_ENCRYPTION struct page *bounce_page = NULL;
struct page *data_page = NULL;
#endif
struct buffer_head *bh, *head; struct buffer_head *bh, *head;
unsigned bio_start = bvec->bv_offset; unsigned bio_start = bvec->bv_offset;
unsigned bio_end = bio_start + bvec->bv_len; unsigned bio_end = bio_start + bvec->bv_len;
...@@ -78,13 +76,10 @@ static void ext4_finish_bio(struct bio *bio) ...@@ -78,13 +76,10 @@ static void ext4_finish_bio(struct bio *bio)
if (!page) if (!page)
continue; continue;
#ifdef CONFIG_FS_ENCRYPTION if (fscrypt_is_bounce_page(page)) {
if (!page->mapping) { bounce_page = page;
/* The bounce data pages are unmapped. */ page = fscrypt_pagecache_page(bounce_page);
data_page = page;
fscrypt_pullback_bio_page(&page, false);
} }
#endif
if (bio->bi_status) { if (bio->bi_status) {
SetPageError(page); SetPageError(page);
...@@ -111,10 +106,7 @@ static void ext4_finish_bio(struct bio *bio) ...@@ -111,10 +106,7 @@ static void ext4_finish_bio(struct bio *bio)
bit_spin_unlock(BH_Uptodate_Lock, &head->b_state); bit_spin_unlock(BH_Uptodate_Lock, &head->b_state);
local_irq_restore(flags); local_irq_restore(flags);
if (!under_io) { if (!under_io) {
#ifdef CONFIG_FS_ENCRYPTION fscrypt_free_bounce_page(bounce_page);
if (data_page)
fscrypt_restore_control_page(data_page);
#endif
end_page_writeback(page); end_page_writeback(page);
} }
} }
...@@ -415,7 +407,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, ...@@ -415,7 +407,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
struct writeback_control *wbc, struct writeback_control *wbc,
bool keep_towrite) bool keep_towrite)
{ {
struct page *data_page = NULL; struct page *bounce_page = NULL;
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
unsigned block_start; unsigned block_start;
struct buffer_head *bh, *head; struct buffer_head *bh, *head;
...@@ -479,10 +471,10 @@ int ext4_bio_write_page(struct ext4_io_submit *io, ...@@ -479,10 +471,10 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
gfp_t gfp_flags = GFP_NOFS; gfp_t gfp_flags = GFP_NOFS;
retry_encrypt: retry_encrypt:
data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0, bounce_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0,
page->index, gfp_flags); page->index, gfp_flags);
if (IS_ERR(data_page)) { if (IS_ERR(bounce_page)) {
ret = PTR_ERR(data_page); ret = PTR_ERR(bounce_page);
if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) { if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
if (io->io_bio) { if (io->io_bio) {
ext4_io_submit(io); ext4_io_submit(io);
...@@ -491,7 +483,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, ...@@ -491,7 +483,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
gfp_flags |= __GFP_NOFAIL; gfp_flags |= __GFP_NOFAIL;
goto retry_encrypt; goto retry_encrypt;
} }
data_page = NULL; bounce_page = NULL;
goto out; goto out;
} }
} }
...@@ -500,8 +492,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, ...@@ -500,8 +492,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
do { do {
if (!buffer_async_write(bh)) if (!buffer_async_write(bh))
continue; continue;
ret = io_submit_add_bh(io, inode, ret = io_submit_add_bh(io, inode, bounce_page ?: page, bh);
data_page ? data_page : page, bh);
if (ret) { if (ret) {
/* /*
* We only get here on ENOMEM. Not much else * We only get here on ENOMEM. Not much else
...@@ -517,8 +508,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, ...@@ -517,8 +508,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
/* Error stopped previous loop? Clean up buffers... */ /* Error stopped previous loop? Clean up buffers... */
if (ret) { if (ret) {
out: out:
if (data_page) fscrypt_free_bounce_page(bounce_page);
fscrypt_restore_control_page(data_page);
printk_ratelimited(KERN_ERR "%s: ret = %d\n", __func__, ret); printk_ratelimited(KERN_ERR "%s: ret = %d\n", __func__, ret);
redirty_page_for_writepage(wbc, page); redirty_page_for_writepage(wbc, page);
do { do {
......
...@@ -185,7 +185,7 @@ static void f2fs_write_end_io(struct bio *bio) ...@@ -185,7 +185,7 @@ static void f2fs_write_end_io(struct bio *bio)
continue; continue;
} }
fscrypt_pullback_bio_page(&page, true); fscrypt_finalize_bounce_page(&page);
if (unlikely(bio->bi_status)) { if (unlikely(bio->bi_status)) {
mapping_set_error(page->mapping, -EIO); mapping_set_error(page->mapping, -EIO);
...@@ -362,10 +362,9 @@ static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode, ...@@ -362,10 +362,9 @@ static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode,
bio_for_each_segment_all(bvec, io->bio, iter_all) { bio_for_each_segment_all(bvec, io->bio, iter_all) {
if (bvec->bv_page->mapping) target = bvec->bv_page;
target = bvec->bv_page; if (fscrypt_is_bounce_page(target))
else target = fscrypt_pagecache_page(target);
target = fscrypt_control_page(bvec->bv_page);
if (inode && inode == target->mapping->host) if (inode && inode == target->mapping->host)
return true; return true;
...@@ -1900,8 +1899,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) ...@@ -1900,8 +1899,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
err = f2fs_inplace_write_data(fio); err = f2fs_inplace_write_data(fio);
if (err) { if (err) {
if (f2fs_encrypted_file(inode)) if (f2fs_encrypted_file(inode))
fscrypt_pullback_bio_page(&fio->encrypted_page, fscrypt_finalize_bounce_page(&fio->encrypted_page);
true);
if (PageWriteback(page)) if (PageWriteback(page))
end_page_writeback(page); end_page_writeback(page);
} else { } else {
......
...@@ -112,12 +112,17 @@ extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, ...@@ -112,12 +112,17 @@ extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int, extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int,
unsigned int, u64); unsigned int, u64);
static inline struct page *fscrypt_control_page(struct page *page) static inline bool fscrypt_is_bounce_page(struct page *page)
{ {
return ((struct fscrypt_ctx *)page_private(page))->w.control_page; return page->mapping == NULL;
} }
extern void fscrypt_restore_control_page(struct page *); static inline struct page *fscrypt_pagecache_page(struct page *bounce_page)
{
return (struct page *)page_private(bounce_page);
}
extern void fscrypt_free_bounce_page(struct page *bounce_page);
/* policy.c */ /* policy.c */
extern int fscrypt_ioctl_set_policy(struct file *, const void __user *); extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
...@@ -223,7 +228,6 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname, ...@@ -223,7 +228,6 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
extern void fscrypt_decrypt_bio(struct bio *); extern void fscrypt_decrypt_bio(struct bio *);
extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
struct bio *bio); struct bio *bio);
extern void fscrypt_pullback_bio_page(struct page **, bool);
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
unsigned int); unsigned int);
...@@ -300,15 +304,19 @@ static inline int fscrypt_decrypt_page(const struct inode *inode, ...@@ -300,15 +304,19 @@ static inline int fscrypt_decrypt_page(const struct inode *inode,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline struct page *fscrypt_control_page(struct page *page) static inline bool fscrypt_is_bounce_page(struct page *page)
{
return false;
}
static inline struct page *fscrypt_pagecache_page(struct page *bounce_page)
{ {
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
static inline void fscrypt_restore_control_page(struct page *page) static inline void fscrypt_free_bounce_page(struct page *bounce_page)
{ {
return;
} }
/* policy.c */ /* policy.c */
...@@ -410,11 +418,6 @@ static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, ...@@ -410,11 +418,6 @@ static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
{ {
} }
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, static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len) sector_t pblk, unsigned int len)
{ {
...@@ -692,4 +695,15 @@ static inline int fscrypt_encrypt_symlink(struct inode *inode, ...@@ -692,4 +695,15 @@ static inline int fscrypt_encrypt_symlink(struct inode *inode,
return 0; return 0;
} }
/* If *pagep is a bounce page, free it and set *pagep to the pagecache page */
static inline void fscrypt_finalize_bounce_page(struct page **pagep)
{
struct page *page = *pagep;
if (fscrypt_is_bounce_page(page)) {
*pagep = fscrypt_pagecache_page(page);
fscrypt_free_bounce_page(page);
}
}
#endif /* _LINUX_FSCRYPT_H */ #endif /* _LINUX_FSCRYPT_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment