is there a way to find the list of slab aliases for a given kmem_cache


Introduction
The kmem subsystem in RHEL7 has changed to include cache aliases, which can be confusing. This article covers a bit of the internals of the slab aliases and which should give some pointers to faster crash analysis as well as some areas for further study.

Kernel code walk-through on 3.10.0-862\*el7
As an example, we start with the 'filp_cachep'. It's fairly easy to see the alias if you know which slab you're looking for.
For example, you can do this and know what the alias is.

crash> p filp_cachep
filp_cachep = $86 = (struct kmem_cache *) 0xffff9ce73fc03700
crash> p filp_cachep->name
$87 = 0xffffffffb3876ec6 "kmalloc-256"
However, what if you just have high slab cache usage in one slab? How do you know what is allocating the memory? If you have a kmem_cache name, how do you list all of the aliases to that  kmem_cache in a RHEL7 vmcore?

Let's see if we can find the actual kmem_cache and look at the items in the cache. At the high level it would seem 'filp' would show up in "kmem -s" output but unfortunately it does not. In case of a crash bug, list out the slab_caches as well, but it is not listed in there.

crash> kmem -s | grep filp
crash>
slab_caches = $15 = {
  next = 0xffff9ce73b987d68, 
  prev = 0xffff9ce73fc02068
}
crash> list -H 0xffff9ce73b987d68 -s kmem_cache.name -o kmem_cache.list | grep filp
crash> 
Now RHEL7 has slab aliases which are recorded in sysfs at /sys/kernel/slab. So look to see if 'filp' is an alias and let's do it "the hard way"

Here's how this works. When kmem_cache_create() is called, we call kmem_cache_create_memcg() with NULL as the 'memcg' parameter. This means we'll call __kmem_cache_alias on line 242 and assuming the alias function comes back with a non-NULL kmem_cache *, we will skip over the allocation. So the next question is how does __kmem_cache_alias work?

