Whamcloud - gitweb
LU-9019 osc: migrate to 64 bit time
[fs/lustre-release.git] / lustre / mdc / lproc_mdc.c
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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32 #define DEBUG_SUBSYSTEM S_CLASS
33
34 #include <linux/version.h>
35 #include <linux/vfs.h>
36 #include <obd_class.h>
37 #include <lprocfs_status.h>
38 #include <lustre_osc.h>
39 #include <cl_object.h>
40
41 #include "mdc_internal.h"
42
43 #ifdef CONFIG_PROC_FS
44 static int mdc_active_seq_show(struct seq_file *m, void *v)
45 {
46         struct obd_device *dev = m->private;
47
48         LPROCFS_CLIMP_CHECK(dev);
49         seq_printf(m, "%d\n", !dev->u.cli.cl_import->imp_deactive);
50         LPROCFS_CLIMP_EXIT(dev);
51         return 0;
52 }
53
54 static ssize_t mdc_active_seq_write(struct file *file,
55                                     const char __user *buffer,
56                                     size_t count, loff_t *off)
57 {
58         struct obd_device *dev;
59         int rc;
60         __s64 val;
61
62         dev = ((struct seq_file *)file->private_data)->private;
63         rc = lprocfs_str_to_s64(buffer, count, &val);
64         if (rc)
65                 return rc;
66         if (val < 0 || val > 1)
67                 return -ERANGE;
68
69         /* opposite senses */
70         if (dev->u.cli.cl_import->imp_deactive == val)
71                 rc = ptlrpc_set_import_active(dev->u.cli.cl_import, val);
72         else
73                 CDEBUG(D_CONFIG, "activate %llu: ignoring repeat request\n",
74                        val);
75
76         return count;
77 }
78 LPROC_SEQ_FOPS(mdc_active);
79
80 static int mdc_max_dirty_mb_seq_show(struct seq_file *m, void *v)
81 {
82         struct obd_device *dev = m->private;
83         struct client_obd *cli = &dev->u.cli;
84         long val;
85         int mult;
86
87         spin_lock(&cli->cl_loi_list_lock);
88         val = cli->cl_dirty_max_pages;
89         spin_unlock(&cli->cl_loi_list_lock);
90
91         mult = 1 << (20 - PAGE_SHIFT);
92         return lprocfs_seq_read_frac_helper(m, val, mult);
93 }
94
95 static ssize_t mdc_max_dirty_mb_seq_write(struct file *file,
96                                           const char __user *buffer,
97                                           size_t count, loff_t *off)
98 {
99         struct seq_file *sfl = file->private_data;
100         struct obd_device *dev = sfl->private;
101         struct client_obd *cli = &dev->u.cli;
102         __s64 pages_number;
103         int rc;
104
105         rc = lprocfs_str_with_units_to_s64(buffer, count, &pages_number, 'M');
106         if (rc)
107                 return rc;
108
109         pages_number >>= PAGE_SHIFT;
110
111         if (pages_number <= 0 ||
112             pages_number >= OSC_MAX_DIRTY_MB_MAX << (20 - PAGE_SHIFT) ||
113             pages_number > totalram_pages / 4) /* 1/4 of RAM */
114                 return -ERANGE;
115
116         spin_lock(&cli->cl_loi_list_lock);
117         cli->cl_dirty_max_pages = pages_number;
118         osc_wake_cache_waiters(cli);
119         spin_unlock(&cli->cl_loi_list_lock);
120
121         return count;
122 }
123 LPROC_SEQ_FOPS(mdc_max_dirty_mb);
124
125 static int mdc_cached_mb_seq_show(struct seq_file *m, void *v)
126 {
127         struct obd_device *dev = m->private;
128         struct client_obd *cli = &dev->u.cli;
129         int shift = 20 - PAGE_SHIFT;
130
131         seq_printf(m, "used_mb: %ld\n"
132                    "busy_cnt: %ld\n"
133                    "reclaim: %llu\n",
134                    (atomic_long_read(&cli->cl_lru_in_list) +
135                     atomic_long_read(&cli->cl_lru_busy)) >> shift,
136                     atomic_long_read(&cli->cl_lru_busy),
137                    cli->cl_lru_reclaim);
138
139         return 0;
140 }
141
142 /* shrink the number of caching pages to a specific number */
143 static ssize_t
144 mdc_cached_mb_seq_write(struct file *file, const char __user *buffer,
145                         size_t count, loff_t *off)
146 {
147         struct seq_file *sfl = file->private_data;
148         struct obd_device *dev = sfl->private;
149         struct client_obd *cli = &dev->u.cli;
150         __s64 pages_number;
151         long rc;
152         char kernbuf[128];
153
154         if (count >= sizeof(kernbuf))
155                 return -EINVAL;
156
157         if (copy_from_user(kernbuf, buffer, count))
158                 return -EFAULT;
159         kernbuf[count] = 0;
160
161         buffer += lprocfs_find_named_value(kernbuf, "used_mb:", &count) -
162                   kernbuf;
163         rc = lprocfs_str_with_units_to_s64(buffer, count, &pages_number, 'M');
164         if (rc)
165                 return rc;
166
167         pages_number >>= PAGE_SHIFT;
168
169         if (pages_number < 0)
170                 return -ERANGE;
171
172         rc = atomic_long_read(&cli->cl_lru_in_list) - pages_number;
173         if (rc > 0) {
174                 struct lu_env *env;
175                 __u16 refcheck;
176
177                 env = cl_env_get(&refcheck);
178                 if (!IS_ERR(env)) {
179                         (void)osc_lru_shrink(env, cli, rc, true);
180                         cl_env_put(env, &refcheck);
181                 }
182         }
183
184         return count;
185 }
186 LPROC_SEQ_FOPS(mdc_cached_mb);
187
188 static int mdc_contention_seconds_seq_show(struct seq_file *m, void *v)
189 {
190         struct obd_device *obd = m->private;
191         struct osc_device *od  = obd2osc_dev(obd);
192
193         seq_printf(m, "%lld\n", od->od_contention_time);
194         return 0;
195 }
196
197 static ssize_t mdc_contention_seconds_seq_write(struct file *file,
198                                                 const char __user *buffer,
199                                                 size_t count, loff_t *off)
200 {
201         struct seq_file *sfl = file->private_data;
202         struct obd_device *obd = sfl->private;
203         struct osc_device *od  = obd2osc_dev(obd);
204         int rc;
205         __s64 val;
206
207         rc = lprocfs_str_to_s64(buffer, count, &val);
208         if (rc)
209                 return rc;
210         if (val < 0 || val > INT_MAX)
211                 return -ERANGE;
212
213         od->od_contention_time = val;
214
215         return count;
216 }
217 LPROC_SEQ_FOPS(mdc_contention_seconds);
218
219 static int mdc_unstable_stats_seq_show(struct seq_file *m, void *v)
220 {
221         struct obd_device *dev = m->private;
222         struct client_obd *cli = &dev->u.cli;
223         long pages;
224         int mb;
225
226         pages = atomic_long_read(&cli->cl_unstable_count);
227         mb    = (pages * PAGE_SIZE) >> 20;
228
229         seq_printf(m, "unstable_pages: %20ld\n"
230                    "unstable_mb:              %10d\n", pages, mb);
231         return 0;
232 }
233 LPROC_SEQ_FOPS_RO(mdc_unstable_stats);
234
235 static int mdc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v)
236 {
237         struct obd_device *dev = m->private;
238         __u32 max;
239
240         max = obd_get_max_rpcs_in_flight(&dev->u.cli);
241         seq_printf(m, "%u\n", max);
242
243         return 0;
244 }
245
246 static ssize_t mdc_max_rpcs_in_flight_seq_write(struct file *file,
247                                                 const char __user *buffer,
248                                                 size_t count, loff_t *off)
249 {
250         struct obd_device *dev;
251         __s64 val;
252         int rc;
253
254         dev = ((struct seq_file *)file->private_data)->private;
255         rc = lprocfs_str_to_s64(buffer, count, &val);
256         if (rc)
257                 return rc;
258
259         if (val < 0 || val > UINT_MAX)
260                 return -ERANGE;
261
262         rc = obd_set_max_rpcs_in_flight(&dev->u.cli, val);
263         if (rc)
264                 return rc;
265
266         return count;
267 }
268 LPROC_SEQ_FOPS(mdc_max_rpcs_in_flight);
269
270 static int mdc_max_mod_rpcs_in_flight_seq_show(struct seq_file *m, void *v)
271 {
272         struct obd_device *dev = m->private;
273         __u16 max;
274
275         max = obd_get_max_mod_rpcs_in_flight(&dev->u.cli);
276         seq_printf(m, "%hu\n", max);
277
278         return 0;
279 }
280
281 static ssize_t mdc_max_mod_rpcs_in_flight_seq_write(struct file *file,
282                                                     const char __user *buffer,
283                                                     size_t count, loff_t *off)
284 {
285         struct obd_device *dev;
286         __s64 val;
287         int rc;
288
289         dev =  ((struct seq_file *)file->private_data)->private;
290         rc = lprocfs_str_to_s64(buffer, count, &val);
291         if (rc)
292                 return rc;
293
294         if (val < 0 || val > USHRT_MAX)
295                 return -ERANGE;
296
297         rc = obd_set_max_mod_rpcs_in_flight(&dev->u.cli, val);
298         if (rc)
299                 count = rc;
300
301         return count;
302 }
303 LPROC_SEQ_FOPS(mdc_max_mod_rpcs_in_flight);
304
305 static ssize_t mdc_rpc_stats_seq_write(struct file *file,
306                                        const char __user *buf,
307                                        size_t len, loff_t *off)
308 {
309         struct seq_file *seq = file->private_data;
310         struct obd_device *dev = seq->private;
311         struct client_obd *cli = &dev->u.cli;
312
313         lprocfs_oh_clear(&cli->cl_mod_rpcs_hist);
314
315         lprocfs_oh_clear(&cli->cl_read_rpc_hist);
316         lprocfs_oh_clear(&cli->cl_write_rpc_hist);
317         lprocfs_oh_clear(&cli->cl_read_page_hist);
318         lprocfs_oh_clear(&cli->cl_write_page_hist);
319         lprocfs_oh_clear(&cli->cl_read_offset_hist);
320         lprocfs_oh_clear(&cli->cl_write_offset_hist);
321
322         return len;
323 }
324
325 #define pct(a, b) (b ? a * 100 / b : 0)
326 static int mdc_rpc_stats_seq_show(struct seq_file *seq, void *v)
327 {
328         struct obd_device *dev = seq->private;
329         struct client_obd *cli = &dev->u.cli;
330         unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum;
331         int i;
332
333         obd_mod_rpc_stats_seq_show(&dev->u.cli, seq);
334
335         spin_lock(&cli->cl_loi_list_lock);
336
337         seq_printf(seq, "\nread RPCs in flight:  %d\n",
338                    cli->cl_r_in_flight);
339         seq_printf(seq, "write RPCs in flight: %d\n",
340                    cli->cl_w_in_flight);
341         seq_printf(seq, "pending write pages:  %d\n",
342                    atomic_read(&cli->cl_pending_w_pages));
343         seq_printf(seq, "pending read pages:   %d\n",
344                    atomic_read(&cli->cl_pending_r_pages));
345
346         seq_printf(seq, "\n\t\t\tread\t\t\twrite\n");
347         seq_printf(seq, "pages per rpc         rpcs   %% cum %% |");
348         seq_printf(seq, "       rpcs   %% cum %%\n");
349
350         read_tot = lprocfs_oh_sum(&cli->cl_read_page_hist);
351         write_tot = lprocfs_oh_sum(&cli->cl_write_page_hist);
352
353         read_cum = 0;
354         write_cum = 0;
355         for (i = 0; i < OBD_HIST_MAX; i++) {
356                 unsigned long r = cli->cl_read_page_hist.oh_buckets[i];
357                 unsigned long w = cli->cl_write_page_hist.oh_buckets[i];
358
359                 read_cum += r;
360                 write_cum += w;
361                 seq_printf(seq, "%d:\t\t%10lu %3lu %3lu   | %10lu %3lu %3lu\n",
362                            1 << i, r, pct(r, read_tot),
363                            pct(read_cum, read_tot), w,
364                            pct(w, write_tot),
365                            pct(write_cum, write_tot));
366                 if (read_cum == read_tot && write_cum == write_tot)
367                         break;
368         }
369
370         seq_printf(seq, "\n\t\t\tread\t\t\twrite\n");
371         seq_printf(seq, "rpcs in flight        rpcs   %% cum %% |");
372         seq_printf(seq, "       rpcs   %% cum %%\n");
373
374         read_tot = lprocfs_oh_sum(&cli->cl_read_rpc_hist);
375         write_tot = lprocfs_oh_sum(&cli->cl_write_rpc_hist);
376
377         read_cum = 0;
378         write_cum = 0;
379         for (i = 0; i < OBD_HIST_MAX; i++) {
380                 unsigned long r = cli->cl_read_rpc_hist.oh_buckets[i];
381                 unsigned long w = cli->cl_write_rpc_hist.oh_buckets[i];
382
383                 read_cum += r;
384                 write_cum += w;
385                 seq_printf(seq, "%d:\t\t%10lu %3lu %3lu   | %10lu %3lu %3lu\n",
386                            i, r, pct(r, read_tot), pct(read_cum, read_tot), w,
387                            pct(w, write_tot), pct(write_cum, write_tot));
388                 if (read_cum == read_tot && write_cum == write_tot)
389                         break;
390         }
391
392         seq_printf(seq, "\n\t\t\tread\t\t\twrite\n");
393         seq_printf(seq, "offset                rpcs   %% cum %% |");
394         seq_printf(seq, "       rpcs   %% cum %%\n");
395
396         read_tot = lprocfs_oh_sum(&cli->cl_read_offset_hist);
397         write_tot = lprocfs_oh_sum(&cli->cl_write_offset_hist);
398
399         read_cum = 0;
400         write_cum = 0;
401         for (i = 0; i < OBD_HIST_MAX; i++) {
402                 unsigned long r = cli->cl_read_offset_hist.oh_buckets[i];
403                 unsigned long w = cli->cl_write_offset_hist.oh_buckets[i];
404
405                 read_cum += r;
406                 write_cum += w;
407                 seq_printf(seq, "%d:\t\t%10lu %3lu %3lu   | %10lu %3lu %3lu\n",
408                            (i == 0) ? 0 : 1 << (i - 1),
409                            r, pct(r, read_tot), pct(read_cum, read_tot),
410                            w, pct(w, write_tot), pct(write_cum, write_tot));
411                 if (read_cum == read_tot && write_cum == write_tot)
412                         break;
413         }
414         spin_unlock(&cli->cl_loi_list_lock);
415
416         return 0;
417 }
418 #undef pct
419 LPROC_SEQ_FOPS(mdc_rpc_stats);
420
421 static int mdc_stats_seq_show(struct seq_file *seq, void *v)
422 {
423         struct timespec64 now;
424         struct obd_device *dev = seq->private;
425         struct osc_stats *stats = &obd2osc_dev(dev)->od_stats;
426
427         ktime_get_real_ts64(&now);
428
429         seq_printf(seq, "snapshot_time:         %lld.%09lu (secs.nsecs)\n",
430                    (s64)now.tv_sec, now.tv_nsec);
431         seq_printf(seq, "lockless_write_bytes\t\t%llu\n",
432                    stats->os_lockless_writes);
433         seq_printf(seq, "lockless_read_bytes\t\t%llu\n",
434                    stats->os_lockless_reads);
435         seq_printf(seq, "lockless_truncate\t\t%llu\n",
436                    stats->os_lockless_truncates);
437         return 0;
438 }
439
440 static ssize_t mdc_stats_seq_write(struct file *file,
441                                    const char __user *buf,
442                                    size_t len, loff_t *off)
443 {
444         struct seq_file *seq = file->private_data;
445         struct obd_device *dev = seq->private;
446         struct osc_stats *stats = &obd2osc_dev(dev)->od_stats;
447
448         memset(stats, 0, sizeof(*stats));
449         return len;
450 }
451 LPROC_SEQ_FOPS(mdc_stats);
452
453 LPROC_SEQ_FOPS_WR_ONLY(mdc, ping);
454
455 LPROC_SEQ_FOPS_RO_TYPE(mdc, connect_flags);
456 LPROC_SEQ_FOPS_RO_TYPE(mdc, server_uuid);
457 LPROC_SEQ_FOPS_RO_TYPE(mdc, conn_uuid);
458 LPROC_SEQ_FOPS_RO_TYPE(mdc, timeouts);
459 LPROC_SEQ_FOPS_RO_TYPE(mdc, state);
460 LPROC_SEQ_FOPS_RW_TYPE(mdc, obd_max_pages_per_rpc);
461 LPROC_SEQ_FOPS_RW_TYPE(mdc, import);
462 LPROC_SEQ_FOPS_RW_TYPE(mdc, pinger_recov);
463
464 struct lprocfs_vars lprocfs_mdc_obd_vars[] = {
465         { .name =       "ping",
466           .fops =       &mdc_ping_fops,
467           .proc_mode =  0222                    },
468         { .name =       "connect_flags",
469           .fops =       &mdc_connect_flags_fops },
470         { .name =       "mds_server_uuid",
471           .fops =       &mdc_server_uuid_fops   },
472         { .name =       "mds_conn_uuid",
473           .fops =       &mdc_conn_uuid_fops     },
474         { .name =       "max_pages_per_rpc",
475           .fops =       &mdc_obd_max_pages_per_rpc_fops },
476         { .name =       "max_rpcs_in_flight",
477           .fops =       &mdc_max_rpcs_in_flight_fops    },
478         { .name =       "max_mod_rpcs_in_flight",
479           .fops =       &mdc_max_mod_rpcs_in_flight_fops },
480         { .name =       "max_dirty_mb",
481           .fops =       &mdc_max_dirty_mb_fops          },
482         { .name =       "mdc_cached_mb",
483           .fops =       &mdc_cached_mb_fops             },
484         { .name =       "timeouts",
485           .fops =       &mdc_timeouts_fops              },
486         { .name =       "contention_seconds",
487           .fops =       &mdc_contention_seconds_fops    },
488         { .name =       "import",
489           .fops =       &mdc_import_fops                },
490         { .name =       "state",
491           .fops =       &mdc_state_fops                 },
492         { .name =       "pinger_recov",
493           .fops =       &mdc_pinger_recov_fops          },
494         { .name =       "rpc_stats",
495           .fops =       &mdc_rpc_stats_fops             },
496         { .name =       "active",
497           .fops =       &mdc_active_fops                },
498         { .name =       "unstable_stats",
499           .fops =       &mdc_unstable_stats_fops        },
500         { .name =       "mdc_stats",
501           .fops =       &mdc_stats_fops                 },
502         { NULL }
503 };
504
505 #endif /* CONFIG_PROC_FS */