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