From: Zhi Yong Wu <wu...@linux.vnet.ibm.com>

  Introduce one way to enable that specific FS
can inject its own hot tracking type.

Signed-off-by: Zhi Yong Wu <wu...@linux.vnet.ibm.com>
---
 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-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to