mm/slab_common.c
    182 /*
    183  * kmem_cache_create - Create a cache.
    184  * @name: A string which is used in /proc/slabinfo to identify this cache.
    185  * @size: The size of objects to be created in this cache.
    186  * @align: The required alignment for the objects.
    187  * @flags: SLAB flags
    188  * @ctor: A constructor for the objects.
    189  *
    190  * Returns a ptr to the cache on success, NULL on failure.
    191  * Cannot be called within a interrupt, but can be interrupted.
    192  * The @ctor is run when new pages are allocated by the cache.
    193  *
    194  * The flags are
    195  *
    196  * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5)
    197  * to catch references to uninitialised memory.
    198  *
    199  * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check
    200  * for buffer overruns.
    201  *
    202  * %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware
    203  * cacheline.  This can be beneficial if you're counting cycles as closely
    204  * as davem.
    205  */
    206 
    207 struct kmem_cache *
    208 kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size,
    209                         size_t align, unsigned long flags, void (*ctor)(void *),
    210                         struct kmem_cache *parent_cache)
    211 {
    212         struct kmem_cache *s = NULL;
    213         int err = 0;
    214 
    215         get_online_cpus();
    216         mutex_lock(&slab_mutex);
    217 
    218         if (!kmem_cache_sanity_check(memcg, name, size) == 0)
    219                 goto out_locked;
    220 
    221         if (memcg) {
    222                 /*
    223                  * Since per-memcg caches are created asynchronously on first
    224                  * allocation (see memcg_kmem_get_cache()), several threads can
    225                  * try to create the same cache, but only one of them may
    226                  * succeed. Therefore if we get here and see the cache has
    227                  * already been created, we silently return NULL.
    228                  */
    229                 if (cache_from_memcg(parent_cache, memcg_cache_id(memcg)))
    230                         goto out_locked;
    231         }
    232 
    233         /*
    234          * Some allocators will constraint the set of valid flags to a subset
    235          * of all flags. We expect them to define CACHE_CREATE_MASK in this
    236          * case, and we'll just provide them with a sanitized version of the
    237          * passed flags.
    238          */
    239         flags &= CACHE_CREATE_MASK;
    240 
    241         if (!memcg) {
    242                 s = __kmem_cache_alias(name, size, align, flags, ctor);
    243                 if (s)
    244                         goto out_locked;
    245         }
    246 
    247         s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL);
    248         if (s) {
    249                 s->object_size = s->size = size;
    250                 s->align = calculate_alignment(flags, align, size);
    251                 s->ctor = ctor;
    252 
    253                 err = memcg_alloc_cache_params(memcg, s, parent_cache);
    254                 if (err) {
    255                         kmem_cache_free(kmem_cache, s);
    256                         goto out_locked;
    257                 }
    258 
    259                 s->name = kstrdup(name, GFP_KERNEL);
    260                 if (!s->name) {
    261                         memcg_free_cache_params(s);
    262                         kmem_cache_free(kmem_cache, s);
    263                         err = -ENOMEM;
    264                         goto out_locked;
    265                 }
    266 
    267                 err = __kmem_cache_create(s, flags);
    268                 if (!err) {
    269                         s->refcount = 1;
    270                         list_add(&s->list, &slab_caches);
    271                         memcg_register_cache(s);
    272                 } else {
    273                         memcg_free_cache_params(s);
    274                         kfree(s->name);
    275                         kmem_cache_free(kmem_cache, s);
    276                 }
    277         } else
    278                 err = -ENOMEM;
    279 
    280 out_locked:
    281         mutex_unlock(&slab_mutex);
    282         put_online_cpus();
    283 
    284         if (err) {
    285 
    286                 if (flags & SLAB_PANIC)
    287                         panic("kmem_cache_create: Failed to create slab '%s'. Error %d\n",
    288                                 name, err);
    289                 else {
    290                         printk(KERN_WARNING "kmem_cache_create(%s) failed with error %d",
    291                                 name, err);
    292                         dump_stack();
    293                 }
    294 
    295                 return NULL;
    296         }
    297 
    298         return s;
    299 }
    300 
    301 struct kmem_cache *
    302 kmem_cache_create(const char *name, size_t size, size_t align,
    303                   unsigned long flags, void (*ctor)(void *))
    304 {
    305         return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL);
    306 }
    307 EXPORT_SYMBOL(kmem_cache_create);

Now __kmem_cache_alias calls find_mergeable, which does a few checks and then eventually runs through 'slab_caches' list of kmem_cache structures allocated. Assuming it passes additional checks, the function will return that kmem_cache pointer. Otherwise, it eventually goes through the full list, finds nothing, and returns NULL. But we're thinking we found something which is why 'filp' did not show up the list of slab_caches. So we think find_mergeable() returned non-NULL, which implies __kmem_cache_alias passes the 'if (s)' check on line 3960. Then we call into sysfs_slab_alias with the kmem_cache we found and our 'name' that we're wanting to alias to this existing kmem_cache.

mm/slub.c
   3913 static struct kmem_cache *find_mergeable(size_t size, size_t align,
   3914                 unsigned long flags, const char *name, void (*ctor)(void *))
   3915 {
   3916         struct kmem_cache *s;
   3917 
   3918         if (slub_nomerge || (flags & SLUB_NEVER_MERGE))
   3919                 return NULL;
   3920 
   3921         if (ctor)
   3922                 return NULL;
   3923 
   3924         size = ALIGN(size, sizeof(void *));
   3925         align = calculate_alignment(flags, align, size);
   3926         size = ALIGN(size, align);
   3927         flags = kmem_cache_flags(size, flags, name, NULL);
   3928 
   3929         list_for_each_entry(s, &slab_caches, list) {
   3930                 if (slab_unmergeable(s))
   3931                         continue;
   3932 
   3933                 if (size > s->size)
   3934                         continue;
   3935 
   3936                 if ((flags & SLUB_MERGE_SAME) != (s->flags & SLUB_MERGE_SAME))
   3937                         continue;
   3938                 /*
   3939                  * Check if alignment is compatible.
   3940                  * Courtesy of Adrian Drzewiecki
   3941                  */
   3942                 if ((s->size & ~(align - 1)) != s->size)
   3943                         continue;
   3944 
   3945                 if (s->size - size >= sizeof(void *))
   3946                         continue;
   3947 
   3948                 return s;
   3949         }
   3950         return NULL;
   3951 }
