lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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

Powered by Openwall GNU/*/Linux Powered by OpenVZ