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