From patchwork Tue Mar 1 12:28:26 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 84933 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 43F06B70EA for ; Tue, 1 Mar 2011 23:28:30 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753542Ab1CAM22 (ORCPT ); Tue, 1 Mar 2011 07:28:28 -0500 Received: from mail-qy0-f174.google.com ([209.85.216.174]:43031 "EHLO mail-qy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753181Ab1CAM21 (ORCPT ); Tue, 1 Mar 2011 07:28:27 -0500 Received: by qyk7 with SMTP id 7so3192450qyk.19 for ; Tue, 01 Mar 2011 04:28:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:date:message-id:subject:from:to:cc :content-type; bh=4YIJJ1PIIooMknb2QH9LgkXDzL6EataXlZFkiNcewv0=; b=GAdp9LKPy0KDbCU9stYBINtTWHy71WvdBj0hyHGIl541OfNfZBjXb7JPQPIp3DRxec 1JQDiFfMz6W1fVYXZxpu4ScW/qwGJn7tFHIbZIJdUYy65Qrm+u5+o6aH+bq0bMc04bwP vKvuOHqOh8Tw2lh3RJV8L8skOg47MAjRb5QpI= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:cc:content-type; b=vUIOgwrlasHsYLNVy2bSQD8XbGaoVZ3iGGpv7PPFwBk52kSieKgF300/+kc0Q8aC45 Kad/YKFVodeBxL7iHYu+4HhTdZe/+nmz9s43mIZROi8PWdjWyuCk5Vo7p649FUmoRRux 4A/SsiyWxI+dgBMgdR6hoUKsENtyngr8vMxBE= MIME-Version: 1.0 Received: by 10.224.11.18 with SMTP id r18mr5618792qar.377.1298982506895; Tue, 01 Mar 2011 04:28:26 -0800 (PST) Received: by 10.229.96.71 with HTTP; Tue, 1 Mar 2011 04:28:26 -0800 (PST) Date: Tue, 1 Mar 2011 14:28:26 +0200 Message-ID: Subject: [PATCH 2/2] ext4: handle errors in ext4_clear_blocks() From: Amir Goldstein To: Theodore Tso Cc: Ext4 Developers List Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Checking return code from ext4_journal_get_write_access() is important with snapshots, because this function invokes COW, so may return new errors, such as ENOSPC. ext4_clear_blocks() now returns < 0 for fatal errors, in which case, ext4_free_data() is aborted. Signed-off-by: Amir Goldstein --- fs/ext4/inode.c | 46 ++++++++++++++++++++++++++-------------------- 1 files changed, 26 insertions(+), 20 deletions(-) @@ -4149,6 +4148,9 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, ext4_free_blocks(handle, inode, NULL, block_to_free, count, flags); return 0; +out_err: + ext4_std_error(inode->i_sb, err); + return err; } /** @@ -4182,7 +4184,7 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, ext4_fsblk_t nr; /* Current block # */ __le32 *p; /* Pointer into inode/ind for current block */ - int err; + int err = 0; if (this_bh) { /* For indirect block */ BUFFER_TRACE(this_bh, "get_write_access"); @@ -4204,9 +4206,10 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, } else if (nr == block_to_free + count) { count++; } else { - if (ext4_clear_blocks(handle, inode, this_bh, - block_to_free, count, - block_to_free_p, p)) + err = ext4_clear_blocks(handle, inode, this_bh, + block_to_free, count, + block_to_free_p, p); + if (err) break; block_to_free = nr; block_to_free_p = p; @@ -4215,9 +4218,12 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, } } - if (count > 0) - ext4_clear_blocks(handle, inode, this_bh, block_to_free, - count, block_to_free_p, p); + if (!err && count > 0) + err = ext4_clear_blocks(handle, inode, this_bh, block_to_free, + count, block_to_free_p, p); + if (err < 0) + /* fatal error */ + return; if (this_bh) { BUFFER_TRACE(this_bh, "call ext4_handle_dirty_metadata"); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 67e7a3c..13d3952 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4096,6 +4096,9 @@ no_top: * * We release `count' blocks on disk, but (last - first) may be greater * than `count' because there can be holes in there. + * + * Return 0 on success, 1 on invalid block range + * and < 0 on fatal error. */ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh, @@ -4122,25 +4125,21 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, if (bh) { BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); err = ext4_handle_dirty_metadata(handle, inode, bh); - if (unlikely(err)) { - ext4_std_error(inode->i_sb, err); - return 1; - } + if (unlikely(err)) + goto out_err; } err = ext4_mark_inode_dirty(handle, inode); - if (unlikely(err)) { - ext4_std_error(inode->i_sb, err); - return 1; - } + if (unlikely(err)) + goto out_err; err = ext4_truncate_restart_trans(handle, inode, blocks_for_truncate(inode)); - if (unlikely(err)) { - ext4_std_error(inode->i_sb, err); - return 1; - } + if (unlikely(err)) + goto out_err; if (bh) { BUFFER_TRACE(bh, "retaking write access"); - ext4_journal_get_write_access(handle, bh); + err = ext4_journal_get_write_access(handle, bh); + if (unlikely(err)) + goto out_err; } }