summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ulist.h
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2012-05-22 14:56:50 +0200
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-05-26 12:17:49 +0200
commitcd1b413c5c863a96bfdeab8e91b1fb3a52665e42 (patch)
treea433c13c530c487f2d7e209402ef72ec67e48647 /fs/btrfs/ulist.h
parentBtrfs: avoid sleeping in verify_parent_transid while atomic (diff)
downloadlinux-cd1b413c5c863a96bfdeab8e91b1fb3a52665e42.tar.xz
linux-cd1b413c5c863a96bfdeab8e91b1fb3a52665e42.zip
Btrfs: ulist realloc bugfix
ulist_next gets the pointer to the previously returned element to find the next element from there. However, when we call ulist_add while iteration with ulist_next is in progress (ulist explicitly supports this), we can realloc the ulist internal memory, which makes the pointer to the previous element useless. Instead, we now use an iterator parameter that's independent from the internal pointers. Reported-by: Alexander Block <ablock84@googlemail.com> Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs/ulist.h')
-rw-r--r--fs/btrfs/ulist.h9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/btrfs/ulist.h b/fs/btrfs/ulist.h
index 2e25dec58ec0..62d2574f775a 100644
--- a/fs/btrfs/ulist.h
+++ b/fs/btrfs/ulist.h
@@ -24,6 +24,10 @@
*/
#define ULIST_SIZE 16
+struct ulist_iterator {
+ int i;
+};
+
/*
* element of the list
*/
@@ -63,6 +67,9 @@ struct ulist *ulist_alloc(unsigned long gfp_mask);
void ulist_free(struct ulist *ulist);
int ulist_add(struct ulist *ulist, u64 val, unsigned long aux,
unsigned long gfp_mask);
-struct ulist_node *ulist_next(struct ulist *ulist, struct ulist_node *prev);
+struct ulist_node *ulist_next(struct ulist *ulist,
+ struct ulist_iterator *uiter);
+
+#define ULIST_ITER_INIT(uiter) ((uiter)->i = 0)
#endif