Merge branch 'entropy'
[linux-2.6-block.git] / fs / ext4 / page-io.c
index 4690618a92e93f133ba3c176b4757a9976805b32..12ceadef32c5a393a7588f80067418f20bc1e10d 100644 (file)
@@ -66,9 +66,7 @@ static void ext4_finish_bio(struct bio *bio)
 
        bio_for_each_segment_all(bvec, bio, iter_all) {
                struct page *page = bvec->bv_page;
-#ifdef CONFIG_FS_ENCRYPTION
-               struct page *data_page = NULL;
-#endif
+               struct page *bounce_page = NULL;
                struct buffer_head *bh, *head;
                unsigned bio_start = bvec->bv_offset;
                unsigned bio_end = bio_start + bvec->bv_len;
@@ -78,13 +76,10 @@ static void ext4_finish_bio(struct bio *bio)
                if (!page)
                        continue;
 
-#ifdef CONFIG_FS_ENCRYPTION
-               if (!page->mapping) {
-                       /* The bounce data pages are unmapped. */
-                       data_page = page;
-                       fscrypt_pullback_bio_page(&page, false);
+               if (fscrypt_is_bounce_page(page)) {
+                       bounce_page = page;
+                       page = fscrypt_pagecache_page(bounce_page);
                }
-#endif
 
                if (bio->bi_status) {
                        SetPageError(page);
@@ -111,10 +106,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_FS_ENCRYPTION
-                       if (data_page)
-                               fscrypt_restore_control_page(data_page);
-#endif
+                       fscrypt_free_bounce_page(bounce_page);
                        end_page_writeback(page);
                }
        }
@@ -404,7 +396,7 @@ submit_and_retry:
        ret = bio_add_page(io->io_bio, page, bh->b_size, bh_offset(bh));
        if (ret != bh->b_size)
                goto submit_and_retry;
-       wbc_account_io(io->io_wbc, page, bh->b_size);
+       wbc_account_cgroup_owner(io->io_wbc, page, bh->b_size);
        io->io_next_block++;
        return 0;
 }
@@ -415,7 +407,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
                        struct writeback_control *wbc,
                        bool keep_towrite)
 {
-       struct page *data_page = NULL;
+       struct page *bounce_page = NULL;
        struct inode *inode = page->mapping->host;
        unsigned block_start;
        struct buffer_head *bh, *head;
@@ -475,14 +467,22 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
 
        bh = head = page_buffers(page);
 
+       /*
+        * If any blocks are being written to an encrypted file, encrypt them
+        * into a bounce page.  For simplicity, just encrypt until the last
+        * block which might be needed.  This may cause some unneeded blocks
+        * (e.g. holes) to be unnecessarily encrypted, but this is rare and
+        * can't happen in the common case of blocksize == PAGE_SIZE.
+        */
        if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) {
                gfp_t gfp_flags = GFP_NOFS;
+               unsigned int enc_bytes = round_up(len, i_blocksize(inode));
 
        retry_encrypt:
-               data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0,
-                                               page->index, gfp_flags);
-               if (IS_ERR(data_page)) {
-                       ret = PTR_ERR(data_page);
+               bounce_page = fscrypt_encrypt_pagecache_blocks(page, enc_bytes,
+                                                              0, gfp_flags);
+               if (IS_ERR(bounce_page)) {
+                       ret = PTR_ERR(bounce_page);
                        if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
                                if (io->io_bio) {
                                        ext4_io_submit(io);
@@ -491,7 +491,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
                                gfp_flags |= __GFP_NOFAIL;
                                goto retry_encrypt;
                        }
-                       data_page = NULL;
+                       bounce_page = NULL;
                        goto out;
                }
        }
@@ -500,8 +500,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
        do {
                if (!buffer_async_write(bh))
                        continue;
-               ret = io_submit_add_bh(io, inode,
-                                      data_page ? data_page : page, bh);
+               ret = io_submit_add_bh(io, inode, bounce_page ?: page, bh);
                if (ret) {
                        /*
                         * We only get here on ENOMEM.  Not much else
@@ -517,8 +516,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
        /* Error stopped previous loop? Clean up buffers... */
        if (ret) {
        out:
-               if (data_page)
-                       fscrypt_restore_control_page(data_page);
+               fscrypt_free_bounce_page(bounce_page);
                printk_ratelimited(KERN_ERR "%s: ret = %d\n", __func__, ret);
                redirty_page_for_writepage(wbc, page);
                do {