From: Zhi Yong Wu <wuzhy@xxxxxxxxxxxxxxxxxx> Introduce one ability to enable that specific FS can register its own hot tracking functions. Signed-off-by: Chandra Seetharaman <sekharan@xxxxxxxxxx> Signed-off-by: Zhi Yong Wu <wuzhy@xxxxxxxxxxxxxxxxxx> --- fs/hot_tracking.c | 28 +++++++++++++++++++--------- fs/hot_tracking.h | 13 +++++++++++++ fs/ioctl.c | 2 +- include/linux/fs.h | 1 + include/linux/hot_tracking.h | 20 +++++++++++++++++++- 5 files changed, 53 insertions(+), 11 deletions(-) diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c index 915b48b..dbc90d4 100644 --- a/fs/hot_tracking.c +++ b/fs/hot_tracking.c @@ -54,7 +54,7 @@ static void hot_range_item_init(struct hot_range_item *hr, struct hot_inode_item *he, loff_t start) { hr->start = start; - hr->len = hot_shift(1, RANGE_BITS, true); + hr->len = hot_shift(1, he->hot_root->hot_type->range_bits, true); hr->hot_inode = he; hr->storage_type = -1; hot_comm_item_init(&hr->hot_range, TYPE_RANGE); @@ -273,10 +273,11 @@ struct hot_range_item { struct rb_node **p; struct rb_node *parent = NULL; + struct hot_info *root = he->hot_root; struct hot_comm_item *ci; struct hot_range_item *hr, *hr_new = NULL; - start = hot_shift(start, RANGE_BITS, true); + start = hot_shift(start, root->hot_type->range_bits, true); /* walk tree to find insertion point */ redo: @@ -367,13 +368,13 @@ static void hot_freq_update(struct hot_info *root, if (write) { freq_data->nr_writes += 1; - hot_freq_calc(freq_data->last_write_time, + HOT_FREQ_CALC(root, 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_freq_calc(freq_data->last_read_time, + HOT_FREQ_CALC(root, freq_data->last_read_time, cur_time, &freq_data->avg_delta_reads); freq_data->last_read_time = cur_time; @@ -398,7 +399,7 @@ static void hot_freq_update(struct hot_info *root, * the *_COEFF_POWER values and combined to a single temperature * value. */ -u32 hot_temp_calc(struct hot_comm_item *ci) +static u32 hot_temp_calc(struct hot_comm_item *ci) { u32 result = 0; struct hot_freq_data *freq_data = &ci->hot_freq_data; @@ -470,7 +471,7 @@ u32 hot_temp_calc(struct hot_comm_item *ci) static bool hot_map_update(struct hot_info *root, struct hot_comm_item *ci) { - u32 temp = hot_temp_calc(ci); + u32 temp = HOT_TEMP_CALC(root, ci); u8 cur_temp, prev_temp; bool flag = false; @@ -1164,10 +1165,10 @@ void hot_update_freqs(struct inode *inode, loff_t start, * Align ranges on range size boundary * to prevent proliferation of range structs */ - range_size = hot_shift(1, RANGE_BITS, true); + range_size = hot_shift(1, root->hot_type->range_bits, true); end = hot_shift((start + len + range_size - 1), - RANGE_BITS, false); - cur = hot_shift(start, RANGE_BITS, false); + root->hot_type->range_bits, false); + cur = hot_shift(start, root->hot_type->range_bits, false); for (; cur < end; cur++) { hr = hot_range_item_lookup(he, cur, 1); if (IS_ERR(hr)) { @@ -1209,6 +1210,15 @@ static struct hot_info *hot_tree_init(struct super_block *sb) INIT_LIST_HEAD(&root->hot_map[j][i]); } + /* Get hot type for specific FS */ + root->hot_type = &sb->s_type->hot_type; + if (!HOT_FREQ_FN_EXIST(root)) + SET_HOT_FREQ_FN(root, hot_freq_calc); + if (!HOT_TEMP_FN_EXIST(root)) + SET_HOT_TEMP_FN(root, hot_temp_calc); + 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 be9f5cd..b5f043c 100644 --- a/fs/hot_tracking.h +++ b/fs/hot_tracking.h @@ -40,6 +40,19 @@ #define AVW_DIVIDER_POWER 40 /* AVW - average delta between recent writes(ns) */ #define AVW_COEFF_POWER 0 +#define HOT_FREQ_FN_EXIST(root) \ + ((root)->hot_type->ops.hot_freq_calc) +#define HOT_TEMP_FN_EXIST(root) \ + ((root)->hot_type->ops.hot_temp_calc) + +#define HOT_FREQ_CALC(root, lt, ct, avg) \ + ((root)->hot_type->ops.hot_freq_calc(lt, ct, avg)) + +#define SET_HOT_FREQ_FN(root, fn) \ + (root)->hot_type->ops.hot_freq_calc = fn +#define SET_HOT_TEMP_FN(root, fn) \ + (root)->hot_type->ops.hot_temp_calc = fn + struct hot_debugfs { const char *name; const struct file_operations *fops; diff --git a/fs/ioctl.c b/fs/ioctl.c index f9f3497..95ec029 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -585,7 +585,7 @@ static int ioctl_heat_info(struct file *file, void __user *argp) * got a request for live temperature, * call hot_calc_temp() to recalculate */ - heat_info.temp = hot_temp_calc(&he->hot_inode); + heat_info.temp = HOT_TEMP_CALC(he->hot_root, &he->hot_inode); } else { /* not live temperature, get it from the map list */ heat_info.temp = he->hot_inode.hot_freq_data.last_temp; diff --git a/include/linux/fs.h b/include/linux/fs.h index ee2c54f..dda3b9c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1817,6 +1817,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 03e5026..1009377 100644 --- a/include/linux/hot_tracking.h +++ b/include/linux/hot_tracking.h @@ -98,6 +98,24 @@ struct hot_range_item { int storage_type; /* type of storage */ }; +typedef void (hot_freq_calc_fn) (struct timespec old_atime, + struct timespec cur_time, u64 *avg); +typedef u32 (hot_temp_calc_fn) (struct hot_comm_item *ci); + +struct hot_func_ops { + hot_freq_calc_fn *hot_freq_calc; + hot_temp_calc_fn *hot_temp_calc; +}; + +/* identifies an hot type */ +struct hot_type { + u64 range_bits; + struct hot_func_ops ops; /* fields provided by specific FS */ +}; + +#define HOT_TEMP_CALC(root, ci) \ + ((root)->hot_type->ops.hot_temp_calc(ci)) + struct hot_info { struct rb_root hot_inode_tree; spinlock_t t_lock; /* protect above tree */ @@ -106,6 +124,7 @@ struct hot_info { atomic_t hot_map_nr; struct workqueue_struct *update_wq; struct delayed_work update_work; + struct hot_type *hot_type; struct shrinker hot_shrink; struct dentry *debugfs_dentry; atomic_t run_debugfs; @@ -138,7 +157,6 @@ extern struct hot_inode_item *hot_inode_item_lookup(struct hot_info *root, extern struct hot_range_item *hot_range_item_lookup(struct hot_inode_item *he, loff_t start, int alloc); extern void hot_inode_item_delete(struct inode *inode); -extern u32 hot_temp_calc(struct hot_comm_item *ci); static inline u64 hot_shift(u64 counter, u32 bits, bool dir) { -- 1.7.11.7 -- 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