A new option of the new command lscgroup

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

 



Hello, Dave,

I have read your mail and think over the suggestions and done some changes. Firstly, I added a new option "-a" to meet the demand that user can enter a cgroup address and it would display its controller/path name.

Secondly, previously, when user specify controller:path to display
chosen cgroups,there is no option. To make it in accordance with -a
option, I did a little change, that is when user specify
controller:path, there should be a option -g. The following example
illustrates the change.
Previously, user may run : crash> lscgroup cpu:/
but now, user should run  : crash > lscgroup -g cpu:/

Accordingly,the help information was revised. You can refer to the
help information and attachment to see detailed changes.

Many thanks
Yongming Yu

	
Dave Anderson 写道:

----- Original Message -----

And I would suggest a new option, where a user can enter a cgroup
address, and it would find and display its controller/path name:

 crash> lscgroup
      CGROUP       CONTROLLER:PATH
 ffff8801f668c400  cpuacct,cpu:/system/nfs-lock.service
 crash>

Sorry -- I meant something like this:

 crash> lscgroup ffff8801f668c400
      CGROUP       CONTROLLER:PATH
 ffff8801f668c400  cpuacct,cpu:/system/nfs-lock.service
 crash>

Dave



--
--------------------------------------------------
Yu Yongming
Nanjing Fujitsu Nanda Software Tech. Co., Ltd.
(FNST)No. 6 Wenzhu Road, Nanjing, 210012, China
EMail:yuym.fnst@xxxxxxxxxxxxxx

Regards__
--------------------------------------------------



/* lscgroup.c - list cgroups
 *
 * Copyright (C) 2012 FUJITSU LIMITED
 * Author: Yu Yongming <yuym.fnst@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"

#define PATHNAME_MAX      200
#define ROOT_MAX          64
#define CG_CONTROLLER_MAX 20
#define CG_HIER_MAX       20
#define LIST_CER	  0x1
#define LIST_ADD	  0x2


#define CGROUP_MEMBER_OFFSET_INIT(X,Y,Z) (cgroup_offset_table.X=MEMBER_OFFSET(Y,Z))
#define CGROUP_OFFSET(X) (OFFSET_verify(cgroup_offset_table.X, (char *)__FUNCTION__, __FILE__, __LINE__, #X))

/*
 *struct declaration
 */
struct cgroup_offset_table {
	long cgroupfs_root_root_list;
	long cgroupfs_root_top_cgroup;
	long cgroupfs_root_subsys_list;
	long cgroupfs_root_actual_subsys_bits;
	long cgroupfs_root_name;
	long cgroup_sibling;
	long cgroup_children;
	long cgroup_dentry;
	long cgroup_subsys_name;
	long cgroup_subsys_sibling;
};

struct cgroup_group_spec {
	char path[PATHNAME_MAX];
	char *controllers[CG_CONTROLLER_MAX];
};

/*
 *function declaration
 */
int _init(void);
int _fini(void);

void cmd_lscgroup(void);
char *help_lscgroup[];

static void cgroup_init(void);
static void get_controller_name(ulong);
static void get_cgroup_name(ulong, char *);
static void parse_top_cgroup(ulong, char *);
static void print_all_cgroups(void);
static int in_cgroupfs_root(char *, struct cgroup_group_spec *);
static ulong locate_top_cgroup(struct cgroup_group_spec *);
static void parse_path(char *, char **);
static ulong locate_cgroup(ulong, ulong, char *);
static void standarlize_path(char *);
static void cgroup_elem(struct cgroup_group_spec *);
static void check_addr(ulong, ulong, char *, char *);
static ulong addr_to_cgroup(ulong, char *);
static void cgroup_addr(char *);
static void cgroup_list_cgroups(char **, struct cgroup_group_spec **, int);
static int parse_cgroup_spec(struct cgroup_group_spec **, char *);
static void free_cgroup_spec(char **, struct cgroup_group_spec **);

/*
 * global data
 */

static char controller_name[PATHNAME_MAX];
static int authen = FALSE;

static struct command_table_entry command_table[] = {
	{"lscgroup", cmd_lscgroup, help_lscgroup, 0},
	{NULL},
};

