Whamcloud - gitweb
LU-4788 lfsck: replace cfs_list_t with list_head
[fs/lustre-release.git] / lustre / lod / lproc_lod.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, 2013, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36 #define DEBUG_SUBSYSTEM S_CLASS
37
38 #include <lprocfs_status.h>
39 #include <obd_class.h>
40 #include <linux/seq_file.h>
41 #include "lod_internal.h"
42 #include <lustre_param.h>
43
44 #ifdef LPROCFS
45 static int lod_stripesize_seq_show(struct seq_file *m, void *v)
46 {
47         struct obd_device *dev = m->private;
48         struct lod_device *lod;
49
50         LASSERT(dev != NULL);
51         lod  = lu2lod_dev(dev->obd_lu_dev);
52         return seq_printf(m, LPU64"\n",
53                         lod->lod_desc.ld_default_stripe_size);
54 }
55
56 static ssize_t
57 lod_stripesize_seq_write(struct file *file, const char *buffer,
58                          size_t count, loff_t *off)
59 {
60         struct seq_file   *m = file->private_data;
61         struct obd_device *dev = m->private;
62         struct lod_device *lod;
63         __u64 val;
64         int rc;
65
66         LASSERT(dev != NULL);
67         lod  = lu2lod_dev(dev->obd_lu_dev);
68         rc = lprocfs_write_u64_helper(buffer, count, &val);
69         if (rc)
70                 return rc;
71
72         lod_fix_desc_stripe_size(&val);
73         lod->lod_desc.ld_default_stripe_size = val;
74         return count;
75 }
76 LPROC_SEQ_FOPS(lod_stripesize);
77
78 static int lod_stripeoffset_seq_show(struct seq_file *m, void *v)
79 {
80         struct obd_device *dev = m->private;
81         struct lod_device *lod;
82
83         LASSERT(dev != NULL);
84         lod  = lu2lod_dev(dev->obd_lu_dev);
85         return seq_printf(m, LPU64"\n",
86                         lod->lod_desc.ld_default_stripe_offset);
87 }
88
89 static ssize_t
90 lod_stripeoffset_seq_write(struct file *file, const char *buffer,
91                            size_t count, loff_t *off)
92 {
93         struct seq_file   *m = file->private_data;
94         struct obd_device *dev = m->private;
95         struct lod_device *lod;
96         __u64 val;
97         int rc;
98
99         LASSERT(dev != NULL);
100         lod  = lu2lod_dev(dev->obd_lu_dev);
101         rc = lprocfs_write_u64_helper(buffer, count, &val);
102         if (rc)
103                 return rc;
104
105         lod->lod_desc.ld_default_stripe_offset = val;
106         return count;
107 }
108 LPROC_SEQ_FOPS(lod_stripeoffset);
109
110 static int lod_stripetype_seq_show(struct seq_file *m, void *v)
111 {
112         struct obd_device *dev = m->private;
113         struct lod_device *lod;
114
115         LASSERT(dev != NULL);
116         lod  = lu2lod_dev(dev->obd_lu_dev);
117         return seq_printf(m, "%u\n", lod->lod_desc.ld_pattern);
118 }
119
120 static ssize_t
121 lod_stripetype_seq_write(struct file *file, const char *buffer,
122                          size_t count, loff_t *off)
123 {
124         struct seq_file   *m = file->private_data;
125         struct obd_device *dev = m->private;
126         struct lod_device *lod;
127         int val, rc;
128
129         LASSERT(dev != NULL);
130         lod  = lu2lod_dev(dev->obd_lu_dev);
131         rc = lprocfs_write_helper(buffer, count, &val);
132         if (rc)
133                 return rc;
134
135         lod_fix_desc_pattern(&val);
136         lod->lod_desc.ld_pattern = val;
137         return count;
138 }
139 LPROC_SEQ_FOPS(lod_stripetype);
140
141 static int lod_stripecount_seq_show(struct seq_file *m, void *v)
142 {
143         struct obd_device *dev = m->private;
144         struct lod_device *lod;
145
146         LASSERT(dev != NULL);
147         lod  = lu2lod_dev(dev->obd_lu_dev);
148         return seq_printf(m, "%d\n",
149                         (__s16)(lod->lod_desc.ld_default_stripe_count + 1) - 1);
150 }
151
152 static ssize_t
153 lod_stripecount_seq_write(struct file *file, const char *buffer,
154                           size_t count, loff_t *off)
155 {
156         struct seq_file   *m = file->private_data;
157         struct obd_device *dev = m->private;
158         struct lod_device *lod;
159         int val, rc;
160
161         LASSERT(dev != NULL);
162         lod  = lu2lod_dev(dev->obd_lu_dev);
163         rc = lprocfs_write_helper(buffer, count, &val);
164         if (rc)
165                 return rc;
166
167         lod_fix_desc_stripe_count(&val);
168         lod->lod_desc.ld_default_stripe_count = val;
169         return count;
170 }
171 LPROC_SEQ_FOPS(lod_stripecount);
172
173 static int lod_numobd_seq_show(struct seq_file *m, void *v)
174 {
175         struct obd_device *dev = m->private;
176         struct lod_device *lod;
177
178         LASSERT(dev != NULL);
179         lod  = lu2lod_dev(dev->obd_lu_dev);
180         return seq_printf(m, "%u\n", lod->lod_desc.ld_tgt_count);
181 }
182 LPROC_SEQ_FOPS_RO(lod_numobd);
183
184 static int lod_activeobd_seq_show(struct seq_file *m, void *v)
185 {
186         struct obd_device *dev = m->private;
187         struct lod_device *lod;
188
189         LASSERT(dev != NULL);
190         lod  = lu2lod_dev(dev->obd_lu_dev);
191         return seq_printf(m, "%u\n", lod->lod_desc.ld_active_tgt_count);
192 }
193 LPROC_SEQ_FOPS_RO(lod_activeobd);
194
195 static int lod_desc_uuid_seq_show(struct seq_file *m, void *v)
196 {
197         struct obd_device *dev = m->private;
198         struct lod_device *lod;
199
200         LASSERT(dev != NULL);
201         lod  = lu2lod_dev(dev->obd_lu_dev);
202         return seq_printf(m, "%s\n", lod->lod_desc.ld_uuid.uuid);
203 }
204 LPROC_SEQ_FOPS_RO(lod_desc_uuid);
205
206 /* free priority (0-255): how badly user wants to choose empty osts */
207 static int lod_qos_priofree_seq_show(struct seq_file *m, void *v)
208 {
209         struct obd_device *dev = m->private;
210         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
211
212         LASSERT(lod != NULL);
213         return seq_printf(m, "%d%%\n",
214                         (lod->lod_qos.lq_prio_free * 100 + 255) >> 8);
215 }
216
217 static ssize_t
218 lod_qos_priofree_seq_write(struct file *file, const char *buffer,
219                            size_t count, loff_t *off)
220 {
221         struct seq_file   *m = file->private_data;
222         struct obd_device *dev = m->private;
223         struct lod_device *lod;
224         int val, rc;
225
226         LASSERT(dev != NULL);
227         lod = lu2lod_dev(dev->obd_lu_dev);
228
229         rc = lprocfs_write_helper(buffer, count, &val);
230         if (rc)
231                 return rc;
232
233         if (val > 100)
234                 return -EINVAL;
235         lod->lod_qos.lq_prio_free = (val << 8) / 100;
236         lod->lod_qos.lq_dirty = 1;
237         lod->lod_qos.lq_reset = 1;
238         return count;
239 }
240 LPROC_SEQ_FOPS(lod_qos_priofree);
241
242 static int lod_qos_thresholdrr_seq_show(struct seq_file *m, void *v)
243 {
244         struct obd_device *dev = m->private;
245         struct lod_device *lod;
246
247         LASSERT(dev != NULL);
248         lod = lu2lod_dev(dev->obd_lu_dev);
249         return seq_printf(m, "%d%%\n",
250                         (lod->lod_qos.lq_threshold_rr * 100 + 255) >> 8);
251 }
252
253 static ssize_t
254 lod_qos_thresholdrr_seq_write(struct file *file, const char *buffer,
255                               size_t count, loff_t *off)
256 {
257         struct seq_file   *m = file->private_data;
258         struct obd_device *dev = m->private;
259         struct lod_device *lod;
260         int val, rc;
261
262         LASSERT(dev != NULL);
263         lod = lu2lod_dev(dev->obd_lu_dev);
264
265         rc = lprocfs_write_helper(buffer, count, &val);
266         if (rc)
267                 return rc;
268
269         if (val > 100 || val < 0)
270                 return -EINVAL;
271
272         lod->lod_qos.lq_threshold_rr = (val << 8) / 100;
273         lod->lod_qos.lq_dirty = 1;
274         return count;
275 }
276 LPROC_SEQ_FOPS(lod_qos_thresholdrr);
277
278 static int lod_qos_maxage_seq_show(struct seq_file *m, void *v)
279 {
280         struct obd_device *dev = m->private;
281         struct lod_device *lod;
282
283         LASSERT(dev != NULL);
284         lod = lu2lod_dev(dev->obd_lu_dev);
285         return seq_printf(m, "%u Sec\n", lod->lod_desc.ld_qos_maxage);
286 }
287
288 static ssize_t
289 lod_qos_maxage_seq_write(struct file *file, const char *buffer,
290                          size_t count, loff_t *off)
291 {
292         struct seq_file         *m = file->private_data;
293         struct obd_device       *dev = m->private;
294         struct lustre_cfg_bufs   bufs;
295         struct lod_device       *lod;
296         struct lu_device        *next;
297         struct lustre_cfg       *lcfg;
298         char                     str[32];
299         unsigned int             i;
300         int                      val, rc;
301
302         LASSERT(dev != NULL);
303         lod = lu2lod_dev(dev->obd_lu_dev);
304
305         rc = lprocfs_write_helper(buffer, count, &val);
306         if (rc)
307                 return rc;
308
309         if (val <= 0)
310                 return -EINVAL;
311         lod->lod_desc.ld_qos_maxage = val;
312
313         /*
314          * propogate the value down to OSPs
315          */
316         lustre_cfg_bufs_reset(&bufs, NULL);
317         sprintf(str, "%smaxage=%d", PARAM_OSP, val);
318         lustre_cfg_bufs_set_string(&bufs, 1, str);
319         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
320         lod_getref(&lod->lod_ost_descs);
321         lod_foreach_ost(lod, i) {
322                 next = &OST_TGT(lod,i)->ltd_ost->dd_lu_dev;
323                 rc = next->ld_ops->ldo_process_config(NULL, next, lcfg);
324                 if (rc)
325                         CERROR("can't set maxage on #%d: %d\n", i, rc);
326         }
327         lod_putref(lod, &lod->lod_ost_descs);
328         lustre_cfg_free(lcfg);
329
330         return count;
331 }
332 LPROC_SEQ_FOPS(lod_qos_maxage);
333
334 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos)
335 {
336         struct obd_device *dev = p->private;
337         struct lod_device *lod;
338
339         LASSERT(dev != NULL);
340         lod = lu2lod_dev(dev->obd_lu_dev);
341
342         lod_getref(&lod->lod_ost_descs); /* released in lod_osts_seq_stop */
343         if (*pos >= lod->lod_ost_bitmap->size)
344                 return NULL;
345
346         *pos = find_next_bit(lod->lod_ost_bitmap->data,
347                                  lod->lod_ost_bitmap->size, *pos);
348         if (*pos < lod->lod_ost_bitmap->size)
349                 return OST_TGT(lod,*pos);
350         else
351                 return NULL;
352 }
353
354 static void lod_osts_seq_stop(struct seq_file *p, void *v)
355 {
356         struct obd_device *dev = p->private;
357         struct lod_device *lod;
358
359         LASSERT(dev != NULL);
360         lod = lu2lod_dev(dev->obd_lu_dev);
361         lod_putref(lod, &lod->lod_ost_descs);
362 }
363
364 static void *lod_osts_seq_next(struct seq_file *p, void *v, loff_t *pos)
365 {
366         struct obd_device *dev = p->private;
367         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
368
369         if (*pos >= lod->lod_ost_bitmap->size - 1)
370                 return NULL;
371
372         *pos = find_next_bit(lod->lod_ost_bitmap->data,
373                                  lod->lod_ost_bitmap->size, *pos + 1);
374         if (*pos < lod->lod_ost_bitmap->size)
375                 return OST_TGT(lod,*pos);
376         else
377                 return NULL;
378 }
379
380 static int lod_osts_seq_show(struct seq_file *p, void *v)
381 {
382         struct obd_device   *obd = p->private;
383         struct lod_ost_desc *ost_desc = v;
384         struct lod_device   *lod;
385         int                  idx, rc, active;
386         struct dt_device    *next;
387         struct obd_statfs    sfs;
388
389         LASSERT(obd->obd_lu_dev);
390         lod = lu2lod_dev(obd->obd_lu_dev);
391
392         idx = ost_desc->ltd_index;
393         next = OST_TGT(lod,idx)->ltd_ost;
394         if (next == NULL)
395                 return -EINVAL;
396
397         /* XXX: should be non-NULL env, but it's very expensive */
398         active = 1;
399         rc = dt_statfs(NULL, next, &sfs);
400         if (rc == -ENOTCONN) {
401                 active = 0;
402                 rc = 0;
403         } else if (rc)
404                 return rc;
405
406         return seq_printf(p, "%d: %s %sACTIVE\n", idx,
407                           obd_uuid2str(&ost_desc->ltd_uuid),
408                           active ? "" : "IN");
409 }
410
411 static const struct seq_operations lod_osts_sops = {
412         .start  = lod_osts_seq_start,
413         .stop   = lod_osts_seq_stop,
414         .next   = lod_osts_seq_next,
415         .show   = lod_osts_seq_show,
416 };
417
418 static int lod_osts_seq_open(struct inode *inode, struct file *file)
419 {
420         struct seq_file *seq;
421         int rc;
422
423         rc = seq_open(file, &lod_osts_sops);
424         if (rc)
425                 return rc;
426
427         seq = file->private_data;
428         seq->private = PDE_DATA(inode);
429         return 0;
430 }
431
432 LPROC_SEQ_FOPS_RO_TYPE(lod, uuid);
433
434 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_blksize);
435 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytestotal);
436 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytesfree);
437 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytesavail);
438 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filestotal);
439 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filesfree);
440
441 static int lod_lmv_failout_seq_show(struct seq_file *m, void *v)
442 {
443         struct obd_device *dev = m->private;
444         struct lod_device *lod;
445
446         LASSERT(dev != NULL);
447         lod = lu2lod_dev(dev->obd_lu_dev);
448
449         return seq_printf(m, "%d\n", lod->lod_lmv_failout ? 1 : 0);
450 }
451
452 static ssize_t
453 lod_lmv_failout_seq_write(struct file *file, const char *buffer,
454                           size_t count, loff_t *off)
455 {
456         struct seq_file         *m      = file->private_data;
457         struct obd_device       *dev    = m->private;
458         struct lod_device       *lod;
459         int                      val    = 0;
460         int                      rc;
461
462         LASSERT(dev != NULL);
463         lod = lu2lod_dev(dev->obd_lu_dev);
464
465         rc = lprocfs_write_helper(buffer, count, &val);
466         if (rc != 0)
467                 return rc;
468
469         if (val != 0)
470                 lod->lod_lmv_failout = 1;
471         else
472                 lod->lod_lmv_failout = 0;
473
474         return count;
475 }
476 LPROC_SEQ_FOPS(lod_lmv_failout);
477
478 static struct lprocfs_seq_vars lprocfs_lod_obd_vars[] = {
479         { .name =       "uuid",
480           .fops =       &lod_uuid_fops          },
481         { .name =       "stripesize",
482           .fops =       &lod_stripesize_fops    },
483         { .name =       "stripeoffset",
484           .fops =       &lod_stripeoffset_fops  },
485         { .name =       "stripecount",
486           .fops =       &lod_stripecount_fops   },
487         { .name =       "stripetype",
488           .fops =       &lod_stripetype_fops    },
489         { .name =       "numobd",
490           .fops =       &lod_numobd_fops        },
491         { .name =       "activeobd",
492           .fops =       &lod_activeobd_fops     },
493         { .name =       "desc_uuid",
494           .fops =       &lod_desc_uuid_fops     },
495         { .name =       "qos_prio_free",
496           .fops =       &lod_qos_priofree_fops  },
497         { .name =       "qos_threshold_rr",
498           .fops =       &lod_qos_thresholdrr_fops },
499         { .name =       "qos_maxage",
500           .fops =       &lod_qos_maxage_fops    },
501         { .name =       "lmv_failout",
502           .fops =       &lod_lmv_failout_fops   },
503         { 0 }
504 };
505
506 static struct lprocfs_seq_vars lprocfs_lod_osd_vars[] = {
507         { "blocksize",          &lod_dt_blksize_fops            },
508         { "kbytestotal",        &lod_dt_kbytestotal_fops        },
509         { "kbytesfree",         &lod_dt_kbytesfree_fops         },
510         { "kbytesavail",        &lod_dt_kbytesavail_fops        },
511         { "filestotal",         &lod_dt_filestotal_fops         },
512         { "filesfree",          &lod_dt_filesfree_fops          },
513         { 0 }
514 };
515
516 static const struct file_operations lod_proc_target_fops = {
517         .owner   = THIS_MODULE,
518         .open    = lod_osts_seq_open,
519         .read    = seq_read,
520         .llseek  = seq_lseek,
521         .release = lprocfs_seq_release,
522 };
523
524 int lod_procfs_init(struct lod_device *lod)
525 {
526         struct obd_device       *obd = lod2obd(lod);
527         struct proc_dir_entry   *lov_proc_dir = NULL;
528         struct obd_type         *type;
529         int                      rc;
530
531         obd->obd_vars = lprocfs_lod_obd_vars;
532         rc = lprocfs_seq_obd_setup(obd);
533         if (rc) {
534                 CERROR("%s: cannot setup procfs entry: %d\n",
535                        obd->obd_name, rc);
536                 RETURN(rc);
537         }
538
539         rc = lprocfs_seq_add_vars(obd->obd_proc_entry, lprocfs_lod_osd_vars,
540                                   &lod->lod_dt_dev);
541         if (rc) {
542                 CERROR("%s: cannot setup procfs entry: %d\n",
543                        obd->obd_name, rc);
544                 GOTO(out, rc);
545         }
546
547         rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
548                                 0444, &lod_proc_target_fops, obd);
549         if (rc) {
550                 CWARN("%s: Error adding the target_obd file %d\n",
551                       obd->obd_name, rc);
552                 GOTO(out, rc);
553         }
554
555         lod->lod_pool_proc_entry = lprocfs_seq_register("pools",
556                                                         obd->obd_proc_entry,
557                                                         NULL, NULL);
558         if (IS_ERR(lod->lod_pool_proc_entry)) {
559                 rc = PTR_ERR(lod->lod_pool_proc_entry);
560                 lod->lod_pool_proc_entry = NULL;
561                 CWARN("%s: Failed to create pool proc file: %d\n",
562                       obd->obd_name, rc);
563                 GOTO(out, rc);
564         }
565
566         /* If the real LOV is present which is the case for setups
567          * with both server and clients on the same node then use
568          * the LOV's proc root */
569         type = class_search_type(LUSTRE_LOV_NAME);
570         if (type != NULL && type->typ_procroot != NULL)
571                 lov_proc_dir = type->typ_procroot;
572         else
573                 lov_proc_dir = obd->obd_type->typ_procsym;
574
575         if (lov_proc_dir == NULL)
576                 RETURN(0);
577
578         /* for compatibility we link old procfs's LOV entries to lod ones */
579         lod->lod_symlink = lprocfs_add_symlink(obd->obd_name, lov_proc_dir,
580                                                "../lod/%s", obd->obd_name);
581         if (lod->lod_symlink == NULL)
582                 CERROR("could not register LOV symlink for "
583                         "/proc/fs/lustre/lod/%s.", obd->obd_name);
584         RETURN(0);
585
586 out:
587         lprocfs_obd_cleanup(obd);
588
589         return rc;
590 }
591
592 void lod_procfs_fini(struct lod_device *lod)
593 {
594         struct obd_device *obd = lod2obd(lod);
595
596         if (lod->lod_symlink != NULL)
597                 lprocfs_remove(&lod->lod_symlink);
598
599         if (lod->lod_pool_proc_entry != NULL) {
600                 lprocfs_remove(&lod->lod_pool_proc_entry);
601                 lod->lod_pool_proc_entry = NULL;
602         }
603
604         lprocfs_obd_cleanup(obd);
605 }
606
607 #endif /* LPROCFS */
608