1
0
Fork 0

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: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
wifi-calibration
Heiko Carstens 2012-09-03 09:38:30 +02:00 committed by Martin Schwidefsky
parent 7860913279
commit 0facaa170a
1 changed files with 119 additions and 171 deletions

View File

@ -25,14 +25,14 @@
static inline int stsi_0(void) static inline int stsi_0(void)
{ {
int rc = stsi(NULL, 0, 0, 0); int rc = stsi(NULL, 0, 0, 0);
return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); 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) if (stsi(info, 1, 1, 1) == -ENOSYS)
return len; return;
EBCASC(info->manufacturer, sizeof(info->manufacturer)); EBCASC(info->manufacturer, sizeof(info->manufacturer));
EBCASC(info->type, sizeof(info->type)); EBCASC(info->type, sizeof(info->type));
EBCASC(info->model, sizeof(info->model)); EBCASC(info->model, sizeof(info->model));
@ -41,58 +41,45 @@ 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_capacity, sizeof(info->model_capacity));
EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap)); EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap));
EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap)); EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap));
len += sprintf(page + len, "Manufacturer: %-16.16s\n", seq_printf(m, "Manufacturer: %-16.16s\n", info->manufacturer);
info->manufacturer); seq_printf(m, "Type: %-4.4s\n", info->type);
len += sprintf(page + len, "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
* after the plant field. To avoid confusing older programs
* the "Model:" prints "model_capacity model" or just
* "model_capacity" if the model string is empty .
*/
seq_printf(m, "Model: %-16.16s", info->model_capacity);
if (info->model[0] != '\0') if (info->model[0] != '\0')
/* seq_printf(m, " %-16.16s", info->model);
* Sigh: the model field has been renamed with System z9 seq_putc(m, '\n');
* to model_capacity and a new model field has been added seq_printf(m, "Sequence Code: %-16.16s\n", info->sequence);
* after the plant field. To avoid confusing older programs seq_printf(m, "Plant: %-4.4s\n", info->plant);
* the "Model:" prints "model_capacity model" or just seq_printf(m, "Model Capacity: %-16.16s %08u\n",
* "model_capacity" if the model string is empty . info->model_capacity, *(u32 *) info->model_cap_rating);
*/
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",
info->model_capacity, *(u32 *) info->model_cap_rating);
if (info->model_perm_cap[0] != '\0') if (info->model_perm_cap[0] != '\0')
len += sprintf(page + len, seq_printf(m, "Model Perm. Capacity: %-16.16s %08u\n",
"Model Perm. Capacity: %-16.16s %08u\n", info->model_perm_cap,
info->model_perm_cap, *(u32 *) info->model_perm_cap_rating);
*(u32 *) info->model_perm_cap_rating);
if (info->model_temp_cap[0] != '\0') if (info->model_temp_cap[0] != '\0')
len += sprintf(page + len, seq_printf(m, "Model Temp. Capacity: %-16.16s %08u\n",
"Model Temp. Capacity: %-16.16s %08u\n", info->model_temp_cap,
info->model_temp_cap, *(u32 *) info->model_temp_cap_rating);
*(u32 *) info->model_temp_cap_rating);
if (info->cai) { if (info->cai) {
len += sprintf(page + len, seq_printf(m, "Capacity Adj. Ind.: %d\n", info->cai);
"Capacity Adj. Ind.: %d\n", seq_printf(m, "Capacity Ch. Reason: %d\n", info->ccr);
info->cai);
len += sprintf(page + len, "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; static int max_mnest;
int i, rc; int i, rc;
len += sprintf(page + len, "\n"); seq_putc(m, '\n');
if (!MACHINE_HAS_TOPOLOGY) if (!MACHINE_HAS_TOPOLOGY)
return len; return;
if (max_mnest) { if (max_mnest) {
stsi(info, 15, 1, max_mnest); stsi(info, 15, 1, max_mnest);
} else { } else {
@ -102,181 +89,142 @@ static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len)
break; break;
} }
} }
len += sprintf(page + len, "CPU Topology HW: "); seq_printf(m, "CPU Topology HW: ");
for (i = 0; i < TOPOLOGY_NR_MAG; i++) for (i = 0; i < TOPOLOGY_NR_MAG; i++)
len += sprintf(page + len, " %d", info->mag[i]); seq_printf(m, " %d", info->mag[i]);
len += sprintf(page + len, "\n"); seq_putc(m, '\n');
#ifdef CONFIG_SCHED_MC #ifdef CONFIG_SCHED_MC
store_topology(info); store_topology(info);
len += sprintf(page + len, "CPU Topology SW: "); seq_printf(m, "CPU Topology SW: ");
for (i = 0; i < TOPOLOGY_NR_MAG; i++) for (i = 0; i < TOPOLOGY_NR_MAG; i++)
len += sprintf(page + len, " %d", info->mag[i]); seq_printf(m, " %d", info->mag[i]);
len += sprintf(page + len, "\n"); seq_putc(m, '\n');
#endif #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; struct sysinfo_1_2_2_extension *ext;
int i; int i;
if (stsi(info, 1, 2, 2) == -ENOSYS) if (stsi(info, 1, 2, 2) == -ENOSYS)
return len; return;
ext = (struct sysinfo_1_2_2_extension *) ext = (struct sysinfo_1_2_2_extension *)
((unsigned long) info + info->acc_offset); ((unsigned long) info + info->acc_offset);
seq_printf(m, "CPUs Total: %d\n", info->cpus_total);
len += sprintf(page + len, "CPUs Total: %d\n", seq_printf(m, "CPUs Configured: %d\n", info->cpus_configured);
info->cpus_total); seq_printf(m, "CPUs Standby: %d\n", info->cpus_standby);
len += sprintf(page + len, "CPUs Configured: %d\n", seq_printf(m, "CPUs Reserved: %d\n", info->cpus_reserved);
info->cpus_configured); /*
len += sprintf(page + len, "CPUs Standby: %d\n", * Sigh 2. According to the specification the alternate
info->cpus_standby); * capability field is a 32 bit floating point number
len += sprintf(page + len, "CPUs Reserved: %d\n", * if the higher order 8 bits are not zero. Printing
info->cpus_reserved); * a floating point number in the kernel is a no-no,
* always print the number as 32 bit unsigned integer.
if (info->format == 1) { * The user-space needs to know about the strange
/* * encoding of the alternate cpu capability.
* Sigh 2. According to the specification the alternate */
* capability field is a 32 bit floating point number seq_printf(m, "Capability: %u", info->capability);
* if the higher order 8 bits are not zero. Printing if (info->format == 1)
* a floating point number in the kernel is a no-no, seq_printf(m, " %u", ext->alt_capability);
* always print the number as 32 bit unsigned integer. seq_putc(m, '\n');
* The user-space needs to know about the strange for (i = 2; i <= info->cpus_total; i++) {
* encoding of the alternate cpu capability. seq_printf(m, "Adjustment %02d-way: %u",
*/ i, info->adjustment[i-2]);
len += sprintf(page + len, "Capability: %u %u\n", if (info->format == 1)
info->capability, ext->alt_capability); seq_printf(m, " %u", ext->alt_adjustment[i-2]);
for (i = 2; i <= info->cpus_total; i++) seq_putc(m, '\n');
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",
i, info->adjustment[i-2]);
} }
if (info->secondary_capability)
if (info->secondary_capability != 0) seq_printf(m, "Secondary Capability: %d\n",
len += sprintf(page + len, "Secondary Capability: %d\n", info->secondary_capability);
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) if (stsi(info, 2, 2, 2) == -ENOSYS)
return len; return;
EBCASC(info->name, sizeof(info->name)); EBCASC(info->name, sizeof(info->name));
seq_putc(m, '\n');
len += sprintf(page + len, "\n"); seq_printf(m, "LPAR Number: %d\n", info->lpar_number);
len += sprintf(page + len, "LPAR Number: %d\n", seq_printf(m, "LPAR Characteristics: ");
info->lpar_number);
len += sprintf(page + len, "LPAR Characteristics: ");
if (info->characteristics & LPAR_CHAR_DEDICATED) if (info->characteristics & LPAR_CHAR_DEDICATED)
len += sprintf(page + len, "Dedicated "); seq_printf(m, "Dedicated ");
if (info->characteristics & LPAR_CHAR_SHARED) if (info->characteristics & LPAR_CHAR_SHARED)
len += sprintf(page + len, "Shared "); seq_printf(m, "Shared ");
if (info->characteristics & LPAR_CHAR_LIMITED) if (info->characteristics & LPAR_CHAR_LIMITED)
len += sprintf(page + len, "Limited "); seq_printf(m, "Limited ");
len += sprintf(page + len, "\n"); seq_putc(m, '\n');
seq_printf(m, "LPAR Name: %-8.8s\n", info->name);
len += sprintf(page + len, "LPAR Name: %-8.8s\n", seq_printf(m, "LPAR Adjustment: %d\n", info->caf);
info->name); seq_printf(m, "LPAR CPUs Total: %d\n", info->cpus_total);
seq_printf(m, "LPAR CPUs Configured: %d\n", info->cpus_configured);
len += sprintf(page + len, "LPAR Adjustment: %d\n", seq_printf(m, "LPAR CPUs Standby: %d\n", info->cpus_standby);
info->caf); seq_printf(m, "LPAR CPUs Reserved: %d\n", info->cpus_reserved);
seq_printf(m, "LPAR CPUs Dedicated: %d\n", info->cpus_dedicated);
len += sprintf(page + len, "LPAR CPUs Total: %d\n", seq_printf(m, "LPAR CPUs Shared: %d\n", info->cpus_shared);
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;
} }
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; int i;
if (stsi(info, 3, 2, 2) == -ENOSYS) if (stsi(info, 3, 2, 2) == -ENOSYS)
return len; return;
for (i = 0; i < info->count; i++) { for (i = 0; i < info->count; i++) {
EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); EBCASC(info->vm[i].name, sizeof(info->vm[i].name));
EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi)); EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi));
len += sprintf(page + len, "\n"); seq_putc(m, '\n');
len += sprintf(page + len, "VM%02d Name: %-8.8s\n", seq_printf(m, "VM%02d Name: %-8.8s\n", i, info->vm[i].name);
i, info->vm[i].name); seq_printf(m, "VM%02d Control Program: %-16.16s\n", i, info->vm[i].cpi);
len += sprintf(page + len, "VM%02d Control Program: %-16.16s\n", seq_printf(m, "VM%02d Adjustment: %d\n", i, info->vm[i].caf);
i, info->vm[i].cpi); 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);
len += sprintf(page + len, "VM%02d Adjustment: %d\n", seq_printf(m, "VM%02d CPUs Standby: %d\n", i, info->vm[i].cpus_standby);
i, info->vm[i].caf); seq_printf(m, "VM%02d CPUs Reserved: %d\n", i, info->vm[i].cpus_reserved);
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);
} }
return len;
} }
static int proc_read_sysinfo(char *page, char **start, static int sysinfo_show(struct seq_file *m, void *v)
off_t off, int count,
int *eof, void *data)
{ {
unsigned long info = get_zeroed_page(GFP_KERNEL); void *info = (void *)get_zeroed_page(GFP_KERNEL);
int level, len; int level;
if (!info) if (!info)
return 0; return 0;
len = 0;
level = stsi_0(); level = stsi_0();
if (level >= 1) 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) 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) 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) 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) 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);
free_page(info);
return len;
}
static __init int create_proc_sysinfo(void)
{
create_proc_read_entry("sysinfo", 0444, NULL,
proc_read_sysinfo, NULL);
return 0; return 0;
} }
device_initcall(create_proc_sysinfo);
static int sysinfo_open(struct inode *inode, struct file *file)
{
return single_open(file, sysinfo_show, NULL);
}
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)
{
proc_create("sysinfo", 0444, NULL, &sysinfo_fops);
return 0;
}
device_initcall(sysinfo_create_proc);
/* /*
* Service levels interface. * Service levels interface.