Re: [PATCH v2] Add -m option to kmem

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

 




----- Original Message -----
> 
> ----- Original Message -----
>>
>> ----- Original Message -----
>>>> kmem -m|-M is used for displaying information of all ksm pages or
>>>> some ksm pages for specified ksm stable tree node addresses
>>>>
>>>> for example:
>>>> crash> kmem -m
>>>> STABLE_NODE : ffff88083fc927e0
>>>> PAGE : ffffea000e667998
>>>> PHYSICAL ADDRESS: 41d475000
>>>>
>>>> PID: 2967 MAPPING: 3
>>>>
>>>> STABLE_NODE : ffff88083fc84a10
>>>> PAGE : ffffea000e3dd5d8
>>>> PHYSICAL ADDRESS: 411aad000
>>>>
>>>> PID: 2967 MAPPING: 7
>>>>
>>>> STABLE_NODE : ffff88041980dda8
>>>> PAGE : ffffea000e335568
>>>> PHYSICAL ADDRESS: 40eaab000
>>>>
>>>> PID: 2967 MAPPING: 8
>>>> ...
>>>>
>>>> STABLE_NODE : ffff880841ea43f8
>>>> PAGE : ffffea000f62de38
>>>> PHYSICAL ADDRESS: 465641000
>>>>
>>>> PID: 2967 MAPPING: 729
>>>> PID: 3017 MAPPING: 499
>>>>
>>>> P.S.
>>>> This patch is based on the patch from Qiao(qiaonuohan cn fujitsu com )
>>>> 0001-make-rbtree-manipulation-functions-global.patch
>>>> Because this patch also uses rb_tree operations.
>>>
>>> I cannot test this because all of my sample dumps either return:
>>>
>>> crash> kmem -m
>>> kmem: -m option not supported or applicable on this architecture or
>>> kernel
>>> crash>
>>>
>>> this is the kernel that doesn't support ksm
>>>
>>> or:
>>>
>>> crash> kmem -m
>>> ksm may not be enabled
>>> crash>
>>>
>>> This is because ksm is disabled or there is no ksm page in your
>>> system.
>> 
>> Which one?  Can't you determine that?
>
> I will change the message to:
>
> no ksm pages in the system
>
> meaning that there is not any ksm page in the system.
>
>> 
>>>
>>> which, by the way, is not a very helpful error message.
>>>
>>> Do you have a reasonably-sized vmcore that I can download and test?
>>>
>>> I have no vmcore on hand now. You could follow the below steps to
>>> make ksm work in your system.
>>>
>>>     * Ensure you are using kernel >= 2.6.31-0.94.rc4.fc12 and qemu-kvm >=0.10.92-4.fc12
>>>     * Run two or more similar virtual machines
>>>     * service ksm start
>>>     * service ksmtuned start
>>>     * Wait a while
>>>     * Check whether pages were merged using /sys/kernel/mm/ksm/pages_shared
>>>     * If value in /sys/kernel/mm/ksm/pages_shared is not zero, you
>>>       could run crash kmem -m to see the output.
>> 
>> OK look, if I get the time, I'll try to set this up...  
>> 
>> But just the fact that I have to go to all this trouble, and the fact 
>> that you don't even have a sample vmcore available again begs the question
>> as to how useful -- or better put -- how often, this command would ever
>> be utilized.
>
> Sorry about this. I will make a vmcore and tell where you can download it later.
>
>> 
>> On the other hand, if you were to create a "ksm" extension module, then 
>> I would be more than happy to post it with all of the others on the 
>> extensions web page.
>> 
>>> Also, I have a question about the help message:
>>>
>>> crash> help kmem
>>>
>>> NAME
>>> kmem - kernel memory
>>>
>>> SYNOPSIS
>>> kmem [-f|-F|-p|-c|-C|-i|-s|-S|-v|-V|-n|-z|-o|-m|-M] [slab] [[-P]
>>> address]
>>> [-g [flags]
>>>
>>> DESCRIPTION
>>> ... [ cut ] ...
>>> -m displays information of ksm pages.
>>> -M same as -m, but also dumps virtual addresses that mapping the
>>> ksm pages.
>>> ... [ cut ] ...
>>> address when used with -m or -M, the address can be either a ksm stable
>>> tree node address, a page's physical address, or a page pointer,
>>> the information of the ksm page (if it is) is displayed.
>>> ... [ cut ] ...
>>>
>>> Display information of ksm pages:
>>>
>>> crash> kmem -m ffff88086f22eec0 ffff8803573964c0
>>> STABLE_NODE : ffff88083fc927e0
>>> PAGE : ffffea000e667998
>>> PHYSICAL ADDRESS: 41d475000
>>>
>>> PID: 2967 MAPPING: 3
>>>
>>> STABLE_NODE : ffff88083fc84a10
>>> PAGE : ffffea000e3dd5d8
>>> PHYSICAL ADDRESS: 411aad000
>>>
>>> PID: 2967 MAPPING: 7
>>>
>>> STABLE_NODE : ffff88041980dda8
>>> PAGE : ffffea000e335568
>>> PHYSICAL ADDRESS: 40eaab000
>>>
>>> PID: 2967 MAPPING: 8
>>>
>>> ......
>>>
>>> STABLE_NODE : ffff880841ea43f8
>>> PAGE : ffffea000f62de38
>>> PHYSICAL ADDRESS: 465641000
>>>
>>> PID: 2967 MAPPING: 729
>>> PID: 3017 MAPPING: 499
>>>
>>> crash>
>>>
>>> Please tell me how the two address arguments ffff88086f22eec0 and
>>> ffff8803573964c0 have any relationship to the subsequent display?
>>>
>>>
>>> Sorry this is a mistake. The two addresses in the example are
>>> redundant.
>> 
>> Well, they aren't "redundant", they just don't make any sense at all.
>> I'm presuming that they don't belong there at all, and that you're
>> just showing the output of "kmem -m" alone, correct?
> 
> Yes, you are right.
> 
> Thanks
> Zhang


Hello Zhang,

I have spent some time testing/playing with this with a local
system set up with 4 KVM guests, and also with the sample
vmcore that you sent to me.

The problem I have is that I find it difficult to justify adding
the command to the base crash utility.  It's hard to conceive
of a situation where the command would be useful in a kernel
debugging session -- that is unless perhaps you were actually 
developing the KSM feature, or if the KSM subsystem were to be
prone to breakage, which doesn't seem to be the case.  

It also could be argued that it's output is more relevant to 
the "vm" command instead of the "kmem" command.  In other words,
it's really an abstraction of the virtual-to-physical aspect
of the "vm -p" output, but specific to only "qemu-kvm" tasks.  

Now, like I mentioned before, I'm sure you do have your reasons,
but certainly have not responded as to why this functionality
is not more suitable as an extension module?  To me it makes
perfect sense as a standalone command.

And to that end, I have flipped your patch into a "ksm" extension
module, which I've attached.  I've slightly tinkered with the 
output display, and given that it's an standalone command, replaced
the -m and -M options with a -v for the virtual addresses dump.  
The help page looks like this: 
  
  crash> help ksm
  
  NAME
    ksm - kernel samepage merging (KSM) information
  
  SYNOPSIS
    ksm [-v] [[-p] address ...]
  
  DESCRIPTION
    This command displays information about all KSM pages currently
    in use.  For each KSM page, the display includes its stable_node
    address, its page struct address, its physical address, the TGID/PID
    for each task that is using the page, and the number of mappings in
    the task's address space for the page.
   
         -v  also dump each virtual address in a PID's virtual address
             space that maps the KSM page.
    address  restricts the output to the KSM data associated with a
             stable_node address, a page's physical address, or a page
             pointer.
         -p  specifies that the address argument is a physical address,
             for architectures that require it.
  
  EXAMPLE
    Display information about all KSM pages:
  
      crash> ksm
                  PAGE: ffffea000ae7f6a8
           STABLE_NODE: ffff8806248c2d80
      PHYSICAL ADDRESS: 31db43000
                   PID: 2205  MAPPINGS: 2
  
                  PAGE: ffffea000ae800f0
           STABLE_NODE: ffff880624aa57b8
      PHYSICAL ADDRESS: 31db72000
                   PID: 2205  MAPPINGS: 2
  
                  PAGE: ffffea000ae7f8d8
           STABLE_NODE: ffff8806248c2dd0
      PHYSICAL ADDRESS: 31db4d000
                   PID: 2205  MAPPINGS: 2
      ...
  
    Display all information about the KSM page whose physical
    address is 0x626e60000:
  
      crash> ksm -v 626e60000
                  PAGE: ffffea0015882500
           STABLE_NODE: ffff88028b2af3d0
      PHYSICAL ADDRESS: 626e60000
                   PID: 2603  MAPPINGS: 8
                   VIRTUAL:
                   7ff46bcb4000
                   7ff46bcad000
                   7ff46bc9f000
                   7ff46bc7c000
                   7ff46bc6e000
                   7ff46bc67000
                   7ff46bc60000
                   7ff46bc59000
  
  crash>
  
I've attached the ksm.c extension module for you to check out.
Just throw it into a crash-<version>/extensions subdirectory,
enter "make extensions", and it will build automatically.
For that matter, you may even want to consider adding additional
KSM-related functionality to the command?  But anyway, with your
approval, I'd like to add it to the extensions web page.

Thanks,
  Dave



/*
 * Copyright (C) 2013 FUJITSU LIMITED
 * Author: Zhang Yanfei <zhangyanfei@xxxxxxxxxxxxxx>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 */

#include "defs.h"

void ksm_init(void);
void ksm_fini(void);

void cmd_ksm(void);
char *help_ksm[];

static struct command_table_entry command_table[] = {
        { "ksm", cmd_ksm, help_ksm, 0},          
        { NULL },
};

struct ksm_offset_table {
	long stable_node_node;
	long stable_node_hlist;
	long stable_node_kpfn;
	long rmap_item_mm;
	long rmap_item_address;
	long rmap_item_hlist;
} ksm_offset_table;

#define KSM_ASSIGN_OFFSET(X)   (ksm_offset_table.X)
#define KSM_MEMBER_OFFSET_INIT(X, Y, Z) (KSM_ASSIGN_OFFSET(X) = MEMBER_OFFSET(Y, Z))
#define KSM_ANON_MEMBER_OFFSET_INIT(X, Y, Z) (KSM_ASSIGN_OFFSET(X) = ANON_MEMBER_OFFSET(Y, Z))
#define KSM_OFFSET(X)  (OFFSET_verify(ksm_offset_table.X, (char *)__FUNCTION__, __FILE__, __LINE__, #X))

struct meminfo {
	int memtype;
	ulong flags;
	ulonglong spec_addr;
};

struct page_ref {
        ulong mm;
        ulong pid;
        int ref;
};

static void dump_ksm(struct meminfo *);

void __attribute__((constructor))
ksm_init(void) /* Register the command set. */
{ 
	if (STRUCT_EXISTS("stable_node")) {
		KSM_MEMBER_OFFSET_INIT(stable_node_node, "stable_node", "node");
		KSM_MEMBER_OFFSET_INIT(stable_node_hlist, "stable_node", "hlist");
		KSM_MEMBER_OFFSET_INIT(stable_node_kpfn, "stable_node", "kpfn");
		KSM_MEMBER_OFFSET_INIT(stable_node_node, "stable_node", "node");
		KSM_MEMBER_OFFSET_INIT(rmap_item_mm, "rmap_item", "mm");
		KSM_MEMBER_OFFSET_INIT(rmap_item_address, "rmap_item", "address");
		KSM_ANON_MEMBER_OFFSET_INIT(rmap_item_hlist, "rmap_item", "hlist");
	} else
		error(FATAL, "ksm_init: stable_node does not exist\n"); 

       	register_extension(command_table);
}
 
void __attribute__((destructor))
ksm_fini(void) { }

void
cmd_ksm(void)
{
        int i, c, vflag, pflag;
	ulong ksm_pages_shared;
        ulonglong value[MAXARGS];
	int spec_addr;
	struct meminfo meminfo;

	vflag = pflag = spec_addr = 0;
	BZERO(&meminfo, sizeof (struct meminfo));

        while ((c = getopt(argcnt, args, "vp")) != EOF) {
                switch(c)
                {
		case 'v':
			vflag++;
			break;
		case 'p':
			pflag++;
			break;
                default:
                        argerrs++;
                        break;
                }
        }

        if (argerrs)
                cmd_usage(pc->curcmd, SYNOPSIS);

	get_symbol_data("ksm_pages_shared", sizeof(ulong), &ksm_pages_shared);
	if (!ksm_pages_shared)
		error(FATAL, "no ksm pages in the system\n");

        while (args[optind]) {
		if (hexadecimal(args[optind], 0))
                        value[spec_addr++] =
                                htoll(args[optind], FAULT_ON_ERROR, NULL);
		optind++;
	}

	for (i = 0; i < spec_addr; i++) {
		meminfo.spec_addr = value[i];
		meminfo.flags = ADDRESS_SPECIFIED;
		if (pflag)
                	meminfo.memtype = PHYSADDR;
		else
                	meminfo.memtype = IS_KVADDR(value[i]) ? KVADDR : PHYSADDR;
		if (meminfo.memtype == PHYSADDR)
			meminfo.spec_addr = (ulonglong)PHYSPAGEBASE(meminfo.spec_addr);
		if (vflag)
			meminfo.flags |= VERBOSE;
		dump_ksm(&meminfo);
	}

	if (!spec_addr) {
		if (vflag) {
			meminfo.flags |= VERBOSE;
			dump_ksm(&meminfo);
		} else
			dump_ksm(NULL);
        }
}

char *help_ksm[] = {
        "ksm", 
        "kernel samepage merging (KSM) information",
        "[-v] [[-p] address ...]",                   
 
        "  This command displays information about all KSM pages currently",
        "  in use.  For each KSM page, the display includes its stable_node",
        "  address, its page struct address, its physical address, the TGID/PID", 
        "  for each task that is using the page, and the number of mappings in",
        "  the task's address space for the page.",
        " ",
        "       -v  also dump each virtual address in a PID's virtual address",
        "           space that maps the KSM page.",
        "  address  restricts the output to the KSM data associated with a",
        "           stable_node address, a page's physical address, or a page",
        "           pointer.",
        "       -p  specifies that the address argument is a physical address,",
        "           for architectures that require it.",
        "\nEXAMPLE",
        "  Display information about all KSM pages:\n",
        "    %s> ksm",
//      "    STABLE_NODE     : ffff8806248c2d80",
//      "    PAGE            : ffffea000ae7f6a8",
//      "    PHYSICAL ADDRESS: 31db43000",
        "                PAGE: ffffea000ae7f6a8",
        "         STABLE_NODE: ffff8806248c2d80",
        "    PHYSICAL ADDRESS: 31db43000",
        "                 PID: 2205  MAPPINGS: 2",
        "",
//      "    STABLE_NODE     : ffff880624aa57b8",
//      "    PAGE            : ffffea000ae800f0",
//      "    PHYSICAL ADDRESS: 31db72000",
        "                PAGE: ffffea000ae800f0",
        "         STABLE_NODE: ffff880624aa57b8",
        "    PHYSICAL ADDRESS: 31db72000",
        "                 PID: 2205  MAPPINGS: 2",
        "",
//      "    STABLE_NODE     : ffff8806248c2dd0",
//      "    PAGE            : ffffea000ae7f8d8",
//      "    PHYSICAL ADDRESS: 31db4d000",
        "                PAGE: ffffea000ae7f8d8",
        "         STABLE_NODE: ffff8806248c2dd0",
        "    PHYSICAL ADDRESS: 31db4d000",
        "                 PID: 2205  MAPPINGS: 2",
        "    ...",
        "",
        "  Display all information about the KSM page whose physical",
        "  address is 0x626e60000:\n",
        "    %s> ksm -v 626e60000",
        "                PAGE: ffffea0015882500",
        "         STABLE_NODE: ffff88028b2af3d0",
        "    PHYSICAL ADDRESS: 626e60000",
        "                 PID: 2603  MAPPINGS: 8",
        "                 VIRTUAL:",
        "                 7ff46bcb4000",
        "                 7ff46bcad000",
        "                 7ff46bc9f000",
        "                 7ff46bc7c000",
        "                 7ff46bc6e000",
        "                 7ff46bc67000",
        "                 7ff46bc60000",
        "                 7ff46bc59000",
        NULL
};


/*
 * dump_ksm() displays information of ksm pages.
 */
static void
dump_ksm(struct meminfo *mi)
{
	ulong root_stable_tree, stable_node, kpfn;
	ulong rmap_item, mm, paddr;
	struct rb_root *root;
	struct rb_node *node;
	ulong first, next;
	struct task_context *tc;
	int i, ref_size, refs, found;
	struct page_ref *ref;
	ulong page, address;

	if (!symbol_exists("root_stable_tree")) {
		error(INFO, "cannot determine ksm stable tree address from root_stable_tree\n");
		return;
	}
	root_stable_tree = symbol_value("root_stable_tree");
	root = (struct rb_root *)root_stable_tree;

	refs = 0;
	ref_size = sizeof(struct page_ref) * RUNNING_TASKS();
	ref = (struct page_ref *)GETBUF(ref_size);
	BZERO(ref, ref_size);

	found = (mi && mi->flags & ADDRESS_SPECIFIED) ? 0 : -1;
	for (node = rb_first(root); node; node = rb_next(node)) {
		stable_node = (ulong) node - KSM_OFFSET(stable_node_node);
		if (CRASHDEBUG(1))
			fprintf(fp, "  stable_node = %lx\n", stable_node);

		readmem(stable_node + KSM_OFFSET(stable_node_hlist),
			KVADDR, &first, sizeof(ulong),
			"stable_node hlist", FAULT_ON_ERROR);
		readmem(stable_node + KSM_OFFSET(stable_node_kpfn),
			KVADDR, &kpfn, sizeof(ulong),
			"stable_node kpfn", FAULT_ON_ERROR);
		paddr = kpfn << PAGE_SHIFT;
		phys_to_page(paddr, &page);

		if (found == 0) {
			if ((mi->memtype == KVADDR) &&
			    (((mi->spec_addr & ~0x3) == stable_node) ||
			     (mi->spec_addr == page)))
				found = 1;
			if ((mi->memtype == PHYSADDR) &&
			    (mi->spec_addr == paddr))
				found = 1;
		}
		if (found == 0)
			continue;

//		fprintf(fp, "STABLE_NODE     : %lx\n", stable_node);
//		fprintf(fp, "PAGE            : %lx\n", page);
//		fprintf(fp, "PHYSICAL ADDRESS: %lx\n\n", paddr);

		fprintf(fp, "            PAGE: %lx\n", page);
		fprintf(fp, "     STABLE_NODE: %lx\n", stable_node);
		fprintf(fp, "PHYSICAL ADDRESS: %lx\n", paddr);

		readmem(stable_node + KSM_OFFSET(stable_node_hlist),
			KVADDR, &first, sizeof(ulong),
			"stable_node hlist", FAULT_ON_ERROR);

		next = first;
		while (next) {
			rmap_item = next - KSM_OFFSET(rmap_item_hlist);
			readmem(rmap_item + KSM_OFFSET(rmap_item_mm),
				KVADDR, &mm, sizeof(ulong),
				"rmap_item mm", FAULT_ON_ERROR);

			for (i = 0; i < refs; i++) {
				if (ref[i].mm == mm) {
					ref[i].ref += 1;
					goto next;
				}
			}

			tc = FIRST_CONTEXT();
			for (i = 0; i < RUNNING_TASKS(); i++, tc++) {
				if (tc->mm_struct == mm) {
					ref[refs].mm = mm;
					ref[refs].pid = tc->pid;
					ref[refs++].ref = 1;
					break;
				}
			}

next:
			readmem(next + OFFSET(hlist_node_next),
				KVADDR, &next, sizeof(ulong),
				"hlist_node next", FAULT_ON_ERROR);
		};

		for (i = 0; i < refs; i++) {
			fprintf(fp, "             PID: %ld ", ref[i].pid);
			fprintf(fp, " MAPPINGS: %d\n", ref[i].ref);

			if (!(mi && mi->flags & VERBOSE))
				continue;

			fprintf(fp, "             VIRTUAL:\n");
			next = first;
			while (next) {
				rmap_item = next - KSM_OFFSET(rmap_item_hlist);
				readmem(rmap_item + KSM_OFFSET(rmap_item_mm),
					KVADDR, &mm, sizeof(ulong),
					"rmap_item mm", FAULT_ON_ERROR);
				if (ref[i].mm == mm) {
					readmem(rmap_item + KSM_OFFSET(rmap_item_address),
						KVADDR, &address, sizeof(ulong),
						"rmap_item address", FAULT_ON_ERROR);
					fprintf(fp, "             %lx\n",
						PAGEBASE(address));
				}
				readmem(next + OFFSET(hlist_node_next),
					KVADDR, &next, sizeof(ulong),
					"hlist_node next", FAULT_ON_ERROR);
			}
			fprintf(fp, "\n");
		}
		if (!(mi && mi->flags & VERBOSE))
			fprintf(fp, "\n");
		refs = 0;

		if (found == 1)
			break;
	}

	if (found == 0)
		fprintf(fp, "address 0x%llx cannot specify a ksm stable tree node\n",
			mi->spec_addr);

	FREEBUF(ref);
}
--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux