Whamcloud - gitweb
LU-10308 misc: update Intel copyright messages for 2017
[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         /* */
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         __s64 val;
212         int rc;
213
214         LASSERT(dev != NULL);
215         lod  = lu2lod_dev(dev->obd_lu_dev);
216         rc = lprocfs_str_to_s64(buffer, count, &val);
217         if (rc)
218                 return rc;
219         if (val < -1)
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         int rc;
268         __u32 pattern;
269         __s64 val;
270
271         LASSERT(dev != NULL);
272         lod  = lu2lod_dev(dev->obd_lu_dev);
273         rc = lprocfs_str_to_s64(buffer, count, &val);
274         if (rc)
275                 return rc;
276         if (val < 0)
277                 return -ERANGE;
278
279         pattern = val;
280         lod_fix_desc_pattern(&pattern);
281         lod->lod_desc.ld_pattern = pattern;
282
283         return count;
284 }
285 LPROC_SEQ_FOPS(lod_stripetype);
286
287 /**
288  * Show default number of stripes.
289  *
290  * \param[in] m         seq file
291  * \param[in] v         unused for single entry
292  *
293  * \retval 0            on success,
294  * \retval negative     error code if failed
295  */
296 static int lod_stripecount_seq_show(struct seq_file *m, void *v)
297 {
298         struct obd_device *dev = m->private;
299         struct lod_device *lod;
300
301         LASSERT(dev != NULL);
302         lod  = lu2lod_dev(dev->obd_lu_dev);
303         seq_printf(m, "%d\n",
304                    (__s16)(lod->lod_desc.ld_default_stripe_count + 1) - 1);
305         return 0;
306 }
307
308 /**
309  * Set default number of stripes.
310  *
311  * \param[in] file      proc file
312  * \param[in] buffer    string containing the default number of stripes
313  *                      for new files
314  * \param[in] count     @buffer length
315  * \param[in] off       unused for single entry
316  *
317  * \retval @count       on success
318  * \retval negative     error code otherwise
319  */
320 static ssize_t
321 lod_stripecount_seq_write(struct file *file, const char __user *buffer,
322                           size_t count, loff_t *off)
323 {
324         struct seq_file *m = file->private_data;
325         struct obd_device *dev = m->private;
326         struct lod_device *lod;
327         int rc;
328         __s64 val;
329         __u32 stripe_count;
330
331         LASSERT(dev != NULL);
332         lod  = lu2lod_dev(dev->obd_lu_dev);
333         rc = lprocfs_str_to_s64(buffer, count, &val);
334         if (rc)
335                 return rc;
336         if (val < -1)
337                 return -ERANGE;
338
339         stripe_count = val;
340         lod_fix_desc_stripe_count(&stripe_count);
341         lod->lod_desc.ld_default_stripe_count = stripe_count;
342
343         return count;
344 }
345 LPROC_SEQ_FOPS(lod_stripecount);
346
347 /**
348  * Show number of targets.
349  *
350  * \param[in] m         seq file
351  * \param[in] v         unused for single entry
352  *
353  * \retval 0            on success
354  * \retval negative     error code if failed
355  */
356 static int lod_numobd_seq_show(struct seq_file *m, void *v)
357 {
358         struct obd_device *dev = m->private;
359         struct lod_device *lod;
360
361         LASSERT(dev != NULL);
362         lod  = lu2lod_dev(dev->obd_lu_dev);
363         seq_printf(m, "%u\n", lod->lod_desc.ld_tgt_count);
364         return 0;
365 }
366 LPROC_SEQ_FOPS_RO(lod_numobd);
367
368 /**
369  * Show number of active targets.
370  *
371  * \param[in] m         seq file
372  * \param[in] v         unused for single entry
373  *
374  * \retval 0            on success
375  * \retval negative     error code if failed
376  */
377 static int lod_activeobd_seq_show(struct seq_file *m, void *v)
378 {
379         struct obd_device *dev = m->private;
380         struct lod_device *lod;
381
382         LASSERT(dev != NULL);
383         lod  = lu2lod_dev(dev->obd_lu_dev);
384         seq_printf(m, "%u\n", lod->lod_desc.ld_active_tgt_count);
385         return 0;
386 }
387 LPROC_SEQ_FOPS_RO(lod_activeobd);
388
389 /**
390  * Show UUID of LOD device.
391  *
392  * \param[in] m         seq file
393  * \param[in] v         unused for single entry
394  *
395  * \retval 0            on success
396  * \retval negative     error code if failed
397  */
398 static int lod_desc_uuid_seq_show(struct seq_file *m, void *v)
399 {
400         struct obd_device *dev = m->private;
401         struct lod_device *lod;
402
403         LASSERT(dev != NULL);
404         lod  = lu2lod_dev(dev->obd_lu_dev);
405         seq_printf(m, "%s\n", lod->lod_desc.ld_uuid.uuid);
406         return 0;
407 }
408 LPROC_SEQ_FOPS_RO(lod_desc_uuid);
409
410 /**
411  * Show QoS priority parameter.
412  *
413  * The printed value is a percentage value (0-100%) indicating the priority
414  * of free space compared to performance. 0% means select OSTs equally
415  * regardless of their free space, 100% means select OSTs only by their free
416  * space even if it results in very imbalanced load on the OSTs.
417  *
418  * \param[in] m         seq file
419  * \param[in] v         unused for single entry
420  *
421  * \retval 0            on success
422  * \retval negative     error code if failed
423  */
424 static int lod_qos_priofree_seq_show(struct seq_file *m, void *v)
425 {
426         struct obd_device *dev = m->private;
427         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
428
429         LASSERT(lod != NULL);
430         seq_printf(m, "%d%%\n",
431                    (lod->lod_qos.lq_prio_free * 100 + 255) >> 8);
432         return 0;
433 }
434
435 /**
436  * Set QoS free space priority parameter.
437  *
438  * Set the relative priority of free OST space compared to OST load when OSTs
439  * are space imbalanced.  See lod_qos_priofree_seq_show() for description of
440  * this parameter.  See lod_qos_thresholdrr_seq_write() and lq_threshold_rr to
441  * determine what constitutes "space imbalanced" OSTs.
442  *
443  * \param[in] file      proc file
444  * \param[in] buffer    string which contains the free space priority (0-100)
445  * \param[in] count     @buffer length
446  * \param[in] off       unused for single entry
447  *
448  * \retval @count       on success
449  * \retval negative     error code if failed
450  */
451 static ssize_t
452 lod_qos_priofree_seq_write(struct file *file, const char __user *buffer,
453                            size_t count, loff_t *off)
454 {
455         struct seq_file *m = file->private_data;
456         struct obd_device *dev = m->private;
457         struct lod_device *lod;
458         int rc;
459         __s64 val;
460
461         LASSERT(dev != NULL);
462         lod = lu2lod_dev(dev->obd_lu_dev);
463
464         rc = lprocfs_str_to_s64(buffer, count, &val);
465         if (rc)
466                 return rc;
467
468         if (val < 0 || val > 100)
469                 return -EINVAL;
470         lod->lod_qos.lq_prio_free = (val << 8) / 100;
471         lod->lod_qos.lq_dirty = 1;
472         lod->lod_qos.lq_reset = 1;
473
474         return count;
475 }
476 LPROC_SEQ_FOPS(lod_qos_priofree);
477
478 /**
479  * Show threshold for "same space on all OSTs" rule.
480  *
481  * \param[in] m         seq file
482  * \param[in] v         unused for single entry
483  *
484  * \retval 0            on success
485  * \retval negative     error code if failed
486  */
487 static int lod_qos_thresholdrr_seq_show(struct seq_file *m, void *v)
488 {
489         struct obd_device *dev = m->private;
490         struct lod_device *lod;
491
492         LASSERT(dev != NULL);
493         lod = lu2lod_dev(dev->obd_lu_dev);
494         seq_printf(m, "%d%%\n",
495                    (lod->lod_qos.lq_threshold_rr * 100 + 255) >> 8);
496         return 0;
497 }
498
499 /**
500  * Set threshold for "same space on all OSTs" rule.
501  *
502  * This sets the maximum percentage difference of free space between the most
503  * full and most empty OST in the currently available OSTs. If this percentage
504  * is exceeded, use the QoS allocator to select OSTs based on their available
505  * space so that more full OSTs are chosen less often, otherwise use the
506  * round-robin allocator for efficiency and performance.
507
508  * \param[in] file      proc file
509  * \param[in] buffer    string containing percentage difference of free space
510  * \param[in] count     @buffer length
511  * \param[in] off       unused for single entry
512  *
513  * \retval @count       on success
514  * \retval negative     error code if failed
515  */
516 static ssize_t
517 lod_qos_thresholdrr_seq_write(struct file *file, const char __user *buffer,
518                               size_t count, loff_t *off)
519 {
520         struct seq_file *m = file->private_data;
521         struct obd_device *dev = m->private;
522         struct lod_device *lod;
523         int rc;
524         __s64 val;
525
526         LASSERT(dev != NULL);
527         lod = lu2lod_dev(dev->obd_lu_dev);
528
529         rc = lprocfs_str_with_units_to_s64(buffer, count, &val, '%');
530         if (rc)
531                 return rc;
532
533         if (val > 100 || val < 0)
534                 return -EINVAL;
535
536         lod->lod_qos.lq_threshold_rr = (val << 8) / 100;
537         lod->lod_qos.lq_dirty = 1;
538
539         return count;
540 }
541 LPROC_SEQ_FOPS(lod_qos_thresholdrr);
542
543 /**
544  * Show expiration period used to refresh cached statfs data, which
545  * is used to implement QoS/RR striping allocation algorithm.
546  *
547  * \param[in] m         seq file
548  * \param[in] v         unused for single entry
549  *
550  * \retval 0            on success
551  * \retval negative     error code if failed
552  */
553 static int lod_qos_maxage_seq_show(struct seq_file *m, void *v)
554 {
555         struct obd_device *dev = m->private;
556         struct lod_device *lod;
557
558         LASSERT(dev != NULL);
559         lod = lu2lod_dev(dev->obd_lu_dev);
560         seq_printf(m, "%u Sec\n", lod->lod_desc.ld_qos_maxage);
561         return 0;
562 }
563
564 /**
565  * Set expiration period used to refresh cached statfs data.
566  *
567  * \param[in] file      proc file
568  * \param[in] buffer    string contains maximum age of statfs data in seconds
569  * \param[in] count     @buffer length
570  * \param[in] off       unused for single entry
571  *
572  * \retval @count       on success
573  * \retval negative     error code if failed
574  */
575 static ssize_t
576 lod_qos_maxage_seq_write(struct file *file, const char __user *buffer,
577                          size_t count, loff_t *off)
578 {
579         struct seq_file *m = file->private_data;
580         struct obd_device *dev = m->private;
581         struct lustre_cfg_bufs bufs;
582         struct lod_device *lod;
583         struct lu_device *next;
584         struct lustre_cfg *lcfg;
585         char str[32];
586         unsigned int i;
587         int rc;
588         __s64 val;
589
590         LASSERT(dev != NULL);
591         lod = lu2lod_dev(dev->obd_lu_dev);
592
593         rc = lprocfs_str_to_s64(buffer, count, &val);
594         if (rc)
595                 return rc;
596
597         if (val <= 0)
598                 return -EINVAL;
599         lod->lod_desc.ld_qos_maxage = val;
600
601         /*
602          * propogate the value down to OSPs
603          */
604         lustre_cfg_bufs_reset(&bufs, NULL);
605         snprintf(str, 32, "%smaxage=%u", PARAM_OSP, (__u32)val);
606         lustre_cfg_bufs_set_string(&bufs, 1, str);
607         OBD_ALLOC(lcfg, lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen));
608         if (lcfg == NULL)
609                 return -ENOMEM;
610         lustre_cfg_init(lcfg, LCFG_PARAM, &bufs);
611
612         lod_getref(&lod->lod_ost_descs);
613         lod_foreach_ost(lod, i) {
614                 next = &OST_TGT(lod,i)->ltd_ost->dd_lu_dev;
615                 rc = next->ld_ops->ldo_process_config(NULL, next, lcfg);
616                 if (rc)
617                         CERROR("can't set maxage on #%d: %d\n", i, rc);
618         }
619         lod_putref(lod, &lod->lod_ost_descs);
620         OBD_FREE(lcfg, lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens));
621
622         return count;
623 }
624 LPROC_SEQ_FOPS(lod_qos_maxage);
625
626 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos)
627 {
628         struct obd_device *dev = p->private;
629         struct lod_device *lod;
630
631         LASSERT(dev != NULL);
632         lod = lu2lod_dev(dev->obd_lu_dev);
633
634         lod_getref(&lod->lod_ost_descs); /* released in lod_osts_seq_stop */
635         if (*pos >= lod->lod_ost_bitmap->size)
636                 return NULL;
637
638         *pos = find_next_bit(lod->lod_ost_bitmap->data,
639                                  lod->lod_ost_bitmap->size, *pos);
640         if (*pos < lod->lod_ost_bitmap->size)
641                 return OST_TGT(lod,*pos);
642         else
643                 return NULL;
644 }
645
646 static void lod_osts_seq_stop(struct seq_file *p, void *v)
647 {
648         struct obd_device *dev = p->private;
649         struct lod_device *lod;
650
651         LASSERT(dev != NULL);
652         lod = lu2lod_dev(dev->obd_lu_dev);
653         lod_putref(lod, &lod->lod_ost_descs);
654 }
655
656 static void *lod_osts_seq_next(struct seq_file *p, void *v, loff_t *pos)
657 {
658         struct obd_device *dev = p->private;
659         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
660
661         if (*pos >= lod->lod_ost_bitmap->size - 1)
662                 return NULL;
663
664         *pos = find_next_bit(lod->lod_ost_bitmap->data,
665                                  lod->lod_ost_bitmap->size, *pos + 1);
666         if (*pos < lod->lod_ost_bitmap->size)
667                 return OST_TGT(lod,*pos);
668         else
669                 return NULL;
670 }
671
672 /**
673  * Show active/inactive status for OST found by lod_osts_seq_next().
674  *
675  * \param[in] m         seq file
676  * \param[in] v         unused for single entry
677  *
678  * \retval 0            on success
679  * \retval negative     error code if failed
680  */
681 static int lod_osts_seq_show(struct seq_file *p, void *v)
682 {
683         struct obd_device   *obd = p->private;
684         struct lod_ost_desc *ost_desc = v;
685         struct lod_device   *lod;
686         int                  idx, rc, active;
687         struct dt_device    *next;
688         struct obd_statfs    sfs;
689
690         LASSERT(obd->obd_lu_dev);
691         lod = lu2lod_dev(obd->obd_lu_dev);
692
693         idx = ost_desc->ltd_index;
694         next = OST_TGT(lod,idx)->ltd_ost;
695         if (next == NULL)
696                 return -EINVAL;
697
698         /* XXX: should be non-NULL env, but it's very expensive */
699         active = 1;
700         rc = dt_statfs(NULL, next, &sfs);
701         if (rc == -ENOTCONN) {
702                 active = 0;
703                 rc = 0;
704         } else if (rc)
705                 return rc;
706
707         seq_printf(p, "%d: %s %sACTIVE\n", idx,
708                    obd_uuid2str(&ost_desc->ltd_uuid),
709                    active ? "" : "IN");
710         return 0;
711 }
712
713 static const struct seq_operations lod_osts_sops = {
714         .start  = lod_osts_seq_start,
715         .stop   = lod_osts_seq_stop,
716         .next   = lod_osts_seq_next,
717         .show   = lod_osts_seq_show,
718 };
719
720 static int lod_osts_seq_open(struct inode *inode, struct file *file)
721 {
722         struct seq_file *seq;
723         int rc;
724
725         rc = seq_open(file, &lod_osts_sops);
726         if (rc)
727                 return rc;
728
729         seq = file->private_data;
730         seq->private = PDE_DATA(inode);
731         return 0;
732 }
733
734 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_blksize);
735 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytestotal);
736 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytesfree);
737 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytesavail);
738 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filestotal);
739 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filesfree);
740
741 /**
742  * Show whether special failout mode for testing is enabled or not.
743  *
744  * \param[in] m         seq file
745  * \param[in] v         unused for single entry
746  *
747  * \retval 0            on success
748  * \retval negative     error code if failed
749  */
750 static int lod_lmv_failout_seq_show(struct seq_file *m, void *v)
751 {
752         struct obd_device *dev = m->private;
753         struct lod_device *lod;
754
755         LASSERT(dev != NULL);
756         lod = lu2lod_dev(dev->obd_lu_dev);
757
758         seq_printf(m, "%d\n", lod->lod_lmv_failout ? 1 : 0);
759         return 0;
760 }
761
762 /**
763  * Enable/disable a special failout mode for testing.
764  *
765  * This determines whether the LMV will try to continue processing a striped
766  * directory even if it has a (partly) corrupted entry in the master directory,
767  * or if it will abort upon finding a corrupted slave directory entry.
768  *
769  * \param[in] file      proc file
770  * \param[in] buffer    string: 0 or non-zero to disable or enable LMV failout
771  * \param[in] count     @buffer length
772  * \param[in] off       unused for single entry
773  *
774  * \retval @count       on success
775  * \retval negative     error code if failed
776  */
777 static ssize_t
778 lod_lmv_failout_seq_write(struct file *file, const char __user *buffer,
779                           size_t count, loff_t *off)
780 {
781         struct seq_file *m = file->private_data;
782         struct obd_device *dev = m->private;
783         struct lod_device *lod;
784         __s64 val = 0;
785         int rc;
786
787         LASSERT(dev != NULL);
788         lod = lu2lod_dev(dev->obd_lu_dev);
789
790         rc = lprocfs_str_to_s64(buffer, count, &val);
791         if (rc)
792                 return rc;
793
794         lod->lod_lmv_failout = !!val;
795
796         return count;
797 }
798 LPROC_SEQ_FOPS(lod_lmv_failout);
799
800 static struct lprocfs_vars lprocfs_lod_obd_vars[] = {
801         { .name =       "stripesize",
802           .fops =       &lod_stripesize_fops    },
803         { .name =       "stripeoffset",
804           .fops =       &lod_stripeoffset_fops  },
805         { .name =       "stripecount",
806           .fops =       &lod_stripecount_fops   },
807         { .name =       "stripetype",
808           .fops =       &lod_stripetype_fops    },
809         { .name =       "numobd",
810           .fops =       &lod_numobd_fops        },
811         { .name =       "activeobd",
812           .fops =       &lod_activeobd_fops     },
813         { .name =       "desc_uuid",
814           .fops =       &lod_desc_uuid_fops     },
815         { .name =       "qos_prio_free",
816           .fops =       &lod_qos_priofree_fops  },
817         { .name =       "qos_threshold_rr",
818           .fops =       &lod_qos_thresholdrr_fops },
819         { .name =       "qos_maxage",
820           .fops =       &lod_qos_maxage_fops    },
821         { .name =       "lmv_failout",
822           .fops =       &lod_lmv_failout_fops   },
823         {
824           .name = "dom_stripesize",
825           .fops = &lod_dom_stripesize_fops
826         },
827         { NULL }
828 };
829
830 static struct lprocfs_vars lprocfs_lod_osd_vars[] = {
831         { .name = "blocksize",   .fops = &lod_dt_blksize_fops },
832         { .name = "kbytestotal", .fops = &lod_dt_kbytestotal_fops },
833         { .name = "kbytesfree",  .fops = &lod_dt_kbytesfree_fops },
834         { .name = "kbytesavail", .fops = &lod_dt_kbytesavail_fops },
835         { .name = "filestotal",  .fops = &lod_dt_filestotal_fops },
836         { .name = "filesfree",   .fops = &lod_dt_filesfree_fops },
837         { .name = NULL }
838 };
839
840 static const struct file_operations lod_proc_target_fops = {
841         .owner   = THIS_MODULE,
842         .open    = lod_osts_seq_open,
843         .read    = seq_read,
844         .llseek  = seq_lseek,
845         .release = lprocfs_seq_release,
846 };
847
848 /**
849  * Initialize procfs entries for LOD.
850  *
851  * \param[in] lod       LOD device
852  *
853  * \retval 0            on success
854  * \retval negative     error code if failed
855  */
856 int lod_procfs_init(struct lod_device *lod)
857 {
858         struct obd_device       *obd = lod2obd(lod);
859         struct proc_dir_entry   *lov_proc_dir = NULL;
860         struct obd_type         *type;
861         int                      rc;
862
863         obd->obd_vars = lprocfs_lod_obd_vars;
864         rc = lprocfs_obd_setup(obd, true);
865         if (rc) {
866                 CERROR("%s: cannot setup procfs entry: %d\n",
867                        obd->obd_name, rc);
868                 RETURN(rc);
869         }
870
871         rc = lprocfs_add_vars(obd->obd_proc_entry, lprocfs_lod_osd_vars,
872                               &lod->lod_dt_dev);
873         if (rc) {
874                 CERROR("%s: cannot setup procfs entry: %d\n",
875                        obd->obd_name, rc);
876                 GOTO(out, rc);
877         }
878
879         rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
880                                 0444, &lod_proc_target_fops, obd);
881         if (rc) {
882                 CWARN("%s: Error adding the target_obd file %d\n",
883                       obd->obd_name, rc);
884                 GOTO(out, rc);
885         }
886
887         lod->lod_pool_proc_entry = lprocfs_register("pools",
888                                                     obd->obd_proc_entry,
889                                                     NULL, NULL);
890         if (IS_ERR(lod->lod_pool_proc_entry)) {
891                 rc = PTR_ERR(lod->lod_pool_proc_entry);
892                 lod->lod_pool_proc_entry = NULL;
893                 CWARN("%s: Failed to create pool proc file: %d\n",
894                       obd->obd_name, rc);
895                 GOTO(out, rc);
896         }
897
898         /* If the real LOV is present which is the case for setups
899          * with both server and clients on the same node then use
900          * the LOV's proc root */
901         type = class_search_type(LUSTRE_LOV_NAME);
902         if (type != NULL && type->typ_procroot != NULL)
903                 lov_proc_dir = type->typ_procroot;
904         else
905                 lov_proc_dir = obd->obd_type->typ_procsym;
906
907         if (lov_proc_dir == NULL)
908                 RETURN(0);
909
910         /* for compatibility we link old procfs's LOV entries to lod ones */
911         lod->lod_symlink = lprocfs_add_symlink(obd->obd_name, lov_proc_dir,
912                                                "../lod/%s", obd->obd_name);
913         if (lod->lod_symlink == NULL)
914                 CERROR("cannot create LOV symlink for /proc/fs/lustre/lod/%s\n",
915                        obd->obd_name);
916         RETURN(0);
917
918 out:
919         lprocfs_obd_cleanup(obd);
920
921         return rc;
922 }
923
924 /**
925  * Cleanup procfs entries registred for LOD.
926  *
927  * \param[in] lod       LOD device
928  */
929 void lod_procfs_fini(struct lod_device *lod)
930 {
931         struct obd_device *obd = lod2obd(lod);
932
933         if (lod->lod_symlink != NULL) {
934                 lprocfs_remove(&lod->lod_symlink);
935                 lod->lod_symlink = NULL;
936         }
937
938         if (lod->lod_pool_proc_entry != NULL) {
939                 lprocfs_remove(&lod->lod_pool_proc_entry);
940                 lod->lod_pool_proc_entry = NULL;
941         }
942
943         lprocfs_obd_cleanup(obd);
944 }
945
946 #endif /* CONFIG_PROC_FS */
947