diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index 32db72c7c055fa2f566f70d89cce51402f213b28..6fdf7eb33a11900ebd7ba50d679f938b7f372d76 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h @@ -303,6 +303,27 @@ TRACE_EVENT(writeback_bdi_register, ) ); +TRACE_EVENT(insert_memcg_blkcg_link, + TP_PROTO(struct cgroup_subsys_state *memcg_css, + struct cgroup_subsys_state *blkcg_css, + struct cgroup_subsys_state *old_blkcg_css), + TP_ARGS(memcg_css, blkcg_css, old_blkcg_css), + TP_STRUCT__entry( + __field(unsigned int, memcg_ino) + __field(unsigned int, blkcg_ino) + __field(unsigned int, old_blkcg_ino) + ), + TP_fast_assign( + __entry->memcg_ino = memcg_css->cgroup->kn->id.ino; + __entry->blkcg_ino = blkcg_css->cgroup->kn->id.ino; + __entry->old_blkcg_ino = old_blkcg_css ? + old_blkcg_css->cgroup->kn->id.ino : 0; + ), + TP_printk("memcg_ino=%u blkcg_ino=%u old_blkcg_ino=%u", + __entry->memcg_ino, __entry->blkcg_ino, __entry->old_blkcg_ino + ) +); + DECLARE_EVENT_CLASS(wbc_class, TP_PROTO(struct writeback_control *wbc, struct backing_dev_info *bdi), TP_ARGS(wbc, bdi), diff --git a/mm/backing-dev.c b/mm/backing-dev.c index a28fc475fde1f6fbac6445f42265ab0020e0654d..13d945d2137fde4b354fb454cc2f445963f66fbc 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -36,9 +36,22 @@ struct workqueue_struct *bdi_wq; static struct dentry *bdi_debug_root; +#ifdef CONFIG_CGROUP_WRITEBACK +static struct dentry *memcg_blkcg_file; +static const struct file_operations memcg_blkcg_debug_fops; +#endif + static void bdi_debug_init(void) { bdi_debug_root = debugfs_create_dir("bdi", NULL); + +#ifdef CONFIG_CGROUP_WRITEBACK + if (!bdi_debug_root) + return; + + memcg_blkcg_file = debugfs_create_file("bdi_wb_link", 0444, bdi_debug_root, + NULL, &memcg_blkcg_debug_fops); +#endif } static int bdi_debug_stats_show(struct seq_file *m, void *v) @@ -403,6 +416,40 @@ struct memcg_blkcg_link { static RADIX_TREE(memcg_blkcg_tree, GFP_ATOMIC); DEFINE_SPINLOCK(memcg_blkcg_tree_lock); +static int memcg_blkcg_link_show(struct seq_file *m, void *v) +{ + struct memcg_blkcg_link *link; + struct radix_tree_iter iter; + void **slot; + + seq_printf(m, "memory <---> blkio\n"); + rcu_read_lock(); + radix_tree_for_each_slot(slot, &memcg_blkcg_tree, &iter, 0) { + link = *slot; + seq_printf(m, "%s:%5u <---> %s:%5u\n", + link->memcg_css->cgroup->kn->name, + link->memcg_css->cgroup->kn->id.ino, + (link->blkcg_css == blkcg_root_css) ? + "root" : link->blkcg_css->cgroup->kn->name, + link->blkcg_css->cgroup->kn->id.ino); + } + rcu_read_unlock(); + + return 0; +} + +static int memcg_blkcg_link_open(struct inode *inode, struct file *file) +{ + return single_open(file, memcg_blkcg_link_show, inode->i_private); +} + +static const struct file_operations memcg_blkcg_debug_fops = { + .open = memcg_blkcg_link_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + int allocate_memcg_blkcg_links(int count, struct list_head *tmp_links) { struct memcg_blkcg_link *link; @@ -456,6 +503,9 @@ void insert_memcg_blkcg_link(struct cgroup_subsys *ss, } rcu_read_unlock(); + trace_insert_memcg_blkcg_link(memcg_css, blkcg_css, + link ? link->blkcg_css : NULL); + spin_lock(&memcg_blkcg_tree_lock); if (link) { radix_tree_delete(&memcg_blkcg_tree, memcg_css->id);