Whamcloud - gitweb
LU-9325 obdclass: make niduuid for lustre_stop_mgc() static
[fs/lustre-release.git] / lustre / lod / lproc_lod.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  */
31 #define DEBUG_SUBSYSTEM S_CLASS
32
33 #include <lprocfs_status.h>
34 #include <obd_class.h>
35 #include <linux/seq_file.h>
36 #include "lod_internal.h"
37 #include <uapi/linux/lustre/lustre_param.h>
38
39 /*
40  * Notice, all the functions below (except for lod_procfs_init() and
41  * lod_procfs_fini()) are not supposed to be used directly. They are
42  * called by Linux kernel's procfs.
43  */
44
45 #ifdef CONFIG_PROC_FS
46
47 static ssize_t dom_stripesize_show(struct kobject *kobj,
48                                    struct attribute *attr,
49                                    char *buf)
50 {
51         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
52         struct lod_device *lod = dt2lod_dev(dt);
53
54         return scnprintf(buf, PAGE_SIZE, "%u\n",
55                          lod->lod_dom_stripesize_max_kb << 10);
56 }
57
58 static inline int dom_stripesize_max_kb_update(struct lod_device *lod,
59                                                __u64 val)
60 {
61         /* 1GB is the limit */
62         if (val > (1ULL << 20))
63                 return -ERANGE;
64
65         if (val > 0) {
66                 if (val < LOD_DOM_MIN_SIZE_KB) {
67                         LCONSOLE_INFO("Increasing provided stripe size to a minimum value %u\n",
68                                       LOD_DOM_MIN_SIZE_KB);
69                         val = LOD_DOM_MIN_SIZE_KB;
70                 } else if (val & (LOD_DOM_MIN_SIZE_KB - 1)) {
71                         val &= ~(LOD_DOM_MIN_SIZE_KB - 1);
72                         LCONSOLE_WARN("Changing provided stripe size to %llu (a multiple of minimum %u)\n",
73                                       val, LOD_DOM_MIN_SIZE_KB);
74                 }
75         }
76         spin_lock(&lod->lod_lsfs_lock);
77         lod->lod_dom_stripesize_max_kb = val;
78         lod_dom_stripesize_recalc(lod);
79         spin_unlock(&lod->lod_lsfs_lock);
80         return 0;
81 }
82
83 static ssize_t dom_stripesize_store(struct kobject *kobj,
84                                     struct attribute *attr,
85                                     const char *buffer, size_t count)
86 {
87         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
88         struct lod_device *lod = dt2lod_dev(dt);
89         u64 val;
90         int rc;
91
92         rc = sysfs_memparse(buffer, count, &val, "B");
93         if (rc < 0)
94                 return rc;
95
96         rc = dom_stripesize_max_kb_update(lod, val >> 10);
97         if (rc)
98                 return rc;
99         return count;
100 }
101
102 /* Old attribute name is still supported */
103 LUSTRE_RW_ATTR(dom_stripesize);
104
105 /**
106  * Show DoM maximum allowed stripe size.
107  */
108 static ssize_t dom_stripesize_max_kb_show(struct kobject *kobj,
109                                           struct attribute *attr,
110                                           char *buf)
111 {
112         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
113         struct lod_device *lod = dt2lod_dev(dt);
114
115         return scnprintf(buf, PAGE_SIZE, "%u\n",
116                          lod->lod_dom_stripesize_max_kb);
117 }
118
119 /**
120  * Set DoM maximum allowed stripe size.
121  */
122 static ssize_t dom_stripesize_max_kb_store(struct kobject *kobj,
123                                            struct attribute *attr,
124                                            const char *buffer, size_t count)
125 {
126         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
127         struct lod_device *lod = dt2lod_dev(dt);
128         u64 val;
129         int rc;
130
131         rc = sysfs_memparse(buffer, count, &val, "KiB");
132         if (rc < 0)
133                 return rc;
134
135         rc = dom_stripesize_max_kb_update(lod, val >> 10);
136         if (rc)
137                 return rc;
138         return count;
139 }
140 LUSTRE_RW_ATTR(dom_stripesize_max_kb);
141
142 /**
143  * Show DoM default stripe size.
144  */
145 static ssize_t dom_stripesize_cur_kb_show(struct kobject *kobj,
146                                           struct attribute *attr,
147                                           char *buf)
148 {
149         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
150         struct lod_device *lod = dt2lod_dev(dt);
151
152         return scnprintf(buf, PAGE_SIZE, "%u\n",
153                          lod->lod_dom_stripesize_cur_kb);
154 }
155
156 LUSTRE_RO_ATTR(dom_stripesize_cur_kb);
157
158 /**
159  * Show DoM threshold.
160  */
161 static ssize_t dom_threshold_free_mb_show(struct kobject *kobj,
162                                           struct attribute *attr, char *buf)
163 {
164         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
165         struct lod_device *lod = dt2lod_dev(dt);
166
167         return scnprintf(buf, PAGE_SIZE, "%llu\n",
168                          lod->lod_dom_threshold_free_mb);
169 }
170
171 /**
172  * Set DoM default stripe size.
173  */
174 static ssize_t dom_threshold_free_mb_store(struct kobject *kobj,
175                                            struct attribute *attr,
176                                            const char *buffer, size_t count)
177 {
178         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
179         struct lod_device *lod = dt2lod_dev(dt);
180         u64 val;
181         int rc;
182         char *pct;
183
184         pct = strnchr(buffer, count, '%');
185         if (pct) {
186                 rc = string_to_size(&val, buffer, pct - buffer);
187                 if (rc < 0)
188                         return rc;
189                 val = mult_frac(lod->lod_lsfs_total_mb,
190                                 min_t(unsigned int, val, 100), 100);
191         } else {
192                 rc = sysfs_memparse(buffer, count, &val, "MiB");
193                 if (rc < 0)
194                         return rc;
195                 val >>= 20;
196         }
197
198         spin_lock(&lod->lod_lsfs_lock);
199         lod->lod_dom_threshold_free_mb = val;
200         lod_dom_stripesize_recalc(lod);
201         spin_unlock(&lod->lod_lsfs_lock);
202
203         return count;
204 }
205
206 LUSTRE_RW_ATTR(dom_threshold_free_mb);
207
208 static ssize_t stripesize_show(struct kobject *kobj, struct attribute *attr,
209                                char *buf)
210 {
211         struct dt_device *dt = container_of(kobj, struct dt_device,
212                                             dd_kobj);
213         struct lod_device *lod = dt2lod_dev(dt);
214
215         return scnprintf(buf, PAGE_SIZE, "%llu\n",
216                          lod->lod_ost_descs.ltd_lov_desc.ld_default_stripe_size);
217 }
218
219 static ssize_t stripesize_store(struct kobject *kobj, struct attribute *attr,
220                                 const char *buffer, size_t count)
221 {
222         struct dt_device *dt = container_of(kobj, struct dt_device,
223                                             dd_kobj);
224         struct lod_device *lod = dt2lod_dev(dt);
225         u64 val;
226         int rc;
227
228         rc = sysfs_memparse(buffer, count, &val, "B");
229         if (rc < 0)
230                 return rc;
231
232         lod_fix_desc_stripe_size(&val);
233         lod->lod_ost_descs.ltd_lov_desc.ld_default_stripe_size = val;
234
235         return count;
236 }
237
238 LUSTRE_RW_ATTR(stripesize);
239
240 /**
241  * Show default stripe offset.
242  */
243 static ssize_t stripeoffset_show(struct kobject *kobj, struct attribute *attr,
244                                  char *buf)
245 {
246         struct dt_device *dt = container_of(kobj, struct dt_device,
247                                             dd_kobj);
248         struct lod_device *lod = dt2lod_dev(dt);
249
250         return scnprintf(buf, PAGE_SIZE, "%lld\n",
251                 lod->lod_ost_descs.ltd_lov_desc.ld_default_stripe_offset);
252 }
253
254 /**
255  * Set default stripe offset.
256  *
257  * Usually contains -1 allowing Lustre to balance objects among OST
258  * otherwise may cause severe OST imbalance.
259  */
260 static ssize_t stripeoffset_store(struct kobject *kobj,
261                                     struct attribute *attr,
262                                     const char *buffer, size_t count)
263 {
264         struct dt_device *dt = container_of(kobj, struct dt_device,
265                                             dd_kobj);
266         struct lod_device *lod = dt2lod_dev(dt);
267         long val;
268         int rc;
269
270         rc = kstrtol(buffer, 0, &val);
271         if (rc)
272                 return rc;
273
274         if (val < -1 || val > LOV_MAX_STRIPE_COUNT)
275                 return -ERANGE;
276
277         lod->lod_ost_descs.ltd_lov_desc.ld_default_stripe_offset = val;
278
279         return count;
280 }
281
282 LUSTRE_RW_ATTR(stripeoffset);
283
284 static ssize_t max_stripecount_show(struct kobject *kobj,
285                                     struct attribute *attr, char *buf)
286 {
287         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
288         struct lod_device *lod = dt2lod_dev(dt);
289
290         return scnprintf(buf, PAGE_SIZE, "%u\n", lod->lod_max_stripecount);
291 }
292
293 static ssize_t max_stripecount_store(struct kobject *kobj,
294                                      struct attribute *attr,
295                                      const char *buffer, size_t count)
296 {
297         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
298         struct lod_device *lod = dt2lod_dev(dt);
299         long val;
300         int rc;
301
302         rc = kstrtol(buffer, 0, &val);
303         if (rc)
304                 return rc;
305
306         if (val < 0 || val > LOV_MAX_STRIPE_COUNT)
307                 return -ERANGE;
308
309         lod->lod_max_stripecount = val;
310
311         return count;
312 }
313
314 LUSTRE_RW_ATTR(max_stripecount);
315
316 /**
317  * Show default striping pattern (LOV_PATTERN_*).
318  */
319 static ssize_t __stripetype_show(struct kobject *kobj, struct attribute *attr,
320                                  char *buf, bool is_mdt)
321 {
322         struct dt_device *dt = container_of(kobj, struct dt_device,
323                                             dd_kobj);
324         struct lod_device *lod = dt2lod_dev(dt);
325         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
326                                             &lod->lod_ost_descs;
327
328         return scnprintf(buf, PAGE_SIZE, "%u\n", ltd->ltd_lov_desc.ld_pattern);
329 }
330
331 static ssize_t mdt_stripetype_show(struct kobject *kobj, struct attribute *attr,
332                                    char *buf)
333 {
334         return __stripetype_show(kobj, attr, buf, true);
335 }
336
337 static ssize_t stripetype_show(struct kobject *kobj, struct attribute *attr,
338                                char *buf)
339 {
340         return __stripetype_show(kobj, attr, buf, false);
341 }
342
343 /**
344  * Set default striping pattern (a number, not a human-readable string).
345  */
346 static ssize_t __stripetype_store(struct kobject *kobj, struct attribute *attr,
347                                   const char *buffer, size_t count, bool is_mdt)
348 {
349         struct dt_device *dt = container_of(kobj, struct dt_device,
350                                             dd_kobj);
351         struct lod_device *lod = dt2lod_dev(dt);
352         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
353                                             &lod->lod_ost_descs;
354         u32 pattern;
355         int rc;
356
357         rc = kstrtouint(buffer, 0, &pattern);
358         if (rc)
359                 return rc;
360
361         if (is_mdt)
362                 lod_fix_lmv_desc_pattern(&pattern);
363         else
364                 lod_fix_desc_pattern(&pattern);
365
366         ltd->ltd_lov_desc.ld_pattern = pattern;
367
368         return count;
369 }
370
371 static ssize_t mdt_stripetype_store(struct kobject *kobj,
372                                     struct attribute *attr, const char *buffer,
373                                     size_t count)
374 {
375         return __stripetype_store(kobj, attr, buffer, count, true);
376 }
377
378 static ssize_t stripetype_store(struct kobject *kobj,
379                                     struct attribute *attr, const char *buffer,
380                                     size_t count)
381 {
382         return __stripetype_store(kobj, attr, buffer, count, false);
383 }
384
385 LUSTRE_RW_ATTR(mdt_stripetype);
386 LUSTRE_RW_ATTR(stripetype);
387
388 /**
389  * Show default number of stripes.
390  */
391 static ssize_t __stripecount_show(struct kobject *kobj, struct attribute *attr,
392                                   char *buf, bool is_mdt)
393 {
394         struct dt_device *dt = container_of(kobj, struct dt_device,
395                                             dd_kobj);
396         struct lod_device *lod = dt2lod_dev(dt);
397         struct lov_desc *desc = is_mdt ? &lod->lod_mdt_descs.ltd_lov_desc :
398                                          &lod->lod_ost_descs.ltd_lov_desc;
399
400         return scnprintf(buf, PAGE_SIZE, "%d\n",
401                          (s16)(desc->ld_default_stripe_count + 1) - 1);
402 }
403
404 static ssize_t mdt_stripecount_show(struct kobject *kobj,
405                                     struct attribute *attr, char *buf)
406 {
407         return __stripecount_show(kobj, attr, buf, true);
408 }
409
410 static ssize_t stripecount_show(struct kobject *kobj, struct attribute *attr,
411                                 char *buf)
412 {
413         return __stripecount_show(kobj, attr, buf, false);
414 }
415
416 /**
417  * Set default number of stripes.
418  */
419 static ssize_t __stripecount_store(struct kobject *kobj, struct attribute *attr,
420                                    const char *buffer, size_t count,
421                                    bool is_mdt)
422 {
423         struct dt_device *dt = container_of(kobj, struct dt_device,
424                                             dd_kobj);
425         struct lod_device *lod = dt2lod_dev(dt);
426         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
427                                             &lod->lod_ost_descs;
428         int stripe_count;
429         int rc;
430
431         rc = kstrtoint(buffer, 0, &stripe_count);
432         if (rc)
433                 return rc;
434
435         if (stripe_count < -1)
436                 return -ERANGE;
437
438         lod_fix_desc_stripe_count(&stripe_count);
439         ltd->ltd_lov_desc.ld_default_stripe_count = stripe_count;
440
441         return count;
442 }
443
444 static ssize_t mdt_stripecount_store(struct kobject *kobj,
445                                      struct attribute *attr,
446                                      const char *buffer, size_t count)
447 {
448         return __stripecount_store(kobj, attr, buffer, count, true);
449 }
450
451 static ssize_t stripecount_store(struct kobject *kobj,
452                                  struct attribute *attr,
453                                  const char *buffer, size_t count)
454 {
455         return __stripecount_store(kobj, attr, buffer, count, false);
456 }
457
458 LUSTRE_RW_ATTR(mdt_stripecount);
459 LUSTRE_RW_ATTR(stripecount);
460
461 /**
462  * Show number of targets.
463  */
464 static ssize_t __numobd_show(struct kobject *kobj, struct attribute *attr,
465                              char *buf, bool is_mdt)
466 {
467         struct dt_device *dt = container_of(kobj, struct dt_device,
468                                             dd_kobj);
469         struct lod_device *lod = dt2lod_dev(dt);
470         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
471                                             &lod->lod_ost_descs;
472
473         return scnprintf(buf, PAGE_SIZE, "%u\n",
474                          ltd->ltd_lov_desc.ld_tgt_count);
475 }
476
477 static ssize_t mdt_numobd_show(struct kobject *kobj, struct attribute *attr,
478                                char *buf)
479 {
480         return __numobd_show(kobj, attr, buf, true);
481 }
482
483 static ssize_t numobd_show(struct kobject *kobj, struct attribute *attr,
484                            char *buf)
485 {
486         return __numobd_show(kobj, attr, buf, false);
487 }
488
489 LUSTRE_RO_ATTR(mdt_numobd);
490 LUSTRE_RO_ATTR(numobd);
491
492 /**
493  * Show number of active targets.
494  */
495 static ssize_t __activeobd_show(struct kobject *kobj, struct attribute *attr,
496                                 char *buf, bool is_mdt)
497 {
498         struct dt_device *dt = container_of(kobj, struct dt_device,
499                                             dd_kobj);
500         struct lod_device *lod = dt2lod_dev(dt);
501         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
502                                             &lod->lod_ost_descs;
503
504         return scnprintf(buf, PAGE_SIZE, "%u\n",
505                          ltd->ltd_lov_desc.ld_active_tgt_count);
506 }
507
508 static ssize_t mdt_activeobd_show(struct kobject *kobj, struct attribute *attr,
509                                   char *buf)
510 {
511         return __activeobd_show(kobj, attr, buf, true);
512 }
513
514 static ssize_t activeobd_show(struct kobject *kobj, struct attribute *attr,
515                               char *buf)
516 {
517         return __activeobd_show(kobj, attr, buf, false);
518 }
519
520 LUSTRE_RO_ATTR(mdt_activeobd);
521 LUSTRE_RO_ATTR(activeobd);
522
523 /**
524  * Show UUID of LOD device.
525  */
526 static ssize_t desc_uuid_show(struct kobject *kobj, struct attribute *attr,
527                               char *buf)
528 {
529         struct dt_device *dt = container_of(kobj, struct dt_device,
530                                             dd_kobj);
531         struct lod_device *lod = dt2lod_dev(dt);
532
533         return scnprintf(buf, PAGE_SIZE, "%s\n",
534                          lod->lod_ost_descs.ltd_lov_desc.ld_uuid.uuid);
535 }
536 LUSTRE_RO_ATTR(desc_uuid);
537
538 /**
539  * Show QoS priority parameter.
540  *
541  * The printed value is a percentage value (0-100%) indicating the priority
542  * of free space compared to performance. 0% means select OSTs equally
543  * regardless of their free space, 100% means select OSTs only by their free
544  * space even if it results in very imbalanced load on the OSTs.
545  */
546 static ssize_t __qos_prio_free_show(struct kobject *kobj,
547                                     struct attribute *attr, char *buf,
548                                     bool is_mdt)
549 {
550         struct dt_device *dt = container_of(kobj, struct dt_device,
551                                             dd_kobj);
552         struct lod_device *lod = dt2lod_dev(dt);
553         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
554                                             &lod->lod_ost_descs;
555
556         return scnprintf(buf, PAGE_SIZE, "%d%%\n",
557                          (ltd->ltd_qos.lq_prio_free * 100 + 255) >> 8);
558 }
559
560 static ssize_t mdt_qos_prio_free_show(struct kobject *kobj,
561                                       struct attribute *attr, char *buf)
562 {
563         return __qos_prio_free_show(kobj, attr, buf, true);
564 }
565
566 static ssize_t qos_prio_free_show(struct kobject *kobj,
567                                   struct attribute *attr, char *buf)
568 {
569         return __qos_prio_free_show(kobj, attr, buf, false);
570 }
571
572 /**
573  * Set QoS free space priority parameter.
574  *
575  * Set the relative priority of free OST space compared to OST load when OSTs
576  * are space imbalanced.  See qos_priofree_show() for description of
577  * this parameter.  See qos_threshold_rr_store() and lq_threshold_rr to
578  * determine what constitutes "space imbalanced" OSTs.
579  */
580 static ssize_t __qos_prio_free_store(struct kobject *kobj,
581                                      struct attribute *attr,
582                                      const char *buffer, size_t count,
583                                      bool is_mdt)
584 {
585         struct dt_device *dt = container_of(kobj, struct dt_device,
586                                             dd_kobj);
587         struct lod_device *lod = dt2lod_dev(dt);
588         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
589                                             &lod->lod_ost_descs;
590         char buf[6], *tmp;
591         unsigned int val;
592         int rc;
593
594         /* "100%\n\0" should be largest string */
595         if (count >= sizeof(buf))
596                 return -ERANGE;
597
598         strncpy(buf, buffer, sizeof(buf));
599         buf[sizeof(buf) - 1] = '\0';
600         tmp = strchr(buf, '%');
601         if (tmp)
602                 *tmp = '\0';
603
604         rc = kstrtouint(buf, 0, &val);
605         if (rc)
606                 return rc;
607
608         if (val > 100)
609                 return -EINVAL;
610
611         ltd->ltd_qos.lq_prio_free = (val << 8) / 100;
612         set_bit(LQ_DIRTY, &ltd->ltd_qos.lq_flags);
613         set_bit(LQ_RESET, &ltd->ltd_qos.lq_flags);
614
615         return count;
616 }
617
618 static ssize_t mdt_qos_prio_free_store(struct kobject *kobj,
619                                        struct attribute *attr,
620                                        const char *buffer, size_t count)
621 {
622         return __qos_prio_free_store(kobj, attr, buffer, count, true);
623 }
624
625 static ssize_t qos_prio_free_store(struct kobject *kobj, struct attribute *attr,
626                                    const char *buffer, size_t count)
627 {
628         return __qos_prio_free_store(kobj, attr, buffer, count, false);
629 }
630
631 LUSTRE_RW_ATTR(mdt_qos_prio_free);
632 LUSTRE_RW_ATTR(qos_prio_free);
633
634 /**
635  * Show threshold for "same space on all OSTs" rule.
636  */
637 static ssize_t __qos_threshold_rr_show(struct kobject *kobj,
638                                        struct attribute *attr, char *buf,
639                                        bool is_mdt)
640 {
641         struct dt_device *dt = container_of(kobj, struct dt_device,
642                                             dd_kobj);
643         struct lod_device *lod = dt2lod_dev(dt);
644         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
645                                             &lod->lod_ost_descs;
646
647         return scnprintf(buf, PAGE_SIZE, "%d%%\n",
648                          (ltd->ltd_qos.lq_threshold_rr * 100 + 255) >> 8);
649 }
650
651 static ssize_t mdt_qos_threshold_rr_show(struct kobject *kobj,
652                                          struct attribute *attr, char *buf)
653 {
654         return __qos_threshold_rr_show(kobj, attr, buf, true);
655 }
656
657 static ssize_t qos_threshold_rr_show(struct kobject *kobj,
658                                      struct attribute *attr, char *buf)
659 {
660         return __qos_threshold_rr_show(kobj, attr, buf, false);
661 }
662
663 /**
664  * Set threshold for "same space on all OSTs" rule.
665  *
666  * This sets the maximum percentage difference of free space between the most
667  * full and most empty OST in the currently available OSTs. If this percentage
668  * is exceeded, use the QoS allocator to select OSTs based on their available
669  * space so that more full OSTs are chosen less often, otherwise use the
670  * round-robin allocator for efficiency and performance.
671  */
672 static ssize_t __qos_threshold_rr_store(struct kobject *kobj,
673                                         struct attribute *attr,
674                                         const char *buffer, size_t count,
675                                         bool is_mdt)
676 {
677         struct dt_device *dt = container_of(kobj, struct dt_device,
678                                             dd_kobj);
679         struct lod_device *lod = dt2lod_dev(dt);
680         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
681                                             &lod->lod_ost_descs;
682         char buf[6], *tmp;
683         unsigned int val;
684         int rc;
685
686         /* "100%\n\0" should be largest string */
687         if (count >= sizeof(buf))
688                 return -ERANGE;
689
690         strncpy(buf, buffer, sizeof(buf));
691         buf[sizeof(buf) - 1] = '\0';
692         tmp = strchr(buf, '%');
693         if (tmp)
694                 *tmp = '\0';
695
696         rc = kstrtouint(buf, 0, &val);
697         if (rc)
698                 return rc;
699
700         if (val > 100)
701                 return -EINVAL;
702         ltd->ltd_qos.lq_threshold_rr = (val << 8) / 100;
703         set_bit(LQ_DIRTY, &ltd->ltd_qos.lq_flags);
704
705         return count;
706 }
707
708 static ssize_t mdt_qos_threshold_rr_store(struct kobject *kobj,
709                                           struct attribute *attr,
710                                           const char *buffer, size_t count)
711 {
712         return __qos_threshold_rr_store(kobj, attr, buffer, count, true);
713 }
714
715 static ssize_t qos_threshold_rr_store(struct kobject *kobj,
716                                       struct attribute *attr,
717                                       const char *buffer, size_t count)
718 {
719         return __qos_threshold_rr_store(kobj, attr, buffer, count, false);
720 }
721
722 LUSTRE_RW_ATTR(mdt_qos_threshold_rr);
723 LUSTRE_RW_ATTR(qos_threshold_rr);
724
725 /**
726  * Show expiration period used to refresh cached statfs data, which
727  * is used to implement QoS/RR striping allocation algorithm.
728  */
729 static ssize_t __qos_maxage_show(struct kobject *kobj, struct attribute *attr,
730                                  char *buf, bool is_mdt)
731 {
732         struct dt_device *dt = container_of(kobj, struct dt_device,
733                                             dd_kobj);
734         struct lod_device *lod = dt2lod_dev(dt);
735         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
736                                             &lod->lod_ost_descs;
737
738         return scnprintf(buf, PAGE_SIZE, "%u\n",
739                          ltd->ltd_lov_desc.ld_qos_maxage);
740 }
741
742 static ssize_t mdt_qos_maxage_show(struct kobject *kobj, struct attribute *attr,
743                                    char *buf)
744 {
745         return __qos_maxage_show(kobj, attr, buf, true);
746 }
747
748 static ssize_t qos_maxage_show(struct kobject *kobj, struct attribute *attr,
749                                char *buf)
750 {
751         return __qos_maxage_show(kobj, attr, buf, true);
752 }
753
754 /**
755  * Set expiration period used to refresh cached statfs data.
756  */
757 static ssize_t __qos_maxage_store(struct kobject *kobj, struct attribute *attr,
758                                   const char *buffer, size_t count, bool is_mdt)
759 {
760         struct dt_device *dt = container_of(kobj, struct dt_device,
761                                             dd_kobj);
762         struct lod_device *lod = dt2lod_dev(dt);
763         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
764                                             &lod->lod_ost_descs;
765         struct lustre_cfg_bufs bufs;
766         struct lu_device *next;
767         struct lustre_cfg *lcfg;
768         char str[32];
769         struct lu_tgt_desc *tgt;
770         int rc;
771         u32 val;
772
773         rc = kstrtouint(buffer, 0, &val);
774         if (rc)
775                 return rc;
776
777         if (val <= 0)
778                 return -EINVAL;
779
780         ltd->ltd_lov_desc.ld_qos_maxage = val;
781
782         /*
783          * propogate the value down to OSPs
784          */
785         lustre_cfg_bufs_reset(&bufs, NULL);
786         snprintf(str, 32, "%smaxage=%u", PARAM_OSP, val);
787         lustre_cfg_bufs_set_string(&bufs, 1, str);
788         OBD_ALLOC(lcfg, lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen));
789         if (lcfg == NULL)
790                 return -ENOMEM;
791         lustre_cfg_init(lcfg, LCFG_PARAM, &bufs);
792
793         lod_getref(ltd);
794         ltd_foreach_tgt(ltd, tgt) {
795                 next = &tgt->ltd_tgt->dd_lu_dev;
796                 rc = next->ld_ops->ldo_process_config(NULL, next, lcfg);
797                 if (rc)
798                         CERROR("can't set maxage on #%d: %d\n",
799                                tgt->ltd_index, rc);
800         }
801         lod_putref(lod, ltd);
802         OBD_FREE(lcfg, lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens));
803
804         return count;
805 }
806
807 static ssize_t mdt_qos_maxage_store(struct kobject *kobj,
808                                     struct attribute *attr,
809                                     const char *buffer, size_t count)
810 {
811         return __qos_maxage_store(kobj, attr, buffer, count, true);
812 }
813
814 static ssize_t qos_maxage_store(struct kobject *kobj, struct attribute *attr,
815                                 const char *buffer, size_t count)
816 {
817         return __qos_maxage_store(kobj, attr, buffer, count, false);
818 }
819
820 LUSTRE_RW_ATTR(mdt_qos_maxage);
821 LUSTRE_RW_ATTR(qos_maxage);
822
823 static void *lod_tgts_seq_start(struct seq_file *p, loff_t *pos, bool is_mdt)
824 {
825         struct obd_device *obd = p->private;
826         struct lod_device *lod = lu2lod_dev(obd->obd_lu_dev);
827         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
828                                             &lod->lod_ost_descs;
829
830         LASSERT(obd != NULL);
831
832         lod_getref(ltd); /* released in lod_tgts_seq_stop */
833         if (*pos >= ltd->ltd_tgts_size)
834                 return NULL;
835
836         *pos = find_next_bit(ltd->ltd_tgt_bitmap,
837                              ltd->ltd_tgts_size, *pos);
838         if (*pos < ltd->ltd_tgts_size)
839                 return LTD_TGT(ltd, *pos);
840         else
841                 return NULL;
842 }
843
844 static void *lod_mdts_seq_start(struct seq_file *p, loff_t *pos)
845 {
846         return lod_tgts_seq_start(p, pos, true);
847 }
848
849 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos)
850 {
851         return lod_tgts_seq_start(p, pos, false);
852 }
853
854 static void lod_tgts_seq_stop(struct seq_file *p, void *v, bool is_mdt)
855 {
856         struct obd_device *obd = p->private;
857         struct lod_device *lod = lu2lod_dev(obd->obd_lu_dev);
858         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
859                                             &lod->lod_ost_descs;
860
861         LASSERT(obd != NULL);
862         lod_putref(lod, ltd);
863 }
864
865 static void lod_mdts_seq_stop(struct seq_file *p, void *v)
866 {
867         lod_tgts_seq_stop(p, v, true);
868 }
869
870 static void lod_osts_seq_stop(struct seq_file *p, void *v)
871 {
872         lod_tgts_seq_stop(p, v, false);
873 }
874
875 static void *lod_tgts_seq_next(struct seq_file *p, void *v, loff_t *pos,
876                                bool is_mdt)
877 {
878         struct obd_device *obd = p->private;
879         struct lod_device *lod = lu2lod_dev(obd->obd_lu_dev);
880         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
881                                             &lod->lod_ost_descs;
882
883         (*pos)++;
884         if (*pos > ltd->ltd_tgts_size - 1)
885                 return NULL;
886
887         *pos = find_next_bit(ltd->ltd_tgt_bitmap,
888                              ltd->ltd_tgts_size, *pos);
889         if (*pos < ltd->ltd_tgts_size)
890                 return LTD_TGT(ltd, *pos);
891         else
892                 return NULL;
893 }
894
895 static void *lod_mdts_seq_next(struct seq_file *p, void *v, loff_t *pos)
896 {
897         return lod_tgts_seq_next(p, v, pos, true);
898 }
899
900 static void *lod_osts_seq_next(struct seq_file *p, void *v, loff_t *pos)
901 {
902         return lod_tgts_seq_next(p, v, pos, false);
903 }
904
905 /**
906  * Show active/inactive status for OST found by lod_osts_seq_next().
907  *
908  * \param[in] m         seq file
909  * \param[in] v         unused for single entry
910  *
911  * \retval 0            on success
912  * \retval negative     error code if failed
913  */
914 static int lod_tgts_seq_show(struct seq_file *p, void *v)
915 {
916         struct obd_device *obd = p->private;
917         struct lu_tgt_desc *tgt = v;
918         struct dt_device *next;
919         int rc, active;
920
921         LASSERT(obd->obd_lu_dev);
922
923         next = tgt->ltd_tgt;
924         if (!next)
925                 return -EINVAL;
926
927         /* XXX: should be non-NULL env, but it's very expensive */
928         active = 1;
929         rc = dt_statfs(NULL, next, &tgt->ltd_statfs);
930         if (rc == -ENOTCONN) {
931                 active = 0;
932                 rc = 0;
933         } else if (rc)
934                 return rc;
935
936         seq_printf(p, "%d: %s %sACTIVE\n", tgt->ltd_index,
937                    obd_uuid2str(&tgt->ltd_uuid),
938                    active ? "" : "IN");
939         return 0;
940 }
941
942 static const struct seq_operations lod_mdts_sops = {
943         .start  = lod_mdts_seq_start,
944         .stop   = lod_mdts_seq_stop,
945         .next   = lod_mdts_seq_next,
946         .show   = lod_tgts_seq_show,
947 };
948
949 static const struct seq_operations lod_osts_sops = {
950         .start  = lod_osts_seq_start,
951         .stop   = lod_osts_seq_stop,
952         .next   = lod_osts_seq_next,
953         .show   = lod_tgts_seq_show,
954 };
955
956 static int lod_mdts_seq_open(struct inode *inode, struct file *file)
957 {
958         struct seq_file *seq;
959         int rc;
960
961         rc = seq_open(file, &lod_mdts_sops);
962         if (rc)
963                 return rc;
964
965         seq = file->private_data;
966         seq->private = PDE_DATA(inode);
967         return 0;
968 }
969
970 static int lod_osts_seq_open(struct inode *inode, struct file *file)
971 {
972         struct seq_file *seq;
973         int rc;
974
975         rc = seq_open(file, &lod_osts_sops);
976         if (rc)
977                 return rc;
978
979         seq = file->private_data;
980         seq->private = PDE_DATA(inode);
981         return 0;
982 }
983
984 /**
985  * Show whether special failout mode for testing is enabled or not.
986  */
987 static ssize_t lmv_failout_show(struct kobject *kobj, struct attribute *attr,
988                                 char *buf)
989 {
990         struct dt_device *dt = container_of(kobj, struct dt_device,
991                                             dd_kobj);
992         struct lod_device *lod = dt2lod_dev(dt);
993
994         return scnprintf(buf, PAGE_SIZE, "%d\n", lod->lod_lmv_failout ? 1 : 0);
995 }
996
997 /**
998  * Enable/disable a special failout mode for testing.
999  *
1000  * This determines whether the LMV will try to continue processing a striped
1001  * directory even if it has a (partly) corrupted entry in the master directory,
1002  * or if it will abort upon finding a corrupted slave directory entry.
1003  */
1004 static ssize_t lmv_failout_store(struct kobject *kobj, struct attribute *attr,
1005                                  const char *buffer, size_t count)
1006 {
1007         struct dt_device *dt = container_of(kobj, struct dt_device,
1008                                             dd_kobj);
1009         struct lod_device *lod = dt2lod_dev(dt);
1010         bool val = 0;
1011         int rc;
1012
1013         rc = kstrtobool(buffer, &val);
1014         if (rc)
1015                 return rc;
1016
1017         lod->lod_lmv_failout = val;
1018
1019         return count;
1020 }
1021 LUSTRE_RW_ATTR(lmv_failout);
1022
1023 static ssize_t mdt_hash_show(struct kobject *kobj, struct attribute *attr,
1024                              char *buf)
1025 {
1026         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
1027         struct lod_device *lod = dt2lod_dev(dt);
1028
1029         return scnprintf(buf, PAGE_SIZE, "%s\n",
1030                 mdt_hash_name[lod->lod_mdt_descs.ltd_lmv_desc.ld_pattern]);
1031 }
1032
1033 static ssize_t mdt_hash_store(struct kobject *kobj, struct attribute *attr,
1034                               const char *buffer, size_t count)
1035 {
1036         struct dt_device *dt = container_of(kobj, struct dt_device, dd_kobj);
1037         struct lod_device *lod = dt2lod_dev(dt);
1038         char *hash;
1039         int len;
1040         int i;
1041
1042         hash = kstrndup(buffer, count, GFP_KERNEL);
1043         if (!hash)
1044                 return -ENOMEM;
1045
1046         len = strcspn(hash, "\n ");
1047         hash[len] = '\0';
1048         for (i = LMV_HASH_TYPE_ALL_CHARS; i < LMV_HASH_TYPE_MAX; i++) {
1049                 if (!strcmp(hash, mdt_hash_name[i])) {
1050                         lod->lod_mdt_descs.ltd_lmv_desc.ld_pattern = i;
1051                         kfree(hash);
1052                         return count;
1053                 }
1054         }
1055         kfree(hash);
1056
1057         return -EINVAL;
1058 }
1059 LUSTRE_RW_ATTR(mdt_hash);
1060
1061 static const struct proc_ops lod_proc_mdt_fops = {
1062         PROC_OWNER(THIS_MODULE)
1063         .proc_open      = lod_mdts_seq_open,
1064         .proc_read      = seq_read,
1065         .proc_lseek     = seq_lseek,
1066         .proc_release   = lprocfs_seq_release,
1067 };
1068
1069 static int lod_spill_threshold_pct_seq_show(struct seq_file *m, void *v)
1070 {
1071         struct pool_desc *pool = m->private;
1072
1073         LASSERT(pool != NULL);
1074         seq_printf(m, "%d\n", pool->pool_spill_threshold_pct);
1075
1076         return 0;
1077 }
1078
1079 static ssize_t
1080 lod_spill_threshold_pct_seq_write(struct file *file, const char __user *buffer,
1081                                   size_t count, loff_t *off)
1082 {
1083         struct seq_file *m = file->private_data;
1084         struct pool_desc *pool = m->private;
1085         int rc;
1086         int val;
1087
1088         LASSERT(pool != NULL);
1089
1090         rc = kstrtoint_from_user(buffer, count, 0, &val);
1091         if (rc)
1092                 return rc;
1093
1094         if (val > 100 || val < 0)
1095                 return -EINVAL;
1096
1097         pool->pool_spill_threshold_pct = val;
1098         pool->pool_spill_expire = 0;
1099         if (pool->pool_spill_threshold_pct == 0)
1100                 pool->pool_spill_is_active = false;
1101
1102         return count;
1103 }
1104 LPROC_SEQ_FOPS(lod_spill_threshold_pct);
1105
1106 static int lod_spill_target_seq_show(struct seq_file *m, void *v)
1107 {
1108         struct pool_desc *pool = m->private;
1109
1110         LASSERT(pool != NULL);
1111         seq_printf(m, "%s\n", pool->pool_spill_target);
1112
1113         return 0;
1114 }
1115
1116 static ssize_t
1117 lod_spill_target_seq_write(struct file *file, const char __user *buffer,
1118                            size_t count, loff_t *off)
1119 {
1120         struct seq_file *m = file->private_data;
1121         struct pool_desc *pool = m->private;
1122         struct lod_device *lod;
1123
1124         LASSERT(pool != NULL);
1125         lod = lu2lod_dev(pool->pool_lobd->obd_lu_dev);
1126
1127         if (count == 0) {
1128                 pool->pool_spill_target[0] = '\0';
1129                 pool->pool_spill_is_active = false;
1130                 return count;
1131         }
1132
1133         if (count > LOV_MAXPOOLNAME - 1)
1134                 return -E2BIG;
1135         if (copy_from_user(pool->pool_spill_target, buffer, count))
1136                 return -EFAULT;
1137
1138         pool->pool_spill_target[count] = '\0';
1139         if (strcmp(pool->pool_name, pool->pool_spill_target) == 0)
1140                 return -ELOOP;
1141         if (!lod_pool_exists(lod, pool->pool_spill_target)) {
1142                 pool->pool_spill_target[0] = '\0';
1143                 pool->pool_spill_expire = 0;
1144                 return -ENODEV;
1145         }
1146
1147         return count;
1148 }
1149 LPROC_SEQ_FOPS(lod_spill_target);
1150
1151 static int lod_spill_is_active_seq_show(struct seq_file *m, void *v)
1152 {
1153         struct pool_desc *pool = m->private;
1154         struct lod_device *lod;
1155         struct lu_env env;
1156         int rc;
1157
1158         if (!pool)
1159                 return -ENODEV;
1160
1161         rc = lu_env_init(&env, LCT_LOCAL);
1162         if (rc)
1163                 return rc;
1164
1165         lod = lu2lod_dev(pool->pool_lobd->obd_lu_dev);
1166         lod_spill_target_refresh(&env, lod, pool);
1167         lu_env_fini(&env);
1168
1169         seq_printf(m, "%d\n", pool->pool_spill_is_active ? 1 : 0);
1170
1171         return 0;
1172 }
1173 LPROC_SEQ_FOPS_RO(lod_spill_is_active);
1174
1175 static int lod_spill_hit_seq_show(struct seq_file *m, void *v)
1176 {
1177         struct pool_desc  *pool = m->private;
1178
1179         LASSERT(pool != NULL);
1180         seq_printf(m, "%d\n", atomic_read(&pool->pool_spill_hit));
1181         return 0;
1182 }
1183 LPROC_SEQ_FOPS_RO(lod_spill_hit);
1184
1185 struct lprocfs_vars lprocfs_lod_spill_vars[] = {
1186         { .name =       "spill_threshold_pct",
1187           .fops =       &lod_spill_threshold_pct_fops },
1188         { .name =       "spill_target",
1189           .fops =       &lod_spill_target_fops },
1190         { .name =       "spill_is_active",
1191           .fops =       &lod_spill_is_active_fops },
1192         { .name =       "spill_hit",
1193           .fops =       &lod_spill_hit_fops },
1194         { NULL }
1195 };
1196
1197 static struct proc_ops lod_proc_target_fops = {
1198         PROC_OWNER(THIS_MODULE)
1199         .proc_open      = lod_osts_seq_open,
1200         .proc_read      = seq_read,
1201         .proc_lseek     = seq_lseek,
1202         .proc_release   = lprocfs_seq_release,
1203 };
1204
1205 static struct attribute *lod_attrs[] = {
1206         &lustre_attr_dom_stripesize.attr,
1207         &lustre_attr_dom_stripesize_max_kb.attr,
1208         &lustre_attr_dom_stripesize_cur_kb.attr,
1209         &lustre_attr_dom_threshold_free_mb.attr,
1210         &lustre_attr_stripesize.attr,
1211         &lustre_attr_stripeoffset.attr,
1212         &lustre_attr_stripecount.attr,
1213         &lustre_attr_max_stripecount.attr,
1214         &lustre_attr_stripetype.attr,
1215         &lustre_attr_activeobd.attr,
1216         &lustre_attr_desc_uuid.attr,
1217         &lustre_attr_lmv_failout.attr,
1218         &lustre_attr_numobd.attr,
1219         &lustre_attr_qos_maxage.attr,
1220         &lustre_attr_qos_prio_free.attr,
1221         &lustre_attr_qos_threshold_rr.attr,
1222         &lustre_attr_mdt_stripecount.attr,
1223         &lustre_attr_mdt_stripetype.attr,
1224         &lustre_attr_mdt_activeobd.attr,
1225         &lustre_attr_mdt_numobd.attr,
1226         &lustre_attr_mdt_qos_maxage.attr,
1227         &lustre_attr_mdt_qos_prio_free.attr,
1228         &lustre_attr_mdt_qos_threshold_rr.attr,
1229         &lustre_attr_mdt_hash.attr,
1230         NULL,
1231 };
1232
1233 /**
1234  * Initialize procfs entries for LOD.
1235  *
1236  * \param[in] lod       LOD device
1237  *
1238  * \retval 0            on success
1239  * \retval negative     error code if failed
1240  */
1241 int lod_procfs_init(struct lod_device *lod)
1242 {
1243         struct obd_device *obd = lod2obd(lod);
1244         struct obd_type *type;
1245         struct kobject *lov;
1246         int rc;
1247
1248         lod->lod_dt_dev.dd_ktype.default_attrs = lod_attrs;
1249         rc = dt_tunables_init(&lod->lod_dt_dev, obd->obd_type, obd->obd_name,
1250                               NULL);
1251         if (rc) {
1252                 CERROR("%s: failed to setup DT tunables: %d\n",
1253                        obd->obd_name, rc);
1254                 RETURN(rc);
1255         }
1256
1257         obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1258                                                obd->obd_type->typ_procroot,
1259                                                NULL, obd);
1260         if (IS_ERR(obd->obd_proc_entry)) {
1261                 rc = PTR_ERR(obd->obd_proc_entry);
1262                 CERROR("%s: error %d setting up lprocfs\n",
1263                        obd->obd_name, rc);
1264                 GOTO(out, rc);
1265         }
1266
1267         rc = lprocfs_seq_create(obd->obd_proc_entry, "mdt_obd",
1268                                 0444, &lod_proc_mdt_fops, obd);
1269         if (rc) {
1270                 CWARN("%s: Error adding the target_obd file %d\n",
1271                       obd->obd_name, rc);
1272                 GOTO(out, rc);
1273         }
1274
1275         rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
1276                                 0444, &lod_proc_target_fops, obd);
1277         if (rc) {
1278                 CWARN("%s: Error adding the target_obd file %d\n",
1279                       obd->obd_name, rc);
1280                 GOTO(out, rc);
1281         }
1282
1283         lod->lod_pool_proc_entry = lprocfs_register("pools",
1284                                                     obd->obd_proc_entry,
1285                                                     NULL, NULL);
1286         if (IS_ERR(lod->lod_pool_proc_entry)) {
1287                 rc = PTR_ERR(lod->lod_pool_proc_entry);
1288                 lod->lod_pool_proc_entry = NULL;
1289                 CWARN("%s: Failed to create pools proc file: %d\n",
1290                       obd->obd_name, rc);
1291                 GOTO(out, rc);
1292         }
1293
1294         lod->lod_spill_proc_entry = lprocfs_register("pool",
1295                                                     obd->obd_proc_entry,
1296                                                     NULL, NULL);
1297         if (IS_ERR(lod->lod_spill_proc_entry)) {
1298                 rc = PTR_ERR(lod->lod_spill_proc_entry);
1299                 lod->lod_spill_proc_entry = NULL;
1300                 CWARN("%s: Failed to create pool proc file: %d\n",
1301                       obd->obd_name, rc);
1302                 GOTO(out, rc);
1303         }
1304
1305         lov = kset_find_obj(lustre_kset, "lov");
1306         if (!lov) {
1307                 CERROR("%s: lov subsystem not found\n", obd->obd_name);
1308                 GOTO(out, rc = -ENODEV);
1309         }
1310
1311         rc = sysfs_create_link(lov, &lod->lod_dt_dev.dd_kobj,
1312                                obd->obd_name);
1313         if (rc)
1314                 CERROR("%s: failed to create LOV sysfs symlink\n",
1315                        obd->obd_name);
1316         kobject_put(lov);
1317
1318         obd->obd_debugfs_entry = debugfs_create_dir(obd->obd_name,
1319                                                     obd->obd_type->typ_debugfs_entry);
1320
1321         lod->lod_debugfs = ldebugfs_add_symlink(obd->obd_name, "lov",
1322                                                 "../lod/%s", obd->obd_name);
1323         if (!lod->lod_debugfs)
1324                 CERROR("%s: failed to create LOV debugfs symlink\n",
1325                        obd->obd_name);
1326
1327         type = container_of(lov, struct obd_type, typ_kobj);
1328         if (!type->typ_procroot)
1329                 RETURN(0);
1330
1331         /* for compatibility we link old procfs's LOV entries to lod ones */
1332         lod->lod_symlink = lprocfs_add_symlink(obd->obd_name,
1333                                                type->typ_procroot,
1334                                                "../lod/%s", obd->obd_name);
1335         if (lod->lod_symlink == NULL)
1336                 CERROR("cannot create LOV symlink for /proc/fs/lustre/lod/%s\n",
1337                        obd->obd_name);
1338         RETURN(0);
1339
1340 out:
1341         dt_tunables_fini(&lod->lod_dt_dev);
1342
1343         return rc;
1344 }
1345
1346 /**
1347  * Cleanup procfs entries registred for LOD.
1348  *
1349  * \param[in] lod       LOD device
1350  */
1351 void lod_procfs_fini(struct lod_device *lod)
1352 {
1353         struct obd_device *obd = lod2obd(lod);
1354         struct kobject *lov;
1355
1356         if (lod->lod_symlink != NULL) {
1357                 lprocfs_remove(&lod->lod_symlink);
1358                 lod->lod_symlink = NULL;
1359         }
1360
1361         lov = kset_find_obj(lustre_kset, "lov");
1362         if (lov) {
1363                 sysfs_remove_link(lov, obd->obd_name);
1364                 kobject_put(lov);
1365         }
1366
1367         debugfs_remove_recursive(lod->lod_debugfs);
1368
1369         if (obd->obd_proc_entry) {
1370                 lprocfs_remove(&obd->obd_proc_entry);
1371                 obd->obd_proc_entry = NULL;
1372         }
1373
1374         dt_tunables_fini(&lod->lod_dt_dev);
1375 }
1376
1377 #endif /* CONFIG_PROC_FS */