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