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