btrfs 0.1.2.3 → 0.2.0.0
raw patch · 14 files changed
+988/−321 lines, 14 filesdep ~basedep ~unixnew-component:exe:btrfs-joinPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, unix
API changes (from Hackage documentation)
- System.Linux.Btrfs: LZO :: CompressionType
- System.Linux.Btrfs: Zlib :: CompressionType
- 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.ByteString: LZO :: CompressionType
- System.Linux.Btrfs.ByteString: Zlib :: CompressionType
- 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: compressLZO :: CompressionType
+ System.Linux.Btrfs: compressNone :: CompressionType
+ System.Linux.Btrfs: compressZlib :: CompressionType
+ System.Linux.Btrfs: compressZstd :: CompressionType
+ System.Linux.Btrfs: data FSInfo
+ System.Linux.Btrfs: fsiCloneAlignment :: FSInfo -> FileSize
+ System.Linux.Btrfs: fsiDeviceCount :: FSInfo -> Word64
+ System.Linux.Btrfs: fsiNodeSize :: FSInfo -> FileSize
+ System.Linux.Btrfs: fsiSectorSize :: FSInfo -> FileSize
+ System.Linux.Btrfs: fsiUuid :: FSInfo -> UUID
+ System.Linux.Btrfs: getFSInfo :: FilePath -> IO FSInfo
+ System.Linux.Btrfs: getFSInfoFd :: Fd -> IO FSInfo
+ System.Linux.Btrfs: getFSLabel :: FilePath -> IO FilePath
+ System.Linux.Btrfs: getFSLabelFd :: Fd -> IO FilePath
+ System.Linux.Btrfs: instance GHC.Classes.Eq System.Linux.Btrfs.FSInfo
+ System.Linux.Btrfs: instance GHC.Show.Show System.Linux.Btrfs.FSInfo
+ System.Linux.Btrfs: setFSLabel :: FilePath -> FilePath -> IO ()
+ System.Linux.Btrfs: setFSLabelFd :: Fd -> FilePath -> IO ()
+ System.Linux.Btrfs.ByteString: compressLZO :: CompressionType
+ System.Linux.Btrfs.ByteString: compressNone :: CompressionType
+ System.Linux.Btrfs.ByteString: compressZlib :: CompressionType
+ System.Linux.Btrfs.ByteString: compressZstd :: CompressionType
+ System.Linux.Btrfs.ByteString: data FSInfo
+ System.Linux.Btrfs.ByteString: fsiCloneAlignment :: FSInfo -> FileSize
+ System.Linux.Btrfs.ByteString: fsiDeviceCount :: FSInfo -> Word64
+ System.Linux.Btrfs.ByteString: fsiNodeSize :: FSInfo -> FileSize
+ System.Linux.Btrfs.ByteString: fsiSectorSize :: FSInfo -> FileSize
+ System.Linux.Btrfs.ByteString: fsiUuid :: FSInfo -> UUID
+ System.Linux.Btrfs.ByteString: getFSInfo :: RawFilePath -> IO FSInfo
+ System.Linux.Btrfs.ByteString: getFSInfoFd :: Fd -> IO FSInfo
+ System.Linux.Btrfs.ByteString: getFSLabel :: RawFilePath -> IO RawFilePath
+ System.Linux.Btrfs.ByteString: getFSLabelFd :: Fd -> IO RawFilePath
+ System.Linux.Btrfs.ByteString: instance GHC.Classes.Eq System.Linux.Btrfs.ByteString.FSInfo
+ System.Linux.Btrfs.ByteString: instance GHC.Show.Show System.Linux.Btrfs.ByteString.FSInfo
+ System.Linux.Btrfs.ByteString: setFSLabel :: RawFilePath -> RawFilePath -> IO ()
+ System.Linux.Btrfs.ByteString: setFSLabelFd :: Fd -> RawFilePath -> IO ()
- System.Linux.Btrfs: DefragRangeArgs :: FileSize -> FileSize -> Word32 -> Maybe CompressionType -> Bool -> DefragRangeArgs
+ System.Linux.Btrfs: DefragRangeArgs :: FileSize -> FileSize -> Word32 -> CompressionType -> Bool -> DefragRangeArgs
- System.Linux.Btrfs: [draCompress] :: DefragRangeArgs -> Maybe CompressionType
+ System.Linux.Btrfs: [draCompress] :: DefragRangeArgs -> CompressionType
- System.Linux.Btrfs.ByteString: DefragRangeArgs :: FileSize -> FileSize -> Word32 -> Maybe CompressionType -> Bool -> DefragRangeArgs
+ System.Linux.Btrfs.ByteString: DefragRangeArgs :: FileSize -> FileSize -> Word32 -> CompressionType -> Bool -> DefragRangeArgs
- System.Linux.Btrfs.ByteString: [draCompress] :: DefragRangeArgs -> Maybe CompressionType
+ System.Linux.Btrfs.ByteString: [draCompress] :: DefragRangeArgs -> CompressionType
Files
- ChangeLog +0/−26
- ChangeLog.md +40/−0
- System/Linux/Btrfs.hsc +142/−30
- System/Linux/Btrfs/ByteString.hsc +142/−30
- System/Linux/Btrfs/FilePathLike.hs +25/−23
- btrfs.cabal +23/−12
- examples/btrfs-join.hs +38/−0
- include/btrfs/ctree.h +354/−160
- include/btrfs/extent-cache.h +0/−2
- include/btrfs/extent_io.h +13/−13
- include/btrfs/ioctl.h +107/−1
- include/btrfs/kerncompat.h +57/−23
- include/btrfs/sizes.h +47/−0
- include/sys/capability.h +0/−1
− ChangeLog
@@ -1,26 +0,0 @@-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.--v0.1.2.1-- * Support cloneRangeIfSame on read-only subvolumes (requires- CAP_SYS_ADMIN).--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.--v0.1.1.0-- * Support defraging file ranges.
+ ChangeLog.md view
@@ -0,0 +1,40 @@+#### 0.2.0.0 *2018-10-25*++ * Implement getFSInfo.+ * Remove an ugly hack that was used to block signals while defrag was running.+ * Support Zstd compression.+ * Make CompressionType abstract.+ * Fix handling of filenames that are not valid according to the current locale.+ * Deprecate System.Linux.Btrfs.ByteString.+ * Support getting/setting file system labels.++#### 0.1.2.3 *2017-01-30*++ * System.Linux.Btrfs.UUID.fromString did not handle all malformed+ UUIDs correctly.++#### 0.1.2.2 *2016-11-15*++ * Fix compilation error when libcap is not installed.++#### 0.1.2.1 *2016-11-13*++ * Support cloneRangeIfSame on read-only subvolumes (requires+ CAP_SYS_ADMIN).++#### 0.1.2.0 *2016-02-23*++ * Expose System.Linux.Btrfs.Time.+ * Add example program that prints the file creation timestamp.++#### 0.1.1.1 *2014-10-05*++ * Support getting/setting the id of the default subvolume.++#### 0.1.1.0 *2014-10-05*++ * Support defraging file ranges.++#### 0.1.0.0 *2014-09-01*++ * Initial public release.
System/Linux/Btrfs.hsc view
@@ -16,13 +16,18 @@ #if BTRFS_RAW_PATHS ##define FILEPATH RawFilePath module System.Linux.Btrfs.ByteString+{-# DEPRECATED "This module is deprecated and will be removed in a\+ future version of this library. Please leave a comment on\+ https://github.com/redneb/hs-btrfs/issues/5 if you think that is\+ should not be removed." #-} #else ##define FILEPATH FilePath module System.Linux.Btrfs #endif ( -- * Basic types- FileSize, ObjectType, ObjectId, InodeNum, SubvolId, CompressionType(..)+ FileSize, ObjectType, ObjectId, InodeNum, SubvolId+ , CompressionType, compressNone, compressZlib, compressLZO, compressZstd -- * File cloning/deduplication , cloneFd, clone, cloneNew , cloneRangeFd, cloneRange@@ -48,10 +53,26 @@ , getSubvolByReceivedUuidFd, getSubvolByReceivedUuid , getDefaultSubvolFd, getDefaultSubvol , setDefaultSubvolFd, setDefaultSubvol- -- * Defragging+ -- * Defrag+ -- | There is a limitation in the kernel whereby a defrag operation+ -- will be silently aborted when the calling process receives any+ -- signal. This does not play well with GHC's rts which in some+ -- cases uses signals as a way to preempt haskell threads. So in order+ -- to use 'defrag' or 'defragRange', you must compile your program with+ -- GHC >=8.2 and the use the threaded runtime which does not use+ -- signals anymore. Alternatively, for older versions of GHC, you can+ -- use something like the @withRTSSignalsBlocked@ function from+ -- <http://www.serpentine.com/blog/2010/09/04/dealing-with-fragile-c-libraries-e-g-mysql-from-haskell/ here>. , defragFd, defrag , DefragRangeArgs(..), defaultDefragRangeArgs , defragRangeFd, defragRange+ -- * File system info+ , FSInfo+ , fsiDeviceCount, fsiUuid, fsiNodeSize, fsiSectorSize, fsiCloneAlignment+ , getFSInfoFd, getFSInfo+ -- * File system label+ , getFSLabelFd, getFSLabel+ , setFSLabelFd, setFSLabel -- * Sync , syncFd, sync , startSyncFd, startSync@@ -77,7 +98,6 @@ import System.Posix.Types import System.Posix.IO hiding (openFd) import System.Posix.Files-import System.Posix.Signals import System.IO.Error import Control.Exception import Control.Monad@@ -117,9 +137,23 @@ type SubvolId = ObjectId -data CompressionType = Zlib | LZO- deriving (Show, Read, Eq, Enum, Bounded)+newtype CompressionType = CompressionType Word32+ deriving Eq +instance Show CompressionType where+ show t+ | t == compressNone = "compressNone"+ | t == compressZlib = "compressZlib"+ | t == compressLZO = "compressLZO"+ | t == compressZstd = "compressZstd"+ | otherwise = error "unknown compression type"++compressNone, compressZlib, compressLZO, compressZstd :: CompressionType+compressNone = CompressionType (#const BTRFS_COMPRESS_NONE)+compressZlib = CompressionType (#const BTRFS_COMPRESS_ZLIB)+compressLZO = CompressionType (#const BTRFS_COMPRESS_LZO)+compressZstd = CompressionType (#const BTRFS_COMPRESS_ZSTD)+ -------------------------------------------------------------------------------- cloneFd :: Fd -> Fd -> IO ()@@ -164,7 +198,8 @@ ioctl_fast dstFd (#const BTRFS_IOC_CLONE_RANGE) cra -- | Clones a range of bytes from a file to another file. All ranges must--- be block-aligned.+-- be block-aligned (the block size can be obtained using 'getFSInfo' and+-- 'fsiCloneAlignment'). -- -- Note: calls the @BTRFS_IOC_CLONE_RANGE@/@FICLONERANGE@ @ioctl@. cloneRange@@ -697,7 +732,7 @@ l <- treeSearchListFd fd sk $ \_ ptr -> do LE16 nameLen <- (#peek struct btrfs_dir_item, name_len) ptr let cName = ptr `plusPtr` (#size struct btrfs_dir_item)- name <- peekCStringLen (cName, fromIntegral nameLen)+ name <- peekFilePathLen (cName, fromIntegral nameLen) if name /= "default" then return Nothing else do@@ -737,8 +772,7 @@ defragFd :: Fd -> IO () defragFd fd = throwErrnoIfMinus1_ "defragFd" $- withBlockSIGVTALRM $ -- this is probably a bad idea- ioctl fd (#const BTRFS_IOC_DEFRAG) nullPtr+ ioctl fd (#const BTRFS_IOC_DEFRAG) nullPtr -- | Defrag a single file. --@@ -755,7 +789,7 @@ , draExtentThreshold :: Word32 -- ^ Any extent of size bigger or equal to this number will be -- considered already defragged. Use 0 for the kernel default.- , draCompress :: Maybe CompressionType+ , draCompress :: CompressionType -- ^ Compress the file while defragmenting. , draFlush :: Bool -- ^ Flush data to disk immediately after defragmenting.@@ -769,7 +803,7 @@ { draStart = 0 , draLength = maxBound , draExtentThreshold = 0- , draCompress = Nothing+ , draCompress = compressNone , draFlush = False } @@ -782,17 +816,14 @@ (#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+ ioctl fd (#const BTRFS_IOC_DEFRAG_RANGE) args where+ flags :: Word64 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))+ comp_flags+ | draCompress == compressNone = 0+ | otherwise = (#const BTRFS_DEFRAG_RANGE_COMPRESS)+ CompressionType comp_type = draCompress -- | Defrag a range within a single file. --@@ -804,6 +835,93 @@ -------------------------------------------------------------------------------- +-- | Information about a btrfs file system.+data FSInfo = FSInfo+ { fsiDeviceCount :: Word64+ -- ^ The number of devices in the file system.+ , fsiUuid :: UUID+ -- ^ The UUID of the file system.+ , fsiNodeSize :: FileSize+ -- ^ The tree block size in which metadata is stored.+ , fsiSectorSize :: FileSize+ -- ^ The minimum data block allocation unit.+ , fsiCloneAlignment :: FileSize+ -- ^ The size that is used for the alignment constraints of clone+ -- range operations.+ }+ deriving (Show, Eq)++getFSInfoFd :: Fd -> IO FSInfo+getFSInfoFd fd =+ allocaBytes (#size struct btrfs_ioctl_fs_info_args) $ \fsia -> do+ throwErrnoIfMinus1_ "getFSInfoFd" $+ ioctl_fast fd (#const BTRFS_IOC_FS_INFO) fsia+ nd <- (#peek struct btrfs_ioctl_fs_info_args, num_devices) fsia :: IO Word64+ uuid <- (#peek struct btrfs_ioctl_fs_info_args, fsid) fsia :: IO UUID+ ns <- (#peek struct btrfs_ioctl_fs_info_args, nodesize) fsia :: IO Word32+ ss <- (#peek struct btrfs_ioctl_fs_info_args, sectorsize) fsia :: IO Word32+ ca <- (#peek struct btrfs_ioctl_fs_info_args, clone_alignment) fsia :: IO Word32+ return FSInfo+ { fsiDeviceCount = nd+ , fsiUuid = uuid+ , fsiNodeSize = fromIntegral ns+ , fsiSectorSize = fromIntegral ss+ , fsiCloneAlignment = fromIntegral ca+ }++-- | Retrieve information about a btrfs file system.+--+-- Note: calls the @BTRFS_IOC_FS_INFO@ @ioctl@.+getFSInfo+ :: FILEPATH -- ^ The mount point of the volume (or any file in that volume).+ -> IO FSInfo+getFSInfo path =+ withFd path ReadOnly getFSInfoFd++--------------------------------------------------------------------------------++getFSLabelFd :: Fd -> IO FILEPATH+getFSLabelFd fd =+ allocaBytesZero maxLabelSize $ \ptr -> do+ throwErrnoIfMinus1_ "getFSLabelFd" $+ ioctl_fast fd (#const BTRFS_IOC_GET_FSLABEL) ptr+ peekFilePath ptr++-- | Retrieve the label of a btrfs file system.+--+-- Note: calls the @BTRFS_IOC_GET_FSLABEL@ @ioctl@.+getFSLabel+ :: FILEPATH -- ^ The mount point of the volume (or any file in that volume).+ -> IO FILEPATH+getFSLabel path =+ withFd path ReadOnly getFSLabelFd++setFSLabelFd :: Fd -> FILEPATH -> IO ()+setFSLabelFd fd label =+ withFilePathLen label $ \(ptr, len) ->+ allocaBytesZero maxLabelSize $ \buf -> do+ copyArray buf ptr (min len (maxLabelSize - 1))+ throwErrnoIfMinus1_ "setFSLabelFd" $+ ioctl fd (#const BTRFS_IOC_SET_FSLABEL) buf++-- | Set the label of a btrfs file system. Note that a label can be up to+-- 255 /bytes/ long. If the provided label is longer, it will be silently+-- truncated.+--+-- Note: calls the @BTRFS_IOC_SET_FSLABEL@ @ioctl@.+setFSLabel+ :: FILEPATH -- ^ The mount point of the volume (or any file in that volume).+ -> FILEPATH -- ^ The new label.+ -> IO ()+setFSLabel path label =+ withFd path ReadOnly $ \fd ->+ setFSLabelFd fd label++maxLabelSize :: Int+maxLabelSize = (#const BTRFS_LABEL_SIZE)++--------------------------------------------------------------------------------+ syncFd :: Fd -> IO () syncFd fd = throwErrnoIfMinus1_ "syncFd" $@@ -888,7 +1006,7 @@ count <- (#peek struct btrfs_data_container, elem_cnt ) fspath :: IO Word32 let val = (#ptr struct btrfs_data_container, val) fspath :: Ptr Word64 vals <- peekArray (fromIntegral count) val- paths <- mapM (peekCString . plusPtr val . fromIntegral) vals+ paths <- mapM (peekFilePath . plusPtr val . fromIntegral) vals return (paths, fromIntegral elemMissed) where fspathSize = 2 * 1024 + (#size struct btrfs_data_container)@@ -917,7 +1035,7 @@ ioctl_fast fd (#const BTRFS_IOC_INO_LOOKUP) ila treeId' <- (#peek struct btrfs_ioctl_ino_lookup_args, treeid) ila :: IO Word64 let cName = (#ptr struct btrfs_ioctl_ino_lookup_args, name) ila- name <- peekCString cName+ name <- peekFilePath cName return (treeId', dropTrailingSlash name) -- | Find the path of a file given its inode number and the id of the@@ -1122,7 +1240,7 @@ LE64 dirId <- (#peek struct btrfs_root_ref, dirid ) rrPtr LE16 nameLen <- (#peek struct btrfs_root_ref, name_len) rrPtr let cName = rrPtr `plusPtr` (#size struct btrfs_root_ref)- name <- peekCStringLen (cName, fromIntegral nameLen)+ name <- peekFilePathLen (cName, fromIntegral nameLen) return (dirId, name) --------------------------------------------------------------------------------@@ -1134,19 +1252,13 @@ withSplitPathOpenParent :: String -> Int -> FILEPATH -> (CStringLen -> Fd -> IO r) -> IO r withSplitPathOpenParent loc maxLen path action =- unsafeWithCStringLen name $ \cName @ (_, l) -> do+ unsafeWithFilePathLen name $ \cName @ (_, l) -> do unless (l <= maxLen) $ ioError $ flip ioeSetErrorString "the subvolume name is too long" $ mkIOError illegalOperationErrorType loc Nothing (Just (asString name)) withFd dir ReadOnly $ action cName where (dir, name) = splitFileName (dropTrailingSlash path)--withBlockSIGVTALRM :: IO a -> IO a-withBlockSIGVTALRM =- bracket_ (blockSignals s) (unblockSignals s)- where- s = addSignal sigVTALRM emptySignalSet nothingIf :: Bool -> a -> Maybe a nothingIf f v = if f then Nothing else Just v
System/Linux/Btrfs/ByteString.hsc view
@@ -16,13 +16,18 @@ #if BTRFS_RAW_PATHS ##define FILEPATH RawFilePath module System.Linux.Btrfs.ByteString+{-# DEPRECATED "This module is deprecated and will be removed in a\+ future version of this library. Please leave a comment on\+ https://github.com/redneb/hs-btrfs/issues/5 if you think that is\+ should not be removed." #-} #else ##define FILEPATH FilePath module System.Linux.Btrfs #endif ( -- * Basic types- FileSize, ObjectType, ObjectId, InodeNum, SubvolId, CompressionType(..)+ FileSize, ObjectType, ObjectId, InodeNum, SubvolId+ , CompressionType, compressNone, compressZlib, compressLZO, compressZstd -- * File cloning/deduplication , cloneFd, clone, cloneNew , cloneRangeFd, cloneRange@@ -48,10 +53,26 @@ , getSubvolByReceivedUuidFd, getSubvolByReceivedUuid , getDefaultSubvolFd, getDefaultSubvol , setDefaultSubvolFd, setDefaultSubvol- -- * Defragging+ -- * Defrag+ -- | There is a limitation in the kernel whereby a defrag operation+ -- will be silently aborted when the calling process receives any+ -- signal. This does not play well with GHC's rts which in some+ -- cases uses signals as a way to preempt haskell threads. So in order+ -- to use 'defrag' or 'defragRange', you must compile your program with+ -- GHC >=8.2 and the use the threaded runtime which does not use+ -- signals anymore. Alternatively, for older versions of GHC, you can+ -- use something like the @withRTSSignalsBlocked@ function from+ -- <http://www.serpentine.com/blog/2010/09/04/dealing-with-fragile-c-libraries-e-g-mysql-from-haskell/ here>. , defragFd, defrag , DefragRangeArgs(..), defaultDefragRangeArgs , defragRangeFd, defragRange+ -- * File system info+ , FSInfo+ , fsiDeviceCount, fsiUuid, fsiNodeSize, fsiSectorSize, fsiCloneAlignment+ , getFSInfoFd, getFSInfo+ -- * File system label+ , getFSLabelFd, getFSLabel+ , setFSLabelFd, setFSLabel -- * Sync , syncFd, sync , startSyncFd, startSync@@ -77,7 +98,6 @@ import System.Posix.Types import System.Posix.IO hiding (openFd) import System.Posix.Files-import System.Posix.Signals import System.IO.Error import Control.Exception import Control.Monad@@ -117,9 +137,23 @@ type SubvolId = ObjectId -data CompressionType = Zlib | LZO- deriving (Show, Read, Eq, Enum, Bounded)+newtype CompressionType = CompressionType Word32+ deriving Eq +instance Show CompressionType where+ show t+ | t == compressNone = "compressNone"+ | t == compressZlib = "compressZlib"+ | t == compressLZO = "compressLZO"+ | t == compressZstd = "compressZstd"+ | otherwise = error "unknown compression type"++compressNone, compressZlib, compressLZO, compressZstd :: CompressionType+compressNone = CompressionType (#const BTRFS_COMPRESS_NONE)+compressZlib = CompressionType (#const BTRFS_COMPRESS_ZLIB)+compressLZO = CompressionType (#const BTRFS_COMPRESS_LZO)+compressZstd = CompressionType (#const BTRFS_COMPRESS_ZSTD)+ -------------------------------------------------------------------------------- cloneFd :: Fd -> Fd -> IO ()@@ -164,7 +198,8 @@ ioctl_fast dstFd (#const BTRFS_IOC_CLONE_RANGE) cra -- | Clones a range of bytes from a file to another file. All ranges must--- be block-aligned.+-- be block-aligned (the block size can be obtained using 'getFSInfo' and+-- 'fsiCloneAlignment'). -- -- Note: calls the @BTRFS_IOC_CLONE_RANGE@/@FICLONERANGE@ @ioctl@. cloneRange@@ -697,7 +732,7 @@ l <- treeSearchListFd fd sk $ \_ ptr -> do LE16 nameLen <- (#peek struct btrfs_dir_item, name_len) ptr let cName = ptr `plusPtr` (#size struct btrfs_dir_item)- name <- peekCStringLen (cName, fromIntegral nameLen)+ name <- peekFilePathLen (cName, fromIntegral nameLen) if name /= "default" then return Nothing else do@@ -737,8 +772,7 @@ defragFd :: Fd -> IO () defragFd fd = throwErrnoIfMinus1_ "defragFd" $- withBlockSIGVTALRM $ -- this is probably a bad idea- ioctl fd (#const BTRFS_IOC_DEFRAG) nullPtr+ ioctl fd (#const BTRFS_IOC_DEFRAG) nullPtr -- | Defrag a single file. --@@ -755,7 +789,7 @@ , draExtentThreshold :: Word32 -- ^ Any extent of size bigger or equal to this number will be -- considered already defragged. Use 0 for the kernel default.- , draCompress :: Maybe CompressionType+ , draCompress :: CompressionType -- ^ Compress the file while defragmenting. , draFlush :: Bool -- ^ Flush data to disk immediately after defragmenting.@@ -769,7 +803,7 @@ { draStart = 0 , draLength = maxBound , draExtentThreshold = 0- , draCompress = Nothing+ , draCompress = compressNone , draFlush = False } @@ -782,17 +816,14 @@ (#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+ ioctl fd (#const BTRFS_IOC_DEFRAG_RANGE) args where+ flags :: Word64 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))+ comp_flags+ | draCompress == compressNone = 0+ | otherwise = (#const BTRFS_DEFRAG_RANGE_COMPRESS)+ CompressionType comp_type = draCompress -- | Defrag a range within a single file. --@@ -804,6 +835,93 @@ -------------------------------------------------------------------------------- +-- | Information about a btrfs file system.+data FSInfo = FSInfo+ { fsiDeviceCount :: Word64+ -- ^ The number of devices in the file system.+ , fsiUuid :: UUID+ -- ^ The UUID of the file system.+ , fsiNodeSize :: FileSize+ -- ^ The tree block size in which metadata is stored.+ , fsiSectorSize :: FileSize+ -- ^ The minimum data block allocation unit.+ , fsiCloneAlignment :: FileSize+ -- ^ The size that is used for the alignment constraints of clone+ -- range operations.+ }+ deriving (Show, Eq)++getFSInfoFd :: Fd -> IO FSInfo+getFSInfoFd fd =+ allocaBytes (#size struct btrfs_ioctl_fs_info_args) $ \fsia -> do+ throwErrnoIfMinus1_ "getFSInfoFd" $+ ioctl_fast fd (#const BTRFS_IOC_FS_INFO) fsia+ nd <- (#peek struct btrfs_ioctl_fs_info_args, num_devices) fsia :: IO Word64+ uuid <- (#peek struct btrfs_ioctl_fs_info_args, fsid) fsia :: IO UUID+ ns <- (#peek struct btrfs_ioctl_fs_info_args, nodesize) fsia :: IO Word32+ ss <- (#peek struct btrfs_ioctl_fs_info_args, sectorsize) fsia :: IO Word32+ ca <- (#peek struct btrfs_ioctl_fs_info_args, clone_alignment) fsia :: IO Word32+ return FSInfo+ { fsiDeviceCount = nd+ , fsiUuid = uuid+ , fsiNodeSize = fromIntegral ns+ , fsiSectorSize = fromIntegral ss+ , fsiCloneAlignment = fromIntegral ca+ }++-- | Retrieve information about a btrfs file system.+--+-- Note: calls the @BTRFS_IOC_FS_INFO@ @ioctl@.+getFSInfo+ :: FILEPATH -- ^ The mount point of the volume (or any file in that volume).+ -> IO FSInfo+getFSInfo path =+ withFd path ReadOnly getFSInfoFd++--------------------------------------------------------------------------------++getFSLabelFd :: Fd -> IO FILEPATH+getFSLabelFd fd =+ allocaBytesZero maxLabelSize $ \ptr -> do+ throwErrnoIfMinus1_ "getFSLabelFd" $+ ioctl_fast fd (#const BTRFS_IOC_GET_FSLABEL) ptr+ peekFilePath ptr++-- | Retrieve the label of a btrfs file system.+--+-- Note: calls the @BTRFS_IOC_GET_FSLABEL@ @ioctl@.+getFSLabel+ :: FILEPATH -- ^ The mount point of the volume (or any file in that volume).+ -> IO FILEPATH+getFSLabel path =+ withFd path ReadOnly getFSLabelFd++setFSLabelFd :: Fd -> FILEPATH -> IO ()+setFSLabelFd fd label =+ withFilePathLen label $ \(ptr, len) ->+ allocaBytesZero maxLabelSize $ \buf -> do+ copyArray buf ptr (min len (maxLabelSize - 1))+ throwErrnoIfMinus1_ "setFSLabelFd" $+ ioctl fd (#const BTRFS_IOC_SET_FSLABEL) buf++-- | Set the label of a btrfs file system. Note that a label can be up to+-- 255 /bytes/ long. If the provided label is longer, it will be silently+-- truncated.+--+-- Note: calls the @BTRFS_IOC_SET_FSLABEL@ @ioctl@.+setFSLabel+ :: FILEPATH -- ^ The mount point of the volume (or any file in that volume).+ -> FILEPATH -- ^ The new label.+ -> IO ()+setFSLabel path label =+ withFd path ReadOnly $ \fd ->+ setFSLabelFd fd label++maxLabelSize :: Int+maxLabelSize = (#const BTRFS_LABEL_SIZE)++--------------------------------------------------------------------------------+ syncFd :: Fd -> IO () syncFd fd = throwErrnoIfMinus1_ "syncFd" $@@ -888,7 +1006,7 @@ count <- (#peek struct btrfs_data_container, elem_cnt ) fspath :: IO Word32 let val = (#ptr struct btrfs_data_container, val) fspath :: Ptr Word64 vals <- peekArray (fromIntegral count) val- paths <- mapM (peekCString . plusPtr val . fromIntegral) vals+ paths <- mapM (peekFilePath . plusPtr val . fromIntegral) vals return (paths, fromIntegral elemMissed) where fspathSize = 2 * 1024 + (#size struct btrfs_data_container)@@ -917,7 +1035,7 @@ ioctl_fast fd (#const BTRFS_IOC_INO_LOOKUP) ila treeId' <- (#peek struct btrfs_ioctl_ino_lookup_args, treeid) ila :: IO Word64 let cName = (#ptr struct btrfs_ioctl_ino_lookup_args, name) ila- name <- peekCString cName+ name <- peekFilePath cName return (treeId', dropTrailingSlash name) -- | Find the path of a file given its inode number and the id of the@@ -1122,7 +1240,7 @@ LE64 dirId <- (#peek struct btrfs_root_ref, dirid ) rrPtr LE16 nameLen <- (#peek struct btrfs_root_ref, name_len) rrPtr let cName = rrPtr `plusPtr` (#size struct btrfs_root_ref)- name <- peekCStringLen (cName, fromIntegral nameLen)+ name <- peekFilePathLen (cName, fromIntegral nameLen) return (dirId, name) --------------------------------------------------------------------------------@@ -1134,19 +1252,13 @@ withSplitPathOpenParent :: String -> Int -> FILEPATH -> (CStringLen -> Fd -> IO r) -> IO r withSplitPathOpenParent loc maxLen path action =- unsafeWithCStringLen name $ \cName @ (_, l) -> do+ unsafeWithFilePathLen name $ \cName @ (_, l) -> do unless (l <= maxLen) $ ioError $ flip ioeSetErrorString "the subvolume name is too long" $ mkIOError illegalOperationErrorType loc Nothing (Just (asString name)) withFd dir ReadOnly $ action cName where (dir, name) = splitFileName (dropTrailingSlash path)--withBlockSIGVTALRM :: IO a -> IO a-withBlockSIGVTALRM =- bracket_ (blockSignals s) (unblockSignals s)- where- s = addSignal sigVTALRM emptySignalSet nothingIf :: Bool -> a -> Maybe a nothingIf f v = if f then Nothing else Just v
System/Linux/Btrfs/FilePathLike.hs view
@@ -7,29 +7,29 @@ import Data.String import Data.Monoid-import Data.List-import Foreign.C.String hiding- ( peekCString, peekCStringLen- , newCString, newCStringLen- , withCString, withCStringLen)-import qualified Foreign.C.String as S+import Data.List (dropWhileEnd)+import Foreign.C.String (CString, CStringLen)+import qualified System.Posix.Internals as P+import GHC.IO.Encoding (getFileSystemEncoding)+import qualified GHC.Foreign as GHC import qualified Data.ByteString as B import qualified Data.ByteString.Unsafe as B import qualified Data.ByteString.Char8 as B8-import System.Posix.Types+import System.Posix.Types (Fd, FileMode) import System.Posix.IO hiding (openFd) import System.Posix.ByteString.FilePath (RawFilePath) import qualified System.Posix.IO as S (openFd) import qualified System.Posix.IO.ByteString as B (openFd) import System.IO.Unsafe (unsafePerformIO)+import Prelude class (Monoid s, IsString s) => FilePathLike s where asString :: s -> String- peekCString :: CString -> IO s- peekCStringLen :: CStringLen -> IO s- withCString :: s -> (CString -> IO a) -> IO a - withCStringLen :: s -> (CStringLen -> IO a) -> IO a - unsafeWithCStringLen :: s -> (CStringLen -> IO a) -> IO a + peekFilePath :: CString -> IO s+ peekFilePathLen :: CStringLen -> IO s+ withFilePath :: s -> (CString -> IO a) -> IO a+ withFilePathLen :: s -> (CStringLen -> IO a) -> IO a+ unsafeWithFilePathLen :: s -> (CStringLen -> IO a) -> IO a openFd :: s -> OpenMode -> Maybe FileMode -> OpenFileFlags -> IO Fd dropTrailingSlash :: s -> s (</>) :: s -> s -> s@@ -37,11 +37,13 @@ instance FilePathLike [Char] where asString = id- peekCString = S.peekCString- peekCStringLen = S.peekCStringLen- withCString = S.withCString- withCStringLen = S.withCStringLen- unsafeWithCStringLen = withCStringLen+ peekFilePath = P.peekFilePath+ peekFilePathLen = P.peekFilePathLen+ withFilePath = P.withFilePath+ withFilePathLen path action =+ getFileSystemEncoding >>= \enc ->+ GHC.withCStringLen enc path action+ unsafeWithFilePathLen = withFilePathLen openFd = S.openFd dropTrailingSlash s = if null s' then "/" else s' where@@ -58,11 +60,11 @@ instance FilePathLike B.ByteString where asString = convert- peekCString = B.packCString- peekCStringLen = B.packCStringLen- withCString = B.useAsCString- withCStringLen = B.useAsCStringLen- unsafeWithCStringLen = B.unsafeUseAsCStringLen+ peekFilePath = B.packCString+ peekFilePathLen = B.packCStringLen+ withFilePath = B.useAsCString+ withFilePathLen = B.useAsCStringLen+ unsafeWithFilePathLen = B.unsafeUseAsCStringLen openFd = B.openFd dropTrailingSlash s = if B.null s' then slashBS else s' where@@ -81,7 +83,7 @@ curDir = B8.pack "./" convert :: (FilePathLike s1, FilePathLike s2) => s1 -> s2-convert s = unsafePerformIO $ unsafeWithCStringLen s peekCStringLen+convert s = unsafePerformIO $ unsafeWithFilePathLen s peekFilePathLen slashBS :: B.ByteString slashBS = B8.singleton '/'
btrfs.cabal view
@@ -1,5 +1,5 @@ name: btrfs-version: 0.1.2.3+version: 0.2.0.0 synopsis: Bindings to the btrfs API description: This package provides bindings to the low-level btrfs API (i.e. the@@ -23,7 +23,7 @@ cabal-version: >=1.10 extra-source-files:- ChangeLog+ ChangeLog.md include/btrfs/ctree.h include/btrfs/extent-cache.h include/btrfs/extent_io.h@@ -32,6 +32,7 @@ include/btrfs/list.h include/btrfs/radix-tree.h include/btrfs/rbtree.h+ include/btrfs/sizes.h include/sys/capability.h make-bytestring.hs @@ -64,8 +65,8 @@ else build-depends: base >=4.6 && <5, btrfs, unix, filepath, linux-file-extents, ansi-terminal- default-language: Haskell2010- ghc-options: -Wall+ default-language: Haskell2010+ ghc-options: -Wall -threaded executable btrfs-clone-range hs-source-dirs: examples@@ -74,8 +75,8 @@ buildable: False else build-depends: base >=4.6 && <5, btrfs- default-language: Haskell2010- ghc-options: -Wall+ default-language: Haskell2010+ ghc-options: -Wall executable btrfs-split hs-source-dirs: examples@@ -84,9 +85,19 @@ buildable: False else build-depends: base >=4.6 && <5, btrfs, unix- default-language: Haskell2010- ghc-options: -Wall+ default-language: Haskell2010+ ghc-options: -Wall +executable btrfs-join+ hs-source-dirs: examples+ main-is: btrfs-join.hs+ if !flag(examples)+ buildable: False+ else+ build-depends: base >=4.6 && <5, btrfs, unix+ default-language: Haskell2010+ ghc-options: -Wall+ executable btrfs-list-subvols hs-source-dirs: examples main-is: btrfs-list-subvols.hs@@ -94,8 +105,8 @@ buildable: False else build-depends: base >=4.6 && <5, btrfs- default-language: Haskell2010- ghc-options: -Wall+ default-language: Haskell2010+ ghc-options: -Wall executable btrfs-print-creation-time hs-source-dirs: examples@@ -105,5 +116,5 @@ buildable: False else build-depends: base >=4.6 && <5, btrfs, unix >=2.6, time >=1.4- default-language: Haskell2010- ghc-options: -Wall+ default-language: Haskell2010+ ghc-options: -Wall
+ examples/btrfs-join.hs view
@@ -0,0 +1,38 @@+import System.Environment (getArgs, getProgName)+import System.Exit (exitFailure)+import System.IO (stderr, hPutStrLn)+import Control.Exception (bracket)+import System.Posix++import System.Linux.Btrfs (cloneRangeFd)++main :: IO ()+main = do+ args <- getArgs+ case args of+ dstPath : srcFiles0@(_ : _) ->+ withWriteFd dstPath $ \dstFd -> do+ let loop offset (srcFile : srcFiles) = do+ len <- withReadFd srcFile $ \srcFd -> do+ cloneRangeFd srcFd 0 0 dstFd offset+ fileSize <$> getFdStatus srcFd+ loop (offset + fromIntegral len) srcFiles+ loop _ [] = return ()+ loop 0 srcFiles0+ _ -> do+ prog <- getProgName+ hPutStrLn stderr "Invalid command line arguments"+ hPutStrLn stderr $ "Usage: " ++ prog ++ " DEST SOURCE [SOURCE]..."+ exitFailure++withReadFd :: FilePath -> (Fd -> IO r) -> IO r+withReadFd path action =+ bracket+ (openFd path ReadOnly Nothing defaultFileFlags {nonBlock = True})+ closeFd action++withWriteFd :: FilePath -> (Fd -> IO r) -> IO r+withWriteFd path action =+ bracket+ (openFd path WriteOnly (Just stdFileMode) defaultFileFlags {trunc = True})+ closeFd action
include/btrfs/ctree.h view
@@ -19,6 +19,8 @@ #ifndef __BTRFS_CTREE_H__ #define __BTRFS_CTREE_H__ +#include <stdbool.h>+ #if BTRFS_FLAT_INCLUDES #include "list.h" #include "kerncompat.h"@@ -26,6 +28,7 @@ #include "extent-cache.h" #include "extent_io.h" #include "ioctl.h"+#include "sizes.h" #else #include <btrfs/list.h> #include <btrfs/kerncompat.h>@@ -33,6 +36,7 @@ #include <btrfs/extent-cache.h> #include <btrfs/extent_io.h> #include <btrfs/ioctl.h>+#include <btrfs/sizes.h> #endif /* BTRFS_FLAT_INCLUDES */ struct btrfs_root;@@ -40,6 +44,14 @@ struct btrfs_free_space_ctl; #define BTRFS_MAGIC 0x4D5F53665248425FULL /* ascii _BHRfS_M, no null */ +/*+ * Fake signature for an unfinalized filesystem, which only has barebone tree+ * structures (normally 6 near empty trees, on SINGLE meta/sys temporary chunks)+ *+ * ascii !BHRfS_M, no null+ */+#define BTRFS_MAGIC_TEMPORARY 0x4D5F536652484221ULL+ #define BTRFS_MAX_MIRRORS 3 #define BTRFS_MAX_LEVEL 8@@ -79,6 +91,9 @@ /* tracks free space in block groups. */ #define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL +/* device stats in the device tree */+#define BTRFS_DEV_STATS_OBJECTID 0ULL+ /* for storing balance parameters in the root tree */ #define BTRFS_BALANCE_OBJECTID -4ULL @@ -127,6 +142,8 @@ */ #define BTRFS_DEV_ITEMS_OBJECTID 1ULL +#define BTRFS_EMPTY_SUBVOL_DIR_OBJECTID 2ULL+ /* * the max metadata block size. This limit is somewhat artificial, * but the memmove costs go through the roof for larger blocks.@@ -152,10 +169,9 @@ /* csum types */ #define BTRFS_CSUM_TYPE_CRC32 0 +/* four bytes for CRC32 */ static int btrfs_csum_sizes[] = { 4 }; -/* four bytes for CRC32 */-#define BTRFS_CRC32_SIZE 4 #define BTRFS_EMPTY_DIR_SIZE 0 #define BTRFS_FT_UNKNOWN 0@@ -341,18 +357,9 @@ u8 level; } __attribute__ ((__packed__)); -#define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->nodesize - \- 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->nodesize))-#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \- sizeof(struct btrfs_item) - \- sizeof(struct btrfs_file_extent_item))-#define BTRFS_MAX_XATTR_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \- sizeof(struct btrfs_item) -\- sizeof(struct btrfs_dir_item))-+#define BTRFS_LEAF_DATA_SIZE(fs_info) \+ (__BTRFS_LEAF_DATA_SIZE(fs_info->nodesize)) /* * this is a very generous portion of the super block, giving us@@ -429,7 +436,7 @@ __le32 sectorsize; __le32 nodesize; /* Unused and must be equal to nodesize */- __le32 leafsize;+ __le32 __unused_leafsize; __le32 stripesize; __le32 sys_chunk_array_size; __le64 chunk_root_generation;@@ -458,19 +465,20 @@ * ones specified below then we will fail to mount */ #define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0)+/*+ * Older kernels on big-endian systems produced broken free space tree bitmaps,+ * and btrfs-progs also used to corrupt the free space tree. If this bit is+ * clear, then the free space tree cannot be trusted. btrfs-progs can also+ * intentionally clear this bit to ask the kernel to rebuild the free space+ * tree.+ */+#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID (1ULL << 1) #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) #define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) #define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO (1ULL << 3)--/*- * some patches floated around with a second compression method- * lets save that incompat here for when they do get in- * Note we don't actually support it, we're just reserving the- * number- */-#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZOv2 (1ULL << 4)+#define BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD (1ULL << 4) /* * older kernels tried to do bigger metadata blocks, but the@@ -484,13 +492,18 @@ #define BTRFS_FEATURE_COMPAT_SUPP 0ULL -#define BTRFS_FEATURE_COMPAT_RO_SUPP \- (BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)+/*+ * The FREE_SPACE_TREE and FREE_SPACE_TREE_VALID compat_ro bits must not be+ * added here until read-write support for the free space tree is implemented in+ * btrfs-progs.+ */+#define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL #define BTRFS_FEATURE_INCOMPAT_SUPP \ (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \ BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \ BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO | \+ BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD | \ BTRFS_FEATURE_INCOMPAT_BIG_METADATA | \ BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF | \ BTRFS_FEATURE_INCOMPAT_RAID56 | \@@ -543,22 +556,24 @@ * The slots array records the index of the item or block pointer * used while walking the tree. */-+enum { READA_NONE = 0, READA_BACK, READA_FORWARD }; struct btrfs_path { struct extent_buffer *nodes[BTRFS_MAX_LEVEL]; int slots[BTRFS_MAX_LEVEL];- /* if there is real range locking, this locks field will change */+#if 0+ /* The kernel locking sheme is not done in userspace. */ int locks[BTRFS_MAX_LEVEL];- int reada;+#endif+ signed char reada; /* keep some upper locks as we walk down */- int lowest_level;+ u8 lowest_level; /* * set by btrfs_split_item, tells search_slot to keep all locks * and to force calls to keep space in the nodes */- unsigned int search_for_split:1;- unsigned int skip_check_block:1;+ u8 search_for_split;+ u8 skip_check_block; }; /*@@ -576,9 +591,10 @@ __le32 refs; } __attribute__ ((__packed__)); -#define BTRFS_MAX_EXTENT_ITEM_SIZE(r) ((BTRFS_LEAF_DATA_SIZE(r) >> 4) - \+#define BTRFS_MAX_EXTENT_ITEM_SIZE(r) \+ ((BTRFS_LEAF_DATA_SIZE(r->fs_info) >> 4) - \ sizeof(struct btrfs_item))-#define BTRFS_MAX_EXTENT_SIZE (128 * 1024 * 1024)+#define BTRFS_MAX_EXTENT_SIZE SZ_128M #define BTRFS_EXTENT_FLAG_DATA (1ULL << 0) #define BTRFS_EXTENT_FLAG_TREE_BLOCK (1ULL << 1)@@ -650,8 +666,9 @@ BTRFS_COMPRESS_NONE = 0, BTRFS_COMPRESS_ZLIB = 1, BTRFS_COMPRESS_LZO = 2,- BTRFS_COMPRESS_TYPES = 2,- BTRFS_COMPRESS_LAST = 3,+ BTRFS_COMPRESS_ZSTD = 3,+ BTRFS_COMPRESS_TYPES = 3,+ BTRFS_COMPRESS_LAST = 4, } btrfs_compression_type; /* we don't understand any encryption methods right now */@@ -780,6 +797,84 @@ __le16 name_len; } __attribute__ ((__packed__)); +struct btrfs_disk_balance_args {+ /*+ * profiles to operate on, single is denoted by+ * BTRFS_AVAIL_ALLOC_BIT_SINGLE+ */+ __le64 profiles;++ /*+ * usage filter+ * BTRFS_BALANCE_ARGS_USAGE with a single value means '0..N'+ * BTRFS_BALANCE_ARGS_USAGE_RANGE - range syntax, min..max+ */+ union {+ __le64 usage;+ struct {+ __le32 usage_min;+ __le32 usage_max;+ };+ };++ /* devid filter */+ __le64 devid;++ /* devid subset filter [pstart..pend) */+ __le64 pstart;+ __le64 pend;++ /* btrfs virtual address space subset filter [vstart..vend) */+ __le64 vstart;+ __le64 vend;++ /*+ * profile to convert to, single is denoted by+ * BTRFS_AVAIL_ALLOC_BIT_SINGLE+ */+ __le64 target;++ /* BTRFS_BALANCE_ARGS_* */+ __le64 flags;++ /*+ * BTRFS_BALANCE_ARGS_LIMIT with value 'limit'+ * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum+ * and maximum+ */+ union {+ __le64 limit;+ struct {+ __le32 limit_min;+ __le32 limit_max;+ };+ };++ /*+ * Process chunks that cross stripes_min..stripes_max devices,+ * BTRFS_BALANCE_ARGS_STRIPES_RANGE+ */+ __le32 stripes_min;+ __le32 stripes_max;++ __le64 unused[6];+} __attribute__ ((__packed__));++/*+ * store balance parameters to disk so that balance can be properly+ * resumed after crash or unmount+ */+struct btrfs_balance_item {+ /* BTRFS_BALANCE_* */+ __le64 flags;++ struct btrfs_disk_balance_args data;+ struct btrfs_disk_balance_args meta;+ struct btrfs_disk_balance_args sys;++ __le64 unused[4];+} __attribute__ ((__packed__));+ #define BTRFS_FILE_EXTENT_INLINE 0 #define BTRFS_FILE_EXTENT_REG 1 #define BTRFS_FILE_EXTENT_PREALLOC 2@@ -833,6 +928,14 @@ } __attribute__ ((__packed__)); +struct btrfs_dev_stats_item {+ /*+ * grow this item struct at the end for future enhancements and keep+ * the existing values unchanged+ */+ __le64 values[BTRFS_DEV_STAT_VALUES_MAX];+} __attribute__ ((__packed__));+ struct btrfs_csum_item { u8 csum; } __attribute__ ((__packed__));@@ -843,7 +946,7 @@ * - the first 64k blank is useful for some boot loader/manager * - the first 1M could be scratched by buggy partitioner or somesuch */-#define BTRFS_BLOCK_RESERVED_1M_FOR_SUPER ((u64)1024 * 1024)+#define BTRFS_BLOCK_RESERVED_1M_FOR_SUPER ((u64)SZ_1M) /* tag for the radix tree of block groups in ram */ #define BTRFS_BLOCK_GROUP_DATA (1ULL << 0)@@ -856,8 +959,18 @@ #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 +enum btrfs_raid_types {+ BTRFS_RAID_RAID10,+ BTRFS_RAID_RAID1,+ BTRFS_RAID_DUP,+ BTRFS_RAID_RAID0,+ BTRFS_RAID_SINGLE,+ BTRFS_RAID_RAID5,+ BTRFS_RAID_RAID6,+ BTRFS_NR_RAID_TYPES+};+ #define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | \ BTRFS_BLOCK_GROUP_SYSTEM | \ BTRFS_BLOCK_GROUP_METADATA)@@ -1015,8 +1128,8 @@ struct btrfs_fs_devices *fs_devices; struct list_head space_info;- int system_allocs; + unsigned int system_allocs:1; unsigned int readonly:1; unsigned int on_restoring:1; unsigned int is_chunk_recover:1;@@ -1026,15 +1139,21 @@ unsigned int ignore_chunk_tree_error:1; unsigned int avoid_meta_chunk_alloc:1; unsigned int avoid_sys_chunk_alloc:1;+ unsigned int finalize_on_close:1; - int (*free_extent_hook)(struct btrfs_trans_handle *trans,- struct btrfs_root *root,+ int transaction_aborted;++ int (*free_extent_hook)(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset, int refs_to_drop); struct cache_tree *fsck_extent_cache; struct cache_tree *corrupt_blocks; + /* Cached block sizes */+ u32 nodesize;+ u32 sectorsize;+ u32 stripesize; }; /*@@ -1050,24 +1169,11 @@ u64 objectid; u64 last_trans; - /* data allocations are done in sectorsize units */- u32 sectorsize;-- /* node allocations are done in nodesize units */- u32 nodesize;-- /* Unused, equal to nodesize */- u32 leafsize;-- /* leaf allocations are done in nodesize units */- u32 stripesize;- int ref_cows; int track_dirty; u32 type;- u64 highest_inode; u64 last_inode_alloc; /*@@ -1085,6 +1191,35 @@ struct rb_node rb_node; }; +static inline u32 BTRFS_MAX_ITEM_SIZE(const struct btrfs_fs_info *info)+{+ return BTRFS_LEAF_DATA_SIZE(info) - sizeof(struct btrfs_item);+}++static inline u32 BTRFS_NODEPTRS_PER_BLOCK(const struct btrfs_fs_info *info)+{+ return BTRFS_LEAF_DATA_SIZE(info) / sizeof(struct btrfs_key_ptr);+}++static inline u32 BTRFS_NODEPTRS_PER_EXTENT_BUFFER(const struct extent_buffer *eb)+{+ BUG_ON(eb->fs_info && eb->fs_info->nodesize != eb->len);+ return __BTRFS_LEAF_DATA_SIZE(eb->len) / sizeof(struct btrfs_key_ptr);+}++#define BTRFS_FILE_EXTENT_INLINE_DATA_START \+ (offsetof(struct btrfs_file_extent_item, disk_bytenr))+static inline u32 BTRFS_MAX_INLINE_DATA_SIZE(const struct btrfs_fs_info *info)+{+ return BTRFS_MAX_ITEM_SIZE(info) -+ BTRFS_FILE_EXTENT_INLINE_DATA_START;+}++static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_fs_info *info)+{+ return BTRFS_MAX_ITEM_SIZE(info) - sizeof(struct btrfs_dir_item);+}+ /* * inode items have the data typically returned from stat and store other * info about object characteristics. There is one for every file and dir in@@ -1205,12 +1340,44 @@ #define BTRFS_QGROUP_RELATION_KEY 246 /*- * Persistently stores the io stats in the device tree.- * One key for all stats, (0, BTRFS_DEV_STATS_KEY, devid).+ * Obsolete name, see BTRFS_TEMPORARY_ITEM_KEY. */-#define BTRFS_DEV_STATS_KEY 249+#define BTRFS_BALANCE_ITEM_KEY 248 /*+ * The key type for tree items that are stored persistently, but do not need to+ * exist for extended period of time. The items can exist in any tree.+ *+ * [subtype, BTRFS_TEMPORARY_ITEM_KEY, data]+ *+ * Existing items:+ *+ * - balance status item+ * (BTRFS_BALANCE_OBJECTID, BTRFS_TEMPORARY_ITEM_KEY, 0)+ */+#define BTRFS_TEMPORARY_ITEM_KEY 248++/*+ * Obsolete name, see BTRFS_PERSISTENT_ITEM_KEY+ */+#define BTRFS_DEV_STATS_KEY 249++/*+ * The key type for tree items that are stored persistently and usually exist+ * for a long period, eg. filesystem lifetime. The item kinds can be status+ * information, stats or preference values. The item can exist in any tree.+ *+ * [subtype, BTRFS_PERSISTENT_ITEM_KEY, data]+ *+ * Existing items:+ *+ * - device statistics, store IO stats in the device tree, one key for all+ * stats+ * (BTRFS_DEV_STATS_OBJECTID, BTRFS_DEV_STATS_KEY, 0)+ */+#define BTRFS_PERSISTENT_ITEM_KEY 249++/* * Persistently stores the device replace state in the device tree. * The key is built like this: (0, BTRFS_DEV_REPLACE_KEY, 0). */@@ -1240,6 +1407,15 @@ #define BTRFS_INODE_NODATASUM (1 << 0) #define BTRFS_INODE_NODATACOW (1 << 1) #define BTRFS_INODE_READONLY (1 << 2)+#define BTRFS_INODE_NOCOMPRESS (1 << 3)+#define BTRFS_INODE_PREALLOC (1 << 4)+#define BTRFS_INODE_SYNC (1 << 5)+#define BTRFS_INODE_IMMUTABLE (1 << 6)+#define BTRFS_INODE_APPEND (1 << 7)+#define BTRFS_INODE_NODUMP (1 << 8)+#define BTRFS_INODE_NOATIME (1 << 9)+#define BTRFS_INODE_DIRSYNC (1 << 10)+#define BTRFS_INODE_COMPRESS (1 << 11) #define read_eb_member(eb, ptr, type, member, result) ( \ read_extent_buffer(eb, (char *)(result), \@@ -1697,7 +1873,7 @@ return btrfs_item_end(eb, btrfs_item_nr(nr)); } -static inline u32 btrfs_item_offset_nr(struct extent_buffer *eb, int nr)+static inline u32 btrfs_item_offset_nr(const struct extent_buffer *eb, int nr) { return btrfs_item_offset(eb, btrfs_item_nr(nr)); }@@ -1740,7 +1916,10 @@ BTRFS_SETGET_FUNCS(dir_name_len, struct btrfs_dir_item, name_len, 16); BTRFS_SETGET_FUNCS(dir_transid, struct btrfs_dir_item, transid, 64); +BTRFS_SETGET_STACK_FUNCS(stack_dir_data_len, struct btrfs_dir_item, data_len, 16);+BTRFS_SETGET_STACK_FUNCS(stack_dir_type, struct btrfs_dir_item, type, 8); BTRFS_SETGET_STACK_FUNCS(stack_dir_name_len, struct btrfs_dir_item, name_len, 16);+BTRFS_SETGET_STACK_FUNCS(stack_dir_transid, struct btrfs_dir_item, transid, 64); static inline void btrfs_dir_item_key(struct extent_buffer *eb, struct btrfs_dir_item *item,@@ -1825,17 +2004,6 @@ btrfs_disk_key_to_cpu(key, &disk_key); } --static inline u8 btrfs_key_type(struct btrfs_key *key)-{- return key->type;-}--static inline void btrfs_set_key_type(struct btrfs_key *key, u8 val)-{- key->type = val;-}- /* struct btrfs_header */ BTRFS_SETGET_HEADER_FUNCS(header_bytenr, struct btrfs_header, bytenr, 64); BTRFS_SETGET_HEADER_FUNCS(header_generation, struct btrfs_header,@@ -1895,33 +2063,12 @@ return offsetof(struct btrfs_header, chunk_tree_uuid); } -static inline u8 *btrfs_super_fsid(struct extent_buffer *eb)-{- unsigned long ptr = offsetof(struct btrfs_super_block, fsid);- return (u8 *)ptr;-}- static inline u8 *btrfs_header_csum(struct extent_buffer *eb) { unsigned long ptr = offsetof(struct btrfs_header, csum); return (u8 *)ptr; } -static inline struct btrfs_node *btrfs_buffer_node(struct extent_buffer *eb)-{- return NULL;-}--static inline struct btrfs_leaf *btrfs_buffer_leaf(struct extent_buffer *eb)-{- return NULL;-}--static inline struct btrfs_header *btrfs_buffer_header(struct extent_buffer *eb)-{- return NULL;-}- static inline int btrfs_is_leaf(struct extent_buffer *eb) { return (btrfs_header_level(eb) == 0);@@ -1956,6 +2103,38 @@ BTRFS_SETGET_STACK_FUNCS(root_rtransid, struct btrfs_root_item, rtransid, 64); +static inline struct btrfs_timespec* btrfs_root_ctime(+ struct btrfs_root_item *root_item)+{+ unsigned long ptr = (unsigned long)root_item;+ ptr += offsetof(struct btrfs_root_item, ctime);+ return (struct btrfs_timespec *)ptr;+}++static inline struct btrfs_timespec* btrfs_root_otime(+ struct btrfs_root_item *root_item)+{+ unsigned long ptr = (unsigned long)root_item;+ ptr += offsetof(struct btrfs_root_item, otime);+ return (struct btrfs_timespec *)ptr;+}++static inline struct btrfs_timespec* btrfs_root_stime(+ struct btrfs_root_item *root_item)+{+ unsigned long ptr = (unsigned long)root_item;+ ptr += offsetof(struct btrfs_root_item, stime);+ return (struct btrfs_timespec *)ptr;+}++static inline struct btrfs_timespec* btrfs_root_rtime(+ struct btrfs_root_item *root_item)+{+ unsigned long ptr = (unsigned long)root_item;+ ptr += offsetof(struct btrfs_root_item, rtime);+ return (struct btrfs_timespec *)ptr;+}+ /* struct btrfs_root_backup */ BTRFS_SETGET_STACK_FUNCS(backup_tree_root, struct btrfs_root_backup, tree_root, 64);@@ -2036,8 +2215,6 @@ sectorsize, 32); BTRFS_SETGET_STACK_FUNCS(super_nodesize, struct btrfs_super_block, nodesize, 32);-BTRFS_SETGET_STACK_FUNCS(super_leafsize, struct btrfs_super_block,- leafsize, 32); BTRFS_SETGET_STACK_FUNCS(super_stripesize, struct btrfs_super_block, stripesize, 32); BTRFS_SETGET_STACK_FUNCS(super_root_dir, struct btrfs_super_block,@@ -2183,7 +2360,50 @@ BTRFS_SETGET_STACK_FUNCS(stack_qgroup_limit_rsv_exclusive, struct btrfs_qgroup_limit_item, rsv_exclusive, 64); +/* btrfs_balance_item */+BTRFS_SETGET_FUNCS(balance_item_flags, struct btrfs_balance_item, flags, 64);++static inline struct btrfs_disk_balance_args* btrfs_balance_item_data(+ struct extent_buffer *eb, struct btrfs_balance_item *bi)+{+ unsigned long offset = (unsigned long)bi;+ struct btrfs_balance_item *p;+ p = (struct btrfs_balance_item *)(eb->data + offset);+ return &p->data;+}++static inline struct btrfs_disk_balance_args* btrfs_balance_item_meta(+ struct extent_buffer *eb, struct btrfs_balance_item *bi)+{+ unsigned long offset = (unsigned long)bi;+ struct btrfs_balance_item *p;+ p = (struct btrfs_balance_item *)(eb->data + offset);+ return &p->meta;+}++static inline struct btrfs_disk_balance_args* btrfs_balance_item_sys(+ struct extent_buffer *eb, struct btrfs_balance_item *bi)+{+ unsigned long offset = (unsigned long)bi;+ struct btrfs_balance_item *p;+ p = (struct btrfs_balance_item *)(eb->data + offset);+ return &p->sys;+}+ /*+ * btrfs_dev_stats_item helper, returns pointer to the raw array, do the+ * endiannes conversion, @dsi is offset to eb data+ */+static inline __le64* btrfs_dev_stats_values(struct extent_buffer *eb,+ struct btrfs_dev_stats_item *dsi)+{+ unsigned long offset = (unsigned long)dsi;+ struct btrfs_dev_stats_item *p;+ p = (struct btrfs_dev_stats_item *)(eb->data + offset);+ return p->values;+}++/* * this returns the number of bytes used by the item on disk, minus the * size of any extent headers. If a file is compressed on disk, this is * the compressed size@@ -2222,47 +2442,20 @@ 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- */-static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,- int slot,- struct btrfs_file_extent_item *fi)-{- /*- * return the space used on disk if this item isn't- * compressed or encoded- */- if (btrfs_file_extent_compression(eb, fi) == 0 &&- btrfs_file_extent_encryption(eb, fi) == 0 &&- btrfs_file_extent_other_encoding(eb, fi) == 0) {- return btrfs_file_extent_inline_item_len(eb,- btrfs_item_nr(slot));- }-- /* otherwise use the ram bytes field */- 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;- return root->nodesize;-}+#define btrfs_fs_incompat(fs_info, opt) \+ __btrfs_fs_incompat((fs_info), BTRFS_FEATURE_INCOMPAT_##opt) -static inline int btrfs_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag)+static inline bool __btrfs_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag) { struct btrfs_super_block *disk_super; disk_super = fs_info->super_copy; return !!(btrfs_super_incompat_flags(disk_super) & flag); } -static inline int btrfs_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag)+#define btrfs_fs_compat_ro(fs_info, opt) \+ __btrfs_fs_compat_ro((fs_info), BTRFS_FEATURE_COMPAT_RO_##opt)++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;@@ -2283,14 +2476,12 @@ struct btrfs_root *root, u64 num_bytes, u64 empty_size, u64 hint_byte, u64 search_end,- struct btrfs_key *ins, int data);-int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans,- struct btrfs_root *root);+ struct btrfs_key *ins, bool is_data);+int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans); void btrfs_pin_extent(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes); void btrfs_unpin_extent(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes);-int btrfs_extent_post_op(struct btrfs_trans_handle *trans,- struct btrfs_root *root);+int btrfs_extent_post_op(struct btrfs_trans_handle *trans); struct btrfs_block_group_cache *btrfs_lookup_block_group(struct btrfs_fs_info *info, u64 bytenr);@@ -2302,22 +2493,19 @@ u32 blocksize, u64 root_objectid, struct btrfs_disk_key *key, int level, u64 hint, u64 empty_size);-int btrfs_alloc_extent(struct btrfs_trans_handle *trans,- struct btrfs_root *root,- u64 num_bytes, u64 parent,- u64 root_objectid, u64 ref_generation,- u64 owner, u64 empty_size, u64 hint_byte,- u64 search_end, struct btrfs_key *ins, int data); int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,- struct btrfs_root *root, u64 bytenr,+ struct btrfs_fs_info *fs_info, u64 bytenr, u64 offset, int metadata, u64 *refs, u64 *flags);-int btrfs_set_block_flags(struct btrfs_trans_handle *trans,- struct btrfs_root *root,- u64 bytenr, int level, u64 flags);+int btrfs_set_block_flags(struct btrfs_trans_handle *trans, u64 bytenr,+ int level, u64 flags); int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, int record_parent); int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, int record_parent);+int btrfs_free_tree_block(struct btrfs_trans_handle *trans,+ struct btrfs_root *root,+ struct extent_buffer *buf,+ u64 parent, int last_ref); int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u64 num_bytes, u64 parent,@@ -2341,15 +2529,13 @@ int btrfs_read_block_groups(struct btrfs_root *root); struct btrfs_block_group_cache * btrfs_add_block_group(struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type,- u64 chunk_objectid, u64 chunk_offset, u64 size);+ u64 chunk_offset, u64 size); int btrfs_make_block_group(struct btrfs_trans_handle *trans,- struct btrfs_root *root, u64 bytes_used,- u64 type, u64 chunk_objectid, u64 chunk_offset,- u64 size);+ struct btrfs_fs_info *fs_info, u64 bytes_used,+ u64 type, u64 chunk_offset, u64 size); int btrfs_make_block_groups(struct btrfs_trans_handle *trans,- struct btrfs_root *root);-int btrfs_update_block_group(struct btrfs_trans_handle *trans,- struct btrfs_root *root, u64 bytenr, u64 num,+ struct btrfs_fs_info *fs_info);+int btrfs_update_block_group(struct btrfs_root *root, u64 bytenr, u64 num, int alloc, int mark_free); int btrfs_record_file_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid,@@ -2364,10 +2550,12 @@ 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);+u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset);+ /* 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,- struct btrfs_path *path, int level, int slot);+int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path,+ int level, int slot); enum btrfs_tree_block_status btrfs_check_node(struct btrfs_root *root, struct btrfs_disk_key *parent_key, struct extent_buffer *buf);@@ -2376,7 +2564,7 @@ struct extent_buffer *buf); void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, int level, int slot, u64 objectid);-struct extent_buffer *read_node_slot(struct btrfs_root *root,+struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info, struct extent_buffer *parent, int slot); int btrfs_previous_item(struct btrfs_root *root, struct btrfs_path *path, u64 min_objectid,@@ -2399,11 +2587,9 @@ struct btrfs_root *root, struct extent_buffer *buf, struct extent_buffer **cow_ret, u64 new_root_objectid);-int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root- *root, struct btrfs_path *path, u32 data_size);-int btrfs_truncate_item(struct btrfs_trans_handle *trans,- struct btrfs_root *root,- struct btrfs_path *path,+int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path,+ u32 data_size);+int btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path, u32 new_size, int from_end); int btrfs_split_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,@@ -2458,7 +2644,7 @@ } 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);+int btrfs_leaf_free_space(struct extent_buffer *leaf); void btrfs_fixup_low_keys(struct btrfs_root *root, struct btrfs_path *path, struct btrfs_disk_key *key, int level); int btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path,@@ -2476,6 +2662,8 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, struct btrfs_root_item *item);+int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,+ struct btrfs_key *key); int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, struct btrfs_root_item *item);@@ -2535,14 +2723,13 @@ 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 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,- struct btrfs_root *root, u64 bytenr, u64 len);+int btrfs_del_csums(struct btrfs_trans_handle *trans, u64 bytenr, u64 len); int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 pos, u64 offset,@@ -2550,7 +2737,7 @@ u64 num_bytes); int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid,- u64 offset, char *buffer, size_t size);+ u64 offset, const char *buffer, size_t size); int btrfs_csum_file_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 alloc_end, u64 bytenr, char *data, size_t len);@@ -2576,9 +2763,11 @@ u64 dir, u64 index); int btrfs_new_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 ino, u32 mode);+int btrfs_change_inode_flags(struct btrfs_trans_handle *trans,+ struct btrfs_root *root, u64 ino, u64 flags); 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);+ u8 type, u64 *index, int add_backref, int ignore_existed); 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);@@ -2587,6 +2776,8 @@ 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);+struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, const char *base,+ u64 root_objectid, bool convert); /* file.c */ int btrfs_get_extent(struct btrfs_trans_handle *trans,@@ -2596,4 +2787,7 @@ int btrfs_punch_hole(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 ino, u64 offset, u64 len);+int btrfs_read_file(struct btrfs_root *root, u64 ino, u64 start, int len,+ char *dest);+ #endif
include/btrfs/extent-cache.h view
@@ -106,8 +106,6 @@ */ 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); /*
include/btrfs/extent_io.h view
@@ -75,6 +75,7 @@ struct cache_tree cache; struct list_head lru; u64 cache_size;+ u64 max_cache_size; }; struct extent_state {@@ -90,14 +91,15 @@ struct cache_extent cache_node; u64 start; u64 dev_bytenr;- u32 len; struct extent_io_tree *tree; struct list_head lru; struct list_head recow;+ u32 len; int refs; u32 flags; int fd;- char data[];+ struct btrfs_fs_info *fs_info;+ char data[] __attribute__((aligned(8))); }; static inline void extent_buffer_get(struct extent_buffer *eb)@@ -106,27 +108,24 @@ } void extent_io_tree_init(struct extent_io_tree *tree);+void extent_io_tree_init_cache_max(struct extent_io_tree *tree,+ u64 max_cache_size); void extent_io_tree_cleanup(struct extent_io_tree *tree);-int set_extent_bits(struct extent_io_tree *tree, u64 start,- u64 end, int bits, gfp_t mask);-int clear_extent_bits(struct extent_io_tree *tree, u64 start,- u64 end, int bits, gfp_t mask);+int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, int bits);+int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, int bits); int find_first_extent_bit(struct extent_io_tree *tree, u64 start, u64 *start_ret, u64 *end_ret, int bits); int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits, int filled);-int set_extent_dirty(struct extent_io_tree *tree, u64 start,- u64 end, gfp_t mask);-int clear_extent_dirty(struct extent_io_tree *tree, u64 start,- u64 end, gfp_t mask);+int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end);+int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end); 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)+static inline int clear_extent_buffer_uptodate(struct extent_buffer *eb) { eb->flags &= ~EXTENT_UPTODATE; return 0;@@ -147,10 +146,11 @@ u64 bytenr, u32 blocksize); struct extent_buffer *find_first_extent_buffer(struct extent_io_tree *tree, u64 start);-struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,+struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, u64 bytenr, u32 blocksize); struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src); void free_extent_buffer(struct extent_buffer *eb);+void free_extent_buffer_nocache(struct extent_buffer *eb); int read_extent_from_disk(struct extent_buffer *eb, unsigned long offset, unsigned long len); int write_extent_to_disk(struct extent_buffer *eb);
include/btrfs/ioctl.h view
@@ -25,11 +25,17 @@ #include <asm/types.h> #include <linux/ioctl.h>+#include <stddef.h> #ifndef __user #define __user #endif +/* We don't want to include entire kerncompat.h */+#ifndef BUILD_ASSERT+#define BUILD_ASSERT(x)+#endif+ #define BTRFS_IOCTL_MAGIC 0x94 #define BTRFS_VOL_NAME_MAX 255 @@ -39,6 +45,7 @@ __s64 fd; char name[BTRFS_PATH_NAME_MAX + 1]; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_vol_args) == 4096); #define BTRFS_DEVICE_PATH_NAME_MAX 1024 @@ -65,6 +72,7 @@ __u64 rsv_referenced; __u64 rsv_exclusive; };+BUILD_ASSERT(sizeof(struct btrfs_qgroup_limit) == 40); struct btrfs_qgroup_inherit { __u64 flags;@@ -74,11 +82,13 @@ struct btrfs_qgroup_limit lim; __u64 qgroups[0]; };+BUILD_ASSERT(sizeof(struct btrfs_qgroup_inherit) == 72); struct btrfs_ioctl_qgroup_limit_args { __u64 qgroupid; struct btrfs_qgroup_limit lim; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_qgroup_limit_args) == 48); #define BTRFS_SUBVOL_NAME_MAX 4039 struct btrfs_ioctl_vol_args_v2 {@@ -97,6 +107,7 @@ __u64 devid; }; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_vol_args_v2) == 4096); /* * structure to report errors and progress to userspace, either as a@@ -145,6 +156,7 @@ /* pad to 1k */ __u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8]; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_scrub_args) == 1024); #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS 0 #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID 1@@ -155,6 +167,7 @@ __u8 srcdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1]; /* in */ __u8 tgtdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1]; /* in */ };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_dev_replace_start_params) == 2072); #define BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED 0 #define BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED 1@@ -169,6 +182,7 @@ __u64 num_write_errors; /* out */ __u64 num_uncorrectable_read_errors; /* out */ };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_dev_replace_status_params) == 48); #define BTRFS_IOCTL_DEV_REPLACE_CMD_START 0 #define BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS 1@@ -189,6 +203,7 @@ __u64 spare[64]; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_dev_replace_args) == 2600); struct btrfs_ioctl_dev_info_args { __u64 devid; /* in/out */@@ -198,6 +213,7 @@ __u64 unused[379]; /* pad to 4k */ __u8 path[BTRFS_DEVICE_PATH_NAME_MAX]; /* out */ };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_dev_info_args) == 4096); struct btrfs_ioctl_fs_info_args { __u64 max_id; /* out */@@ -209,12 +225,14 @@ __u32 reserved32; __u64 reserved[122]; /* pad to 1k */ };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_fs_info_args) == 1024); struct btrfs_ioctl_feature_flags { __u64 compat_flags; __u64 compat_ro_flags; __u64 incompat_flags; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_feature_flags) == 24); /* balance control ioctl modes */ #define BTRFS_BALANCE_CTL_PAUSE 1@@ -292,6 +310,7 @@ __u64 unused[72]; /* pad to 1k */ };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_balance_args) == 1024); #define BTRFS_INO_LOOKUP_PATH_MAX 4080 struct btrfs_ioctl_ino_lookup_args {@@ -299,6 +318,7 @@ __u64 objectid; char name[BTRFS_INO_LOOKUP_PATH_MAX]; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_ino_lookup_args) == 4096); struct btrfs_ioctl_search_key { /* which root are we searching. 0 is the tree of tree roots */@@ -366,6 +386,7 @@ * to store item */ __u64 buf[0]; /* out - found items */ };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_search_args_v2) == 112); /* With a @src_length of zero, the range from @src_offset->EOF is cloned! */ struct btrfs_ioctl_clone_range_args {@@ -373,6 +394,7 @@ __u64 src_offset, src_length; __u64 dest_offset; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_clone_range_args) == 32); /* flags for the defrag range ioctl */ #define BTRFS_DEFRAG_RANGE_COMPRESS 1@@ -402,6 +424,7 @@ __u32 reserved2; struct btrfs_ioctl_same_extent_info info[0]; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_same_args) == 24); struct btrfs_ioctl_defrag_range_args { /* start of the defrag operation */@@ -433,6 +456,7 @@ /* spare for later */ __u32 unused[4]; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_defrag_range_args) == 48); struct btrfs_ioctl_space_info { __u64 flags;@@ -445,6 +469,7 @@ __u64 total_spaces; struct btrfs_ioctl_space_info spaces[0]; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_space_args) == 16); struct btrfs_data_container { __u32 bytes_left; /* out -- bytes not needed to deliver output */@@ -461,6 +486,7 @@ /* struct btrfs_data_container *fspath; out */ __u64 fspath; /* out */ };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_ino_path_args) == 56); struct btrfs_ioctl_logical_ino_args { __u64 logical; /* in */@@ -500,8 +526,9 @@ /* out values: */ __u64 values[BTRFS_DEV_STAT_VALUES_MAX]; - __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */+ __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k + 8B */ };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_get_dev_stats) == 1032); /* BTRFS_IOC_SNAP_CREATE is no longer used by the btrfs command */ #define BTRFS_QUOTA_CTL_ENABLE 1@@ -511,12 +538,14 @@ __u64 cmd; __u64 status; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_quota_ctl_args) == 16); struct btrfs_ioctl_quota_rescan_args { __u64 flags; __u64 progress; __u64 reserved[6]; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_quota_rescan_args) == 64); struct btrfs_ioctl_qgroup_assign_args { __u64 assign;@@ -528,6 +557,8 @@ __u64 create; __u64 qgroupid; };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_qgroup_create_args) == 16);+ struct btrfs_ioctl_timespec { __u64 sec; __u32 nsec;@@ -542,8 +573,41 @@ __u64 flags; /* in */ __u64 reserved[16]; /* in */ };+BUILD_ASSERT(sizeof(struct btrfs_ioctl_received_subvol_args) == 200); /*+ * If we have a 32-bit userspace and 64-bit kernel, then the UAPI+ * structures are incorrect, as the timespec structure from userspace+ * is 4 bytes too small. We define these alternatives here for backward+ * compatibility, the kernel understands both values.+ */++/*+ * Structure size is different on 32bit and 64bit, has some padding if the+ * structure is embedded. Packing makes sure the size is same on both, but will+ * be misaligned on 64bit.+ *+ * NOTE: do not use in your code, this is for testing only+ */+struct btrfs_ioctl_timespec_32 {+ __u64 sec;+ __u32 nsec;+} __attribute__ ((__packed__));++struct btrfs_ioctl_received_subvol_args_32 {+ char uuid[BTRFS_UUID_SIZE]; /* in */+ __u64 stransid; /* in */+ __u64 rtransid; /* out */+ struct btrfs_ioctl_timespec_32 stime; /* in */+ struct btrfs_ioctl_timespec_32 rtime; /* out */+ __u64 flags; /* in */+ __u64 reserved[16]; /* in */+} __attribute__ ((__packed__));+BUILD_ASSERT(sizeof(struct btrfs_ioctl_received_subvol_args_32) == 192);++#define BTRFS_IOC_SET_RECEIVED_SUBVOL_32_COMPAT_DEFINED 1++/* * 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.@@ -576,7 +640,38 @@ __u64 flags; /* in */ __u64 reserved[4]; /* in */ };+/*+ * Size of structure depends on pointer width, was not caught in the early+ * days. Kernel handles pointer width differences transparently.+ */+BUILD_ASSERT(sizeof(__u64 *) == 8+ ? sizeof(struct btrfs_ioctl_send_args) == 72+ : (sizeof(void *) == 4+ ? sizeof(struct btrfs_ioctl_send_args) == 68+ : 0)); +/*+ * Different pointer width leads to structure size change. Kernel should accept+ * both ioctl values (derived from the structures) for backward compatibility.+ * Size of this structure is same on 32bit and 64bit though.+ *+ * NOTE: do not use in your code, this is for testing only+ */+struct btrfs_ioctl_send_args_64 {+ __s64 send_fd; /* in */+ __u64 clone_sources_count; /* in */+ union {+ __u64 __user *clone_sources; /* in */+ __u64 __clone_sources_alignment;+ };+ __u64 parent_root; /* in */+ __u64 flags; /* in */+ __u64 reserved[4]; /* in */+} __attribute__((packed));+BUILD_ASSERT(sizeof(struct btrfs_ioctl_send_args_64) == 72);++#define BTRFS_IOC_SEND_64_COMPAT_DEFINED 1+ /* Error codes as returned by the kernel */ enum btrfs_err_code { notused,@@ -688,6 +783,17 @@ struct btrfs_ioctl_logical_ino_args) #define BTRFS_IOC_SET_RECEIVED_SUBVOL _IOWR(BTRFS_IOCTL_MAGIC, 37, \ struct btrfs_ioctl_received_subvol_args)++#ifdef BTRFS_IOC_SET_RECEIVED_SUBVOL_32_COMPAT_DEFINED+#define BTRFS_IOC_SET_RECEIVED_SUBVOL_32 _IOWR(BTRFS_IOCTL_MAGIC, 37, \+ struct btrfs_ioctl_received_subvol_args_32)+#endif++#ifdef BTRFS_IOC_SEND_64_COMPAT_DEFINED+#define BTRFS_IOC_SEND_64 _IOW(BTRFS_IOCTL_MAGIC, 38, \+ struct btrfs_ioctl_send_args_64)+#endif+ #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)
include/btrfs/kerncompat.h view
@@ -68,6 +68,14 @@ #define ULONG_MAX (~0UL) #endif +#define __token_glue(a,b,c) ___token_glue(a,b,c)+#define ___token_glue(a,b,c) a ## b ## c+#ifdef DEBUG_BUILD_CHECKS+#define BUILD_ASSERT(x) extern int __token_glue(compile_time_assert_,__LINE__,__COUNTER__)[1-2*!(x)] __attribute__((unused))+#else+#define BUILD_ASSERT(x)+#endif+ #ifndef BTRFS_DISABLE_BACKTRACE #define MAX_BACKTRACE 16 static inline void print_trace(void)@@ -78,26 +86,35 @@ size = backtrace(array, MAX_BACKTRACE); backtrace_symbols_fd(array, size, 2); }+#endif -static inline void assert_trace(const char *assertion, const char *filename,- const char *func, unsigned line, int val)+static inline void warning_trace(const char *assertion, const char *filename,+ const char *func, unsigned line, long val) {- if (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);+ fprintf(stderr,+ "%s:%d: %s: Warning: assertion `%s` failed, value %ld\n",+ filename, line, func, assertion, val);+#ifndef BTRFS_DISABLE_BACKTRACE print_trace();- exit(1);+#endif } -#define BUG() assert_trace(NULL, __FILE__, __func__, __LINE__, 0)-#else-#define BUG() assert(0)+static inline void bugon_trace(const char *assertion, const char *filename,+ const char *func, unsigned line, long val)+{+ if (!val)+ return;+ fprintf(stderr,+ "%s:%d: %s: BUG_ON `%s` triggered, value %ld\n",+ filename, line, func, assertion, val);+#ifndef BTRFS_DISABLE_BACKTRACE+ print_trace(); #endif+ abort();+ exit(1);+} #ifdef __CHECKER__ #define __force __attribute__((force))@@ -236,11 +253,16 @@ return (long) ptr; } -static inline long IS_ERR(const void *ptr)+static inline int IS_ERR(const void *ptr) { return IS_ERR_VALUE((unsigned long)ptr); } +static inline int IS_ERR_OR_NULL(const void *ptr)+{+ return !ptr || IS_ERR(ptr);+}+ /* * 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@@ -269,27 +291,39 @@ #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))-#endif--#define WARN_ON(c) BUG_ON(c)-+static inline void assert_trace(const char *assertion, const char *filename,+ const char *func, unsigned line, long val)+{+ if (val)+ return;+ fprintf(stderr,+ "%s:%d: %s: Assertion `%s` failed, value %ld\n",+ filename, line, func, assertion, val); #ifndef BTRFS_DISABLE_BACKTRACE-#define ASSERT(c) assert_trace(#c, __FILE__, __func__, __LINE__, (c))+ print_trace();+#endif+ abort();+ exit(1);+}+#define ASSERT(c) assert_trace(#c, __FILE__, __func__, __LINE__, (long)(c)) #else #define ASSERT(c) assert(c) #endif +#define BUG_ON(c) bugon_trace(#c, __FILE__, __func__, __LINE__, (long)(c))+#define BUG() BUG_ON(1)+#define WARN_ON(c) warning_trace(#c, __FILE__, __func__, __LINE__, (long)(c))+ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})+#ifndef __bitwise #ifdef __CHECKER__ #define __bitwise __bitwise__ #else #define __bitwise-#endif+#endif /* __CHECKER__ */+#endif /* __bitwise */ /* Alignment check */ #define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)
+ include/btrfs/sizes.h view
@@ -0,0 +1,47 @@+/*+ * include/linux/sizes.h+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ */+#ifndef __LINUX_SIZES_H__+#define __LINUX_SIZES_H__++#define SZ_1 0x00000001+#define SZ_2 0x00000002+#define SZ_4 0x00000004+#define SZ_8 0x00000008+#define SZ_16 0x00000010+#define SZ_32 0x00000020+#define SZ_64 0x00000040+#define SZ_128 0x00000080+#define SZ_256 0x00000100+#define SZ_512 0x00000200++#define SZ_1K 0x00000400+#define SZ_2K 0x00000800+#define SZ_4K 0x00001000+#define SZ_8K 0x00002000+#define SZ_16K 0x00004000+#define SZ_32K 0x00008000+#define SZ_64K 0x00010000+#define SZ_128K 0x00020000+#define SZ_256K 0x00040000+#define SZ_512K 0x00080000++#define SZ_1M 0x00100000+#define SZ_2M 0x00200000+#define SZ_4M 0x00400000+#define SZ_8M 0x00800000+#define SZ_16M 0x01000000+#define SZ_32M 0x02000000+#define SZ_64M 0x04000000+#define SZ_128M 0x08000000+#define SZ_256M 0x10000000+#define SZ_512M 0x20000000++#define SZ_1G 0x40000000+#define SZ_2G 0x80000000++#endif /* __LINUX_SIZES_H__ */
include/sys/capability.h view
@@ -27,7 +27,6 @@ #define __user #endif #include <linux/capability.h>-#include <linux/xattr.h> /* * POSIX capability types