monky-2.0.0.0: Monky/Disk/Btrfs.hs
{-
Copyright 2015 Markus Ongyerth, Stephan Guenther
This file is part of Monky.
Monky is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Monky is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Monky. If not, see <http://www.gnu.org/licenses/>.
-}
{-# LANGUAGE CPP #-}
{-|
Module : Monky.Disk.Btrfs
Description : Allows access to information about a btrfs pool
Maintainer : ongy
Stability : experimental
Portability : Linux
This module allows for some support for btrfs devices.
This may be renamed in the future when a general block-device module appears.
-}
module Monky.Disk.Btrfs
( BtrfsHandle
, getBtrfsHandle
, getFSDevices
)
where
import Monky.Utility
import System.Directory (doesDirectoryExist)
import Monky.Disk.Common
#if MIN_VERSION_base(4,8,0)
#else
import Control.Applicative ((<$>))
#endif
-- Size data metadata system
-- |The FsInfo exported by this module
data BtrfsHandle = BtrfsH Int File File File
instance FsInfo BtrfsHandle where
getFsSize = return . getSize
getFsUsed = getUsed
fsBasePath :: String
fsBasePath = "/sys/fs/btrfs/"
sectorSize :: Int
sectorSize = 512
getSize :: BtrfsHandle -> Int
getSize (BtrfsH s _ _ _) = s
getUsed :: BtrfsHandle -> IO Int
getUsed (BtrfsH _ d m s) = do
dv <- readValue d
mv <- readValue m
sm <- readValue s
return $ dv + mv + sm
-- |Get the block devices used by a btrfs FileSystem. This resolves mappers as far as possible
getFSDevices :: String -> IO [String]
getFSDevices fs = do
let devP = fsBasePath ++ fs ++ "/devices/"
concat <$> (mapM mapperToDev =<< listDirectory devP)
getBtrfsHandle' :: String -> IO BtrfsHandle
getBtrfsHandle' fs = do
devices <- getFSDevices fs
sizes <- mapM (\dev -> fmap read $ readFile (blBasePath ++ dev ++ "/size")) devices
let size = sum sizes
d <- fopen (fsBasePath ++ fs ++ "/allocation/data/bytes_used")
m <- fopen (fsBasePath ++ fs ++ "/allocation/metadata/bytes_used")
s <- fopen (fsBasePath ++ fs ++ "/allocation/system/bytes_used")
return (BtrfsH (size*sectorSize) d m s)
{-| Try to create a btfshanlde given the UUID
This will create a 'BtrfsHandle' which is an instance of FsInfo and
a list of block devices that are slaves of our file system.
This allows the upper layer to monitor the read/write rates of all
block devices that belong to our file system and report them as
read/write rate for the file system.
Due to compression and encryption the read/write rate on the block
device may be quite different to the one that application see.
-}
getBtrfsHandle
:: String -- ^The UUID of the file system to monitor
-> IO (Maybe (BtrfsHandle, [String]))
getBtrfsHandle fs = do
e <- doesDirectoryExist (fsBasePath ++ fs)
if e
then do
h <- getBtrfsHandle' fs
devs <- getFSDevices fs
return $ Just (h, devs)
else return Nothing