Whamcloud - gitweb
f748010681316f8e313faa09fcabaed062868e0e
[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         if (lcfg == NULL)
518                 return -ENOMEM;
519
520         lod_getref(&lod->lod_ost_descs);
521         lod_foreach_ost(lod, i) {
522                 next = &OST_TGT(lod,i)->ltd_ost->dd_lu_dev;
523                 rc = next->ld_ops->ldo_process_config(NULL, next, lcfg);
524                 if (rc)
525                         CERROR("can't set maxage on #%d: %d\n", i, rc);
526         }
527         lod_putref(lod, &lod->lod_ost_descs);
528         lustre_cfg_free(lcfg);
529
530         return count;
531 }
532 LPROC_SEQ_FOPS(lod_qos_maxage);
533
534 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos)
535 {
536         struct obd_device *dev = p->private;
537         struct lod_device *lod;
538
539         LASSERT(dev != NULL);
540         lod = lu2lod_dev(dev->obd_lu_dev);
541
542         lod_getref(&lod->lod_ost_descs); /* released in lod_osts_seq_stop */
543         if (*pos >= lod->lod_ost_bitmap->size)
544                 return NULL;
545
546         *pos = find_next_bit(lod->lod_ost_bitmap->data,
547                                  lod->lod_ost_bitmap->size, *pos);
548         if (*pos < lod->lod_ost_bitmap->size)
549                 return OST_TGT(lod,*pos);
550         else
551                 return NULL;
552 }
553
554 static void lod_osts_seq_stop(struct seq_file *p, void *v)
555 {
556         struct obd_device *dev = p->private;
557         struct lod_device *lod;
558
559         LASSERT(dev != NULL);
560         lod = lu2lod_dev(dev->obd_lu_dev);
561         lod_putref(lod, &lod->lod_ost_descs);
562 }
563
564 static void *lod_osts_seq_next(struct seq_file *p, void *v, loff_t *pos)
565 {
566         struct obd_device *dev = p->private;
567         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
568
569         if (*pos >= lod->lod_ost_bitmap->size - 1)
570                 return NULL;
571
572         *pos = find_next_bit(lod->lod_ost_bitmap->data,
573                                  lod->lod_ost_bitmap->size, *pos + 1);
574         if (*pos < lod->lod_ost_bitmap->size)
575                 return OST_TGT(lod,*pos);
576         else
577                 return NULL;
578 }
579
580 /**
581  * Show active/inactive status for OST found by lod_osts_seq_next().
582  *
583  * \param[in] m         seq file
584  * \param[in] v         unused for single entry
585  *
586  * \retval 0            on success
587  * \retval negative     error code if failed
588  */
589 static int lod_osts_seq_show(struct seq_file *p, void *v)
590 {
591         struct obd_device   *obd = p->private;
592         struct lod_ost_desc *ost_desc = v;
593         struct lod_device   *lod;
594         int                  idx, rc, active;
595         struct dt_device    *next;
596         struct obd_statfs    sfs;
597
598         LASSERT(obd->obd_lu_dev);
599         lod = lu2lod_dev(obd->obd_lu_dev);
600
601         idx = ost_desc->ltd_index;
602         next = OST_TGT(lod,idx)->ltd_ost;
603         if (next == NULL)
604                 return -EINVAL;
605
606         /* XXX: should be non-NULL env, but it's very expensive */
607         active = 1;
608         rc = dt_statfs(NULL, next, &sfs);
609         if (rc == -ENOTCONN) {
610                 active = 0;
611                 rc = 0;
612         } else if (rc)
613                 return rc;
614
615         return seq_printf(p, "%d: %s %sACTIVE\n", idx,
616                           obd_uuid2str(&ost_desc->ltd_uuid),
617                           active ? "" : "IN");
618 }
619
620 static const struct seq_operations lod_osts_sops = {
621         .start  = lod_osts_seq_start,
622         .stop   = lod_osts_seq_stop,
623         .next   = lod_osts_seq_next,
624         .show   = lod_osts_seq_show,
625 };
626
627 static int lod_osts_seq_open(struct inode *inode, struct file *file)
628 {
629         struct seq_file *seq;
630         int rc;
631
632         rc = seq_open(file, &lod_osts_sops);
633         if (rc)
634                 return rc;
635
636         seq = file->private_data;
637         seq->private = PDE_DATA(inode);
638         return 0;
639 }
640
641 LPROC_SEQ_FOPS_RO_TYPE(lod, uuid);
642
643 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_blksize);
644 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytestotal);
645 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytesfree);
646 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytesavail);
647 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filestotal);
648 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filesfree);
649
650 /**
651  * Show whether special failout mode for testing is enabled or not.
652  *
653  * \param[in] m         seq file
654  * \param[in] v         unused for single entry
655  *
656  * \retval 0            on success
657  * \retval negative     error code if failed
658  */
659 static int lod_lmv_failout_seq_show(struct seq_file *m, void *v)
660 {
661         struct obd_device *dev = m->private;
662         struct lod_device *lod;
663
664         LASSERT(dev != NULL);
665         lod = lu2lod_dev(dev->obd_lu_dev);
666
667         return seq_printf(m, "%d\n", lod->lod_lmv_failout ? 1 : 0);
668 }
669
670 /**
671  * Enable/disable a special failout mode for testing.
672  *
673  * This determines whether the LMV will try to continue processing a striped
674  * directory even if it has a (partly) corrupted entry in the master directory,
675  * or if it will abort upon finding a corrupted slave directory entry.
676  *
677  * \param[in] file      proc file
678  * \param[in] buffer    string: 0 or non-zero to disable or enable LMV failout
679  * \param[in] count     @buffer length
680  * \param[in] off       unused for single entry
681  *
682  * \retval @count       on success
683  * \retval negative     error code if failed
684  */
685 static ssize_t
686 lod_lmv_failout_seq_write(struct file *file, const char *buffer,
687                           size_t count, loff_t *off)
688 {
689         struct seq_file         *m      = file->private_data;
690         struct obd_device       *dev    = m->private;
691         struct lod_device       *lod;
692         int                      val    = 0;
693         int                      rc;
694
695         LASSERT(dev != NULL);
696         lod = lu2lod_dev(dev->obd_lu_dev);
697
698         rc = lprocfs_write_helper(buffer, count, &val);
699         if (rc != 0)
700                 return rc;
701
702         if (val != 0)
703                 lod->lod_lmv_failout = 1;
704         else
705                 lod->lod_lmv_failout = 0;
706
707         return count;
708 }
709 LPROC_SEQ_FOPS(lod_lmv_failout);
710
711 static struct lprocfs_seq_vars lprocfs_lod_obd_vars[] = {
712         { .name =       "uuid",
713           .fops =       &lod_uuid_fops          },
714         { .name =       "stripesize",
715           .fops =       &lod_stripesize_fops    },
716         { .name =       "stripeoffset",
717           .fops =       &lod_stripeoffset_fops  },
718         { .name =       "stripecount",
719           .fops =       &lod_stripecount_fops   },
720         { .name =       "stripetype",
721           .fops =       &lod_stripetype_fops    },
722         { .name =       "numobd",
723           .fops =       &lod_numobd_fops        },
724         { .name =       "activeobd",
725           .fops =       &lod_activeobd_fops     },
726         { .name =       "desc_uuid",
727           .fops =       &lod_desc_uuid_fops     },
728         { .name =       "qos_prio_free",
729           .fops =       &lod_qos_priofree_fops  },
730         { .name =       "qos_threshold_rr",
731           .fops =       &lod_qos_thresholdrr_fops },
732         { .name =       "qos_maxage",
733           .fops =       &lod_qos_maxage_fops    },
734         { .name =       "lmv_failout",
735           .fops =       &lod_lmv_failout_fops   },
736         { 0 }
737 };
738
739 static struct lprocfs_seq_vars lprocfs_lod_osd_vars[] = {
740         { "blocksize",          &lod_dt_blksize_fops            },
741         { "kbytestotal",        &lod_dt_kbytestotal_fops        },
742         { "kbytesfree",         &lod_dt_kbytesfree_fops         },
743         { "kbytesavail",        &lod_dt_kbytesavail_fops        },
744         { "filestotal",         &lod_dt_filestotal_fops         },
745         { "filesfree",          &lod_dt_filesfree_fops          },
746         { 0 }
747 };
748
749 static const struct file_operations lod_proc_target_fops = {
750         .owner   = THIS_MODULE,
751         .open    = lod_osts_seq_open,
752         .read    = seq_read,
753         .llseek  = seq_lseek,
754         .release = lprocfs_seq_release,
755 };
756
757 /**
758  * Initialize procfs entries for LOD.
759  *
760  * \param[in] lod       LOD device
761  *
762  * \retval 0            on success
763  * \retval negative     error code if failed
764  */
765 int lod_procfs_init(struct lod_device *lod)
766 {
767         struct obd_device       *obd = lod2obd(lod);
768         struct proc_dir_entry   *lov_proc_dir = NULL;
769         struct obd_type         *type;
770         int                      rc;
771
772         obd->obd_vars = lprocfs_lod_obd_vars;
773         rc = lprocfs_obd_setup(obd);
774         if (rc) {
775                 CERROR("%s: cannot setup procfs entry: %d\n",
776                        obd->obd_name, rc);
777                 RETURN(rc);
778         }
779
780         rc = lprocfs_seq_add_vars(obd->obd_proc_entry, lprocfs_lod_osd_vars,
781                                   &lod->lod_dt_dev);
782         if (rc) {
783                 CERROR("%s: cannot setup procfs entry: %d\n",
784                        obd->obd_name, rc);
785                 GOTO(out, rc);
786         }
787
788         rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
789                                 0444, &lod_proc_target_fops, obd);
790         if (rc) {
791                 CWARN("%s: Error adding the target_obd file %d\n",
792                       obd->obd_name, rc);
793                 GOTO(out, rc);
794         }
795
796         lod->lod_pool_proc_entry = lprocfs_seq_register("pools",
797                                                         obd->obd_proc_entry,
798                                                         NULL, NULL);
799         if (IS_ERR(lod->lod_pool_proc_entry)) {
800                 rc = PTR_ERR(lod->lod_pool_proc_entry);
801                 lod->lod_pool_proc_entry = NULL;
802                 CWARN("%s: Failed to create pool proc file: %d\n",
803                       obd->obd_name, rc);
804                 GOTO(out, rc);
805         }
806
807         /* If the real LOV is present which is the case for setups
808          * with both server and clients on the same node then use
809          * the LOV's proc root */
810         type = class_search_type(LUSTRE_LOV_NAME);
811         if (type != NULL && type->typ_procroot != NULL)
812                 lov_proc_dir = type->typ_procroot;
813         else
814                 lov_proc_dir = obd->obd_type->typ_procsym;
815
816         if (lov_proc_dir == NULL)
817                 RETURN(0);
818
819         /* for compatibility we link old procfs's LOV entries to lod ones */
820         lod->lod_symlink = lprocfs_add_symlink(obd->obd_name, lov_proc_dir,
821                                                "../lod/%s", obd->obd_name);
822         if (lod->lod_symlink == NULL)
823                 CERROR("cannot create LOV symlink for /proc/fs/lustre/lod/%s\n",
824                        obd->obd_name);
825         RETURN(0);
826
827 out:
828         lprocfs_obd_cleanup(obd);
829
830         return rc;
831 }
832
833 /**
834  * Cleanup procfs entries registred for LOD.
835  *
836  * \param[in] lod       LOD device
837  */
838 void lod_procfs_fini(struct lod_device *lod)
839 {
840         struct obd_device *obd = lod2obd(lod);
841
842         if (lod->lod_symlink != NULL)
843                 lprocfs_remove(&lod->lod_symlink);
844
845         if (lod->lod_pool_proc_entry != NULL) {
846                 lprocfs_remove(&lod->lod_pool_proc_entry);
847                 lod->lod_pool_proc_entry = NULL;
848         }
849
850         lprocfs_obd_cleanup(obd);
851 }
852
853 #endif /* LPROCFS */
854