diff options
author | Eric Biggers <ebiggers@google.com> | 2019-05-20 12:29:39 -0400 |
---|---|---|
committer | Eric Biggers <ebiggers@google.com> | 2019-05-28 13:27:52 -0400 |
commit | d2d0727b1654e11563f181f4d3d48b9275514480 (patch) | |
tree | fca4761fc4cf02a31f43aac5ae86e5276bbc298b | |
parent | cd6c84d8f0cdc911df435bb075ba22ce3c605b07 (diff) |
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: Chandan Rajendra <chandan@linux.ibm.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
-rw-r--r-- | fs/crypto/bio.c | 38 | ||||
-rw-r--r-- | fs/crypto/crypto.c | 104 | ||||
-rw-r--r-- | fs/crypto/fscrypt_private.h | 4 | ||||
-rw-r--r-- | fs/ext4/page-io.c | 36 | ||||
-rw-r--r-- | fs/f2fs/data.c | 12 | ||||
-rw-r--r-- | include/linux/fscrypt.h | 38 |
6 files changed, 84 insertions, 148 deletions
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c index b46021ebde85..c857b70b5328 100644 --- a/fs/crypto/bio.c +++ b/fs/crypto/bio.c | |||
@@ -70,46 +70,18 @@ void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio) | |||
70 | } | 70 | } |
71 | EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio); | 71 | EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio); |
72 | 72 | ||
73 | void fscrypt_pullback_bio_page(struct page **page, bool restore) | ||
74 | { | ||
75 | struct fscrypt_ctx *ctx; | ||
76 | struct page *bounce_page; | ||
77 | |||
78 | /* The bounce data pages are unmapped. */ | ||
79 | if ((*page)->mapping) | ||
80 | return; | ||
81 | |||
82 | /* The bounce data page is unmapped. */ | ||
83 | bounce_page = *page; | ||
84 | ctx = (struct fscrypt_ctx *)page_private(bounce_page); | ||
85 | |||
86 | /* restore control page */ | ||
87 | *page = ctx->w.control_page; | ||
88 | |||
89 | if (restore) | ||
90 | fscrypt_restore_control_page(bounce_page); | ||
91 | } | ||
92 | EXPORT_SYMBOL(fscrypt_pullback_bio_page); | ||
93 | |||
94 | int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, | 73 | int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, |
95 | sector_t pblk, unsigned int len) | 74 | sector_t pblk, unsigned int len) |
96 | { | 75 | { |
97 | struct fscrypt_ctx *ctx; | 76 | struct page *ciphertext_page; |
98 | struct page *ciphertext_page = NULL; | ||
99 | struct bio *bio; | 77 | struct bio *bio; |
100 | int ret, err = 0; | 78 | int ret, err = 0; |
101 | 79 | ||
102 | BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE); | 80 | BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE); |
103 | 81 | ||
104 | ctx = fscrypt_get_ctx(GFP_NOFS); | 82 | ciphertext_page = fscrypt_alloc_bounce_page(GFP_NOWAIT); |
105 | if (IS_ERR(ctx)) | 83 | if (!ciphertext_page) |
106 | return PTR_ERR(ctx); | 84 | return -ENOMEM; |
107 | |||
108 | ciphertext_page = fscrypt_alloc_bounce_page(ctx, GFP_NOWAIT); | ||
109 | if (IS_ERR(ciphertext_page)) { | ||
110 | err = PTR_ERR(ciphertext_page); | ||
111 | goto errout; | ||
112 | } | ||
113 | 85 | ||
114 | while (len--) { | 86 | while (len--) { |
115 | err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk, | 87 | 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 | } | 119 | } |
148 | err = 0; | 120 | err = 0; |
149 | errout: | 121 | errout: |
150 | fscrypt_release_ctx(ctx); | 122 | fscrypt_free_bounce_page(ciphertext_page); |
151 | return err; | 123 | return err; |
152 | } | 124 | } |
153 | EXPORT_SYMBOL(fscrypt_zeroout_range); | 125 | EXPORT_SYMBOL(fscrypt_zeroout_range); |
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 335a362ee446..881e2a69f8a6 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c | |||
@@ -64,18 +64,11 @@ EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work); | |||
64 | * | 64 | * |
65 | * If the encryption context was allocated from the pre-allocated pool, returns | 65 | * If the encryption context was allocated from the pre-allocated pool, returns |
66 | * it to that pool. Else, frees it. | 66 | * it to that pool. Else, frees it. |
67 | * | ||
68 | * If there's a bounce page in the context, this frees that. | ||
69 | */ | 67 | */ |
70 | void fscrypt_release_ctx(struct fscrypt_ctx *ctx) | 68 | void fscrypt_release_ctx(struct fscrypt_ctx *ctx) |
71 | { | 69 | { |
72 | unsigned long flags; | 70 | unsigned long flags; |
73 | 71 | ||
74 | if (ctx->flags & FS_CTX_HAS_BOUNCE_BUFFER_FL && ctx->w.bounce_page) { | ||
75 | mempool_free(ctx->w.bounce_page, fscrypt_bounce_page_pool); | ||
76 | ctx->w.bounce_page = NULL; | ||
77 | } | ||
78 | ctx->w.control_page = NULL; | ||
79 | if (ctx->flags & FS_CTX_REQUIRES_FREE_ENCRYPT_FL) { | 72 | if (ctx->flags & FS_CTX_REQUIRES_FREE_ENCRYPT_FL) { |
80 | kmem_cache_free(fscrypt_ctx_cachep, ctx); | 73 | kmem_cache_free(fscrypt_ctx_cachep, ctx); |
81 | } else { | 74 | } else { |
@@ -100,14 +93,8 @@ struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags) | |||
100 | unsigned long flags; | 93 | unsigned long flags; |
101 | 94 | ||
102 | /* | 95 | /* |
103 | * We first try getting the ctx from a free list because in | 96 | * First try getting a ctx from the free list so that we don't have to |
104 | * the common case the ctx will have an allocated and | 97 | * call into the slab allocator. |
105 | * initialized crypto tfm, so it's probably a worthwhile | ||
106 | * optimization. For the bounce page, we first try getting it | ||
107 | * from the kernel allocator because that's just about as fast | ||
108 | * as getting it from a list and because a cache of free pages | ||
109 | * should generally be a "last resort" option for a filesystem | ||
110 | * to be able to do its job. | ||
111 | */ | 98 | */ |
112 | spin_lock_irqsave(&fscrypt_ctx_lock, flags); | 99 | spin_lock_irqsave(&fscrypt_ctx_lock, flags); |
113 | ctx = list_first_entry_or_null(&fscrypt_free_ctxs, | 100 | ctx = list_first_entry_or_null(&fscrypt_free_ctxs, |
@@ -123,11 +110,31 @@ struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags) | |||
123 | } else { | 110 | } else { |
124 | ctx->flags &= ~FS_CTX_REQUIRES_FREE_ENCRYPT_FL; | 111 | ctx->flags &= ~FS_CTX_REQUIRES_FREE_ENCRYPT_FL; |
125 | } | 112 | } |
126 | ctx->flags &= ~FS_CTX_HAS_BOUNCE_BUFFER_FL; | ||
127 | return ctx; | 113 | return ctx; |
128 | } | 114 | } |
129 | EXPORT_SYMBOL(fscrypt_get_ctx); | 115 | EXPORT_SYMBOL(fscrypt_get_ctx); |
130 | 116 | ||
117 | struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags) | ||
118 | { | ||
119 | return mempool_alloc(fscrypt_bounce_page_pool, gfp_flags); | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * fscrypt_free_bounce_page() - free a ciphertext bounce page | ||
124 | * | ||
125 | * Free a bounce page that was allocated by fscrypt_encrypt_page(), or by | ||
126 | * fscrypt_alloc_bounce_page() directly. | ||
127 | */ | ||
128 | void fscrypt_free_bounce_page(struct page *bounce_page) | ||
129 | { | ||
130 | if (!bounce_page) | ||
131 | return; | ||
132 | set_page_private(bounce_page, (unsigned long)NULL); | ||
133 | ClearPagePrivate(bounce_page); | ||
134 | mempool_free(bounce_page, fscrypt_bounce_page_pool); | ||
135 | } | ||
136 | EXPORT_SYMBOL(fscrypt_free_bounce_page); | ||
137 | |||
131 | void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, | 138 | void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, |
132 | const struct fscrypt_info *ci) | 139 | const struct fscrypt_info *ci) |
133 | { | 140 | { |
@@ -186,16 +193,6 @@ int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, | |||
186 | return 0; | 193 | return 0; |
187 | } | 194 | } |
188 | 195 | ||
189 | struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, | ||
190 | gfp_t gfp_flags) | ||
191 | { | ||
192 | ctx->w.bounce_page = mempool_alloc(fscrypt_bounce_page_pool, gfp_flags); | ||
193 | if (ctx->w.bounce_page == NULL) | ||
194 | return ERR_PTR(-ENOMEM); | ||
195 | ctx->flags |= FS_CTX_HAS_BOUNCE_BUFFER_FL; | ||
196 | return ctx->w.bounce_page; | ||
197 | } | ||
198 | |||
199 | /** | 196 | /** |
200 | * fscypt_encrypt_page() - Encrypts a page | 197 | * fscypt_encrypt_page() - Encrypts a page |
201 | * @inode: The inode for which the encryption should take place | 198 | * @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 | * previously written data. | 207 | * previously written data. |
211 | * @gfp_flags: The gfp flag for memory allocation | 208 | * @gfp_flags: The gfp flag for memory allocation |
212 | * | 209 | * |
213 | * Encrypts @page using the ctx encryption context. Performs encryption | 210 | * Encrypts @page. If the filesystem set FS_CFLG_OWN_PAGES, then the data is |
214 | * either in-place or into a newly allocated bounce page. | 211 | * encrypted in-place and @page is returned. Else, a bounce page is allocated, |
215 | * Called on the page write path. | 212 | * the data is encrypted into the bounce page, and the bounce page is returned. |
216 | * | 213 | * The caller is responsible for calling fscrypt_free_bounce_page(). |
217 | * Bounce page allocation is the default. | ||
218 | * In this case, the contents of @page are encrypted and stored in an | ||
219 | * allocated bounce page. @page has to be locked and the caller must call | ||
220 | * fscrypt_restore_control_page() on the returned ciphertext page to | ||
221 | * release the bounce buffer and the encryption context. | ||
222 | * | ||
223 | * In-place encryption is used by setting the FS_CFLG_OWN_PAGES flag in | ||
224 | * fscrypt_operations. Here, the input-page is returned with its content | ||
225 | * encrypted. | ||
226 | * | 214 | * |
227 | * Return: A page with the encrypted content on success. Else, an | 215 | * Return: A page containing the encrypted data on success, else an ERR_PTR() |
228 | * error value or NULL. | ||
229 | */ | 216 | */ |
230 | struct page *fscrypt_encrypt_page(const struct inode *inode, | 217 | struct page *fscrypt_encrypt_page(const struct inode *inode, |
231 | struct page *page, | 218 | struct page *page, |
@@ -234,7 +221,6 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, | |||
234 | u64 lblk_num, gfp_t gfp_flags) | 221 | u64 lblk_num, gfp_t gfp_flags) |
235 | 222 | ||
236 | { | 223 | { |
237 | struct fscrypt_ctx *ctx; | ||
238 | struct page *ciphertext_page = page; | 224 | struct page *ciphertext_page = page; |
239 | int err; | 225 | int err; |
240 | 226 | ||
@@ -253,30 +239,20 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, | |||
253 | 239 | ||
254 | BUG_ON(!PageLocked(page)); | 240 | BUG_ON(!PageLocked(page)); |
255 | 241 | ||
256 | ctx = fscrypt_get_ctx(gfp_flags); | ||
257 | if (IS_ERR(ctx)) | ||
258 | return ERR_CAST(ctx); | ||
259 | |||
260 | /* The encryption operation will require a bounce page. */ | 242 | /* The encryption operation will require a bounce page. */ |
261 | ciphertext_page = fscrypt_alloc_bounce_page(ctx, gfp_flags); | 243 | ciphertext_page = fscrypt_alloc_bounce_page(gfp_flags); |
262 | if (IS_ERR(ciphertext_page)) | 244 | if (!ciphertext_page) |
263 | goto errout; | 245 | return ERR_PTR(-ENOMEM); |
264 | 246 | ||
265 | ctx->w.control_page = page; | ||
266 | err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num, | 247 | err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num, |
267 | page, ciphertext_page, len, offs, | 248 | page, ciphertext_page, len, offs, |
268 | gfp_flags); | 249 | gfp_flags); |
269 | if (err) { | 250 | if (err) { |
270 | ciphertext_page = ERR_PTR(err); | 251 | fscrypt_free_bounce_page(ciphertext_page); |
271 | goto errout; | 252 | return ERR_PTR(err); |
272 | } | 253 | } |
273 | SetPagePrivate(ciphertext_page); | 254 | SetPagePrivate(ciphertext_page); |
274 | set_page_private(ciphertext_page, (unsigned long)ctx); | 255 | set_page_private(ciphertext_page, (unsigned long)page); |
275 | lock_page(ciphertext_page); | ||
276 | return ciphertext_page; | ||
277 | |||
278 | errout: | ||
279 | fscrypt_release_ctx(ctx); | ||
280 | return ciphertext_page; | 256 | return ciphertext_page; |
281 | } | 257 | } |
282 | EXPORT_SYMBOL(fscrypt_encrypt_page); | 258 | EXPORT_SYMBOL(fscrypt_encrypt_page); |
@@ -355,18 +331,6 @@ const struct dentry_operations fscrypt_d_ops = { | |||
355 | .d_revalidate = fscrypt_d_revalidate, | 331 | .d_revalidate = fscrypt_d_revalidate, |
356 | }; | 332 | }; |
357 | 333 | ||
358 | void fscrypt_restore_control_page(struct page *page) | ||
359 | { | ||
360 | struct fscrypt_ctx *ctx; | ||
361 | |||
362 | ctx = (struct fscrypt_ctx *)page_private(page); | ||
363 | set_page_private(page, (unsigned long)NULL); | ||
364 | ClearPagePrivate(page); | ||
365 | unlock_page(page); | ||
366 | fscrypt_release_ctx(ctx); | ||
367 | } | ||
368 | EXPORT_SYMBOL(fscrypt_restore_control_page); | ||
369 | |||
370 | static void fscrypt_destroy(void) | 334 | static void fscrypt_destroy(void) |
371 | { | 335 | { |
372 | struct fscrypt_ctx *pos, *n; | 336 | struct fscrypt_ctx *pos, *n; |
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 7da276159593..4122ee1a0b7b 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h | |||
@@ -94,7 +94,6 @@ typedef enum { | |||
94 | } fscrypt_direction_t; | 94 | } fscrypt_direction_t; |
95 | 95 | ||
96 | #define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001 | 96 | #define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001 |
97 | #define FS_CTX_HAS_BOUNCE_BUFFER_FL 0x00000002 | ||
98 | 97 | ||
99 | static inline bool fscrypt_valid_enc_modes(u32 contents_mode, | 98 | static inline bool fscrypt_valid_enc_modes(u32 contents_mode, |
100 | u32 filenames_mode) | 99 | u32 filenames_mode) |
@@ -123,8 +122,7 @@ extern int fscrypt_do_page_crypto(const struct inode *inode, | |||
123 | struct page *dest_page, | 122 | struct page *dest_page, |
124 | unsigned int len, unsigned int offs, | 123 | unsigned int len, unsigned int offs, |
125 | gfp_t gfp_flags); | 124 | gfp_t gfp_flags); |
126 | extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, | 125 | extern struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags); |
127 | gfp_t gfp_flags); | ||
128 | extern const struct dentry_operations fscrypt_d_ops; | 126 | extern const struct dentry_operations fscrypt_d_ops; |
129 | 127 | ||
130 | extern void __printf(3, 4) __cold | 128 | extern void __printf(3, 4) __cold |
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 4690618a92e9..13d5ecc0af03 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
@@ -66,9 +66,7 @@ static void ext4_finish_bio(struct bio *bio) | |||
66 | 66 | ||
67 | bio_for_each_segment_all(bvec, bio, iter_all) { | 67 | bio_for_each_segment_all(bvec, bio, iter_all) { |
68 | struct page *page = bvec->bv_page; | 68 | struct page *page = bvec->bv_page; |
69 | #ifdef CONFIG_FS_ENCRYPTION | 69 | struct page *bounce_page = NULL; |
70 | struct page *data_page = NULL; | ||
71 | #endif | ||
72 | struct buffer_head *bh, *head; | 70 | struct buffer_head *bh, *head; |
73 | unsigned bio_start = bvec->bv_offset; | 71 | unsigned bio_start = bvec->bv_offset; |
74 | unsigned bio_end = bio_start + bvec->bv_len; | 72 | unsigned bio_end = bio_start + bvec->bv_len; |
@@ -78,13 +76,10 @@ static void ext4_finish_bio(struct bio *bio) | |||
78 | if (!page) | 76 | if (!page) |
79 | continue; | 77 | continue; |
80 | 78 | ||
81 | #ifdef CONFIG_FS_ENCRYPTION | 79 | if (fscrypt_is_bounce_page(page)) { |
82 | if (!page->mapping) { | 80 | bounce_page = page; |
83 | /* The bounce data pages are unmapped. */ | 81 | page = fscrypt_pagecache_page(bounce_page); |
84 | data_page = page; | ||
85 | fscrypt_pullback_bio_page(&page, false); | ||
86 | } | 82 | } |
87 | #endif | ||
88 | 83 | ||
89 | if (bio->bi_status) { | 84 | if (bio->bi_status) { |
90 | SetPageError(page); | 85 | SetPageError(page); |
@@ -111,10 +106,7 @@ static void ext4_finish_bio(struct bio *bio) | |||
111 | bit_spin_unlock(BH_Uptodate_Lock, &head->b_state); | 106 | bit_spin_unlock(BH_Uptodate_Lock, &head->b_state); |
112 | local_irq_restore(flags); | 107 | local_irq_restore(flags); |
113 | if (!under_io) { | 108 | if (!under_io) { |
114 | #ifdef CONFIG_FS_ENCRYPTION | 109 | fscrypt_free_bounce_page(bounce_page); |
115 | if (data_page) | ||
116 | fscrypt_restore_control_page(data_page); | ||
117 | #endif | ||
118 | end_page_writeback(page); | 110 | end_page_writeback(page); |
119 | } | 111 | } |
120 | } | 112 | } |
@@ -415,7 +407,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
415 | struct writeback_control *wbc, | 407 | struct writeback_control *wbc, |
416 | bool keep_towrite) | 408 | bool keep_towrite) |
417 | { | 409 | { |
418 | struct page *data_page = NULL; | 410 | struct page *bounce_page = NULL; |
419 | struct inode *inode = page->mapping->host; | 411 | struct inode *inode = page->mapping->host; |
420 | unsigned block_start; | 412 | unsigned block_start; |
421 | struct buffer_head *bh, *head; | 413 | struct buffer_head *bh, *head; |
@@ -479,10 +471,10 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
479 | gfp_t gfp_flags = GFP_NOFS; | 471 | gfp_t gfp_flags = GFP_NOFS; |
480 | 472 | ||
481 | retry_encrypt: | 473 | retry_encrypt: |
482 | data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0, | 474 | bounce_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0, |
483 | page->index, gfp_flags); | 475 | page->index, gfp_flags); |
484 | if (IS_ERR(data_page)) { | 476 | if (IS_ERR(bounce_page)) { |
485 | ret = PTR_ERR(data_page); | 477 | ret = PTR_ERR(bounce_page); |
486 | if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) { | 478 | if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) { |
487 | if (io->io_bio) { | 479 | if (io->io_bio) { |
488 | ext4_io_submit(io); | 480 | ext4_io_submit(io); |
@@ -491,7 +483,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
491 | gfp_flags |= __GFP_NOFAIL; | 483 | gfp_flags |= __GFP_NOFAIL; |
492 | goto retry_encrypt; | 484 | goto retry_encrypt; |
493 | } | 485 | } |
494 | data_page = NULL; | 486 | bounce_page = NULL; |
495 | goto out; | 487 | goto out; |
496 | } | 488 | } |
497 | } | 489 | } |
@@ -500,8 +492,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
500 | do { | 492 | do { |
501 | if (!buffer_async_write(bh)) | 493 | if (!buffer_async_write(bh)) |
502 | continue; | 494 | continue; |
503 | ret = io_submit_add_bh(io, inode, | 495 | ret = io_submit_add_bh(io, inode, bounce_page ?: page, bh); |
504 | data_page ? data_page : page, bh); | ||
505 | if (ret) { | 496 | if (ret) { |
506 | /* | 497 | /* |
507 | * We only get here on ENOMEM. Not much else | 498 | * We only get here on ENOMEM. Not much else |
@@ -517,8 +508,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
517 | /* Error stopped previous loop? Clean up buffers... */ | 508 | /* Error stopped previous loop? Clean up buffers... */ |
518 | if (ret) { | 509 | if (ret) { |
519 | out: | 510 | out: |
520 | if (data_page) | 511 | fscrypt_free_bounce_page(bounce_page); |
521 | fscrypt_restore_control_page(data_page); | ||
522 | printk_ratelimited(KERN_ERR "%s: ret = %d\n", __func__, ret); | 512 | printk_ratelimited(KERN_ERR "%s: ret = %d\n", __func__, ret); |
523 | redirty_page_for_writepage(wbc, page); | 513 | redirty_page_for_writepage(wbc, page); |
524 | do { | 514 | do { |
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index eda4181d2092..968ebdbcb583 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -185,7 +185,7 @@ static void f2fs_write_end_io(struct bio *bio) | |||
185 | continue; | 185 | continue; |
186 | } | 186 | } |
187 | 187 | ||
188 | fscrypt_pullback_bio_page(&page, true); | 188 | fscrypt_finalize_bounce_page(&page); |
189 | 189 | ||
190 | if (unlikely(bio->bi_status)) { | 190 | if (unlikely(bio->bi_status)) { |
191 | mapping_set_error(page->mapping, -EIO); | 191 | mapping_set_error(page->mapping, -EIO); |
@@ -362,10 +362,9 @@ static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode, | |||
362 | 362 | ||
363 | bio_for_each_segment_all(bvec, io->bio, iter_all) { | 363 | bio_for_each_segment_all(bvec, io->bio, iter_all) { |
364 | 364 | ||
365 | if (bvec->bv_page->mapping) | 365 | target = bvec->bv_page; |
366 | target = bvec->bv_page; | 366 | if (fscrypt_is_bounce_page(target)) |
367 | else | 367 | target = fscrypt_pagecache_page(target); |
368 | target = fscrypt_control_page(bvec->bv_page); | ||
369 | 368 | ||
370 | if (inode && inode == target->mapping->host) | 369 | if (inode && inode == target->mapping->host) |
371 | return true; | 370 | return true; |
@@ -1900,8 +1899,7 @@ got_it: | |||
1900 | err = f2fs_inplace_write_data(fio); | 1899 | err = f2fs_inplace_write_data(fio); |
1901 | if (err) { | 1900 | if (err) { |
1902 | if (f2fs_encrypted_file(inode)) | 1901 | if (f2fs_encrypted_file(inode)) |
1903 | fscrypt_pullback_bio_page(&fio->encrypted_page, | 1902 | fscrypt_finalize_bounce_page(&fio->encrypted_page); |
1904 | true); | ||
1905 | if (PageWriteback(page)) | 1903 | if (PageWriteback(page)) |
1906 | end_page_writeback(page); | 1904 | end_page_writeback(page); |
1907 | } else { | 1905 | } else { |
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index f7680ef1abd2..d016fa384d60 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h | |||
@@ -112,12 +112,17 @@ extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, | |||
112 | extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int, | 112 | extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int, |
113 | unsigned int, u64); | 113 | unsigned int, u64); |
114 | 114 | ||
115 | static inline struct page *fscrypt_control_page(struct page *page) | 115 | static inline bool fscrypt_is_bounce_page(struct page *page) |
116 | { | 116 | { |
117 | return ((struct fscrypt_ctx *)page_private(page))->w.control_page; | 117 | return page->mapping == NULL; |
118 | } | 118 | } |
119 | 119 | ||
120 | extern void fscrypt_restore_control_page(struct page *); | 120 | static inline struct page *fscrypt_pagecache_page(struct page *bounce_page) |
121 | { | ||
122 | return (struct page *)page_private(bounce_page); | ||
123 | } | ||
124 | |||
125 | extern void fscrypt_free_bounce_page(struct page *bounce_page); | ||
121 | 126 | ||
122 | /* policy.c */ | 127 | /* policy.c */ |
123 | extern int fscrypt_ioctl_set_policy(struct file *, const void __user *); | 128 | 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 | extern void fscrypt_decrypt_bio(struct bio *); | 228 | extern void fscrypt_decrypt_bio(struct bio *); |
224 | extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, | 229 | extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, |
225 | struct bio *bio); | 230 | struct bio *bio); |
226 | extern void fscrypt_pullback_bio_page(struct page **, bool); | ||
227 | extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, | 231 | extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, |
228 | unsigned int); | 232 | unsigned int); |
229 | 233 | ||
@@ -300,15 +304,19 @@ static inline int fscrypt_decrypt_page(const struct inode *inode, | |||
300 | return -EOPNOTSUPP; | 304 | return -EOPNOTSUPP; |
301 | } | 305 | } |
302 | 306 | ||
303 | static inline struct page *fscrypt_control_page(struct page *page) | 307 | static inline bool fscrypt_is_bounce_page(struct page *page) |
308 | { | ||
309 | return false; | ||
310 | } | ||
311 | |||
312 | static inline struct page *fscrypt_pagecache_page(struct page *bounce_page) | ||
304 | { | 313 | { |
305 | WARN_ON_ONCE(1); | 314 | WARN_ON_ONCE(1); |
306 | return ERR_PTR(-EINVAL); | 315 | return ERR_PTR(-EINVAL); |
307 | } | 316 | } |
308 | 317 | ||
309 | static inline void fscrypt_restore_control_page(struct page *page) | 318 | static inline void fscrypt_free_bounce_page(struct page *bounce_page) |
310 | { | 319 | { |
311 | return; | ||
312 | } | 320 | } |
313 | 321 | ||
314 | /* policy.c */ | 322 | /* policy.c */ |
@@ -410,11 +418,6 @@ static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, | |||
410 | { | 418 | { |
411 | } | 419 | } |
412 | 420 | ||
413 | static inline void fscrypt_pullback_bio_page(struct page **page, bool restore) | ||
414 | { | ||
415 | return; | ||
416 | } | ||
417 | |||
418 | static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, | 421 | static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, |
419 | sector_t pblk, unsigned int len) | 422 | sector_t pblk, unsigned int len) |
420 | { | 423 | { |
@@ -692,4 +695,15 @@ static inline int fscrypt_encrypt_symlink(struct inode *inode, | |||
692 | return 0; | 695 | return 0; |
693 | } | 696 | } |
694 | 697 | ||
698 | /* If *pagep is a bounce page, free it and set *pagep to the pagecache page */ | ||
699 | static inline void fscrypt_finalize_bounce_page(struct page **pagep) | ||
700 | { | ||
701 | struct page *page = *pagep; | ||
702 | |||
703 | if (fscrypt_is_bounce_page(page)) { | ||
704 | *pagep = fscrypt_pagecache_page(page); | ||
705 | fscrypt_free_bounce_page(page); | ||
706 | } | ||
707 | } | ||
708 | |||
695 | #endif /* _LINUX_FSCRYPT_H */ | 709 | #endif /* _LINUX_FSCRYPT_H */ |