From patchwork Fri Oct 26 13:23:44 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zheng Liu X-Patchwork-Id: 194475 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 E93502C009B for ; Sat, 27 Oct 2012 00:13:13 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758647Ab2JZNNM (ORCPT ); Fri, 26 Oct 2012 09:13:12 -0400 Received: from mail-da0-f46.google.com ([209.85.210.46]:34022 "EHLO mail-da0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758550Ab2JZNNL (ORCPT ); Fri, 26 Oct 2012 09:13:11 -0400 Received: by mail-da0-f46.google.com with SMTP id n41so1300913dak.19 for ; Fri, 26 Oct 2012 06:13:10 -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=UBQ0+wUTJ3m7Y2tqOdqfesAHsFotZxDOd+OrKyobJJs=; b=MxoRyfdyRCeY6KXQ2op1qDWT+zTwKbhaXd3pWabdoHa7odRlxrJAx7Gs4GvCE3BYV7 8G3NZ7dmxyVGeXwmsHY8dUXrT4u4xwmVIT/vr/7gCkrcdQ+/97uLH/gZVbXs0ZtCN+Um JVSotrJQsx6WqmfW0nvieUNK44vSfMGa2eY73poyPZNe939zaDg4Lx2vTrtrCJsySvmx /ZJxPsTIU2klUrcdO5O6zEgaDfNd/vqo2Oyk9xCpxlE7tYfgU3DfRnP6YdOhbCFELl7L 1BURn9Ru2Yqa0ANhCl9gPYpsNPhGBHbYyXrfoaTyJldd4M/+CrqFe+TFrLct6J34r6ec ZV4Q== Received: by 10.68.218.132 with SMTP id pg4mr70061732pbc.100.1351257190819; Fri, 26 Oct 2012 06:13:10 -0700 (PDT) Received: from lz-desktop.hz.ali.com ([182.92.247.2]) by mx.google.com with ESMTPS id a10sm1000164paw.17.2012.10.26.06.13.07 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 26 Oct 2012 06:13:10 -0700 (PDT) From: Zheng Liu To: linux-ext4@vger.kernel.org, jeff.liu@oracle.com Cc: tytso@mit.edu, hughd@google.com, xiaoqiangnk@gmail.com, achender@linux.vnet.ibm.com, lczerner@redhat.com, Zheng Liu Subject: [PATCH 7/8 v3] ext4: reimplement fiemap on extent status tree Date: Fri, 26 Oct 2012 21:23:44 +0800 Message-Id: <1351257825-3701-8-git-send-email-wenqing.lz@taobao.com> X-Mailer: git-send-email 1.7.12.rc2.18.g61b472e In-Reply-To: <1351257825-3701-1-git-send-email-wenqing.lz@taobao.com> References: <1351257825-3701-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. CC: "Theodore Ts'o" Signed-off-by: Yongqiang Yang Signed-off-by: Allison Henderson Signed-off-by: Zheng Liu --- fs/ext4/extents.c | 184 +++++++----------------------------------------------- 1 file changed, 21 insertions(+), 163 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index d6da3a8..a72197b 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4499,193 +4499,51 @@ 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; + next_del = ext4_es_find_extent(inode, &es); + 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; + 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; } -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; - } - - 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)