aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/sysinfo.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2012-09-03 03:38:30 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-09-26 09:45:07 -0400
commit0facaa170a6a0255092d3b32325a15672465ac4c (patch)
tree4f5220dc76f33fbb315751ab7f4d84dccea2ea40 /arch/s390/kernel/sysinfo.c
parent78609132795b4e3d6d51c6b67d461bf1626afb2f (diff)
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>
Diffstat (limited to 'arch/s390/kernel/sysinfo.c')
-rw-r--r--arch/s390/kernel/sysinfo.c282
1 files changed, 115 insertions, 167 deletions
diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c
index fa0eb238dac7..d3b543c3617a 100644
--- a/arch/s390/kernel/sysinfo.c
+++ b/arch/s390/kernel/sysinfo.c
@@ -25,14 +25,14 @@
25static inline int stsi_0(void) 25static inline int stsi_0(void)
26{ 26{
27 int rc = stsi(NULL, 0, 0, 0); 27 int rc = stsi(NULL, 0, 0, 0);
28
28 return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); 29 return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28);
29} 30}
30 31
31static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) 32static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info)
32{ 33{
33 if (stsi(info, 1, 1, 1) == -ENOSYS) 34 if (stsi(info, 1, 1, 1) == -ENOSYS)
34 return len; 35 return;
35
36 EBCASC(info->manufacturer, sizeof(info->manufacturer)); 36 EBCASC(info->manufacturer, sizeof(info->manufacturer));
37 EBCASC(info->type, sizeof(info->type)); 37 EBCASC(info->type, sizeof(info->type));
38 EBCASC(info->model, sizeof(info->model)); 38 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)
41 EBCASC(info->model_capacity, sizeof(info->model_capacity)); 41 EBCASC(info->model_capacity, sizeof(info->model_capacity));
42 EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap)); 42 EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap));
43 EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap)); 43 EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap));
44 len += sprintf(page + len, "Manufacturer: %-16.16s\n", 44 seq_printf(m, "Manufacturer: %-16.16s\n", info->manufacturer);
45 info->manufacturer); 45 seq_printf(m, "Type: %-4.4s\n", info->type);
46 len += sprintf(page + len, "Type: %-4.4s\n", 46 /*
47 info->type); 47 * Sigh: the model field has been renamed with System z9
48 * to model_capacity and a new model field has been added
49 * after the plant field. To avoid confusing older programs
50 * the "Model:" prints "model_capacity model" or just
51 * "model_capacity" if the model string is empty .
52 */
53 seq_printf(m, "Model: %-16.16s", info->model_capacity);
48 if (info->model[0] != '\0') 54 if (info->model[0] != '\0')
49 /* 55 seq_printf(m, " %-16.16s", info->model);
50 * Sigh: the model field has been renamed with System z9 56 seq_putc(m, '\n');
51 * to model_capacity and a new model field has been added 57 seq_printf(m, "Sequence Code: %-16.16s\n", info->sequence);
52 * after the plant field. To avoid confusing older programs 58 seq_printf(m, "Plant: %-4.4s\n", info->plant);
53 * the "Model:" prints "model_capacity model" or just 59 seq_printf(m, "Model Capacity: %-16.16s %08u\n",
54 * "model_capacity" if the model string is empty . 60 info->model_capacity, *(u32 *) info->model_cap_rating);
55 */
56 len += sprintf(page + len,
57 "Model: %-16.16s %-16.16s\n",
58 info->model_capacity, info->model);
59 else
60 len += sprintf(page + len, "Model: %-16.16s\n",
61 info->model_capacity);
62 len += sprintf(page + len, "Sequence Code: %-16.16s\n",
63 info->sequence);
64 len += sprintf(page + len, "Plant: %-4.4s\n",
65 info->plant);
66 len += sprintf(page + len, "Model Capacity: %-16.16s %08u\n",
67 info->model_capacity, *(u32 *) info->model_cap_rating);
68 if (info->model_perm_cap[0] != '\0') 61 if (info->model_perm_cap[0] != '\0')
69 len += sprintf(page + len, 62 seq_printf(m, "Model Perm. Capacity: %-16.16s %08u\n",
70 "Model Perm. Capacity: %-16.16s %08u\n", 63 info->model_perm_cap,
71 info->model_perm_cap, 64 *(u32 *) info->model_perm_cap_rating);
72 *(u32 *) info->model_perm_cap_rating);
73 if (info->model_temp_cap[0] != '\0') 65 if (info->model_temp_cap[0] != '\0')
74 len += sprintf(page + len, 66 seq_printf(m, "Model Temp. Capacity: %-16.16s %08u\n",
75 "Model Temp. Capacity: %-16.16s %08u\n", 67 info->model_temp_cap,
76 info->model_temp_cap, 68 *(u32 *) info->model_temp_cap_rating);
77 *(u32 *) info->model_temp_cap_rating);
78 if (info->cai) { 69 if (info->cai) {
79 len += sprintf(page + len, 70 seq_printf(m, "Capacity Adj. Ind.: %d\n", info->cai);
80 "Capacity Adj. Ind.: %d\n", 71 seq_printf(m, "Capacity Ch. Reason: %d\n", info->ccr);
81 info->cai);
82 len += sprintf(page + len, "Capacity Ch. Reason: %d\n",
83 info->ccr);
84 } 72 }
85 return len;
86} 73}
87 74
88static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len) 75static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info)
89{ 76{
90 static int max_mnest; 77 static int max_mnest;
91 int i, rc; 78 int i, rc;
92 79
93 len += sprintf(page + len, "\n"); 80 seq_putc(m, '\n');
94 if (!MACHINE_HAS_TOPOLOGY) 81 if (!MACHINE_HAS_TOPOLOGY)
95 return len; 82 return;
96 if (max_mnest) { 83 if (max_mnest) {
97 stsi(info, 15, 1, max_mnest); 84 stsi(info, 15, 1, max_mnest);
98 } else { 85 } else {
@@ -102,181 +89,142 @@ static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len)
102 break; 89 break;
103 } 90 }
104 } 91 }
105 len += sprintf(page + len, "CPU Topology HW: "); 92 seq_printf(m, "CPU Topology HW: ");
106 for (i = 0; i < TOPOLOGY_NR_MAG; i++) 93 for (i = 0; i < TOPOLOGY_NR_MAG; i++)
107 len += sprintf(page + len, " %d", info->mag[i]); 94 seq_printf(m, " %d", info->mag[i]);
108 len += sprintf(page + len, "\n"); 95 seq_putc(m, '\n');
109#ifdef CONFIG_SCHED_MC 96#ifdef CONFIG_SCHED_MC
110 store_topology(info); 97 store_topology(info);
111 len += sprintf(page + len, "CPU Topology SW: "); 98 seq_printf(m, "CPU Topology SW: ");
112 for (i = 0; i < TOPOLOGY_NR_MAG; i++) 99 for (i = 0; i < TOPOLOGY_NR_MAG; i++)
113 len += sprintf(page + len, " %d", info->mag[i]); 100 seq_printf(m, " %d", info->mag[i]);
114 len += sprintf(page + len, "\n"); 101 seq_putc(m, '\n');
115#endif 102#endif
116 return len;
117} 103}
118 104
119static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) 105static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info)
120{ 106{
121 struct sysinfo_1_2_2_extension *ext; 107 struct sysinfo_1_2_2_extension *ext;
122 int i; 108 int i;
123 109
124 if (stsi(info, 1, 2, 2) == -ENOSYS) 110 if (stsi(info, 1, 2, 2) == -ENOSYS)
125 return len; 111 return;
126 ext = (struct sysinfo_1_2_2_extension *) 112 ext = (struct sysinfo_1_2_2_extension *)
127 ((unsigned long) info + info->acc_offset); 113 ((unsigned long) info + info->acc_offset);
128 114 seq_printf(m, "CPUs Total: %d\n", info->cpus_total);
129 len += sprintf(page + len, "CPUs Total: %d\n", 115 seq_printf(m, "CPUs Configured: %d\n", info->cpus_configured);
130 info->cpus_total); 116 seq_printf(m, "CPUs Standby: %d\n", info->cpus_standby);
131 len += sprintf(page + len, "CPUs Configured: %d\n", 117 seq_printf(m, "CPUs Reserved: %d\n", info->cpus_reserved);
132 info->cpus_configured); 118 /*
133 len += sprintf(page + len, "CPUs Standby: %d\n", 119 * Sigh 2. According to the specification the alternate
134 info->cpus_standby); 120 * capability field is a 32 bit floating point number
135 len += sprintf(page + len, "CPUs Reserved: %d\n", 121 * if the higher order 8 bits are not zero. Printing
136 info->cpus_reserved); 122 * a floating point number in the kernel is a no-no,
137 123 * always print the number as 32 bit unsigned integer.
138 if (info->format == 1) { 124 * The user-space needs to know about the strange
139 /* 125 * encoding of the alternate cpu capability.
140 * Sigh 2. According to the specification the alternate 126 */
141 * capability field is a 32 bit floating point number 127 seq_printf(m, "Capability: %u", info->capability);
142 * if the higher order 8 bits are not zero. Printing 128 if (info->format == 1)
143 * a floating point number in the kernel is a no-no, 129 seq_printf(m, " %u", ext->alt_capability);
144 * always print the number as 32 bit unsigned integer. 130 seq_putc(m, '\n');
145 * The user-space needs to know about the strange 131 for (i = 2; i <= info->cpus_total; i++) {
146 * encoding of the alternate cpu capability. 132 seq_printf(m, "Adjustment %02d-way: %u",
147 */ 133 i, info->adjustment[i-2]);
148 len += sprintf(page + len, "Capability: %u %u\n", 134 if (info->format == 1)
149 info->capability, ext->alt_capability); 135 seq_printf(m, " %u", ext->alt_adjustment[i-2]);
150 for (i = 2; i <= info->cpus_total; i++) 136 seq_putc(m, '\n');
151 len += sprintf(page + len,
152 "Adjustment %02d-way: %u %u\n",
153 i, info->adjustment[i-2],
154 ext->alt_adjustment[i-2]);
155
156 } else {
157 len += sprintf(page + len, "Capability: %u\n",
158 info->capability);
159 for (i = 2; i <= info->cpus_total; i++)
160 len += sprintf(page + len,
161 "Adjustment %02d-way: %u\n",
162 i, info->adjustment[i-2]);
163 } 137 }
164 138 if (info->secondary_capability)
165 if (info->secondary_capability != 0) 139 seq_printf(m, "Secondary Capability: %d\n",
166 len += sprintf(page + len, "Secondary Capability: %d\n", 140 info->secondary_capability);
167 info->secondary_capability);
168 return len;
169} 141}
170 142
171static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len) 143static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info)
172{ 144{
173 if (stsi(info, 2, 2, 2) == -ENOSYS) 145 if (stsi(info, 2, 2, 2) == -ENOSYS)
174 return len; 146 return;
175
176 EBCASC(info->name, sizeof(info->name)); 147 EBCASC(info->name, sizeof(info->name));
177 148 seq_putc(m, '\n');
178 len += sprintf(page + len, "\n"); 149 seq_printf(m, "LPAR Number: %d\n", info->lpar_number);
179 len += sprintf(page + len, "LPAR Number: %d\n", 150 seq_printf(m, "LPAR Characteristics: ");
180 info->lpar_number);
181
182 len += sprintf(page + len, "LPAR Characteristics: ");
183 if (info->characteristics & LPAR_CHAR_DEDICATED) 151 if (info->characteristics & LPAR_CHAR_DEDICATED)
184 len += sprintf(page + len, "Dedicated "); 152 seq_printf(m, "Dedicated ");
185 if (info->characteristics & LPAR_CHAR_SHARED) 153 if (info->characteristics & LPAR_CHAR_SHARED)
186 len += sprintf(page + len, "Shared "); 154 seq_printf(m, "Shared ");
187 if (info->characteristics & LPAR_CHAR_LIMITED) 155 if (info->characteristics & LPAR_CHAR_LIMITED)
188 len += sprintf(page + len, "Limited "); 156 seq_printf(m, "Limited ");
189 len += sprintf(page + len, "\n"); 157 seq_putc(m, '\n');
190 158 seq_printf(m, "LPAR Name: %-8.8s\n", info->name);
191 len += sprintf(page + len, "LPAR Name: %-8.8s\n", 159 seq_printf(m, "LPAR Adjustment: %d\n", info->caf);
192 info->name); 160 seq_printf(m, "LPAR CPUs Total: %d\n", info->cpus_total);
193 161 seq_printf(m, "LPAR CPUs Configured: %d\n", info->cpus_configured);
194 len += sprintf(page + len, "LPAR Adjustment: %d\n", 162 seq_printf(m, "LPAR CPUs Standby: %d\n", info->cpus_standby);
195 info->caf); 163 seq_printf(m, "LPAR CPUs Reserved: %d\n", info->cpus_reserved);
196 164 seq_printf(m, "LPAR CPUs Dedicated: %d\n", info->cpus_dedicated);
197 len += sprintf(page + len, "LPAR CPUs Total: %d\n", 165 seq_printf(m, "LPAR CPUs Shared: %d\n", info->cpus_shared);
198 info->cpus_total);
199 len += sprintf(page + len, "LPAR CPUs Configured: %d\n",
200 info->cpus_configured);
201 len += sprintf(page + len, "LPAR CPUs Standby: %d\n",
202 info->cpus_standby);
203 len += sprintf(page + len, "LPAR CPUs Reserved: %d\n",
204 info->cpus_reserved);
205 len += sprintf(page + len, "LPAR CPUs Dedicated: %d\n",
206 info->cpus_dedicated);
207 len += sprintf(page + len, "LPAR CPUs Shared: %d\n",
208 info->cpus_shared);
209 return len;
210} 166}
211 167
212static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len) 168static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info)
213{ 169{
214 int i; 170 int i;
215 171
216 if (stsi(info, 3, 2, 2) == -ENOSYS) 172 if (stsi(info, 3, 2, 2) == -ENOSYS)
217 return len; 173 return;
218 for (i = 0; i < info->count; i++) { 174 for (i = 0; i < info->count; i++) {
219 EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); 175 EBCASC(info->vm[i].name, sizeof(info->vm[i].name));
220 EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi)); 176 EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi));
221 len += sprintf(page + len, "\n"); 177 seq_putc(m, '\n');
222 len += sprintf(page + len, "VM%02d Name: %-8.8s\n", 178 seq_printf(m, "VM%02d Name: %-8.8s\n", i, info->vm[i].name);
223 i, info->vm[i].name); 179 seq_printf(m, "VM%02d Control Program: %-16.16s\n", i, info->vm[i].cpi);
224 len += sprintf(page + len, "VM%02d Control Program: %-16.16s\n", 180 seq_printf(m, "VM%02d Adjustment: %d\n", i, info->vm[i].caf);
225 i, info->vm[i].cpi); 181 seq_printf(m, "VM%02d CPUs Total: %d\n", i, info->vm[i].cpus_total);
226 182 seq_printf(m, "VM%02d CPUs Configured: %d\n", i, info->vm[i].cpus_configured);
227 len += sprintf(page + len, "VM%02d Adjustment: %d\n", 183 seq_printf(m, "VM%02d CPUs Standby: %d\n", i, info->vm[i].cpus_standby);
228 i, info->vm[i].caf); 184 seq_printf(m, "VM%02d CPUs Reserved: %d\n", i, info->vm[i].cpus_reserved);
229
230 len += sprintf(page + len, "VM%02d CPUs Total: %d\n",
231 i, info->vm[i].cpus_total);
232 len += sprintf(page + len, "VM%02d CPUs Configured: %d\n",
233 i, info->vm[i].cpus_configured);
234 len += sprintf(page + len, "VM%02d CPUs Standby: %d\n",
235 i, info->vm[i].cpus_standby);
236 len += sprintf(page + len, "VM%02d CPUs Reserved: %d\n",
237 i, info->vm[i].cpus_reserved);
238 } 185 }
239 return len;
240} 186}
241 187
242static int proc_read_sysinfo(char *page, char **start, 188static int sysinfo_show(struct seq_file *m, void *v)
243 off_t off, int count,
244 int *eof, void *data)
245{ 189{
246 unsigned long info = get_zeroed_page(GFP_KERNEL); 190 void *info = (void *)get_zeroed_page(GFP_KERNEL);
247 int level, len; 191 int level;
248 192
249 if (!info) 193 if (!info)
250 return 0; 194 return 0;
251
252 len = 0;
253 level = stsi_0(); 195 level = stsi_0();
254 if (level >= 1) 196 if (level >= 1)
255 len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len); 197 stsi_1_1_1(m, info);
256
257 if (level >= 1) 198 if (level >= 1)
258 len = stsi_15_1_x((struct sysinfo_15_1_x *) info, page, len); 199 stsi_15_1_x(m, info);
259
260 if (level >= 1) 200 if (level >= 1)
261 len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len); 201 stsi_1_2_2(m, info);
262
263 if (level >= 2) 202 if (level >= 2)
264 len = stsi_2_2_2((struct sysinfo_2_2_2 *) info, page, len); 203 stsi_2_2_2(m, info);
265
266 if (level >= 3) 204 if (level >= 3)
267 len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len); 205 stsi_3_2_2(m, info);
206 free_page((unsigned long)info);
207 return 0;
208}
268 209
269 free_page(info); 210static int sysinfo_open(struct inode *inode, struct file *file)
270 return len; 211{
212 return single_open(file, sysinfo_show, NULL);
271} 213}
272 214
273static __init int create_proc_sysinfo(void) 215static const struct file_operations sysinfo_fops = {
216 .open = sysinfo_open,
217 .read = seq_read,
218 .llseek = seq_lseek,
219 .release = single_release,
220};
221
222static int __init sysinfo_create_proc(void)
274{ 223{
275 create_proc_read_entry("sysinfo", 0444, NULL, 224 proc_create("sysinfo", 0444, NULL, &sysinfo_fops);
276 proc_read_sysinfo, NULL);
277 return 0; 225 return 0;
278} 226}
279device_initcall(create_proc_sysinfo); 227device_initcall(sysinfo_create_proc);
280 228
281/* 229/*
282 * Service levels interface. 230 * Service levels interface.