...
   3953 struct kmem_cache *
   3954 __kmem_cache_alias(const char *name, size_t size, size_t align,
   3955                    unsigned long flags, void (*ctor)(void *))
   3956 {
   3957         struct kmem_cache *s;
   3958 
   3959         s = find_mergeable(size, align, flags, name, ctor);
   3960         if (s) {
   3961                 s->refcount++;
   3962                 /*
   3963                  * Adjust the object sizes so that we clear
   3964                  * the complete object on kzalloc.
   3965                  */
   3966                 s->object_size = max(s->object_size, (int)size);
   3967                 s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *)));
   3968 
   3969                 if (sysfs_slab_alias(s, name)) {
   3970                         s->refcount--;
   3971                         s = NULL;
   3972                 }
   3973         }
   3974 
   3975         return s;
   3976 }


Ok, so sysfs_slab_alias will call sysfs_create_link with the slab_kset->kobj and our kmem_cache's kobj, as well as the 'name' we passed in for the alias.

 

 5452 static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
   5453 {
   5454         struct saved_alias *al;
   5455 
   5456         if (slab_state == FULL) {
   5457                 /*
   5458                  * If we have a leftover link then remove it.
   5459                  */
   5460                 sysfs_remove_link(&slab_kset->kobj, name);
   5461                 return sysfs_create_link(&slab_kset->kobj, &s->kobj, name);
   5462         }
   5463 
   5464         al = kmalloc(sizeof(struct saved_alias), GFP_KERNEL);
   5465         if (!al)
   5466                 return -ENOMEM;
   5467 
   5468         al->s = s;
   5469         al->name = name;
   5470         al->next = alias_list;
   5471         alias_list = al;
   5472         return 0;
   5473 }


Now we move over into sysfs's symlink code. At this point it appears we probably can walk slab_kset->kobj and obtain the list of all aliases, but we don't know how to do that yet, so let's look at the code further.


fs/sysfs/symlink.c
     21 static int sysfs_do_create_link_sd(struct kernfs_node *parent,
     22                                    struct kobject *target_kobj,
     23                                    const char *name, int warn)
     24 {
     25         struct kernfs_node *kn, *target = NULL;
     26 
     27         BUG_ON(!name || !parent);
     28 
     29         /*
     30          * We don't own @target_kobj and it may be removed at any time.
     31          * Synchronize using sysfs_symlink_target_lock.  See
     32          * sysfs_remove_dir() for details.
     33          */
     34         spin_lock(&sysfs_symlink_target_lock);
     35         if (target_kobj->sd) {
     36                 target = target_kobj->sd;
     37                 kernfs_get(target);
     38         }
     39         spin_unlock(&sysfs_symlink_target_lock);
     40 
     41         if (!target)
     42                 return -ENOENT;
     43 
     44         kn = kernfs_create_link(parent, name, target);
     45         kernfs_put(target);
     46 
     47         if (!IS_ERR(kn))
     48                 return 0;
     49 
     50         if (warn && PTR_ERR(kn) == -EEXIST)
     51                 sysfs_warn_dup(parent, name);
     52         return PTR_ERR(kn);
     53 }
     54 
     55 /**
     56  *      sysfs_create_link_sd - create symlink to a given object.
     57  *      @kn:            directory we're creating the link in.
     58  *      @target:        object we're pointing to.
     59  *      @name:          name of the symlink.
     60  */
     61 int sysfs_create_link_sd(struct kernfs_node *kn, struct kobject *target,
     62                          const char *name)
     63 {
     64         return sysfs_do_create_link_sd(kn, target, name, 1);
     65 }
     66 
     67 static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
     68                                 const char *name, int warn)
     69 {
     70         struct kernfs_node *parent = NULL;
     71 
     72         if (!kobj)
     73                 parent = sysfs_root_kn;
     74         else
     75                 parent = kobj->sd;
     76 
     77         if (!parent)
     78                 return -EFAULT;
     79 
     80         return sysfs_do_create_link_sd(parent, target, name, warn);
     81 }
     82 
     83 /**
     84  *      sysfs_create_link - create symlink between two objects.
     85  *      @kobj:  object whose directory we're creating the link in.
     86  *      @target:        object we're pointing to.
     87  *      @name:          name of the symlink.
     88  */
     89 int sysfs_create_link(struct kobject *kobj, struct kobject *target,
     90                       const char *name)
     91 {
     92         return sysfs_do_create_link(kobj, target, name, 1);
     93 }
     94 EXPORT_SYMBOL_GPL(sysfs_create_link);


