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