BTRFS hot relocation support
Subsystems (3)
v2 cover BTRFS hot relocation support
From: Zhi Yong Wu <[email protected]>
This patchset can work well with the patchset v3 for VFS
hot tracking in RAID single mode now.
The patchset as RFC is sent out mainly to see if its design
goes in the correct development direction.
When working on this feature, i am trying to change as less
the existing btrfs code as possible. After V0 was sent out, i carefully checked the patchset for speed profile, and don't think that it is meanful to BTRFS hot relocation, but think that it is one simple and effective way to introduce one new block group for nonrotating disk to differentiate if the block space is reserved from rotating disk or nonrotating disk; So It's very appreciated that the developers can double check if the design is appropriate to BTRFS hot relocation.
The patchset is trying to introduce hot relocation support
for BTRFS. In hybrid storage environment, when the data in rotating disk get hot, it can be relocated to nonrotating disk by BTRFS hot relocation support automatically; also, if nonrotating disk ratio exceed its upper threshold, the data which get cold can be looked up and relocated to rotating disk to make more space in nonrotating disk at first, and then the data which get hot will be relocated to nonrotating disk automatically.
BTRFS hot relocation mainly reserve block space from nonrotating
disk at first, load the hot data to page cache from rotating disk, allocate block space from nonrotating disk, and finally write the data to it.
Below is its TODO list:
- BTRFS RAID full support. [Martin Steigerwald, Zhiyong]
- Mark files as hot via ioctl. [Martin Steigerwald]
- Easier setup. With BTRFS flexibility I would expect that a SSD as hot data
cache can be added and removed on the fly during filesystem is mounted. Only seems supported at mkfs-time as I read the patch docs, but from my basic technical understanding of BTRFS it can be extented to be done on the fly with a mounted FS as well. [Martin Steigerwald]
If you'd like to play with it, pls pull the patchset from
my git on github:
https://github.com/wuzhy/kernel.git hot_reloc
For how to use, please refer too the example below:
root@debian-i386:~# echo 0 > /sys/block/vdc/queue/rotational ^^^ Above command will hack /dev/vdc to be one SSD disk root@debian-i386:~# echo 999999 > /proc/sys/fs/hot-age-interval root@debian-i386:~# echo 10 > /proc/sys/fs/hot-update-interval root@debian-i386:~# echo 10 > /proc/sys/fs/hot-reloc-interval root@debian-i386:~# mkfs.btrfs -d single -m single -h /dev/vdb /dev/vdc -f
WARNING! - Btrfs v0.20-rc1-254-gb0136aa-dirty IS EXPERIMENTAL WARNING! - see http://btrfs.wiki.kernel.org before using
[ 140.279011] device fsid c563a6dc-f192-41a9-9fe1-5a3aa01f5e4c devid 1 transid 16 /dev/vdb [ 140.283650] device fsid c563a6dc-f192-41a9-9fe1-5a3aa01f5e4c devid 2 transid 16 /dev/vdc [ 140.550759] device fsid 197d47a7-b9cd-46a8-9360-eb087b119424 devid 1 transid 3 /dev/vdb [ 140.552473] device fsid c563a6dc-f192-41a9-9fe1-5a3aa01f5e4c devid 2 transid 16 /dev/vdc adding device /dev/vdc id 2 [ 140.636215] device fsid 197d47a7-b9cd-46a8-9360-eb087b119424 devid 2 transid 3 /dev/vdc fs created label (null) on /dev/vdb nodesize 4096 leafsize 4096 sectorsize 4096 size 14.65GB Btrfs v0.20-rc1-254-gb0136aa-dirty root@debian-i386:~# mount -o hot_move /dev/vdb /data2 [ 144.855471] device fsid 197d47a7-b9cd-46a8-9360-eb087b119424 devid 1 transid 6 /dev/vdb [ 144.870444] btrfs: disk space caching is enabled [ 144.904214] VFS: Turning on hot data tracking root@debian-i386:~# dd if=/dev/zero of=/data2/test1 bs=1M count=2048 2048+0 records in 2048+0 records out 2147483648 bytes (2.1 GB) copied, 23.4948 s, 91.4 MB/s root@debian-i386:~# df -h Filesystem Size Used Avail Use% Mounted on /dev/vda1 16G 13G 2.2G 86% / tmpfs 4.8G 0 4.8G 0% /lib/init/rw udev 10M 176K 9.9M 2% /dev tmpfs 4.8G 0 4.8G 0% /dev/shm /dev/vdb 15G 2.0G 13G 14% /data2 root@debian-i386:~# btrfs fi df /data2 Data: total=3.01GB, used=2.00GB System: total=4.00MB, used=4.00KB Metadata: total=8.00MB, used=2.19MB Data_SSD: total=8.00MB, used=0.00 root@debian-i386:~# echo 108 > /proc/sys/fs/hot-reloc-threshold ^^^ Above command will start HOT RLEOCATE, because The data temperature is currently 109 root@debian-i386:~# df -h Filesystem Size Used Avail Use% Mounted on /dev/vda1 16G 13G 2.2G 86% / tmpfs 4.8G 0 4.8G 0% /lib/init/rw udev 10M 176K 9.9M 2% /dev tmpfs 4.8G 0 4.8G 0% /dev/shm /dev/vdb 15G 2.1G 13G 14% /data2 root@debian-i386:~# btrfs fi df /data2 Data: total=3.01GB, used=6.25MB System: total=4.00MB, used=4.00KB Metadata: total=8.00MB, used=2.26MB Data_SSD: total=2.01GB, used=2.00GB root@debian-i386:~#
Changelog from v1:
- Fixed up one nospc bug which is introduced by this feature.
v1:
- Refactor introducing one new block group.
Zhi Yong Wu (5):
BTRFS hot reloc, vfs: add one list_head field BTRFS hot reloc: add one new block group BTRFS hot reloc: add one hot reloc thread BTRFS hot reloc, procfs: add three proc interfaces BTRFS hot reloc: add hot relocation support
fs/btrfs/Makefile | 3 +- fs/btrfs/ctree.h | 35 ++- fs/btrfs/extent-tree.c | 99 ++++-- fs/btrfs/extent_io.c | 51 ++- fs/btrfs/extent_io.h | 7 + fs/btrfs/file.c | 27 +- fs/btrfs/free-space-cache.c | 2 +- fs/btrfs/hot_relocate.c | 721 +++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/hot_relocate.h | 38 +++ fs/btrfs/inode-map.c | 7 +- fs/btrfs/inode.c | 106 +++++-- fs/btrfs/ioctl.c | 17 +- fs/btrfs/relocation.c | 6 +- fs/btrfs/super.c | 30 +- fs/btrfs/volumes.c | 29 +- fs/hot_tracking.c | 1 + include/linux/btrfs.h | 4 + include/linux/hot_tracking.h | 1 + kernel/sysctl.c | 22 ++ 19 files changed, 1132 insertions(+), 74 deletions(-) create mode 100644 fs/btrfs/hot_relocate.c create mode 100644 fs/btrfs/hot_relocate.h
Signature · 1 line
1.7.11.7
RFC PATCH v2 3/5 BTRFS hot reloc: add one hot reloc thread
From: Zhi Yong Wu <[email protected]>
Add one private thread for hot relocation. It will check
if there're some extents which is hotter than the threshold and queue them at first, if no, it will return and wait for its next turn; otherwise, it will check if nonrotating disk ratio is beyond its usage threshold, if no, it will directly relocate hot extents from rotating disk to nonrotating disk; otherwise it will find the extents with low temperature and queue them, then relocate those extents with low temperature and queue them, and finally relocate the hot extents from from rotating disk to nonrotating disk.
--- fs/btrfs/Makefile | 3 +- fs/btrfs/ctree.h | 2 + fs/btrfs/hot_relocate.c | 713 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/hot_relocate.h | 43 +++ 4 files changed, 760 insertions(+), 1 deletion(-) create mode 100644 fs/btrfs/hot_relocate.c create mode 100644 fs/btrfs/hot_relocate.h
fs/btrfs/Makefile +2 -1
@@ -8,7 +8,8 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \ export.o tree-log.o free-space-cache.o zlib.o lzo.o \ compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \ - reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o + reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \ + hot_relocate.o btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o
fs/btrfs/ctree.h +2 -0
@@ -1636,6 +1636,8 @@ struct btrfs_fs_info {struct btrfs_dev_replace dev_replace;atomic_t mutually_exclusive_operation_running; + +void *hot_reloc; };/*
fs/btrfs/hot_relocate.c new file +713 -0
713 lines not on this page · raw message
fs/btrfs/hot_relocate.h new file +43 -0
43 lines not on this page · raw message
Signature · 1 line
1.7.11.7
RFC PATCH v2 5/5 BTRFS hot reloc: add hot relocation support
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Add one new mount option '-o hot_move' for hot
relocation support. When hot relocation is enabled, hot tracking will be enabled automatically.
Its usage looks like:
mount -o hot_move
mount -o nouser,hot_move
mount -o nouser,hot_move,loop
mount -o hot_move,nouser
--- fs/btrfs/super.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-)
fs/btrfs/super.c +23 -3
@@ -309,8 +309,13 @@ static void btrfs_put_super(struct super_block *sb)* process... Whom would you report that to? */ +/* Hot data relocation */ +if (btrfs_test_opt (btrfs_sb (sb)->tree_root,HOT_MOVE )) +hot_relocate_exit (btrfs_sb (sb)); +/* Hot data tracking */ -if (btrfs_test_opt (btrfs_sb (sb)->tree_root,HOT_TRACK )) +if (btrfs_test_opt (btrfs_sb (sb)->tree_root,HOT_MOVE ) + ||btrfs_test_opt (btrfs_sb (sb)->tree_root,HOT_TRACK ))hot_track_exit (sb); }
@@ -325,7 +330,7 @@ enum { Opt_no_space_cache, Opt_recovery, Opt_skip_balance, Opt_check_integrity, Opt_check_integrity_including_extent_data, Opt_check_integrity_print_mask, Opt_fatal_errors, Opt_hot_track, - Opt_err, + Opt_hot_move, Opt_err, }; static match_table_t tokens = {
@@ -366,6 +371,7 @@ static match_table_t tokens = { {Opt_check_integrity_print_mask, "check_int_print_mask=%d"}, {Opt_fatal_errors, "fatal_errors=%s"}, {Opt_hot_track, "hot_track"}, + {Opt_hot_move, "hot_move"}, {Opt_err, NULL}, };
@@ -634,6 +640,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)case Opt_hot_track:btrfs_set_opt (info->mount_opt,HOT_TRACK );break ; +case Opt_hot_move: +btrfs_set_opt (info->mount_opt,HOT_MOVE ); +break ;case Opt_err:printk (KERN_INFO "btrfs: unrecognized mount option " "'%s'\n" , p);
@@ -853,17 +862,26 @@ static int btrfs_fill_super(struct super_block *sb, goto fail_close; } -if (btrfs_test_opt (fs_info->tree_root,HOT_TRACK )) { +if (btrfs_test_opt (fs_info->tree_root,HOT_MOVE ) + ||btrfs_test_opt (fs_info->tree_root,HOT_TRACK )) { err =hot_track_init (sb);if (err) goto fail_hot; } +if (btrfs_test_opt (fs_info->tree_root,HOT_MOVE )) { + err =hot_relocate_init (fs_info); +if (err) + goto fail_reloc; + } +save_mount_options (sb, data);cleancache_init_fs (sb); sb->s_flags |=MS_ACTIVE ;return 0 ; +fail_reloc: +hot_track_exit (sb); fail_hot:dput (sb->s_root); sb->s_root =NULL ;
@@ -964,6 +982,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)seq_puts (seq,",fatal_errors=panic" );if (btrfs_test_opt (root,HOT_TRACK ))seq_puts (seq,",hot_track" ); +if (btrfs_test_opt (root,HOT_MOVE )) +seq_puts (seq,",hot_move" );return 0 ; }
Signature · 1 line
1.7.11.7
RFC PATCH v2 1/5 BTRFS hot reloc, vfs: add one list_head field
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Add one list_head field 'reloc_list' to accommodate
hot relocation support.
--- fs/hot_tracking.c | 1 + include/linux/hot_tracking.h | 1 + 2 files changed, 2 insertions(+)
fs/hot_tracking.c +1 -0
@@ -44,6 +44,7 @@ static void hot_comm_item_init(struct hot_comm_item *ci, int type)clear_bit (HOT_IN_LIST , &ci->delete_flag);clear_bit (HOT_DELETING , &ci->delete_flag);INIT_LIST_HEAD (&ci->track_list); +INIT_LIST_HEAD (&ci->reloc_list);memset (&ci->hot_freq_data,0 ,sizeof (struct hot_freq_data )); ci->hot_freq_data.avg_delta_reads = (u64) -1 ; ci->hot_freq_data.avg_delta_writes = (u64) -1 ;
include/linux/hot_tracking.h +1 -0
@@ -75,6 +75,7 @@ struct hot_comm_item {unsigned long delete_flag;struct rcu_head c_rcu;struct list_head track_list;/* link to *_map[] */ +struct list_head reloc_list;/* used in hot relocation*/ };/* An item representing an inode and its access frequency */
Signature · 1 line
1.7.11.7
RFC PATCH v2 2/5 BTRFS hot reloc: add one new block group
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Introduce one new block group BTRFS_BLOCK_GROUP_DATA_NONROT,
which is used to differentiate if the block space is reserved and allocated from one rotating disk or nonrotating disk.
--- fs/btrfs/ctree.h | 33 +++++++++++--- fs/btrfs/extent-tree.c | 99 +++++++++++++++++++++++++++++++++-------- fs/btrfs/extent_io.c | 51 ++++++++++++++++++++- fs/btrfs/extent_io.h | 7 +++ fs/btrfs/file.c | 27 +++++++---- fs/btrfs/free-space-cache.c | 2 +- fs/btrfs/inode-map.c | 7 +-- fs/btrfs/inode.c | 106 +++++++++++++++++++++++++++++++++++--------- fs/btrfs/ioctl.c | 17 ++++--- fs/btrfs/relocation.c | 6 ++- fs/btrfs/super.c | 4 +- fs/btrfs/volumes.c | 29 +++++++++++- 12 files changed, 318 insertions(+), 70 deletions(-)
fs/btrfs/ctree.h +27 -6
@@ -963,6 +963,12 @@ struct btrfs_dev_replace_item {#define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6)#define BTRFS_BLOCK_GROUP_RAID5 (1 << 7)#define BTRFS_BLOCK_GROUP_RAID6 (1 << 8) +/* +* New block groups for use with BTRFS hot relocation feature. +* When BTRFS hot relocation is enabled, *_NONROT block group is +* forced to nonrotating drives. +*/ +#define BTRFS_BLOCK_GROUP_DATA_NONROT (1ULL << 9)#define BTRFS_BLOCK_GROUP_RESERVED BTRFS_AVAIL_ALLOC_BIT_SINGLEenum btrfs_raid_types {
@@ -978,7 +984,8 @@ enum btrfs_raid_types {#define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | \ BTRFS_BLOCK_GROUP_SYSTEM | \ - BTRFS_BLOCK_GROUP_METADATA) + BTRFS_BLOCK_GROUP_METADATA | \ + BTRFS_BLOCK_GROUP_DATA_NONROT)#define BTRFS_BLOCK_GROUP_PROFILE_MASK (BTRFS_BLOCK_GROUP_RAID0 | \ BTRFS_BLOCK_GROUP_RAID1 | \
@@ -1521,6 +1528,7 @@ struct btrfs_fs_info {struct list_head space_info;struct btrfs_space_info *data_sinfo; +struct btrfs_space_info *nonrot_data_sinfo;struct reloc_control *reloc_ctl;
@@ -1545,6 +1553,7 @@ struct btrfs_fs_info {u64 avail_data_alloc_bits;u64 avail_metadata_alloc_bits;u64 avail_system_alloc_bits; +u64 avail_data_nonrot_alloc_bits;/* restriper state */ spinlock_t balance_lock;
@@ -1557,6 +1566,7 @@ struct btrfs_fs_info {unsigned data_chunk_allocations;unsigned metadata_ratio; +unsigned data_nonrot_chunk_allocations;void *bdev_holder;
@@ -1928,6 +1938,7 @@ struct btrfs_ioctl_defrag_range_args {#define BTRFS_MOUNT_CHECK_INTEGRITY_INCLUDING_EXTENT_DATA (1 << 21)#define BTRFS_MOUNT_PANIC_ON_FATAL_ERROR (1 << 22)#define BTRFS_MOUNT_HOT_TRACK (1 << 23) +#define BTRFS_MOUNT_HOT_MOVE (1 << 24)#define btrfs_clear_opt (o, opt) ((o) &= ~BTRFS_MOUNT_##opt)#define btrfs_set_opt (o, opt) ((o) |= BTRFS_MOUNT_##opt)
@@ -3043,6 +3054,8 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_root *root,int btrfs_cross_ref_exist (struct btrfs_trans_handle *trans,struct btrfs_root *root,u64 objectid,u64 offset,u64 bytenr); +struct btrfs_block_group_cache *btrfs_lookup_first_block_group ( +struct btrfs_fs_info *info,u64 bytenr);struct btrfs_block_group_cache *btrfs_lookup_block_group (struct btrfs_fs_info *info,u64 bytenr);
@@ -3093,6 +3106,8 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,struct btrfs_root *root, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset, int for_cow); +struct btrfs_block_group_cache *next_block_group (struct btrfs_root *root, +struct btrfs_block_group_cache *cache);int btrfs_write_dirty_block_groups (struct btrfs_trans_handle *trans,struct btrfs_root *root);
@@ -3122,8 +3137,14 @@ enum btrfs_reserve_flush_enum { BTRFS_RESERVE_FLUSH_ALL, }; -int btrfs_check_data_free_space (struct inode *inode,u64 bytes); -void btrfs_free_reserved_data_space (struct inode *inode,u64 bytes); +enum { +TYPE_ROT =0 ,/* rot -> rotating */ +TYPE_NONROT ,/* nonrot -> nonrotating */ +MAX_RELOC_TYPES , +}; + +int btrfs_check_data_free_space (struct inode *inode,u64 bytes,int *flag); +void btrfs_free_reserved_data_space (struct inode *inode,u64 bytes,int flag);void btrfs_trans_release_metadata (struct btrfs_trans_handle *trans,struct btrfs_root *root); int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,
@@ -3138,8 +3159,8 @@ void btrfs_subvolume_release_metadata(struct btrfs_root *root, u64 qgroup_reserved);int btrfs_delalloc_reserve_metadata (struct inode *inode,u64 num_bytes);void btrfs_delalloc_release_metadata (struct inode *inode,u64 num_bytes); -int btrfs_delalloc_reserve_space (struct inode *inode,u64 num_bytes); -void btrfs_delalloc_release_space (struct inode *inode,u64 num_bytes); +int btrfs_delalloc_reserve_space (struct inode *inode,u64 num_bytes,int *flag); +void btrfs_delalloc_release_space (struct inode *inode,u64 num_bytes,int flag);void btrfs_init_block_rsv (struct btrfs_block_rsv *rsv,unsigned short type);struct btrfs_block_rsv *btrfs_alloc_block_rsv (struct btrfs_root *root,unsigned short type);
@@ -3612,7 +3633,7 @@ int btrfs_release_file(struct inode *inode, struct file *file);int btrfs_dirty_pages (struct btrfs_root *root,struct inode *inode,struct page **pages,size_t num_pages,loff_t pos,size_t write_bytes, -struct extent_state **cached); +struct extent_state **cached,int flag);/* tree-defrag.c */ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
fs/btrfs/extent-tree.c +80 -19
279 lines not on this page · raw message
fs/btrfs/extent_io.c +49 -2
90 lines not on this page · raw message
fs/btrfs/extent_io.h +7 -0
@@ -19,6 +19,8 @@#define EXTENT_FIRST_DELALLOC (1 << 12)#define EXTENT_NEED_WAIT (1 << 13)#define EXTENT_DAMAGED (1 << 14) +#define EXTENT_HOT (1 << 15) +#define EXTENT_COLD (1 << 16)#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)#define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC)
@@ -51,6 +53,8 @@#define EXTENT_END_WRITEBACK 0x20#define EXTENT_SET_PRIVATE2 0x40#define EXTENT_CLEAR_ACCOUNTING 0x80 +#define EXTENT_CLEAR_HOT 0x100 +#define EXTENT_CLEAR_COLD 0x200/* * page->private values. Every page that is controlled by the extent
@@ -237,6 +241,9 @@ int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, struct extent_state **cached_state, gfp_t mask);int set_extent_defrag (struct extent_io_tree *tree,u64 start,u64 end,struct extent_state **cached_state,gfp_t mask); +void set_extent_hot (struct inode *inode,u64 start,u64 end, +struct extent_state **cached_state, +int type,int flag);int find_first_extent_bit (struct extent_io_tree *tree,u64 start,u64 *start_ret,u64 *end_ret,unsigned long bits,struct extent_state **cached_state);
fs/btrfs/file.c +18 -9
@@ -41,6 +41,7 @@#include "locking.h" #include "compat.h" #include "volumes.h" +#include "hot_relocate.h" static struct kmem_cache *btrfs_inode_defrag_cachep;/*
@@ -500,7 +501,7 @@ static void btrfs_drop_pages(struct page **pages, size_t num_pages)int btrfs_dirty_pages (struct btrfs_root *root,struct inode *inode,struct page **pages,size_t num_pages,loff_t pos,size_t write_bytes, -struct extent_state **cached) +struct extent_state **cached,int flag) {int err =0 ;int i;
@@ -514,6 +515,11 @@ int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode, num_bytes =ALIGN (write_bytes + pos - start_pos, root->sectorsize); end_of_last_block = start_pos + num_bytes -1 ; + +if (btrfs_test_opt (root,HOT_MOVE )) +set_extent_hot (inode, start_pos, end_of_last_block, + cached, flag,0 ); + err =btrfs_set_extent_delalloc (inode, start_pos, end_of_last_block, cached);if (err)
@@ -1294,7 +1300,8 @@ again:clear_extent_bit (&BTRFS_I (inode)->io_tree, start_pos, last_pos -1 ,EXTENT_DIRTY |EXTENT_DELALLOC | -EXTENT_DO_ACCOUNTING |EXTENT_DEFRAG , +EXTENT_DO_ACCOUNTING |EXTENT_DEFRAG | +EXTENT_HOT |EXTENT_COLD ,0 ,0 , &cached_state,GFP_NOFS ); unlock_extent_cached(&BTRFS_I(inode)->io_tree, start_pos, last_pos - 1, &cached_state,
@@ -1350,6 +1357,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;size_t dirty_pages;size_t copied; +int flag =TYPE_ROT ;WARN_ON (num_pages > nrptrs);
@@ -1363,7 +1371,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, } ret =btrfs_delalloc_reserve_space (inode, - num_pages <<PAGE_CACHE_SHIFT ); + num_pages <<PAGE_CACHE_SHIFT , &flag);if (ret)break ;
@@ -1377,7 +1385,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, force_page_uptodate);if (ret) {btrfs_delalloc_release_space (inode, - num_pages <<PAGE_CACHE_SHIFT ); + num_pages <<PAGE_CACHE_SHIFT , flag);break ; }
@@ -1416,16 +1424,16 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, }btrfs_delalloc_release_space (inode, (num_pages - dirty_pages) << -PAGE_CACHE_SHIFT ); +PAGE_CACHE_SHIFT , flag); }if (copied >0 ) { ret =btrfs_dirty_pages (root, inode, pages, dirty_pages, pos, copied, -NULL ); +NULL , flag);if (ret) {btrfs_delalloc_release_space (inode, - dirty_pages <<PAGE_CACHE_SHIFT ); + dirty_pages <<PAGE_CACHE_SHIFT , flag);btrfs_drop_pages (pages, num_pages);break ; }
@@ -2150,6 +2158,7 @@ static long btrfs_fallocate(struct file *file, int mode,u64 locked_end;struct extent_map *em;int blocksize =BTRFS_I (inode)->root->sectorsize; +int flag =TYPE_ROT ;int ret; alloc_start =round_down (offset, blocksize);
@@ -2166,7 +2175,7 @@ static long btrfs_fallocate(struct file *file, int mode,* Make sure we have enough space before we do the * allocation. */ - ret =btrfs_check_data_free_space (inode, alloc_end - alloc_start); + ret =btrfs_check_data_free_space (inode, alloc_end - alloc_start, &flag);if (ret)return ret;if (root->fs_info->quota_enabled) {
@@ -2281,7 +2290,7 @@ out:btrfs_qgroup_free (root, alloc_end - alloc_start); out_reserve_fail:/* Let go of our reservation. */ -btrfs_free_reserved_data_space (inode, alloc_end - alloc_start); +btrfs_free_reserved_data_space (inode, alloc_end - alloc_start, flag);return ret; }
fs/btrfs/free-space-cache.c +1 -1
@@ -1004,7 +1004,7 @@ static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,io_ctl_zero_remaining_pages (&io_ctl); ret =btrfs_dirty_pages (root, inode, io_ctl.pages, io_ctl.num_pages, -0 ,i_size_read (inode), &cached_state); +0 ,i_size_read (inode), &cached_state,TYPE_ROT );io_ctl_drop_pages (&io_ctl);unlock_extent_cached (&BTRFS_I (inode)->io_tree,0 ,i_size_read (inode) -1 , &cached_state,GFP_NOFS );
fs/btrfs/inode-map.c +4 -3
@@ -403,6 +403,7 @@ int btrfs_save_ino_cache(struct btrfs_root *root,u64 alloc_hint =0 ;int ret;int prealloc; +int flag =TYPE_ROT ;bool retry = false;/* only fs tree and subvol/snap needs ino cache */
@@ -492,17 +493,17 @@ again:/* Just to make sure we have enough space */ prealloc +=8 *PAGE_CACHE_SIZE ; - ret =btrfs_delalloc_reserve_space (inode, prealloc); + ret =btrfs_delalloc_reserve_space (inode, prealloc, &flag);if (ret) goto out_put; ret =btrfs_prealloc_file_range_trans (inode, trans,0 ,0 , prealloc, prealloc, prealloc, &alloc_hint);if (ret) { -btrfs_delalloc_release_space (inode, prealloc); +btrfs_delalloc_release_space (inode, prealloc, flag); goto out_put; } -btrfs_free_reserved_data_space (inode, prealloc); +btrfs_free_reserved_data_space (inode, prealloc, flag); ret =btrfs_write_out_ino_cache (root, trans, path); out_put:
fs/btrfs/inode.c +86 -20
274 lines not on this page · raw message
fs/btrfs/ioctl.c +12 -5
@@ -56,6 +56,7 @@#include "rcu-string.h" #include "send.h" #include "dev-replace.h" +#include "hot_relocate.h" /* Mask out flags that are inappropriate for the given type of inode. */ static inline __u32 btrfs_mask_flags (umode_t mode,__u32 flags)
@@ -1001,6 +1002,7 @@ static int cluster_pages_for_defrag(struct inode *inode,int ret;int i;int i_done; +int flag =TYPE_ROT ;struct btrfs_ordered_extent *ordered;struct extent_state *cached_state =NULL ;struct extent_io_tree *tree;
@@ -1013,7 +1015,7 @@ static int cluster_pages_for_defrag(struct inode *inode, page_cnt =min_t (u64, (u64 )num_pages, (u64 )file_end - start_index +1 ); ret =btrfs_delalloc_reserve_space (inode, - page_cnt <<PAGE_CACHE_SHIFT ); + page_cnt <<PAGE_CACHE_SHIFT , &flag);if (ret)return ret; i_done =0 ;
@@ -1101,9 +1103,12 @@ again:BTRFS_I (inode)->outstanding_extents++;spin_unlock (&BTRFS_I (inode)->lock);btrfs_delalloc_release_space (inode, - (page_cnt - i_done) <<PAGE_CACHE_SHIFT ); + (page_cnt - i_done) <<PAGE_CACHE_SHIFT , flag); } +if (btrfs_test_opt (BTRFS_I (inode)->root,HOT_MOVE )) +set_extent_hot (inode, page_start, page_end -1 , + &cached_state, flag,0 );set_extent_defrag (&BTRFS_I (inode)->io_tree, page_start, page_end -1 , &cached_state,GFP_NOFS );
@@ -1126,7 +1131,8 @@ out:unlock_page (pages[i]);page_cache_release (pages[i]); } -btrfs_delalloc_release_space (inode, page_cnt <<PAGE_CACHE_SHIFT ); +btrfs_delalloc_release_space (inode, + page_cnt <<PAGE_CACHE_SHIFT , flag);return ret; }
@@ -3021,8 +3027,9 @@ static long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)u64 types[] = {BTRFS_BLOCK_GROUP_DATA ,BTRFS_BLOCK_GROUP_SYSTEM ,BTRFS_BLOCK_GROUP_METADATA , -BTRFS_BLOCK_GROUP_DATA |BTRFS_BLOCK_GROUP_METADATA }; -int num_types =4 ; +BTRFS_BLOCK_GROUP_DATA |BTRFS_BLOCK_GROUP_METADATA , +BTRFS_BLOCK_GROUP_DATA_NONROT }; +int num_types =5 ;int alloc_size;int ret =0 ;u64 slot_count =0 ;
fs/btrfs/relocation.c +4 -2
@@ -31,6 +31,7 @@#include "async-thread.h" #include "free-space-cache.h" #include "inode-map.h" +#include "hot_relocate.h" /* * backref_node, mapping_node and tree_block start with this
@@ -2938,12 +2939,13 @@ int prealloc_file_extent_cluster(struct inode *inode,u64 num_bytes;int nr =0 ;int ret =0 ; +int flag =TYPE_ROT ;BUG_ON (cluster->start != cluster->boundary[0 ]);mutex_lock (&inode->i_mutex); ret =btrfs_check_data_free_space (inode, cluster->end + -1 - cluster->start); +1 - cluster->start, &flag);if (ret) goto out;
@@ -2965,7 +2967,7 @@ int prealloc_file_extent_cluster(struct inode *inode, nr++; }btrfs_free_reserved_data_space (inode, cluster->end + -1 - cluster->start); +1 - cluster->start, flag); out:mutex_unlock (&inode->i_mutex);return ret;
fs/btrfs/super.c +3 -1
@@ -58,6 +58,7 @@#include "rcu-string.h" #include "dev-replace.h" #include "free-space-cache.h" +#include "hot_relocate.h" #define CREATE_TRACE_POINTS #include <trace/events/btrfs.h>
@@ -1521,7 +1522,8 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)mutex_lock (&fs_info->chunk_mutex);rcu_read_lock ();list_for_each_entry_rcu (found, head, list) { -if (found->flags &BTRFS_BLOCK_GROUP_DATA ) { +if ((found->flags &BTRFS_BLOCK_GROUP_DATA ) || + (found->flags &BTRFS_BLOCK_GROUP_DATA_NONROT )) { total_free_data += found->disk_total - found->disk_used; total_free_data -=btrfs_account_ro_block_groups_free_space (found);
fs/btrfs/volumes.c +27 -2
@@ -1451,6 +1451,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) all_avail = root->fs_info->avail_data_alloc_bits | root->fs_info->avail_system_alloc_bits | root->fs_info->avail_metadata_alloc_bits; +if (btrfs_test_opt (root,HOT_MOVE )) + all_avail |= + root->fs_info->avail_data_nonrot_alloc_bits; }while (read_seqretry (&root->fs_info->profiles_lock, seq)); num_devices = root->fs_info->fs_devices->num_devices;
@@ -3728,7 +3731,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, devs_increment = btrfs_raid_array[index].devs_increment; ncopies = btrfs_raid_array[index].ncopies; -if (type &BTRFS_BLOCK_GROUP_DATA ) { +if (type &BTRFS_BLOCK_GROUP_DATA || + type &BTRFS_BLOCK_GROUP_DATA_NONROT ) { max_stripe_size =1024 *1024 *1024 ; max_chunk_size =10 * max_stripe_size; }else if (type &BTRFS_BLOCK_GROUP_METADATA ) {
@@ -3767,9 +3771,30 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,struct btrfs_device *device;u64 max_avail;u64 dev_offset; +int dev_rot; +int skip =0 ; device = list_entry(cur, struct btrfs_device, dev_alloc_list); +/* +* If HOT_MOVE is set, the chunk type being allocated +* determines which disks the data may be allocated on. +* This can cause problems if, for example, the data alloc +* profile is RAID0 and there are only two devices, 1 SSD + +* 1 HDD. All allocations to BTRFS_BLOCK_GROUP_DATA_NONROT +* in this config will return -ENOSPC as the allocation code +* can't find allowable space for the second stripe. +*/ + dev_rot = !blk_queue_nonrot (bdev_get_queue (device->bdev)); +if (btrfs_test_opt (extent_root,HOT_MOVE )) { +int ret1 = type & (BTRFS_BLOCK_GROUP_DATA | +BTRFS_BLOCK_GROUP_METADATA | +BTRFS_BLOCK_GROUP_SYSTEM ) && !dev_rot; +int ret2 = type &BTRFS_BLOCK_GROUP_DATA_NONROT && dev_rot; +if (ret1 || ret2) + skip =1 ; + } + cur = cur->next;if (!device->writeable) {
@@ -3778,7 +3803,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,continue ; } -if (!device->in_fs_metadata || +if (skip || !device->in_fs_metadata || device->is_tgtdev_for_dev_replace)continue ;
Signature · 1 line
1.7.11.7
RFC PATCH v2 4/5 BTRFS hot reloc, procfs: add three proc interfaces
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Add three proc interfaces hot-reloc-interval, hot-reloc-threshold,
and hot-reloc-max-items under the dir /proc/sys/fs/ in order to turn HOT_RELOC_INTERVAL, HOT_RELOC_THRESHOLD, and HOT_RELOC_MAX_ITEMS into be tunable.
--- fs/btrfs/hot_relocate.c | 26 +++++++++++++++++--------- fs/btrfs/hot_relocate.h | 5 ----- include/linux/btrfs.h | 4 ++++ kernel/sysctl.c | 22 ++++++++++++++++++++++ 4 files changed, 43 insertions(+), 14 deletions(-)
fs/btrfs/hot_relocate.c +17 -9
@@ -25,7 +25,7 @@* The relocation code below operates on the heat map lists to identify * hot or cold data logical file ranges that are candidates for relocation. * The triggering mechanism for relocation is controlled by a global heat -* threshold integer value (HOT_RELOC_THRESHOLD). Ranges are +* threshold integer value (sysctl_hot_reloc_thresh). Ranges are * queued for relocation by the periodically executing relocate kthread, * which updates the global heat threshold and responds to space pressure * on the nonrotating disks.
@@ -53,6 +53,15 @@* (assuming, critically, the HOT_MOVE option is set at mount time). */ +int sysctl_hot_reloc_thresh =150 ; +EXPORT_SYMBOL_GPL (sysctl_hot_reloc_thresh); + +int sysctl_hot_reloc_interval__read_mostly =120 ; +EXPORT_SYMBOL_GPL (sysctl_hot_reloc_interval); + +int sysctl_hot_reloc_max_items__read_mostly =250 ; +EXPORT_SYMBOL_GPL (sysctl_hot_reloc_max_items); +/* * Returns the ratio of nonrotating disks that are full. * If no nonrotating disk is found, returns THRESH_MAX_VALUE + 1.
@@ -103,7 +112,7 @@ static int hot_calc_nonrot_ratio(struct hot_reloc *hot_reloc)static int hot_update_threshold (struct hot_reloc *hot_reloc,int update) { -int thresh = hot_reloc->thresh; +int thresh = sysctl_hot_reloc_thresh;int ratio =hot_calc_nonrot_ratio (hot_reloc);/* Sometimes update global threshold, others not */
@@ -127,7 +136,7 @@ static int hot_update_threshold(struct hot_reloc *hot_reloc, thresh =0 ; } - hot_reloc->thresh = thresh; + sysctl_hot_reloc_thresh = thresh;return ratio; }
@@ -215,7 +224,7 @@ static int hot_queue_extent(struct hot_reloc *hot_reloc, *counter = *counter +1 ; } -if (*counter >=HOT_RELOC_MAX_ITEMS ) +if (*counter >= sysctl_hot_reloc_max_items)break ;if (kthread_should_stop ()) {
@@ -293,7 +302,7 @@ again:while (1 ) {lock_extent (tree, page_start, page_end); ordered =btrfs_lookup_ordered_extent (inode, - page_start); + page_start);unlock_extent (tree, page_start, page_end);if (!ordered)break ;
@@ -559,7 +568,7 @@ void hot_do_relocate(struct hot_reloc *hot_reloc) run++; ratio =hot_update_threshold (hot_reloc, !(run %15 )); - thresh = hot_reloc->thresh; + thresh = sysctl_hot_reloc_thresh;INIT_LIST_HEAD (&hot_reloc->hot_relocq[TYPE_NONROT ]);
@@ -569,7 +578,7 @@ void hot_do_relocate(struct hot_reloc *hot_reloc)if (count_to_hot ==0 )return ; - count_to_cold =HOT_RELOC_MAX_ITEMS ; + count_to_cold = sysctl_hot_reloc_max_items;/* Don't move cold data to HDD unless there's space pressure */ if (ratio <HIGH_WATER_LEVEL )
@@ -653,7 +662,7 @@ static int hot_relocate_kthread(void *arg)unsigned long delay; do { - delay = HZ * HOT_RELOC_INTERVAL; + delay = HZ * sysctl_hot_reloc_interval; if (mutex_trylock(&hot_reloc->hot_reloc_mutex)) { hot_do_relocate(hot_reloc); mutex_unlock(&hot_reloc->hot_reloc_mutex);
@@ -685,7 +694,6 @@ int hot_relocate_init(struct btrfs_fs_info *fs_info) fs_info->hot_reloc = hot_reloc; hot_reloc->fs_info = fs_info; - hot_reloc->thresh =HOT_RELOC_THRESHOLD ;for (i =0 ; i <MAX_RELOC_TYPES ; i++)INIT_LIST_HEAD (&hot_reloc->hot_relocq[i]);mutex_init (&hot_reloc->hot_reloc_mutex);
fs/btrfs/hot_relocate.h +0 -5
@@ -18,10 +18,6 @@#include "btrfs_inode.h" #include "volumes.h" -#define HOT_RELOC_INTERVAL 120 -#define HOT_RELOC_THRESHOLD 150 -#define HOT_RELOC_MAX_ITEMS 250 -#define HEAT_MAX_VALUE (MAP_SIZE - 1)#define HIGH_WATER_LEVEL 75/* when to raise the threshold */ #define LOW_WATER_LEVEL 50/* when to lower the threshold */
@@ -32,7 +28,6 @@struct hot_reloc {struct btrfs_fs_info *fs_info;struct list_head hot_relocq[MAX_RELOC_TYPES ]; -int thresh;struct task_struct *hot_reloc_kthread;struct mutex hot_reloc_mutex; };
include/linux/btrfs.h +4 -0
@@ -3,4 +3,8 @@#include <uapi/linux/btrfs.h> +extern int sysctl_hot_reloc_thresh; +extern int sysctl_hot_reloc_interval; +extern int sysctl_hot_reloc_max_items; +#endif /* _LINUX_BTRFS_H */
kernel/sysctl.c +22 -0
@@ -62,6 +62,7 @@#include <linux/capability.h> #include <linux/binfmts.h> #include <linux/sched/sysctl.h> +#include <linux/btrfs.h> #include <asm/uaccess.h> #include <asm/processor.h>
@@ -1637,6 +1638,27 @@ static struct ctl_table fs_table[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "hot-reloc-thresh", + .data = &sysctl_hot_reloc_thresh, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "hot-reloc-interval", + .data = &sysctl_hot_reloc_interval, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "hot-reloc-max-items", + .data = &sysctl_hot_reloc_max_items, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { } };
Signature · 1 line
1.7.11.7