From patchwork Mon Jul 15 04:11:19 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Theodore Ts'o X-Patchwork-Id: 258945 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 E661E2C017B for ; Mon, 15 Jul 2013 14:11:23 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751352Ab3GOELW (ORCPT ); Mon, 15 Jul 2013 00:11:22 -0400 Received: from li9-11.members.linode.com ([67.18.176.11]:37812 "EHLO imap.thunk.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751144Ab3GOELV (ORCPT ); Mon, 15 Jul 2013 00:11:21 -0400 Received: from root (helo=closure.thunk.org) by imap.thunk.org with local-esmtp (Exim 4.80) (envelope-from ) id 1UyaEa-00067G-I4; Mon, 15 Jul 2013 04:18:00 +0000 Received: by closure.thunk.org (Postfix, from userid 15806) id 92D7358053C; Mon, 15 Jul 2013 00:11:19 -0400 (EDT) From: Theodore Ts'o To: Ext4 Developers List Cc: Theodore Ts'o , stable@vger.kernel.org Subject: [PATCH] ext4: block direct I/O writes during ext4_truncate Date: Mon, 15 Jul 2013 00:11:19 -0400 Message-Id: <1373861479-15136-1-git-send-email-tytso@mit.edu> X-Mailer: git-send-email 1.7.12.rc0.22.gcdd159b X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: tytso@thunk.org X-SA-Exim-Scanned: No (on imap.thunk.org); SAEximRunCond expanded to false Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Just as in ext4_punch_hole() it is important that we block DIO writes while the truncate is proceeding, since during the overwriting DIO write, we drop i_mutex, which means a truncate could start while the Direct I/O operation is still in progress. Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/inode.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 98b9bff..3c5edf2 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3659,12 +3659,16 @@ void ext4_truncate(struct inode *inode) if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC)) ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE); + /* Wait all existing dio workers, newcomers will block on i_mutex */ + ext4_inode_block_unlocked_dio(inode); + inode_dio_wait(inode); + if (ext4_has_inline_data(inode)) { int has_inline = 1; ext4_inline_data_truncate(inode, &has_inline); if (has_inline) - return; + goto out_resume; } if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) @@ -3675,7 +3679,7 @@ void ext4_truncate(struct inode *inode) handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); if (IS_ERR(handle)) { ext4_std_error(inode->i_sb, PTR_ERR(handle)); - return; + goto out_resume; } if (inode->i_size & (inode->i_sb->s_blocksize - 1)) @@ -3722,6 +3726,8 @@ out_stop: ext4_mark_inode_dirty(handle, inode); ext4_journal_stop(handle); +out_resume: + ext4_inode_resume_unlocked_dio(inode); trace_ext4_truncate_exit(inode); }