From patchwork Sun Jul 22 07:46:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zheng Liu X-Patchwork-Id: 172486 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 E095D2C0143 for ; Sun, 22 Jul 2012 17:38:57 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751254Ab2GVHiy (ORCPT ); Sun, 22 Jul 2012 03:38:54 -0400 Received: from mail-pb0-f46.google.com ([209.85.160.46]:36677 "EHLO mail-pb0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751164Ab2GVHiT (ORCPT ); Sun, 22 Jul 2012 03:38:19 -0400 Received: by mail-pb0-f46.google.com with SMTP id rp8so8900821pbb.19 for ; Sun, 22 Jul 2012 00:38:19 -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:x-mailer:in-reply-to:references; bh=5anEEKax9f43zLqjs+WnhO+Io7pugUH8+Dm9DMfOizM=; b=Vq9YfTyUTllU5upa55DifLd58r48G8bPlqgd0kBQfxiM5CptMDI+hvIvgPu4s3uPev YfoJbI6dZ2SXQlS73frQG4M+7pQ6pTqgWwQk6tCQNHgmhGsdB+wtVHlTvse9s/DWzlJf QgIgWpXWaw5TD3+KDkF+hePTZtoe+1R/9dnbFd7ilD41scXIxr078YztqTaEr4m+/qmp D541i3q58iEKR9D2DKlySZIfD6/7MBmfu8pHk5MAt+wx7xnpQj23qBMuZlaOJnQF4Vy1 4TuDmp00oBLoLCJHSMZ7cFwa8CFqPelBRex3hj9nLposnP8tNSljvl6VZQFBnEdlS5GY HQiA== Received: by 10.68.203.7 with SMTP id km7mr26214413pbc.7.1342942699037; Sun, 22 Jul 2012 00:38:19 -0700 (PDT) Received: from localhost.localdomain ([182.92.247.2]) by mx.google.com with ESMTPS id ru10sm7481626pbc.50.2012.07.22.00.38.16 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 22 Jul 2012 00:38:18 -0700 (PDT) From: Zheng Liu To: linux-ext4@vger.kernel.org, linux-fsdevel@vger.kernel.org Cc: xiaoqiangnk@gmail.com, achender@linux.vnet.ibm.com, wenqing.lz@taobao.com Subject: [RFC][PATCH 5/10 v1] ext4: reimplement fiemap on extent status tree Date: Sun, 22 Jul 2012 15:46:03 +0800 Message-Id: <1342943167-12153-7-git-send-email-wenqing.lz@taobao.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1342943167-12153-1-git-send-email-wenqing.lz@taobao.com> References: <1342943167-12153-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 This patch reimplements fiemap on extent status tree. Signed-off-by: Yongqiang Yang Signed-off-by: Allison Henderson Signed-off-by: Zheng Liu --- fs/ext4/extents.c | 186 +++++++---------------------------------------------- 1 files changed, 23 insertions(+), 163 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 0747917..06ca2a3 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4501,193 +4501,53 @@ static int ext4_ext_fiemap_cb(struct inode *inode, ext4_lblk_t next, struct ext4_ext_cache *newex, struct ext4_extent *ex, void *data) { + struct extent_status es; __u64 logical; __u64 physical; __u64 length; __u32 flags = 0; + ext4_lblk_t next_del; int ret = 0; struct fiemap_extent_info *fieinfo = data; unsigned char blksize_bits; - blksize_bits = inode->i_sb->s_blocksize_bits; - logical = (__u64)newex->ec_block << blksize_bits; + es.start = newex->ec_block; + down_read(&EXT4_I(inode)->i_data_sem); + next_del = ext4_es_find_extent(inode, &es); + up_read(&EXT4_I(inode)->i_data_sem); + next = min(next_del, next); if (newex->ec_start == 0) { /* * No extent in extent-tree contains block @newex->ec_start, * then the block may stay in 1)a hole or 2)delayed-extent. - * - * Holes or delayed-extents are processed as follows. - * 1. lookup dirty pages with specified range in pagecache. - * If no page is got, then there is no delayed-extent and - * return with EXT_CONTINUE. - * 2. find the 1st mapped buffer, - * 3. check if the mapped buffer is both in the request range - * and a delayed buffer. If not, there is no delayed-extent, - * then return. - * 4. a delayed-extent is found, the extent will be collected. */ - ext4_lblk_t end = 0; - pgoff_t last_offset; - pgoff_t offset; - pgoff_t index; - pgoff_t start_index = 0; - struct page **pages = NULL; - struct buffer_head *bh = NULL; - struct buffer_head *head = NULL; - unsigned int nr_pages = PAGE_SIZE / sizeof(struct page *); - - pages = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (pages == NULL) - return -ENOMEM; - - offset = logical >> PAGE_SHIFT; -repeat: - last_offset = offset; - head = NULL; - ret = find_get_pages_tag(inode->i_mapping, &offset, - PAGECACHE_TAG_DIRTY, nr_pages, pages); - - if (!(flags & FIEMAP_EXTENT_DELALLOC)) { - /* First time, try to find a mapped buffer. */ - if (ret == 0) { -out: - for (index = 0; index < ret; index++) - page_cache_release(pages[index]); - /* just a hole. */ - kfree(pages); - return EXT_CONTINUE; - } - index = 0; - -next_page: - /* Try to find the 1st mapped buffer. */ - end = ((__u64)pages[index]->index << PAGE_SHIFT) >> - blksize_bits; - if (!page_has_buffers(pages[index])) - goto out; - head = page_buffers(pages[index]); - if (!head) - goto out; - - index++; - bh = head; - do { - if (end >= newex->ec_block + - newex->ec_len) - /* The buffer is out of - * the request range. - */ - goto out; - - if (buffer_mapped(bh) && - end >= newex->ec_block) { - start_index = index - 1; - /* get the 1st mapped buffer. */ - goto found_mapped_buffer; - } - - bh = bh->b_this_page; - end++; - } while (bh != head); - - /* No mapped buffer in the range found in this page, - * We need to look up next page. - */ - if (index >= ret) { - /* There is no page left, but we need to limit - * newex->ec_len. - */ - newex->ec_len = end - newex->ec_block; - goto out; - } - goto next_page; - } else { - /*Find contiguous delayed buffers. */ - if (ret > 0 && pages[0]->index == last_offset) - head = page_buffers(pages[0]); - bh = head; - index = 1; - start_index = 0; - } - -found_mapped_buffer: - if (bh != NULL && buffer_delay(bh)) { - /* 1st or contiguous delayed buffer found. */ - if (!(flags & FIEMAP_EXTENT_DELALLOC)) { - /* - * 1st delayed buffer found, record - * the start of extent. - */ - flags |= FIEMAP_EXTENT_DELALLOC; - newex->ec_block = end; - logical = (__u64)end << blksize_bits; - } - /* Find contiguous delayed buffers. */ - do { - if (!buffer_delay(bh)) - goto found_delayed_extent; - bh = bh->b_this_page; - end++; - } while (bh != head); - - for (; index < ret; index++) { - if (!page_has_buffers(pages[index])) { - bh = NULL; - break; - } - head = page_buffers(pages[index]); - if (!head) { - bh = NULL; - break; - } - - if (pages[index]->index != - pages[start_index]->index + index - - start_index) { - /* Blocks are not contiguous. */ - bh = NULL; - break; - } - bh = head; - do { - if (!buffer_delay(bh)) - /* Delayed-extent ends. */ - goto found_delayed_extent; - bh = bh->b_this_page; - end++; - } while (bh != head); - } - } else if (!(flags & FIEMAP_EXTENT_DELALLOC)) - /* a hole found. */ - goto out; - -found_delayed_extent: - newex->ec_len = min(end - newex->ec_block, - (ext4_lblk_t)EXT_INIT_MAX_LEN); - if (ret == nr_pages && bh != NULL && - newex->ec_len < EXT_INIT_MAX_LEN && - buffer_delay(bh)) { - /* Have not collected an extent and continue. */ - for (index = 0; index < ret; index++) - page_cache_release(pages[index]); - goto repeat; + if (es.len == 0) + /* A hole found. */ + return EXT_CONTINUE; + + if (es.start > newex->ec_block) { + /* A hole found. */ + newex->ec_len = min(es.start - newex->ec_block, + newex->ec_len); + return EXT_CONTINUE; } - for (index = 0; index < ret; index++) - page_cache_release(pages[index]); - kfree(pages); + flags |= FIEMAP_EXTENT_DELALLOC; + newex->ec_len = es.start + es.len - newex->ec_block; } - physical = (__u64)newex->ec_start << blksize_bits; - length = (__u64)newex->ec_len << blksize_bits; - if (ex && ext4_ext_is_uninitialized(ex)) flags |= FIEMAP_EXTENT_UNWRITTEN; if (next == EXT_MAX_BLOCKS) flags |= FIEMAP_EXTENT_LAST; + blksize_bits = inode->i_sb->s_blocksize_bits; + logical = (__u64)newex->ec_block << blksize_bits; + physical = (__u64)newex->ec_start << blksize_bits; + length = (__u64)newex->ec_len << blksize_bits; + ret = fiemap_fill_next_extent(fieinfo, logical, physical, length, flags); if (ret < 0)