diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+v0.1.2.3
+
+	* System.Linux.Btrfs.UUID.fromString did not handle all malformed
+	UUIDs correctly.
+
 v0.1.2.2
 
 	* Fix compilation error when libcap is not installed.
diff --git a/System/Linux/Btrfs.hsc b/System/Linux/Btrfs.hsc
--- a/System/Linux/Btrfs.hsc
+++ b/System/Linux/Btrfs.hsc
@@ -313,7 +313,10 @@
 createSubvol path =
     simpleSubvolOp "createSubvol" path (#const BTRFS_IOC_SUBVOL_CREATE)
 
--- | Destroy (delete) a subvolume.
+-- | Destroy (delete) a subvolume. The directory that corresponds to the
+-- subvolume is removed asynchronously. As a result, the subvolume may
+-- appear again after a crash. If this is not acceptable, call 'startSync'
+-- followed by a 'waitSync', after the @destroySubvol@ call.
 --
 -- Note: calls the @BTRFS_IOC_SNAP_DESTROY@ @ioctl@.
 destroySubvol :: FILEPATH -> IO ()
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
@@ -313,7 +313,10 @@
 createSubvol path =
     simpleSubvolOp "createSubvol" path (#const BTRFS_IOC_SUBVOL_CREATE)
 
--- | Destroy (delete) a subvolume.
+-- | Destroy (delete) a subvolume. The directory that corresponds to the
+-- subvolume is removed asynchronously. As a result, the subvolume may
+-- appear again after a crash. If this is not acceptable, call 'startSync'
+-- followed by a 'waitSync', after the @destroySubvol@ call.
 --
 -- Note: calls the @BTRFS_IOC_SNAP_DESTROY@ @ioctl@.
 destroySubvol :: FILEPATH -> IO ()
diff --git a/System/Linux/Btrfs/UUID.hs b/System/Linux/Btrfs/UUID.hs
--- a/System/Linux/Btrfs/UUID.hs
+++ b/System/Linux/Btrfs/UUID.hs
@@ -52,11 +52,11 @@
     s' = filter (/= '-') s
 
 isValidUUID :: String -> Bool
-isValidUUID = and . zipWith checkChar [0..]
+isValidUUID s = length s == 36 && and (zipWith checkChar [0..] s)
   where
     checkChar i c =
         if i `elem` hyphenPosns then
             c == '-'
         else
-            c `elem` "0123456789abcdefABCDEF"
+            ('0' <= c && c <= '9') || ('a' <= c && c <= 'f')|| ('A' <= c && c <= 'F')
     hyphenPosns = [8, 13, 18, 23] :: [Int]
diff --git a/btrfs.cabal b/btrfs.cabal
--- a/btrfs.cabal
+++ b/btrfs.cabal
@@ -1,5 +1,5 @@
 name:                btrfs
-version:             0.1.2.2
+version:             0.1.2.3
 synopsis:            Bindings to the btrfs API
 description:
   This package provides bindings to the low-level btrfs API (i.e. the
@@ -74,6 +74,16 @@
     buildable:           False
   else
     build-depends:       base >=4.6 && <5, btrfs
+    default-language:    Haskell2010
+    ghc-options:         -Wall
+
+executable btrfs-split
+  hs-source-dirs:      examples
+  main-is:             btrfs-split.hs
+  if !flag(examples)
+    buildable:           False
+  else
+    build-depends:       base >=4.6 && <5, btrfs, unix
     default-language:    Haskell2010
     ghc-options:         -Wall
 
diff --git a/examples/btrfs-clone-range.hs b/examples/btrfs-clone-range.hs
--- a/examples/btrfs-clone-range.hs
+++ b/examples/btrfs-clone-range.hs
@@ -1,9 +1,23 @@
-import System.Environment
+import System.Environment (getArgs, getProgName)
+import System.Exit (exitFailure)
+import System.IO (stderr, hPutStrLn)
+import Text.Read (readMaybe)
 
 import System.Linux.Btrfs
 
 main :: IO ()
 main = do
-    [srcPath, srcOff, srcLen, dstPath, dstOff] <- getArgs
-    cloneRange srcPath (read srcOff) (read srcLen)
-               dstPath (read dstOff)
+    args <- getArgs
+    case args of
+        [srcPath, srcOffS, srcLenS, dstPath, dstOffS]
+            | Just srcOff <- readMaybe srcOffS
+            , Just srcLen <- readMaybe srcLenS
+            , Just dstOff <- readMaybe dstOffS ->
+                cloneRange srcPath srcOff srcLen dstPath dstOff
+        _ -> do
+            prog <- getProgName
+            hPutStrLn stderr "Invalid command line arguments"
+            hPutStrLn stderr $
+                "Usage: " ++ prog ++
+                " SOURCE SOURCE_OFF SOURCE_LEN DEST DEST_OFF"
+            exitFailure
diff --git a/examples/btrfs-split.hs b/examples/btrfs-split.hs
new file mode 100644
--- /dev/null
+++ b/examples/btrfs-split.hs
@@ -0,0 +1,47 @@
+import System.Environment (getArgs, getProgName)
+import System.Exit (exitFailure)
+import System.IO (stderr, hPutStrLn)
+import Text.Read (readMaybe)
+import Text.Printf (printf)
+import Control.Exception (bracket)
+import Data.Function (fix)
+import Control.Monad (when)
+import System.Posix
+
+import System.Linux.Btrfs (cloneRangeFd)
+
+main :: IO ()
+main = do
+    args <- getArgs
+    case args of
+        [srcPath, sizeS, prefix] | Just size <- readMaybe sizeS, size > 0 ->
+            withReadFd srcPath $ \srcFd -> do
+                stat <- getFdStatus srcFd
+                let totSize = fromIntegral $ fileSize stat
+                    mode = fileMode stat
+                    lastN = (totSize - 1) `div` size
+                    formatStr = "%0" ++ show (length (show lastN)) ++ "d"
+                flip fix (0 :: Int, 0) $ \loop (n, offset) -> do
+                    let filename = prefix ++ printf formatStr n
+                        size' = min size (totSize - offset)
+                    withWriteFd filename mode $ \dstFd ->
+                        cloneRangeFd srcFd offset size' dstFd 0
+                    let offset' = offset + size'
+                    when (offset' < totSize) $ loop (n + 1, offset')
+        _ -> do
+            prog <- getProgName
+            hPutStrLn stderr "Invalid command line arguments"
+            hPutStrLn stderr $ "Usage: " ++ prog ++ " FILE SIZE PREFIX"
+            exitFailure
+
+withReadFd :: FilePath -> (Fd -> IO r) -> IO r
+withReadFd path action =
+    bracket
+        (openFd path ReadOnly Nothing defaultFileFlags {nonBlock = True})
+        closeFd action
+
+withWriteFd :: FilePath -> FileMode -> (Fd -> IO r) -> IO r
+withWriteFd path mode action =
+    bracket
+        (openFd path WriteOnly (Just mode) defaultFileFlags {trunc = True})
+        closeFd action
