summaryrefslogtreecommitdiff
path: root/SOURCE
diff options
context:
space:
mode:
authorgit-baoyou <[email protected]>2021-11-25 16:31:25 +0800
committerGitHub <[email protected]>2021-11-25 16:31:25 +0800
commit5222f30832e1d1c366c692ba9eb7968c0420ebce (patch)
tree4a91b51d2721132d7ffd722057999958182f790a /SOURCE
parent1793502843cd8f3a5932fa602cdb9f4b3b390cbe (diff)
parenta5c8f452d5e97dd535a92a22ba52a3649bddb065 (diff)
Merge pull request #151 from w-simon/fix_5.10
memcg-stats: 输出mount点的路径,便于分析memcg的内存占用
Diffstat (limited to 'SOURCE')
-rw-r--r--SOURCE/diagnose-tools/memcg_stats.cc6
-rw-r--r--SOURCE/module/mm/memcg_stats.c63
-rw-r--r--SOURCE/uapi/memcg_stats.h1
3 files changed, 68 insertions, 2 deletions
diff --git a/SOURCE/diagnose-tools/memcg_stats.cc b/SOURCE/diagnose-tools/memcg_stats.cc
index 690e091..653572e 100644
--- a/SOURCE/diagnose-tools/memcg_stats.cc
+++ b/SOURCE/diagnose-tools/memcg_stats.cc
@@ -172,20 +172,22 @@ static int memcg_stats_extract(void *buf, unsigned int len, void *)
break;
detail = (struct diag_memcg_stats_detail *)buf;
if (debug_mode) {
- printf("memcg: %p inode: %p major: %u minor: %u ino: %lu pages: %u name: %s\n",
+ printf("memcg: %p inode: %p major: %u minor: %u ino: %lu pages: %u mnt: %s name: %s\n",
(void *)detail->cg_addr,
(void *)detail->key,
MAJOR(detail->dev),
MINOR(detail->dev),
detail->ino,
detail->pages,
+ detail->mnt_dir,
detail->name);
} else {
- printf("major: %u minor: %u ino: %lu pages: %u name: %s\n",
+ printf("major: %u minor: %u ino: %lu pages: %u mnt: %s name: %s\n",
MAJOR(detail->dev),
MINOR(detail->dev),
detail->ino,
detail->pages,
+ detail->mnt_dir,
detail->name);
}
break;
diff --git a/SOURCE/module/mm/memcg_stats.c b/SOURCE/module/mm/memcg_stats.c
index dc00824..17b5bf8 100644
--- a/SOURCE/module/mm/memcg_stats.c
+++ b/SOURCE/module/mm/memcg_stats.c
@@ -10,6 +10,7 @@
#include <linux/kallsyms.h>
#include <linux/kernfs.h>
#include <linux/version.h>
+#include <linux/mount.h>
#if KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE
#include <linux/kernfs.h>
#endif
@@ -33,6 +34,8 @@ static struct pglist_data * (*orig_first_online_pgdat)(void) = NULL;
static struct pglist_data * (*orig_next_online_pgdat)(struct pglist_data *pgdat) = NULL;
+seqlock_t * orig_mount_lock = NULL;
+
static struct diag_variant_buffer memcg_stats_variant_buffer;
static int memcg_stats_alloced = 0;
@@ -114,6 +117,64 @@ static void inode_name(struct inode *ino, char *buf, unsigned int len)
kfree(name);
}
+struct mount_diag {
+ struct hlist_node mnt_hash;
+ struct mount_diag *mnt_parent;
+ struct dentry *mnt_mountpoint;
+ struct vfsmount mnt;
+ union {
+ struct rcu_head mnt_rcu;
+ struct llist_node mnt_llist;
+ };
+#ifdef CONFIG_SMP
+ struct mnt_pcp __percpu *mnt_pcp;
+#else
+ int mnt_count;
+ int mnt_writers;
+#endif
+ struct list_head mnt_mounts; /* list of children, anchored here */
+ struct list_head mnt_child; /* and going through their mnt_child */
+ struct list_head mnt_instance; /* mount instance on sb->s_mounts */
+};
+
+static void mnt_dir(struct inode *ino, char *buf, unsigned int len)
+{
+ struct mount_diag *mnt = NULL;
+ struct super_block *sb;
+ struct dentry *dentry;
+ char *name;
+
+ buf[0] = '\0';
+ if (!ino || !buf || !len)
+ goto out;
+ sb = ino->i_sb;
+ if (!sb)
+ goto out;
+
+ write_seqlock(orig_mount_lock);
+ if (!list_empty(&sb->s_mounts))
+ mnt = list_first_entry(&sb->s_mounts, struct mount_diag,
+ mnt_instance);
+ write_sequnlock(orig_mount_lock);
+
+ if (!mnt)
+ goto out;
+ dentry = mnt->mnt_mountpoint;
+ if (!dentry)
+ goto out;
+
+ name = __getname();
+ if (!name)
+ goto out;
+
+ __dentry_name(dentry, name);
+ strncpy(buf, name, len - 1);
+ kfree(name);
+
+out:
+ return;
+}
+
static void diag_memcg_dump_variant_buffer(void * data, unsigned int len)
{
unsigned long flags;
@@ -225,6 +286,7 @@ static void diag_memcg_build_inode_stats(struct mem_cgroup *memcg,
stats->cg_addr = (unsigned long)memcg;
stats->dev = inode->i_sb->s_dev;
inode_name(inode, stats->name, MEMCG_NAME_LEN);
+ mnt_dir(inode, stats->mnt_dir, MEMCG_NAME_LEN);
stats->pages = 1;
radix_tree_insert(inode_stats_tree, (unsigned long)inode, stats);
} else
@@ -389,6 +451,7 @@ static int lookup_syms(void)
LOOKUP_SYMS(page_mapping);
LOOKUP_SYMS(first_online_pgdat);
LOOKUP_SYMS(next_online_pgdat);
+ LOOKUP_SYMS(mount_lock);
return 0;
}
diff --git a/SOURCE/uapi/memcg_stats.h b/SOURCE/uapi/memcg_stats.h
index c2509d7..d22e0c7 100644
--- a/SOURCE/uapi/memcg_stats.h
+++ b/SOURCE/uapi/memcg_stats.h
@@ -51,6 +51,7 @@ struct diag_memcg_stats_detail {
unsigned int dev;
unsigned int pages;
char name[MEMCG_NAME_LEN];
+ char mnt_dir[MEMCG_NAME_LEN];
};
#endif /* UAPI_MEMCG_STATS_H */