From patchwork Thu Aug 7 03:35:50 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zheng Liu X-Patchwork-Id: 377723 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 34C8D14012D for ; Thu, 7 Aug 2014 13:31:10 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756749AbaHGDbJ (ORCPT ); Wed, 6 Aug 2014 23:31:09 -0400 Received: from mail-pa0-f47.google.com ([209.85.220.47]:63784 "EHLO mail-pa0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756746AbaHGDbH (ORCPT ); Wed, 6 Aug 2014 23:31:07 -0400 Received: by mail-pa0-f47.google.com with SMTP id kx10so4575489pab.20 for ; Wed, 06 Aug 2014 20:31:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=x9djP29+jfC9RKRWDkdCaB6Whp/JaOapGkrksT4WU3U=; b=w2w2NuSJBrjKB7L2Bxb/s25f56Zdel2G5Wm0GaheENDHoiurvd8s2+YjXTU+6sPRRg 26XHXmk21HsV+uk2S1Fqgt0KwDouSRz8KppWwMu1sCdgSjB5WPFp7Nt2/3QZmWZfyaYN rZrwWAWjRsyt9jJheoKrRhyj5PMIC9hfDP1k4/Z30bRgts9wdDMlquNk+FJEa+w2NomY QN/hFrsbWjWynlZJbrdMbe0sIYbHGSTDyO4YV8SbZz1led4KZrLknrJRVqvEgjhXOiYQ tGKfY6iR1u8iWwiFYLKegIFoMPeDcjls9mW10WaeqzalCq6gJLUNg8HBJCG1moFWKuTi YLWA== X-Received: by 10.68.164.4 with SMTP id ym4mr15087564pbb.53.1407382267349; Wed, 06 Aug 2014 20:31:07 -0700 (PDT) Received: from alpha.hz.ali.com ([182.92.253.16]) by mx.google.com with ESMTPSA id ak1sm2741160pbc.58.2014.08.06.20.31.05 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 06 Aug 2014 20:31:06 -0700 (PDT) From: Zheng Liu X-Google-Original-From: Zheng Liu To: linux-ext4@vger.kernel.org Cc: "Theodore Ts'o" , Andreas Dilger , Jan Kara , Zheng Liu Subject: [PATCH v3 3/6] ext4: cache extent hole in extent status tree for ext4_da_map_blocks() Date: Thu, 7 Aug 2014 11:35:50 +0800 Message-Id: <1407382553-24256-4-git-send-email-wenqing.lz@taobao.com> X-Mailer: git-send-email 1.7.9.7 In-Reply-To: <1407382553-24256-1-git-send-email-wenqing.lz@taobao.com> References: <1407382553-24256-1-git-send-email-wenqing.lz@taobao.com> Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org From: Zheng Liu Currently extent status tree doesn't cache extent hole when a write looks up in extent tree to make sure whether a block has been allocated or not. In this case, we don't put extent hole in extent cache because later this extent might be removed and a new delayed extent might be added back. But it will cause a defect when we do a lot of writes. If we don't put extent hole in extent cache, the following writes also need to access extent tree to look at whether or not a block has been allocated. It brings a cache miss. This commit fixes this defect. Meanwhile, if an inode has no any extent, this extent hole also will be cached. Cc: "Theodore Ts'o" Cc: Andreas Dilger Cc: Jan Kara Signed-off-by: Zheng Liu --- fs/ext4/ext4.h | 4 +--- fs/ext4/extents.c | 23 +++++++++-------------- fs/ext4/inode.c | 6 ++---- include/trace/events/ext4.h | 3 +-- 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6f294d3..7df9220 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -565,10 +565,8 @@ enum { #define EXT4_GET_BLOCKS_KEEP_SIZE 0x0080 /* Do not take i_data_sem locking in ext4_map_blocks */ #define EXT4_GET_BLOCKS_NO_LOCK 0x0100 - /* Do not put hole in extent cache */ -#define EXT4_GET_BLOCKS_NO_PUT_HOLE 0x0200 /* Convert written extents to unwritten */ -#define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN 0x0400 +#define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN 0x0200 /* * The bit position of these flags must not overlap with any of the diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 76c2df3..6463d34 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2284,16 +2284,15 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, ext4_lblk_t block) { int depth = ext_depth(inode); - unsigned long len = 0; - ext4_lblk_t lblock = 0; + unsigned long len; + ext4_lblk_t lblock; struct ext4_extent *ex; ex = path[depth].p_ext; if (ex == NULL) { - /* - * there is no extent yet, so gap is [0;-] and we - * don't cache it - */ + /* there is no extent yet, so gap is [0;-] */ + lblock = 0; + len = EXT_MAX_BLOCKS; ext_debug("cache gap(whole file):"); } else if (block < le32_to_cpu(ex->ee_block)) { lblock = block; @@ -2302,9 +2301,6 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, block, le32_to_cpu(ex->ee_block), ext4_ext_get_actual_len(ex)); - if (!ext4_find_delalloc_range(inode, lblock, lblock + len - 1)) - ext4_es_insert_extent(inode, lblock, len, ~0, - EXTENT_STATUS_HOLE); } else if (block >= le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex)) { ext4_lblk_t next; @@ -2318,14 +2314,14 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, block); BUG_ON(next == lblock); len = next - lblock; - if (!ext4_find_delalloc_range(inode, lblock, lblock + len - 1)) - ext4_es_insert_extent(inode, lblock, len, ~0, - EXTENT_STATUS_HOLE); } else { BUG(); } ext_debug(" -> %u:%lu\n", lblock, len); + if (!ext4_find_delalloc_range(inode, lblock, lblock + len - 1)) + ext4_es_insert_extent(inode, lblock, len, ~0, + EXTENT_STATUS_HOLE); } /* @@ -4362,8 +4358,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, * put just found gap into cache to speed up * subsequent requests */ - if ((flags & EXT4_GET_BLOCKS_NO_PUT_HOLE) == 0) - ext4_ext_put_gap_in_cache(inode, path, map->m_lblk); + ext4_ext_put_gap_in_cache(inode, path, map->m_lblk); goto out2; } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 367a60c..d1ad9f9 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1485,11 +1485,9 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, map->m_flags |= EXT4_MAP_FROM_CLUSTER; retval = 0; } else if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) - retval = ext4_ext_map_blocks(NULL, inode, map, - EXT4_GET_BLOCKS_NO_PUT_HOLE); + retval = ext4_ext_map_blocks(NULL, inode, map, 0); else - retval = ext4_ind_map_blocks(NULL, inode, map, - EXT4_GET_BLOCKS_NO_PUT_HOLE); + retval = ext4_ind_map_blocks(NULL, inode, map, 0); add_delayed: if (retval == 0) { diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index ff4bd1b..9337d36 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h @@ -43,8 +43,7 @@ struct extent_status; { EXT4_GET_BLOCKS_METADATA_NOFAIL, "METADATA_NOFAIL" }, \ { EXT4_GET_BLOCKS_NO_NORMALIZE, "NO_NORMALIZE" }, \ { EXT4_GET_BLOCKS_KEEP_SIZE, "KEEP_SIZE" }, \ - { EXT4_GET_BLOCKS_NO_LOCK, "NO_LOCK" }, \ - { EXT4_GET_BLOCKS_NO_PUT_HOLE, "NO_PUT_HOLE" }) + { EXT4_GET_BLOCKS_NO_LOCK, "NO_LOCK" }) #define show_mflags(flags) __print_flags(flags, "", \ { EXT4_MAP_NEW, "N" }, \