Whamcloud - gitweb
b2318bbf54e782575877c19033afc38a0cec2526
[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         int                      val, rc, i;
300
301         LASSERT(dev != NULL);
302         lod = lu2lod_dev(dev->obd_lu_dev);
303
304         rc = lprocfs_write_helper(buffer, count, &val);
305         if (rc)
306                 return rc;
307
308         if (val <= 0)
309                 return -EINVAL;
310         lod->lod_desc.ld_qos_maxage = val;
311
312         /*
313          * propogate the value down to OSPs
314          */
315         lustre_cfg_bufs_reset(&bufs, NULL);
316         sprintf(str, "%smaxage=%d", PARAM_OSP, val);
317         lustre_cfg_bufs_set_string(&bufs, 1, str);
318         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
319         lod_getref(&lod->lod_ost_descs);
320         lod_foreach_ost(lod, i) {
321                 next = &OST_TGT(lod,i)->ltd_ost->dd_lu_dev;
322                 rc = next->ld_ops->ldo_process_config(NULL, next, lcfg);
323                 if (rc)
324                         CERROR("can't set maxage on #%d: %d\n", i, rc);
325         }
326         lod_putref(lod, &lod->lod_ost_descs);
327         lustre_cfg_free(lcfg);
328
329         return count;
330 }
331 LPROC_SEQ_FOPS(lod_qos_maxage);
332
333 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos)
334 {
335         struct obd_device *dev = p->private;
336         struct lod_device *lod;
337
338         LASSERT(dev != NULL);
339         lod = lu2lod_dev(dev->obd_lu_dev);
340
341         lod_getref(&lod->lod_ost_descs); /* released in lod_osts_seq_stop */
342         if (*pos >= lod->lod_ost_bitmap->size)
343                 return NULL;
344
345         *pos = find_next_bit(lod->lod_ost_bitmap->data,
346                                  lod->lod_ost_bitmap->size, *pos);
347         if (*pos < lod->lod_ost_bitmap->size)
348                 return OST_TGT(lod,*pos);
349         else
350                 return NULL;
351 }
352
353 static void lod_osts_seq_stop(struct seq_file *p, void *v)
354 {
355         struct obd_device *dev = p->private;
356         struct lod_device *lod;
357
358         LASSERT(dev != NULL);
359         lod = lu2lod_dev(dev->obd_lu_dev);
360         lod_putref(lod, &lod->lod_ost_descs);
361 }
362
363 static void *lod_osts_seq_next(struct seq_file *p, void *v, loff_t *pos)
364 {
365         struct obd_device *dev = p->private;
366         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
367
368         if (*pos >= lod->lod_ost_bitmap->size - 1)
369                 return NULL;
370
371         *pos = find_next_bit(lod->lod_ost_bitmap->data,
372                                  lod->lod_ost_bitmap->size, *pos + 1);
373         if (*pos < lod->lod_ost_bitmap->size)
374                 return OST_TGT(lod,*pos);
375         else
376                 return NULL;
377 }
378
379 static int lod_osts_seq_show(struct seq_file *p, void *v)
380 {
381         struct obd_device   *obd = p->private;
382         struct lod_ost_desc *ost_desc = v;
383         struct lod_device   *lod;
384         int                  idx, rc, active;
385         struct dt_device    *next;
386         struct obd_statfs    sfs;
387
388         LASSERT(obd->obd_lu_dev);
389         lod = lu2lod_dev(obd->obd_lu_dev);
390
391         idx = ost_desc->ltd_index;
392         next = OST_TGT(lod,idx)->ltd_ost;
393         if (next == NULL)
394                 return -EINVAL;
395
396         /* XXX: should be non-NULL env, but it's very expensive */
397         active = 1;
398         rc = dt_statfs(NULL, next, &sfs);
399         if (rc == -ENOTCONN) {
400                 active = 0;
401                 rc = 0;
402         } else if (rc)
403                 return rc;
404
405         return seq_printf(p, "%d: %s %sACTIVE\n", idx,
406                           obd_uuid2str(&ost_desc->ltd_uuid),
407                           active ? "" : "IN");
408 }
409
410 static const struct seq_operations lod_osts_sops = {
411         .start  = lod_osts_seq_start,
412         .stop   = lod_osts_seq_stop,
413         .next   = lod_osts_seq_next,
414         .show   = lod_osts_seq_show,
415 };
416
417 static int lod_osts_seq_open(struct inode *inode, struct file *file)
418 {
419         struct seq_file *seq;
420         int rc;
421
422         rc = seq_open(file, &lod_osts_sops);
423         if (rc)
424                 return rc;
425
426         seq = file->private_data;
427         seq->private = PDE_DATA(inode);
428         return 0;
429 }
430
431 LPROC_SEQ_FOPS_RO_TYPE(lod, uuid);
432
433 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_blksize);
434 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytestotal);
435 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytesfree);
436 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_kbytesavail);
437 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filestotal);
438 LPROC_SEQ_FOPS_RO_TYPE(lod, dt_filesfree);
439
440 static int lod_lmv_failout_seq_show(struct seq_file *m, void *v)
441 {
442         struct obd_device *dev = m->private;
443         struct lod_device *lod;
444
445         LASSERT(dev != NULL);
446         lod = lu2lod_dev(dev->obd_lu_dev);
447
448         return seq_printf(m, "%d\n", lod->lod_lmv_failout ? 1 : 0);
449 }
450
451 static ssize_t
452 lod_lmv_failout_seq_write(struct file *file, const char *buffer,
453                           size_t count, loff_t *off)
454 {
455         struct seq_file         *m      = file->private_data;
456         struct obd_device       *dev    = m->private;
457         struct lod_device       *lod;
458         int                      val    = 0;
459         int                      rc;
460
461         LASSERT(dev != NULL);
462         lod = lu2lod_dev(dev->obd_lu_dev);
463
464         rc = lprocfs_write_helper(buffer, count, &val);
465         if (rc != 0)
466                 return rc;
467
468         if (val != 0)
469                 lod->lod_lmv_failout = 1;
470         else
471                 lod->lod_lmv_failout = 0;
472
473         return count;
474 }
475 LPROC_SEQ_FOPS(lod_lmv_failout);
476
477 static struct lprocfs_seq_vars lprocfs_lod_obd_vars[] = {
478         { .name =       "uuid",
479           .fops =       &lod_uuid_fops          },
480         { .name =       "stripesize",
481           .fops =       &lod_stripesize_fops    },
482         { .name =       "stripeoffset",
483           .fops =       &lod_stripeoffset_fops  },
484         { .name =       "stripecount",
485           .fops =       &lod_stripecount_fops   },
486         { .name =       "stripetype",
487           .fops =       &lod_stripetype_fops    },
488         { .name =       "numobd",
489           .fops =       &lod_numobd_fops        },
490         { .name =       "activeobd",
491           .fops =       &lod_activeobd_fops     },
492         { .name =       "desc_uuid",
493           .fops =       &lod_desc_uuid_fops     },
494         { .name =       "qos_prio_free",
495           .fops =       &lod_qos_priofree_fops  },
496         { .name =       "qos_threshold_rr",
497           .fops =       &lod_qos_thresholdrr_fops },
498         { .name =       "qos_maxage",
499           .fops =       &lod_qos_maxage_fops    },
500         { .name =       "lmv_failout",
501           .fops =       &lod_lmv_failout_fops   },
502         { 0 }
503 };
504
505 static struct lprocfs_seq_vars lprocfs_lod_osd_vars[] = {
506         { "blocksize",          &lod_dt_blksize_fops            },
507         { "kbytestotal",        &lod_dt_kbytestotal_fops        },
508         { "kbytesfree",         &lod_dt_kbytesfree_fops         },
509         { "kbytesavail",        &lod_dt_kbytesavail_fops        },
510         { "filestotal",         &lod_dt_filestotal_fops         },
511         { "filesfree",          &lod_dt_filesfree_fops          },
512         { 0 }
513 };
514
515 static const struct file_operations lod_proc_target_fops = {
516         .owner   = THIS_MODULE,
517         .open    = lod_osts_seq_open,
518         .read    = seq_read,
519         .llseek  = seq_lseek,
520         .release = lprocfs_seq_release,
521 };
522
523 int lod_procfs_init(struct lod_device *lod)
524 {
525         struct obd_device       *obd = lod2obd(lod);
526         struct proc_dir_entry   *lov_proc_dir = NULL;
527         struct obd_type         *type;
528         int                      rc;
529
530         obd->obd_vars = lprocfs_lod_obd_vars;
531         rc = lprocfs_seq_obd_setup(obd);
532         if (rc) {
533                 CERROR("%s: cannot setup procfs entry: %d\n",
534                        obd->obd_name, rc);
535                 RETURN(rc);
536         }
537
538         rc = lprocfs_seq_add_vars(obd->obd_proc_entry, lprocfs_lod_osd_vars,
539                                   &lod->lod_dt_dev);
540         if (rc) {
541                 CERROR("%s: cannot setup procfs entry: %d\n",
542                        obd->obd_name, rc);
543                 GOTO(out, rc);
544         }
545
546         rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
547                                 0444, &lod_proc_target_fops, obd);
548         if (rc) {
549                 CWARN("%s: Error adding the target_obd file %d\n",
550                       obd->obd_name, rc);
551                 GOTO(out, rc);
552         }
553
554         lod->lod_pool_proc_entry = lprocfs_seq_register("pools",
555                                                         obd->obd_proc_entry,
556                                                         NULL, NULL);
557         if (IS_ERR(lod->lod_pool_proc_entry)) {
558                 rc = PTR_ERR(lod->lod_pool_proc_entry);
559                 lod->lod_pool_proc_entry = NULL;
560                 CWARN("%s: Failed to create pool proc file: %d\n",
561                       obd->obd_name, rc);
562                 GOTO(out, rc);
563         }
564
565         /* If the real LOV is present which is the case for setups
566          * with both server and clients on the same node then use
567          * the LOV's proc root */
568         type = class_search_type(LUSTRE_LOV_NAME);
569         if (type != NULL && type->typ_procroot != NULL)
570                 lov_proc_dir = type->typ_procroot;
571         else
572                 lov_proc_dir = obd->obd_type->typ_procsym;
573
574         if (lov_proc_dir == NULL)
575                 RETURN(0);
576
577         /* for compatibility we link old procfs's LOV entries to lod ones */
578         lod->lod_symlink = lprocfs_add_symlink(obd->obd_name, lov_proc_dir,
579                                                "../lod/%s", obd->obd_name);
580         if (lod->lod_symlink == NULL)
581                 CERROR("could not register LOV symlink for "
582                         "/proc/fs/lustre/lod/%s.", obd->obd_name);
583         RETURN(0);
584
585 out:
586         lprocfs_obd_cleanup(obd);
587
588         return rc;
589 }
590
591 void lod_procfs_fini(struct lod_device *lod)
592 {
593         struct obd_device *obd = lod2obd(lod);
594
595         if (lod->lod_symlink != NULL)
596                 lprocfs_remove(&lod->lod_symlink);
597
598         if (lod->lod_pool_proc_entry != NULL) {
599                 lprocfs_remove(&lod->lod_pool_proc_entry);
600                 lod->lod_pool_proc_entry = NULL;
601         }
602
603         lprocfs_obd_cleanup(obd);
604 }
605
606 #endif /* LPROCFS */
607