Whamcloud - gitweb
1598658853c59a2b47ba0e34a4e619dd002edee5
[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 struct lprocfs_seq_vars lprocfs_lod_obd_vars[] = {
441         { .name =       "uuid",
442           .fops =       &lod_uuid_fops          },
443         { .name =       "stripesize",
444           .fops =       &lod_stripesize_fops    },
445         { .name =       "stripeoffset",
446           .fops =       &lod_stripeoffset_fops  },
447         { .name =       "stripecount",
448           .fops =       &lod_stripecount_fops   },
449         { .name =       "stripetype",
450           .fops =       &lod_stripetype_fops    },
451         { .name =       "numobd",
452           .fops =       &lod_numobd_fops        },
453         { .name =       "activeobd",
454           .fops =       &lod_activeobd_fops     },
455         { .name =       "desc_uuid",
456           .fops =       &lod_desc_uuid_fops     },
457         { .name =       "qos_prio_free",
458           .fops =       &lod_qos_priofree_fops  },
459         { .name =       "qos_threshold_rr",
460           .fops =       &lod_qos_thresholdrr_fops },
461         { .name =       "qos_maxage",
462           .fops =       &lod_qos_maxage_fops    },
463         { 0 }
464 };
465
466 static struct lprocfs_seq_vars lprocfs_lod_osd_vars[] = {
467         { "blocksize",          &lod_dt_blksize_fops            },
468         { "kbytestotal",        &lod_dt_kbytestotal_fops        },
469         { "kbytesfree",         &lod_dt_kbytesfree_fops         },
470         { "kbytesavail",        &lod_dt_kbytesavail_fops        },
471         { "filestotal",         &lod_dt_filestotal_fops         },
472         { "filesfree",          &lod_dt_filesfree_fops          },
473         { 0 }
474 };
475
476 static const struct file_operations lod_proc_target_fops = {
477         .owner   = THIS_MODULE,
478         .open    = lod_osts_seq_open,
479         .read    = seq_read,
480         .llseek  = seq_lseek,
481         .release = lprocfs_seq_release,
482 };
483
484 int lod_procfs_init(struct lod_device *lod)
485 {
486         struct obd_device       *obd = lod2obd(lod);
487         struct proc_dir_entry   *lov_proc_dir = NULL;
488         struct obd_type         *type;
489         int                      rc;
490
491         obd->obd_vars = lprocfs_lod_obd_vars;
492         rc = lprocfs_seq_obd_setup(obd);
493         if (rc) {
494                 CERROR("%s: cannot setup procfs entry: %d\n",
495                        obd->obd_name, rc);
496                 RETURN(rc);
497         }
498
499         rc = lprocfs_seq_add_vars(obd->obd_proc_entry, lprocfs_lod_osd_vars,
500                                   &lod->lod_dt_dev);
501         if (rc) {
502                 CERROR("%s: cannot setup procfs entry: %d\n",
503                        obd->obd_name, rc);
504                 GOTO(out, rc);
505         }
506
507         rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
508                                 0444, &lod_proc_target_fops, obd);
509         if (rc) {
510                 CWARN("%s: Error adding the target_obd file %d\n",
511                       obd->obd_name, rc);
512                 GOTO(out, rc);
513         }
514
515         lod->lod_pool_proc_entry = lprocfs_seq_register("pools",
516                                                         obd->obd_proc_entry,
517                                                         NULL, NULL);
518         if (IS_ERR(lod->lod_pool_proc_entry)) {
519                 rc = PTR_ERR(lod->lod_pool_proc_entry);
520                 lod->lod_pool_proc_entry = NULL;
521                 CWARN("%s: Failed to create pool proc file: %d\n",
522                       obd->obd_name, rc);
523                 GOTO(out, rc);
524         }
525
526         /* If the real LOV is present which is the case for setups
527          * with both server and clients on the same node then use
528          * the LOV's proc root */
529         type = class_search_type(LUSTRE_LOV_NAME);
530         if (type != NULL && type->typ_procroot != NULL)
531                 lov_proc_dir = type->typ_procroot;
532         else
533                 lov_proc_dir = obd->obd_type->typ_procsym;
534
535         if (lov_proc_dir == NULL)
536                 RETURN(0);
537
538         /* for compatibility we link old procfs's LOV entries to lod ones */
539         lod->lod_symlink = lprocfs_add_symlink(obd->obd_name, lov_proc_dir,
540                                                "../lod/%s", obd->obd_name);
541         if (lod->lod_symlink == NULL)
542                 CERROR("could not register LOV symlink for "
543                         "/proc/fs/lustre/lod/%s.", obd->obd_name);
544         RETURN(0);
545
546 out:
547         lprocfs_obd_cleanup(obd);
548
549         return rc;
550 }
551
552 void lod_procfs_fini(struct lod_device *lod)
553 {
554         struct obd_device *obd = lod2obd(lod);
555
556         if (lod->lod_symlink != NULL)
557                 lprocfs_remove(&lod->lod_symlink);
558
559         if (lod->lod_pool_proc_entry != NULL) {
560                 lprocfs_remove(&lod->lod_pool_proc_entry);
561                 lod->lod_pool_proc_entry = NULL;
562         }
563
564         lprocfs_obd_cleanup(obd);
565 }
566
567 #endif /* LPROCFS */
568