static struct cgroup_offset_table cgroup_offset_table = { 0 };

char *help_lscgroup[] = {
"lscgroup",
"list all cgroups",
"[-g [controllers:path] [...]] [-a [address]]",
"  The command list all present cgroups and their addresses, chosen cgroups",
"  and corresponding addresses or cgroup according to input address.",
"  When no parameter is specified, the command list all cgroups which are ",
"  present. The option -g is used to list subcgroups of cgroup specified by",
"  parameter <controllers>:<path>, controllers in <controllers>:<path> can be",
"  a comma separated controller list. The option -a is used to list cgroup ",
"  whose address equals to the succedent specified parameter. ",
"\nEXAMPLE",
"  display all cgroups:\n",
"    %s>lscgroup",
"         CGROUP       CONTROLLER:PATH",
"    ffff8801188f8030  blkio:/",
"    ffff8801188d3200  blkio:/libvirt",
"    ffff88011a724600  blkio:/libvirt/lxc",
"    ffff88011adac600  blkio:/libvirt/qemu",
"    ffff8801151f6030  net_cls:/",
"    ffff88011522a030  freezer:/",
"    ffff8801158f9200  freezer:/libvirt",
"    ffff88011a724800  freezer:/libvirt/lxc",
"    ffff88011adac800  freezer:/libvirt/qemu",
"    ffff880115264030  devices:/",
"    ffff880115846e00  devices:/libvirt",
"    ffff88011a724a00  devices:/libvirt/lxc",
"    ffff88011adaca00  devices:/libvirt/qemu",
"    ffff88011794c030  memory:/",
"    ffff88011738ca00  memory:/libvirt",
"    ffff88011a724c00  memory:/libvirt/lxc",
"    ffff88011adacc00  memory:/libvirt/qemu",
"    ffff880115b20030  cpuacct:/",
"    ffff8801191ed600  cpuacct:/libvirt",
"    ffff88011a08d200  cpuacct:/libvirt/lxc",
"    ffff8801188d3e00  cpuacct:/libvirt/qemu",
"    ffff88011923a030  cpu:/",
"    ffff880115846600  cpu:/libvirt",
"    ffff88011906e400  cpu:/libvirt/lxc",
"    ffff880117be6400  cpu:/libvirt/qemu",
"    ffff8801173f2030  cpuset:/",
"    ffff8801179e6200  cpuset:/libvirt",
"    ffff88011a08d000  cpuset:/libvirt/lxc",
"    ffff880119fe8000  cpuset:/libvirt/qemu",
"	",
"  display chosen cgroups:\n",
"    %s>lscgroup -g cpuset:/libvirt  -g cpu:/",
"         CGROUP       CONTROLLER:PATH",
"    ffff880115846600  cpu:/libvirt",
"    ffff88011906e400  cpu:/libvirt/lxc",
"    ffff880117be6400  cpu:/libvirt/qemu",
"         CGROUP       CONTROLLER:PATH",
"    ffff88011923a030  cpu:/",
"    ffff880115846600  cpu:/libvirt",
"    ffff88011906e400  cpu:/libvirt/lxc",
"    ffff880117be6400  cpu:/libvirt/qemu",
"       ",
"  display cgroup according to input address:\n",
"    %s>lscgroup -a ffff880119fe8000 -a ffff880115846600",
"         CGROUP       CONTROLLER:PATH",
"    ffff880119fe8000  cpuset:/libvirt/qemu",
"         CGROUP       CONTROLLER:PATH",
"    ffff880115846600  cpu:/libvirt",
NULL
};

int 
_init(void)
{
	register_extension(command_table);
	return 1;
}

int 
_fini(void)
{
	return 1;
}

