btrfs 0.1.0.1 → 0.1.1.0
raw patch · 10 files changed
+215/−18 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ System.Linux.Btrfs: DefragRangeArgs :: FileSize -> FileSize -> Word32 -> Maybe CompressionType -> Bool -> DefragRangeArgs
+ System.Linux.Btrfs: LZO :: CompressionType
+ System.Linux.Btrfs: Zlib :: CompressionType
+ System.Linux.Btrfs: data CompressionType
+ System.Linux.Btrfs: data DefragRangeArgs
+ System.Linux.Btrfs: defaultDefragRangeArgs :: DefragRangeArgs
+ System.Linux.Btrfs: defragRange :: FilePath -> DefragRangeArgs -> IO ()
+ System.Linux.Btrfs: defragRangeFd :: Fd -> DefragRangeArgs -> IO ()
+ System.Linux.Btrfs: draCompress :: DefragRangeArgs -> Maybe CompressionType
+ System.Linux.Btrfs: draExtentThreshold :: DefragRangeArgs -> Word32
+ System.Linux.Btrfs: draFlush :: DefragRangeArgs -> Bool
+ System.Linux.Btrfs: draLength :: DefragRangeArgs -> FileSize
+ System.Linux.Btrfs: draStart :: DefragRangeArgs -> FileSize
+ System.Linux.Btrfs: instance Bounded CompressionType
+ System.Linux.Btrfs: instance Enum CompressionType
+ System.Linux.Btrfs: instance Eq CompressionType
+ System.Linux.Btrfs: instance Read CompressionType
+ System.Linux.Btrfs: instance Show CompressionType
+ System.Linux.Btrfs.ByteString: DefragRangeArgs :: FileSize -> FileSize -> Word32 -> Maybe CompressionType -> Bool -> DefragRangeArgs
+ System.Linux.Btrfs.ByteString: LZO :: CompressionType
+ System.Linux.Btrfs.ByteString: Zlib :: CompressionType
+ System.Linux.Btrfs.ByteString: data CompressionType
+ System.Linux.Btrfs.ByteString: data DefragRangeArgs
+ System.Linux.Btrfs.ByteString: defaultDefragRangeArgs :: DefragRangeArgs
+ System.Linux.Btrfs.ByteString: defragRange :: RawFilePath -> DefragRangeArgs -> IO ()
+ System.Linux.Btrfs.ByteString: defragRangeFd :: Fd -> DefragRangeArgs -> IO ()
+ System.Linux.Btrfs.ByteString: draCompress :: DefragRangeArgs -> Maybe CompressionType
+ System.Linux.Btrfs.ByteString: draExtentThreshold :: DefragRangeArgs -> Word32
+ System.Linux.Btrfs.ByteString: draFlush :: DefragRangeArgs -> Bool
+ System.Linux.Btrfs.ByteString: draLength :: DefragRangeArgs -> FileSize
+ System.Linux.Btrfs.ByteString: draStart :: DefragRangeArgs -> FileSize
+ System.Linux.Btrfs.ByteString: instance Bounded CompressionType
+ System.Linux.Btrfs.ByteString: instance Enum CompressionType
+ System.Linux.Btrfs.ByteString: instance Eq CompressionType
+ System.Linux.Btrfs.ByteString: instance Read CompressionType
+ System.Linux.Btrfs.ByteString: instance Show CompressionType
Files
- ChangeLog +3/−0
- System/Linux/Btrfs.hsc +68/−6
- System/Linux/Btrfs/ByteString.hsc +68/−6
- System/Linux/Btrfs/UUID.hs +1/−1
- btrfs.cabal +4/−2
- include/btrfs/ctree.h +12/−0
- include/btrfs/ioctl.h +3/−1
- include/btrfs/kerncompat.h +5/−1
- include/missing.h +48/−0
- make-bytestring.hs +3/−1
+ ChangeLog view
@@ -0,0 +1,3 @@+v0.1.1.0++ * Support defraging file ranges.
System/Linux/Btrfs.hsc view
@@ -11,6 +11,7 @@ -} {-# LANGUAGE CPP #-}+{-# LANGUAGE RecordWildCards #-} #if BTRFS_RAW_PATHS ##define FILEPATH RawFilePath@@ -21,7 +22,7 @@ #endif ( -- * Basic types- FileSize, ObjectType, ObjectId, InodeNum, SubvolId+ FileSize, ObjectType, ObjectId, InodeNum, SubvolId, CompressionType(..) -- * File cloning , cloneFd, clone, cloneNew , cloneRangeFd, cloneRange@@ -47,6 +48,8 @@ , getSubvolByReceivedUuidFd, getSubvolByReceivedUuid -- * Defragging , defragFd, defrag+ , DefragRangeArgs(..), defaultDefragRangeArgs+ , defragRangeFd, defragRange -- * Sync , syncFd, sync , startSyncFd, startSync@@ -90,9 +93,9 @@ import System.Linux.Btrfs.Time import System.Linux.Btrfs.UUID -#include <linux/btrfs.h>-#define __IOCTL_+#include <btrfs/ioctl.h> #include <btrfs/ctree.h>+#include <missing.h> #include <linux/fs.h> @@ -111,6 +114,9 @@ type SubvolId = ObjectId +data CompressionType = Zlib | LZO+ deriving (Show, Read, Eq, Enum, Bounded)+ -------------------------------------------------------------------------------- cloneFd :: Fd -> Fd -> IO ()@@ -325,7 +331,7 @@ snapshot :: FILEPATH -- ^ The source subvolume. -> FILEPATH -- ^ The destination subvolume (must not exist).- -> Bool -- ^ Make the subvolume read-only?+ -> Bool -- ^ Create a read-only snapshot? -> IO () snapshot srcPath dstPath readOnly = withFd srcPath ReadOnly $ \srcFd ->@@ -680,6 +686,62 @@ defrag :: FILEPATH -> IO () defrag path = withFd path ReadWrite defragFd +-- | Argument to the 'defragRange' operation.+data DefragRangeArgs = DefragRangeArgs+ { draStart :: FileSize+ -- ^ Beginning of the defrag range.+ , draLength :: FileSize+ -- ^ Number of bytes to defrag, use 'maxBound' to say all.+ , draExtentThreshold :: Word32+ -- ^ Any extent bigger than this size will be considered already+ -- defragged. Use 0 to take the kernel default, use 1 to say every+ -- single extent must be rewritten.+ , draCompress :: Maybe CompressionType+ -- ^ Compress the file while defragmenting.+ , draFlush :: Bool+ -- ^ Flush data to disk immediately after defragmenting.+ }++-- | Defaults for 'defragRange'. Selects the entire file, no compression,+-- and no flushing.+defaultDefragRangeArgs :: DefragRangeArgs+defaultDefragRangeArgs = DefragRangeArgs+ { draStart = 0+ , draLength = maxBound+ , draExtentThreshold = 0+ , draCompress = Nothing+ , draFlush = False+ }++defragRangeFd :: Fd -> DefragRangeArgs -> IO ()+defragRangeFd fd DefragRangeArgs{..} =+ allocaBytesZero (#size struct btrfs_ioctl_defrag_range_args) $ \args -> do+ (#poke struct btrfs_ioctl_defrag_range_args, start ) args draStart+ (#poke struct btrfs_ioctl_defrag_range_args, len ) args draLength+ (#poke struct btrfs_ioctl_defrag_range_args, flags ) args flags+ (#poke struct btrfs_ioctl_defrag_range_args, extent_thresh) args draExtentThreshold+ (#poke struct btrfs_ioctl_defrag_range_args, compress_type) args comp_type+ throwErrnoIfMinus1_ "defragRangeFd" $+ withBlockSIGVTALRM $ -- this is probably a bad idea+ ioctl fd (#const BTRFS_IOC_DEFRAG_RANGE) args+ where+ flags = comp_flags .|. if draFlush then (#const BTRFS_DEFRAG_RANGE_START_IO) else 0+ comp_flags :: Word64+ comp_type :: Word32+ (comp_flags, comp_type) =+ case draCompress of+ Nothing -> (0, 0)+ Just Zlib -> ((#const BTRFS_DEFRAG_RANGE_COMPRESS), (#const BTRFS_COMPRESS_ZLIB))+ Just LZO -> ((#const BTRFS_DEFRAG_RANGE_COMPRESS), (#const BTRFS_COMPRESS_LZO))++-- | Defrag a range within a single file.+--+-- Note: calls the @BTRFS_IOC_DEFRAG_RANGE@ @ioctl@.+defragRange :: FILEPATH -> DefragRangeArgs -> IO ()+defragRange path args =+ withFd path ReadWrite $ \fd ->+ defragRangeFd fd args+ -------------------------------------------------------------------------------- syncFd :: Fd -> IO ()@@ -772,7 +834,7 @@ fspathSize = 2 * 1024 + (#size struct btrfs_data_container) -- | Find the file path(s) given an inode number. Returns a list of file paths--- and an integer indicating the number of path found but not included in+-- and an integer indicating the number of paths found but not included in -- the resulting list. This is because of a limitation in the kernel (it -- will not return an arbitrarily large list). The paths returned are -- relative to the root of the subvolume.@@ -925,7 +987,7 @@ else do let shPtr' = itemPtr `plusPtr` fromIntegral (shLen sh) loopItems shPtr' (itemsFound - 1)- -- items are index by keys which are (objectId, iType, offset)+ -- items are indexed by keys which are (objectId, iType, offset) -- they are returned in lexicographical order wrt the keys nextKey (objectId, iType, offset) | offset < maxBound = Just (objectId, iType, offset + 1)
System/Linux/Btrfs/ByteString.hsc view
@@ -11,6 +11,7 @@ -} {-# LANGUAGE CPP #-}+{-# LANGUAGE RecordWildCards #-} #if BTRFS_RAW_PATHS ##define FILEPATH RawFilePath@@ -21,7 +22,7 @@ #endif ( -- * Basic types- FileSize, ObjectType, ObjectId, InodeNum, SubvolId+ FileSize, ObjectType, ObjectId, InodeNum, SubvolId, CompressionType(..) -- * File cloning , cloneFd, clone, cloneNew , cloneRangeFd, cloneRange@@ -47,6 +48,8 @@ , getSubvolByReceivedUuidFd, getSubvolByReceivedUuid -- * Defragging , defragFd, defrag+ , DefragRangeArgs(..), defaultDefragRangeArgs+ , defragRangeFd, defragRange -- * Sync , syncFd, sync , startSyncFd, startSync@@ -90,9 +93,9 @@ import System.Linux.Btrfs.Time import System.Linux.Btrfs.UUID -#include <linux/btrfs.h>-#define __IOCTL_+#include <btrfs/ioctl.h> #include <btrfs/ctree.h>+#include <missing.h> #include <linux/fs.h> @@ -111,6 +114,9 @@ type SubvolId = ObjectId +data CompressionType = Zlib | LZO+ deriving (Show, Read, Eq, Enum, Bounded)+ -------------------------------------------------------------------------------- cloneFd :: Fd -> Fd -> IO ()@@ -325,7 +331,7 @@ snapshot :: FILEPATH -- ^ The source subvolume. -> FILEPATH -- ^ The destination subvolume (must not exist).- -> Bool -- ^ Make the subvolume read-only?+ -> Bool -- ^ Create a read-only snapshot? -> IO () snapshot srcPath dstPath readOnly = withFd srcPath ReadOnly $ \srcFd ->@@ -680,6 +686,62 @@ defrag :: FILEPATH -> IO () defrag path = withFd path ReadWrite defragFd +-- | Argument to the 'defragRange' operation.+data DefragRangeArgs = DefragRangeArgs+ { draStart :: FileSize+ -- ^ Beginning of the defrag range.+ , draLength :: FileSize+ -- ^ Number of bytes to defrag, use 'maxBound' to say all.+ , draExtentThreshold :: Word32+ -- ^ Any extent bigger than this size will be considered already+ -- defragged. Use 0 to take the kernel default, use 1 to say every+ -- single extent must be rewritten.+ , draCompress :: Maybe CompressionType+ -- ^ Compress the file while defragmenting.+ , draFlush :: Bool+ -- ^ Flush data to disk immediately after defragmenting.+ }++-- | Defaults for 'defragRange'. Selects the entire file, no compression,+-- and no flushing.+defaultDefragRangeArgs :: DefragRangeArgs+defaultDefragRangeArgs = DefragRangeArgs+ { draStart = 0+ , draLength = maxBound+ , draExtentThreshold = 0+ , draCompress = Nothing+ , draFlush = False+ }++defragRangeFd :: Fd -> DefragRangeArgs -> IO ()+defragRangeFd fd DefragRangeArgs{..} =+ allocaBytesZero (#size struct btrfs_ioctl_defrag_range_args) $ \args -> do+ (#poke struct btrfs_ioctl_defrag_range_args, start ) args draStart+ (#poke struct btrfs_ioctl_defrag_range_args, len ) args draLength+ (#poke struct btrfs_ioctl_defrag_range_args, flags ) args flags+ (#poke struct btrfs_ioctl_defrag_range_args, extent_thresh) args draExtentThreshold+ (#poke struct btrfs_ioctl_defrag_range_args, compress_type) args comp_type+ throwErrnoIfMinus1_ "defragRangeFd" $+ withBlockSIGVTALRM $ -- this is probably a bad idea+ ioctl fd (#const BTRFS_IOC_DEFRAG_RANGE) args+ where+ flags = comp_flags .|. if draFlush then (#const BTRFS_DEFRAG_RANGE_START_IO) else 0+ comp_flags :: Word64+ comp_type :: Word32+ (comp_flags, comp_type) =+ case draCompress of+ Nothing -> (0, 0)+ Just Zlib -> ((#const BTRFS_DEFRAG_RANGE_COMPRESS), (#const BTRFS_COMPRESS_ZLIB))+ Just LZO -> ((#const BTRFS_DEFRAG_RANGE_COMPRESS), (#const BTRFS_COMPRESS_LZO))++-- | Defrag a range within a single file.+--+-- Note: calls the @BTRFS_IOC_DEFRAG_RANGE@ @ioctl@.+defragRange :: FILEPATH -> DefragRangeArgs -> IO ()+defragRange path args =+ withFd path ReadWrite $ \fd ->+ defragRangeFd fd args+ -------------------------------------------------------------------------------- syncFd :: Fd -> IO ()@@ -772,7 +834,7 @@ fspathSize = 2 * 1024 + (#size struct btrfs_data_container) -- | Find the file path(s) given an inode number. Returns a list of file paths--- and an integer indicating the number of path found but not included in+-- and an integer indicating the number of paths found but not included in -- the resulting list. This is because of a limitation in the kernel (it -- will not return an arbitrarily large list). The paths returned are -- relative to the root of the subvolume.@@ -925,7 +987,7 @@ else do let shPtr' = itemPtr `plusPtr` fromIntegral (shLen sh) loopItems shPtr' (itemsFound - 1)- -- items are index by keys which are (objectId, iType, offset)+ -- items are indexed by keys which are (objectId, iType, offset) -- they are returned in lexicographical order wrt the keys nextKey (objectId, iType, offset) | offset < maxBound = Just (objectId, iType, offset + 1)
System/Linux/Btrfs/UUID.hs view
@@ -13,7 +13,6 @@ import Foreign.Ptr (castPtr) import Foreign.C.Types (CInt) --- | A @UUID@ is stored as two big-endian 'Word64's. data UUID = UUID Word64 Word64 deriving (Eq, Ord) @@ -22,6 +21,7 @@ showParen (p > 9) $ showString "fromString " . shows (toString u) +-- | A @UUID@ is stored as two big-endian 'Word64's. instance Storable UUID where sizeOf _ = 16 alignment _ = alignment (undefined :: CInt)
btrfs.cabal view
@@ -1,5 +1,5 @@ name: btrfs-version: 0.1.0.1+version: 0.1.1.0 synopsis: Bindings to the btrfs API description: This package provides low-level bindings to the btrfs API (i.e. the@@ -7,7 +7,7 @@ supported, including functions needed to work with subvolumes/snapshots as well as file cloning. .- In order to build this package, you need to @linux-headers 3.9@ or newer.+ In order to build this package, @linux-headers@ need to be installed. . Warning: btrfs is still considered experimental. This module is also experimental and may contain serious bugs that may result in data loss.@@ -23,6 +23,8 @@ cabal-version: >=1.10 extra-source-files:+ ChangeLog+ include/missing.h include/btrfs/ctree.h include/btrfs/extent-cache.h include/btrfs/extent_io.h
include/btrfs/ctree.h view
@@ -40,6 +40,8 @@ struct btrfs_free_space_ctl; #define BTRFS_MAGIC 0x4D5F53665248425FULL /* ascii _BHRfS_M, no null */ +#define BTRFS_MAX_MIRRORS 3+ #define BTRFS_MAX_LEVEL 8 #define BTRFS_COMPAT_EXTENT_TREE_V0@@ -943,6 +945,7 @@ struct btrfs_root *chunk_root; struct btrfs_root *dev_root; struct btrfs_root *csum_root;+ struct btrfs_root *quota_root; struct rb_root fs_root_tree; @@ -988,6 +991,7 @@ unsigned int readonly:1; unsigned int on_restoring:1; unsigned int is_chunk_recover:1;+ unsigned int quota_enabled:1; int (*free_extent_hook)(struct btrfs_trans_handle *trans, struct btrfs_root *root,@@ -2382,4 +2386,12 @@ int btrfs_lookup_uuid_subvol_item(int fd, const u8 *uuid, u64 *subvol_id); int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid, u64 *subvol_id);++static inline int is_fstree(u64 rootid)+{+ if (rootid == BTRFS_FS_TREE_OBJECTID ||+ (signed long long)rootid >= (signed long long)BTRFS_FIRST_FREE_OBJECTID)+ return 1;+ return 0;+} #endif
include/btrfs/ioctl.h view
@@ -194,7 +194,9 @@ __u64 flags; - __u64 unused[8];+ __u64 limit;++ __u64 unused[7]; } __attribute__ ((__packed__)); struct btrfs_balance_progress {
include/btrfs/kerncompat.h view
@@ -28,7 +28,11 @@ #include <assert.h> #include <stddef.h> #include <linux/types.h>+#include <stdint.h> +#define ptr_to_u64(x) ((u64)(uintptr_t)x)+#define u64_to_ptr(x) ((void *)(uintptr_t)x)+ #ifndef READ #define READ 0 #define WRITE 1@@ -235,7 +239,7 @@ #define BUG_ON(c) assert(!(c)) #define WARN_ON(c) assert(!(c))-+#define ASSERT(c) assert(c) #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ include/missing.h view
@@ -0,0 +1,48 @@+/*+ * Unfortunately, btrfs/ioctl.h (from btrfs-progs) and linux/btrfs.h (from+ * linux-headers) have some differences. We put here some parts that are+ * missing * from btrfs/ioctl.h.+ */++#ifndef MISSING_H+#define MISSING_H+#include <linux/types.h>+#include <linux/ioctl.h>++#ifdef __cplusplus+extern "C" {+#endif++#define BTRFS_SAME_DATA_DIFFERS 1++struct btrfs_ioctl_same_extent_info {+ __s64 fd; /* in - destination file */+ __u64 logical_offset; /* in - start of extent in destination */+ __u64 bytes_deduped; /* out - total # of bytes we were able+ * to dedupe from this file */+ /* status of this dedupe operation:+ * 0 if dedup succeeds+ * < 0 for error+ * == BTRFS_SAME_DATA_DIFFERS if data differs+ */+ __s32 status; /* out - see above description */+ __u32 reserved;+};++struct btrfs_ioctl_same_args {+ __u64 logical_offset; /* in - start of extent in source */+ __u64 length; /* in - length of extent */+ __u16 dest_count; /* in - total elements in info array */+ __u16 reserved1;+ __u32 reserved2;+ struct btrfs_ioctl_same_extent_info info[0];+};++#define BTRFS_IOC_FILE_EXTENT_SAME _IOWR(BTRFS_IOCTL_MAGIC, 54, \+ struct btrfs_ioctl_same_args)++#ifdef __cplusplus+}+#endif++#endif
make-bytestring.hs view
@@ -13,6 +13,8 @@ withFile "System/Linux/Btrfs/ByteString.hsc" WriteMode $ \oHdl -> do hPutStrLn oHdl "#define BTRFS_RAW_PATHS 1" withFile "System/Linux/Btrfs.hsc" ReadMode $ \iHdl -> do- _ <- hGetLine iHdl -- skip the first line+ s <- hGetLine iHdl -- skip the first line+ unless (s == "#define BTRFS_RAW_PATHS 0") $+ fail "the first line does not have the expected contents" contents <- hGetContents iHdl hPutStr oHdl contents