On Wed, August 08, 2012 at 20:55 (+0200), Mark Fasheh wrote:
> The iterate_irefs in backref.c is used to build path components from inode
> refs. This patch adds code to iterate extended refs as well.
> 
> I had modify the callback function signature to abstract out some of the
> differences between ref structures. iref_to_path() also needed similar
> changes.
> 
> Signed-off-by: Mark Fasheh <[email protected]>
> ---
>  fs/btrfs/backref.c |  134 
> +++++++++++++++++++++++++++++++++++++++++++---------
>  fs/btrfs/backref.h |    2 -
>  2 files changed, 112 insertions(+), 24 deletions(-)
> 
> diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
> index 658e09c..4a01f7c 100644
> --- a/fs/btrfs/backref.c
> +++ b/fs/btrfs/backref.c
> @@ -1194,11 +1194,10 @@ int btrfs_find_one_extref(struct btrfs_root *root, 
> u64 inode_objectid,
>   * value will be smaller than dest. callers must check this!
>   */
>  static char *iref_to_path(struct btrfs_root *fs_root, struct btrfs_path 
> *path,
> -                             struct btrfs_inode_ref *iref,
> -                             struct extent_buffer *eb_in, u64 parent,
> -                             char *dest, u32 size)
> +                       u32 name_len, unsigned long name_off,
> +                       struct extent_buffer *eb_in, u64 parent,
> +                       char *dest, u32 size)
>  {
> -     u32 len;
>       int slot;
>       u64 next_inum;
>       int ret;
> @@ -1206,17 +1205,17 @@ static char *iref_to_path(struct btrfs_root *fs_root, 
> struct btrfs_path *path,
>       struct extent_buffer *eb = eb_in;
>       struct btrfs_key found_key;
>       int leave_spinning = path->leave_spinning;
> +     struct btrfs_inode_ref *iref;
>  
>       if (bytes_left >= 0)
>               dest[bytes_left] = '\0';
>  
>       path->leave_spinning = 1;
>       while (1) {
> -             len = btrfs_inode_ref_name_len(eb, iref);
> -             bytes_left -= len;
> +             bytes_left -= name_len;
>               if (bytes_left >= 0)
>                       read_extent_buffer(eb, dest + bytes_left,
> -                                             (unsigned long)(iref + 1), len);
> +                                        name_off, name_len);
>               if (eb != eb_in) {
>                       btrfs_tree_read_unlock_blocking(eb);
>                       free_extent_buffer(eb);
> @@ -1226,6 +1225,7 @@ static char *iref_to_path(struct btrfs_root *fs_root, 
> struct btrfs_path *path,
>                       ret = -ENOENT;
>               if (ret)
>                       break;
> +
>               next_inum = found_key.offset;
>  
>               /* regular exit ahead */
> @@ -1241,8 +1241,11 @@ static char *iref_to_path(struct btrfs_root *fs_root, 
> struct btrfs_path *path,
>                       btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
>               }
>               btrfs_release_path(path);
> -
>               iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
> +
> +             name_len = btrfs_inode_ref_name_len(eb, iref);
> +             name_off = (unsigned long)(iref + 1);
> +
>               parent = next_inum;
>               --bytes_left;
>               if (bytes_left >= 0)
> @@ -1531,9 +1534,12 @@ int iterate_inodes_from_logical(u64 logical, struct 
> btrfs_fs_info *fs_info,
>       return ret;
>  }
>  
> -static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
> -                             struct btrfs_path *path,
> -                             iterate_irefs_t *iterate, void *ctx)
> +typedef int (iterate_irefs_t)(u64 parent, u32 name_len, unsigned long 
> name_off,
> +                           struct extent_buffer *eb, void *ctx);
> +
> +static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root,
> +                           struct btrfs_path *path,
> +                           iterate_irefs_t *iterate, void *ctx)
>  {
>       int ret = 0;
>       int slot;
> @@ -1550,7 +1556,7 @@ static int iterate_irefs(u64 inum, struct btrfs_root 
> *fs_root,
>       while (!ret) {
>               path->leave_spinning = 1;
>               ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path,
> -                                     &found_key);
> +                                  &found_key);
>               if (ret < 0)
>                       break;
>               if (ret) {
> @@ -1578,7 +1584,8 @@ static int iterate_irefs(u64 inum, struct btrfs_root 
> *fs_root,
>                                "tree %llu\n", cur,
>                                (unsigned long long)found_key.objectid,
>                                (unsigned long long)fs_root->objectid);
> -                     ret = iterate(parent, iref, eb, ctx);
> +                     ret = iterate(parent, name_len,
> +                                   (unsigned long)(iref + 1), eb, ctx);
>                       if (ret)
>                               break;
>                       len = sizeof(*iref) + name_len;
> @@ -1593,12 +1600,98 @@ static int iterate_irefs(u64 inum, struct btrfs_root 
> *fs_root,
>       return ret;
>  }
>  
> +static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root,
> +                              struct btrfs_path *path,
> +                              iterate_irefs_t *iterate, void *ctx)
> +{
> +     int ret;
> +     int slot;
> +     u64 offset = 0;
> +     u64 parent;
> +     int found = 0;
> +     struct extent_buffer *eb;
> +     struct btrfs_inode_extref *extref;
> +     struct extent_buffer *leaf;
> +     u32 item_size;
> +     u32 cur_offset;
> +     unsigned long ptr;
> +
> +     while (1) {
> +             ret = btrfs_find_one_extref(fs_root, inum, offset, path, 
> &extref,
> +                                         &offset);
> +             if (ret < 0)
> +                     break;
> +             if (ret) {
> +                     ret = found ? 0 : -ENOENT;
> +                     break;
> +             }
> +             ++found;
> +
> +             slot = path->slots[0];
> +             eb = path->nodes[0];
> +             /* make sure we can use eb after releasing the path */
> +             atomic_inc(&eb->refs);
> +
> +             btrfs_tree_read_lock(eb);
> +             btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
> +             btrfs_release_path(path);
> +
> +             leaf = path->nodes[0];
> +             item_size = btrfs_item_size_nr(leaf, path->slots[0]);
> +             ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
> +             cur_offset = 0;
> +
> +             while (cur_offset < item_size) {
> +                     u32 name_len;
> +
> +                     extref = (struct btrfs_inode_extref *)(ptr + 
> cur_offset);
> +                     parent = btrfs_inode_extref_parent(eb, extref);
> +                     name_len = btrfs_inode_extref_name_len(eb, extref);
> +                     ret = iterate(parent, name_len,
> +                                   (unsigned long)&extref->name, eb, ctx);
> +                     if (ret)
> +                             break;
> +
> +                     cur_offset += btrfs_inode_extref_name_len(leaf, extref);
> +                     cur_offset += sizeof(*extref);
> +             }
> +             btrfs_tree_read_unlock_blocking(eb);
> +             free_extent_buffer(eb);
> +
> +             offset++;
> +     }
> +
> +     btrfs_release_path(path);
> +
> +     return ret;
> +}
> +
> +static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
> +                      struct btrfs_path *path, iterate_irefs_t *iterate,
> +                      void *ctx)
> +{
> +     int ret;
> +     int found_refs = 0;
> +
> +     ret = iterate_inode_refs(inum, fs_root, path, iterate, ctx);
> +     if (!ret)
> +             ++found_refs;
> +     else if (ret != -ENOENT)
> +             return ret;
> +
> +     ret = iterate_inode_extrefs(inum, fs_root, path, iterate, ctx);
> +     if (ret == -ENOENT && found_refs)
> +             return 0;
> +
> +     return ret;
> +}
> +
>  /*
>   * returns 0 if the path could be dumped (probably truncated)
>   * returns <0 in case of an error
>   */
> -static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref,
> -                             struct extent_buffer *eb, void *ctx)
> +static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off,
> +                      struct extent_buffer *eb, void *ctx)
>  {
>       struct inode_fs_paths *ipath = ctx;
>       char *fspath;
> @@ -1611,20 +1704,17 @@ static int inode_to_path(u64 inum, struct 
> btrfs_inode_ref *iref,
>                                       ipath->fspath->bytes_left - s_ptr : 0;
>  
>       fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr;
> -     fspath = iref_to_path(ipath->fs_root, ipath->btrfs_path, iref, eb,
> -                             inum, fspath_min, bytes_left);
> +     fspath = iref_to_path(ipath->fs_root, ipath->btrfs_path, name_len,
> +                           name_off, eb, inum, fspath_min,
> +                           bytes_left);
>       if (IS_ERR(fspath))
>               return PTR_ERR(fspath);
>  
>       if (fspath > fspath_min) {
> -             pr_debug("path resolved: %s\n", fspath);
>               ipath->fspath->val[i] = (u64)(unsigned long)fspath;
>               ++ipath->fspath->elem_cnt;
>               ipath->fspath->bytes_left = fspath - fspath_min;
>       } else {
> -             pr_debug("missed path, not enough space. missing bytes: %lu, "
> -                      "constructed so far: %s\n",
> -                      (unsigned long)(fspath_min - fspath), fspath_min);
>               ++ipath->fspath->elem_missed;
>               ipath->fspath->bytes_missing += fspath_min - fspath;
>               ipath->fspath->bytes_left = 0;
> @@ -1646,7 +1736,7 @@ static int inode_to_path(u64 inum, struct 
> btrfs_inode_ref *iref,
>  int paths_from_inode(u64 inum, struct inode_fs_paths *ipath)
>  {
>       return iterate_irefs(inum, ipath->fs_root, ipath->btrfs_path,
> -                             inode_to_path, ipath);
> +                          inode_to_path, ipath);
>  }
>  
>  struct btrfs_data_container *init_data_container(u32 total_bytes)
> diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h
> index 9f3e251..c80889a 100644
> --- a/fs/btrfs/backref.h
> +++ b/fs/btrfs/backref.h
> @@ -32,8 +32,6 @@ struct inode_fs_paths {
>  
>  typedef int (iterate_extent_inodes_t)(u64 inum, u64 offset, u64 root,
>               void *ctx);
> -typedef int (iterate_irefs_t)(u64 parent, struct btrfs_inode_ref *iref,
> -                             struct extent_buffer *eb, void *ctx);
>  
>  int inode_item_info(u64 inum, u64 ioff, struct btrfs_root *fs_root,
>                       struct btrfs_path *path);

Reviewed-by: Jan Schmidt <[email protected]>

-Jan
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to