From patchwork Mon May 9 23:03:56 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 94915 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 395C6B6F1A for ; Tue, 10 May 2011 09:05:58 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755819Ab1EIXFk (ORCPT ); Mon, 9 May 2011 19:05:40 -0400 Received: from e5.ny.us.ibm.com ([32.97.182.145]:57813 "EHLO e5.ny.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755760Ab1EIXEz (ORCPT ); Mon, 9 May 2011 19:04:55 -0400 Received: from d01relay02.pok.ibm.com (d01relay02.pok.ibm.com [9.56.227.234]) by e5.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id p49Mc1SF027845; Mon, 9 May 2011 18:38:01 -0400 Received: from d01av01.pok.ibm.com (d01av01.pok.ibm.com [9.56.224.215]) by d01relay02.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p49N42Nd321136; Mon, 9 May 2011 19:04:12 -0400 Received: from d01av01.pok.ibm.com (loopback [127.0.0.1]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p49N3wIs010061; Mon, 9 May 2011 19:04:02 -0400 Received: from elm3c44.beaverton.ibm.com (elm3c44.beaverton.ibm.com [9.47.69.44]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p49N3uNQ009914; Mon, 9 May 2011 19:03:57 -0400 Subject: [PATCH 5/7] ext4: Wait for writeback to complete while making pages writable To: Theodore Tso , Jan Kara , Alexander Viro , OGAWA Hirofumi , "Darrick J. Wong" From: "Darrick J. Wong" Cc: Jens Axboe , "Martin K. Petersen" , Jeff Layton , Dave Chinner , linux-kernel , Dave Hansen , Christoph Hellwig , linux-mm@kvack.org, Chris Mason , Joel Becker , linux-scsi , linux-fsdevel , linux-ext4@vger.kernel.org, Mingming Cao Date: Mon, 09 May 2011 16:03:56 -0700 Message-ID: <20110509230356.19566.48351.stgit@elm3c44.beaverton.ibm.com> In-Reply-To: <20110509230318.19566.66202.stgit@elm3c44.beaverton.ibm.com> References: <20110509230318.19566.66202.stgit@elm3c44.beaverton.ibm.com> User-Agent: StGit/0.15 MIME-Version: 1.0 Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org In order to stabilize pages during disk writes, ext4_page_mkwrite must wait for writeback operations to complete before making a page writable. Furthermore, the function must return locked pages, and recheck the writeback status if the page lock is ever dropped. The "someone could wander in" part of this patch was suggested by Chris Mason. Signed-off-by: Darrick J. Wong --- fs/ext4/inode.c | 24 +++++++++++++++++++----- 1 files changed, 19 insertions(+), 5 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 3db34b2..1d162a2 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5809,15 +5809,19 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) goto out_unlock; } ret = 0; - if (PageMappedToDisk(page)) - goto out_unlock; + + lock_page(page); + wait_on_page_writeback(page); + if (PageMappedToDisk(page)) { + up_read(&inode->i_alloc_sem); + return VM_FAULT_LOCKED; + } if (page->index == size >> PAGE_CACHE_SHIFT) len = size & ~PAGE_CACHE_MASK; else len = PAGE_CACHE_SIZE; - lock_page(page); /* * return if we have all the buffers mapped. This avoid * the need to call write_begin/write_end which does a @@ -5827,8 +5831,8 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (page_has_buffers(page)) { if (!walk_page_buffers(NULL, page_buffers(page), 0, len, NULL, ext4_bh_unmapped)) { - unlock_page(page); - goto out_unlock; + up_read(&inode->i_alloc_sem); + return VM_FAULT_LOCKED; } } unlock_page(page); @@ -5848,6 +5852,16 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (ret < 0) goto out_unlock; ret = 0; + + /* + * write_begin/end might have created a dirty page and someone + * could wander in and start the IO. Make sure that hasn't + * happened. + */ + lock_page(page); + wait_on_page_writeback(page); + up_read(&inode->i_alloc_sem); + return VM_FAULT_LOCKED; out_unlock: if (ret) ret = VM_FAULT_SIGBUS;