On Mon, May 21, 2012 at 23:46 (+0200), Mark Fasheh wrote:
> From: Mark Fasheh <mfas...@suse.com>
> 
> 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 <mfas...@suse.de>
> ---
>  fs/btrfs/backref.c |  144 
> +++++++++++++++++++++++++++++++++++++++++++---------
>  fs/btrfs/backref.h |    2 -
>  2 files changed, 119 insertions(+), 27 deletions(-)
> 
> diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
> index c97240a..d88fa49 100644
> --- a/fs/btrfs/backref.c
> +++ b/fs/btrfs/backref.c
> @@ -22,6 +22,7 @@
>  #include "ulist.h"
>  #include "transaction.h"
>  #include "delayed-ref.h"
> +#include "locking.h"

This + line tells me it's not based on top of linux-3.4 or newer. I see that the
changes made in between are now included in your patch set. It might have been
better to rebase it before sending them. Anyway, that only makes review a bit
harder, should affect applying the patches.

>  
>  /*
>   * this structure records all encountered refs on the way up to the root
> @@ -940,34 +941,35 @@ 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;
>       s64 bytes_left = size - 1;
>       struct extent_buffer *eb = eb_in;
>       struct btrfs_key found_key;
> +     struct btrfs_inode_ref *iref;
>  
>       if (bytes_left >= 0)
>               dest[bytes_left] = '\0';
>  
>       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)
>                       free_extent_buffer(eb);
> +
>               ret = inode_ref_info(parent, 0, fs_root, path, &found_key);
>               if (ret > 0)
>                       ret = -ENOENT;
>               if (ret)
>                       break;
> +
>               next_inum = found_key.offset;
>  
>               /* regular exit ahead */
> @@ -980,8 +982,11 @@ static char *iref_to_path(struct btrfs_root *fs_root, 
> struct btrfs_path *path,
>               if (eb != eb_in)
>                       atomic_inc(&eb->refs);
>               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)
> @@ -1294,9 +1299,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;
>       int slot;
> @@ -1312,7 +1320,7 @@ static int iterate_irefs(u64 inum, struct btrfs_root 
> *fs_root,
>  
>       while (1) {
>               ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path,
> -                                     &found_key);
> +                                  &found_key);
>               if (ret < 0)
>                       break;
>               if (ret) {
> @@ -1326,8 +1334,11 @@ static int iterate_irefs(u64 inum, struct btrfs_root 
> *fs_root,
>               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);
>  
> +

I realized you like adding new lines, but we really don't need two of them here.

>               item = btrfs_item_nr(eb, slot);
>               iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
>  
> @@ -1338,15 +1349,81 @@ 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);
> -                     if (ret) {
> -                             free_extent_buffer(eb);
> +                     ret = iterate(parent, name_len,
> +                                   (unsigned long)(iref + 1),eb, ctx);

There's a space missing before "eb".

> +                     if (ret)
>                               break;
> -                     }
>                       len = sizeof(*iref) + name_len;
>                       iref = (struct btrfs_inode_ref *)((char *)iref + len);
>               }
> +             btrfs_tree_read_unlock_blocking(eb);
> +             free_extent_buffer(eb);
> +     }
> +
> +     btrfs_release_path(path);
> +
> +     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);
> @@ -1354,12 +1431,32 @@ static int iterate_irefs(u64 inum, struct btrfs_root 
> *fs_root,
>       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;
> @@ -1372,20 +1469,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;
> @@ -1407,7 +1501,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);
>  }
>  
>  /*
> diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h
> index 8586d1b..649a220 100644
> --- a/fs/btrfs/backref.h
> +++ b/fs/btrfs/backref.h
> @@ -30,8 +30,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);

Almost ready for a reviewed-by tag :-)
-Jan
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to