From: Zhi Yong Wu <wuzhy@xxxxxxxxxxxxxxxxxx> Introduce one way to enable that specific FS can inject its own hot tracking type. Signed-off-by: Zhi Yong Wu <wuzhy@xxxxxxxxxxxxxxxxxx> --- fs/hot_tracking.c | 43 +++++++++++++++++++++++++++++++---------- fs/hot_tracking.h | 1 - include/linux/fs.h | 1 + include/linux/hot_tracking.h | 19 ++++++++++++++++++ 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c index 552bee0..06127cf 100644 --- a/fs/hot_tracking.c +++ b/fs/hot_tracking.c @@ -64,8 +64,11 @@ void hot_range_tree_init(struct hot_inode_item *he) static void hot_range_item_init(struct hot_range_item *hr, loff_t start, struct hot_inode_item *he) { + struct hot_info *root = container_of(he->hot_inode_tree, + struct hot_info, hot_inode_tree); + hr->start = start; - hr->len = RANGE_SIZE; + hr->len = hot_raw_shift(1, root->hot_type->range_bits, true); hr->hot_inode = he; kref_init(&hr->hot_range.refs); spin_lock_init(&hr->hot_range.lock); @@ -309,19 +312,21 @@ static void hot_rw_freq_calc(struct timespec old_atime, *avg = *avg >> FREQ_POWER; } -static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) +static void hot_freq_data_update(struct hot_info *root, + struct hot_freq_data *freq_data, bool write) { struct timespec cur_time = current_kernel_time(); if (write) { freq_data->nr_writes += 1; - hot_rw_freq_calc(freq_data->last_write_time, + root->hot_type->ops.hot_rw_freq_calc_fn( + freq_data->last_write_time, cur_time, &freq_data->avg_delta_writes); freq_data->last_write_time = cur_time; } else { freq_data->nr_reads += 1; - hot_rw_freq_calc(freq_data->last_read_time, + root->hot_type->ops.hot_rw_freq_calc_fn( freq_data->last_read_time, cur_time, &freq_data->avg_delta_reads); @@ -425,7 +430,7 @@ static void hot_map_update(struct hot_freq_data *freq_data, struct hot_comm_item *comm_item; struct hot_inode_item *he; struct hot_range_item *hr; - u32 temp = hot_temp_calc(freq_data); + u32 temp = root->hot_type->ops.hot_temp_calc_fn(freq_data); u8 a_temp = (u8)hot_raw_shift((u64)temp, (32 - HEAT_MAP_BITS), false); u8 b_temp = (u8)hot_raw_shift((u64)freq_data->last_temp, (32 - HEAT_MAP_BITS), false); @@ -507,7 +512,7 @@ static void hot_range_update(struct hot_inode_item *he, &hr_nodes[i]->hot_range.hot_freq_data, root); spin_lock(&hr_nodes[i]->hot_range.lock); - obsolete = hot_is_obsolete( + obsolete = root->hot_type->ops.hot_is_obsolete_fn( &hr_nodes[i]->hot_range.hot_freq_data); spin_unlock(&hr_nodes[i]->hot_range.lock); @@ -652,6 +657,7 @@ void hot_update_freqs(struct inode *inode, loff_t start, struct hot_info *root = inode->i_sb->s_hot_root; struct hot_inode_item *he; struct hot_range_item *hr; + u64 range_size; loff_t cur, end; if (!root || (len == 0)) @@ -664,15 +670,19 @@ void hot_update_freqs(struct inode *inode, loff_t start, } spin_lock(&he->hot_inode.lock); - hot_freq_data_update(&he->hot_inode.hot_freq_data, rw); + hot_freq_data_update(root, &he->hot_inode.hot_freq_data, rw); spin_unlock(&he->hot_inode.lock); /* - * Align ranges on RANGE_SIZE boundary + * Align ranges on range size boundary * to prevent proliferation of range structs */ - end = (start + len + RANGE_SIZE - 1) >> RANGE_BITS; - for (cur = (start >> RANGE_BITS); cur < end; cur++) { + range_size = hot_raw_shift(1, + root->hot_type->range_bits, true); + end = hot_raw_shift((start + len + range_size - 1), + root->hot_type->range_bits, false); + cur = hot_raw_shift(start, root->hot_type->range_bits, false); + for (; cur < end; cur++) { hr = hot_range_item_lookup(he, cur); if (IS_ERR(hr)) { WARN(1, "hot_range_item_lookup returns %ld\n", @@ -682,7 +692,7 @@ void hot_update_freqs(struct inode *inode, loff_t start, } spin_lock(&hr->hot_range.lock); - hot_freq_data_update(&hr->hot_range.hot_freq_data, rw); + hot_freq_data_update(root, &hr->hot_range.hot_freq_data, rw); spin_unlock(&hr->hot_range.lock); hot_range_item_put(hr); @@ -711,6 +721,17 @@ int hot_track_init(struct super_block *sb) hot_inode_tree_init(root); hot_map_init(root); + /* Get hot type for specific FS */ + root->hot_type = &sb->s_type->hot_type; + if (!root->hot_type->ops.hot_rw_freq_calc_fn) + root->hot_type->ops.hot_rw_freq_calc_fn = hot_rw_freq_calc; + if (!root->hot_type->ops.hot_temp_calc_fn) + root->hot_type->ops.hot_temp_calc_fn = hot_temp_calc; + if (!root->hot_type->ops.hot_is_obsolete_fn) + root->hot_type->ops.hot_is_obsolete_fn = hot_is_obsolete; + if (root->hot_type->range_bits == 0) + root->hot_type->range_bits = RANGE_BITS; + root->update_wq = alloc_workqueue( "hot_update_wq", WQ_NON_REENTRANT, 0); if (!root->update_wq) { diff --git a/fs/hot_tracking.h b/fs/hot_tracking.h index 6dbd27a..2914203 100644 --- a/fs/hot_tracking.h +++ b/fs/hot_tracking.h @@ -22,7 +22,6 @@ /* size of sub-file ranges */ #define RANGE_BITS 20 -#define RANGE_SIZE (1 << RANGE_BITS) #define FREQ_POWER 4 /* diff --git a/include/linux/fs.h b/include/linux/fs.h index c541ae7..4e2607d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1821,6 +1821,7 @@ struct file_system_type { struct dentry *(*mount) (struct file_system_type *, int, const char *, void *); void (*kill_sb) (struct super_block *); + struct hot_type hot_type; struct module *owner; struct file_system_type * next; struct hlist_head fs_supers; diff --git a/include/linux/hot_tracking.h b/include/linux/hot_tracking.h index af49078..67fc0bf 100644 --- a/include/linux/hot_tracking.h +++ b/include/linux/hot_tracking.h @@ -73,6 +73,24 @@ struct hot_range_item { size_t len; /* length in bytes */ }; +typedef void (hot_rw_freq_calc_fn) (struct timespec old_atime, + struct timespec cur_time, u64 *avg); +typedef u32 (hot_temp_calc_fn) (struct hot_freq_data *freq_data); +typedef bool (hot_is_obsolete_fn) (struct hot_freq_data *freq_data); + +struct hot_func_ops { + hot_rw_freq_calc_fn *hot_rw_freq_calc_fn; + hot_temp_calc_fn *hot_temp_calc_fn; + hot_is_obsolete_fn *hot_is_obsolete_fn; +}; + +/* identifies an hot type */ +struct hot_type { + u64 range_bits; + /* fields provided by specific FS */ + struct hot_func_ops ops; +}; + struct hot_info { struct radix_tree_root hot_inode_tree; spinlock_t lock; /*protect inode tree */ @@ -85,6 +103,7 @@ struct hot_info { struct workqueue_struct *update_wq; struct delayed_work update_work; + struct hot_type *hot_type; }; extern void __init hot_cache_init(void); -- 1.7.6.5 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html