btrfs: fix check_shared for fiemap ioctl
[sfrench/cifs-2.6.git] / fs / btrfs / extent_io.c
index 44fe66b53c8b450b4d615e06fc5e8c159bfc9885..8644df8ba5277db3b6d2adc04d4e8d7c6394bca5 100644 (file)
@@ -20,6 +20,7 @@
 #include "locking.h"
 #include "rcu-string.h"
 #include "backref.h"
+#include "transaction.h"
 
 static struct kmem_cache *extent_state_cache;
 static struct kmem_cache *extent_buffer_cache;
@@ -4487,11 +4488,24 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                        flags |= (FIEMAP_EXTENT_DELALLOC |
                                  FIEMAP_EXTENT_UNKNOWN);
                } else if (fieinfo->fi_extents_max) {
+                       struct btrfs_trans_handle *trans;
+
                        u64 bytenr = em->block_start -
                                (em->start - em->orig_start);
 
                        disko = em->block_start + offset_in_extent;
 
+                       /*
+                        * We need a trans handle to get delayed refs
+                        */
+                       trans = btrfs_join_transaction(root);
+                       /*
+                        * It's OK if we can't start a trans we can still check
+                        * from commit_root
+                        */
+                       if (IS_ERR(trans))
+                               trans = NULL;
+
                        /*
                         * As btrfs supports shared space, this information
                         * can be exported to userspace tools via
@@ -4499,9 +4513,11 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                         * then we're just getting a count and we can skip the
                         * lookup stuff.
                         */
-                       ret = btrfs_check_shared(NULL, root->fs_info,
+                       ret = btrfs_check_shared(trans, root->fs_info,
                                                 root->objectid,
                                                 btrfs_ino(inode), bytenr);
+                       if (trans)
+                               btrfs_end_transaction(trans, root);
                        if (ret < 0)
                                goto out_free;
                        if (ret)