static void 
cgroup_init(void)
{
	CGROUP_MEMBER_OFFSET_INIT(cgroupfs_root_root_list, "cgroupfs_root",
		"root_list");
	CGROUP_MEMBER_OFFSET_INIT(cgroupfs_root_top_cgroup, "cgroupfs_root",
		"top_cgroup");
	CGROUP_MEMBER_OFFSET_INIT(cgroupfs_root_subsys_list, "cgroupfs_root",
		"subsys_list");
	CGROUP_MEMBER_OFFSET_INIT(cgroupfs_root_actual_subsys_bits,
		"cgroupfs_root", "actual_subsys_bits");
	CGROUP_MEMBER_OFFSET_INIT(cgroupfs_root_name, "cgroupfs_root",
		"name");
	CGROUP_MEMBER_OFFSET_INIT(cgroup_sibling, "cgroup", "sibling");
	CGROUP_MEMBER_OFFSET_INIT(cgroup_children, "cgroup", "children");
	CGROUP_MEMBER_OFFSET_INIT(cgroup_dentry, "cgroup", "dentry");
	CGROUP_MEMBER_OFFSET_INIT(cgroup_subsys_name, "cgroup_subsys", "name");
	CGROUP_MEMBER_OFFSET_INIT(cgroup_subsys_sibling, "cgroup_subsys", 
		"sibling");
}

static void 
get_controller_name(ulong cgroupfs_root)
{
	char name[PATHNAME_MAX];
	ulong subsys, next, subsys_list, name_buf, name_addr;
	int len;
	
	BZERO(name, PATHNAME_MAX);
	BZERO(controller_name, PATHNAME_MAX);

	readmem(cgroupfs_root + CGROUP_OFFSET(cgroupfs_root_actual_subsys_bits),
		KVADDR, &subsys, sizeof(ulong), "cgroupfs_root_actual_subsys",
		FAULT_ON_ERROR);
	if(subsys == 0) {
		readmem(cgroupfs_root + CGROUP_OFFSET(cgroupfs_root_name), 
			KVADDR, &name, ROOT_MAX, "cgroupfs_root_name",
			FAULT_ON_ERROR);
		strcat(controller_name, name);
		return ;
	}
	subsys_list = cgroupfs_root + CGROUP_OFFSET(cgroupfs_root_subsys_list);
	readmem(subsys_list, KVADDR, &next, sizeof(ulong),
		"cgroupfs_root_subsys_list", FAULT_ON_ERROR);
	
	do {
		name_buf = next - CGROUP_OFFSET(cgroup_subsys_sibling)
                	+ CGROUP_OFFSET(cgroup_subsys_name);
		readmem(name_buf, KVADDR, &name_addr, sizeof(ulong),
			"cgroup_subsys_name", FAULT_ON_ERROR);
                readmem(name_addr, KVADDR, name, sizeof(name), 
			"char* name", FAULT_ON_ERROR);
			
		strcat(controller_name, name);
		strcat(controller_name, ",");

		readmem(next, KVADDR, &next, sizeof(ulong),
                "list_head", FAULT_ON_ERROR);
	} while(next != subsys_list);
	
	len = strlen(controller_name);	
	controller_name[len-1] = '\0';
}

static void
get_cgroup_name(ulong cgroup, char *name)
{
	ulong dentry, name_addr;
	char *dentry_buf;
	int len;

	readmem(cgroup + CGROUP_OFFSET(cgroup_dentry), KVADDR,
		&dentry, sizeof(ulong), "cgroup dentry",
		FAULT_ON_ERROR);

	dentry_buf = GETBUF(SIZE(dentry));
	readmem(dentry, KVADDR, dentry_buf, SIZE(dentry),
		"dentry", FAULT_ON_ERROR);
	len = UINT(dentry_buf + OFFSET(dentry_d_name) + OFFSET(qstr_len));
	name_addr = ULONG(dentry_buf + OFFSET(dentry_d_name) + OFFSET(qstr_name));
	readmem(name_addr, KVADDR, name, len, "qstr name", FAULT_ON_ERROR);
	FREEBUF(dentry_buf);
}

