Re: [PATCH v8 1/8] btrfs: added helper functions to iterate backrefs

2011-11-07 Thread Arne Jansen
On 03.11.2011 11:32, Jan Schmidt wrote:
> On 03.11.2011 02:41, Li Zefan wrote:
>> (as this is going to be merged into mainline..)
>>
>>> +/*
>>> + * calls iterate() for every inode that references the extent identified by
>>> + * the given parameters. will use the path given as a parameter and return 
>>> it
>>> + * released.
>>> + * when the iterator function returns a non-zero value, iteration stops.
>>> + */
>>> +int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
>>> +   struct btrfs_path *path,
>>> +   u64 extent_item_objectid,
>>> +   u64 extent_offset,
>>> +   iterate_extent_inodes_t *iterate, void *ctx)
>>
>> While trying to use this API, I found there's a big defect in this function.
>>
>>fs_tree 1   fs_tree 2
>>\  /
>> \/
>>  \  /
>>   \/
>>  node
>>   |
>>   |
>>  leaf  (EXTENT_DATA item)
>>
>> In the above case, the function will find only 1 reference.
> 
> Hum. You are right.
> 
> I'm convinced that I've been at this point months ago, only I cannot
> find code dealing with counts > 1 on nodes. I'll look for a fix in my
> branches or make a new one.
> 
> Currently, this is more of a best-effort resolver. Support for delayed
> extents is missing, it should be used on commit roots to get a
> consistent state.
> 

The qgroups patch contains an implementation to find all roots for a
given extent. A quite extensive part of qgroups is needed for that, so
it might be easiest to build a new version on top of qgroups.
Otherwise I could split qgroups in 2 parts to factor out that half.

-Arne
--
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


Re: [PATCH v8 1/8] btrfs: added helper functions to iterate backrefs

2011-11-03 Thread Jan Schmidt
On 03.11.2011 02:41, Li Zefan wrote:
> (as this is going to be merged into mainline..)
> 
>> +/*
>> + * calls iterate() for every inode that references the extent identified by
>> + * the given parameters. will use the path given as a parameter and return 
>> it
>> + * released.
>> + * when the iterator function returns a non-zero value, iteration stops.
>> + */
>> +int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
>> +struct btrfs_path *path,
>> +u64 extent_item_objectid,
>> +u64 extent_offset,
>> +iterate_extent_inodes_t *iterate, void *ctx)
> 
> While trying to use this API, I found there's a big defect in this function.
> 
>fs_tree 1   fs_tree 2
>\  /
> \/
>  \  /
>   \/
>  node
>   |
>   |
>  leaf  (EXTENT_DATA item)
> 
> In the above case, the function will find only 1 reference.

Hum. You are right.

I'm convinced that I've been at this point months ago, only I cannot
find code dealing with counts > 1 on nodes. I'll look for a fix in my
branches or make a new one.

I also recognized that some "btrfs_" prefixes are missing for the
exported functions. I'm going to change this on the next iteration as well.

Currently, this is more of a best-effort resolver. Support for delayed
extents is missing, it should be used on commit roots to get a
consistent state.

For the userspace part, at least the simple scenario outlined isn't
crucial as "btrfs inspect-internal logical-resolve" will find each of
the two paths, depending on the subvolume path you specify. It never
finds both, though, which I agree it should.

Sigh,
-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


Re: [PATCH v8 1/8] btrfs: added helper functions to iterate backrefs

2011-11-02 Thread Li Zefan
(as this is going to be merged into mainline..)

> +/*
> + * calls iterate() for every inode that references the extent identified by
> + * the given parameters. will use the path given as a parameter and return it
> + * released.
> + * when the iterator function returns a non-zero value, iteration stops.
> + */
> +int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
> + struct btrfs_path *path,
> + u64 extent_item_objectid,
> + u64 extent_offset,
> + iterate_extent_inodes_t *iterate, void *ctx)

While trying to use this API, I found there's a big defect in this function.

   fs_tree 1   fs_tree 2
   \  /
\/
 \  /
  \/
 node
  |
  |
 leaf  (EXTENT_DATA item)

In the above case, the function will find only 1 reference.
--
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


[PATCH v8 1/8] btrfs: added helper functions to iterate backrefs

