btrfs 空闲空间管理(四) fstrim

源文件
      util-linux-<version>/sys-utils/fstrim.c
      linux/fs/btrfs/ioctl.c
      linux/fs/btrfs/extent-tree.c
      linux/fs/btrfs/free-space-cache.c

用户态工具 fstrim

fstrim 是 util-linux 软件包中提供的工具:
      discard unused blocks on a mounted filesystem
该工具有 3 个选项跟要 discard 的范围有关:

       -o, --offset offset
              Byte  offset  in filesystem from which to begin searching for free blocks
              to discard.  Default value is zero, starting  at  the  beginning  of  the
              filesystem.

       -l, --length length
              Number  of  bytes  after starting point to search for free blocks to dis‐
              card.  If the specified value extends past the  end  of  the  filesystem,
              fstrim  will  stop at the filesystem size boundary. Default value extends
              to the end of the filesystem.

       -m, --minimum minimum-free-extent
              Minimum contiguous free range to discard, in bytes. (This value is inter‐
              nally  rounded  up  to  a  multiple  of the filesystem block size).  Free
              ranges smaller than this will be ignored.  By increasing this value,  the
              fstrim  operation  will  complete more quickly for filesystems with badly
              fragmented freespace, although not all blocks will be discarded.  Default
              value is zero, discard every free block.

查看 fstrim.c 的源文件,可以看到,fstrim 将 3 个范围参数封装到结构 struct fstrim_range 中,

    struct fstrim_range {
        uint64_t start;
        uint64_t len;
        uint64_t minlen;
    };

然后通过 ioctl 命令 FITRIM 来完成实际的 discard 操作:

    ioctl(fd, FITRIM, &range)

 

ioctl 接收 FITRIM 命令

btrfs/ioctl.c 对 FITRIM 命令进行处理:

    case FITRIM:
        return btrfs_ioctl_fitrim(file, argp);

ioctl.c 文件中也定义了函数 btrfs_ioctl_fitrim,该函数对参数进行检验调整后(比如调整 minlen 为文件系统设备所支持的最小 discard 粒度,如果这个粒度比命令指定的 minlen 小的话,调整范围不会超出文件末尾),转而由 btrfs_trim_fs(fs_info->tree_root, &range) 来完成实际的工作。

btrfs_trim_fs 在 extent-tree.c 中定义,其工作就是从指定的起始地址对应的 block group 开始,对指定范围内所覆盖的 bg,逐个执行btrfs_trim_block_group。这就是工作的分解:
      fstrim 整个文件系统 -> 逐个 trim 文件系统内的块组
btrfs_trim_block_group 实现在 free-space-cache.c 中。

btrfs_trim_block_group

    int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
                   u64 *trimmed, u64 start, u64 end, u64 minlen)
    {
        int ret;
    
        *trimmed = 0;
 
        ret = trim_no_bitmap(block_group, trimmed, start, end, minlen);
        if (ret)
            return ret;
    
        ret = trim_bitmaps(block_group, trimmed, start, end, minlen);
    
        return ret;
    }

可以看出,trim bg 实际上是对 bg 下面的 extent/bitmap 空闲空间记录进行 trim。

trim_no_bitmap 和 trim_bitmaps 都会调用 btrfs_error_discard_extent,而 btrfs_error_discard_extent 是对 btrfs_discard_extent 的简单封装。btrfs_discard_extent 会调用 btrfs_issue_discard,最终调用 blkdev_issue_discard 向块设备发送 Discard/TRIM 命令

对于 free-space-cache 来说,trim 就是把对应的空闲空间记录给销毁

小结

fstrim 的执行流程:

fstrim -> FITRIM -> btrfs_ioctl_fitrim 
    -> btrfs_trim_fs 
        -> btrfs_trim_block_group -> trim_no_bitmap / trim_bitmaps 
            -> btrfs_error_discard_extent -> btrfs_discard_extent 
                -> btrfs_issue_discard -> blkdev_issue_discard        

posted on 2012-11-27 22:15  refrag  阅读(5053)  评论(0编辑  收藏  举报

导航