Re: [RFC v4+ hot_track 14/19] vfs: add debugfs support
On Mon, Oct 29, 2012 at 12:30:56PM +0800, zwu.ker...@gmail.com wrote: +static int hot_range_seq_show(struct seq_file *seq, void *v) +{ + struct hot_range_item *hr = v; + struct hot_inode_item *he = hr-hot_inode; + struct hot_freq_data *freq_data = hr-hot_range.hot_freq_data; + + /* Always lock hot_inode_item first */ + spin_lock(he-hot_inode.lock); + spin_lock(hr-hot_range.lock); + seq_printf(seq, inode #%llu, range start \ the # seems unnecessary to me + %llu (range len %u) reads %u, writes %u, + avg read time %llu, avg write time %llu, temp %u\n, compiler will complain if it sees a %llu format and not the expected type of 'unsigned long long' + he-i_ino, (unsigned long long)he-i_ino, + (u64)hr-start * RANGE_SIZE, + hr-len, + freq_data-nr_reads, + freq_data-nr_writes, + freq_data-avg_delta_reads / NSEC_PER_MSEC, + freq_data-avg_delta_writes / NSEC_PER_MSEC, + freq_data-last_temp (32 - HEAT_MAP_BITS)); + spin_unlock(hr-hot_range.lock); + spin_unlock(he-hot_inode.lock); + + return 0; +} + +static int hot_inode_seq_show(struct seq_file *seq, void *v) +{ + struct hot_inode_item *he = v; + struct hot_freq_data *freq_data = he-hot_inode.hot_freq_data; + + spin_lock(he-hot_inode.lock); + seq_printf(seq, inode #%llu, reads %u, writes %u, \ + avg read time %llu, avg write time %llu, temp %u\n, (same here) + he-i_ino, + freq_data-nr_reads, + freq_data-nr_writes, + freq_data-avg_delta_reads / NSEC_PER_MSEC, + freq_data-avg_delta_writes / NSEC_PER_MSEC, + freq_data-last_temp (32 - HEAT_MAP_BITS)); + spin_unlock(he-hot_inode.lock); + + return 0; +} +static void *hot_spot_range_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct hot_info *root = seq-private; + struct hot_range_item *hr_next, *hr = v; + struct hot_comm_item *comm_item; + struct list_head *n_list; + int i = + hr-hot_range.hot_freq_data.last_temp (32 - HEAT_MAP_BITS); now I have noticed that I've seen the ... (32 - HEAT_MAP_BITS) expression so many times that it tend to think it deserves a helper function + + n_list = seq_list_next(hr-hot_range.n_list, + root-heat_range_map[i].node_list, pos); + hot_range_item_put(hr); +next: + if (n_list) { + comm_item = container_of(n_list, + struct hot_comm_item, n_list); + hr_next = container_of(comm_item, + struct hot_range_item, hot_range); + kref_get(hr_next-hot_range.refs); + return hr_next; + } else if (--i = 0) { + n_list = seq_list_next(root-heat_range_map[i].node_list, + root-heat_range_map[i].node_list, pos); + goto next; + } + + return NULL; +} + +static void hot_debugfs_exit(struct super_block *sb) +{ + struct dentry *vol_dentry; + + vol_dentry = debugfs_get_dentry(sb-s_id, + sb-s_hot_root-debugfs_root, strlen(sb-s_id)); + /* remove all debugfs entries recursively from the volume root */ + if (vol_dentry) + debugfs_remove_recursive(vol_dentry); + else + BUG_ON(1); BUG() + + if (list_empty(sb-s_hot_root-debugfs_root-d_subdirs)) + debugfs_remove(sb-s_hot_root-debugfs_root); +} + +/* david -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC v4+ hot_track 14/19] vfs: add debugfs support
On Wed, Nov 7, 2012 at 7:45 AM, David Sterba d...@jikos.cz wrote: On Mon, Oct 29, 2012 at 12:30:56PM +0800, zwu.ker...@gmail.com wrote: +static int hot_range_seq_show(struct seq_file *seq, void *v) +{ + struct hot_range_item *hr = v; + struct hot_inode_item *he = hr-hot_inode; + struct hot_freq_data *freq_data = hr-hot_range.hot_freq_data; + + /* Always lock hot_inode_item first */ + spin_lock(he-hot_inode.lock); + spin_lock(hr-hot_range.lock); + seq_printf(seq, inode #%llu, range start \ the # seems unnecessary to me OK, removed. + %llu (range len %u) reads %u, writes %u, + avg read time %llu, avg write time %llu, temp %u\n, compiler will complain if it sees a %llu format and not the expected type of 'unsigned long long' When built, i haven't seen any warning report about this... + he-i_ino, (unsigned long long)he-i_ino, + (u64)hr-start * RANGE_SIZE, + hr-len, + freq_data-nr_reads, + freq_data-nr_writes, + freq_data-avg_delta_reads / NSEC_PER_MSEC, + freq_data-avg_delta_writes / NSEC_PER_MSEC, + freq_data-last_temp (32 - HEAT_MAP_BITS)); + spin_unlock(hr-hot_range.lock); + spin_unlock(he-hot_inode.lock); + + return 0; +} + +static int hot_inode_seq_show(struct seq_file *seq, void *v) +{ + struct hot_inode_item *he = v; + struct hot_freq_data *freq_data = he-hot_inode.hot_freq_data; + + spin_lock(he-hot_inode.lock); + seq_printf(seq, inode #%llu, reads %u, writes %u, \ + avg read time %llu, avg write time %llu, temp %u\n, (same here) ditto. + he-i_ino, + freq_data-nr_reads, + freq_data-nr_writes, + freq_data-avg_delta_reads / NSEC_PER_MSEC, + freq_data-avg_delta_writes / NSEC_PER_MSEC, + freq_data-last_temp (32 - HEAT_MAP_BITS)); + spin_unlock(he-hot_inode.lock); + + return 0; +} +static void *hot_spot_range_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct hot_info *root = seq-private; + struct hot_range_item *hr_next, *hr = v; + struct hot_comm_item *comm_item; + struct list_head *n_list; + int i = + hr-hot_range.hot_freq_data.last_temp (32 - HEAT_MAP_BITS); now I have noticed that I've seen the ... (32 - HEAT_MAP_BITS) expression so many times that it tend to think it deserves a helper function This helper function has existed, hot_raw_shift(), i will replace this with it. + + n_list = seq_list_next(hr-hot_range.n_list, + root-heat_range_map[i].node_list, pos); + hot_range_item_put(hr); +next: + if (n_list) { + comm_item = container_of(n_list, + struct hot_comm_item, n_list); + hr_next = container_of(comm_item, + struct hot_range_item, hot_range); + kref_get(hr_next-hot_range.refs); + return hr_next; + } else if (--i = 0) { + n_list = seq_list_next(root-heat_range_map[i].node_list, + root-heat_range_map[i].node_list, pos); + goto next; + } + + return NULL; +} + +static void hot_debugfs_exit(struct super_block *sb) +{ + struct dentry *vol_dentry; + + vol_dentry = debugfs_get_dentry(sb-s_id, + sb-s_hot_root-debugfs_root, strlen(sb-s_id)); + /* remove all debugfs entries recursively from the volume root */ + if (vol_dentry) + debugfs_remove_recursive(vol_dentry); + else + BUG_ON(1); BUG() done, thanks. + + if (list_empty(sb-s_hot_root-debugfs_root-d_subdirs)) + debugfs_remove(sb-s_hot_root-debugfs_root); +} + +/* david -- Regards, Zhi Yong Wu -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC v4+ hot_track 14/19] vfs: add debugfs support
From: Zhi Yong Wu wu...@linux.vnet.ibm.com Add a /sys/kernel/debug/hot_track/device_name/ directory for each volume that contains two files. The first, `inode_stats', contains the heat information for inodes that have been brought into the hot data map structures. The second, `range_stats', contains similar information for subfile ranges. Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com --- fs/hot_tracking.c| 484 ++ fs/hot_tracking.h|5 + include/linux/hot_tracking.h |1 + 3 files changed, 490 insertions(+), 0 deletions(-) diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c index 54a8208..376d7fb 100644 --- a/fs/hot_tracking.c +++ b/fs/hot_tracking.c @@ -21,6 +21,7 @@ #include linux/blkdev.h #include linux/types.h #include linux/list_sort.h +#include linux/debugfs.h #include linux/limits.h #include hot_tracking.h @@ -628,6 +629,477 @@ static void hot_update_worker(struct work_struct *work) } /* + * take the inode, find ranges associated with inode + * and print each range data struct + */ +static struct hot_range_item +*hot_range_tree_walk(struct hot_inode_item *he, + loff_t *pos, u32 start, bool flag) +{ + struct hot_range_item *hr_nodes[8]; + loff_t l = *pos; + int i, n; + + /* Walk the hot_range_tree for inode */ + while (1) { + spin_lock(he-lock); + n = radix_tree_gang_lookup(he-hot_range_tree, + (void **)hr_nodes, start, + ARRAY_SIZE(hr_nodes)); + if (!n) { + spin_unlock(he-lock); + break; + } + spin_unlock(he-lock); + + start = hr_nodes[n - 1]-start + 1; + for (i = 0; i n; i++) { + if ((!flag !l--) || (flag)) { + if (flag) + (*pos)++; + kref_get(hr_nodes[i]-hot_range.refs); + return hr_nodes[i]; + } + } + } + + return NULL; +} + +static void +*hot_inode_tree_walk(struct seq_file *seq, loff_t *pos, + u64 ino, bool type, bool flag) +{ + struct hot_info *root = seq-private; + struct hot_inode_item *hi_nodes[8]; + struct hot_range_item *hr; + loff_t l = *pos; + int i, n; + + while (1) { + spin_lock(root-lock); + n = radix_tree_gang_lookup(root-hot_inode_tree, + (void **)hi_nodes, ino, + ARRAY_SIZE(hi_nodes)); + if (!n) { + spin_unlock(root-lock); + break; + } + spin_unlock(root-lock); + + ino = hi_nodes[n - 1]-i_ino + 1; + for (i = 0; i n; i++) { + if (!type) { + hr = hot_range_tree_walk(hi_nodes[i], + pos, 0, flag); + if (hr) + return hr; + } else { + if ((!flag !l--) || (flag)) { + if (flag) + (*pos)++; + kref_get(hi_nodes[i]-hot_inode.refs); + return hi_nodes[i]; + } + } + } + } + + return NULL; +} + +static void *hot_range_seq_start(struct seq_file *seq, loff_t *pos) +{ + return hot_inode_tree_walk(seq, pos, 0, false, false); +} + +static void *hot_range_seq_next(struct seq_file *seq, + void *v, loff_t *pos) +{ + struct hot_range_item *hr_next, *hr = v; + u32 start = hr-start + 1; + + /* Walk the hot_range_tree for inode */ + hr_next = hot_range_tree_walk(hr-hot_inode, pos, start, true); + if (hr_next) + return hr_next; + + return hot_inode_tree_walk(seq, pos, + hr-hot_inode-i_ino + 1, false, true); +} + +static void hot_range_seq_stop(struct seq_file *seq, void *v) +{ + struct hot_range_item *hr = v; + + if (hr) + hot_range_item_put(hr); +} + +static int hot_range_seq_show(struct seq_file *seq, void *v) +{ + struct hot_range_item *hr = v; + struct hot_inode_item *he = hr-hot_inode; + struct hot_freq_data *freq_data = hr-hot_range.hot_freq_data; + + /* Always lock hot_inode_item first */ + spin_lock(he-hot_inode.lock); + spin_lock(hr-hot_range.lock); + seq_printf(seq, inode #%llu, range start \ + %llu (range len %u) reads %u,