diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+v0.1.2.1
+
+	* Support cloneRangeIfSame on read-only subvolumes (requires
+	CAP_SYS_ADMIN).
+
 v0.1.2.0
 
 	* Expose System.Linux.Btrfs.Time.
diff --git a/System/Linux/Btrfs.hsc b/System/Linux/Btrfs.hsc
--- a/System/Linux/Btrfs.hsc
+++ b/System/Linux/Btrfs.hsc
@@ -23,7 +23,7 @@
     (
     -- * Basic types
       FileSize, ObjectType, ObjectId, InodeNum, SubvolId, CompressionType(..)
-    -- * File cloning
+    -- * File cloning/deduplication
     , cloneFd, clone, cloneNew
     , cloneRangeFd, cloneRange
     , CloneResult(..)
@@ -95,6 +95,7 @@
 import Data.Word.Endian
 import System.Linux.Btrfs.Time
 import System.Linux.Btrfs.UUID
+import System.Linux.Capabilities
 
 #include <btrfs/ioctl.h>
 #include <btrfs/ctree.h>
@@ -130,7 +131,7 @@
 
 -- | Clone an entire file to an existing file.
 --
--- Note: calls the @BTRFS_IOC_CLONE@ @ioctl@.
+-- Note: calls the @BTRFS_IOC_CLONE@/@FICLONE@ @ioctl@.
 clone
     :: FILEPATH -- ^ The source file.
     -> FILEPATH -- ^ The destination file.
@@ -143,7 +144,7 @@
 -- | Like 'clone' except that it will create or truncate the destination
 -- file if necessary. This is similar to @cp --reflink=always@.
 --
--- Note: calls the @BTRFS_IOC_CLONE@ @ioctl@.
+-- Note: calls the @BTRFS_IOC_CLONE@/@FICLONE@ @ioctl@.
 cloneNew :: FILEPATH -> FILEPATH -> IO ()
 cloneNew srcPath dstPath =
     withFd srcPath ReadOnly $ \srcFd -> do
@@ -165,7 +166,7 @@
 -- | Clones a range of bytes from a file to another file. All ranges must
 -- be block-aligned.
 --
--- Note: calls the @BTRFS_IOC_CLONE_RANGE@ @ioctl@.
+-- Note: calls the @BTRFS_IOC_CLONE_RANGE@/@FICLONERANGE@ @ioctl@.
 cloneRange
     :: FILEPATH -- ^ The source file.
     -> FileSize -- ^ The offset within the source file.
@@ -270,7 +271,7 @@
 -- function returns a list of outcomes, one for each destination file, and
 -- no exceptions will be raised for the failed files.
 --
--- Note: calls the @BTRFS_IOC_FILE_EXTENT_SAME@ @ioctl@.
+-- Note: calls the @BTRFS_IOC_FILE_EXTENT_SAME@/@FIDEDUPERANGE@ @ioctl@.
 --
 -- /Requires Linux 3.12 or later./
 cloneRangeIfSame
@@ -279,14 +280,19 @@
     -> FileSize               -- ^ The length of the range.
     -> [(FILEPATH, FileSize)] -- ^ The destination files and corresponding offsets.
     -> IO [CloneResult]
-cloneRangeIfSame srcPath srcOff srcLen dstsP0 =
+cloneRangeIfSame srcPath srcOff srcLen dstsP0 = do
+    -- we check if the process has the CAP_SYS_ADMIN capability
+    -- if it does we use ReadOnly to open the destination files
+    -- this allows privileged users to operate on readonly snapshots
+    isAdmin <- hasSysAdminCap
+    let openMode = if isAdmin then ReadOnly else WriteOnly
     withFd srcPath ReadOnly $ \srcFd ->
-        loop srcFd (reverse dstsP0) []
+        loop srcFd openMode (reverse dstsP0) []
   where
-    loop srcFd ((dstPath, dstOff) : dstsP) dsts =
-        withFd dstPath WriteOnly $ \fd ->
-            loop srcFd dstsP ((fd, dstOff) : dsts)
-    loop srcFd [] dsts =
+    loop srcFd openMode ((dstPath, dstOff) : dstsP) dsts =
+        withFd dstPath openMode $ \fd ->
+            loop srcFd openMode dstsP ((fd, dstOff) : dsts)
+    loop srcFd _ [] dsts =
         cloneRangeIfSameFd srcFd srcOff srcLen dsts
 
 --------------------------------------------------------------------------------
diff --git a/System/Linux/Btrfs/ByteString.hsc b/System/Linux/Btrfs/ByteString.hsc
--- a/System/Linux/Btrfs/ByteString.hsc
+++ b/System/Linux/Btrfs/ByteString.hsc
@@ -23,7 +23,7 @@
     (
     -- * Basic types
       FileSize, ObjectType, ObjectId, InodeNum, SubvolId, CompressionType(..)
-    -- * File cloning
+    -- * File cloning/deduplication
     , cloneFd, clone, cloneNew
     , cloneRangeFd, cloneRange
     , CloneResult(..)
@@ -95,6 +95,7 @@
 import Data.Word.Endian
 import System.Linux.Btrfs.Time
 import System.Linux.Btrfs.UUID
+import System.Linux.Capabilities
 
 #include <btrfs/ioctl.h>
 #include <btrfs/ctree.h>
@@ -130,7 +131,7 @@
 
 -- | Clone an entire file to an existing file.
 --
--- Note: calls the @BTRFS_IOC_CLONE@ @ioctl@.
+-- Note: calls the @BTRFS_IOC_CLONE@/@FICLONE@ @ioctl@.
 clone
     :: FILEPATH -- ^ The source file.
     -> FILEPATH -- ^ The destination file.
@@ -143,7 +144,7 @@
 -- | Like 'clone' except that it will create or truncate the destination
 -- file if necessary. This is similar to @cp --reflink=always@.
 --
--- Note: calls the @BTRFS_IOC_CLONE@ @ioctl@.
+-- Note: calls the @BTRFS_IOC_CLONE@/@FICLONE@ @ioctl@.
 cloneNew :: FILEPATH -> FILEPATH -> IO ()
 cloneNew srcPath dstPath =
     withFd srcPath ReadOnly $ \srcFd -> do
@@ -165,7 +166,7 @@
 -- | Clones a range of bytes from a file to another file. All ranges must
 -- be block-aligned.
 --
--- Note: calls the @BTRFS_IOC_CLONE_RANGE@ @ioctl@.
+-- Note: calls the @BTRFS_IOC_CLONE_RANGE@/@FICLONERANGE@ @ioctl@.
 cloneRange
     :: FILEPATH -- ^ The source file.
     -> FileSize -- ^ The offset within the source file.
@@ -270,7 +271,7 @@
 -- function returns a list of outcomes, one for each destination file, and
 -- no exceptions will be raised for the failed files.
 --
--- Note: calls the @BTRFS_IOC_FILE_EXTENT_SAME@ @ioctl@.
+-- Note: calls the @BTRFS_IOC_FILE_EXTENT_SAME@/@FIDEDUPERANGE@ @ioctl@.
 --
 -- /Requires Linux 3.12 or later./
 cloneRangeIfSame
@@ -279,14 +280,19 @@
     -> FileSize               -- ^ The length of the range.
     -> [(FILEPATH, FileSize)] -- ^ The destination files and corresponding offsets.
     -> IO [CloneResult]
-cloneRangeIfSame srcPath srcOff srcLen dstsP0 =
+cloneRangeIfSame srcPath srcOff srcLen dstsP0 = do
+    -- we check if the process has the CAP_SYS_ADMIN capability
+    -- if it does we use ReadOnly to open the destination files
+    -- this allows privileged users to operate on readonly snapshots
+    isAdmin <- hasSysAdminCap
+    let openMode = if isAdmin then ReadOnly else WriteOnly
     withFd srcPath ReadOnly $ \srcFd ->
-        loop srcFd (reverse dstsP0) []
+        loop srcFd openMode (reverse dstsP0) []
   where
-    loop srcFd ((dstPath, dstOff) : dstsP) dsts =
-        withFd dstPath WriteOnly $ \fd ->
-            loop srcFd dstsP ((fd, dstOff) : dsts)
-    loop srcFd [] dsts =
+    loop srcFd openMode ((dstPath, dstOff) : dstsP) dsts =
+        withFd dstPath openMode $ \fd ->
+            loop srcFd openMode dstsP ((fd, dstOff) : dsts)
+    loop srcFd _ [] dsts =
         cloneRangeIfSameFd srcFd srcOff srcLen dsts
 
 --------------------------------------------------------------------------------
diff --git a/System/Linux/Capabilities.hsc b/System/Linux/Capabilities.hsc
new file mode 100644
--- /dev/null
+++ b/System/Linux/Capabilities.hsc
@@ -0,0 +1,35 @@
+module System.Linux.Capabilities
+    ( hasSysAdminCap
+    ) where
+
+import Foreign
+import Foreign.C
+import System.Posix (getProcessID)
+
+#include <sys/capability.h>
+
+-- It's probably a bad idea to use the capget syscall instead of the
+-- functions from libcap, but this way we avoid the dependecy on libcap.
+
+hasSysAdminCap :: IO Bool
+hasSysAdminCap =
+    flip testBit (#const CAP_SYS_ADMIN) <$> getCapabilities
+
+getCapabilities :: IO Word64
+getCapabilities =
+    allocaBytes (#size struct __user_cap_header_struct) $ \hdrp ->
+    allocaBytes (2 * (#size struct __user_cap_data_struct)) $ \datap -> do
+        pid <- getProcessID
+        (#poke struct __user_cap_header_struct, version) hdrp ((#const _LINUX_CAPABILITY_VERSION_2) :: Word32)
+        (#poke struct __user_cap_header_struct, pid) hdrp (fromIntegral pid :: Word32)
+        throwErrnoIfMinus1_ "capget" $ c_capget hdrp datap
+        effective0 <- (#peek struct __user_cap_data_struct, effective) datap :: IO Word32
+        let datap1 = datap `plusPtr` (#size struct __user_cap_data_struct)
+        effective1 <- (#peek struct __user_cap_data_struct, effective) datap1 :: IO Word32
+        return (fromIntegral effective1 `unsafeShiftL` 32 .|. fromIntegral effective0)
+
+data CapUserHeader
+data CapUserData
+
+foreign import ccall unsafe "sys/capability.h capget"
+    c_capget :: Ptr CapUserHeader -> Ptr CapUserData -> IO CInt
diff --git a/btrfs.cabal b/btrfs.cabal
--- a/btrfs.cabal
+++ b/btrfs.cabal
@@ -1,5 +1,5 @@
 name:                btrfs
-version:             0.1.2.0
+version:             0.1.2.1
 synopsis:            Bindings to the btrfs API
 description:
   This package provides bindings to the low-level btrfs API (i.e. the
@@ -46,7 +46,8 @@
   exposed-modules:     System.Linux.Btrfs, System.Linux.Btrfs.ByteString,
                        System.Linux.Btrfs.UUID, System.Linux.Btrfs.Time
   other-modules:       Data.Word.Endian,
-                       System.Linux.Btrfs.FilePathLike
+                       System.Linux.Btrfs.FilePathLike,
+                       System.Linux.Capabilities
   build-depends:       base >=4.6 && <5, unix >=2.6,
                        time >=1.4, bytestring >=0.9
   include-dirs:        include
diff --git a/examples/btrfs-defrag.hs b/examples/btrfs-defrag.hs
--- a/examples/btrfs-defrag.hs
+++ b/examples/btrfs-defrag.hs
@@ -4,7 +4,6 @@
 import Control.Monad.Fix
 import Control.Exception
 import Control.Arrow ((***))
-import Data.Monoid
 import Data.IORef
 import Text.Printf
 import System.Posix
@@ -21,8 +20,8 @@
     hSetBuffering stdout LineBuffering
     hSetBuffering stderr LineBuffering
     paths <- getArgs
-    statsRef <- newIORef mempty
-    printStats mempty
+    statsRef <- newIORef zeroStats
+    printStats zeroStats
     mapM_ (flip traverseTree (defragFile statsRef)) paths
     putChar '\n'
 
@@ -30,18 +29,25 @@
 defragFile statsRef path stat
     | isRegularFile stat = do
         extBefore <- getExtentCount defReqFlags path Nothing
-        when (extBefore > 1) $ do -- skip files with 1 extent
-            handleIOExn $ defragRange path dra
-            extAfter  <- getExtentCount defReqFlags path Nothing
-            stats <- readIORef statsRef
-            let stats' = stats <> Stats
-                    { stFiles = 1
-                    , stBytes = fromIntegral (fileSize stat)
-                    , stExtentsBefore = fromIntegral extBefore
-                    , stExtentsAfter  = fromIntegral extAfter
+        stats <- readIORef statsRef
+        stats' <-
+            if extBefore <= 1 then
+                return $ stats
+                    { stSkippedFiles = stSkippedFiles stats + 1
+                    , stSkippedBytes =
+                        stSkippedBytes stats + fromIntegral (fileSize stat)
                     }
-            writeIORef statsRef stats'
-            printStats stats'
+            else do
+                handleIOExn $ defragRange path dra
+                extAfter  <- getExtentCount defReqFlags path Nothing
+                return $ stats
+                    { stFiles = stFiles stats + 1
+                    , stBytes = stBytes stats + fromIntegral (fileSize stat)
+                    , stExtentsBefore = stExtentsBefore stats + fromIntegral extBefore
+                    , stExtentsAfter  = stExtentsAfter stats + fromIntegral extAfter
+                    }
+        writeIORef statsRef stats'
+        printStats stats'
     | otherwise = return ()
   where
     dra = defaultDefragRangeArgs
@@ -78,20 +84,22 @@
 data Stats = Stats
     { stFiles :: !Int
     , stBytes :: !Integer
+    , stSkippedFiles :: !Int
+    , stSkippedBytes :: !Integer
     , stExtentsBefore :: !Int
     , stExtentsAfter  :: !Int
     }
 
-instance Monoid Stats where
-    mempty = Stats 0 0 0 0
-    mappend (Stats a1 b1 c1 d1) (Stats a2 b2 c2 d2) =
-        Stats (a1 + a2) (b1 + b2) (c1 + c2) (d1 + d2)
+zeroStats :: Stats
+zeroStats = Stats 0 0 0 0 0 0
 
 printStats :: Stats -> IO ()
 printStats Stats{..} = do
-    printf "\rprocessed: %d file(s)/%s, extents (before/after): %d/%d"
+    printf "\rprocessed: %d file(s)/%s, skipped: %d file(s)/%s, extents (before/after): %d/%d"
         stFiles
         (prettyFileSize stBytes)
+        stSkippedFiles
+        (prettyFileSize stSkippedBytes)
         stExtentsBefore
         stExtentsAfter
     clearFromCursorToLineEnd
diff --git a/include/btrfs/ctree.h b/include/btrfs/ctree.h
--- a/include/btrfs/ctree.h
+++ b/include/btrfs/ctree.h
@@ -173,7 +173,7 @@
 
 /*
  * the key defines the order in the tree, and so it also defines (optimal)
- * block layout.  objectid corresonds to the inode number.  The flags
+ * block layout.  objectid corresponds to the inode number.  The flags
  * tells us things about the object, and is a kind of stream selector.
  * so for a given inode, keys with flags of 1 might refer to the inode
  * data, flags of 2 may point to file data in the btree and flags == 3
@@ -229,7 +229,7 @@
 
 	/*
 	 * starting byte of this partition on the device,
-	 * to allowr for stripe alignment in the future
+	 * to allow for stripe alignment in the future
 	 */
 	__le64 start_offset;
 
@@ -345,7 +345,7 @@
 			        sizeof(struct btrfs_header)) / \
 			        sizeof(struct btrfs_key_ptr))
 #define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
-#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize))
+#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->nodesize))
 #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
 					sizeof(struct btrfs_item) - \
 					sizeof(struct btrfs_file_extent_item))
@@ -428,6 +428,7 @@
 	__le64 num_devices;
 	__le32 sectorsize;
 	__le32 nodesize;
+	/* Unused and must be equal to nodesize */
 	__le32 leafsize;
 	__le32 stripesize;
 	__le32 sys_chunk_array_size;
@@ -483,7 +484,8 @@
 
 #define BTRFS_FEATURE_COMPAT_SUPP		0ULL
 
-#define BTRFS_FEATURE_COMPAT_RO_SUPP		0ULL
+#define BTRFS_FEATURE_COMPAT_RO_SUPP			\
+	(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)
 
 #define BTRFS_FEATURE_INCOMPAT_SUPP			\
 	(BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF |		\
@@ -576,6 +578,7 @@
 
 #define BTRFS_MAX_EXTENT_ITEM_SIZE(r) ((BTRFS_LEAF_DATA_SIZE(r) >> 4) - \
 					sizeof(struct btrfs_item))
+#define BTRFS_MAX_EXTENT_SIZE		(128 * 1024 * 1024)
 
 #define BTRFS_EXTENT_FLAG_DATA		(1ULL << 0)
 #define BTRFS_EXTENT_FLAG_TREE_BLOCK	(1ULL << 1)
@@ -744,7 +747,7 @@
 
 	/*
 	 * This generation number is used to test if the new fields are valid
-	 * and up to date while reading the root item. Everytime the root item
+	 * and up to date while reading the root item. Every time the root item
 	 * is written out, the "generation" field is copied into this field. If
 	 * anyone ever mounted the fs with an older kernel, we will have
 	 * mismatching generation values here and thus must invalidate the
@@ -895,7 +898,7 @@
 	__le64 version;
 	__le64 generation;
 	__le64 flags;
-	__le64 scan;		/* progress during scanning */
+	__le64 rescan;		/* progress during scanning */
 } __attribute__ ((__packed__));
 
 struct btrfs_block_group_item {
@@ -957,13 +960,6 @@
 	int ro;
 };
 
-struct btrfs_extent_ops {
-       int (*alloc_extent)(struct btrfs_root *root, u64 num_bytes,
-			   u64 hint_byte, struct btrfs_key *ins, int metadata);
-       int (*free_extent)(struct btrfs_root *root, u64 bytenr,
-		          u64 num_bytes);
-};
-
 struct btrfs_device;
 struct btrfs_fs_devices;
 struct btrfs_fs_info {
@@ -1014,7 +1010,6 @@
 	u64 super_bytenr;
 	u64 total_pinned;
 
-	struct btrfs_extent_ops *extent_ops;
 	struct list_head dirty_cowonly_roots;
 	struct list_head recow_ebs;
 
@@ -1028,6 +1023,9 @@
 	unsigned int quota_enabled:1;
 	unsigned int suppress_check_block_errors:1;
 	unsigned int ignore_fsid_mismatch:1;
+	unsigned int ignore_chunk_tree_error:1;
+	unsigned int avoid_meta_chunk_alloc:1;
+	unsigned int avoid_sys_chunk_alloc:1;
 
 	int (*free_extent_hook)(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root,
@@ -1058,10 +1056,10 @@
 	/* node allocations are done in nodesize units */
 	u32 nodesize;
 
-	/* leaf allocations are done in leafsize units */
+	/* Unused, equal to nodesize */
 	u32 leafsize;
 
-	/* leaf allocations are done in leafsize units */
+	/* leaf allocations are done in nodesize units */
 	u32 stripesize;
 
 	int ref_cows;
@@ -2127,8 +2125,8 @@
 		   generation, 64);
 BTRFS_SETGET_FUNCS(qgroup_status_flags, struct btrfs_qgroup_status_item,
 		   flags, 64);
-BTRFS_SETGET_FUNCS(qgroup_status_scan, struct btrfs_qgroup_status_item,
-		   scan, 64);
+BTRFS_SETGET_FUNCS(qgroup_status_rescan, struct btrfs_qgroup_status_item,
+		   rescan, 64);
 
 BTRFS_SETGET_STACK_FUNCS(stack_qgroup_status_version,
 			 struct btrfs_qgroup_status_item, version, 64);
@@ -2136,8 +2134,8 @@
 			 struct btrfs_qgroup_status_item, generation, 64);
 BTRFS_SETGET_STACK_FUNCS(stack_qgroup_status_flags,
 			 struct btrfs_qgroup_status_item, flags, 64);
-BTRFS_SETGET_STACK_FUNCS(stack_qgroup_status_scan,
-			 struct btrfs_qgroup_status_item, scan, 64);
+BTRFS_SETGET_STACK_FUNCS(stack_qgroup_status_rescan,
+			 struct btrfs_qgroup_status_item, rescan, 64);
 
 /* btrfs_qgroup_info_item */
 BTRFS_SETGET_FUNCS(qgroup_info_generation, struct btrfs_qgroup_info_item,
@@ -2198,6 +2196,32 @@
        return btrfs_item_size(eb, e) - offset;
 }
 
+/* struct btrfs_ioctl_search_header */
+static inline u64 btrfs_search_header_transid(struct btrfs_ioctl_search_header *sh)
+{
+	return get_unaligned_64(&sh->transid);
+}
+
+static inline u64 btrfs_search_header_objectid(struct btrfs_ioctl_search_header *sh)
+{
+	return get_unaligned_64(&sh->objectid);
+}
+
+static inline u64 btrfs_search_header_offset(struct btrfs_ioctl_search_header *sh)
+{
+	return get_unaligned_64(&sh->offset);
+}
+
+static inline u32 btrfs_search_header_type(struct btrfs_ioctl_search_header *sh)
+{
+	return get_unaligned_32(&sh->type);
+}
+
+static inline u32 btrfs_search_header_len(struct btrfs_ioctl_search_header *sh)
+{
+	return get_unaligned_32(&sh->len);
+}
+
 /* this returns the number of file bytes represented by the inline item.
  * If an item is compressed, this is the uncompressed size
  */
@@ -2220,6 +2244,11 @@
 	return btrfs_file_extent_ram_bytes(eb, fi);
 }
 
+/*
+ * NOTE: Backward compatibility, do not use.
+ * Replacement: read nodesize directly
+ */
+__attribute__((deprecated))
 static inline u32 btrfs_level_size(struct btrfs_root *root, int level) {
 	if (level == 0)
 		return root->leafsize;
@@ -2354,6 +2383,8 @@
 			int type);
 int btrfs_previous_extent_item(struct btrfs_root *root,
 			struct btrfs_path *path, u64 min_objectid);
+int btrfs_next_extent_item(struct btrfs_root *root,
+			struct btrfs_path *path, u64 max_objectid);
 int btrfs_cow_block(struct btrfs_trans_handle *trans,
 		    struct btrfs_root *root, struct extent_buffer *buf,
 		    struct extent_buffer *parent, int parent_slot,
diff --git a/include/btrfs/extent-cache.h b/include/btrfs/extent-cache.h
--- a/include/btrfs/extent-cache.h
+++ b/include/btrfs/extent-cache.h
@@ -53,7 +53,7 @@
 struct cache_extent *search_cache_extent(struct cache_tree *tree, u64 start);
 
 /*
- * Find a cahce_extent which restrictly covers start.
+ * Find a cache_extent which restrictly covers start.
  *
  * If not found, return NULL.
  */
diff --git a/include/btrfs/extent_io.h b/include/btrfs/extent_io.h
--- a/include/btrfs/extent_io.h
+++ b/include/btrfs/extent_io.h
@@ -29,26 +29,45 @@
 #include <btrfs/list.h>
 #endif /* BTRFS_FLAT_INCLUDES */
 
-#define EXTENT_DIRTY 1
-#define EXTENT_WRITEBACK (1 << 1)
-#define EXTENT_UPTODATE (1 << 2)
-#define EXTENT_LOCKED (1 << 3)
-#define EXTENT_NEW (1 << 4)
-#define EXTENT_DELALLOC (1 << 5)
-#define EXTENT_DEFRAG (1 << 6)
-#define EXTENT_DEFRAG_DONE (1 << 7)
-#define EXTENT_BUFFER_FILLED (1 << 8)
-#define EXTENT_CSUM (1 << 9)
-#define EXTENT_BAD_TRANSID (1 << 10)
-#define EXTENT_BUFFER_DUMMY (1 << 11)
+#define EXTENT_DIRTY		(1U << 0)
+#define EXTENT_WRITEBACK	(1U << 1)
+#define EXTENT_UPTODATE		(1U << 2)
+#define EXTENT_LOCKED		(1U << 3)
+#define EXTENT_NEW		(1U << 4)
+#define EXTENT_DELALLOC		(1U << 5)
+#define EXTENT_DEFRAG		(1U << 6)
+#define EXTENT_DEFRAG_DONE	(1U << 7)
+#define EXTENT_BUFFER_FILLED	(1U << 8)
+#define EXTENT_CSUM		(1U << 9)
+#define EXTENT_BAD_TRANSID	(1U << 10)
+#define EXTENT_BUFFER_DUMMY	(1U << 11)
 #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
 
-#define BLOCK_GROUP_DATA     EXTENT_WRITEBACK
-#define BLOCK_GROUP_METADATA EXTENT_UPTODATE
-#define BLOCK_GROUP_SYSTEM   EXTENT_NEW
+#define BLOCK_GROUP_DATA	(1U << 1)
+#define BLOCK_GROUP_METADATA	(1U << 2)
+#define BLOCK_GROUP_SYSTEM	(1U << 4)
 
-#define BLOCK_GROUP_DIRTY EXTENT_DIRTY
+#define BLOCK_GROUP_DIRTY 	(1U)
 
+/*
+ * The extent buffer bitmap operations are done with byte granularity instead of
+ * word granularity for two reasons:
+ * 1. The bitmaps must be little-endian on disk.
+ * 2. Bitmap items are not guaranteed to be aligned to a word and therefore a
+ *    single word in a bitmap may straddle two pages in the extent buffer.
+ */
+#define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
+#define BYTE_MASK ((1 << BITS_PER_BYTE) - 1)
+#define BITMAP_FIRST_BYTE_MASK(start) \
+	((BYTE_MASK << ((start) & (BITS_PER_BYTE - 1))) & BYTE_MASK)
+#define BITMAP_LAST_BYTE_MASK(nbits) \
+	(BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1)))
+
+static inline int le_test_bit(int nr, const u8 *addr)
+{
+	return 1U & (addr[BIT_BYTE(nr)] >> (nr & (BITS_PER_BYTE-1)));
+}
+
 struct btrfs_fs_info;
 
 struct extent_io_tree {
@@ -76,7 +95,7 @@
 	struct list_head lru;
 	struct list_head recow;
 	int refs;
-	int flags;
+	u32 flags;
 	int fd;
 	char data[];
 };
diff --git a/include/btrfs/ioctl.h b/include/btrfs/ioctl.h
--- a/include/btrfs/ioctl.h
+++ b/include/btrfs/ioctl.h
@@ -45,6 +45,14 @@
 #define BTRFS_SUBVOL_CREATE_ASYNC	(1ULL << 0)
 #define BTRFS_SUBVOL_RDONLY		(1ULL << 1)
 #define BTRFS_SUBVOL_QGROUP_INHERIT	(1ULL << 2)
+#define BTRFS_DEVICE_SPEC_BY_ID		(1ULL << 3)
+
+#define BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED		\
+			(BTRFS_SUBVOL_CREATE_ASYNC |	\
+			BTRFS_SUBVOL_RDONLY |		\
+			BTRFS_SUBVOL_QGROUP_INHERIT |	\
+			BTRFS_DEVICE_SPEC_BY_ID)
+
 #define BTRFS_FSID_SIZE 16
 #define BTRFS_UUID_SIZE 16
 
@@ -84,7 +92,10 @@
 		};
 		__u64 unused[4];
 	};
-	char name[BTRFS_SUBVOL_NAME_MAX + 1];
+	union {
+		char name[BTRFS_SUBVOL_NAME_MAX + 1];
+		__u64 devid;
+	};
 };
 
 /*
@@ -98,7 +109,7 @@
 	__u64 tree_bytes_scrubbed;	/* # of tree bytes scrubbed */
 	__u64 read_errors;		/* # of read errors encountered (EIO) */
 	__u64 csum_errors;		/* # of failed csum checks */
-	__u64 verify_errors;		/* # of occurences, where the metadata
+	__u64 verify_errors;		/* # of occurrences, where the metadata
 					 * of a tree block did not match the
 					 * expected values, like generation or
 					 * logical */
@@ -118,7 +129,7 @@
 	__u64 last_physical;		/* last physical address scrubbed. In
 					 * case a scrub was aborted, this can
 					 * be used to restart the scrub */
-	__u64 unverified_errors;	/* # of occurences where a read for a
+	__u64 unverified_errors;	/* # of occurrences where a read for a
 					 * full (64k) bio failed, but the re-
 					 * check succeeded for each 4k piece.
 					 * Intermittent error. */
@@ -260,7 +271,7 @@
 /* report balance progress to userspace */
 struct btrfs_balance_progress {
 	__u64 expected;		/* estimated # of chunks that will be
-				 * relocated to fulfill the request */
+				 * relocated to fulfil the request */
 	__u64 considered;	/* # of chunks we have considered so far */
 	__u64 completed;	/* # of chunks relocated so far */
 };
@@ -674,7 +685,7 @@
 #define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
 					struct btrfs_ioctl_ino_path_args)
 #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
-					struct btrfs_ioctl_ino_path_args)
+					struct btrfs_ioctl_logical_ino_args)
 #define BTRFS_IOC_SET_RECEIVED_SUBVOL _IOWR(BTRFS_IOCTL_MAGIC, 37, \
 				struct btrfs_ioctl_received_subvol_args)
 #define BTRFS_IOC_SEND _IOW(BTRFS_IOCTL_MAGIC, 38, struct btrfs_ioctl_send_args)