static void 
parse_top_cgroup(ulong top_cgroup, char *path)
{
	int len;
	char tmp_buf[PATHNAME_MAX];
	ulong list_head[2], next, child;

	BZERO(tmp_buf, PATHNAME_MAX);
	get_cgroup_name(top_cgroup, tmp_buf);
	if (strlen(path) > 1) 
		strncat(path, "/", 1);
	strncat(path, tmp_buf, strlen(tmp_buf));

	fprintf(fp, "%lx  %s:%s\n", top_cgroup, controller_name, path);

	child = top_cgroup + CGROUP_OFFSET(cgroup_children);
	readmem(child, KVADDR, list_head, sizeof(ulong) * 2,
		"cgroup children", FAULT_ON_ERROR);

	if ((list_head[0] == child) && (list_head[1] == child))
		return;

	next = list_head[0];
	while (next != child) {
		top_cgroup = next - CGROUP_OFFSET(cgroup_sibling);
		readmem(top_cgroup + CGROUP_OFFSET(cgroup_sibling) +
			OFFSET(list_head_next), KVADDR, &next, sizeof(ulong),
			"cgroup siblings", FAULT_ON_ERROR);
		len = strlen(path);
		parse_top_cgroup(top_cgroup, path);
		path[len] = '\0';
	}
}

static void 
print_all_cgroups(void)
{
	struct syment *roots;
        ulong top_cgroup;
        ulong list_head[2], next, cgroupfs_root;;
        char path_name[PATHNAME_MAX];
	char buf1[BUFSIZE];

        BZERO(path_name, PATHNAME_MAX);

        if (!(roots = symbol_search("roots")))
                error(FATAL, "roots symbol does not exist?\n");

        readmem(roots->value, KVADDR, list_head, sizeof(ulong) * 2,
                "list_head", FAULT_ON_ERROR);

        if ((list_head[0] == roots->value) && (list_head[1] == roots->value)) {
        	fprintf(fp, "no active cgroup hierarchy in the kernel.");
	        return;
	}

	fprintf(fp, "%s  CONTROLLER:PATH\n",
		mkstring(buf1, VADDR_PRLEN, CENTER, "CGROUP"));
        next = list_head[0];
        while (next != roots->value) {
                cgroupfs_root = next - CGROUP_OFFSET(cgroupfs_root_root_list);
		get_controller_name(cgroupfs_root);

                top_cgroup = cgroupfs_root +
                        CGROUP_OFFSET(cgroupfs_root_top_cgroup);
                /* print infomation of cgroup and subcgroup */
                parse_top_cgroup(top_cgroup, path_name);
                readmem(next + OFFSET(list_head_next), KVADDR, &next,
                        sizeof(ulong), "list_head next", FAULT_ON_ERROR);
                BZERO(path_name, PATHNAME_MAX);
		BZERO(controller_name, PATHNAME_MAX);
        }
}

static int
in_cgroupfs_root(char *tmp_name, struct cgroup_group_spec *elem)
{
	char *name;
	int i = 0;
	name = strtok(tmp_name, ",");
	while(name != NULL) {	
		while(elem->controllers[i] != NULL && i < CG_CONTROLLER_MAX) {
			if(STREQ(name, elem->controllers[i]))
				return 1;
			i++;
		}
		name = strtok(NULL, ",");
		i = 0;
	}	
	
	return 0;
}

static ulong 
locate_top_cgroup(struct cgroup_group_spec *elem)
{
	struct syment *roots;
	ulong top_cgroup;
	ulong list_head[2], next, cgroupfs_root;
	char tmp_name[PATHNAME_MAX];

	if (!(roots = symbol_search("roots")))
		error(FATAL, "roots symbol does not exist?");

	readmem(roots->value, KVADDR, list_head, sizeof(ulong)*2,
		"list_head", FAULT_ON_ERROR);

	if ((list_head[0] == roots->value) && (list_head[1] == roots->value))
		return 0;
	
	next = list_head[0];
	while (next != roots->value) {
		/* begin from first root */
		cgroupfs_root = next - CGROUP_OFFSET(cgroupfs_root_root_list);
		get_controller_name(cgroupfs_root);
		strcpy(tmp_name, controller_name);

		if (in_cgroupfs_root(tmp_name, elem)) {
   			top_cgroup = cgroupfs_root +
   				CGROUP_OFFSET(cgroupfs_root_top_cgroup);
  			return top_cgroup;
		}
		readmem(next + OFFSET(list_head_next), KVADDR, &next,
   			sizeof(ulong), "list_head", FAULT_ON_ERROR);
		BZERO(controller_name, PATHNAME_MAX);
	}
	return 0;
}

