Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0facaa17 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky
Browse files

s390/sysinfo: convert /proc/sysinfo to seqfile



The current proc implementation of the /proc/sysinfo file writes all
informations contained in all system information blocks to a single
page.
This is done by calling sprintf all the time in the expectation that
everything will fit into a single page. This however is not necessarily
true if the configuration of a machine is very large.
So convert /proc/sysinfo to avoid writing into random memory regions.

For readability reasons a couple of lines are longer than 80 characters.

Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 78609132
Loading
Loading
Loading
Loading
+115 −167
Original line number Diff line number Diff line
@@ -25,14 +25,14 @@
static inline int stsi_0(void)
{
	int rc = stsi(NULL, 0, 0, 0);

	return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28);
}

static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info)
{
	if (stsi(info, 1, 1, 1) == -ENOSYS)
		return len;

		return;
	EBCASC(info->manufacturer, sizeof(info->manufacturer));
	EBCASC(info->type, sizeof(info->type));
	EBCASC(info->model, sizeof(info->model));
@@ -41,11 +41,8 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
	EBCASC(info->model_capacity, sizeof(info->model_capacity));
	EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap));
	EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap));
	len += sprintf(page + len, "Manufacturer:         %-16.16s\n",
		       info->manufacturer);
	len += sprintf(page + len, "Type:                 %-4.4s\n",
		       info->type);
	if (info->model[0] != '\0')
	seq_printf(m, "Manufacturer:         %-16.16s\n", info->manufacturer);
	seq_printf(m, "Type:                 %-4.4s\n", info->type);
	/*
	 * Sigh: the model field has been renamed with System z9
	 * to model_capacity and a new model field has been added
@@ -53,46 +50,36 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
	 * the "Model:" prints "model_capacity model" or just
	 * "model_capacity" if the model string is empty .
	 */
		len += sprintf(page + len,
			       "Model:                %-16.16s %-16.16s\n",
			       info->model_capacity, info->model);
	else
		len += sprintf(page + len, "Model:                %-16.16s\n",
			       info->model_capacity);
	len += sprintf(page + len, "Sequence Code:        %-16.16s\n",
		       info->sequence);
	len += sprintf(page + len, "Plant:                %-4.4s\n",
		       info->plant);
	len += sprintf(page + len, "Model Capacity:       %-16.16s %08u\n",
	seq_printf(m, "Model:                %-16.16s", info->model_capacity);
	if (info->model[0] != '\0')
		seq_printf(m, " %-16.16s", info->model);
	seq_putc(m, '\n');
	seq_printf(m, "Sequence Code:        %-16.16s\n", info->sequence);
	seq_printf(m, "Plant:                %-4.4s\n", info->plant);
	seq_printf(m, "Model Capacity:       %-16.16s %08u\n",
		   info->model_capacity, *(u32 *) info->model_cap_rating);
	if (info->model_perm_cap[0] != '\0')
		len += sprintf(page + len,
			       "Model Perm. Capacity: %-16.16s %08u\n",
		seq_printf(m, "Model Perm. Capacity: %-16.16s %08u\n",
			   info->model_perm_cap,
			   *(u32 *) info->model_perm_cap_rating);
	if (info->model_temp_cap[0] != '\0')
		len += sprintf(page + len,
			       "Model Temp. Capacity: %-16.16s %08u\n",
		seq_printf(m, "Model Temp. Capacity: %-16.16s %08u\n",
			   info->model_temp_cap,
			   *(u32 *) info->model_temp_cap_rating);
	if (info->cai) {
		len += sprintf(page + len,
			       "Capacity Adj. Ind.:   %d\n",
			       info->cai);
		len += sprintf(page + len, "Capacity Ch. Reason:  %d\n",
			       info->ccr);
		seq_printf(m, "Capacity Adj. Ind.:   %d\n", info->cai);
		seq_printf(m, "Capacity Ch. Reason:  %d\n", info->ccr);
	}
	return len;
}

static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len)
static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info)
{
	static int max_mnest;
	int i, rc;

	len += sprintf(page + len, "\n");
	seq_putc(m, '\n');
	if (!MACHINE_HAS_TOPOLOGY)
		return len;
		return;
	if (max_mnest) {
		stsi(info, 15, 1, max_mnest);
	} else {
@@ -102,40 +89,32 @@ static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len)
				break;
		}
	}
	len += sprintf(page + len, "CPU Topology HW:     ");
	seq_printf(m, "CPU Topology HW:     ");
	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
		len += sprintf(page + len, " %d", info->mag[i]);
	len += sprintf(page + len, "\n");
		seq_printf(m, " %d", info->mag[i]);
	seq_putc(m, '\n');
