@@ -409,6 +409,47 @@ static int io_submit_add_bh(struct ext4_io_submit *io,
return 0;
}
+static struct page *
+encrypt_page(struct inode *inode, struct page *page,
+ struct writeback_control *wbc, struct ext4_io_submit *io)
+{
+ struct page *data_page;
+ struct buffer_head *bh, *head;
+ gfp_t gfp_flags = GFP_NOFS;
+ u64 blk_nr;
+ int err;
+
+retry:
+ data_page = fscrypt_prep_ciphertext_page(inode, page, gfp_flags);
+ if (IS_ERR(data_page))
+ goto out;
+
+ bh = head = page_buffers(page);
+ blk_nr = (u64)page->index << (PAGE_SHIFT - inode->i_blkbits);
+ do {
+ if (!buffer_async_write(bh))
+ continue;
+ err = fscrypt_encrypt_block(inode, page, data_page, bh->b_size,
+ bh_offset(bh), blk_nr, gfp_flags);
+ if (err) {
+ fscrypt_restore_control_page(data_page);
+ data_page = ERR_PTR(err);
+ break;
+ }
+ } while (blk_nr++, (bh = bh->b_this_page) != head);
+
+out:
+ if (data_page == ERR_PTR(-ENOMEM) && wbc->sync_mode == WB_SYNC_ALL) {
+ if (io->io_bio) {
+ ext4_io_submit(io);
+ congestion_wait(BLK_RW_ASYNC, HZ/50);
+ }
+ gfp_flags |= __GFP_NOFAIL;
+ goto retry;
+ }
+ return data_page;
+}
+
int ext4_bio_write_page(struct ext4_io_submit *io,
struct page *page,
int len,
@@ -477,23 +518,10 @@ 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) {
- gfp_t gfp_flags = GFP_NOFS;
-
- retry_encrypt:
- data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0,
- page->index, gfp_flags);
+ if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) {
+ data_page = encrypt_page(inode, page, wbc, io);
if (IS_ERR(data_page)) {
ret = PTR_ERR(data_page);
- if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
- if (io->io_bio) {
- ext4_io_submit(io);
- congestion_wait(BLK_RW_ASYNC, HZ/50);
- }
- gfp_flags |= __GFP_NOFAIL;
- goto retry_encrypt;
- }
data_page = NULL;
goto out;
}