/*
 * function parse_path and extracts the input path before the first '/' as
 * relatively path which will be used to compare with path name of cgroup.
 * In addition, it ignores the unnecessary '/' in the path
 */
static void 
parse_path(char *path, char **elem_path)
{ 
 	char *token;

	token = *elem_path;
	if (token[0] == '/') {
		*path++ = *token++;
	} else {
		while (*token) {
			if (*token == '/' && *(token + 1) == '/') {
				token++;
			} else if (*token == '/' && *(token + 1) != '/') {
				token++; 
				break;
			} else {
				*path++ = *token++;	
			}
		}	
	}
	*elem_path = token;
	*path = '\0';
}

static ulong 
locate_cgroup(ulong current, ulong prev_addr, char *elem_path)
{
        char tmp_buf[PATHNAME_MAX];
	char path[PATHNAME_MAX];
	char *tmp_path = elem_path;
	ulong child, sibling, child_offset, sibling_offset;

	if (*elem_path == '\0')
		return prev_addr;

        BZERO(tmp_buf, PATHNAME_MAX);
	get_cgroup_name(current, tmp_buf);

	parse_path(path, &elem_path);

	readmem(current + CGROUP_OFFSET(cgroup_children), KVADDR, &child,
                sizeof(ulong), "cgroup children", FAULT_ON_ERROR);
        readmem(current + CGROUP_OFFSET(cgroup_sibling), KVADDR, &sibling,
                sizeof(ulong), "cgroup sibling", FAULT_ON_ERROR);	

	child_offset = CGROUP_OFFSET(cgroup_children);
	sibling_offset = CGROUP_OFFSET(cgroup_sibling);
	/* parse the children if temp=path_name, do change elem_path */
	if (STREQ(tmp_buf, path)) {
		if ((child - child_offset != current))
			return locate_cgroup(child - sibling_offset,
					current, elem_path);
		else if (*elem_path == '\0')
			return current;
	} else { 
	/* parse the sibling if temp !=path_name, do not chage elem_path */
		if (((sibling - child_offset) != prev_addr) &&
		    ((sibling - sibling_offset) != current)) {
			elem_path = tmp_path;
			return locate_cgroup(sibling - sibling_offset,
					prev_addr, elem_path);
		}
	}
	return 0;
}

/*
 * make the input path begin with character '/' and end without character '/'
 * to cope with the situation that the input path may be like "/xxxxx",
 * "xxxxx", "xxxxx/", or "/xxxxx/"
 */
static void 
standarlize_path(char *path)
{
	int len;

	len = strlen(path) - 1;
	if (path[len] == '/')
		path[len] = '\0';

	if (path[0] != '/') {
		len = strlen(path);
		path[len + 1] = '\0';
		while (len) {
			path[len] = path[len - 1];
			len--;
		}
		path[0] = '/';
	}
}

static void 
mani_path(char *path)
{	
	int len;

	standarlize_path(path);
 	
	if (STREQ(path, "/")) {
		*path = '\0';
                return ;
	}
	len = strlen(path);
	while (path[len] != '/') {
		path[len] = '\0';
		len--;
	}
	path[len] = '\0';
	path[0] = '/';
}

static void 
cgroup_elem(struct cgroup_group_spec *list_elem)
{
	ulong top_cgroup;
	ulong cgroup;
	char path_name[PATHNAME_MAX];
	char buf1[BUFSIZE];

	top_cgroup = locate_top_cgroup(list_elem);
	if (top_cgroup == 0) {
		fprintf(fp, "can not find cgroup %s, check the input.\n",
			list_elem->path);
		return ;
	}
        
	strcpy(path_name, list_elem->path);
	standarlize_path(path_name);
	cgroup = locate_cgroup(top_cgroup, top_cgroup, path_name);
	if (cgroup == 0) {
		fprintf(fp, "can not find cgroup %s, check the input.\n", 
			list_elem->path);
		return ;
	}
 
	mani_path(list_elem->path);
	fprintf(fp, "%s  CONTROLLER:PATH\n",
                mkstring(buf1, VADDR_PRLEN, CENTER, "CGROUP"));
	parse_top_cgroup(cgroup, list_elem->path);
}