@@ -709,6 +720,8 @@
                                   struct btrfs_ioctl_feature_flags[2])
 #define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \
                                   struct btrfs_ioctl_feature_flags[3])
+#define BTRFS_IOC_RM_DEV_V2	_IOW(BTRFS_IOCTL_MAGIC, 58, \
+				   struct btrfs_ioctl_vol_args_v2)
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/btrfs/kerncompat.h b/include/btrfs/kerncompat.h
--- a/include/btrfs/kerncompat.h
+++ b/include/btrfs/kerncompat.h
@@ -55,7 +55,8 @@
 #define gfp_t int
 #define get_cpu_var(p) (p)
 #define __get_cpu_var(p) (p)
-#define BITS_PER_LONG (__SIZEOF_LONG__ * 8)
+#define BITS_PER_BYTE 8
+#define BITS_PER_LONG (__SIZEOF_LONG__ * BITS_PER_BYTE)
 #define __GFP_BITS_SHIFT 20
 #define __GFP_BITS_MASK ((int)((1 << __GFP_BITS_SHIFT) - 1))
 #define GFP_KERNEL 0
@@ -72,7 +73,7 @@
 static inline void print_trace(void)
 {
 	void *array[MAX_BACKTRACE];
-	size_t size;
+	int size;
 
 	size = backtrace(array, MAX_BACKTRACE);
 	backtrace_symbols_fd(array, size, 2);
@@ -241,26 +242,6 @@
 }
 
 /*
- * max/min macro
- */
-#define min(x,y) ({ \
-	typeof(x) _x = (x);	\
-	typeof(y) _y = (y);	\
-	(void) (&_x == &_y);		\
-	_x < _y ? _x : _y; })
-
-#define max(x,y) ({ \
-	typeof(x) _x = (x);	\
-	typeof(y) _y = (y);	\
-	(void) (&_x == &_y);		\
-	_x > _y ? _x : _y; })
-
-#define min_t(type,x,y) \
-	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-#define max_t(type,x,y) \
-	({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
-
-/*
  * This looks more complex than it should be. But we need to
  * get the type for the ~ right in round_down (it needs to be
  * as wide as the result!), and we want to evaluate the macro
@@ -354,13 +335,21 @@
 struct __una_u64 { __le64 x; } __attribute__((__packed__));
 
 #define get_unaligned_le8(p) (*((u8 *)(p)))
+#define get_unaligned_8(p) (*((u8 *)(p)))
 #define put_unaligned_le8(val,p) ((*((u8 *)(p))) = (val))
+#define put_unaligned_8(val,p) ((*((u8 *)(p))) = (val))
 #define get_unaligned_le16(p) le16_to_cpu(((const struct __una_u16 *)(p))->x)
+#define get_unaligned_16(p) (((const struct __una_u16 *)(p))->x)
 #define put_unaligned_le16(val,p) (((struct __una_u16 *)(p))->x = cpu_to_le16(val))
+#define put_unaligned_16(val,p) (((struct __una_u16 *)(p))->x = (val))
 #define get_unaligned_le32(p) le32_to_cpu(((const struct __una_u32 *)(p))->x)
+#define get_unaligned_32(p) (((const struct __una_u32 *)(p))->x)
 #define put_unaligned_le32(val,p) (((struct __una_u32 *)(p))->x = cpu_to_le32(val))
+#define put_unaligned_32(val,p) (((struct __una_u32 *)(p))->x = (val))
 #define get_unaligned_le64(p) le64_to_cpu(((const struct __una_u64 *)(p))->x)
+#define get_unaligned_64(p) (((const struct __una_u64 *)(p))->x)
 #define put_unaligned_le64(val,p) (((struct __una_u64 *)(p))->x = cpu_to_le64(val))
+#define put_unaligned_64(val,p) (((struct __una_u64 *)(p))->x = (val))
 
 #ifndef true
 #define true 1
diff --git a/include/btrfs/rbtree.h b/include/btrfs/rbtree.h
--- a/include/btrfs/rbtree.h
+++ b/include/btrfs/rbtree.h
@@ -57,7 +57,7 @@
 
 #define RB_EMPTY_ROOT(root)  ((root)->rb_node == NULL)
 
-/* 'empty' nodes are nodes that are known not to be inserted in an rbree */
+/* 'empty' nodes are nodes that are known not to be inserted in an rtbree */
 #define RB_EMPTY_NODE(node)  \
 	((node)->__rb_parent_color == (unsigned long)(node))
 #define RB_CLEAR_NODE(node)  \