#ifdef CONFIG_SCHED_MC
	store_topology(info);
	len += sprintf(page + len, "CPU Topology SW:     ");
	seq_printf(m, "CPU Topology SW:     ");
	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
		len += sprintf(page + len, " %d", info->mag[i]);
	len += sprintf(page + len, "\n");
		seq_printf(m, " %d", info->mag[i]);
	seq_putc(m, '\n');
#endif
	return len;
}

static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info)
{
	struct sysinfo_1_2_2_extension *ext;
	int i;

	if (stsi(info, 1, 2, 2) == -ENOSYS)
		return len;
		return;
	ext = (struct sysinfo_1_2_2_extension *)
		((unsigned long) info + info->acc_offset);

	len += sprintf(page + len, "CPUs Total:           %d\n",
		       info->cpus_total);
	len += sprintf(page + len, "CPUs Configured:      %d\n",
		       info->cpus_configured);
	len += sprintf(page + len, "CPUs Standby:         %d\n",
		       info->cpus_standby);
	len += sprintf(page + len, "CPUs Reserved:        %d\n",
		       info->cpus_reserved);

	if (info->format == 1) {
	seq_printf(m, "CPUs Total:           %d\n", info->cpus_total);
	seq_printf(m, "CPUs Configured:      %d\n", info->cpus_configured);
	seq_printf(m, "CPUs Standby:         %d\n", info->cpus_standby);
	seq_printf(m, "CPUs Reserved:        %d\n", info->cpus_reserved);
	/*
	 * Sigh 2. According to the specification the alternate
	 * capability field is a 32 bit floating point number
@@ -145,138 +124,107 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
	 * The user-space needs to know about the strange
	 * encoding of the alternate cpu capability.
	 */
		len += sprintf(page + len, "Capability:           %u %u\n",
			       info->capability, ext->alt_capability);
		for (i = 2; i <= info->cpus_total; i++)
			len += sprintf(page + len,
				       "Adjustment %02d-way:    %u %u\n",
				       i, info->adjustment[i-2],
				       ext->alt_adjustment[i-2]);

	} else {
		len += sprintf(page + len, "Capability:           %u\n",
			       info->capability);
		for (i = 2; i <= info->cpus_total; i++)
			len += sprintf(page + len,
				       "Adjustment %02d-way:    %u\n",
	seq_printf(m, "Capability:           %u", info->capability);
	if (info->format == 1)
		seq_printf(m, " %u", ext->alt_capability);
	seq_putc(m, '\n');
	for (i = 2; i <= info->cpus_total; i++) {
		seq_printf(m, "Adjustment %02d-way:    %u",
			   i, info->adjustment[i-2]);
		if (info->format == 1)
			seq_printf(m, " %u", ext->alt_adjustment[i-2]);
		seq_putc(m, '\n');
	}

	if (info->secondary_capability != 0)
		len += sprintf(page + len, "Secondary Capability: %d\n",
	if (info->secondary_capability)
		seq_printf(m, "Secondary Capability: %d\n",
			   info->secondary_capability);
	return len;
}

static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len)
static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info)
{
	if (stsi(info, 2, 2, 2) == -ENOSYS)
		return len;

		return;
	EBCASC(info->name, sizeof(info->name));

	len += sprintf(page + len, "\n");
	len += sprintf(page + len, "LPAR Number:          %d\n",
		       info->lpar_number);

	len += sprintf(page + len, "LPAR Characteristics: ");
	seq_putc(m, '\n');
	seq_printf(m, "LPAR Number:          %d\n", info->lpar_number);
	seq_printf(m, "LPAR Characteristics: ");
	if (info->characteristics & LPAR_CHAR_DEDICATED)
		len += sprintf(page + len, "Dedicated ");
		seq_printf(m, "Dedicated ");
	if (info->characteristics & LPAR_CHAR_SHARED)
		len += sprintf(page + len, "Shared ");
		seq_printf(m, "Shared ");
	if (info->characteristics & LPAR_CHAR_LIMITED)
		len += sprintf(page + len, "Limited ");
	len += sprintf(page + len, "\n");

	len += sprintf(page + len, "LPAR Name:            %-8.8s\n",
		       info->name);

	len += sprintf(page + len, "LPAR Adjustment:      %d\n",
		       info->caf);

	len += sprintf(page + len, "LPAR CPUs Total:      %d\n",
		       info->cpus_total);
	len += sprintf(page + len, "LPAR CPUs Configured: %d\n",
		       info->cpus_configured);
	len += sprintf(page + len, "LPAR CPUs Standby:    %d\n",
		       info->cpus_standby);
	len += sprintf(page + len, "LPAR CPUs Reserved:   %d\n",
		       info->cpus_reserved);
	len += sprintf(page + len, "LPAR CPUs Dedicated:  %d\n",
		       info->cpus_dedicated);
	len += sprintf(page + len, "LPAR CPUs Shared:     %d\n",
		       info->cpus_shared);
	return len;
		seq_printf(m, "Limited ");
	seq_putc(m, '\n');
	seq_printf(m, "LPAR Name:            %-8.8s\n", info->name);
	seq_printf(m, "LPAR Adjustment:      %d\n", info->caf);
	seq_printf(m, "LPAR CPUs Total:      %d\n", info->cpus_total);
	seq_printf(m, "LPAR CPUs Configured: %d\n", info->cpus_configured);
	seq_printf(m, "LPAR CPUs Standby:    %d\n", info->cpus_standby);
	seq_printf(m, "LPAR CPUs Reserved:   %d\n", info->cpus_reserved);
	seq_printf(m, "LPAR CPUs Dedicated:  %d\n", info->cpus_dedicated);
	seq_printf(m, "LPAR CPUs Shared:     %d\n", info->cpus_shared);
}

static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len)
static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info)
{
	int i;

	if (stsi(info, 3, 2, 2) == -ENOSYS)
		return len;
		return;
	for (i = 0; i < info->count; i++) {
		EBCASC(info->vm[i].name, sizeof(info->vm[i].name));
		EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi));
		len += sprintf(page + len, "\n");
		len += sprintf(page + len, "VM%02d Name:            %-8.8s\n",
			       i, info->vm[i].name);
		len += sprintf(page + len, "VM%02d Control Program: %-16.16s\n",
			       i, info->vm[i].cpi);

		len += sprintf(page + len, "VM%02d Adjustment:      %d\n",
			       i, info->vm[i].caf);

		len += sprintf(page + len, "VM%02d CPUs Total:      %d\n",
			       i, info->vm[i].cpus_total);
		len += sprintf(page + len, "VM%02d CPUs Configured: %d\n",
			       i, info->vm[i].cpus_configured);
		len += sprintf(page + len, "VM%02d CPUs Standby:    %d\n",
			       i, info->vm[i].cpus_standby);
		len += sprintf(page + len, "VM%02d CPUs Reserved:   %d\n",
			       i, info->vm[i].cpus_reserved);
		seq_putc(m, '\n');
		seq_printf(m, "VM%02d Name:            %-8.8s\n", i, info->vm[i].name);
		seq_printf(m, "VM%02d Control Program: %-16.16s\n", i, info->vm[i].cpi);
		seq_printf(m, "VM%02d Adjustment:      %d\n", i, info->vm[i].caf);
		seq_printf(m, "VM%02d CPUs Total:      %d\n", i, info->vm[i].cpus_total);
		seq_printf(m, "VM%02d CPUs Configured: %d\n", i, info->vm[i].cpus_configured);
		seq_printf(m, "VM%02d CPUs Standby:    %d\n", i, info->vm[i].cpus_standby);
		seq_printf(m, "VM%02d CPUs Reserved:   %d\n", i, info->vm[i].cpus_reserved);
	}
	return len;
}

