From patchwork Tue Dec 4 11:32:32 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Forrest Liu X-Patchwork-Id: 203612 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 72A472C008C for ; Tue, 4 Dec 2012 22:32:56 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751701Ab2LDLcw (ORCPT ); Tue, 4 Dec 2012 06:32:52 -0500 Received: from mail-ie0-f174.google.com ([209.85.223.174]:33191 "EHLO mail-ie0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751613Ab2LDLcv (ORCPT ); Tue, 4 Dec 2012 06:32:51 -0500 Received: by mail-ie0-f174.google.com with SMTP id c11so5928740ieb.19 for ; Tue, 04 Dec 2012 03:32:51 -0800 (PST) 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; bh=l4AwmaSWSuEf3pC32eYwshBZg7hx2ZKm47RyDNGavUc=; b=n/vuVNviH0o2/6jMnPgaiDVOssWnRXWD4yAI9X2UNTjE1a4EUlxjHV9T/YWwOoLKM8 XOEsP4VqDKjLkbKc0WCsp9u6uj094Vjf8/Vkjit5l0u9jiMiWXGeo4+1O9sDLfpbhxId VOatg3DPSEHbaTEpngpo5efmqGdqgDquQ9h6Od7Mg0Jw5tF5ZAtaA82IVCOqAY8JjfCN 5hqiMFbWj45nXRAO9oByhBT+3G1NFMpG5t7EWf6cGofGBoW+rqakyXpTw8xRrcZHZZMW 5OlserMvxi2d0vMHAiSheAseZmMrpgM50i6Hkx9VIk/GA1rYuwqn+GS1lnD+jo++DE8w Pr4g== Received: by 10.50.213.7 with SMTP id no7mr2309549igc.18.1354620771406; Tue, 04 Dec 2012 03:32:51 -0800 (PST) Received: from localhost.localdomain (118-163-30-16.HINET-IP.hinet.net. [118.163.30.16]) by mx.google.com with ESMTPS id hg2sm9623297igc.3.2012.12.04.03.32.46 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 04 Dec 2012 03:32:50 -0800 (PST) From: Forrest Liu To: Theodore Ts'o Cc: =?UTF-8?q?linux-ext4=C2=A0?= , Forrest Liu Subject: [PATCH] ext4: fix extent tree corruption that incurred by hole punch Date: Tue, 4 Dec 2012 19:32:32 +0800 Message-Id: <1354620752-7231-1-git-send-email-forrestl@synology.com> X-Mailer: git-send-email 1.7.5.4 Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org When depth of extent tree is greater than 1, extent indexes didn't update correctly in ext4_ext_rm_idx Signed-off-by: Forrest Liu --- fs/ext4/extents.c | 24 ++++++++++++++++++++---- 1 files changed, 20 insertions(+), 4 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index d3dd618..b10b8c0 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2190,13 +2190,15 @@ errout: * removes index from the index block. */ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, - struct ext4_ext_path *path) + struct ext4_ext_path *path, int depth) { int err; ext4_fsblk_t leaf; + __le32 border; /* free index block */ - path--; + depth--; + path = path + depth; leaf = ext4_idx_pblock(path->p_idx); if (unlikely(path->p_hdr->eh_entries == 0)) { EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0"); @@ -2221,6 +2223,20 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, ext4_free_blocks(handle, inode, NULL, leaf, 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); + + border = path->p_idx->ei_block; + while (--depth >= 0) { + if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr)) + break; + path--; + err = ext4_ext_get_access(handle, inode, path); + if (err) + break; + path->p_idx->ei_block = border; + err = ext4_ext_dirty(handle, inode, path); + if (err) + break; + } return err; } @@ -2557,7 +2573,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, /* if this leaf is free, then we should * remove it from index block above */ if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) - err = ext4_ext_rm_idx(handle, inode, path + depth); + err = ext4_ext_rm_idx(handle, inode, path, depth); out: return err; @@ -2760,7 +2776,7 @@ again: /* index is empty, remove it; * handle must be already prepared by the * truncatei_leaf() */ - err = ext4_ext_rm_idx(handle, inode, path + i); + err = ext4_ext_rm_idx(handle, inode, path, i); } /* root level has p_bh == NULL, brelse() eats this */ brelse(path[i].p_bh);