[PATCH v3 13/13] VFS hot tracking: add fs hot type support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux