{- 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