Whamcloud - gitweb
f89b0dc41cc4d0e7fa89a64e5b19214127d7cb34
[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  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32 #define DEBUG_SUBSYSTEM S_CLASS
33
34 #include <lprocfs_status.h>
35 #include <obd_class.h>
36 #include <linux/seq_file.h>
37 #include "lod_internal.h"
38 #include <uapi/linux/lustre/lustre_param.h>
39
40 /*
41  * Notice, all the functions below (except for lod_procfs_init() and
42  * lod_procfs_fini()) are not supposed to be used directly. They are
43  * called by Linux kernel's procfs.
44  */
45
46 #ifdef CONFIG_PROC_FS
47
48 /**
49  * Show DoM default stripe size.
50  */
51 static ssize_t dom_stripesize_show(struct kobject *kobj, struct attribute *attr,
52                                    char *buf)
53 {
54         struct dt_device *dt = container_of(kobj, struct dt_device,
55                                             dd_kobj);
56         struct lod_device *lod = dt2lod_dev(dt);
57
58         return snprintf(buf, PAGE_SIZE, "%u\n", lod->lod_dom_max_stripesize);
59 }
60
61 /**
62  * Set DoM default stripe size.
63  */
64 static ssize_t dom_stripesize_store(struct kobject *kobj,
65                                     struct attribute *attr, const char *buffer,
66                                     size_t count)
67 {
68         struct dt_device *dt = container_of(kobj, struct dt_device,
69                                             dd_kobj);
70         struct lod_device *lod = dt2lod_dev(dt);
71         char tbuf[22] = "";
72         s64 val;
73         int rc;
74
75         if (count > (sizeof(tbuf) - 1))
76                 return -EINVAL;
77
78         memcpy(tbuf, buffer, count);
79
80         rc = lu_str_to_s64(tbuf, count, &val, '1');
81         if (rc)
82                 return rc;
83
84         if (val < 0)
85                 return -ERANGE;
86
87         /* 1GB is the limit */
88         if (val > (1ULL << 30))
89                 return -ERANGE;
90
91         if (val > 0) {
92                 if (val < LOV_MIN_STRIPE_SIZE) {
93                         LCONSOLE_INFO("Increasing provided stripe size to "
94                                       "a minimum value %u\n",
95                                       LOV_MIN_STRIPE_SIZE);
96                         val = LOV_MIN_STRIPE_SIZE;
97                 } else if (val & (LOV_MIN_STRIPE_SIZE - 1)) {
98                         val &= ~(LOV_MIN_STRIPE_SIZE - 1);
99                         LCONSOLE_WARN("Changing provided stripe size to %llu "
100                                       "(a multiple of minimum %u)\n",
101                                       val, LOV_MIN_STRIPE_SIZE);
102                 }
103         }
104
105         lod->lod_dom_max_stripesize = val;
106
107         return count;
108 }
109
110 LUSTRE_RW_ATTR(dom_stripesize);
111
112 static ssize_t stripesize_show(struct kobject *kobj, struct attribute *attr,
113                                char *buf)
114 {
115         struct dt_device *dt = container_of(kobj, struct dt_device,
116                                             dd_kobj);
117         struct lod_device *lod = dt2lod_dev(dt);
118
119         return snprintf(buf, PAGE_SIZE, "%llu\n",
120                         lod->lod_ost_descs.ltd_lov_desc.ld_default_stripe_size);
121 }
122
123 static ssize_t stripesize_store(struct kobject *kobj, struct attribute *attr,
124                                 const char *buffer, size_t count)
125 {
126         struct dt_device *dt = container_of(kobj, struct dt_device,
127                                             dd_kobj);
128         struct lod_device *lod = dt2lod_dev(dt);
129         char tbuf[22] = "";
130         s64 val;
131         int rc;
132
133         if (count > (sizeof(tbuf) - 1))
134                 return -EINVAL;
135
136         memcpy(tbuf, buffer, count);
137
138         rc = lu_str_to_s64(tbuf, count, &val, '1');
139         if (rc)
140                 return rc;
141
142         if (val < 0)
143                 return -ERANGE;
144
145         lod_fix_desc_stripe_size(&val);
146         lod->lod_ost_descs.ltd_lov_desc.ld_default_stripe_size = val;
147
148         return count;
149 }
150
151 LUSTRE_RW_ATTR(stripesize);
152
153 /**
154  * Show default stripe offset.
155  */
156 static ssize_t stripeoffset_show(struct kobject *kobj, struct attribute *attr,
157                                  char *buf)
158 {
159         struct dt_device *dt = container_of(kobj, struct dt_device,
160                                             dd_kobj);
161         struct lod_device *lod = dt2lod_dev(dt);
162
163         return snprintf(buf, PAGE_SIZE, "%lld\n",
164                 lod->lod_ost_descs.ltd_lov_desc.ld_default_stripe_offset);
165 }
166
167 /**
168  * Set default stripe offset.
169  *
170  * Usually contains -1 allowing Lustre to balance objects among OST
171  * otherwise may cause severe OST imbalance.
172  */
173 static ssize_t stripeoffset_store(struct kobject *kobj,
174                                     struct attribute *attr,
175                                     const char *buffer, size_t count)
176 {
177         struct dt_device *dt = container_of(kobj, struct dt_device,
178                                             dd_kobj);
179         struct lod_device *lod = dt2lod_dev(dt);
180         long val;
181         int rc;
182
183         rc = kstrtol(buffer, 0, &val);
184         if (rc)
185                 return rc;
186
187         if (val < -1 || val > LOV_MAX_STRIPE_COUNT)
188                 return -ERANGE;
189
190         lod->lod_ost_descs.ltd_lov_desc.ld_default_stripe_offset = val;
191
192         return count;
193 }
194
195 LUSTRE_RW_ATTR(stripeoffset);
196
197 /**
198  * Show default striping pattern (LOV_PATTERN_*).
199  */
200 static ssize_t __stripetype_show(struct kobject *kobj, struct attribute *attr,
201                                  char *buf, bool is_mdt)
202 {
203         struct dt_device *dt = container_of(kobj, struct dt_device,
204                                             dd_kobj);
205         struct lod_device *lod = dt2lod_dev(dt);
206         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
207                                             &lod->lod_ost_descs;
208
209         return snprintf(buf, PAGE_SIZE, "%u\n", ltd->ltd_lov_desc.ld_pattern);
210 }
211
212 static ssize_t mdt_stripetype_show(struct kobject *kobj, struct attribute *attr,
213                                    char *buf)
214 {
215         return __stripetype_show(kobj, attr, buf, true);
216 }
217
218 static ssize_t stripetype_show(struct kobject *kobj, struct attribute *attr,
219                                char *buf)
220 {
221         return __stripetype_show(kobj, attr, buf, false);
222 }
223
224 /**
225  * Set default striping pattern (a number, not a human-readable string).
226  */
227 static ssize_t __stripetype_store(struct kobject *kobj, struct attribute *attr,
228                                   const char *buffer, size_t count, bool is_mdt)
229 {
230         struct dt_device *dt = container_of(kobj, struct dt_device,
231                                             dd_kobj);
232         struct lod_device *lod = dt2lod_dev(dt);
233         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
234                                             &lod->lod_ost_descs;
235         u32 pattern;
236         int rc;
237
238         rc = kstrtouint(buffer, 0, &pattern);
239         if (rc)
240                 return rc;
241
242         if (is_mdt)
243                 lod_fix_lmv_desc_pattern(&pattern);
244         else
245                 lod_fix_desc_pattern(&pattern);
246
247         ltd->ltd_lov_desc.ld_pattern = pattern;
248
249         return count;
250 }
251
252 static ssize_t mdt_stripetype_store(struct kobject *kobj,
253                                     struct attribute *attr, const char *buffer,
254                                     size_t count)
255 {
256         return __stripetype_store(kobj, attr, buffer, count, true);
257 }
258
259 static ssize_t stripetype_store(struct kobject *kobj,
260                                     struct attribute *attr, const char *buffer,
261                                     size_t count)
262 {
263         return __stripetype_store(kobj, attr, buffer, count, false);
264 }
265
266 LUSTRE_RW_ATTR(mdt_stripetype);
267 LUSTRE_RW_ATTR(stripetype);
268
269 /**
270  * Show default number of stripes.
271  */
272 static ssize_t __stripecount_show(struct kobject *kobj, struct attribute *attr,
273                                   char *buf, bool is_mdt)
274 {
275         struct dt_device *dt = container_of(kobj, struct dt_device,
276                                             dd_kobj);
277         struct lod_device *lod = dt2lod_dev(dt);
278         struct lov_desc *desc = is_mdt ? &lod->lod_mdt_descs.ltd_lov_desc :
279                                          &lod->lod_ost_descs.ltd_lov_desc;
280
281         return snprintf(buf, PAGE_SIZE, "%d\n",
282                       (s16)(desc->ld_default_stripe_count + 1) - 1);
283 }
284
285 static ssize_t mdt_stripecount_show(struct kobject *kobj,
286                                     struct attribute *attr, char *buf)
287 {
288         return __stripecount_show(kobj, attr, buf, true);
289 }
290
291 static ssize_t stripecount_show(struct kobject *kobj, struct attribute *attr,
292                                 char *buf)
293 {
294         return __stripecount_show(kobj, attr, buf, false);
295 }
296
297 /**
298  * Set default number of stripes.
299  */
300 static ssize_t __stripecount_store(struct kobject *kobj, struct attribute *attr,
301                                    const char *buffer, size_t count,
302                                    bool is_mdt)
303 {
304         struct dt_device *dt = container_of(kobj, struct dt_device,
305                                             dd_kobj);
306         struct lod_device *lod = dt2lod_dev(dt);
307         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
308                                             &lod->lod_ost_descs;
309         int stripe_count;
310         int rc;
311
312         rc = kstrtoint(buffer, 0, &stripe_count);
313         if (rc)
314                 return rc;
315
316         if (stripe_count < -1)
317                 return -ERANGE;
318
319         lod_fix_desc_stripe_count(&stripe_count);
320         ltd->ltd_lov_desc.ld_default_stripe_count = stripe_count;
321
322         return count;
323 }
324
325 static ssize_t mdt_stripecount_store(struct kobject *kobj,
326                                      struct attribute *attr,
327                                      const char *buffer, size_t count)
328 {
329         return __stripecount_store(kobj, attr, buffer, count, true);
330 }
331
332 static ssize_t stripecount_store(struct kobject *kobj,
333                                  struct attribute *attr,
334                                  const char *buffer, size_t count)
335 {
336         return __stripecount_store(kobj, attr, buffer, count, false);
337 }
338
339 LUSTRE_RW_ATTR(mdt_stripecount);
340 LUSTRE_RW_ATTR(stripecount);
341
342 /**
343  * Show number of targets.
344  */
345 static ssize_t __numobd_show(struct kobject *kobj, struct attribute *attr,
346                              char *buf, bool is_mdt)
347 {
348         struct dt_device *dt = container_of(kobj, struct dt_device,
349                                             dd_kobj);
350         struct lod_device *lod = dt2lod_dev(dt);
351         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
352                                             &lod->lod_ost_descs;
353
354         return snprintf(buf, PAGE_SIZE, "%u\n", ltd->ltd_lov_desc.ld_tgt_count);
355 }
356
357 static ssize_t mdt_numobd_show(struct kobject *kobj, struct attribute *attr,
358                                char *buf)
359 {
360         return __numobd_show(kobj, attr, buf, true);
361 }
362
363 static ssize_t numobd_show(struct kobject *kobj, struct attribute *attr,
364                            char *buf)
365 {
366         return __numobd_show(kobj, attr, buf, false);
367 }
368
369 LUSTRE_RO_ATTR(mdt_numobd);
370 LUSTRE_RO_ATTR(numobd);
371
372 /**
373  * Show number of active targets.
374  */
375 static ssize_t __activeobd_show(struct kobject *kobj, struct attribute *attr,
376                                 char *buf, bool is_mdt)
377 {
378         struct dt_device *dt = container_of(kobj, struct dt_device,
379                                             dd_kobj);
380         struct lod_device *lod = dt2lod_dev(dt);
381         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
382                                             &lod->lod_ost_descs;
383
384         return snprintf(buf, PAGE_SIZE, "%u\n",
385                         ltd->ltd_lov_desc.ld_active_tgt_count);
386 }
387
388 static ssize_t mdt_activeobd_show(struct kobject *kobj, struct attribute *attr,
389                                   char *buf)
390 {
391         return __activeobd_show(kobj, attr, buf, true);
392 }
393
394 static ssize_t activeobd_show(struct kobject *kobj, struct attribute *attr,
395                               char *buf)
396 {
397         return __activeobd_show(kobj, attr, buf, false);
398 }
399
400 LUSTRE_RO_ATTR(mdt_activeobd);
401 LUSTRE_RO_ATTR(activeobd);
402
403 /**
404  * Show UUID of LOD device.
405  */
406 static ssize_t desc_uuid_show(struct kobject *kobj, struct attribute *attr,
407                               char *buf)
408 {
409         struct dt_device *dt = container_of(kobj, struct dt_device,
410                                             dd_kobj);
411         struct lod_device *lod = dt2lod_dev(dt);
412
413         return snprintf(buf, PAGE_SIZE, "%s\n",
414                        lod->lod_ost_descs.ltd_lov_desc.ld_uuid.uuid);
415 }
416 LUSTRE_RO_ATTR(desc_uuid);
417
418 /**
419  * Show QoS priority parameter.
420  *
421  * The printed value is a percentage value (0-100%) indicating the priority
422  * of free space compared to performance. 0% means select OSTs equally
423  * regardless of their free space, 100% means select OSTs only by their free
424  * space even if it results in very imbalanced load on the OSTs.
425  */
426 static ssize_t __qos_prio_free_show(struct kobject *kobj,
427                                     struct attribute *attr, char *buf,
428                                     bool is_mdt)
429 {
430         struct dt_device *dt = container_of(kobj, struct dt_device,
431                                             dd_kobj);
432         struct lod_device *lod = dt2lod_dev(dt);
433         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
434                                             &lod->lod_ost_descs;
435
436         return snprintf(buf, PAGE_SIZE, "%d%%\n",
437                        (ltd->ltd_qos.lq_prio_free * 100 + 255) >> 8);
438 }
439
440 static ssize_t mdt_qos_prio_free_show(struct kobject *kobj,
441                                       struct attribute *attr, char *buf)
442 {
443         return __qos_prio_free_show(kobj, attr, buf, true);
444 }
445
446 static ssize_t qos_prio_free_show(struct kobject *kobj,
447                                   struct attribute *attr, char *buf)
448 {
449         return __qos_prio_free_show(kobj, attr, buf, false);
450 }
451
452 /**
453  * Set QoS free space priority parameter.
454  *
455  * Set the relative priority of free OST space compared to OST load when OSTs
456  * are space imbalanced.  See qos_priofree_show() for description of
457  * this parameter.  See qos_threshold_rr_store() and lq_threshold_rr to
458  * determine what constitutes "space imbalanced" OSTs.
459  */
460 static ssize_t __qos_prio_free_store(struct kobject *kobj,
461                                      struct attribute *attr,
462                                      const char *buffer, size_t count,
463                                      bool is_mdt)
464 {
465         struct dt_device *dt = container_of(kobj, struct dt_device,
466                                             dd_kobj);
467         struct lod_device *lod = dt2lod_dev(dt);
468         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
469                                             &lod->lod_ost_descs;
470         unsigned int val;
471         int rc;
472
473         rc = kstrtouint(buffer, 0, &val);
474         if (rc)
475                 return rc;
476
477         if (val > 100)
478                 return -EINVAL;
479         ltd->ltd_qos.lq_prio_free = (val << 8) / 100;
480         ltd->ltd_qos.lq_dirty = 1;
481         ltd->ltd_qos.lq_reset = 1;
482
483         return count;
484 }
485
486 static ssize_t mdt_qos_prio_free_store(struct kobject *kobj,
487                                        struct attribute *attr,
488                                        const char *buffer, size_t count)
489 {
490         return __qos_prio_free_store(kobj, attr, buffer, count, true);
491 }
492
493 static ssize_t qos_prio_free_store(struct kobject *kobj, struct attribute *attr,
494                                    const char *buffer, size_t count)
495 {
496         return __qos_prio_free_store(kobj, attr, buffer, count, false);
497 }
498
499 LUSTRE_RW_ATTR(mdt_qos_prio_free);
500 LUSTRE_RW_ATTR(qos_prio_free);
501
502 /**
503  * Show threshold for "same space on all OSTs" rule.
504  */
505 static ssize_t __qos_threshold_rr_show(struct kobject *kobj,
506                                        struct attribute *attr, char *buf,
507                                        bool is_mdt)
508 {
509         struct dt_device *dt = container_of(kobj, struct dt_device,
510                                             dd_kobj);
511         struct lod_device *lod = dt2lod_dev(dt);
512         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
513                                             &lod->lod_ost_descs;
514
515         return snprintf(buf, PAGE_SIZE, "%d%%\n",
516                        (ltd->ltd_qos.lq_threshold_rr * 100 + 255) >> 8);
517 }
518
519 static ssize_t mdt_qos_threshold_rr_show(struct kobject *kobj,
520                                          struct attribute *attr, char *buf)
521 {
522         return __qos_threshold_rr_show(kobj, attr, buf, true);
523 }
524
525 static ssize_t qos_threshold_rr_show(struct kobject *kobj,
526                                      struct attribute *attr, char *buf)
527 {
528         return __qos_threshold_rr_show(kobj, attr, buf, false);
529 }
530
531 /**
532  * Set threshold for "same space on all OSTs" rule.
533  *
534  * This sets the maximum percentage difference of free space between the most
535  * full and most empty OST in the currently available OSTs. If this percentage
536  * is exceeded, use the QoS allocator to select OSTs based on their available
537  * space so that more full OSTs are chosen less often, otherwise use the
538  * round-robin allocator for efficiency and performance.
539  */
540 static ssize_t __qos_threshold_rr_store(struct kobject *kobj,
541                                         struct attribute *attr,
542                                         const char *buffer, size_t count,
543                                         bool is_mdt)
544 {
545         struct dt_device *dt = container_of(kobj, struct dt_device,
546                                             dd_kobj);
547         struct lod_device *lod = dt2lod_dev(dt);
548         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
549                                             &lod->lod_ost_descs;
550         char buf[6], *tmp;
551         unsigned int val;
552         int rc;
553
554         /* "100%\n\0" should be largest string */
555         if (count >= sizeof(buf))
556                 return -ERANGE;
557
558         strncpy(buf, buffer, sizeof(buf));
559         buf[sizeof(buf) - 1] = '\0';
560         tmp = strchr(buf, '%');
561         if (tmp)
562                 *tmp = '\0';
563
564         rc = kstrtouint(buf, 0, &val);
565         if (rc)
566                 return rc;
567
568         if (val > 100)
569                 return -EINVAL;
570         ltd->ltd_qos.lq_threshold_rr = (val << 8) / 100;
571         ltd->ltd_qos.lq_dirty = 1;
572
573         return count;
574 }
575
576 static ssize_t mdt_qos_threshold_rr_store(struct kobject *kobj,
577                                           struct attribute *attr,
578                                           const char *buffer, size_t count)
579 {
580         return __qos_threshold_rr_store(kobj, attr, buffer, count, true);
581 }
582
583 static ssize_t qos_threshold_rr_store(struct kobject *kobj,
584                                       struct attribute *attr,
585                                       const char *buffer, size_t count)
586 {
587         return __qos_threshold_rr_store(kobj, attr, buffer, count, false);
588 }
589
590 LUSTRE_RW_ATTR(mdt_qos_threshold_rr);
591 LUSTRE_RW_ATTR(qos_threshold_rr);
592
593 /**
594  * Show expiration period used to refresh cached statfs data, which
595  * is used to implement QoS/RR striping allocation algorithm.
596  */
597 static ssize_t __qos_maxage_show(struct kobject *kobj, struct attribute *attr,
598                                  char *buf, bool is_mdt)
599 {
600         struct dt_device *dt = container_of(kobj, struct dt_device,
601                                             dd_kobj);
602         struct lod_device *lod = dt2lod_dev(dt);
603         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
604                                             &lod->lod_ost_descs;
605
606         return snprintf(buf, PAGE_SIZE, "%u Sec\n",
607                        ltd->ltd_lov_desc.ld_qos_maxage);
608 }
609
610 static ssize_t mdt_qos_maxage_show(struct kobject *kobj, struct attribute *attr,
611                                    char *buf)
612 {
613         return __qos_maxage_show(kobj, attr, buf, true);
614 }
615
616 static ssize_t qos_maxage_show(struct kobject *kobj, struct attribute *attr,
617                                char *buf)
618 {
619         return __qos_maxage_show(kobj, attr, buf, true);
620 }
621
622 /**
623  * Set expiration period used to refresh cached statfs data.
624  */
625 static ssize_t __qos_maxage_store(struct kobject *kobj, struct attribute *attr,
626                                   const char *buffer, size_t count, bool is_mdt)
627 {
628         struct dt_device *dt = container_of(kobj, struct dt_device,
629                                             dd_kobj);
630         struct lod_device *lod = dt2lod_dev(dt);
631         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
632                                             &lod->lod_ost_descs;
633         struct lustre_cfg_bufs bufs;
634         struct lu_device *next;
635         struct lustre_cfg *lcfg;
636         char str[32];
637         struct lu_tgt_desc *tgt;
638         int rc;
639         u32 val;
640
641         rc = kstrtouint(buffer, 0, &val);
642         if (rc)
643                 return rc;
644
645         if (val <= 0)
646                 return -EINVAL;
647
648         ltd->ltd_lov_desc.ld_qos_maxage = val;
649
650         /*
651          * propogate the value down to OSPs
652          */
653         lustre_cfg_bufs_reset(&bufs, NULL);
654         snprintf(str, 32, "%smaxage=%u", PARAM_OSP, val);
655         lustre_cfg_bufs_set_string(&bufs, 1, str);
656         OBD_ALLOC(lcfg, lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen));
657         if (lcfg == NULL)
658                 return -ENOMEM;
659         lustre_cfg_init(lcfg, LCFG_PARAM, &bufs);
660
661         lod_getref(ltd);
662         ltd_foreach_tgt(ltd, tgt) {
663                 next = &tgt->ltd_tgt->dd_lu_dev;
664                 rc = next->ld_ops->ldo_process_config(NULL, next, lcfg);
665                 if (rc)
666                         CERROR("can't set maxage on #%d: %d\n",
667                                tgt->ltd_index, rc);
668         }
669         lod_putref(lod, ltd);
670         OBD_FREE(lcfg, lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens));
671
672         return count;
673 }
674
675 static ssize_t mdt_qos_maxage_store(struct kobject *kobj,
676                                     struct attribute *attr,
677                                     const char *buffer, size_t count)
678 {
679         return __qos_maxage_store(kobj, attr, buffer, count, true);
680 }
681
682 static ssize_t qos_maxage_store(struct kobject *kobj, struct attribute *attr,
683                                 const char *buffer, size_t count)
684 {
685         return __qos_maxage_store(kobj, attr, buffer, count, false);
686 }
687
688 LUSTRE_RW_ATTR(mdt_qos_maxage);
689 LUSTRE_RW_ATTR(qos_maxage);
690
691 static void *lod_tgts_seq_start(struct seq_file *p, loff_t *pos, bool is_mdt)
692 {
693         struct obd_device *dev = p->private;
694         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
695         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
696                                             &lod->lod_ost_descs;
697
698         LASSERT(dev != NULL);
699
700         lod_getref(ltd); /* released in lod_tgts_seq_stop */
701         if (*pos >= ltd->ltd_tgt_bitmap->size)
702                 return NULL;
703
704         *pos = find_next_bit(ltd->ltd_tgt_bitmap->data,
705                              ltd->ltd_tgt_bitmap->size, *pos);
706         if (*pos < ltd->ltd_tgt_bitmap->size)
707                 return LTD_TGT(ltd, *pos);
708         else
709                 return NULL;
710 }
711
712 static void *lod_mdts_seq_start(struct seq_file *p, loff_t *pos)
713 {
714         return lod_tgts_seq_start(p, pos, true);
715 }
716
717 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos)
718 {
719         return lod_tgts_seq_start(p, pos, false);
720 }
721
722 static void lod_tgts_seq_stop(struct seq_file *p, void *v, bool is_mdt)
723 {
724         struct obd_device *dev = p->private;
725         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
726         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
727                                             &lod->lod_ost_descs;
728
729         LASSERT(dev != NULL);
730         lod_putref(lod, ltd);
731 }
732
733 static void lod_mdts_seq_stop(struct seq_file *p, void *v)
734 {
735         lod_tgts_seq_stop(p, v, true);
736 }
737
738 static void lod_osts_seq_stop(struct seq_file *p, void *v)
739 {
740         lod_tgts_seq_stop(p, v, false);
741 }
742
743 static void *lod_tgts_seq_next(struct seq_file *p, void *v, loff_t *pos,
744                                bool is_mdt)
745 {
746         struct obd_device *dev = p->private;
747         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
748         struct lu_tgt_descs *ltd = is_mdt ? &lod->lod_mdt_descs :
749                                             &lod->lod_ost_descs;
750
751         if (*pos >= ltd->ltd_tgt_bitmap->size - 1)
752                 return NULL;
753
754         *pos = find_next_bit(ltd->ltd_tgt_bitmap->data,
755                              ltd->ltd_tgt_bitmap->size, *pos + 1);
756         if (*pos < ltd->ltd_tgt_bitmap->size)
757                 return LTD_TGT(ltd, *pos);
758         else
759                 return NULL;
760 }
761
762 static void *lod_mdts_seq_next(struct seq_file *p, void *v, loff_t *pos)
763 {
764         return lod_tgts_seq_next(p, v, pos, true);
765 }
766
767 static void *lod_osts_seq_next(struct seq_file *p, void *v, loff_t *pos)
768 {
769         return lod_tgts_seq_next(p, v, pos, false);
770 }
771
772 /**
773  * Show active/inactive status for OST found by lod_osts_seq_next().
774  *
775  * \param[in] m         seq file
776  * \param[in] v         unused for single entry
777  *
778  * \retval 0            on success
779  * \retval negative     error code if failed
780  */
781 static int lod_tgts_seq_show(struct seq_file *p, void *v)
782 {
783         struct obd_device *obd = p->private;
784         struct lu_tgt_desc *tgt = v;
785         struct dt_device *next;
786         int rc, active;
787
788         LASSERT(obd->obd_lu_dev);
789
790         next = tgt->ltd_tgt;
791         if (!next)
792                 return -EINVAL;
793
794         /* XXX: should be non-NULL env, but it's very expensive */
795         active = 1;
796         rc = dt_statfs(NULL, next, &tgt->ltd_statfs);
797         if (rc == -ENOTCONN) {
798                 active = 0;
799                 rc = 0;
800         } else if (rc)
801                 return rc;
802
803         seq_printf(p, "%d: %s %sACTIVE\n", tgt->ltd_index,
804                    obd_uuid2str(&tgt->ltd_uuid),
805                    active ? "" : "IN");
806         return 0;
807 }
808
809 static const struct seq_operations lod_mdts_sops = {
810         .start  = lod_mdts_seq_start,
811         .stop   = lod_mdts_seq_stop,
812         .next   = lod_mdts_seq_next,
813         .show   = lod_tgts_seq_show,
814 };
815
816 static const struct seq_operations lod_osts_sops = {
817         .start  = lod_osts_seq_start,
818         .stop   = lod_osts_seq_stop,
819         .next   = lod_osts_seq_next,
820         .show   = lod_tgts_seq_show,
821 };
822
823 static int lod_mdts_seq_open(struct inode *inode, struct file *file)
824 {
825         struct seq_file *seq;
826         int rc;
827
828         rc = seq_open(file, &lod_mdts_sops);
829         if (rc)
830                 return rc;
831
832         seq = file->private_data;
833         seq->private = PDE_DATA(inode);
834         return 0;
835 }
836
837 static int lod_osts_seq_open(struct inode *inode, struct file *file)
838 {
839         struct seq_file *seq;
840         int rc;
841
842         rc = seq_open(file, &lod_osts_sops);
843         if (rc)
844                 return rc;
845
846         seq = file->private_data;
847         seq->private = PDE_DATA(inode);
848         return 0;
849 }
850
851 /**
852  * Show whether special failout mode for testing is enabled or not.
853  */
854 static ssize_t lmv_failout_show(struct kobject *kobj, struct attribute *attr,
855                                 char *buf)
856 {
857         struct dt_device *dt = container_of(kobj, struct dt_device,
858                                             dd_kobj);
859         struct lod_device *lod = dt2lod_dev(dt);
860
861         return snprintf(buf, PAGE_SIZE, "%d\n", lod->lod_lmv_failout ? 1 : 0);
862 }
863
864 /**
865  * Enable/disable a special failout mode for testing.
866  *
867  * This determines whether the LMV will try to continue processing a striped
868  * directory even if it has a (partly) corrupted entry in the master directory,
869  * or if it will abort upon finding a corrupted slave directory entry.
870  */
871 static ssize_t lmv_failout_store(struct kobject *kobj, struct attribute *attr,
872                                  const char *buffer, size_t count)
873 {
874         struct dt_device *dt = container_of(kobj, struct dt_device,
875                                             dd_kobj);
876         struct lod_device *lod = dt2lod_dev(dt);
877         bool val = 0;
878         int rc;
879
880         rc = kstrtobool(buffer, &val);
881         if (rc)
882                 return rc;
883
884         lod->lod_lmv_failout = val;
885
886         return count;
887 }
888 LUSTRE_RW_ATTR(lmv_failout);
889
890 static struct lprocfs_vars lprocfs_lod_obd_vars[] = {
891         { NULL }
892 };
893
894 static const struct file_operations lod_proc_mdt_fops = {
895         .owner   = THIS_MODULE,
896         .open    = lod_mdts_seq_open,
897         .read    = seq_read,
898         .llseek  = seq_lseek,
899         .release = lprocfs_seq_release,
900 };
901
902 static const struct file_operations lod_proc_target_fops = {
903         .owner   = THIS_MODULE,
904         .open    = lod_osts_seq_open,
905         .read    = seq_read,
906         .llseek  = seq_lseek,
907         .release = lprocfs_seq_release,
908 };
909
910 static struct attribute *lod_attrs[] = {
911         &lustre_attr_dom_stripesize.attr,
912         &lustre_attr_stripesize.attr,
913         &lustre_attr_stripeoffset.attr,
914         &lustre_attr_stripecount.attr,
915         &lustre_attr_stripetype.attr,
916         &lustre_attr_activeobd.attr,
917         &lustre_attr_desc_uuid.attr,
918         &lustre_attr_lmv_failout.attr,
919         &lustre_attr_numobd.attr,
920         &lustre_attr_qos_maxage.attr,
921         &lustre_attr_qos_prio_free.attr,
922         &lustre_attr_qos_threshold_rr.attr,
923         &lustre_attr_mdt_stripecount.attr,
924         &lustre_attr_mdt_stripetype.attr,
925         &lustre_attr_mdt_activeobd.attr,
926         &lustre_attr_mdt_numobd.attr,
927         &lustre_attr_mdt_qos_maxage.attr,
928         &lustre_attr_mdt_qos_prio_free.attr,
929         &lustre_attr_mdt_qos_threshold_rr.attr,
930         NULL,
931 };
932
933 /**
934  * Initialize procfs entries for LOD.
935  *
936  * \param[in] lod       LOD device
937  *
938  * \retval 0            on success
939  * \retval negative     error code if failed
940  */
941 int lod_procfs_init(struct lod_device *lod)
942 {
943         struct lprocfs_vars ldebugfs_obd_vars[] = { { NULL } };
944         struct obd_device *obd = lod2obd(lod);
945         struct obd_type *type;
946         struct kobject *lov;
947         int rc;
948
949         lod->lod_dt_dev.dd_ktype.default_attrs = lod_attrs;
950         rc = dt_tunables_init(&lod->lod_dt_dev, obd->obd_type, obd->obd_name,
951                               ldebugfs_obd_vars);
952         if (rc) {
953                 CERROR("%s: failed to setup DT tunables: %d\n",
954                        obd->obd_name, rc);
955                 RETURN(rc);
956         }
957
958         obd->obd_vars = lprocfs_lod_obd_vars;
959         obd->obd_proc_entry = lprocfs_register(obd->obd_name,
960                                                obd->obd_type->typ_procroot,
961                                                obd->obd_vars, obd);
962         if (IS_ERR(obd->obd_proc_entry)) {
963                 rc = PTR_ERR(obd->obd_proc_entry);
964                 CERROR("%s: error %d setting up lprocfs\n",
965                        obd->obd_name, rc);
966                 GOTO(out, rc);
967         }
968
969         rc = lprocfs_seq_create(obd->obd_proc_entry, "mdt_obd",
970                                 0444, &lod_proc_mdt_fops, obd);
971         if (rc) {
972                 CWARN("%s: Error adding the target_obd file %d\n",
973                       obd->obd_name, rc);
974                 GOTO(out, rc);
975         }
976
977         rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
978                                 0444, &lod_proc_target_fops, obd);
979         if (rc) {
980                 CWARN("%s: Error adding the target_obd file %d\n",
981                       obd->obd_name, rc);
982                 GOTO(out, rc);
983         }
984
985         lod->lod_pool_proc_entry = lprocfs_register("pools",
986                                                     obd->obd_proc_entry,
987                                                     NULL, NULL);
988         if (IS_ERR(lod->lod_pool_proc_entry)) {
989                 rc = PTR_ERR(lod->lod_pool_proc_entry);
990                 lod->lod_pool_proc_entry = NULL;
991                 CWARN("%s: Failed to create pool proc file: %d\n",
992                       obd->obd_name, rc);
993                 GOTO(out, rc);
994         }
995
996         lov = kset_find_obj(lustre_kset, "lov");
997         if (!lov) {
998                 CERROR("%s: lov subsystem not found\n", obd->obd_name);
999                 GOTO(out, rc = -ENODEV);
1000         }
1001
1002         rc = sysfs_create_link(lov, &lod->lod_dt_dev.dd_kobj,
1003                                obd->obd_name);
1004         if (rc)
1005                 CERROR("%s: failed to create LOV sysfs symlink\n",
1006                        obd->obd_name);
1007         kobject_put(lov);
1008
1009         lod->lod_debugfs = ldebugfs_add_symlink(obd->obd_name, "lov",
1010                                                 "../lod/%s", obd->obd_name);
1011         if (!lod->lod_debugfs)
1012                 CERROR("%s: failed to create LOV debugfs symlink\n",
1013                        obd->obd_name);
1014
1015         type = container_of(lov, struct obd_type, typ_kobj);
1016         if (!type->typ_procroot)
1017                 RETURN(0);
1018
1019         /* for compatibility we link old procfs's LOV entries to lod ones */
1020         lod->lod_symlink = lprocfs_add_symlink(obd->obd_name,
1021                                                type->typ_procroot,
1022                                                "../lod/%s", obd->obd_name);
1023         if (lod->lod_symlink == NULL)
1024                 CERROR("cannot create LOV symlink for /proc/fs/lustre/lod/%s\n",
1025                        obd->obd_name);
1026         RETURN(0);
1027
1028 out:
1029         dt_tunables_fini(&lod->lod_dt_dev);
1030
1031         return rc;
1032 }
1033
1034 /**
1035  * Cleanup procfs entries registred for LOD.
1036  *
1037  * \param[in] lod       LOD device
1038  */
1039 void lod_procfs_fini(struct lod_device *lod)
1040 {
1041         struct obd_device *obd = lod2obd(lod);
1042         struct kobject *lov;
1043
1044         if (lod->lod_symlink != NULL) {
1045                 lprocfs_remove(&lod->lod_symlink);
1046                 lod->lod_symlink = NULL;
1047         }
1048
1049         lov = kset_find_obj(lustre_kset, "lov");
1050         if (lov) {
1051                 sysfs_remove_link(lov, obd->obd_name);
1052                 kobject_put(lov);
1053         }
1054
1055         debugfs_remove_recursive(lod->lod_debugfs);
1056
1057         if (obd->obd_proc_entry) {
1058                 lprocfs_remove(&obd->obd_proc_entry);
1059                 obd->obd_proc_entry = NULL;
1060         }
1061
1062         dt_tunables_fini(&lod->lod_dt_dev);
1063 }
1064
1065 #endif /* CONFIG_PROC_FS */