btrfs 0.1.1.1 → 0.1.2.0
raw patch · 14 files changed
+745/−304 lines, 14 filesdep +ansi-terminaldep +linux-file-extentsnew-component:exe:btrfs-print-creation-timePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: ansi-terminal, linux-file-extents
API changes (from Hackage documentation)
- 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 CloneResult
- System.Linux.Btrfs: instance Eq CompressionType
- System.Linux.Btrfs: instance Eq DefragRangeArgs
- System.Linux.Btrfs: instance Eq SearchHeader
- System.Linux.Btrfs: instance Eq SearchKey
- System.Linux.Btrfs: instance Eq SubvolInfo
- System.Linux.Btrfs: instance Read CompressionType
- System.Linux.Btrfs: instance Show CloneResult
- System.Linux.Btrfs: instance Show CompressionType
- System.Linux.Btrfs: instance Show DefragRangeArgs
- System.Linux.Btrfs: instance Show SearchHeader
- System.Linux.Btrfs: instance Show SearchKey
- System.Linux.Btrfs: instance Show SubvolInfo
- System.Linux.Btrfs: instance Storable SameExtentInfoIn
- System.Linux.Btrfs: instance Storable SameExtentInfoOut
- System.Linux.Btrfs: shLen :: SearchHeader -> Word32
- System.Linux.Btrfs: shObjectId :: SearchHeader -> ObjectId
- System.Linux.Btrfs: shOffset :: SearchHeader -> Word64
- System.Linux.Btrfs: shTransId :: SearchHeader -> Word64
- System.Linux.Btrfs: shType :: SearchHeader -> ObjectType
- System.Linux.Btrfs: siCTime :: SubvolInfo -> Maybe UTCTime
- System.Linux.Btrfs: siCTransId :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs: siGeneration :: SubvolInfo -> Word64
- System.Linux.Btrfs: siLastSnapshot :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs: siOTime :: SubvolInfo -> Maybe UTCTime
- System.Linux.Btrfs: siOTransId :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs: siPUuid :: SubvolInfo -> Maybe UUID
- System.Linux.Btrfs: siParSnapGen :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs: siRTime :: SubvolInfo -> Maybe UTCTime
- System.Linux.Btrfs: siRTransId :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs: siReadOnly :: SubvolInfo -> Bool
- System.Linux.Btrfs: siReceivedUuid :: SubvolInfo -> Maybe UUID
- System.Linux.Btrfs: siSTime :: SubvolInfo -> Maybe UTCTime
- System.Linux.Btrfs: siSTransId :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs: siUuid :: SubvolInfo -> Maybe UUID
- System.Linux.Btrfs: skMaxObjectId :: SearchKey -> ObjectId
- System.Linux.Btrfs: skMaxOffset :: SearchKey -> Word64
- System.Linux.Btrfs: skMaxTransId :: SearchKey -> Word64
- System.Linux.Btrfs: skMaxType :: SearchKey -> ObjectType
- System.Linux.Btrfs: skMinObjectId :: SearchKey -> ObjectId
- System.Linux.Btrfs: skMinOffset :: SearchKey -> Word64
- System.Linux.Btrfs: skMinTransId :: SearchKey -> Word64
- System.Linux.Btrfs: skMinType :: SearchKey -> ObjectType
- System.Linux.Btrfs: skTreeId :: SearchKey -> ObjectId
- 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 CloneResult
- System.Linux.Btrfs.ByteString: instance Eq CompressionType
- System.Linux.Btrfs.ByteString: instance Eq DefragRangeArgs
- System.Linux.Btrfs.ByteString: instance Eq SearchHeader
- System.Linux.Btrfs.ByteString: instance Eq SearchKey
- System.Linux.Btrfs.ByteString: instance Eq SubvolInfo
- System.Linux.Btrfs.ByteString: instance Read CompressionType
- System.Linux.Btrfs.ByteString: instance Show CloneResult
- System.Linux.Btrfs.ByteString: instance Show CompressionType
- System.Linux.Btrfs.ByteString: instance Show DefragRangeArgs
- System.Linux.Btrfs.ByteString: instance Show SearchHeader
- System.Linux.Btrfs.ByteString: instance Show SearchKey
- System.Linux.Btrfs.ByteString: instance Show SubvolInfo
- System.Linux.Btrfs.ByteString: instance Storable SameExtentInfoIn
- System.Linux.Btrfs.ByteString: instance Storable SameExtentInfoOut
- System.Linux.Btrfs.ByteString: shLen :: SearchHeader -> Word32
- System.Linux.Btrfs.ByteString: shObjectId :: SearchHeader -> ObjectId
- System.Linux.Btrfs.ByteString: shOffset :: SearchHeader -> Word64
- System.Linux.Btrfs.ByteString: shTransId :: SearchHeader -> Word64
- System.Linux.Btrfs.ByteString: shType :: SearchHeader -> ObjectType
- System.Linux.Btrfs.ByteString: siCTime :: SubvolInfo -> Maybe UTCTime
- System.Linux.Btrfs.ByteString: siCTransId :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs.ByteString: siGeneration :: SubvolInfo -> Word64
- System.Linux.Btrfs.ByteString: siLastSnapshot :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs.ByteString: siOTime :: SubvolInfo -> Maybe UTCTime
- System.Linux.Btrfs.ByteString: siOTransId :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs.ByteString: siPUuid :: SubvolInfo -> Maybe UUID
- System.Linux.Btrfs.ByteString: siParSnapGen :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs.ByteString: siRTime :: SubvolInfo -> Maybe UTCTime
- System.Linux.Btrfs.ByteString: siRTransId :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs.ByteString: siReadOnly :: SubvolInfo -> Bool
- System.Linux.Btrfs.ByteString: siReceivedUuid :: SubvolInfo -> Maybe UUID
- System.Linux.Btrfs.ByteString: siSTime :: SubvolInfo -> Maybe UTCTime
- System.Linux.Btrfs.ByteString: siSTransId :: SubvolInfo -> Maybe Word64
- System.Linux.Btrfs.ByteString: siUuid :: SubvolInfo -> Maybe UUID
- System.Linux.Btrfs.ByteString: skMaxObjectId :: SearchKey -> ObjectId
- System.Linux.Btrfs.ByteString: skMaxOffset :: SearchKey -> Word64
- System.Linux.Btrfs.ByteString: skMaxTransId :: SearchKey -> Word64
- System.Linux.Btrfs.ByteString: skMaxType :: SearchKey -> ObjectType
- System.Linux.Btrfs.ByteString: skMinObjectId :: SearchKey -> ObjectId
- System.Linux.Btrfs.ByteString: skMinOffset :: SearchKey -> Word64
- System.Linux.Btrfs.ByteString: skMinTransId :: SearchKey -> Word64
- System.Linux.Btrfs.ByteString: skMinType :: SearchKey -> ObjectType
- System.Linux.Btrfs.ByteString: skTreeId :: SearchKey -> ObjectId
- System.Linux.Btrfs.UUID: instance Eq UUID
- System.Linux.Btrfs.UUID: instance Ord UUID
- System.Linux.Btrfs.UUID: instance Show UUID
- System.Linux.Btrfs.UUID: instance Storable UUID
+ 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: [shLen] :: SearchHeader -> Word32
+ System.Linux.Btrfs: [shObjectId] :: SearchHeader -> ObjectId
+ System.Linux.Btrfs: [shOffset] :: SearchHeader -> Word64
+ System.Linux.Btrfs: [shTransId] :: SearchHeader -> Word64
+ System.Linux.Btrfs: [shType] :: SearchHeader -> ObjectType
+ System.Linux.Btrfs: [siCTime] :: SubvolInfo -> Maybe UTCTime
+ System.Linux.Btrfs: [siCTransId] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs: [siGeneration] :: SubvolInfo -> Word64
+ System.Linux.Btrfs: [siLastSnapshot] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs: [siOTime] :: SubvolInfo -> Maybe UTCTime
+ System.Linux.Btrfs: [siOTransId] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs: [siPUuid] :: SubvolInfo -> Maybe UUID
+ System.Linux.Btrfs: [siParSnapGen] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs: [siRTime] :: SubvolInfo -> Maybe UTCTime
+ System.Linux.Btrfs: [siRTransId] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs: [siReadOnly] :: SubvolInfo -> Bool
+ System.Linux.Btrfs: [siReceivedUuid] :: SubvolInfo -> Maybe UUID
+ System.Linux.Btrfs: [siSTime] :: SubvolInfo -> Maybe UTCTime
+ System.Linux.Btrfs: [siSTransId] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs: [siUuid] :: SubvolInfo -> Maybe UUID
+ System.Linux.Btrfs: [skMaxObjectId] :: SearchKey -> ObjectId
+ System.Linux.Btrfs: [skMaxOffset] :: SearchKey -> Word64
+ System.Linux.Btrfs: [skMaxTransId] :: SearchKey -> Word64
+ System.Linux.Btrfs: [skMaxType] :: SearchKey -> ObjectType
+ System.Linux.Btrfs: [skMinObjectId] :: SearchKey -> ObjectId
+ System.Linux.Btrfs: [skMinOffset] :: SearchKey -> Word64
+ System.Linux.Btrfs: [skMinTransId] :: SearchKey -> Word64
+ System.Linux.Btrfs: [skMinType] :: SearchKey -> ObjectType
+ System.Linux.Btrfs: [skTreeId] :: SearchKey -> ObjectId
+ System.Linux.Btrfs: instance Foreign.Storable.Storable System.Linux.Btrfs.SameExtentInfoIn
+ System.Linux.Btrfs: instance Foreign.Storable.Storable System.Linux.Btrfs.SameExtentInfoOut
+ System.Linux.Btrfs: instance GHC.Classes.Eq System.Linux.Btrfs.CloneResult
+ System.Linux.Btrfs: instance GHC.Classes.Eq System.Linux.Btrfs.CompressionType
+ System.Linux.Btrfs: instance GHC.Classes.Eq System.Linux.Btrfs.DefragRangeArgs
+ System.Linux.Btrfs: instance GHC.Classes.Eq System.Linux.Btrfs.SearchHeader
+ System.Linux.Btrfs: instance GHC.Classes.Eq System.Linux.Btrfs.SearchKey
+ System.Linux.Btrfs: instance GHC.Classes.Eq System.Linux.Btrfs.SubvolInfo
+ System.Linux.Btrfs: instance GHC.Enum.Bounded System.Linux.Btrfs.CompressionType
+ System.Linux.Btrfs: instance GHC.Enum.Enum System.Linux.Btrfs.CompressionType
+ System.Linux.Btrfs: instance GHC.Read.Read System.Linux.Btrfs.CompressionType
+ System.Linux.Btrfs: instance GHC.Show.Show System.Linux.Btrfs.CloneResult
+ System.Linux.Btrfs: instance GHC.Show.Show System.Linux.Btrfs.CompressionType
+ System.Linux.Btrfs: instance GHC.Show.Show System.Linux.Btrfs.DefragRangeArgs
+ System.Linux.Btrfs: instance GHC.Show.Show System.Linux.Btrfs.SearchHeader
+ System.Linux.Btrfs: instance GHC.Show.Show System.Linux.Btrfs.SearchKey
+ System.Linux.Btrfs: instance GHC.Show.Show System.Linux.Btrfs.SubvolInfo
+ 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: [shLen] :: SearchHeader -> Word32
+ System.Linux.Btrfs.ByteString: [shObjectId] :: SearchHeader -> ObjectId
+ System.Linux.Btrfs.ByteString: [shOffset] :: SearchHeader -> Word64
+ System.Linux.Btrfs.ByteString: [shTransId] :: SearchHeader -> Word64
+ System.Linux.Btrfs.ByteString: [shType] :: SearchHeader -> ObjectType
+ System.Linux.Btrfs.ByteString: [siCTime] :: SubvolInfo -> Maybe UTCTime
+ System.Linux.Btrfs.ByteString: [siCTransId] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs.ByteString: [siGeneration] :: SubvolInfo -> Word64
+ System.Linux.Btrfs.ByteString: [siLastSnapshot] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs.ByteString: [siOTime] :: SubvolInfo -> Maybe UTCTime
+ System.Linux.Btrfs.ByteString: [siOTransId] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs.ByteString: [siPUuid] :: SubvolInfo -> Maybe UUID
+ System.Linux.Btrfs.ByteString: [siParSnapGen] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs.ByteString: [siRTime] :: SubvolInfo -> Maybe UTCTime
+ System.Linux.Btrfs.ByteString: [siRTransId] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs.ByteString: [siReadOnly] :: SubvolInfo -> Bool
+ System.Linux.Btrfs.ByteString: [siReceivedUuid] :: SubvolInfo -> Maybe UUID
+ System.Linux.Btrfs.ByteString: [siSTime] :: SubvolInfo -> Maybe UTCTime
+ System.Linux.Btrfs.ByteString: [siSTransId] :: SubvolInfo -> Maybe Word64
+ System.Linux.Btrfs.ByteString: [siUuid] :: SubvolInfo -> Maybe UUID
+ System.Linux.Btrfs.ByteString: [skMaxObjectId] :: SearchKey -> ObjectId
+ System.Linux.Btrfs.ByteString: [skMaxOffset] :: SearchKey -> Word64
+ System.Linux.Btrfs.ByteString: [skMaxTransId] :: SearchKey -> Word64
+ System.Linux.Btrfs.ByteString: [skMaxType] :: SearchKey -> ObjectType
+ System.Linux.Btrfs.ByteString: [skMinObjectId] :: SearchKey -> ObjectId
+ System.Linux.Btrfs.ByteString: [skMinOffset] :: SearchKey -> Word64
+ System.Linux.Btrfs.ByteString: [skMinTransId] :: SearchKey -> Word64
+ System.Linux.Btrfs.ByteString: [skMinType] :: SearchKey -> ObjectType
+ System.Linux.Btrfs.ByteString: [skTreeId] :: SearchKey -> ObjectId
+ System.Linux.Btrfs.ByteString: instance Foreign.Storable.Storable System.Linux.Btrfs.ByteString.SameExtentInfoIn
+ System.Linux.Btrfs.ByteString: instance Foreign.Storable.Storable System.Linux.Btrfs.ByteString.SameExtentInfoOut
+ System.Linux.Btrfs.ByteString: instance GHC.Classes.Eq System.Linux.Btrfs.ByteString.CloneResult
+ System.Linux.Btrfs.ByteString: instance GHC.Classes.Eq System.Linux.Btrfs.ByteString.CompressionType
+ System.Linux.Btrfs.ByteString: instance GHC.Classes.Eq System.Linux.Btrfs.ByteString.DefragRangeArgs
+ System.Linux.Btrfs.ByteString: instance GHC.Classes.Eq System.Linux.Btrfs.ByteString.SearchHeader
+ System.Linux.Btrfs.ByteString: instance GHC.Classes.Eq System.Linux.Btrfs.ByteString.SearchKey
+ System.Linux.Btrfs.ByteString: instance GHC.Classes.Eq System.Linux.Btrfs.ByteString.SubvolInfo
+ System.Linux.Btrfs.ByteString: instance GHC.Enum.Bounded System.Linux.Btrfs.ByteString.CompressionType
+ System.Linux.Btrfs.ByteString: instance GHC.Enum.Enum System.Linux.Btrfs.ByteString.CompressionType
+ System.Linux.Btrfs.ByteString: instance GHC.Read.Read System.Linux.Btrfs.ByteString.CompressionType
+ System.Linux.Btrfs.ByteString: instance GHC.Show.Show System.Linux.Btrfs.ByteString.CloneResult
+ System.Linux.Btrfs.ByteString: instance GHC.Show.Show System.Linux.Btrfs.ByteString.CompressionType
+ System.Linux.Btrfs.ByteString: instance GHC.Show.Show System.Linux.Btrfs.ByteString.DefragRangeArgs
+ System.Linux.Btrfs.ByteString: instance GHC.Show.Show System.Linux.Btrfs.ByteString.SearchHeader
+ System.Linux.Btrfs.ByteString: instance GHC.Show.Show System.Linux.Btrfs.ByteString.SearchKey
+ System.Linux.Btrfs.ByteString: instance GHC.Show.Show System.Linux.Btrfs.ByteString.SubvolInfo
+ System.Linux.Btrfs.Time: BtrfsTime :: UTCTime -> BtrfsTime
+ System.Linux.Btrfs.Time: instance Foreign.Storable.Storable System.Linux.Btrfs.Time.BtrfsTime
+ System.Linux.Btrfs.Time: newtype BtrfsTime
+ System.Linux.Btrfs.UUID: instance Foreign.Storable.Storable System.Linux.Btrfs.UUID.UUID
+ System.Linux.Btrfs.UUID: instance GHC.Classes.Eq System.Linux.Btrfs.UUID.UUID
+ System.Linux.Btrfs.UUID: instance GHC.Classes.Ord System.Linux.Btrfs.UUID.UUID
+ System.Linux.Btrfs.UUID: instance GHC.Show.Show System.Linux.Btrfs.UUID.UUID
Files
- ChangeLog +5/−0
- Data/Word/Endian.hs +16/−2
- System/Linux/Btrfs.hsc +2/−2
- System/Linux/Btrfs/ByteString.hsc +2/−2
- btrfs.cabal +19/−8
- examples/btrfs-defrag.hs +78/−10
- examples/btrfs-print-creation-time.hsc +43/−0
- include/btrfs/ctree.h +186/−15
- include/btrfs/extent-cache.h +42/−2
- include/btrfs/extent_io.h +28/−6
- include/btrfs/ioctl.h +198/−93
- include/btrfs/kerncompat.h +78/−4
- include/btrfs/rbtree.h +48/−112
- include/missing.h +0/−48
ChangeLog view
@@ -1,3 +1,8 @@+v0.1.2.0++ * Expose System.Linux.Btrfs.Time.+ * Add example program that prints the file creation timestamp.+ v0.1.1.1 * Support getting/setting the id of the default subvolume.
Data/Word/Endian.hs view
@@ -3,7 +3,11 @@ module Data.Word.Endian where import Data.Word (Word16, Word32, Word64)+#if MIN_VERSION_base(4,7,0)+import Data.Word (byteSwap16, byteSwap32, byteSwap64)+#else import Data.Bits (rotateL, unsafeShiftL, unsafeShiftR, (.&.), (.|.))+#endif import Foreign.Ptr (castPtr) import Foreign.Storable (Storable(..)) @@ -41,16 +45,25 @@ #endif invert16 :: Word16 -> Word16+invert32 :: Word32 -> Word32+invert64 :: Word64 -> Word64++#if MIN_VERSION_base(4,7,0)+invert16 = byteSwap16+{-# INLINE invert16 #-}+invert32 = byteSwap32+{-# INLINE invert32 #-}+invert64 = byteSwap64+{-# INLINE invert64 #-}+#else invert16 x = x `rotateL` 8 -invert32 :: Word32 -> Word32 invert32 x = ((x ) `unsafeShiftR` 24) .|. ((x .&. 0x00ff0000) `unsafeShiftR` 8) .|. ((x .&. 0x0000ff00) `unsafeShiftL` 8) .|. ((x ) `unsafeShiftL` 24) -invert64 :: Word64 -> Word64 invert64 x = ((x ) `unsafeShiftR` 56) .|. ((x .&. 0x00ff000000000000) `unsafeShiftR` 40) .|.@@ -60,3 +73,4 @@ ((x .&. 0x0000000000ff0000) `unsafeShiftL` 24) .|. ((x .&. 0x000000000000ff00) `unsafeShiftL` 40) .|. ((x ) `unsafeShiftL` 56)+#endif
System/Linux/Btrfs.hsc view
@@ -84,20 +84,20 @@ import Data.IORef import Data.Time.Clock (UTCTime) import Data.Monoid-import System.Linux.Btrfs.FilePathLike+import Prelude import Foreign import Foreign.C.Types import Foreign.C.String (CStringLen) import Foreign.C.Error +import System.Linux.Btrfs.FilePathLike import Data.Word.Endian import System.Linux.Btrfs.Time import System.Linux.Btrfs.UUID #include <btrfs/ioctl.h> #include <btrfs/ctree.h>-#include <missing.h> #include <linux/fs.h>
System/Linux/Btrfs/ByteString.hsc view
@@ -84,20 +84,20 @@ import Data.IORef import Data.Time.Clock (UTCTime) import Data.Monoid-import System.Linux.Btrfs.FilePathLike+import Prelude import Foreign import Foreign.C.Types import Foreign.C.String (CStringLen) import Foreign.C.Error +import System.Linux.Btrfs.FilePathLike import Data.Word.Endian import System.Linux.Btrfs.Time import System.Linux.Btrfs.UUID #include <btrfs/ioctl.h> #include <btrfs/ctree.h>-#include <missing.h> #include <linux/fs.h>
btrfs.cabal view
@@ -1,13 +1,13 @@ name: btrfs-version: 0.1.1.1+version: 0.1.2.0 synopsis: Bindings to the btrfs API description:- This package provides low-level bindings to the btrfs API (i.e. the+ This package provides bindings to the low-level btrfs API (i.e. the @BTRFS_IOC_@* @ioctl@s). Currently, only a subset of the API is- supported, including functions needed to work with subvolumes/snapshots+ supported, including all functions needed to work with subvolumes/snapshots as well as file cloning. .- In order to build this package, @linux-headers@ need to be installed.+ In order to build this package, @linux-headers@ needs 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.@@ -24,7 +24,6 @@ extra-source-files: ChangeLog- include/missing.h include/btrfs/ctree.h include/btrfs/extent-cache.h include/btrfs/extent_io.h@@ -45,8 +44,8 @@ library exposed-modules: System.Linux.Btrfs, System.Linux.Btrfs.ByteString,- System.Linux.Btrfs.UUID- other-modules: Data.Word.Endian, System.Linux.Btrfs.Time,+ System.Linux.Btrfs.UUID, System.Linux.Btrfs.Time+ other-modules: Data.Word.Endian, System.Linux.Btrfs.FilePathLike build-depends: base >=4.6 && <5, unix >=2.6, time >=1.4, bytestring >=0.9@@ -61,7 +60,8 @@ if !flag(examples) buildable: False else- build-depends: base >=4.6 && <5, btrfs, unix, filepath+ build-depends: base >=4.6 && <5, btrfs, unix, filepath,+ linux-file-extents, ansi-terminal default-language: Haskell2010 ghc-options: -Wall @@ -82,5 +82,16 @@ buildable: False else build-depends: base >=4.6 && <5, btrfs+ default-language: Haskell2010+ ghc-options: -Wall++executable btrfs-print-creation-time+ hs-source-dirs: examples+ include-dirs: include+ main-is: btrfs-print-creation-time.hs+ if !flag(examples)+ buildable: False+ else+ build-depends: base >=4.6 && <5, btrfs, unix >=2.6, time >=1.4 default-language: Haskell2010 ghc-options: -Wall
examples/btrfs-defrag.hs view
@@ -1,41 +1,109 @@+{-# LANGUAGE RecordWildCards #-}+ import Control.Monad import Control.Monad.Fix import Control.Exception+import Control.Arrow ((***))+import Data.Monoid+import Data.IORef+import Text.Printf import System.Posix import System.Environment import System.FilePath import System.IO+import System.Linux.FileExtents+import System.Console.ANSI import System.Linux.Btrfs main :: IO () main = do+ hSetBuffering stdout LineBuffering+ hSetBuffering stderr LineBuffering paths <- getArgs- mapM_ defragRec paths+ statsRef <- newIORef mempty+ printStats mempty+ mapM_ (flip traverseTree (defragFile statsRef)) paths+ putChar '\n' -defragRec :: FilePath -> IO ()-defragRec path0 =- traverseTree path0 $ \path stat ->- when (isRegularFile stat) $- handleIOExn $ defrag path+defragFile :: IORef Stats -> FilePath -> FileStatus -> IO ()+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+ }+ writeIORef statsRef stats'+ printStats stats'+ | otherwise = return ()+ where+ dra = defaultDefragRangeArgs+ { draExtentThreshold = 32 * 1024 * 1024+ , draFlush = True+ } traverseTree :: FilePath -> (FilePath -> FileStatus -> IO ()) -> IO () traverseTree path action = do stat <- getSymbolicLinkStatus path action path stat- when (isDirectory stat) $ do+ when (isDirectory stat) $ loopDir path $ \s -> traverseTree (path </> s) action loopDir :: FilePath -> (FilePath -> IO ()) -> IO ()-loopDir path action = do+loopDir path action = bracket (openDirStream path) closeDirStream $ \dir -> fix $ \loop -> do s <- readDirStream dir unless (null s) $ do- unless (s == "." || s == "..") $ action s+ unless (s == "." || s == "..") $+ action s loop handleIOExn :: IO () -> IO () handleIOExn =- handle (\e -> hPrint stderr (e :: IOException))+ handle $ \e -> do+ putChar '\r'+ clearFromCursorToLineEnd+ hFlush stdout+ hPrint stderr (e :: IOException)++data Stats = Stats+ { stFiles :: !Int+ , stBytes :: !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)++printStats :: Stats -> IO ()+printStats Stats{..} = do+ printf "\rprocessed: %d file(s)/%s, extents (before/after): %d/%d"+ stFiles+ (prettyFileSize stBytes)+ stExtentsBefore+ stExtentsAfter+ clearFromCursorToLineEnd+ hFlush stdout++prettyFileSize :: Integer -> String+prettyFileSize s+ | s < 1024 = printf "%d b" s+ | s' < 10 = printf "%.2f %ciB" s' c+ | s' < 100 = printf "%.1f %ciB" s' c+ | otherwise = printf "%.0f %ciB" s' c+ where+ (s', c : _) = until ((< 1024) . fst)+ ((/ 1024) *** tail)+ (fromIntegral s / 1024 :: Double, "KMGTPEZY")
+ examples/btrfs-print-creation-time.hsc view
@@ -0,0 +1,43 @@+import System.Environment (getArgs)+import Control.Monad (forM_)+import Foreign (peekByteOff)+import System.Posix (getFileStatus, fileID)+import Data.Time (UTCTime, utcToLocalZonedTime, zonedTimeToLocalTime)++import System.Linux.Btrfs+import System.Linux.Btrfs.Time++#include <btrfs/ctree.h>++{-+Starting with linux 4.0, btrfs records the creation time of inodes ("otime)+for all newly created inodes. Older kernel wrote 0 (i.e. the unix epoch) in+that field.+-}++main :: IO ()+main = do+ paths <- getArgs+ forM_ paths $ \path -> do+ t <- getOTime path >>= fmap zonedTimeToLocalTime . utcToLocalZonedTime+ let s = show t+ putStrLn $ s ++ replicate (30 - length s) ' ' ++ path++getOTime :: FilePath -> IO UTCTime+getOTime path = do+ subvolId <- getSubvol path+ inum <- fmap (fromIntegral . fileID) $ getFileStatus path+ getOTimeById subvolId inum++getOTimeById :: SubvolId -> InodeNum -> IO UTCTime+getOTimeById subvolId inum = do+ findFirstItem "/" sk $ \_ ptr -> do+ BtrfsTime t <- (#peek struct btrfs_inode_item, otime) ptr+ return t+ where+ sk = defaultSearchKey+ { skTreeId = subvolId+ , skMinObjectId = inum, skMinType = objType, skMinOffset = 0+ , skMaxObjectId = inum, skMaxType = objType, skMaxOffset = 0+ }+ objType = #const BTRFS_INODE_ITEM_KEY
include/btrfs/ctree.h view
@@ -16,8 +16,8 @@ * Boston, MA 021110-1307, USA. */ -#ifndef __BTRFS__-#define __BTRFS__+#ifndef __BTRFS_CTREE_H__+#define __BTRFS_CTREE_H__ #if BTRFS_FLAT_INCLUDES #include "list.h"@@ -76,6 +76,9 @@ /* for storing items that use the BTRFS_UUID_KEY* */ #define BTRFS_UUID_TREE_OBJECTID 9ULL +/* tracks free space in block groups. */+#define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL+ /* for storing balance parameters in the root tree */ #define BTRFS_BALANCE_OBJECTID -4ULL @@ -149,7 +152,7 @@ /* csum types */ #define BTRFS_CSUM_TYPE_CRC32 0 -static int btrfs_csum_sizes[] = { 4, 0 };+static int btrfs_csum_sizes[] = { 4 }; /* four bytes for CRC32 */ #define BTRFS_CRC32_SIZE 4@@ -309,6 +312,8 @@ #define BTRFS_HEADER_FLAG_RELOC (1ULL << 1) #define BTRFS_SUPER_FLAG_SEEDING (1ULL << 32) #define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33)+#define BTRFS_SUPER_FLAG_METADUMP_V2 (1ULL << 34)+#define BTRFS_SUPER_FLAG_CHANGING_FSID (1ULL << 35) #define BTRFS_BACKREF_REV_MAX 256 #define BTRFS_BACKREF_REV_SHIFT 56@@ -451,6 +456,8 @@ * Compat flags that we support. If any incompat flags are set other than the * ones specified below then we will fail to mount */+#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0)+ #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) #define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2)@@ -474,9 +481,10 @@ #define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8) #define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9) - #define BTRFS_FEATURE_COMPAT_SUPP 0ULL+ #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL+ #define BTRFS_FEATURE_INCOMPAT_SUPP \ (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \ BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \@@ -548,9 +556,6 @@ * and to force calls to keep space in the nodes */ unsigned int search_for_split:1;- unsigned int keep_locks:1;- unsigned int skip_locking:1;- unsigned int leave_spinning:1; unsigned int skip_check_block:1; }; @@ -845,9 +850,10 @@ #define BTRFS_BLOCK_GROUP_RAID1 (1ULL << 4) #define BTRFS_BLOCK_GROUP_DUP (1ULL << 5) #define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6)-#define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7)-#define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8)+#define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7)+#define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8) #define BTRFS_BLOCK_GROUP_RESERVED BTRFS_AVAIL_ALLOC_BIT_SINGLE+#define BTRFS_NR_RAID_TYPES 7 #define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | \ BTRFS_BLOCK_GROUP_SYSTEM | \@@ -863,12 +869,28 @@ /* used in struct btrfs_balance_args fields */ #define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48) -#define BTRFS_QGROUP_STATUS_OFF 0-#define BTRFS_QGROUP_STATUS_ON 1-#define BTRFS_QGROUP_STATUS_SCANNING 2+/*+ * GLOBAL_RSV does not exist as a on-disk block group type and is used+ * internally for exporting info about global block reserve from space infos+ */+#define BTRFS_SPACE_INFO_GLOBAL_RSV (1ULL << 49) -#define BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT (1 << 0)+#define BTRFS_QGROUP_LEVEL_SHIFT 48 +static inline u64 btrfs_qgroup_level(u64 qgroupid)+{+ return qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT;+}++static inline u64 btrfs_qgroup_subvid(u64 qgroupid)+{+ return qgroupid & ((1ULL << BTRFS_QGROUP_LEVEL_SHIFT) - 1);+}++#define BTRFS_QGROUP_STATUS_FLAG_ON (1ULL << 0)+#define BTRFS_QGROUP_STATUS_FLAG_RESCAN (1ULL << 1)+#define BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT (1ULL << 2)+ struct btrfs_qgroup_status_item { __le64 version; __le64 generation;@@ -882,6 +904,13 @@ __le64 flags; } __attribute__ ((__packed__)); +struct btrfs_free_space_info {+ __le32 extent_count;+ __le32 flags;+} __attribute__ ((__packed__));++#define BTRFS_FREE_SPACE_USING_BITMAPS (1ULL << 0)+ struct btrfs_qgroup_info_item { __le64 generation; __le64 referenced;@@ -921,6 +950,7 @@ struct btrfs_block_group_item item; struct btrfs_space_info *space_info; struct btrfs_free_space_ctl *free_space_ctl;+ u64 bytes_super; u64 pinned; u64 flags; int cached;@@ -929,7 +959,7 @@ struct btrfs_extent_ops { int (*alloc_extent)(struct btrfs_root *root, u64 num_bytes,- u64 hint_byte, struct btrfs_key *ins);+ u64 hint_byte, struct btrfs_key *ins, int metadata); int (*free_extent)(struct btrfs_root *root, u64 bytenr, u64 num_bytes); };@@ -938,7 +968,9 @@ struct btrfs_fs_devices; struct btrfs_fs_info { u8 fsid[BTRFS_FSID_SIZE];+ u8 *new_fsid; u8 chunk_tree_uuid[BTRFS_UUID_SIZE];+ u8 *new_chunk_tree_uuid; struct btrfs_root *fs_root; struct btrfs_root *extent_root; struct btrfs_root *tree_root;@@ -946,6 +978,7 @@ struct btrfs_root *dev_root; struct btrfs_root *csum_root; struct btrfs_root *quota_root;+ struct btrfs_root *free_space_root; struct rb_root fs_root_tree; @@ -958,6 +991,7 @@ struct extent_io_tree pinned_extents; struct extent_io_tree pending_del; struct extent_io_tree extent_ins;+ struct extent_io_tree *excluded_extents; /* logical->physical extent mapping */ struct btrfs_mapping_tree mapping_tree;@@ -992,6 +1026,8 @@ unsigned int on_restoring:1; unsigned int is_chunk_recover:1; unsigned int quota_enabled:1;+ unsigned int suppress_check_block_errors:1;+ unsigned int ignore_fsid_mismatch:1; int (*free_extent_hook)(struct btrfs_trans_handle *trans, struct btrfs_root *root,@@ -1000,6 +1036,7 @@ int refs_to_drop); struct cache_tree *fsck_extent_cache; struct cache_tree *corrupt_blocks;+ }; /*@@ -1035,6 +1072,16 @@ u64 highest_inode; u64 last_inode_alloc; + /*+ * Record orphan data extent ref+ *+ * TODO: Don't restore things in btrfs_root.+ * Directly record it into inode_record, which needs a lot of+ * infrastructure change to allow cooperation between extent+ * and fs tree scan.+ */+ struct list_head orphan_data_extents;+ /* the dirty list is only used by non-reference counted roots */ struct list_head dirty_list; struct rb_node rb_node;@@ -1124,6 +1171,27 @@ */ #define BTRFS_BLOCK_GROUP_ITEM_KEY 192 +/*+ * Every block group is represented in the free space tree by a free space info+ * item, which stores some accounting information. It is keyed on+ * (block_group_start, FREE_SPACE_INFO, block_group_length).+ */+#define BTRFS_FREE_SPACE_INFO_KEY 198++/*+ * A free space extent tracks an extent of space that is free in a block group.+ * It is keyed on (start, FREE_SPACE_EXTENT, length).+ */+#define BTRFS_FREE_SPACE_EXTENT_KEY 199++/*+ * When a block group becomes very fragmented, we convert it to use bitmaps+ * instead of extents. A free space bitmap is keyed on+ * (start, FREE_SPACE_BITMAP, length); the corresponding item is a bitmap with+ * (length / sectorsize) bits.+ */+#define BTRFS_FREE_SPACE_BITMAP_KEY 200+ #define BTRFS_DEV_EXTENT_KEY 204 #define BTRFS_DEV_ITEM_KEY 216 #define BTRFS_CHUNK_ITEM_KEY 228@@ -1361,6 +1429,11 @@ BTRFS_SETGET_STACK_FUNCS(block_group_flags, struct btrfs_block_group_item, flags, 64); +/* struct btrfs_free_space_info */+BTRFS_SETGET_FUNCS(free_space_extent_count, struct btrfs_free_space_info,+ extent_count, 32);+BTRFS_SETGET_FUNCS(free_space_flags, struct btrfs_free_space_info, flags, 32);+ /* struct btrfs_inode_ref */ BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16); BTRFS_SETGET_STACK_FUNCS(stack_inode_ref_name_len, struct btrfs_inode_ref, name_len, 16);@@ -1390,7 +1463,9 @@ BTRFS_SETGET_STACK_FUNCS(stack_inode_generation, struct btrfs_inode_item, generation, 64); BTRFS_SETGET_STACK_FUNCS(stack_inode_sequence,- struct btrfs_inode_item, generation, 64);+ struct btrfs_inode_item, sequence, 64);+BTRFS_SETGET_STACK_FUNCS(stack_inode_transid,+ struct btrfs_inode_item, transid, 64); BTRFS_SETGET_STACK_FUNCS(stack_inode_size, struct btrfs_inode_item, size, 64); BTRFS_SETGET_STACK_FUNCS(stack_inode_nbytes,@@ -1458,6 +1533,9 @@ chunk_offset, 64); BTRFS_SETGET_FUNCS(dev_extent_length, struct btrfs_dev_extent, length, 64); +BTRFS_SETGET_STACK_FUNCS(stack_dev_extent_length, struct btrfs_dev_extent,+ length, 64);+ static inline u8 *btrfs_dev_extent_chunk_tree_uuid(struct btrfs_dev_extent *dev) { unsigned long ptr = offsetof(struct btrfs_dev_extent, chunk_tree_uuid);@@ -2052,6 +2130,15 @@ BTRFS_SETGET_FUNCS(qgroup_status_scan, struct btrfs_qgroup_status_item, scan, 64); +BTRFS_SETGET_STACK_FUNCS(stack_qgroup_status_version,+ struct btrfs_qgroup_status_item, version, 64);+BTRFS_SETGET_STACK_FUNCS(stack_qgroup_status_generation,+ 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_qgroup_info_item */ BTRFS_SETGET_FUNCS(qgroup_info_generation, struct btrfs_qgroup_info_item, generation, 64);@@ -2146,6 +2233,13 @@ return !!(btrfs_super_incompat_flags(disk_super) & flag); } +static inline int btrfs_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag)+{+ struct btrfs_super_block *disk_super;+ disk_super = fs_info->super_copy;+ return !!(btrfs_super_compat_ro_flags(disk_super) & flag);+}+ /* helper function to cast into the data area of the leaf. */ #define btrfs_item_ptr(leaf, slot, type) \ ((type *)(btrfs_leaf_data(leaf) + \@@ -2233,6 +2327,14 @@ struct btrfs_inode_item *inode, u64 file_pos, u64 disk_bytenr, u64 num_bytes);+int btrfs_free_block_group(struct btrfs_trans_handle *trans,+ struct btrfs_fs_info *fs_info, u64 bytenr, u64 len);+void free_excluded_extents(struct btrfs_root *root,+ struct btrfs_block_group_cache *cache);+int exclude_super_stripes(struct btrfs_root *root,+ struct btrfs_block_group_cache *cache);+u64 add_new_free_space(struct btrfs_block_group_cache *block_group,+ struct btrfs_fs_info *info, u64 start, u64 end); /* ctree.c */ int btrfs_comp_cpu_keys(struct btrfs_key *k1, struct btrfs_key *k2); int btrfs_del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,@@ -2250,6 +2352,8 @@ int btrfs_previous_item(struct btrfs_root *root, struct btrfs_path *path, u64 min_objectid, int type);+int btrfs_previous_extent_item(struct btrfs_root *root,+ struct btrfs_path *path, u64 min_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,@@ -2278,6 +2382,9 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, struct btrfs_path *p, int ins_len, int cow);+int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *found_path,+ u64 iobjectid, u64 ioff, u8 key_type,+ struct btrfs_key *found_key); void btrfs_release_path(struct btrfs_path *p); void add_root_to_dirty_list(struct btrfs_root *root); struct btrfs_path *btrfs_alloc_path(void);@@ -2310,6 +2417,15 @@ } int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);+static inline int btrfs_next_item(struct btrfs_root *root,+ struct btrfs_path *p)+{+ ++p->slots[0];+ if (p->slots[0] >= btrfs_header_nritems(p->nodes[0]))+ return btrfs_next_leaf(root, p);+ return 0;+}+ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); void btrfs_fixup_low_keys(struct btrfs_root *root, struct btrfs_path *path,@@ -2343,6 +2459,15 @@ struct btrfs_path *path, u64 dir, const char *name, int name_len, int mod);+struct btrfs_dir_item *btrfs_lookup_dir_index(struct btrfs_trans_handle *trans,+ struct btrfs_root *root,+ struct btrfs_path *path, u64 dir,+ const char *name, int name_len,+ u64 index, int mod);+int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,+ struct btrfs_root *root,+ struct btrfs_path *path,+ struct btrfs_dir_item *di); int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, u16 name_len, const void *data, u16 data_len,@@ -2363,6 +2488,26 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *location, int mod);+struct btrfs_inode_extref *btrfs_lookup_inode_extref(struct btrfs_trans_handle+ *trans, struct btrfs_path *path, struct btrfs_root *root,+ u64 ino, u64 parent_ino, u64 index, const char *name,+ int namelen, int ins_len);+int btrfs_del_inode_extref(struct btrfs_trans_handle *trans,+ struct btrfs_root *root,+ const char *name, int name_len,+ u64 inode_objectid, u64 ref_objectid,+ u64 *index);+int btrfs_insert_inode_extref(struct btrfs_trans_handle *trans,+ struct btrfs_root *root,+ const char *name, int name_len,+ u64 inode_objectid, u64 ref_objectid, u64 index);+struct btrfs_inode_ref *btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans,+ struct btrfs_root *root, struct btrfs_path *path,+ const char *name, int namelen, u64 ino, u64 parent_ino,+ u64 index, int ins_len);+int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,+ struct btrfs_root *root, const char *name, int name_len,+ u64 ino, u64 parent_ino, u64 *index); /* file-item.c */ int btrfs_del_csums(struct btrfs_trans_handle *trans,@@ -2394,4 +2539,30 @@ return 1; return 0; }++/* inode.c */+int check_dir_conflict(struct btrfs_root *root, char *name, int namelen,+ u64 dir, u64 index);+int btrfs_new_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root,+ u64 ino, u32 mode);+int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_root *root,+ u64 ino, u64 parent_ino, char *name, int namelen,+ u8 type, u64 *index, int add_backref);+int btrfs_unlink(struct btrfs_trans_handle *trans, struct btrfs_root *root,+ u64 ino, u64 parent_ino, u64 index, const char *name,+ int namelen, int add_orphan);+int btrfs_add_orphan_item(struct btrfs_trans_handle *trans,+ struct btrfs_root *root, struct btrfs_path *path,+ u64 ino);+int btrfs_mkdir(struct btrfs_trans_handle *trans, struct btrfs_root *root,+ char *name, int namelen, u64 parent_ino, u64 *ino, int mode);++/* file.c */+int btrfs_get_extent(struct btrfs_trans_handle *trans,+ struct btrfs_root *root,+ struct btrfs_path *path,+ u64 ino, u64 offset, u64 len, int ins_len);+int btrfs_punch_hole(struct btrfs_trans_handle *trans,+ struct btrfs_root *root,+ u64 ino, u64 offset, u64 len); #endif
include/btrfs/extent-cache.h view
@@ -16,8 +16,8 @@ * Boston, MA 021110-1307, USA. */ -#ifndef __EXTENT_CACHE_H__-#define __EXTENT_CACHE_H__+#ifndef __BTRFS_EXTENT_CACHE_H__+#define __BTRFS_EXTENT_CACHE_H__ #if BTRFS_FLAT_INCLUDES #include "kerncompat.h"@@ -41,14 +41,35 @@ void cache_tree_init(struct cache_tree *tree); struct cache_extent *first_cache_extent(struct cache_tree *tree);+struct cache_extent *last_cache_extent(struct cache_tree *tree); struct cache_extent *prev_cache_extent(struct cache_extent *pe); struct cache_extent *next_cache_extent(struct cache_extent *pe); +/*+ * Find a cache_extent which covers start.+ *+ * If not found, return next cache_extent if possible.+ */ struct cache_extent *search_cache_extent(struct cache_tree *tree, u64 start);++/*+ * Find a cahce_extent which restrictly covers start.+ *+ * If not found, return NULL.+ */ struct cache_extent *lookup_cache_extent(struct cache_tree *tree, u64 start, u64 size); +/*+ * Add an non-overlap extent into cache tree+ *+ * If [start, start+size) overlap with existing one, it will return -EEXIST.+ */ int add_cache_extent(struct cache_tree *tree, u64 start, u64 size);++/*+ * Same with add_cache_extent, but with cache_extent strcut.+ */ int insert_cache_extent(struct cache_tree *tree, struct cache_extent *pe); void remove_cache_extent(struct cache_tree *tree, struct cache_extent *pe); @@ -70,12 +91,31 @@ void free_extent_cache_tree(struct cache_tree *tree); +/*+ * Search a cache_extent with same objectid, and covers start.+ *+ * If not found, return next if possible.+ */ struct cache_extent *search_cache_extent2(struct cache_tree *tree, u64 objectid, u64 start);+/*+ * Search a cache_extent with same objectid, and covers the range+ * [start, start + size)+ *+ * If not found, return next cache_extent if possible.+ */ struct cache_extent *lookup_cache_extent2(struct cache_tree *tree, u64 objectid, u64 start, u64 size); int add_cache_extent2(struct cache_tree *tree, u64 objectid, u64 start, u64 size); int insert_cache_extent2(struct cache_tree *tree, struct cache_extent *pe); +/*+ * Insert a cache_extent range [start, start + size).+ *+ * This function may merge with existing cache_extent.+ * NOTE: caller must ensure the inserted range won't cover with any existing+ * range.+ */+int add_merge_cache_extent(struct cache_tree *tree, u64 start, u64 size); #endif
include/btrfs/extent_io.h view
@@ -16,8 +16,8 @@ * Boston, MA 021110-1307, USA. */ -#ifndef __EXTENTMAP__-#define __EXTENTMAP__+#ifndef __BTRFS_EXTENT_IO_H__+#define __BTRFS_EXTENT_IO_H__ #if BTRFS_FLAT_INCLUDES #include "kerncompat.h"@@ -40,6 +40,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_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) #define BLOCK_GROUP_DATA EXTENT_WRITEBACK@@ -99,10 +100,28 @@ u64 end, gfp_t mask); int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask);-int extent_buffer_uptodate(struct extent_buffer *eb);-int set_extent_buffer_uptodate(struct extent_buffer *eb);-int clear_extent_buffer_uptodate(struct extent_io_tree *tree,- struct extent_buffer *eb);+static inline int set_extent_buffer_uptodate(struct extent_buffer *eb)+{+ eb->flags |= EXTENT_UPTODATE;+ return 0;+}++static inline int clear_extent_buffer_uptodate(struct extent_io_tree *tree,+ struct extent_buffer *eb)+{+ eb->flags &= ~EXTENT_UPTODATE;+ return 0;+}++static inline int extent_buffer_uptodate(struct extent_buffer *eb)+{+ if (!eb || IS_ERR(eb))+ return 0;+ if (eb->flags & EXTENT_UPTODATE)+ return 1;+ return 0;+}+ int set_state_private(struct extent_io_tree *tree, u64 start, u64 xprivate); int get_state_private(struct extent_io_tree *tree, u64 start, u64 *xprivate); struct extent_buffer *find_extent_buffer(struct extent_io_tree *tree,@@ -111,6 +130,7 @@ u64 start); struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, u64 bytenr, u32 blocksize);+struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src); void free_extent_buffer(struct extent_buffer *eb); int read_extent_from_disk(struct extent_buffer *eb, unsigned long offset, unsigned long len);@@ -128,6 +148,8 @@ unsigned long src_offset, unsigned long len); void memset_extent_buffer(struct extent_buffer *eb, char c, unsigned long start, unsigned long len);+int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,+ unsigned long nr); int set_extent_buffer_dirty(struct extent_buffer *eb); int clear_extent_buffer_dirty(struct extent_buffer *eb); int read_data_from_disk(struct btrfs_fs_info *info, void *buf, u64 offset,
include/btrfs/ioctl.h view
@@ -16,16 +16,20 @@ * Boston, MA 021110-1307, USA. */ -#ifndef __IOCTL_-#define __IOCTL_-#include <asm/types.h>-#include <linux/ioctl.h>-#include <time.h>+#ifndef __BTRFS_IOCTL_H__+#define __BTRFS_IOCTL_H__ #ifdef __cplusplus extern "C" { #endif +#include <asm/types.h>+#include <linux/ioctl.h>++#ifndef __user+#define __user+#endif+ #define BTRFS_IOCTL_MAGIC 0x94 #define BTRFS_VOL_NAME_MAX 255 @@ -41,6 +45,8 @@ #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) #define BTRFS_SUBVOL_RDONLY (1ULL << 1) #define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2)+#define BTRFS_FSID_SIZE 16+#define BTRFS_UUID_SIZE 16 #define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0) @@ -67,7 +73,6 @@ }; #define BTRFS_SUBVOL_NAME_MAX 4039- struct btrfs_ioctl_vol_args_v2 { __s64 fd; __u64 transid;@@ -75,32 +80,48 @@ union { struct { __u64 size;- struct btrfs_qgroup_inherit *qgroup_inherit;+ struct btrfs_qgroup_inherit __user *qgroup_inherit; }; __u64 unused[4]; }; char name[BTRFS_SUBVOL_NAME_MAX + 1]; }; -#define BTRFS_FSID_SIZE 16-#define BTRFS_UUID_SIZE 16-+/*+ * structure to report errors and progress to userspace, either as a+ * result of a finished scrub, a canceled scrub or a progress inquiry+ */ struct btrfs_scrub_progress {- __u64 data_extents_scrubbed;- __u64 tree_extents_scrubbed;- __u64 data_bytes_scrubbed;- __u64 tree_bytes_scrubbed;- __u64 read_errors;- __u64 csum_errors;- __u64 verify_errors;- __u64 no_csum;- __u64 csum_discards;- __u64 super_errors;- __u64 malloc_errors;- __u64 uncorrectable_errors;- __u64 corrected_errors;- __u64 last_physical;- __u64 unverified_errors;+ __u64 data_extents_scrubbed; /* # of data extents scrubbed */+ __u64 tree_extents_scrubbed; /* # of tree extents scrubbed */+ __u64 data_bytes_scrubbed; /* # of data bytes scrubbed */+ __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+ * of a tree block did not match the+ * expected values, like generation or+ * logical */+ __u64 no_csum; /* # of 4k data block for which no csum+ * is present, probably the result of+ * data written with nodatasum */+ __u64 csum_discards; /* # of csum for which no data was found+ * in the extent tree. */+ __u64 super_errors; /* # of bad super blocks encountered */+ __u64 malloc_errors; /* # of internal kmalloc errors. These+ * will likely cause an incomplete+ * scrub */+ __u64 uncorrectable_errors; /* # of errors where either no intact+ * copy was found or the writeback+ * failed */+ __u64 corrected_errors; /* # of errors corrected */+ __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+ * full (64k) bio failed, but the re-+ * check succeeded for each 4k piece.+ * Intermittent error. */ }; #define BTRFS_SCRUB_READONLY 1@@ -141,9 +162,11 @@ #define BTRFS_IOCTL_DEV_REPLACE_CMD_START 0 #define BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS 1 #define BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL 2+#define BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_RESULT -1 #define BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR 0 #define BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED 1 #define BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED 2+#define BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS 3 struct btrfs_ioctl_dev_replace_args { __u64 cmd; /* in */ __u64 result; /* out */@@ -169,9 +192,19 @@ __u64 max_id; /* out */ __u64 num_devices; /* out */ __u8 fsid[BTRFS_FSID_SIZE]; /* out */- __u64 reserved[124]; /* pad to 1k */+ __u32 nodesize; /* out */+ __u32 sectorsize; /* out */+ __u32 clone_alignment; /* out */+ __u32 reserved32;+ __u64 reserved[122]; /* pad to 1k */ }; +struct btrfs_ioctl_feature_flags {+ __u64 compat_flags;+ __u64 compat_ro_flags;+ __u64 incompat_flags;+};+ /* balance control ioctl modes */ #define BTRFS_BALANCE_CTL_PAUSE 1 #define BTRFS_BALANCE_CTL_CANCEL 2@@ -183,7 +216,20 @@ */ struct btrfs_balance_args { __u64 profiles;- __u64 usage;++ /*+ * usage filter+ * BTRFS_BALANCE_ARGS_USAGE with a single value means '0..N'+ * BTRFS_BALANCE_ARGS_USAGE_RANGE - range syntax, min..max+ */+ union {+ __u64 usage;+ struct {+ __u32 usage_min;+ __u32 usage_max;+ };+ };+ __u64 devid; __u64 pstart; __u64 pend;@@ -194,15 +240,29 @@ __u64 flags; - __u64 limit;-- __u64 unused[7];+ /*+ * BTRFS_BALANCE_ARGS_LIMIT with value 'limit'+ * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum+ * and maximum+ */+ union {+ __u64 limit; /* limit number of processed chunks */+ struct {+ __u32 limit_min;+ __u32 limit_max;+ };+ };+ __u32 stripes_min;+ __u32 stripes_max;+ __u64 unused[6]; } __attribute__ ((__packed__)); +/* report balance progress to userspace */ struct btrfs_balance_progress {- __u64 expected;- __u64 considered;- __u64 completed;+ __u64 expected; /* estimated # of chunks that will be+ * relocated to fulfill the request */+ __u64 considered; /* # of chunks we have considered so far */+ __u64 completed; /* # of chunks relocated so far */ }; #define BTRFS_BALANCE_STATE_RUNNING (1ULL << 0)@@ -222,6 +282,13 @@ __u64 unused[72]; /* pad to 1k */ }; +#define BTRFS_INO_LOOKUP_PATH_MAX 4080+struct btrfs_ioctl_ino_lookup_args {+ __u64 treeid;+ __u64 objectid;+ char name[BTRFS_INO_LOOKUP_PATH_MAX];+};+ struct btrfs_ioctl_search_key { /* which root are we searching. 0 is the tree of tree roots */ __u64 tree_id;@@ -277,17 +344,54 @@ char buf[BTRFS_SEARCH_ARGS_BUFSIZE]; }; -#define BTRFS_INO_LOOKUP_PATH_MAX 4080-struct btrfs_ioctl_ino_lookup_args {- __u64 treeid;- __u64 objectid;- char name[BTRFS_INO_LOOKUP_PATH_MAX];+/*+ * Extended version of TREE_SEARCH ioctl that can return more than 4k of bytes.+ * The allocated size of the buffer is set in buf_size.+ */+struct btrfs_ioctl_search_args_v2 {+ struct btrfs_ioctl_search_key key; /* in/out - search parameters */+ __u64 buf_size; /* in - size of buffer+ * out - on EOVERFLOW: needed size+ * to store item */+ __u64 buf[0]; /* out - found items */ }; +/* With a @src_length of zero, the range from @src_offset->EOF is cloned! */+struct btrfs_ioctl_clone_range_args {+ __s64 src_fd;+ __u64 src_offset, src_length;+ __u64 dest_offset;+};+ /* flags for the defrag range ioctl */ #define BTRFS_DEFRAG_RANGE_COMPRESS 1 #define BTRFS_DEFRAG_RANGE_START_IO 2 +#define BTRFS_SAME_DATA_DIFFERS 1+/* For extent-same ioctl */+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];+};+ struct btrfs_ioctl_defrag_range_args { /* start of the defrag operation */ __u64 start;@@ -355,50 +459,6 @@ __u64 inodes; }; -struct btrfs_ioctl_timespec {- __u64 sec;- __u32 nsec;-};--struct btrfs_ioctl_received_subvol_args {- char uuid[BTRFS_UUID_SIZE]; /* in */- __u64 stransid; /* in */- __u64 rtransid; /* out */- struct btrfs_ioctl_timespec stime; /* in */- struct btrfs_ioctl_timespec rtime; /* out */- __u64 flags; /* in */- __u64 reserved[16]; /* in */-};--/*- * Caller doesn't want file data in the send stream, even if the- * search of clone sources doesn't find an extent. UPDATE_EXTENT- * commands will be sent instead of WRITE commands.- */-#define BTRFS_SEND_FLAG_NO_FILE_DATA 0x1--/*- * Do not add the leading stream header. Used when multiple snapshots- * are sent back to back.- */-#define BTRFS_SEND_FLAG_OMIT_STREAM_HEADER 0x2--/*- * Omit the command at the end of the stream that indicated the end- * of the stream. This option is used when multiple snapshots are- * sent back to back.- */-#define BTRFS_SEND_FLAG_OMIT_END_CMD 0x4--struct btrfs_ioctl_send_args {- __s64 send_fd; /* in */- __u64 clone_sources_count; /* in */- __u64 *clone_sources; /* in */- __u64 parent_root; /* in */- __u64 flags; /* in */- __u64 reserved[4]; /* in */-};- enum btrfs_dev_stat_values { /* disk I/O failure stats */ BTRFS_DEV_STAT_WRITE_ERRS, /* EIO or EREMOTEIO from lower layers */@@ -457,7 +517,55 @@ __u64 create; __u64 qgroupid; };+struct btrfs_ioctl_timespec {+ __u64 sec;+ __u32 nsec;+}; +struct btrfs_ioctl_received_subvol_args {+ char uuid[BTRFS_UUID_SIZE]; /* in */+ __u64 stransid; /* in */+ __u64 rtransid; /* out */+ struct btrfs_ioctl_timespec stime; /* in */+ struct btrfs_ioctl_timespec rtime; /* out */+ __u64 flags; /* in */+ __u64 reserved[16]; /* in */+};++/*+ * Caller doesn't want file data in the send stream, even if the+ * search of clone sources doesn't find an extent. UPDATE_EXTENT+ * commands will be sent instead of WRITE commands.+ */+#define BTRFS_SEND_FLAG_NO_FILE_DATA 0x1++/*+ * Do not add the leading stream header. Used when multiple snapshots+ * are sent back to back.+ */+#define BTRFS_SEND_FLAG_OMIT_STREAM_HEADER 0x2++/*+ * Omit the command at the end of the stream that indicated the end+ * of the stream. This option is used when multiple snapshots are+ * sent back to back.+ */+#define BTRFS_SEND_FLAG_OMIT_END_CMD 0x4++#define BTRFS_SEND_FLAG_MASK \+ (BTRFS_SEND_FLAG_NO_FILE_DATA | \+ BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | \+ BTRFS_SEND_FLAG_OMIT_END_CMD)++struct btrfs_ioctl_send_args {+ __s64 send_fd; /* in */+ __u64 clone_sources_count; /* in */+ __u64 __user *clone_sources; /* in */+ __u64 parent_root; /* in */+ __u64 flags; /* in */+ __u64 reserved[4]; /* in */+};+ /* Error codes as returned by the kernel */ enum btrfs_err_code { notused,@@ -507,14 +615,6 @@ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \ struct btrfs_ioctl_vol_args)--/* With a @src_length of zero, the range from @src_offset->EOF is cloned! */-struct btrfs_ioctl_clone_range_args {- __s64 src_fd;- __u64 src_offset, src_length;- __u64 dest_offset;-};- /* trans start and trans end are dangerous, and only for * use by applications that know how to avoid the * resulting deadlocks@@ -530,8 +630,10 @@ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_BALANCE _IOW(BTRFS_IOCTL_MAGIC, 12, \ struct btrfs_ioctl_vol_args)+ #define BTRFS_IOC_CLONE_RANGE _IOW(BTRFS_IOCTL_MAGIC, 13, \ struct btrfs_ioctl_clone_range_args)+ #define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \@@ -540,6 +642,8 @@ struct btrfs_ioctl_defrag_range_args) #define BTRFS_IOC_TREE_SEARCH _IOWR(BTRFS_IOCTL_MAGIC, 17, \ struct btrfs_ioctl_search_args)+#define BTRFS_IOC_TREE_SEARCH_V2 _IOWR(BTRFS_IOCTL_MAGIC, 17, \+ struct btrfs_ioctl_search_args_v2) #define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \ struct btrfs_ioctl_ino_lookup_args) #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, __u64)@@ -571,12 +675,11 @@ struct btrfs_ioctl_ino_path_args) #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ struct btrfs_ioctl_ino_path_args)-#define BTRFS_IOC_DEVICES_READY _IOR(BTRFS_IOCTL_MAGIC, 39, \- struct btrfs_ioctl_vol_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)-+#define BTRFS_IOC_DEVICES_READY _IOR(BTRFS_IOCTL_MAGIC, 39, \+ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_QUOTA_CTL _IOWR(BTRFS_IOCTL_MAGIC, 40, \ struct btrfs_ioctl_quota_ctl_args) #define BTRFS_IOC_QGROUP_ASSIGN _IOW(BTRFS_IOCTL_MAGIC, 41, \@@ -598,6 +701,8 @@ struct btrfs_ioctl_get_dev_stats) #define BTRFS_IOC_DEV_REPLACE _IOWR(BTRFS_IOCTL_MAGIC, 53, \ struct btrfs_ioctl_dev_replace_args)+#define BTRFS_IOC_FILE_EXTENT_SAME _IOWR(BTRFS_IOCTL_MAGIC, 54, \+ struct btrfs_ioctl_same_args) #define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ struct btrfs_ioctl_feature_flags) #define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 57, \
include/btrfs/kerncompat.h view
@@ -16,8 +16,8 @@ * Boston, MA 021110-1307, USA. */ -#ifndef __KERNCOMPAT-#define __KERNCOMPAT+#ifndef __KERNCOMPAT_H__+#define __KERNCOMPAT_H__ #include <stdio.h> #include <stdlib.h>@@ -30,6 +30,19 @@ #include <linux/types.h> #include <stdint.h> +#include <features.h>++#ifndef __GLIBC__+#ifndef BTRFS_DISABLE_BACKTRACE+#define BTRFS_DISABLE_BACKTRACE+#endif+#define __always_inline __inline __attribute__ ((__always_inline__))+#endif++#ifndef BTRFS_DISABLE_BACKTRACE+#include <execinfo.h>+#endif+ #define ptr_to_u64(x) ((u64)(uintptr_t)x) #define u64_to_ptr(x) ((void *)(uintptr_t)x) @@ -54,7 +67,37 @@ #define ULONG_MAX (~0UL) #endif +#ifndef BTRFS_DISABLE_BACKTRACE+#define MAX_BACKTRACE 16+static inline void print_trace(void)+{+ void *array[MAX_BACKTRACE];+ size_t size;++ size = backtrace(array, MAX_BACKTRACE);+ backtrace_symbols_fd(array, size, 2);+}++static inline void assert_trace(const char *assertion, const char *filename,+ const char *func, unsigned line, int val)+{+ if (val)+ return;+ if (assertion)+ fprintf(stderr, "%s:%d: %s: Assertion `%s` failed.\n",+ filename, line, func, assertion);+ else+ fprintf(stderr, "%s:%d: %s: Assertion failed.\n", filename,+ line, func);+ print_trace();+ exit(1);+}++#define BUG() assert_trace(NULL, __FILE__, __func__, __LINE__, 0)+#else #define BUG() assert(0)+#endif+ #ifdef __CHECKER__ #define __force __attribute__((force)) #define __bitwise__ __attribute__((bitwise))@@ -75,6 +118,9 @@ typedef __u64 u64; typedef __u16 u16; typedef __u8 u8;+typedef __s64 s64;+typedef __s32 s32;+ /* * Continuing to define __KERNEL__ breaks others parts of the code, so * we can just undefine it now that we have the correct headers...@@ -86,6 +132,8 @@ typedef unsigned long long u64; typedef unsigned char u8; typedef unsigned short u16;+typedef long long s64;+typedef int s32; #endif @@ -236,11 +284,23 @@ #define kzalloc(x, y) calloc(1, x) #define kstrdup(x, y) strdup(x) #define kfree(x) free(x)+#define vmalloc(x) malloc(x)+#define vfree(x) free(x) +#ifndef BTRFS_DISABLE_BACKTRACE+#define BUG_ON(c) assert_trace(#c, __FILE__, __func__, __LINE__, !(c))+#else #define BUG_ON(c) assert(!(c))-#define WARN_ON(c) assert(!(c))-#define ASSERT(c) assert(c)+#endif +#define WARN_ON(c) BUG_ON(c)++#ifndef BTRFS_DISABLE_BACKTRACE+#define ASSERT(c) assert_trace(#c, __FILE__, __func__, __LINE__, (c))+#else+#define ASSERT(c) assert(c)+#endif+ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})@@ -250,6 +310,14 @@ #define __bitwise #endif +/* Alignment check */+#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)++static inline int is_power_of_2(unsigned long n)+{+ return (n != 0 && ((n & (n - 1)) == 0));+}+ typedef u16 __bitwise __le16; typedef u16 __bitwise __be16; typedef u32 __bitwise __le32;@@ -293,8 +361,14 @@ #define put_unaligned_le32(val,p) (((struct __una_u32 *)(p))->x = cpu_to_le32(val)) #define get_unaligned_le64(p) le64_to_cpu(((const struct __una_u64 *)(p))->x) #define put_unaligned_le64(val,p) (((struct __una_u64 *)(p))->x = cpu_to_le64(val))++#ifndef true+#define true 1+#define false 0 #endif #ifndef noinline #define noinline+#endif+ #endif
include/btrfs/rbtree.h view
@@ -23,72 +23,7 @@ I know it's not the cleaner way, but in C (not in C++) to get performances and genericity... - Some example of insert and search follows here. The search is a plain- normal search over an ordered tree. The insert instead must be implemented- int two steps: as first thing the code must insert the element in- order as a red leaf in the tree, then the support library function- rb_insert_color() must be called. Such function will do the- not trivial work to rebalance the rbtree if necessary.--------------------------------------------------------------------------static inline struct page * rb_search_page_cache(struct inode * inode,- unsigned long offset)-{- struct rb_node * n = inode->i_rb_page_cache.rb_node;- struct page * page;-- while (n)- {- page = rb_entry(n, struct page, rb_page_cache);-- if (offset < page->offset)- n = n->rb_left;- else if (offset > page->offset)- n = n->rb_right;- else- return page;- }- return NULL;-}--static inline struct page * __rb_insert_page_cache(struct inode * inode,- unsigned long offset,- struct rb_node * node)-{- struct rb_node ** p = &inode->i_rb_page_cache.rb_node;- struct rb_node * parent = NULL;- struct page * page;-- while (*p)- {- parent = *p;- page = rb_entry(parent, struct page, rb_page_cache);-- if (offset < page->offset)- p = &(*p)->rb_left;- else if (offset > page->offset)- p = &(*p)->rb_right;- else- return page;- }-- rb_link_node(node, parent, p);-- return NULL;-}--static inline struct page * rb_insert_page_cache(struct inode * inode,- unsigned long offset,- struct rb_node * node)-{- struct page * ret;- if ((ret = __rb_insert_page_cache(inode, offset, node)))- goto out;- rb_insert_color(node, &inode->i_rb_page_cache);- out:- return ret;-}------------------------------------------------------------------------+ See Documentation/rbtree.txt for documentation and samples. */ #ifndef _LINUX_RBTREE_H@@ -98,85 +33,86 @@ #else #include <btrfs/kerncompat.h> #endif /* BTRFS_FLAT_INCLUDES */-struct rb_node-{- unsigned long rb_parent_color;-#define RB_RED 0-#define RB_BLACK 1++#ifdef __cplusplus+extern "C" {+#endif++struct rb_node {+ unsigned long __rb_parent_color; struct rb_node *rb_right; struct rb_node *rb_left; } __attribute__((aligned(sizeof(long)))); /* The alignment might seem pointless, but allegedly CRIS needs it */ -struct rb_root-{+struct rb_root { struct rb_node *rb_node; }; -#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))-#define rb_color(r) ((r)->rb_parent_color & 1)-#define rb_is_red(r) (!rb_color(r))-#define rb_is_black(r) rb_color(r)-#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)-#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) -static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)-{- rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;-}-static inline void rb_set_color(struct rb_node *rb, int color)-{- rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;-}+#define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3)) #define RB_ROOT (struct rb_root) { NULL, } #define rb_entry(ptr, type, member) container_of(ptr, type, member) -#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)-#define RB_EMPTY_NODE(node) (rb_parent(node) == node)-#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))+#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) +/* 'empty' nodes are nodes that are known not to be inserted in an rbree */+#define RB_EMPTY_NODE(node) \+ ((node)->__rb_parent_color == (unsigned long)(node))+#define RB_CLEAR_NODE(node) \+ ((node)->__rb_parent_color = (unsigned long)(node))++ extern void rb_insert_color(struct rb_node *, struct rb_root *); extern void rb_erase(struct rb_node *, struct rb_root *); + /* Find logical next and previous nodes in a tree */-extern struct rb_node *rb_next(struct rb_node *);-extern struct rb_node *rb_prev(struct rb_node *);-extern struct rb_node *rb_first(struct rb_root *);-extern struct rb_node *rb_last(struct rb_root *);+extern struct rb_node *rb_next(const struct rb_node *);+extern struct rb_node *rb_prev(const struct rb_node *);+extern struct rb_node *rb_first(const struct rb_root *);+extern struct rb_node *rb_last(const struct rb_root *); +/* Postorder iteration - always visit the parent after its children */+extern struct rb_node *rb_first_postorder(const struct rb_root *);+extern struct rb_node *rb_next_postorder(const struct rb_node *);+ /* Fast replacement of a single node without remove/rebalance/add/rebalance */-extern void rb_replace_node(struct rb_node *victim, struct rb_node *xnew,+extern void rb_replace_node(struct rb_node *victim, struct rb_node *new_node, struct rb_root *root); static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, struct rb_node ** rb_link) {- node->rb_parent_color = (unsigned long )parent;+ node->__rb_parent_color = (unsigned long)parent; node->rb_left = node->rb_right = NULL; *rb_link = node; } -/* The common insert/search/free functions */-typedef int (*rb_compare_nodes)(struct rb_node *node1, struct rb_node *node2);-typedef int (*rb_compare_keys)(struct rb_node *node, void *key);-typedef void (*rb_free_node)(struct rb_node *node);+#define rb_entry_safe(ptr, type, member) \+ ({ typeof(ptr) ____ptr = (ptr); \+ ____ptr ? rb_entry(____ptr, type, member) : NULL; \+ }) -int rb_insert(struct rb_root *root, struct rb_node *node,- rb_compare_nodes comp);-/*- * In some cases, we need return the next node if we don't find the node we- * specify. At this time, we can use next_ret.+/**+ * rbtree_postorder_for_each_entry_safe - iterate over rb_root in post order of+ * given type safe against removal of rb_node entry+ *+ * @pos: the 'type *' to use as a loop cursor.+ * @n: another 'type *' to use as temporary storage+ * @root: 'rb_root *' of the rbtree.+ * @field: the name of the rb_node field within 'type'. */-struct rb_node *rb_search(struct rb_root *root, void *key, rb_compare_keys comp,- struct rb_node **next_ret);-void rb_free_nodes(struct rb_root *root, rb_free_node free_node);+#define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \+ for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \+ pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \+ typeof(*pos), field); 1; }); \+ pos = n) -#define FREE_RB_BASED_TREE(name, free_func) \-static void free_##name##_tree(struct rb_root *root) \-{ \- rb_free_nodes(root, free_func); \+#ifdef __cplusplus }+#endif #endif /* _LINUX_RBTREE_H */
− include/missing.h
@@ -1,48 +0,0 @@-/*- * 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