From patchwork Fri Sep 28 15:44:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Monakhov X-Patchwork-Id: 187816 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 1EC622C00CE for ; Sat, 29 Sep 2012 01:44:36 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758076Ab2I1Pob (ORCPT ); Fri, 28 Sep 2012 11:44:31 -0400 Received: from mail-la0-f46.google.com ([209.85.215.46]:61221 "EHLO mail-la0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758258Ab2I1PoW (ORCPT ); Fri, 28 Sep 2012 11:44:22 -0400 Received: by mail-la0-f46.google.com with SMTP id h6so1127961lag.19 for ; Fri, 28 Sep 2012 08:44:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=faEYHyA2e0tCq8AVnzR3X+CuynLORzsj5a4B6Z3K1qs=; b=JfvYAsnHgX8IcI3ZtHBOs0u2wtXytZ7UnvdGqidkggYjNuRlSRx1EbWAQ/4Ptpbn9R f9GhAOiNH1IqxWmnlX8ZPOcWsQB+2kxxm0vE/Q9V+z7dOHk8ad+hs0M2PTD06JFMSjEf QznI8EEjzTsFPPjFrHRMDePii9hoI8ns0XeoCV9IjFKlkDnM/1OPoXLdsea9WraZannt 7gv9ljle0LqUVZMSvtDG5jk20+FBJzO1/ynKTaaNV/bMhkWCXTbnMh8jxFzC31cFH6CQ 562JBICOeiV1xgOfvS9ArzpfAHXLQh/m6ngQ6H+ZsKBk2pOH3xJxe0j0I+OUtISlikcq Fn0g== Received: by 10.152.48.102 with SMTP id k6mr6178459lan.12.1348847061941; Fri, 28 Sep 2012 08:44:21 -0700 (PDT) Received: from smtp.gmail.com (swsoft-msk-nat.sw.ru. [195.214.232.10]) by mx.google.com with ESMTPS id pi16sm2597301lab.7.2012.09.28.08.44.21 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 28 Sep 2012 08:44:21 -0700 (PDT) From: Dmitry Monakhov To: linux-ext4@vger.kernel.org Cc: tytso@mit.edu, jack@suse.cz, lczerner@redhat.com, Dmitry Monakhov Subject: [PATCH 03/11] ext4: fix unwritten counter leakage Date: Fri, 28 Sep 2012 19:44:03 +0400 Message-Id: <1348847051-6746-4-git-send-email-dmonakhov@openvz.org> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1348847051-6746-1-git-send-email-dmonakhov@openvz.org> References: <1348847051-6746-1-git-send-email-dmonakhov@openvz.org> Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org ext4_set_io_unwritten_flag() will increment i_unwritten counter, so once we mark end_io with EXT4_END_IO_UNWRITTEN we have to revert it back on error path. - add missed error checks to prevent counter leakage - ext4_end_io_nolock() will clear EXT4_END_IO_UNWRITTEN flag to signal that conversion finished. - add BUG_ON to ext4_free_end_io() to prevent similar leakage in future. Visible effect of this bug is that unaligned aio_stress may deadlock Signed-off-by: Dmitry Monakhov Reviewed-by: Jan Kara --- fs/ext4/extents.c | 21 ++++++++++++++------- fs/ext4/page-io.c | 6 +++++- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index e9549f9..69e2d13 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3545,6 +3545,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { ret = ext4_split_unwritten_extents(handle, inode, map, path, flags); + if (ret <= 0) + goto out; /* * Flag the inode(non aio case) or end_io struct (aio case) * that this IO needs to conversion to written when IO is @@ -3790,6 +3792,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, struct ext4_allocation_request ar; ext4_io_end_t *io = ext4_inode_aio(inode); ext4_lblk_t cluster_offset; + int set_unwritten = 0; ext_debug("blocks %u/%u requested for inode %lu\n", map->m_lblk, map->m_len, inode->i_ino); @@ -4012,13 +4015,8 @@ got_allocated_blocks: * For non asycn direct IO case, flag the inode state * that we need to perform conversion when IO is done. */ - if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { - if (io) - ext4_set_io_unwritten_flag(inode, io); - else - ext4_set_inode_state(inode, - EXT4_STATE_DIO_UNWRITTEN); - } + if ((flags & EXT4_GET_BLOCKS_PRE_IO)) + set_unwritten = 1; if (ext4_should_dioread_nolock(inode)) map->m_flags |= EXT4_MAP_UNINIT; } @@ -4030,6 +4028,15 @@ got_allocated_blocks: if (!err) err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); + + if (!err && set_unwritten) { + if (io) + ext4_set_io_unwritten_flag(inode, io); + else + ext4_set_inode_state(inode, + EXT4_STATE_DIO_UNWRITTEN); + } + if (err && free_on_err) { int fb_flags = flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE ? EXT4_FREE_BLOCKS_NO_QUOT_UPDATE : 0; diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index de77e31..9970022 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -71,6 +71,8 @@ void ext4_free_io_end(ext4_io_end_t *io) int i; BUG_ON(!io); + BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN); + if (io->page) put_page(io->page); for (i = 0; i < io->num_io_pages; i++) @@ -94,6 +96,8 @@ int ext4_end_io_nolock(ext4_io_end_t *io) ssize_t size = io->size; int ret = 0; + BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); + ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," "list->prev 0x%p\n", io, inode->i_ino, io->list.next, io->list.prev); @@ -106,7 +110,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io) "(inode %lu, offset %llu, size %zd, error %d)", inode->i_ino, offset, size, ret); } - + io->flag &= ~EXT4_IO_END_UNWRITTEN; if (io->iocb) aio_complete(io->iocb, io->result, 0);