static int proc_read_sysinfo(char *page, char **start,
			     off_t off, int count,
			     int *eof, void *data)
static int sysinfo_show(struct seq_file *m, void *v)
{
	unsigned long info = get_zeroed_page(GFP_KERNEL);
	int level, len;
	void *info = (void *)get_zeroed_page(GFP_KERNEL);
	int level;

	if (!info)
		return 0;

	len = 0;
	level = stsi_0();
	if (level >= 1)
		len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len);

		stsi_1_1_1(m, info);
	if (level >= 1)
		len = stsi_15_1_x((struct sysinfo_15_1_x *) info, page, len);

		stsi_15_1_x(m, info);
	if (level >= 1)
		len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len);

		stsi_1_2_2(m, info);
	if (level >= 2)
		len = stsi_2_2_2((struct sysinfo_2_2_2 *) info, page, len);

		stsi_2_2_2(m, info);
	if (level >= 3)
		len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len);
		stsi_3_2_2(m, info);
	free_page((unsigned long)info);
	return 0;
}

	free_page(info);
	return len;
static int sysinfo_open(struct inode *inode, struct file *file)
{
	return single_open(file, sysinfo_show, NULL);
}

static __init int create_proc_sysinfo(void)
static const struct file_operations sysinfo_fops = {
	.open		= sysinfo_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
};

static int __init sysinfo_create_proc(void)
{
	create_proc_read_entry("sysinfo", 0444, NULL,
			       proc_read_sysinfo, NULL);
	proc_create("sysinfo", 0444, NULL, &sysinfo_fops);
	return 0;
}
device_initcall(create_proc_sysinfo);
device_initcall(sysinfo_create_proc);

/*
 * Service levels interface.