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