Now inside kernfs_create_link(), we see that the key point is we allocate a new 'kernfs_node' on line 32. Then on line 38 we set kn->synlink.target_kn = target. So this is how we know the aliases.

   

 17 /**
     18  * kernfs_create_link - create a symlink
     19  * @parent: directory to create the symlink in
     20  * @name: name of the symlink
     21  * @target: target node for the symlink to point to
     22  *
     23  * Returns the created node on success, ERR_PTR() value on error.
     24  */
     25 struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
     26                                        const char *name,
     27                                        struct kernfs_node *target)
     28 {
     29         struct kernfs_node *kn;
     30         int error;
     31 
     32         kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, KERNFS_LINK);
     33         if (!kn)
     34                 return ERR_PTR(-ENOMEM);
     35 
     36         if (kernfs_ns_enabled(parent))
     37                 kn->ns = target->ns;
     38         kn->symlink.target_kn = target;
     39         kernfs_get(target);     /* ref owned by symlink */
     40 
     41         error = kernfs_add_one(kn);
     42         if (!error)
     43                 return kn;
     44 
     45         kernfs_put(kn);
     46         return ERR_PTR(error);
     47 }
...
    500 static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
    501                                              const char *name, umode_t mode,
    502                                              unsigned flags)
    503 {
    504         char *dup_name = NULL;
    505         struct kernfs_node *kn;
    506         int ret;
    507 
    508         if (!(flags & KERNFS_STATIC_NAME)) {
    509                 name = dup_name = kstrdup(name, GFP_KERNEL);
    510                 if (!name)
    511                         return NULL;
    512         }
    513 
    514         kn = kmem_cache_zalloc(kernfs_node_cache, GFP_KERNEL);
    515         if (!kn)
    516                 goto err_out1;
    517 
    518         ret = ida_simple_get(&root->ino_ida, 1, 0, GFP_KERNEL);
    519         if (ret < 0)
    520                 goto err_out2;
    521         kn->ino = ret;
    522 
    523         atomic_set(&kn->count, 1);
    524         atomic_set(&kn->active, KN_DEACTIVATED_BIAS);
    525         RB_CLEAR_NODE(&kn->rb);
    526 
    527         kn->name = name;
    528         kn->mode = mode;
    529         kn->flags = flags;
    530 
    531         return kn;
    532 
    533  err_out2:
    534         kmem_cache_free(kernfs_node_cache, kn);
    535  err_out1:
    536         kfree(dup_name);
    537         return NULL;
    538 }
    539 
    540 struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
    541                                     const char *name, umode_t mode,
    542                                     unsigned flags)
    543 {
    544         struct kernfs_node *kn;
    545 
    546         kn = __kernfs_new_node(kernfs_root(parent), name, mode, flags);
    547         if (kn) {
    548                 kernfs_get(parent);
    549                 kn->parent = parent;
    550         }
    551         return kn;
    552 }
