]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
ext4: optimize ext4_writepage() for attempted 4k delalloc writes
authorTheodore Ts'o <tytso@mit.edu>
Sat, 3 Oct 2015 14:49:23 +0000 (10:49 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 3 Oct 2015 14:49:23 +0000 (10:49 -0400)
In cases where the file system block size is the same as the page
size, and ext4_writepage() is asked to write out a page which is
either has the unwritten bit set in the extent tree, or which does not
yet have a block assigned due to delayed allocation, we can bail out
early and, unlocking the page earlier and avoiding a round trip
through ext4_bio_write_page() with the attendant calls to
set_page_writeback() and redirty_page_for_writeback().

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/inode.c

index 612fbcf76b5c4820ad6a18d7723f7e65db803d18..c95d4065897982b11ffce8c982a508a069fe1704 100644 (file)
@@ -1815,11 +1815,22 @@ static int ext4_writepage(struct page *page,
         * the page. But we may reach here when we do a journal commit via
         * journal_submit_inode_data_buffers() and in that case we must write
         * allocated buffers to achieve data=ordered mode guarantees.
+        *
+        * Also, if there is only one buffer per page (the fs block
+        * size == the page size), if one buffer needs block
+        * allocation or needs to modify the extent tree to clear the
+        * unwritten flag, we know that the page can't be written at
+        * all, so we might as well refuse the write immediately.
+        * Unfortunately if the block size != page size, we can't as
+        * easily detect this case using ext4_walk_page_buffers(), but
+        * for the extremely common case, this is an optimization that
+        * skips a useless round trip through ext4_bio_write_page().
         */
        if (ext4_walk_page_buffers(NULL, page_bufs, 0, len, NULL,
                                   ext4_bh_delay_or_unwritten)) {
                redirty_page_for_writepage(wbc, page);
-               if (current->flags & PF_MEMALLOC) {
+               if ((current->flags & PF_MEMALLOC) ||
+                   (inode->i_sb->s_blocksize == PAGE_CACHE_SIZE)) {
                        /*
                         * For memory cleaning there's no point in writing only
                         * some buffers. So just bail out. Warn if we came here