In this patch, we make two things:

a) skiplist -> rcu-skiplist
   This is quite direct, since in skiplist each level is a list,
   any modification to the skiplist refers to "pointers change",
   which fits RCU's sematic.

b) use rcu lock for reader side and mutex lock for updater side
   to protect extent_map instead of rwlock.

Signed-off-by: Liu Bo <[email protected]>
---
changes v2:
- fix a bug reported by David Sterba <[email protected]>, thanks a lot!
- use mutex lock to protect extent_map updater side, so that we can make
  the reclaim code much easier.
---
 fs/btrfs/compression.c |    8 ++++----
 fs/btrfs/disk-io.c     |    9 ++++-----
 fs/btrfs/extent_io.c   |   13 ++++++-------
 fs/btrfs/extent_map.c  |   28 ++++++++++++++++++----------
 fs/btrfs/extent_map.h  |    5 ++---
 fs/btrfs/file.c        |   11 ++++++-----
 fs/btrfs/inode.c       |   28 ++++++++++++++--------------
 fs/btrfs/ioctl.c       |    8 ++++----
 fs/btrfs/relocation.c  |    4 ++--
 fs/btrfs/scrub.c       |    4 ++--
 fs/btrfs/skiplist.c    |   11 +++++++----
 fs/btrfs/skiplist.h    |   25 ++++++++++++++++---------
 fs/btrfs/volumes.c     |   36 ++++++++++++++++++------------------
 13 files changed, 103 insertions(+), 87 deletions(-)

diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 14f1c5a..bb4ac31 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -498,10 +498,10 @@ static noinline int add_ra_bio_pages(struct inode *inode,
                 */
                set_page_extent_mapped(page);
                lock_extent(tree, last_offset, end, GFP_NOFS);
-               read_lock(&em_tree->lock);
+               rcu_read_lock();
                em = lookup_extent_mapping(em_tree, last_offset,
                                           PAGE_CACHE_SIZE);
-               read_unlock(&em_tree->lock);
+               rcu_read_unlock();
 
                if (!em || last_offset < em->start ||
                    (last_offset + PAGE_CACHE_SIZE > extent_map_end(em)) ||
@@ -583,11 +583,11 @@ int btrfs_submit_compressed_read(struct inode *inode, 
struct bio *bio,
        em_tree = &BTRFS_I(inode)->extent_tree;
 
        /* we need the actual starting offset of this extent in the file */
-       read_lock(&em_tree->lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(em_tree,
                                   page_offset(bio->bi_io_vec->bv_page),
                                   PAGE_CACHE_SIZE);
-       read_unlock(&em_tree->lock);
+       rcu_read_unlock();
 
        compressed_len = em->block_len;
        cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 3f9d555..8e09517 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -191,15 +191,14 @@ static struct extent_map *btree_get_extent(struct inode 
*inode,
        struct extent_map *em;
        int ret;
 
-       read_lock(&em_tree->lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(em_tree, start, len);
+       rcu_read_unlock();
        if (em) {
                em->bdev =
                        BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev;
-               read_unlock(&em_tree->lock);
                goto out;
        }
-       read_unlock(&em_tree->lock);
 
        em = alloc_extent_map();
        if (!em) {
@@ -212,7 +211,7 @@ static struct extent_map *btree_get_extent(struct inode 
*inode,
        em->block_start = 0;
        em->bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev;
 
-       write_lock(&em_tree->lock);
+       mutex_lock(&em_tree->lock);
        ret = add_extent_mapping(em_tree, em);
        if (ret == -EEXIST) {
                u64 failed_start = em->start;
@@ -231,7 +230,7 @@ static struct extent_map *btree_get_extent(struct inode 
*inode,
                free_extent_map(em);
                em = NULL;
        }
-       write_unlock(&em_tree->lock);
+       mutex_unlock(&em_tree->lock);
 
        if (ret)
                em = ERR_PTR(ret);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 49f3c9d..7efa8dd 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2013,10 +2013,10 @@ static int bio_readpage_error(struct bio *failed_bio, 
struct page *page,
                failrec->bio_flags = 0;
                failrec->in_validation = 0;
 
-               read_lock(&em_tree->lock);
+               rcu_read_lock();
                em = lookup_extent_mapping(em_tree, start, failrec->len);
+               rcu_read_unlock();
                if (!em) {
-                       read_unlock(&em_tree->lock);
                        kfree(failrec);
                        return -EIO;
                }
@@ -2025,7 +2025,6 @@ static int bio_readpage_error(struct bio *failed_bio, 
struct page *page,
                        free_extent_map(em);
                        em = NULL;
                }
-               read_unlock(&em_tree->lock);
 
                if (!em || IS_ERR(em)) {
                        kfree(failrec);
@@ -3286,15 +3285,15 @@ int try_release_extent_mapping(struct extent_map_tree 
*map,
                u64 len;
                while (start <= end) {
                        len = end - start + 1;
-                       write_lock(&map->lock);
+                       mutex_lock(&map->lock);
                        em = lookup_extent_mapping(map, start, len);
                        if (IS_ERR_OR_NULL(em)) {
-                               write_unlock(&map->lock);
+                               mutex_unlock(&map->lock);
                                break;
                        }
                        if (test_bit(EXTENT_FLAG_PINNED, &em->flags) ||
                            em->start != start) {
-                               write_unlock(&map->lock);
+                               mutex_unlock(&map->lock);
                                free_extent_map(em);
                                break;
                        }
@@ -3307,7 +3306,7 @@ int try_release_extent_mapping(struct extent_map_tree 
*map,
                                free_extent_map(em);
                        }
                        start = extent_map_end(em);
-                       write_unlock(&map->lock);
+                       mutex_unlock(&map->lock);
 
                        /* once for us */
                        free_extent_map(em);
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index e0a7881..8d40638 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -11,6 +11,7 @@ static struct kmem_cache *extent_map_cache;
 
 static LIST_HEAD(maps);
 
+#define MAP_REFS_DEBUG 1
 #define MAP_LEAK_DEBUG 1
 #if MAP_LEAK_DEBUG
 static DEFINE_SPINLOCK(map_leak_lock);
@@ -67,7 +68,7 @@ void extent_map_tree_init(struct extent_map_tree *tree)
 {
        tree->head.start = (-1ULL);
        sl_init_list(&tree->map, &tree->head.sl_node);
-       rwlock_init(&tree->lock);
+       mutex_init(&tree->lock);
 }
 
 /**
@@ -100,8 +101,11 @@ struct extent_map *alloc_extent_map(void)
        return em;
 }
 
-static inline void __free_extent_map(struct extent_map *em)
+static inline void __free_extent_map(struct rcu_head *head)
 {
+       struct sl_node *node = container_of(head, struct sl_node, rcu_head);
+       struct extent_map *em = sl_entry(node, struct extent_map, sl_node);
+
 #if MAP_LEAK_DEBUG
        unsigned long flags;
 
@@ -129,7 +133,7 @@ void free_extent_map(struct extent_map *em)
 
        WARN_ON(atomic_read(&em->refs) == 0);
        if (atomic_dec_and_test(&em->refs))
-               __free_extent_map(em);
+               call_rcu(&em->sl_node.rcu_head, __free_extent_map);
 }
 
 static inline int in_entry(struct sl_node *node, u64 offset)
@@ -166,14 +170,14 @@ static struct sl_node *sl_search(struct sl_list *list, 
u64 offset,
 
        BUG_ON(!list);
        level = list->level;
-       p = list->head;
+       p = rcu_dereference(list->head);
        BUG_ON(!p);
 
        if (sl_empty(p))
                return NULL;
        do {
                while (entry = next_entry(p, level, &q), entry->start <= offset)
-                       p = q;
+                       p = rcu_dereference(q);
 
                if (in_entry(p, offset))
                        return p;
@@ -299,7 +303,7 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 
start, u64 len)
        int ret = 0;
        struct extent_map *em;
 
-       write_lock(&tree->lock);
+       mutex_lock(&tree->lock);
        em = lookup_extent_mapping(tree, start, len);
 
        WARN_ON(!em || em->start != start);
@@ -312,7 +316,7 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 
start, u64 len)
 
        free_extent_map(em);
 out:
-       write_unlock(&tree->lock);
+       mutex_unlock(&tree->lock);
        return ret;
 }
 
@@ -326,8 +330,7 @@ out:
  * into the tree directly, with an additional reference taken, or a
  * reference dropped if the merge attempt was successful.
  */
-int add_extent_mapping(struct extent_map_tree *tree,
-                      struct extent_map *em)
+int add_extent_mapping(struct extent_map_tree *tree, struct extent_map *em)
 {
        int ret = 0;
        struct sl_node *sl_node;
@@ -382,7 +385,12 @@ struct extent_map *__lookup_extent_mapping(struct 
extent_map_tree *tree,
        if (strict && !(end > em->start && start < extent_map_end(em)))
                return NULL;
 
-       atomic_inc(&em->refs);
+#if MAP_REFS_DEBUG
+       if (!atomic_read(&em->refs))
+               printk(KERN_INFO "Btrfs: Reader gets an em with 0 refs\n");
+#endif
+       if (!atomic_inc_not_zero(&em->refs))
+               return NULL;
        return em;
 }
 
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
index 6d2c247..6563800 100644
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -41,7 +41,7 @@ struct map_head {
 
 struct extent_map_tree {
        struct sl_list map;
-       rwlock_t lock;
+       struct mutex lock;
        struct map_head head;
 };
 
@@ -62,8 +62,7 @@ static inline u64 extent_map_block_end(struct extent_map *em)
 void extent_map_tree_init(struct extent_map_tree *tree);
 struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree,
                                         u64 start, u64 len);
-int add_extent_mapping(struct extent_map_tree *tree,
-                      struct extent_map *em);
+int add_extent_mapping(struct extent_map_tree *tree, struct extent_map *em);
 int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em);
 
 struct extent_map *alloc_extent_map(void);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index cc7492c..27c5ff3 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -454,24 +454,25 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 
start, u64 end,
                        split2 = alloc_extent_map();
                BUG_ON(!split || !split2);
 
-               write_lock(&em_tree->lock);
+               mutex_lock(&em_tree->lock);
                em = lookup_extent_mapping(em_tree, start, len);
                if (!em) {
-                       write_unlock(&em_tree->lock);
+                       mutex_unlock(&em_tree->lock);
                        break;
                }
+
                flags = em->flags;
                if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) {
                        if (testend && em->start + em->len >= start + len) {
                                free_extent_map(em);
-                               write_unlock(&em_tree->lock);
+                               mutex_unlock(&em_tree->lock);
                                break;
                        }
                        start = em->start + em->len;
                        if (testend)
                                len = start + len - (em->start + em->len);
                        free_extent_map(em);
-                       write_unlock(&em_tree->lock);
+                       mutex_unlock(&em_tree->lock);
                        continue;
                }
                compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
@@ -524,7 +525,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, 
u64 end,
                        free_extent_map(split);
                        split = NULL;
                }
-               write_unlock(&em_tree->lock);
+               mutex_unlock(&em_tree->lock);
 
                /* once for us */
                free_extent_map(em);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 13b0542..edf3258 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -675,9 +675,9 @@ retry:
                set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
 
                while (1) {
-                       write_lock(&em_tree->lock);
+                       mutex_lock(&em_tree->lock);
                        ret = add_extent_mapping(em_tree, em);
-                       write_unlock(&em_tree->lock);
+                       mutex_unlock(&em_tree->lock);
                        if (ret != -EEXIST) {
                                free_extent_map(em);
                                break;
@@ -732,7 +732,7 @@ static u64 get_extent_allocation_hint(struct inode *inode, 
u64 start,
        struct extent_map *em;
        u64 alloc_hint = 0;
 
-       read_lock(&em_tree->lock);
+       rcu_read_lock();
        em = search_extent_mapping(em_tree, start, num_bytes);
        if (em) {
                /*
@@ -752,7 +752,7 @@ static u64 get_extent_allocation_hint(struct inode *inode, 
u64 start,
                        free_extent_map(em);
                }
        }
-       read_unlock(&em_tree->lock);
+       rcu_read_unlock();
 
        return alloc_hint;
 }
@@ -854,9 +854,9 @@ static noinline int cow_file_range(struct inode *inode,
                set_bit(EXTENT_FLAG_PINNED, &em->flags);
 
                while (1) {
-                       write_lock(&em_tree->lock);
+                       mutex_lock(&em_tree->lock);
                        ret = add_extent_mapping(em_tree, em);
-                       write_unlock(&em_tree->lock);
+                       mutex_unlock(&em_tree->lock);
                        if (ret != -EEXIST) {
                                free_extent_map(em);
                                break;
@@ -1207,9 +1207,9 @@ out_check:
                        em->bdev = root->fs_info->fs_devices->latest_bdev;
                        set_bit(EXTENT_FLAG_PINNED, &em->flags);
                        while (1) {
-                               write_lock(&em_tree->lock);
+                               mutex_lock(&em_tree->lock);
                                ret = add_extent_mapping(em_tree, em);
-                               write_unlock(&em_tree->lock);
+                               mutex_unlock(&em_tree->lock);
                                if (ret != -EEXIST) {
                                        free_extent_map(em);
                                        break;
@@ -4950,11 +4950,11 @@ struct extent_map *btrfs_get_extent(struct inode 
*inode, struct page *page,
        int compress_type;
 
 again:
-       read_lock(&em_tree->lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(em_tree, start, len);
        if (em)
                em->bdev = root->fs_info->fs_devices->latest_bdev;
-       read_unlock(&em_tree->lock);
+       rcu_read_unlock();
 
        if (em) {
                if (em->start > start || em->start + em->len <= start)
@@ -5166,7 +5166,7 @@ insert:
        }
 
        err = 0;
-       write_lock(&em_tree->lock);
+       mutex_lock(&em_tree->lock);
        ret = add_extent_mapping(em_tree, em);
        /* it is possible that someone inserted the extent into the tree
         * while we had the lock dropped.  It is also possible that
@@ -5206,7 +5206,7 @@ insert:
                        err = 0;
                }
        }
-       write_unlock(&em_tree->lock);
+       mutex_unlock(&em_tree->lock);
 out:
 
        trace_btrfs_get_extent(root, em);
@@ -5414,9 +5414,9 @@ static struct extent_map *btrfs_new_extent_direct(struct 
inode *inode,
        set_bit(EXTENT_FLAG_PINNED, &em->flags);
 
        while (insert) {
-               write_lock(&em_tree->lock);
+               mutex_lock(&em_tree->lock);
                ret = add_extent_mapping(em_tree, em);
-               write_unlock(&em_tree->lock);
+               mutex_unlock(&em_tree->lock);
                if (ret != -EEXIST)
                        break;
                btrfs_drop_extent_cache(inode, start, start + em->len - 1, 0);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index c04f02c..83fc601 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -673,9 +673,9 @@ static int check_defrag_in_cache(struct inode *inode, u64 
offset, int thresh)
        struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
        u64 end;
 
-       read_lock(&em_tree->lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(em_tree, offset, PAGE_CACHE_SIZE);
-       read_unlock(&em_tree->lock);
+       rcu_read_unlock();
 
        if (em) {
                end = extent_map_end(em);
@@ -782,9 +782,9 @@ static int should_defrag_range(struct inode *inode, u64 
start, u64 len,
         * hopefully we have this extent in the tree already, try without
         * the full extent lock
         */
-       read_lock(&em_tree->lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(em_tree, start, len);
-       read_unlock(&em_tree->lock);
+       rcu_read_unlock();
 
        if (!em) {
                /* get the big lock and read metadata off disk */
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index cfb5543..7eb4685 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2899,9 +2899,9 @@ int setup_extent_mapping(struct inode *inode, u64 start, 
u64 end,
 
        lock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
        while (1) {
-               write_lock(&em_tree->lock);
+               mutex_lock(&em_tree->lock);
                ret = add_extent_mapping(em_tree, em);
-               write_unlock(&em_tree->lock);
+               mutex_unlock(&em_tree->lock);
                if (ret != -EEXIST) {
                        free_extent_map(em);
                        break;
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index ddf2c90..5aec748 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -1374,9 +1374,9 @@ static noinline_for_stack int scrub_chunk(struct 
scrub_dev *sdev,
        int i;
        int ret = -EINVAL;
 
-       read_lock(&map_tree->map_tree.lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(&map_tree->map_tree, chunk_offset, 1);
-       read_unlock(&map_tree->map_tree.lock);
+       rcu_read_unlock();
 
        if (!em)
                return -EINVAL;
diff --git a/fs/btrfs/skiplist.c b/fs/btrfs/skiplist.c
index c803478..621eb7b 100644
--- a/fs/btrfs/skiplist.c
+++ b/fs/btrfs/skiplist.c
@@ -29,6 +29,7 @@ inline int sl_fill_node(struct sl_node *node, int level, 
gfp_t mask)
        struct sl_node **p;
        struct sl_node **q;
        int num;
+       int i;
 
        BUG_ON(level > MAXLEVEL);
 
@@ -44,6 +45,9 @@ inline int sl_fill_node(struct sl_node *node, int level, 
gfp_t mask)
                return -ENOMEM;
        }
 
+       for (i = 0; i < num; i++)
+               p[i] = q[i] = NULL;
+
        node->next = p;
        node->prev = q;
        node->level = level;
@@ -62,7 +66,7 @@ inline void sl_link_node(struct sl_node *node, struct sl_node 
**backlook,
 
                node->next[i] = q;
                node->prev[i] = p;
-               p->next[i] = node;
+               rcu_assign_pointer(p->next[i], node);
                q->prev[i] = node;
 
                i++;
@@ -78,14 +82,13 @@ void sl_erase(struct sl_node *node, struct sl_list *list)
 
        level = node->level;
 
-       for (i = 0; i <= level; i++) {
+       for (i = level; i >= 0; i--) {
                prev = node->prev[i];
                next = node->next[i];
 
                prev->next[i] = next;
                next->prev[i] = prev;
-               node->next[i] = node;
-               node->prev[i] = node;
+               node->prev[i] = NULL;
        }
 
        head = list->head;
diff --git a/fs/btrfs/skiplist.h b/fs/btrfs/skiplist.h
index 3e414b5..2ae997d 100644
--- a/fs/btrfs/skiplist.h
+++ b/fs/btrfs/skiplist.h
@@ -102,41 +102,48 @@ struct sl_node *sl_insert_node(struct sl_list *list, u64 
offset,
 #define _SKIPLIST_H
 
 #include <linux/random.h>
+#include <linux/rcupdate.h>
 
 #define MAXLEVEL 16
 /* double p = 0.25; */
 
 struct sl_node {
-       struct sl_node **next;
-       struct sl_node **prev;
+       struct sl_node __rcu **next;
+       struct sl_node __rcu **prev;
+       struct rcu_head rcu_head;
        unsigned int level;
        unsigned int head:1;
 };
 
 struct sl_list {
-       struct sl_node *head;
-       struct sl_node *h_next[MAXLEVEL];
-       struct sl_node *h_prev[MAXLEVEL];
+       struct sl_node __rcu *head;
+       struct sl_node __rcu *h_next[MAXLEVEL];
+       struct sl_node __rcu *h_prev[MAXLEVEL];
        unsigned int level;
 };
 
-#define sl_entry(ptr, type, member) container_of(ptr, type, member)
+#define sl_entry(ptr, type, member) \
+       ({ \
+               typeof(*ptr) __rcu *__ptr = (typeof(*ptr) __rcu __force *)ptr; \
+               container_of((typeof(ptr))rcu_dereference(__ptr), \
+                            type, member); \
+       })
 
 static inline int sl_empty(const struct sl_node *head)
 {
-       return head->next[0] == head;
+       return (rcu_dereference(head->next[0]) == head);
 }
 
 static inline struct sl_node *__sl_next_with_level(struct sl_node *node,
                                                   int level)
 {
-       return node->next[level];
+       return rcu_dereference(node->next[level]);
 }
 
 static inline struct sl_node *__sl_prev_with_level(struct sl_node *node,
                                                   int level)
 {
-       return node->prev[level];
+       return rcu_dereference(node->prev[level]);
 }
 
 static inline struct sl_node *sl_next(struct sl_node *node)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index adaac9e..acc86b4 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1955,9 +1955,9 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
         * step two, delete the device extents and the
         * chunk tree entries
         */
-       read_lock(&em_tree->lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(em_tree, chunk_offset, 1);
-       read_unlock(&em_tree->lock);
+       rcu_read_unlock();
 
        BUG_ON(em->start > chunk_offset ||
               em->start + em->len < chunk_offset);
@@ -1988,9 +1988,9 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
        ret = btrfs_remove_block_group(trans, extent_root, chunk_offset);
        BUG_ON(ret);
 
-       write_lock(&em_tree->lock);
+       mutex_lock(&em_tree->lock);
        remove_extent_mapping(em_tree, em);
-       write_unlock(&em_tree->lock);
+       mutex_unlock(&em_tree->lock);
 
        kfree(map);
        em->bdev = NULL;
@@ -2589,9 +2589,9 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle 
*trans,
        em->block_len = em->len;
 
        em_tree = &extent_root->fs_info->mapping_tree.map_tree;
-       write_lock(&em_tree->lock);
+       mutex_lock(&em_tree->lock);
        ret = add_extent_mapping(em_tree, em);
-       write_unlock(&em_tree->lock);
+       mutex_unlock(&em_tree->lock);
        BUG_ON(ret);
        free_extent_map(em);
 
@@ -2800,9 +2800,9 @@ int btrfs_chunk_readonly(struct btrfs_root *root, u64 
chunk_offset)
        int readonly = 0;
        int i;
 
-       read_lock(&map_tree->map_tree.lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(&map_tree->map_tree, chunk_offset, 1);
-       read_unlock(&map_tree->map_tree.lock);
+       rcu_read_unlock();
        if (!em)
                return 1;
 
@@ -2854,9 +2854,9 @@ int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, 
u64 logical, u64 len)
        struct extent_map_tree *em_tree = &map_tree->map_tree;
        int ret;
 
-       read_lock(&em_tree->lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(em_tree, logical, len);
-       read_unlock(&em_tree->lock);
+       rcu_read_unlock();
        BUG_ON(!em);
 
        BUG_ON(em->start > logical || em->start + em->len < logical);
@@ -2921,9 +2921,9 @@ again:
                atomic_set(&bbio->error, 0);
        }
 
-       read_lock(&em_tree->lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(em_tree, logical, *length);
-       read_unlock(&em_tree->lock);
+       rcu_read_unlock();
 
        if (!em) {
                printk(KERN_CRIT "unable to find logical %llu len %llu\n",
@@ -3187,9 +3187,9 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
        u64 stripe_nr;
        int i, j, nr = 0;
 
-       read_lock(&em_tree->lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(em_tree, chunk_start, 1);
-       read_unlock(&em_tree->lock);
+       rcu_read_unlock();
 
        BUG_ON(!em || em->start != chunk_start);
        map = (struct map_lookup *)em->bdev;
@@ -3472,9 +3472,9 @@ static int read_one_chunk(struct btrfs_root *root, struct 
btrfs_key *key,
        logical = key->offset;
        length = btrfs_chunk_length(leaf, chunk);
 
-       read_lock(&map_tree->map_tree.lock);
+       rcu_read_lock();
        em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);
-       read_unlock(&map_tree->map_tree.lock);
+       rcu_read_unlock();
 
        /* already mapped? */
        if (em && em->start <= logical && em->start + em->len > logical) {
@@ -3533,9 +3533,9 @@ static int read_one_chunk(struct btrfs_root *root, struct 
btrfs_key *key,
                map->stripes[i].dev->in_fs_metadata = 1;
        }
 
-       write_lock(&map_tree->map_tree.lock);
+       mutex_lock(&map_tree->map_tree.lock);
        ret = add_extent_mapping(&map_tree->map_tree, em);
-       write_unlock(&map_tree->map_tree.lock);
+       mutex_unlock(&map_tree->map_tree.lock);
        BUG_ON(ret);
        free_extent_map(em);
 
-- 
1.6.5.2

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