...
fs/kernfs/kernfs-internal.h
     31 /**
     32  * kernfs_root - find out the kernfs_root a kernfs_node belongs to
     33  * @kn: kernfs_node of interest
     34  *
     35  * Return the kernfs_root @kn belongs to.
     36  */
     37 static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn)
     38 {
     39         /* if parent exists, it's always a dir; otherwise, @sd is a dir */
     40         if (kn->parent)
     41                 kn = kn->parent;
     42         return kn->dir.root;
     43 }


Example 1: Finding the target kmem_cache for "kmalloc-256" and the list of aliases to the target
1) Find the kmem_cache structure for the specific slab cache you're interested in, which can be done easily with the 'kmem -s' command of crash.


crash> kmem -s kmalloc-256
CACHE            NAME                 OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE
ffff9ce73fc03700 kmalloc-256              256   58268801  58289024  1821532     8k
crash> p (struct kmem_cache *)0xffff9ce73fc03700
$1 = (struct kmem_cache *) 0xffff9ce73fc03700
2) Now using the kmem_cache pointer, move through the kobject to the kernfs_node, then the parent of the kernfs_node. From there, go the directory and print out the 'rb_root' for the rbtree that lists the children for the kernfs_node that represents the parent. This in essence is how we will list the directory contents of '/sys/kernel/slab'

crash> p &$1->kobj.sd->parent.dir.children
$2 = (struct rb_root *) 0xffff9cf1cef3ab10
3) Using the rb_root pointer, list out the rbtree and grep out the name of the specific slab cache you were interested in. List the pointer that is printed in the tree, since that represents the kernfs_node of this child, as well as the 'name' and in the 'synmlink' structure the 'target_kn' which is the target of the symlink. The target of the symlink is the actual kmem_alloc slab that has been allocated and this one is aliased to. If the target_kn is 0, then there is no alias.

crash> tree -t rbtree 0xffff9cf1cef3ab10 -s kernfs_node -o kernfs_node.rb | egrep '(^ffff|name|symlink|target_kn)' | grep -A 2 -B 1 "kmalloc-256"
ffff9cedce86fd20
  name = 0xffff9cf5def7c510 "dma-kmalloc-256",
    symlink = {
      target_kn = 0xffff9ce9cfbc2e10
--
ffff9cf1cef4a708
  name = 0xffff9cf5def7c780 "kmalloc-256",
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
4) Now print the name of the 'target_kn' to see what the target of the alias is.

crash> kernfs_node.name 0xffff9ce9cfbc67f8
  name = 0xffff9cf5def7c770 ":t-0000256"
5) Now that we know the target of the alias, list all the other kernfs_nodes that also have this same target_kn. These will be all the aliases to the same slab, ":t-0000256"

crash> tree -t rbtree 0xffff9cf1cef3ab10 -s kernfs_node -o kernfs_node.rb | egrep '(^ffff|name|symlink|target_kn)' | grep -B 3 "target_kn = 0xffff9ce9cfbc67f8"
  name = 0xffff9cf5def7cc50 "sgpool-8", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
ffff9cf1cef4f528
  name = 0xffff9cf1cef06250 "filp", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9cf1cef4f168
  name = 0xffff9ce9cfb466c0 "skbuff_head_cache", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9ce9cfbcbbb8
  name = 0xffff9cf1cef06240 "bio-1", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9ce9cfbcbc30
  name = 0xffff9cf1cef06248 "bio-0", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
