[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAGBYx2bOO8ERru_i6dViVC0iOfkjJf4epT_R1WCoHCKt2_J_+w@mail.gmail.com>
Date: Fri, 30 Sep 2011 08:54:16 +0800
From: Yongqiang Yang <xiaoqiangnk@...il.com>
To: Jeff liu <jeff.liu@...cle.com>
Cc: linux-ext4@...r.kernel.org, jack@...e.cz,
achender@...ux.vnet.ibm.com, adityakali@...gle.com
Subject: Re: [RFC PATCH V2 6/6] ext4: reimplement fiemap on delayed extent tree
On Thu, Sep 29, 2011 at 11:28 PM, Jeff liu <jeff.liu@...cle.com> wrote:
> Hi Yongqiang,
>
>> This patch reimplements fiemap on delayed extent tree.
>>
>> Signed-off-by: Yongqiang Yang <xiaoqiangnk@...il.com>
>> ---
>> 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 bdbb984..c2ae125 100644
>> --- a/fs/ext4/extents.c
>> +++ b/fs/ext4/extents.c
>> @@ -3909,193 +3909,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 delayed_extent de;
>> __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;
>> + de.start = newex->ec_block;
>> + down_read(&EXT4_I(inode)->i_data_sem);
>> + next_del = ext4_de_find_extent(inode, &de);
>> + 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 (de.len == 0)
>> + /* A hole found. */
>> + return EXT_CONTINUE;
>> +
>> + if (de.start > newex->ec_block) {
>> + /* A hole found. */
>> + newex->ec_len = min(de.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 = de.start + de.len - newex->ec_block;
>> }
>
> How about to isolate "get delayed extent info" as above to an inline function?
> We can gather them via newex->xxx then, so other features need to iterate through file special range like SEEK_HOLE/DATA could be benefit
> from it in their callback functions.
Sure.
Thx!
Yongqiang.
>
>
> Thanks,
> -Jeff
>>
>> - 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)
>> --
>> 1.7.5.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
>> the body of a message to majordomo@...r.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
--
Best Wishes
Yongqiang Yang
Powered by blists - more mailing lists