static void 
check_addr(ulong top_cgroup, ulong addr_num, char *path, char *full_path)
{
	int len;
        char tmp_buf[PATHNAME_MAX];
        ulong list_head[2], next, child;

        BZERO(tmp_buf, PATHNAME_MAX);
        get_cgroup_name(top_cgroup, tmp_buf);
        if (strlen(path) > 1)
                strncat(path, "/", 1);
        strncat(path, tmp_buf, strlen(tmp_buf));

	if (top_cgroup == addr_num) {
                strcpy(full_path, path);
		authen = TRUE;
                return ;
        }

        child = top_cgroup + CGROUP_OFFSET(cgroup_children);
        readmem(child, KVADDR, list_head, sizeof(ulong) * 2,
                "cgroup children", FAULT_ON_ERROR);

        next = list_head[0];
        while (next != child) {
                top_cgroup = next - CGROUP_OFFSET(cgroup_sibling);
                readmem(top_cgroup + CGROUP_OFFSET(cgroup_sibling) +
                        OFFSET(list_head_next), KVADDR, &next, sizeof(ulong),
                        "cgroup siblings", FAULT_ON_ERROR);
                len = strlen(path);
                check_addr(top_cgroup, addr_num, path, full_path);
                path[len] = '\0';
        }
}

static ulong 
addr_to_cgroup(ulong addr_num, char *path)
{
	struct syment *roots;
        ulong top_cgroup;
        ulong list_head[2], next, cgroupfs_root;
	char path_name[PATHNAME_MAX];

	BZERO(path_name, PATHNAME_MAX);
        if (!(roots = symbol_search("roots")))
                error(FATAL, "roots symbol does not exist?");

        readmem(roots->value, KVADDR, list_head, sizeof(ulong)*2,
                "list_head", FAULT_ON_ERROR);

        next = list_head[0];
        while (next != roots->value) {
                /* begin from first root */
                cgroupfs_root = next - CGROUP_OFFSET(cgroupfs_root_root_list);
                get_controller_name(cgroupfs_root);

                top_cgroup = cgroupfs_root +
                	CGROUP_OFFSET(cgroupfs_root_top_cgroup);
		check_addr(top_cgroup, addr_num, path_name, path);
		if (authen) {
			authen = FALSE;
			return TRUE;
		}	
                readmem(next + OFFSET(list_head_next), KVADDR, &next,
                        sizeof(ulong), "list_head", FAULT_ON_ERROR);
		BZERO(path_name, PATHNAME_MAX);
                BZERO(controller_name, PATHNAME_MAX);
        }
        return FALSE;	 	
}

static void 
cgroup_addr(char *addr)
{
	ulong addr_num;
	char path[PATHNAME_MAX];
	char buf1[BUFSIZE];

	BZERO(path, PATHNAME_MAX);
	addr_num = stol (addr, FAULT_ON_ERROR, NULL);

	if (!addr_to_cgroup(addr_num, path)) {
		fprintf(fp, "can not find cgroup with address %lx", addr_num);
		return ;	
	}
	fprintf(fp, "%s  CONTROLLER:PATH\n",
                mkstring(buf1, VADDR_PRLEN, CENTER, "CGROUP"));
	fprintf(fp, "%lx  %s:%s\n", addr_num, controller_name, path);	
}

static void 
cgroup_list_cgroups(char **addr, struct cgroup_group_spec *cgroup_list[],
	int flags)
{
	int i,j;

	i = j = 0;	
	cgroup_init();
	if(cgroup_offset_table.cgroupfs_root_root_list == -1) {
		fprintf(fp, "cgroup does not exist, check kernel version.");
		return ;
	}
	if (flags == 0 ) {
		/* list all the cgroups */
		print_all_cgroups();
	} 
	if (flags & LIST_CER) {
		/* list the specified cgroups */
		while ((cgroup_list[i]->path != NULL)) {
			cgroup_elem(cgroup_list[i]);
			i++;
		}
	}
	if (flags & LIST_ADD) {
		/* list specified addr cgroups */
		while ((addr[j] != NULL)) {
			cgroup_addr(addr[j]);
			j++;
		}	
	}
}