ffff9cf1cef4f348
  name = 0xffff9cf5def7ca50 "pool_workqueue", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9cf1ce665d98
  name = 0xffff9cf1cf714178 "bio-2", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9ce9cfbcb708
  name = 0xffff9cf5def7c9b0 "ip_dst_cache", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9ce9cfbcbe10
  name = 0xffff9cf5def7ca20 "biovec-16", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9cf1cef7e1e0
  name = 0xffff9cf5cdc9e200 "request_sock_TCPv6", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9cf1cef4a708
  name = 0xffff9cf5def7c780 "kmalloc-256", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9cf5c8ebc4b0
  name = 0xffff9cf5c97eb520 "nf_conntrack_expect", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9cf1ceb6ae88
  name = 0xffff9cf1dfeeea40 "rpc_tasks", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
--
ffff9ce9cfbcb870
  name = 0xffff9ce9cfb463a0 "request_sock_TCP", 
    symlink = {
      target_kn = 0xffff9ce9cfbc67f8
Example 2: Finding the target kmem_cache for "kmalloc-192" and the list of aliases to the target
1) Find the kmem_cache structure and list out the rb_root
crash> kmem -s kmalloc-192
CACHE            NAME                 OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE
ffff9ce73fc03800 kmalloc-192              192  116270567  116306442  2769201     8k
crash> p &((struct kmem_cache *)0xffff9ce73fc03800)->kobj.sd->parent.dir.children
$88 = (struct rb_root *) 0xffff9cf1cef3ab10
crash> tree -t rbtree 0xffff9cf1cef3ab10 -s kernfs_node -o kernfs_node.rb | egrep '(^ffff|name|symlink|target_kn)' | grep -A 2 -B 1 "kmalloc-192"
ffff9ce9cfbc3a50
  name = 0xffff9cf5def7c630 "dma-kmalloc-192", 
    symlink = {
      target_kn = 0xffff9cf1cef46b40
--
ffff9ce9cfbc7690
  name = 0xffff9cf5def7c7b0 "kmalloc-192", 
    symlink = {
      target_kn = 0xffff9cf1cef4a780
crash> 
2) List out the aliases

Raw
crash> tree -t rbtree 0xffff9cf1cef3ab10 -s kernfs_node -o kernfs_node.rb | egrep '(^ffff|name|symlink|target_kn)' | grep -B 3 "target_kn = 0xffff9cf1cef4a780"
ffff9ce9cfbcb528
  name = 0xffff9cf5def7c970 "inet_peer_cache", 
    symlink = {
      target_kn = 0xffff9cf1cef4a780
--
ffff9cf1cef4f690
  name = 0xffff9cf1cef06258 "key_jar", 
    symlink = {
      target_kn = 0xffff9cf1cef4a780
--
ffff9cf1cef55168
  name = 0xffff9cf1cef06278 "kiocb", 
    symlink = {
      target_kn = 0xffff9cf1cef4a780
--
ffff9cf1cef4f000
  name = 0xffff9ce9cfb46660 "dmaengine-unmap-16", 
    symlink = {
      target_kn = 0xffff9cf1cef4a780
--
ffff9ce9cfbcbe88
  name = 0xffff9ce9cfb46620 "bio_integrity_payload", 
    symlink = {
      target_kn = 0xffff9cf1cef4a780
--
ffff9ce9cfbc7690
  name = 0xffff9cf5def7c7b0 "kmalloc-192", 
    symlink = {
      target_kn = 0xffff9cf1cef4a780
--
ffff9cf1cef4f7f8
  name = 0xffff9cf5def7cac0 "cred_jar", 
    symlink = {
      target_kn = 0xffff9cf1cef4a780
--
ffff9cf1cef4f1e0
  name = 0xffff9cf5def7ca40 "file_lock_cache", 
    symlink = {
      target_kn = 0xffff9cf1cef4a780
3) Dump out the name and 'symlink.target_kn' field of the kernfs_node for the allocated kmem_cache. Note that the 'target_kn' field is NULL and the name is "dt-0000192".

crash> kernfs_node.name 0xffff9cf1cef46b40
  name = 0xffff9cf5def7c620 ":dt-0000192"
crash> kernfs_node.name,symlink 0xffff9cf1cef46b40 | grep target_kn
      target_kn = 0x0
Example 3: Finding the target kmem_cache for "kmalloc-32" and "kmalloc-16" and all the aliases
Below all steps are combined. Interestingly, there is only two aliases here - "kmalloc-32" and "dma-kmalloc-32" is aliased to ":dt-0000032".

crash> kmem -s kmalloc-32
CACHE            NAME                 OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE
ffff9ce73fc03c00 kmalloc-32                32   58259317  58278144  455298     4k
crash> p &((struct kmem_cache *)0xffff9ce73fc03c00)->kobj.sd->parent.dir.children
$89 = (struct rb_root *) 0xffff9cf1cef3ab10
crash> tree -t rbtree 0xffff9cf1cef3ab10 -s kernfs_node -o kernfs_node.rb | egrep '(^ffff|name|symlink|target_kn)' | grep -A 2 -B 1 "kmalloc-32"
ffff9ce9cfbc94b0
  name = 0xffff9cf5def7c870 "kmalloc-32", 
    symlink = {
      target_kn = 0xffff9cf1cef4c5a0
--
ffff9cf5def76bb8
  name = 0xffff9cf5def7c5a0 "dma-kmalloc-32", 
    symlink = {
      target_kn = 0xffff9cedce870ca8
crash> tree -t rbtree 0xffff9cf1cef3ab10 -s kernfs_node -o kernfs_node.rb | egrep '(^ffff|name|symlink|target_kn)' | grep -B 3 "target_kn = 0xffff9cedce870ca8"
ffff9cf5def76bb8
  name = 0xffff9cf5def7c5a0 "dma-kmalloc-32", 
    symlink = {
      target_kn = 0xffff9cedce870ca8
crash> kernfs_node.name,symlink 0xffff9cedce870ca8 | grep target_kn
      target_kn = 0x0
crash> kernfs_node.name,symlink 0xffff9cedce870ca8 
  name = 0xffff9cf5def7c590 ":dt-0000032"
    symlink = {
      target_kn = 0x0
    }
Similarly, "kmalloc-16" and "dma-kmalloc-16" are the only two aliases to ":dt-0000016"

crash> kmem -s kmalloc-16
CACHE            NAME                 OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE
ffff9ce73fc03d00 kmalloc-16                16   58194387  58206464  227369     4k
crash> p &((struct kmem_cache *)0xffff9ce73fc03d00)->kobj.sd->parent.dir.children
$90 = (struct rb_root *) 0xffff9cf1cef3ab10
crash> tree -t rbtree 0xffff9cf1cef3ab10 -s kernfs_node -o kernfs_node.rb | egrep '(^ffff|name|symlink|target_kn)' | grep -A 2 -B 1 "kmalloc-16"
ffff9cf1cef4d438
  name = 0xffff9cf5def7c8a0 "kmalloc-16", 
    symlink = {
      target_kn = 0xffff9ce9cfbc9528
--
ffff9cedce871b40
  name = 0xffff9cf5def7c5d0 "dma-kmalloc-16", 
    symlink = {
      target_kn = 0xffff9cf5def76c30
crash> tree -t rbtree 0xffff9cf1cef3ab10 -s kernfs_node -o kernfs_node.rb | egrep '(^ffff|name|symlink|target_kn)' | grep -B 3 "target_kn = 0xffff9cf5def76c30"
ffff9cedce871b40
  name = 0xffff9cf5def7c5d0 "dma-kmalloc-16", 
    symlink = {
      target_kn = 0xffff9cf5def76c30
crash> kernfs_node.name,symlink 0xffff9cf5def76c30
  name = 0xffff9cf5def7c5c0 ":dt-0000016"
    symlink = {
      target_kn = 0x0
    }

上一篇:概率论与数理统计知识点(二) 离散型随机变量及其分布


下一篇:欧几里得算法