Whamcloud - gitweb
429b9fedb673e540a0ccf228e31b50525b86be68
[fs/lustre-release.git] / lustre / lod / lproc_lod.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  2008 Sun Microsystems, Inc. All rights reserved
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 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 <lprocfs_status.h>
35 #include <obd_class.h>
36 #include <linux/seq_file.h>
37 #include "lod_internal.h"
38 #include <uapi/linux/lustre/lustre_param.h>
39
40 /*
41  * Notice, all the functions below (except for lod_procfs_init() and
42  * lod_procfs_fini()) are not supposed to be used directly. They are
43  * called by Linux kernel's procfs.
44  */
45
46 #ifdef CONFIG_PROC_FS
47
48 /**
49  * Show default stripe size.
50  *
51  * \param[in] m         seq file
52  * \param[in] v         unused for single entry
53  *
54  * \retval 0            on success
55  * \retval negative     error code if failed
56  */
57 static int lod_dom_stripesize_seq_show(struct seq_file *m, void *v)
58 {
59         struct obd_device *dev = m->private;
60         struct lod_device *lod;
61
62         LASSERT(dev != NULL);
63         lod = lu2lod_dev(dev->obd_lu_dev);
64         seq_printf(m, "%u\n", lod->lod_dom_max_stripesize);
65         return 0;
66 }
67
68 /**
69  * Set default stripe size.
70  *
71  * \param[in] file      proc file
72  * \param[in] buffer    string containing the maximum number of bytes stored in
73  *                      each object before moving to the next object in the
74  *                      layout (if any)
75  * \param[in] count     @buffer length
76  * \param[in] off       unused for single entry
77  *
78  * \retval @count       on success
79  * \retval negative     error code if failed
80  */
81 static ssize_t
82 lod_dom_stripesize_seq_write(struct file *file, const char __user *buffer,
83                               size_t count, loff_t *off)
84 {
85         struct seq_file *m = file->private_data;
86         struct obd_device *dev = m->private;
87         struct lod_device *lod;
88         s64 val;
89         int rc;
90
91         LASSERT(dev != NULL);
92         lod = lu2lod_dev(dev->obd_lu_dev);
93         rc = lprocfs_str_with_units_to_s64(buffer, count, &val, '1');
94         if (rc)
95                 return rc;
96         if (val < 0)
97                 return -ERANGE;
98
99         /* 1GB is the limit */
100         if (val > (1ULL << 30))
101                 return -ERANGE;
102         else if (val > 0)
103                 lod_fix_desc_stripe_size(&val);
104
105         lod->lod_dom_max_stripesize = val;
106
107         return count;
108 }
109 LPROC_SEQ_FOPS(lod_dom_stripesize);
110
111 /**
112  * Show default stripe size.
113  *
114  * \param[in] m         seq file
115  * \param[in] v         unused for single entry
116  *
117  * \retval 0            on success
118  * \retval negative     error code if failed
119  */
120 static int lod_stripesize_seq_show(struct seq_file *m, void *v)
121 {
122         struct obd_device *dev = m->private;
123         struct lod_device *lod;
124
125         LASSERT(dev != NULL);
126         lod  = lu2lod_dev(dev->obd_lu_dev);
127         seq_printf(m, "%llu\n",
128                    lod->lod_desc.ld_default_stripe_size);
129         return 0;
130 }
131
132 /**
133  * Set default stripe size.
134  *
135  * \param[in] file      proc file
136  * \param[in] buffer    string containing the maximum number of bytes stored in
137  *                      each object before moving to the next object in the
138  *                      layout (if any)
139  * \param[in] count     @buffer length
140  * \param[in] off       unused for single entry
141  *
142  * \retval @count       on success
143  * \retval negative     error code if failed
144  */
145 static ssize_t
146 lod_stripesize_seq_write(struct file *file, const char __user *buffer,
147                          size_t count, loff_t *off)
148 {
149         struct seq_file *m = file->private_data;
150         struct obd_device *dev = m->private;
151         struct lod_device *lod;
152         s64 val;
153         int rc;
154
155         LASSERT(dev != NULL);
156         lod  = lu2lod_dev(dev->obd_lu_dev);
157         rc = lprocfs_str_with_units_to_s64(buffer, count, &val, '1');
158         if (rc)
159                 return rc;
160         if (val < 0)
161                 return -ERANGE;
162
163         lod_fix_desc_stripe_size(&val);
164         lod->lod_desc.ld_default_stripe_size = val;
165
166         return count;
167 }
168 LPROC_SEQ_FOPS(lod_stripesize);
169
170 /**
171  * Show default stripe offset.
172  *
173  * \param[in] m         seq file
174  * \param[in] v         unused for single entry
175  *
176  * \retval 0            on success
177  * \retval negative     error code if failed
178  */
179 static int lod_stripeoffset_seq_show(struct seq_file *m, void *v)
180 {
181         struct obd_device *dev = m->private;
182         struct lod_device *lod;
183
184         LASSERT(dev != NULL);
185         lod  = lu2lod_dev(dev->obd_lu_dev);
186         seq_printf(m, "%lld\n", lod->lod_desc.ld_default_stripe_offset);
187         return 0;
188 }
189
190 /**
191  * Set default stripe offset.
192  *
193  * Usually contains -1 allowing Lustre to balance objects among OST
194  * otherwise may cause severe OST imbalance.
195  *
196  * \param[in] file      proc file
197  * \param[in] buffer    string describing starting OST index for new files
198  * \param[in] count     @buffer length
199  * \param[in] off       unused for single entry
200  *
201  * \retval @count       on success
202  * \retval negative     error code if failed
203  */
204 static ssize_t
205 lod_stripeoffset_seq_write(struct file *file, const char __user *buffer,
206                            size_t count, loff_t *off)
207 {
208         struct seq_file *m = file->private_data;
209         struct obd_device *dev = m->private;
210         struct lod_device *lod;
211         long val;
212         int rc;
213
214         LASSERT(dev != NULL);
215         lod  = lu2lod_dev(dev->obd_lu_dev);
216         rc = kstrtol_from_user(buffer, count, 0, &val);
217         if (rc)
218                 return rc;
219         if (val < -1 || val > LOV_MAX_STRIPE_COUNT)
220                 return -ERANGE;
221
222         lod->lod_desc.ld_default_stripe_offset = val;
223
224         return count;
225 }
226 LPROC_SEQ_FOPS(lod_stripeoffset);
227
228 /**
229  * Show default striping pattern (LOV_PATTERN_*).
230  *
231  * \param[in] m         seq file
232  * \param[in] v         unused for single entry
233  *
234  * \retval 0            on success
235  * \retval negative     error code if failed
236  */
237 static int lod_stripetype_seq_show(struct seq_file *m, void *v)
238 {
239         struct obd_device *dev = m->private;
240         struct lod_device *lod;
241
242         LASSERT(dev != NULL);
243         lod  = lu2lod_dev(dev->obd_lu_dev);
244         seq_printf(m, "%u\n", lod->lod_desc.ld_pattern);
245         return 0;
246 }
247
248 /**
249  * Set default striping pattern (a number, not a human-readable string).
250  *
251  * \param[in] file      proc file
252  * \param[in] buffer    string containing the default striping pattern for new
253  *                      files. This is an integer LOV_PATTERN_* value
254  * \param[in] count     @buffer length
255  * \param[in] off       unused for single entry
256  *
257  * \retval @count       on success
258  * \retval negative     error code if failed
259  */
260 static ssize_t
261 lod_stripetype_seq_write(struct file *file, const char __user *buffer,
262                          size_t count, loff_t *off)
263 {
264         struct seq_file *m = file->private_data;
265         struct obd_device *dev = m->private;
266         struct lod_device *lod;
267         u32 pattern;
268         int rc;
269
270         LASSERT(dev != NULL);
271         lod  = lu2lod_dev(dev->obd_lu_dev);
272         rc = kstrtouint_from_user(buffer, count, 0, &pattern);
273         if (rc)
274                 return rc;
275
276         lod_fix_desc_pattern(&pattern);
277         lod->lod_desc.ld_pattern = pattern;
278
279         return count;
280 }
281 LPROC_SEQ_FOPS(lod_stripetype);
282
283 /**
284  * Show default number of stripes.
285  *
286  * \param[in] m         seq file
287  * \param[in] v         unused for single entry
288  *
289  * \retval 0            on success,
290  * \retval negative     error code if failed
291  */
292 static int lod_stripecount_seq_show(struct seq_file *m, void *v)
293 {
294         struct obd_device *dev = m->private;
295         struct lod_device *lod;
296
297         LASSERT(dev != NULL);
298         lod  = lu2lod_dev(dev->obd_lu_dev);
299         seq_printf(m, "%d\n",
300                    (__s16)(lod->lod_desc.ld_default_stripe_count + 1) - 1);
301         return 0;
302 }
303
304 /**
305  * Set default number of stripes.
306  *
307  * \param[in] file      proc file
308  * \param[in] buffer    string containing the default number of stripes
309  *                      for new files
310  * \param[in] count     @buffer length
311  * \param[in] off       unused for single entry
312  *
313  * \retval @count       on success
314  * \retval negative     error code otherwise
315  */
316 static ssize_t
317 lod_stripecount_seq_write(struct file *file, const char __user *buffer,
318                           size_t count, loff_t *off)
319 {
320         struct seq_file *m = file->private_data;
321         struct obd_device *dev = m->private;
322         struct lod_device *lod;
323         u32 stripe_count;
324         int rc;
325
326         LASSERT(dev != NULL);
327         lod = lu2lod_dev(dev->obd_lu_dev);
328         rc = kstrtouint_from_user(buffer, count, 0, &stripe_count);
329         if (rc)
330                 return rc;
331
332         lod_fix_desc_stripe_count(&stripe_count);
333         lod->lod_desc.ld_default_stripe_count = stripe_count;
334
335         return count;
336 }
337 LPROC_SEQ_FOPS(lod_stripecount);
338
339 /**
340  * Show number of targets.
341  *
342  * \param[in] m         seq file
343  * \param[in] v         unused for single entry
344  *
345  * \retval 0            on success
346  * \retval negative     error code if failed
347  */
348 static int lod_numobd_seq_show(struct seq_file *m, void *v)
349 {
350         struct obd_device *dev = m->private;
351         struct lod_device *lod;
352
353         LASSERT(dev != NULL);
354         lod  = lu2lod_dev(dev->obd_lu_dev);
355         seq_printf(m, "%u\n", lod->lod_desc.ld_tgt_count);
356         return 0;
357 }
358 LPROC_SEQ_FOPS_RO(lod_numobd);
359
360 /**
361  * Show number of active targets.
362  *
363  * \param[in] m         seq file
364  * \param[in] v         unused for single entry
365  *
366  * \retval 0            on success
367  * \retval negative     error code if failed
368  */
369 static int lod_activeobd_seq_show(struct seq_file *m, void *v)
370 {
371         struct obd_device *dev = m->private;
372         struct lod_device *lod;
373
374         LASSERT(dev != NULL);
375         lod  = lu2lod_dev(dev->obd_lu_dev);
376         seq_printf(m, "%u\n", lod->lod_desc.ld_active_tgt_count);
377         return 0;
378 }
379 LPROC_SEQ_FOPS_RO(lod_activeobd);
380
381 /**
382  * Show UUID of LOD device.
383  *
384  * \param[in] m         seq file
385  * \param[in] v         unused for single entry
386  *
387  * \retval 0            on success
388  * \retval negative     error code if failed
389  */
390 static int lod_desc_uuid_seq_show(struct seq_file *m, void *v)
391 {
392         struct obd_device *dev = m->private;
393         struct lod_device *lod;
394
395         LASSERT(dev != NULL);
396         lod  = lu2lod_dev(dev->obd_lu_dev);
397         seq_printf(m, "%s\n", lod->lod_desc.ld_uuid.uuid);
398         return 0;
399 }
400 LPROC_SEQ_FOPS_RO(lod_desc_uuid);
401
402 /**
403  * Show QoS priority parameter.
404  *
405  * The printed value is a percentage value (0-100%) indicating the priority
406  * of free space compared to performance. 0% means select OSTs equally
407  * regardless of their free space, 100% means select OSTs only by their free
408  * space even if it results in very imbalanced load on the OSTs.
409  *
410  * \param[in] m         seq file
411  * \param[in] v         unused for single entry
412  *
413  * \retval 0            on success
414  * \retval negative     error code if failed
415  */
416 static int lod_qos_priofree_seq_show(struct seq_file *m, void *v)
417 {
418         struct obd_device *dev = m->private;
419         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
420
421         LASSERT(lod != NULL);
422         seq_printf(m, "%d%%\n",
423                    (lod->lod_qos.lq_prio_free * 100 + 255) >> 8);
424         return 0;
425 }
426
427 /**
428  * Set QoS free space priority parameter.
429  *
430  * Set the relative priority of free OST space compared to OST load when OSTs
431  * are space imbalanced.  See lod_qos_priofree_seq_show() for description of
432  * this parameter.  See lod_qos_thresholdrr_seq_write() and lq_threshold_rr to
433  * determine what constitutes "space imbalanced" OSTs.
434  *
435  * \param[in] file      proc file
436  * \param[in] buffer    string which contains the free space priority (0-100)
437  * \param[in] count     @buffer length
438  * \param[in] off       unused for single entry
439  *
440  * \retval @count       on success
441  * \retval negative     error code if failed
442  */
443 static ssize_t
444 lod_qos_priofree_seq_write(struct file *file, const char __user *buffer,
445                            size_t count, loff_t *off)
446 {
447         struct seq_file *m = file->private_data;
448         struct obd_device *dev = m->private;
449         struct lod_device *lod;
450         unsigned int val;
451         int rc;
452
453         LASSERT(dev != NULL);
454         lod = lu2lod_dev(dev->obd_lu_dev);
455
456         rc = kstrtouint_from_user(buffer, count, 0, &val);
457         if (rc)
458                 return rc;
459
460         if (val > 100)
461                 return -EINVAL;
462         lod->lod_qos.lq_prio_free = (val << 8) / 100;
463         lod->lod_qos.lq_dirty = 1;
464         lod->lod_qos.lq_reset = 1;
465
466         return count;
467 }
468 LPROC_SEQ_FOPS(lod_qos_priofree);
469
470 /**
471  * Show threshold for "same space on all OSTs" rule.
472  *
473  * \param[in] m         seq file
474  * \param[in] v         unused for single entry
475  *
476  * \retval 0            on success
477  * \retval negative     error code if failed
478  */
479 static int lod_qos_thresholdrr_seq_show(struct seq_file *m, void *v)
480 {
481         struct obd_device *dev = m->private;
482         struct lod_device *lod;
483
484         LASSERT(dev != NULL);
485         lod = lu2lod_dev(dev->obd_lu_dev);
486         seq_printf(m, "%d%%\n",
487                    (lod->lod_qos.lq_threshold_rr * 100 + 255) >> 8);
488         return 0;
489 }
490
491 /**
492  * Set threshold for "same space on all OSTs" rule.
493  *
494  * This sets the maximum percentage difference of free space between the most
495  * full and most empty OST in the currently available OSTs. If this percentage
496  * is exceeded, use the QoS allocator to select OSTs based on their available
497  * space so that more full OSTs are chosen less often, otherwise use the
498  * round-robin allocator for efficiency and performance.
499
500  * \param[in] file      proc file
501  * \param[in] buffer    string containing percentage difference of free space
502  * \param[in] count     @buffer length
503  * \param[in] off       unused for single entry
504  *
505  * \retval @count       on success
506  * \retval negative     error code if failed
507  */
508 static ssize_t
509 lod_qos_thresholdrr_seq_write(struct file *file, const char __user *buffer,
510                               size_t count, loff_t *off)
511 {
512         struct seq_file *m = file->private_data;
513         struct obd_device *dev = m->private;
514         struct lod_device *lod;
515         int rc;
516         __s64 val;
517
518         LASSERT(dev != NULL);
519         lod = lu2lod_dev(dev->obd_lu_dev);
520
521         rc = lprocfs_str_with_units_to_s64(buffer, count, &val, '%');
522         if (rc)
523                 return rc;
524
525         if (val > 100 || val < 0)
526                 return -EINVAL;
527
528         lod->lod_qos.lq_threshold_rr = (val << 8) / 100;
529         lod->lod_qos.lq_dirty = 1;
530
531         return count;
532 }
533 LPROC_SEQ_FOPS(lod_qos_thresholdrr);
534
535 /**
536  * Show expiration period used to refresh cached statfs data, which
537  * is used to implement QoS/RR striping allocation algorithm.
538  *
539  * \param[in] m         seq file
540  * \param[in] v         unused for single entry
541  *
542  * \retval 0            on success
543  * \retval negative     error code if failed
544  */
545 static int lod_qos_maxage_seq_show(struct seq_file *m, void *v)
546 {
547         struct obd_device *dev = m->private;
548         struct lod_device *lod;
549
550         LASSERT(dev != NULL);
551         lod = lu2lod_dev(dev->obd_lu_dev);
552         seq_printf(m, "%u Sec\n", lod->lod_desc.ld_qos_maxage);
553         return 0;
554 }
555
556 /**
557  * Set expiration period used to refresh cached statfs data.
558  *
559  * \param[in] file      proc file
560  * \param[in] buffer    string contains maximum age of statfs data in seconds
561  * \param[in] count     @buffer length
562  * \param[in] off       unused for single entry
563  *
564  * \retval @count       on success
565  * \retval negative     error code if failed
566  */
567 static ssize_t
568 lod_qos_maxage_seq_write(struct file *file, const char __user *buffer,
569                          size_t count, loff_t *off)
570 {
571         struct seq_file *m = file->private_data;
572         struct obd_device *dev = m->private;
573         struct lustre_cfg_bufs bufs;
574         struct lod_device *lod;
575         struct lu_device *next;
576         struct lustre_cfg *lcfg;
577         char str[32];
578         unsigned int i;
579         int rc;
580         u32 val;
581
582         LASSERT(dev != NULL);
583         lod = lu2lod_dev(dev->obd_lu_dev);
584
585         rc = kstrtouint_from_user(buffer, count, 0, &val);
586         if (rc)
587                 return rc;
588
589         if (val <= 0)
590                 return -EINVAL;
591         lod->lod_desc.ld_qos_maxage = val;
592
593         /*
594          * propogate the value down to OSPs
595          */
596         lustre_cfg_bufs_reset(&bufs, NULL);
597         snprintf(str, 32, "%smaxage=%u", PARAM_OSP, val);
598         lustre_cfg_bufs_set_string(&bufs, 1, str);
599         OBD_ALLOC(lcfg, lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen));
600         if (lcfg == NULL)
601                 return -ENOMEM;
602         lustre_cfg_init(lcfg, LCFG_PARAM, &bufs);
603
604         lod_getref(&lod->lod_ost_descs);
605         lod_foreach_ost(lod, i) {
606                 next = &OST_TGT(lod,i)->ltd_ost->dd_lu_dev;
607                 rc = next->ld_ops->ldo_process_config(NULL, next, lcfg);
608                 if (rc)
609                         CERROR("can't set maxage on #%d: %d\n", i, rc);
610         }
611         lod_putref(lod, &lod->lod_ost_descs);
612         OBD_FREE(lcfg, lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens));
613
614         return count;
615 }
616 LPROC_SEQ_FOPS(lod_qos_maxage);
617
618 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos)
619 {
620         struct obd_device *dev = p->private;
621         struct lod_device *lod;
622
623         LASSERT(dev != NULL);
624         lod = lu2lod_dev(dev->obd_lu_dev);
625
626         lod_getref(&lod->lod_ost_descs); /* released in lod_osts_seq_stop */
627         if (*pos >= lod->lod_ost_bitmap->size)
628                 return NULL;
629
630         *pos = find_next_bit(lod->lod_ost_bitmap->data,
631                                  lod->lod_ost_bitmap->size, *pos);
632         if (*pos < lod->lod_ost_bitmap->size)
633                 return OST_TGT(lod,*pos);
634         else
635                 return NULL;
636 }
637
638 static void lod_osts_seq_stop(struct seq_file *p, void *v)
639 {
640         struct obd_device *dev = p->private;
641         struct lod_device *lod;
642
643         LASSERT(dev != NULL);
644         lod = lu2lod_dev(dev->obd_lu_dev);
645         lod_putref(lod, &lod->lod_ost_descs);
646 }
647
648 static void *lod_osts_seq_next(struct seq_file *p, void *v, loff_t *pos)
649 {
650         struct obd_device *dev = p->private;
651         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
652
653         if (*pos >= lod->lod_ost_bitmap->size - 1)
654                 return NULL;
655
656         *pos = find_next_bit(lod->lod_ost_bitmap->data,
657                                  lod->lod_ost_bitmap->size, *pos + 1);
658         if (*pos < lod->lod_ost_bitmap->size)
659                 return OST_TGT(lod,*pos);
660         else
661                 return NULL;
662 }
663
664 /**
665  * Show active/inactive status for OST found by lod_osts_seq_next().
666  *
667  * \param[in] m         seq file
668  * \param[in] v         unused for single entry
669  *
670  * \retval 0            on success
671  * \retval negative     error code if failed
672  */
673 static int lod_osts_seq_show(struct seq_file *p, void *v)
674 {
675         struct obd_device   *obd = p->private;
676         struct lod_ost_desc *ost_desc = v;
677         struct lod_device   *lod;
678         int                  idx, rc, active;
679         struct dt_device    *next;
680         struct obd_statfs    sfs;
681
682         LASSERT(obd->obd_lu_dev);
683         lod = lu2lod_dev(obd->obd_lu_dev);
684
685         idx = ost_desc->ltd_index;
686         next = OST_TGT(lod,idx)->ltd_ost;
687         if (next == NULL)
688                 return -EINVAL;
689
690         /* XXX: should be non-NULL env, but it's very expensive */
691         active = 1;
692         rc = dt_statfs(NULL, next, &sfs);
693         if (rc == -ENOTCONN) {
694                 active = 0;
695                 rc = 0;
696         } else if (rc)
697                 return rc;
698
699         seq_printf(p, "%d: %s %sACTIVE\n", idx,
700                    obd_uuid2str(&ost_desc->ltd_uuid),
701                    active ? "" : "IN");
702         return 0;
703 }
704
705 static const struct seq_operations lod_osts_sops = {
706         .start  = lod_osts_seq_start,
707         .stop   = lod_osts_seq_stop,
708         .next   = lod_osts_seq_next,
709         .show   = lod_osts_seq_show,
710 };
711
712 static int lod_osts_seq_open(struct inode *inode, struct file *file)
713 {
714         struct seq_file *seq;
715         int rc;
716
717         rc = seq_open(file, &lod_osts_sops);
718         if (rc)
719                 return rc;
720
721         seq = file->private_data;
722         seq->private = PDE_DATA(inode);
723         return 0;
724 }
725
726 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_blksize);
727 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytestotal);
728 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytesfree);
729 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytesavail);
730 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filestotal);
731 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filesfree);
732
733 /**
734  * Show whether special failout mode for testing is enabled or not.
735  *
736  * \param[in] m         seq file
737  * \param[in] v         unused for single entry
738  *
739  * \retval 0            on success
740  * \retval negative     error code if failed
741  */
742 static int lod_lmv_failout_seq_show(struct seq_file *m, void *v)
743 {
744         struct obd_device *dev = m->private;
745         struct lod_device *lod;
746
747         LASSERT(dev != NULL);
748         lod = lu2lod_dev(dev->obd_lu_dev);
749
750         seq_printf(m, "%d\n", lod->lod_lmv_failout ? 1 : 0);
751         return 0;
752 }
753
754 /**
755  * Enable/disable a special failout mode for testing.
756  *
757  * This determines whether the LMV will try to continue processing a striped
758  * directory even if it has a (partly) corrupted entry in the master directory,
759  * or if it will abort upon finding a corrupted slave directory entry.
760  *
761  * \param[in] file      proc file
762  * \param[in] buffer    string: 0 or non-zero to disable or enable LMV failout
763  * \param[in] count     @buffer length
764  * \param[in] off       unused for single entry
765  *
766  * \retval @count       on success
767  * \retval negative     error code if failed
768  */
769 static ssize_t
770 lod_lmv_failout_seq_write(struct file *file, const char __user *buffer,
771                           size_t count, loff_t *off)
772 {
773         struct seq_file *m = file->private_data;
774         struct obd_device *dev = m->private;
775         struct lod_device *lod;
776         bool val = 0;
777         int rc;
778
779         LASSERT(dev != NULL);
780         lod = lu2lod_dev(dev->obd_lu_dev);
781
782         rc = kstrtobool_from_user(buffer, count, &val);
783         if (rc)
784                 return rc;
785
786         lod->lod_lmv_failout = val;
787
788         return count;
789 }
790 LPROC_SEQ_FOPS(lod_lmv_failout);
791
792 static struct lprocfs_vars lprocfs_lod_obd_vars[] = {
793         { .name =       "stripesize",
794           .fops =       &lod_stripesize_fops    },
795         { .name =       "stripeoffset",
796           .fops =       &lod_stripeoffset_fops  },
797         { .name =       "stripecount",
798           .fops =       &lod_stripecount_fops   },
799         { .name =       "stripetype",
800           .fops =       &lod_stripetype_fops    },
801         { .name =       "numobd",
802           .fops =       &lod_numobd_fops        },
803         { .name =       "activeobd",
804           .fops =       &lod_activeobd_fops     },
805         { .name =       "desc_uuid",
806           .fops =       &lod_desc_uuid_fops     },
807         { .name =       "qos_prio_free",
808           .fops =       &lod_qos_priofree_fops  },
809         { .name =       "qos_threshold_rr",
810           .fops =       &lod_qos_thresholdrr_fops },
811         { .name =       "qos_maxage",
812           .fops =       &lod_qos_maxage_fops    },
813         { .name =       "lmv_failout",
814           .fops =       &lod_lmv_failout_fops   },
815         {
816           .name = "dom_stripesize",
817           .fops = &lod_dom_stripesize_fops
818         },
819         { NULL }
820 };
821
822 static struct lprocfs_vars lprocfs_lod_osd_vars[] = {
823         { .name = "blocksize",   .fops = &lod_dt_blksize_fops },
824         { .name = "kbytestotal", .fops = &lod_dt_kbytestotal_fops },
825         { .name = "kbytesfree",  .fops = &lod_dt_kbytesfree_fops },
826         { .name = "kbytesavail", .fops = &lod_dt_kbytesavail_fops },
827         { .name = "filestotal",  .fops = &lod_dt_filestotal_fops },
828         { .name = "filesfree",   .fops = &lod_dt_filesfree_fops },
829         { .name = NULL }
830 };
831
832 static const struct file_operations lod_proc_target_fops = {
833         .owner   = THIS_MODULE,
834         .open    = lod_osts_seq_open,
835         .read    = seq_read,
836         .llseek  = seq_lseek,
837         .release = lprocfs_seq_release,
838 };
839
840 /**
841  * Initialize procfs entries for LOD.
842  *
843  * \param[in] lod       LOD device
844  *
845  * \retval 0            on success
846  * \retval negative     error code if failed
847  */
848 int lod_procfs_init(struct lod_device *lod)
849 {
850         struct obd_device       *obd = lod2obd(lod);
851         struct proc_dir_entry   *lov_proc_dir = NULL;
852         struct obd_type         *type;
853         int                      rc;
854
855         obd->obd_vars = lprocfs_lod_obd_vars;
856         rc = lprocfs_obd_setup(obd, true);
857         if (rc) {
858                 CERROR("%s: cannot setup procfs entry: %d\n",
859                        obd->obd_name, rc);
860                 RETURN(rc);
861         }
862
863         rc = lprocfs_add_vars(obd->obd_proc_entry, lprocfs_lod_osd_vars,
864                               &lod->lod_dt_dev);
865         if (rc) {
866                 CERROR("%s: cannot setup procfs entry: %d\n",
867                        obd->obd_name, rc);
868                 GOTO(out, rc);
869         }
870
871         rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
872                                 0444, &lod_proc_target_fops, obd);
873         if (rc) {
874                 CWARN("%s: Error adding the target_obd file %d\n",
875                       obd->obd_name, rc);
876                 GOTO(out, rc);
877         }
878
879         lod->lod_pool_proc_entry = lprocfs_register("pools",
880                                                     obd->obd_proc_entry,
881                                                     NULL, NULL);
882         if (IS_ERR(lod->lod_pool_proc_entry)) {
883                 rc = PTR_ERR(lod->lod_pool_proc_entry);
884                 lod->lod_pool_proc_entry = NULL;
885                 CWARN("%s: Failed to create pool proc file: %d\n",
886                       obd->obd_name, rc);
887                 GOTO(out, rc);
888         }
889
890         /* If the real LOV is present which is the case for setups
891          * with both server and clients on the same node then use
892          * the LOV's proc root */
893         type = class_search_type(LUSTRE_LOV_NAME);
894         if (type != NULL && type->typ_procroot != NULL)
895                 lov_proc_dir = type->typ_procroot;
896         else
897                 lov_proc_dir = obd->obd_type->typ_procsym;
898
899         if (lov_proc_dir == NULL)
900                 RETURN(0);
901
902         /* for compatibility we link old procfs's LOV entries to lod ones */
903         lod->lod_symlink = lprocfs_add_symlink(obd->obd_name, lov_proc_dir,
904                                                "../lod/%s", obd->obd_name);
905         if (lod->lod_symlink == NULL)
906                 CERROR("cannot create LOV symlink for /proc/fs/lustre/lod/%s\n",
907                        obd->obd_name);
908         RETURN(0);
909
910 out:
911         lprocfs_obd_cleanup(obd);
912
913         return rc;
914 }
915
916 /**
917  * Cleanup procfs entries registred for LOD.
918  *
919  * \param[in] lod       LOD device
920  */
921 void lod_procfs_fini(struct lod_device *lod)
922 {
923         struct obd_device *obd = lod2obd(lod);
924
925         if (lod->lod_symlink != NULL) {
926                 lprocfs_remove(&lod->lod_symlink);
927                 lod->lod_symlink = NULL;
928         }
929
930         if (lod->lod_pool_proc_entry != NULL) {
931                 lprocfs_remove(&lod->lod_pool_proc_entry);
932                 lod->lod_pool_proc_entry = NULL;
933         }
934
935         lprocfs_obd_cleanup(obd);
936 }
937
938 #endif /* CONFIG_PROC_FS */
939