Commit | Line | Data |
---|---|---|
d7e09d03 PT |
1 | /* |
2 | * GPL HEADER START | |
3 | * | |
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 only, | |
8 | * as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License version 2 for more details (a copy is included | |
14 | * in the LICENSE file that accompanied this code). | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * version 2 along with this program; If not, see | |
18 | * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf | |
19 | * | |
20 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
21 | * CA 95054 USA or visit www.sun.com if you need additional information or | |
22 | * have any questions. | |
23 | * | |
24 | * GPL HEADER END | |
25 | */ | |
26 | /* | |
27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | |
28 | * Use is subject to license terms. | |
29 | * | |
30 | * Copyright (c) 2011, 2012, Intel Corporation. | |
31 | */ | |
32 | /* | |
33 | * This file is part of Lustre, http://www.lustre.org/ | |
34 | * Lustre is a trademark of Sun Microsystems, Inc. | |
35 | */ | |
36 | #define DEBUG_SUBSYSTEM S_CLASS | |
37 | ||
38 | #include <linux/version.h> | |
39 | #include <asm/statfs.h> | |
40 | #include <obd_cksum.h> | |
41 | #include <obd_class.h> | |
42 | #include <lprocfs_status.h> | |
43 | #include <linux/seq_file.h> | |
44 | #include "osc_internal.h" | |
45 | ||
46 | #ifdef LPROCFS | |
73bb1da6 | 47 | static int osc_active_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 48 | { |
73bb1da6 | 49 | struct obd_device *dev = m->private; |
d7e09d03 PT |
50 | int rc; |
51 | ||
52 | LPROCFS_CLIMP_CHECK(dev); | |
73bb1da6 | 53 | rc = seq_printf(m, "%d\n", !dev->u.cli.cl_import->imp_deactive); |
d7e09d03 PT |
54 | LPROCFS_CLIMP_EXIT(dev); |
55 | return rc; | |
56 | } | |
57 | ||
73bb1da6 PT |
58 | static ssize_t osc_active_seq_write(struct file *file, const char *buffer, |
59 | size_t count, loff_t *off) | |
d7e09d03 | 60 | { |
73bb1da6 | 61 | struct obd_device *dev = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
62 | int val, rc; |
63 | ||
64 | rc = lprocfs_write_helper(buffer, count, &val); | |
65 | if (rc) | |
66 | return rc; | |
67 | if (val < 0 || val > 1) | |
68 | return -ERANGE; | |
69 | ||
70 | /* opposite senses */ | |
71 | if (dev->u.cli.cl_import->imp_deactive == val) | |
72 | rc = ptlrpc_set_import_active(dev->u.cli.cl_import, val); | |
73 | else | |
74 | CDEBUG(D_CONFIG, "activate %d: ignoring repeat request\n", val); | |
75 | ||
76 | return count; | |
77 | } | |
73bb1da6 | 78 | LPROC_SEQ_FOPS(osc_active); |
d7e09d03 | 79 | |
73bb1da6 | 80 | static int osc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 81 | { |
73bb1da6 | 82 | struct obd_device *dev = m->private; |
d7e09d03 PT |
83 | struct client_obd *cli = &dev->u.cli; |
84 | int rc; | |
85 | ||
86 | client_obd_list_lock(&cli->cl_loi_list_lock); | |
73bb1da6 | 87 | rc = seq_printf(m, "%u\n", cli->cl_max_rpcs_in_flight); |
d7e09d03 PT |
88 | client_obd_list_unlock(&cli->cl_loi_list_lock); |
89 | return rc; | |
90 | } | |
91 | ||
73bb1da6 PT |
92 | static ssize_t osc_max_rpcs_in_flight_seq_write(struct file *file, |
93 | const char *buffer, size_t count, loff_t *off) | |
d7e09d03 | 94 | { |
73bb1da6 | 95 | struct obd_device *dev = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
96 | struct client_obd *cli = &dev->u.cli; |
97 | struct ptlrpc_request_pool *pool = cli->cl_import->imp_rq_pool; | |
98 | int val, rc; | |
99 | ||
100 | rc = lprocfs_write_helper(buffer, count, &val); | |
101 | if (rc) | |
102 | return rc; | |
103 | ||
104 | if (val < 1 || val > OSC_MAX_RIF_MAX) | |
105 | return -ERANGE; | |
106 | ||
107 | LPROCFS_CLIMP_CHECK(dev); | |
108 | if (pool && val > cli->cl_max_rpcs_in_flight) | |
109 | pool->prp_populate(pool, val-cli->cl_max_rpcs_in_flight); | |
110 | ||
111 | client_obd_list_lock(&cli->cl_loi_list_lock); | |
112 | cli->cl_max_rpcs_in_flight = val; | |
113 | client_obd_list_unlock(&cli->cl_loi_list_lock); | |
114 | ||
115 | LPROCFS_CLIMP_EXIT(dev); | |
116 | return count; | |
117 | } | |
73bb1da6 | 118 | LPROC_SEQ_FOPS(osc_max_rpcs_in_flight); |
d7e09d03 | 119 | |
73bb1da6 | 120 | static int osc_max_dirty_mb_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 121 | { |
73bb1da6 | 122 | struct obd_device *dev = m->private; |
d7e09d03 PT |
123 | struct client_obd *cli = &dev->u.cli; |
124 | long val; | |
125 | int mult; | |
126 | ||
127 | client_obd_list_lock(&cli->cl_loi_list_lock); | |
128 | val = cli->cl_dirty_max; | |
129 | client_obd_list_unlock(&cli->cl_loi_list_lock); | |
130 | ||
131 | mult = 1 << 20; | |
73bb1da6 | 132 | return lprocfs_seq_read_frac_helper(m, val, mult); |
d7e09d03 PT |
133 | } |
134 | ||
73bb1da6 PT |
135 | static ssize_t osc_max_dirty_mb_seq_write(struct file *file, const char *buffer, |
136 | size_t count, loff_t *off) | |
d7e09d03 | 137 | { |
73bb1da6 | 138 | struct obd_device *dev = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
139 | struct client_obd *cli = &dev->u.cli; |
140 | int pages_number, mult, rc; | |
141 | ||
142 | mult = 1 << (20 - PAGE_CACHE_SHIFT); | |
143 | rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult); | |
144 | if (rc) | |
145 | return rc; | |
146 | ||
147 | if (pages_number <= 0 || | |
148 | pages_number > OSC_MAX_DIRTY_MB_MAX << (20 - PAGE_CACHE_SHIFT) || | |
149 | pages_number > num_physpages / 4) /* 1/4 of RAM */ | |
150 | return -ERANGE; | |
151 | ||
152 | client_obd_list_lock(&cli->cl_loi_list_lock); | |
153 | cli->cl_dirty_max = (obd_count)(pages_number << PAGE_CACHE_SHIFT); | |
154 | osc_wake_cache_waiters(cli); | |
155 | client_obd_list_unlock(&cli->cl_loi_list_lock); | |
156 | ||
157 | return count; | |
158 | } | |
73bb1da6 | 159 | LPROC_SEQ_FOPS(osc_max_dirty_mb); |
d7e09d03 | 160 | |
73bb1da6 | 161 | static int osc_cached_mb_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 162 | { |
73bb1da6 | 163 | struct obd_device *dev = m->private; |
d7e09d03 PT |
164 | struct client_obd *cli = &dev->u.cli; |
165 | int shift = 20 - PAGE_CACHE_SHIFT; | |
166 | int rc; | |
167 | ||
73bb1da6 | 168 | rc = seq_printf(m, |
d7e09d03 PT |
169 | "used_mb: %d\n" |
170 | "busy_cnt: %d\n", | |
171 | (atomic_read(&cli->cl_lru_in_list) + | |
172 | atomic_read(&cli->cl_lru_busy)) >> shift, | |
173 | atomic_read(&cli->cl_lru_busy)); | |
174 | ||
175 | return rc; | |
176 | } | |
177 | ||
178 | /* shrink the number of caching pages to a specific number */ | |
73bb1da6 PT |
179 | static ssize_t osc_cached_mb_seq_write(struct file *file, const char *buffer, |
180 | size_t count, loff_t *off) | |
d7e09d03 | 181 | { |
73bb1da6 | 182 | struct obd_device *dev = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
183 | struct client_obd *cli = &dev->u.cli; |
184 | int pages_number, mult, rc; | |
185 | ||
186 | mult = 1 << (20 - PAGE_CACHE_SHIFT); | |
187 | buffer = lprocfs_find_named_value(buffer, "used_mb:", &count); | |
188 | rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult); | |
189 | if (rc) | |
190 | return rc; | |
191 | ||
192 | if (pages_number < 0) | |
193 | return -ERANGE; | |
194 | ||
195 | rc = atomic_read(&cli->cl_lru_in_list) - pages_number; | |
196 | if (rc > 0) | |
197 | (void)osc_lru_shrink(cli, rc); | |
198 | ||
199 | return count; | |
200 | } | |
73bb1da6 | 201 | LPROC_SEQ_FOPS(osc_cached_mb); |
d7e09d03 | 202 | |
73bb1da6 | 203 | static int osc_cur_dirty_bytes_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 204 | { |
73bb1da6 | 205 | struct obd_device *dev = m->private; |
d7e09d03 PT |
206 | struct client_obd *cli = &dev->u.cli; |
207 | int rc; | |
208 | ||
209 | client_obd_list_lock(&cli->cl_loi_list_lock); | |
73bb1da6 | 210 | rc = seq_printf(m, "%lu\n", cli->cl_dirty); |
d7e09d03 PT |
211 | client_obd_list_unlock(&cli->cl_loi_list_lock); |
212 | return rc; | |
213 | } | |
73bb1da6 | 214 | LPROC_SEQ_FOPS_RO(osc_cur_dirty_bytes); |
d7e09d03 | 215 | |
73bb1da6 | 216 | static int osc_cur_grant_bytes_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 217 | { |
73bb1da6 | 218 | struct obd_device *dev = m->private; |
d7e09d03 PT |
219 | struct client_obd *cli = &dev->u.cli; |
220 | int rc; | |
221 | ||
222 | client_obd_list_lock(&cli->cl_loi_list_lock); | |
73bb1da6 | 223 | rc = seq_printf(m, "%lu\n", cli->cl_avail_grant); |
d7e09d03 PT |
224 | client_obd_list_unlock(&cli->cl_loi_list_lock); |
225 | return rc; | |
226 | } | |
227 | ||
73bb1da6 PT |
228 | static ssize_t osc_cur_grant_bytes_seq_write(struct file *file, const char *buffer, |
229 | size_t count, loff_t *off) | |
d7e09d03 | 230 | { |
73bb1da6 | 231 | struct obd_device *obd = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
232 | struct client_obd *cli = &obd->u.cli; |
233 | int rc; | |
234 | __u64 val; | |
235 | ||
236 | if (obd == NULL) | |
237 | return 0; | |
238 | ||
239 | rc = lprocfs_write_u64_helper(buffer, count, &val); | |
240 | if (rc) | |
241 | return rc; | |
242 | ||
243 | /* this is only for shrinking grant */ | |
244 | client_obd_list_lock(&cli->cl_loi_list_lock); | |
245 | if (val >= cli->cl_avail_grant) { | |
246 | client_obd_list_unlock(&cli->cl_loi_list_lock); | |
247 | return 0; | |
248 | } | |
249 | client_obd_list_unlock(&cli->cl_loi_list_lock); | |
250 | ||
251 | LPROCFS_CLIMP_CHECK(obd); | |
252 | if (cli->cl_import->imp_state == LUSTRE_IMP_FULL) | |
253 | rc = osc_shrink_grant_to_target(cli, val); | |
254 | LPROCFS_CLIMP_EXIT(obd); | |
255 | if (rc) | |
256 | return rc; | |
257 | return count; | |
258 | } | |
73bb1da6 | 259 | LPROC_SEQ_FOPS(osc_cur_grant_bytes); |
d7e09d03 | 260 | |
73bb1da6 | 261 | static int osc_cur_lost_grant_bytes_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 262 | { |
73bb1da6 | 263 | struct obd_device *dev = m->private; |
d7e09d03 PT |
264 | struct client_obd *cli = &dev->u.cli; |
265 | int rc; | |
266 | ||
267 | client_obd_list_lock(&cli->cl_loi_list_lock); | |
73bb1da6 | 268 | rc = seq_printf(m, "%lu\n", cli->cl_lost_grant); |
d7e09d03 PT |
269 | client_obd_list_unlock(&cli->cl_loi_list_lock); |
270 | return rc; | |
271 | } | |
73bb1da6 | 272 | LPROC_SEQ_FOPS_RO(osc_cur_lost_grant_bytes); |
d7e09d03 | 273 | |
73bb1da6 | 274 | static int osc_grant_shrink_interval_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 275 | { |
73bb1da6 | 276 | struct obd_device *obd = m->private; |
d7e09d03 PT |
277 | |
278 | if (obd == NULL) | |
279 | return 0; | |
73bb1da6 | 280 | return seq_printf(m, "%d\n", |
d7e09d03 PT |
281 | obd->u.cli.cl_grant_shrink_interval); |
282 | } | |
283 | ||
73bb1da6 PT |
284 | static ssize_t osc_grant_shrink_interval_seq_write(struct file *file, |
285 | const char *buffer, size_t count, loff_t *off) | |
d7e09d03 | 286 | { |
73bb1da6 | 287 | struct obd_device *obd = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
288 | int val, rc; |
289 | ||
290 | if (obd == NULL) | |
291 | return 0; | |
292 | ||
293 | rc = lprocfs_write_helper(buffer, count, &val); | |
294 | if (rc) | |
295 | return rc; | |
296 | ||
297 | if (val <= 0) | |
298 | return -ERANGE; | |
299 | ||
300 | obd->u.cli.cl_grant_shrink_interval = val; | |
301 | ||
302 | return count; | |
303 | } | |
73bb1da6 | 304 | LPROC_SEQ_FOPS(osc_grant_shrink_interval); |
d7e09d03 | 305 | |
73bb1da6 | 306 | static int osc_checksum_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 307 | { |
73bb1da6 | 308 | struct obd_device *obd = m->private; |
d7e09d03 PT |
309 | |
310 | if (obd == NULL) | |
311 | return 0; | |
312 | ||
73bb1da6 | 313 | return seq_printf(m, "%d\n", |
d7e09d03 PT |
314 | obd->u.cli.cl_checksum ? 1 : 0); |
315 | } | |
316 | ||
73bb1da6 PT |
317 | static ssize_t osc_checksum_seq_write(struct file *file, const char *buffer, |
318 | size_t count, loff_t *off) | |
d7e09d03 | 319 | { |
73bb1da6 | 320 | struct obd_device *obd = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
321 | int val, rc; |
322 | ||
323 | if (obd == NULL) | |
324 | return 0; | |
325 | ||
326 | rc = lprocfs_write_helper(buffer, count, &val); | |
327 | if (rc) | |
328 | return rc; | |
329 | ||
330 | obd->u.cli.cl_checksum = (val ? 1 : 0); | |
331 | ||
332 | return count; | |
333 | } | |
73bb1da6 | 334 | LPROC_SEQ_FOPS(osc_checksum); |
d7e09d03 | 335 | |
73bb1da6 | 336 | static int osc_checksum_type_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 337 | { |
73bb1da6 PT |
338 | struct obd_device *obd = m->private; |
339 | int i; | |
d7e09d03 PT |
340 | DECLARE_CKSUM_NAME; |
341 | ||
342 | if (obd == NULL) | |
343 | return 0; | |
344 | ||
73bb1da6 | 345 | for (i = 0; i < ARRAY_SIZE(cksum_name); i++) { |
d7e09d03 PT |
346 | if (((1 << i) & obd->u.cli.cl_supp_cksum_types) == 0) |
347 | continue; | |
348 | if (obd->u.cli.cl_cksum_type == (1 << i)) | |
73bb1da6 | 349 | seq_printf(m, "[%s] ", cksum_name[i]); |
d7e09d03 | 350 | else |
73bb1da6 | 351 | seq_printf(m, "%s ", cksum_name[i]); |
d7e09d03 | 352 | } |
73bb1da6 PT |
353 | seq_printf(m, "\n"); |
354 | return 0; | |
d7e09d03 PT |
355 | } |
356 | ||
73bb1da6 PT |
357 | static ssize_t osc_checksum_type_seq_write(struct file *file, const char *buffer, |
358 | size_t count, loff_t *off) | |
d7e09d03 | 359 | { |
73bb1da6 | 360 | struct obd_device *obd = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
361 | int i; |
362 | DECLARE_CKSUM_NAME; | |
363 | char kernbuf[10]; | |
364 | ||
365 | if (obd == NULL) | |
366 | return 0; | |
367 | ||
368 | if (count > sizeof(kernbuf) - 1) | |
369 | return -EINVAL; | |
370 | if (copy_from_user(kernbuf, buffer, count)) | |
371 | return -EFAULT; | |
372 | if (count > 0 && kernbuf[count - 1] == '\n') | |
373 | kernbuf[count - 1] = '\0'; | |
374 | else | |
375 | kernbuf[count] = '\0'; | |
376 | ||
377 | for (i = 0; i < ARRAY_SIZE(cksum_name); i++) { | |
378 | if (((1 << i) & obd->u.cli.cl_supp_cksum_types) == 0) | |
379 | continue; | |
380 | if (!strcmp(kernbuf, cksum_name[i])) { | |
381 | obd->u.cli.cl_cksum_type = 1 << i; | |
382 | return count; | |
383 | } | |
384 | } | |
385 | return -EINVAL; | |
386 | } | |
73bb1da6 | 387 | LPROC_SEQ_FOPS(osc_checksum_type); |
d7e09d03 | 388 | |
73bb1da6 | 389 | static int osc_resend_count_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 390 | { |
73bb1da6 | 391 | struct obd_device *obd = m->private; |
d7e09d03 | 392 | |
73bb1da6 | 393 | return seq_printf(m, "%u\n", atomic_read(&obd->u.cli.cl_resends)); |
d7e09d03 PT |
394 | } |
395 | ||
73bb1da6 PT |
396 | static ssize_t osc_resend_count_seq_write(struct file *file, const char *buffer, |
397 | size_t count, loff_t *off) | |
d7e09d03 | 398 | { |
73bb1da6 | 399 | struct obd_device *obd = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
400 | int val, rc; |
401 | ||
402 | rc = lprocfs_write_helper(buffer, count, &val); | |
403 | if (rc) | |
404 | return rc; | |
405 | ||
406 | if (val < 0) | |
407 | return -EINVAL; | |
408 | ||
409 | atomic_set(&obd->u.cli.cl_resends, val); | |
410 | ||
411 | return count; | |
412 | } | |
73bb1da6 | 413 | LPROC_SEQ_FOPS(osc_resend_count); |
d7e09d03 | 414 | |
73bb1da6 | 415 | static int osc_contention_seconds_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 416 | { |
73bb1da6 | 417 | struct obd_device *obd = m->private; |
d7e09d03 PT |
418 | struct osc_device *od = obd2osc_dev(obd); |
419 | ||
73bb1da6 | 420 | return seq_printf(m, "%u\n", od->od_contention_time); |
d7e09d03 PT |
421 | } |
422 | ||
73bb1da6 PT |
423 | static ssize_t osc_contention_seconds_seq_write(struct file *file, const char *buffer, |
424 | size_t count, loff_t *off) | |
d7e09d03 | 425 | { |
73bb1da6 | 426 | struct obd_device *obd = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
427 | struct osc_device *od = obd2osc_dev(obd); |
428 | ||
429 | return lprocfs_write_helper(buffer, count, &od->od_contention_time) ?: | |
430 | count; | |
431 | } | |
73bb1da6 | 432 | LPROC_SEQ_FOPS(osc_contention_seconds); |
d7e09d03 | 433 | |
73bb1da6 | 434 | static int osc_lockless_truncate_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 435 | { |
73bb1da6 | 436 | struct obd_device *obd = m->private; |
d7e09d03 PT |
437 | struct osc_device *od = obd2osc_dev(obd); |
438 | ||
73bb1da6 | 439 | return seq_printf(m, "%u\n", od->od_lockless_truncate); |
d7e09d03 PT |
440 | } |
441 | ||
73bb1da6 PT |
442 | static ssize_t osc_lockless_truncate_seq_write(struct file *file, const char *buffer, |
443 | size_t count, loff_t *off) | |
d7e09d03 | 444 | { |
73bb1da6 | 445 | struct obd_device *obd = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
446 | struct osc_device *od = obd2osc_dev(obd); |
447 | ||
448 | return lprocfs_write_helper(buffer, count, &od->od_lockless_truncate) ?: | |
449 | count; | |
450 | } | |
73bb1da6 | 451 | LPROC_SEQ_FOPS(osc_lockless_truncate); |
d7e09d03 | 452 | |
73bb1da6 | 453 | static int osc_destroys_in_flight_seq_show(struct seq_file *m, void *v) |
d7e09d03 | 454 | { |
73bb1da6 PT |
455 | struct obd_device *obd = m->private; |
456 | return seq_printf(m, "%u\n", | |
d7e09d03 PT |
457 | atomic_read(&obd->u.cli.cl_destroy_in_flight)); |
458 | } | |
73bb1da6 PT |
459 | LPROC_SEQ_FOPS_RO(osc_destroys_in_flight); |
460 | ||
461 | static int osc_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *v) | |
462 | { | |
463 | return lprocfs_obd_rd_max_pages_per_rpc(m, m->private); | |
464 | } | |
d7e09d03 | 465 | |
73bb1da6 PT |
466 | static ssize_t osc_obd_max_pages_per_rpc_seq_write(struct file *file, |
467 | const char *buffer, size_t count, loff_t *off) | |
d7e09d03 | 468 | { |
73bb1da6 | 469 | struct obd_device *dev = ((struct seq_file *)file->private_data)->private; |
d7e09d03 PT |
470 | struct client_obd *cli = &dev->u.cli; |
471 | struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data; | |
472 | int chunk_mask, rc; | |
473 | __u64 val; | |
474 | ||
475 | rc = lprocfs_write_u64_helper(buffer, count, &val); | |
476 | if (rc) | |
477 | return rc; | |
478 | ||
479 | /* if the max_pages is specified in bytes, convert to pages */ | |
480 | if (val >= ONE_MB_BRW_SIZE) | |
481 | val >>= PAGE_CACHE_SHIFT; | |
482 | ||
483 | LPROCFS_CLIMP_CHECK(dev); | |
484 | ||
485 | chunk_mask = ~((1 << (cli->cl_chunkbits - PAGE_CACHE_SHIFT)) - 1); | |
486 | /* max_pages_per_rpc must be chunk aligned */ | |
487 | val = (val + ~chunk_mask) & chunk_mask; | |
488 | if (val == 0 || val > ocd->ocd_brw_size >> PAGE_CACHE_SHIFT) { | |
489 | LPROCFS_CLIMP_EXIT(dev); | |
490 | return -ERANGE; | |
491 | } | |
492 | client_obd_list_lock(&cli->cl_loi_list_lock); | |
493 | cli->cl_max_pages_per_rpc = val; | |
494 | client_obd_list_unlock(&cli->cl_loi_list_lock); | |
495 | ||
496 | LPROCFS_CLIMP_EXIT(dev); | |
497 | return count; | |
498 | } | |
73bb1da6 PT |
499 | LPROC_SEQ_FOPS(osc_obd_max_pages_per_rpc); |
500 | ||
501 | LPROC_SEQ_FOPS_RO_TYPE(osc, uuid); | |
502 | LPROC_SEQ_FOPS_RO_TYPE(osc, connect_flags); | |
503 | LPROC_SEQ_FOPS_RO_TYPE(osc, blksize); | |
504 | LPROC_SEQ_FOPS_RO_TYPE(osc, kbytestotal); | |
505 | LPROC_SEQ_FOPS_RO_TYPE(osc, kbytesfree); | |
506 | LPROC_SEQ_FOPS_RO_TYPE(osc, kbytesavail); | |
507 | LPROC_SEQ_FOPS_RO_TYPE(osc, filestotal); | |
508 | LPROC_SEQ_FOPS_RO_TYPE(osc, filesfree); | |
509 | LPROC_SEQ_FOPS_RO_TYPE(osc, server_uuid); | |
510 | LPROC_SEQ_FOPS_RO_TYPE(osc, conn_uuid); | |
511 | LPROC_SEQ_FOPS_RO_TYPE(osc, timeouts); | |
512 | LPROC_SEQ_FOPS_RO_TYPE(osc, state); | |
513 | ||
514 | LPROC_SEQ_FOPS_WR_ONLY(osc, ping); | |
515 | ||
516 | LPROC_SEQ_FOPS_RW_TYPE(osc, import); | |
517 | LPROC_SEQ_FOPS_RW_TYPE(osc, pinger_recov); | |
d7e09d03 PT |
518 | |
519 | static struct lprocfs_vars lprocfs_osc_obd_vars[] = { | |
73bb1da6 PT |
520 | { "uuid", &osc_uuid_fops, 0, 0 }, |
521 | { "ping", &osc_ping_fops, 0, 0222 }, | |
522 | { "connect_flags", &osc_connect_flags_fops, 0, 0 }, | |
523 | { "blocksize", &osc_blksize_fops, 0, 0 }, | |
524 | { "kbytestotal", &osc_kbytestotal_fops, 0, 0 }, | |
525 | { "kbytesfree", &osc_kbytesfree_fops, 0, 0 }, | |
526 | { "kbytesavail", &osc_kbytesavail_fops, 0, 0 }, | |
527 | { "filestotal", &osc_filestotal_fops, 0, 0 }, | |
528 | { "filesfree", &osc_filesfree_fops, 0, 0 }, | |
d7e09d03 | 529 | //{ "filegroups", lprocfs_rd_filegroups, 0, 0 }, |
73bb1da6 PT |
530 | { "ost_server_uuid", &osc_server_uuid_fops, 0, 0 }, |
531 | { "ost_conn_uuid", &osc_conn_uuid_fops, 0, 0 }, | |
532 | { "active", &osc_active_fops, 0 }, | |
533 | { "max_pages_per_rpc", &osc_obd_max_pages_per_rpc_fops, 0 }, | |
534 | { "max_rpcs_in_flight", &osc_max_rpcs_in_flight_fops, 0 }, | |
535 | { "destroys_in_flight", &osc_destroys_in_flight_fops, 0, 0 }, | |
536 | { "max_dirty_mb", &osc_max_dirty_mb_fops, 0 }, | |
537 | { "osc_cached_mb", &osc_cached_mb_fops, 0 }, | |
538 | { "cur_dirty_bytes", &osc_cur_dirty_bytes_fops, 0, 0 }, | |
539 | { "cur_grant_bytes", &osc_cur_grant_bytes_fops, 0 }, | |
540 | { "cur_lost_grant_bytes", &osc_cur_lost_grant_bytes_fops, 0, 0}, | |
541 | { "grant_shrink_interval", &osc_grant_shrink_interval_fops, 0 }, | |
542 | { "checksums", &osc_checksum_fops, 0 }, | |
543 | { "checksum_type", &osc_checksum_type_fops, 0 }, | |
544 | { "resend_count", &osc_resend_count_fops, 0}, | |
545 | { "timeouts", &osc_timeouts_fops, 0, 0 }, | |
546 | { "contention_seconds", &osc_contention_seconds_fops, 0 }, | |
547 | { "lockless_truncate", &osc_lockless_truncate_fops, 0 }, | |
548 | { "import", &osc_import_fops, 0 }, | |
549 | { "state", &osc_state_fops, 0, 0 }, | |
550 | { "pinger_recov", &osc_pinger_recov_fops, 0 }, | |
d7e09d03 PT |
551 | { 0 } |
552 | }; | |
553 | ||
73bb1da6 | 554 | LPROC_SEQ_FOPS_RO_TYPE(osc, numrefs); |
d7e09d03 | 555 | static struct lprocfs_vars lprocfs_osc_module_vars[] = { |
73bb1da6 | 556 | { "num_refs", &osc_numrefs_fops, 0, 0 }, |
d7e09d03 PT |
557 | { 0 } |
558 | }; | |
559 | ||
560 | #define pct(a,b) (b ? a * 100 / b : 0) | |
561 | ||
562 | static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) | |
563 | { | |
564 | struct timeval now; | |
565 | struct obd_device *dev = seq->private; | |
566 | struct client_obd *cli = &dev->u.cli; | |
567 | unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum; | |
568 | int i; | |
569 | ||
570 | do_gettimeofday(&now); | |
571 | ||
572 | client_obd_list_lock(&cli->cl_loi_list_lock); | |
573 | ||
574 | seq_printf(seq, "snapshot_time: %lu.%lu (secs.usecs)\n", | |
575 | now.tv_sec, now.tv_usec); | |
576 | seq_printf(seq, "read RPCs in flight: %d\n", | |
577 | cli->cl_r_in_flight); | |
578 | seq_printf(seq, "write RPCs in flight: %d\n", | |
579 | cli->cl_w_in_flight); | |
580 | seq_printf(seq, "pending write pages: %d\n", | |
581 | atomic_read(&cli->cl_pending_w_pages)); | |
582 | seq_printf(seq, "pending read pages: %d\n", | |
583 | atomic_read(&cli->cl_pending_r_pages)); | |
584 | ||
585 | seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); | |
586 | seq_printf(seq, "pages per rpc rpcs %% cum %% |"); | |
587 | seq_printf(seq, " rpcs %% cum %%\n"); | |
588 | ||
589 | read_tot = lprocfs_oh_sum(&cli->cl_read_page_hist); | |
590 | write_tot = lprocfs_oh_sum(&cli->cl_write_page_hist); | |
591 | ||
592 | read_cum = 0; | |
593 | write_cum = 0; | |
594 | for (i = 0; i < OBD_HIST_MAX; i++) { | |
595 | unsigned long r = cli->cl_read_page_hist.oh_buckets[i]; | |
596 | unsigned long w = cli->cl_write_page_hist.oh_buckets[i]; | |
597 | read_cum += r; | |
598 | write_cum += w; | |
599 | seq_printf(seq, "%d:\t\t%10lu %3lu %3lu | %10lu %3lu %3lu\n", | |
600 | 1 << i, r, pct(r, read_tot), | |
601 | pct(read_cum, read_tot), w, | |
602 | pct(w, write_tot), | |
603 | pct(write_cum, write_tot)); | |
604 | if (read_cum == read_tot && write_cum == write_tot) | |
605 | break; | |
606 | } | |
607 | ||
608 | seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); | |
609 | seq_printf(seq, "rpcs in flight rpcs %% cum %% |"); | |
610 | seq_printf(seq, " rpcs %% cum %%\n"); | |
611 | ||
612 | read_tot = lprocfs_oh_sum(&cli->cl_read_rpc_hist); | |
613 | write_tot = lprocfs_oh_sum(&cli->cl_write_rpc_hist); | |
614 | ||
615 | read_cum = 0; | |
616 | write_cum = 0; | |
617 | for (i = 0; i < OBD_HIST_MAX; i++) { | |
618 | unsigned long r = cli->cl_read_rpc_hist.oh_buckets[i]; | |
619 | unsigned long w = cli->cl_write_rpc_hist.oh_buckets[i]; | |
620 | read_cum += r; | |
621 | write_cum += w; | |
622 | seq_printf(seq, "%d:\t\t%10lu %3lu %3lu | %10lu %3lu %3lu\n", | |
623 | i, r, pct(r, read_tot), | |
624 | pct(read_cum, read_tot), w, | |
625 | pct(w, write_tot), | |
626 | pct(write_cum, write_tot)); | |
627 | if (read_cum == read_tot && write_cum == write_tot) | |
628 | break; | |
629 | } | |
630 | ||
631 | seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); | |
632 | seq_printf(seq, "offset rpcs %% cum %% |"); | |
633 | seq_printf(seq, " rpcs %% cum %%\n"); | |
634 | ||
635 | read_tot = lprocfs_oh_sum(&cli->cl_read_offset_hist); | |
636 | write_tot = lprocfs_oh_sum(&cli->cl_write_offset_hist); | |
637 | ||
638 | read_cum = 0; | |
639 | write_cum = 0; | |
640 | for (i = 0; i < OBD_HIST_MAX; i++) { | |
641 | unsigned long r = cli->cl_read_offset_hist.oh_buckets[i]; | |
642 | unsigned long w = cli->cl_write_offset_hist.oh_buckets[i]; | |
643 | read_cum += r; | |
644 | write_cum += w; | |
645 | seq_printf(seq, "%d:\t\t%10lu %3lu %3lu | %10lu %3lu %3lu\n", | |
646 | (i == 0) ? 0 : 1 << (i - 1), | |
647 | r, pct(r, read_tot), pct(read_cum, read_tot), | |
648 | w, pct(w, write_tot), pct(write_cum, write_tot)); | |
649 | if (read_cum == read_tot && write_cum == write_tot) | |
650 | break; | |
651 | } | |
652 | ||
653 | client_obd_list_unlock(&cli->cl_loi_list_lock); | |
654 | ||
655 | return 0; | |
656 | } | |
657 | #undef pct | |
658 | ||
659 | static ssize_t osc_rpc_stats_seq_write(struct file *file, const char *buf, | |
660 | size_t len, loff_t *off) | |
661 | { | |
662 | struct seq_file *seq = file->private_data; | |
663 | struct obd_device *dev = seq->private; | |
664 | struct client_obd *cli = &dev->u.cli; | |
665 | ||
666 | lprocfs_oh_clear(&cli->cl_read_rpc_hist); | |
667 | lprocfs_oh_clear(&cli->cl_write_rpc_hist); | |
668 | lprocfs_oh_clear(&cli->cl_read_page_hist); | |
669 | lprocfs_oh_clear(&cli->cl_write_page_hist); | |
670 | lprocfs_oh_clear(&cli->cl_read_offset_hist); | |
671 | lprocfs_oh_clear(&cli->cl_write_offset_hist); | |
672 | ||
673 | return len; | |
674 | } | |
675 | ||
676 | LPROC_SEQ_FOPS(osc_rpc_stats); | |
677 | ||
678 | static int osc_stats_seq_show(struct seq_file *seq, void *v) | |
679 | { | |
680 | struct timeval now; | |
681 | struct obd_device *dev = seq->private; | |
682 | struct osc_stats *stats = &obd2osc_dev(dev)->od_stats; | |
683 | ||
684 | do_gettimeofday(&now); | |
685 | ||
686 | seq_printf(seq, "snapshot_time: %lu.%lu (secs.usecs)\n", | |
687 | now.tv_sec, now.tv_usec); | |
688 | seq_printf(seq, "lockless_write_bytes\t\t"LPU64"\n", | |
689 | stats->os_lockless_writes); | |
690 | seq_printf(seq, "lockless_read_bytes\t\t"LPU64"\n", | |
691 | stats->os_lockless_reads); | |
692 | seq_printf(seq, "lockless_truncate\t\t"LPU64"\n", | |
693 | stats->os_lockless_truncates); | |
694 | return 0; | |
695 | } | |
696 | ||
697 | static ssize_t osc_stats_seq_write(struct file *file, const char *buf, | |
698 | size_t len, loff_t *off) | |
699 | { | |
700 | struct seq_file *seq = file->private_data; | |
701 | struct obd_device *dev = seq->private; | |
702 | struct osc_stats *stats = &obd2osc_dev(dev)->od_stats; | |
703 | ||
704 | memset(stats, 0, sizeof(*stats)); | |
705 | return len; | |
706 | } | |
707 | ||
708 | LPROC_SEQ_FOPS(osc_stats); | |
709 | ||
710 | int lproc_osc_attach_seqstat(struct obd_device *dev) | |
711 | { | |
712 | int rc; | |
713 | ||
714 | rc = lprocfs_seq_create(dev->obd_proc_entry, "osc_stats", 0644, | |
715 | &osc_stats_fops, dev); | |
716 | if (rc == 0) | |
717 | rc = lprocfs_obd_seq_create(dev, "rpc_stats", 0644, | |
718 | &osc_rpc_stats_fops, dev); | |
719 | ||
720 | return rc; | |
721 | } | |
722 | ||
723 | void lprocfs_osc_init_vars(struct lprocfs_static_vars *lvars) | |
724 | { | |
725 | lvars->module_vars = lprocfs_osc_module_vars; | |
726 | lvars->obd_vars = lprocfs_osc_obd_vars; | |
727 | } | |
728 | #endif /* LPROCFS */ |