From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jan Kara Subject: [PATCH 4/5] fs: Move i_size update in write_end() from under page lock Date: Tue, 11 Aug 2009 00:20:46 +0200 Message-ID: <1249942847-23851-5-git-send-email-jack@suse.cz> References: <1249942847-23851-1-git-send-email-jack@suse.cz> Cc: linux-mm@vger.kernel.org, npiggin@suse.de, Jan Kara To: linux-fsdevel@vger.kernel.org Return-path: Received: from cantor2.suse.de ([195.135.220.15]:52447 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754063AbZHJWUs (ORCPT ); Mon, 10 Aug 2009 18:20:48 -0400 In-Reply-To: <1249942847-23851-1-git-send-email-jack@suse.cz> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: From: Nick Piggin The previous patch allows us to relax the requirement that the page lock must be held in order to avoid writepage zeroing out new data beyond isize. Signed-off-by: Nick Piggin Signed-off-by: Jan Kara --- fs/buffer.c | 28 ++++++++-------------------- mm/shmem.c | 6 +++--- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 2b8cabe..15e7f40 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2049,33 +2049,20 @@ int generic_write_end(struct file *file, struct address_space *mapping, struct page *page, void *fsdata) { struct inode *inode = mapping->host; - int i_size_changed = 0; copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); + unlock_page(page); + page_cache_release(page); + /* * No need to use i_size_read() here, the i_size * cannot change under us because we hold i_mutex. - * - * But it's important to update i_size while still holding page lock: - * page writeout could otherwise come in and zero beyond i_size. */ if (pos+copied > inode->i_size) { i_size_write(inode, pos+copied); - i_size_changed = 1; - } - - unlock_page(page); - page_cache_release(page); - - /* - * Don't mark the inode dirty under page lock. First, it unnecessarily - * makes the holding time of page lock longer. Second, it forces lock - * ordering of page lock and transaction start for journaling - * filesystems. - */ - if (i_size_changed) mark_inode_dirty(inode); + } return copied; } @@ -2629,14 +2616,15 @@ int nobh_write_end(struct file *file, struct address_space *mapping, SetPageUptodate(page); set_page_dirty(page); + + unlock_page(page); + page_cache_release(page); + if (pos+copied > inode->i_size) { i_size_write(inode, pos+copied); mark_inode_dirty(inode); } - unlock_page(page); - page_cache_release(page); - while (head) { bh = head; head = head->b_this_page; diff --git a/mm/shmem.c b/mm/shmem.c index d713239..52ac65c 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1627,13 +1627,13 @@ shmem_write_end(struct file *file, struct address_space *mapping, { struct inode *inode = mapping->host; - if (pos + copied > inode->i_size) - i_size_write(inode, pos + copied); - unlock_page(page); set_page_dirty(page); page_cache_release(page); + if (pos + copied > inode->i_size) + i_size_write(inode, pos + copied); + return copied; } -- 1.6.0.2