static int 
parse_cgroup_spec(struct cgroup_group_spec **list, char *optarg)
{
	struct cgroup_group_spec *ptr;
	int i, j;
	char *controller, *path, *temp;

	ptr = *list;

	for (i = 0; i < CG_HIER_MAX; i++, ptr++) {
		if (!list[i])
			break;
	}

	if (i == CG_HIER_MAX) {
		fprintf(fp, "Max allowed hierarchies %d reached\n",
			CG_HIER_MAX);
		return -1;
	}

	controller = strtok(optarg, ":");
	if (!controller)
		return -1;

	path = strtok(NULL, ":");
	if (!path)
		return -1;

	list[i] = (struct cgroup_group_spec *)GETBUF(sizeof(**list));
	j = 0;
	do {
		if (j == 0)
			temp = strtok(controller, ",");
		else
			temp = strtok(NULL, ",");

		if (temp) {
			list[i]->controllers[j] = strdup(temp);
			if (!list[i]->controllers[j]) {
				FREEBUF(list[i]);
				fprintf(fp, "%s\n", strerror(errno));
				return -1;
			}
		}
		j++;
	} while (temp && (j < (CG_CONTROLLER_MAX - 1)));

	strncpy(list[i]->path, path, strlen(path));

	return 0;
}

static int 
parse_addr_spec(char **addr,char *optarg)
{
	int i;

	for(i = 0; i < CG_HIER_MAX; i++)
		if (!addr[i])
			break;
	if (i == CG_HIER_MAX) {
                fprintf(fp, "Max allowed hierarchies %d reached\n",
                        CG_HIER_MAX);
                return -1;
        }
	
	addr[i] = strdup(optarg);
	if (!addr[i]) {
		fprintf(fp, "%s\n",strerror(errno));
		return -1;
	}
	return 0;
}

static void 
free_cgroup_spec(char **addr, struct cgroup_group_spec **list)
{
	int i,j;

	for (i = 0; i < CG_HIER_MAX; i++) {
		if (list[i]) {
			for(j = 0; j< CG_CONTROLLER_MAX; j++)
				if (list[i]->controllers[j])
					free(list[i]->controllers[j]);
			FREEBUF(list[i]);
		}
		else {
			break;
		}	
	}
	for (i =0; i< CG_HIER_MAX; i++) {
		if (addr[i])
			free(addr[i]);
		else 
			break;
	}

}

void 
cmd_lscgroup(void)
{
	int c, ret, flags;
	char *addr[CG_HIER_MAX];
	struct cgroup_group_spec *cgroup_list[CG_HIER_MAX];

	ret = flags = 0;
	BZERO(cgroup_list, sizeof(cgroup_list));
	BZERO(addr, sizeof(addr));

	while ((c = getopt(argcnt, args, "a:g:")) != EOF) {
		switch(c) {
		case 'a':
			ret = parse_addr_spec(addr, optarg);	
			if(ret) {
				fprintf(fp, "%s: cgroup address parsing failed"
					"(%s)\n", args[0], optarg);
				free_cgroup_spec(addr, cgroup_list);
				return ;	
			}
			flags |= LIST_ADD;
			break;

		case 'g':
			ret = parse_cgroup_spec(cgroup_list, optarg);
			if(ret) {
				fprintf(fp, "%s: cgroup controller and path "
				 	"parsing failed(%s)\n",
					args[0], optarg);
				free_cgroup_spec(addr, cgroup_list);
				return ;
			}
			flags |= LIST_CER;
			break;

		default:
			cmd_usage(pc->curcmd, SYNOPSIS);
			return ;
		}
	}
	if (argerrs)
		cmd_usage(pc->curcmd, SYNOPSIS);
	if (optind < argcnt)
		cmd_usage(pc->curcmd, SYNOPSIS);

	cgroup_list_cgroups(addr, cgroup_list, flags);
	free_cgroup_spec(addr, cgroup_list);
}

--
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