2011-07-27 Thread Jan Schmidt
These helper functions iterate back references and call a function for each
backref. There is also a function to resolve an inode to a path in the
file system.

Signed-off-by: Jan Schmidt 
---
 fs/btrfs/Makefile  |3 +-
 fs/btrfs/backref.c |  764 
 fs/btrfs/backref.h |   62 +
 fs/btrfs/ioctl.h   |   11 +
 4 files changed, 839 insertions(+), 1 deletions(-)

diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
index 9b72dcf..c63f649 100644
--- a/fs/btrfs/Makefile
+++ b/fs/btrfs/Makefile
@@ -7,4 +7,5 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o 
root-tree.o dir-item.o \
   extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
   extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
   export.o tree-log.o acl.o free-space-cache.o zlib.o lzo.o \
-  compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o
+  compression.o delayed-ref.o relocation.o delayed-inode.o backref.o \
+  scrub.o
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
new file mode 100644
index 000..5bca830
--- /dev/null
+++ b/fs/btrfs/backref.c
@@ -0,0 +1,764 @@
+/*
+ * Copyright (C) 2011 STRATO.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#include "ctree.h"
+#include "disk-io.h"
+#include "backref.h"
+
+struct __data_ref {
+   struct list_head list;
+   u64 inum;
+   u64 root;
+   u64 extent_data_item_offset;
+};
+
+struct __shared_ref {
+   struct list_head list;
+   u64 disk_byte;
+};
+
+static int __inode_info(u64 inum, u64 ioff, u8 key_type,
+   struct btrfs_root *fs_root, struct btrfs_path *path,
+   struct btrfs_key *found_key)
+{
+   int ret;
+   struct btrfs_key key;
+   struct extent_buffer *eb;
+
+   key.type = key_type;
+   key.objectid = inum;
+   key.offset = ioff;
+
+   ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0);
+   if (ret < 0)
+   return ret;
+
+   eb = path->nodes[0];
+   if (ret && path->slots[0] >= btrfs_header_nritems(eb)) {
+   ret = btrfs_next_leaf(fs_root, path);
+   if (ret)
+   return ret;
+   eb = path->nodes[0];
+   }
+
+   btrfs_item_key_to_cpu(eb, found_key, path->slots[0]);
+   if (found_key->type != key.type || found_key->objectid != key.objectid)
+   return 1;
+
+   return 0;
+}
+
+/*
+ * this makes the path point to (inum INODE_ITEM ioff)
+ */
+int inode_item_info(u64 inum, u64 ioff, struct btrfs_root *fs_root,
+   struct btrfs_path *path)
+{
+   struct btrfs_key key;
+   return __inode_info(inum, ioff, BTRFS_INODE_ITEM_KEY, fs_root, path,
+   &key);
+}
+
+static int inode_ref_info(u64 inum, u64 ioff, struct btrfs_root *fs_root,
+   struct btrfs_path *path, int strict,
+   u64 *out_parent_inum,
+   struct extent_buffer **out_iref_eb,
+   int *out_slot)
+{
+   int ret;
+   struct btrfs_key found_key;
+
+   ret = __inode_info(inum, ioff, BTRFS_INODE_REF_KEY, fs_root, path,
+   &found_key);
+
+   if (!ret) {
+   if (out_slot)
+   *out_slot = path->slots[0];
+   if (out_iref_eb)
+   *out_iref_eb = path->nodes[0];
+   if (out_parent_inum)
+   *out_parent_inum = found_key.offset;
+   }
+
+   btrfs_release_path(path);
+   return ret;
+}
+
+/*
+ * this iterates to turn a btrfs_inode_ref into a full filesystem path. 
elements
+ * of the path are separated by '/' and the path is guaranteed to be
+ * 0-terminated. the path is only given within the current file system.
+ * Therefore, it never starts with a '/'. the caller is responsible to provide
+ * "size" bytes in "dest". the dest buffer will be filled backwards. finally,
+ * the start point of the resulting string is returned. this pointer is within
+ * dest, normally.
+ * in case the path buffer would overflow, the pointer is decremented further
+ * as if output was written to the buffer, though no more output is actually
+ * generated. that way, the caller