[Ocfs2-devel] [PATCH 3/3] du-enhancement: show the shared extents per file and the footprint v2

Tao Ma tao.ma at oracle.com
Wed Mar 3 23:39:33 PST 2010


Jie Liu wrote:
> this patch add fiemap feature support in du, du show the shared extents size in parens per file
> as well as the footprint for each request with either '--shared-size' or '-E' option.
>
> the footprint which is total minus the sum total of all extents in the rbtree
> that have ei_shared_count > 0.
>
> Signed-off-by: Jie Liu <jeff.liu at oracle.com>
> ---
>  coreutils-6.9/src/du.c |  444 +++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 437 insertions(+), 7 deletions(-)
>
> diff --git a/coreutils-6.9/src/du.c b/coreutils-6.9/src/du.c
> index 206d318..3adc3a8 100644
> --- a/coreutils-6.9/src/du.c
> +++ b/coreutils-6.9/src/du.c
> +/* Insert new extent based on the new parent.  */
> +
> +static void
> +insert_new_extent_info (struct rb_node *parent,
> +                        uint64_t fe_physical,
> +                        uint64_t fe_length,
> +                        size_t extent_shared_count)
> +{
> +  struct rb_node **p = parent ? &parent : &((&fe_root)->rb_node);
> +  struct rb_node *pp = NULL;
> +  struct extent_info *this = NULL;
> +  struct extent_info *ei;
> +
> +  while (*p)
> +    {
> +      pp = *p;
> +      this = rb_entry (*p, struct extent_info, ei_node);
> +
> +      if (this->ei_physical > fe_physical)
> +        p = &(*p)->rb_left;
> +      else if (this->ei_physical < fe_physical)
> +	p = &(*p)->rb_right;
> +      else
> +	return;
>   
I am just curious in your code the last "else" should never happen? If 
yes, maybe if we meet with this, it means a bug in the code.
So better assert here?
> +    }
> +
> +/* Find the left-most position to insert.  */
> +
> +static struct rb_node *
> +lookup_leftmost_extent_info (uint64_t fe_physical)
> +{
> +  struct rb_node **p = &((&fe_root)->rb_node);
> +  struct rb_node *parent;
> +  struct extent_info *this;
> +
> +  while (*p)
> +    {
> +      parent = *p;
> +      this = rb_entry (*p, struct extent_info, ei_node);
> +
> +      if (this->ei_physical > fe_physical)
> +       p = &(*p)->rb_left;
> +      else if (this->ei_physical < fe_physical)
> +	p = &(*p)->rb_right;
> +      else
> +	break;
> +    }
> +
> +  return parent;
>   
If the rb-tree is empty, the parent is uninitialized. So please set 
parent to NULL in the declaration.
> +}
> +
> +/* Split the new extent into mutiple items if there is overlap
> +   with the search returned, insert each item or increase the
> +   existed items shared count for the shared part.  */
> +
> +static void
> +split_extent (uint64_t extent_physical_offset,
> +              uint64_t extent_length)
> +{
> +  struct rb_node *parent = NULL;
> +  struct rb_node *prev_parent = NULL;
> +  struct extent_info *this;
> +  uint64_t pb_start = extent_physical_offset;
> +  uint64_t ext_len = extent_length;
> +  uint64_t new_pb_start;
> +  uint64_t new_ext_len;
> +  uint64_t old_ext_len;
> +  size_t ext_shared_count = 0;
> +
> +  parent = lookup_leftmost_extent_info (pb_start);
> +
>   
> +      /* The new extent physical offset if greater than the search returned.
> +         there are 3 scenarios need to check against the old one which shown
> +	 as the following sketch.
> +         |-----------| old
> +           |----| new1
> +           |-----------| new2
> +           |---------------| new3.  */
> +      if (pb_start < this->ei_physical + this->ei_length)
> +        {
> +	  old_ext_len = this->ei_physical + this->ei_length - pb_start;
> +	  new_ext_len = MIN (ext_len, old_ext_len);
> +
> +          ext_shared_count = this->ei_shared_count;
> +
> +          /* The new extent overlapped with the old one, as a result, we
> +	     need to increase its shared count before inserting.  */
> +          ext_shared_count++;
> +	  insert_new_extent_info (parent, pb_start, new_ext_len, ext_shared_count);
> +
> +          /* Decrease the search returned extent size and keep it on the tree.  */
> +          this->ei_length = pb_start - this->ei_physical;
> +
> +	  pb_start += new_ext_len;
> +	  ext_len -= new_ext_len;
>   
We also need prev_parent = parent here?
> +          parent = rb_next (parent);
> +          continue;
> +        }
> +
> +      prev_parent = parent;
> +      parent = rb_next (parent);
>   
btw, in the above 3 cases, you always call "continue", so we have no 
chance to arrive here actually.
> +    }
> +}
> +
> +/* This function is called once for every file system object that fts
> +   encounters, get its extent mapping info for the proceeding extent
> +   spliting operation.  */
> +
> +static void
> +process_extent(int cwd_fd, char const *file,
> +               char const *file_full_name)
> +{
> +  char buf[4096] = "";
> +  struct fiemap *fiemap = (struct fiemap *)buf;
> +  struct fiemap_extent *fm_ext = &fiemap->fm_extents[0];
> +  uint32_t count = (sizeof (buf) - sizeof (*fiemap)) /
> +               sizeof (struct fiemap_extent);
> +  int last = 0;
> +
> +  int fd = openat (cwd_fd, file, O_RDONLY);
> +  if (fd < 0)
> +    {
> +      fd = open (file_full_name, O_RDONLY);
> +      if (fd < 0)
> +        {
> +          error(0, errno, _("cannot open %s"), quote (file_full_name));
> +          return;
> +	}
> +    }
> +
> +  memset (fiemap, 0, sizeof (*fiemap));
> +
> +  do {
> +    fiemap->fm_length = ~0ULL;
> +    fiemap->fm_flags = fiemap_bits_flags;
> +    fiemap->fm_extent_count = count;
> +
> +    if (ioctl (fd, FS_IOC_FIEMAP, (unsigned long) fiemap) < 0)
> +      {
> +        if (errno == EBADR)
> +            error (0, errno, _("%s FIEMAP failed with unsupported flags %x\n"),
> +                                quote (file_full_name), fiemap->fm_flags);
> +
> +        error(0, errno, _("%s extent mapping failed"), quote (file_full_name));
> +        goto close_file;
> +      }
> +
> +    /* If 0 extents are returned, then more ioctls
> +       are not needed.  */
> +    if (fiemap->fm_mapped_extents == 0)
> +      goto close_file;
> +
> +    uint64_t ext_phy_offset;
> +    uint64_t ext_len;
> +    size_t i;
>   
better move these declaration above.
> +    for (i = 0; i < fiemap->fm_mapped_extents; i++)
> +      {
> +        ext_phy_offset = fm_ext[i].fe_physical;
> +	ext_len = fm_ext[i].fe_length;
> +
> +        /* Skip inline file which its data mixed with metadata.  */
> +        if (fm_ext[i].fe_flags & FIEMAP_EXTENT_DATA_INLINE)
> +	  {
> +            if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST)
> +              {
> +                last = 1;
> +                break;
> +	      }
> +	    continue;
> +	  }
> +
> +        /* Increase the shared extents size per file.  */
> +        if (fm_ext[i].fe_flags & FIEMAP_EXTENT_SHARED)
> +          file_shared_extents += fm_ext[i].fe_length;
> +
> +        split_extent (ext_phy_offset, ext_len);
> +
> +        if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST)
> +          last = 1;
> +
> +        fiemap->fm_start = (fm_ext[i-1].fe_logical + fm_ext[i-1].fe_length);
>   
I am just curious you start from i=0, so how could fm_ext[-1] work? Or I 
miss something here?
> +      }
> +    } while (last == 0);
> +
>   
Regards,
Tao




More information about the Ocfs2-devel mailing list