4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
27 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
28 * Use is subject to license terms.
30 * Copyright (c) 2012, 2013, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 #define DEBUG_SUBSYSTEM S_CLASS
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>
45 static int lod_stripesize_seq_show(struct seq_file *m, void *v)
47 struct obd_device *dev = m->private;
48 struct lod_device *lod;
51 lod = lu2lod_dev(dev->obd_lu_dev);
52 return seq_printf(m, LPU64"\n",
53 lod->lod_desc.ld_default_stripe_size);
57 lod_stripesize_seq_write(struct file *file, const char *buffer,
58 size_t count, loff_t *off)
60 struct seq_file *m = file->private_data;
61 struct obd_device *dev = m->private;
62 struct lod_device *lod;
67 lod = lu2lod_dev(dev->obd_lu_dev);
68 rc = lprocfs_write_u64_helper(buffer, count, &val);
72 lod_fix_desc_stripe_size(&val);
73 lod->lod_desc.ld_default_stripe_size = val;
76 LPROC_SEQ_FOPS(lod_stripesize);
78 static int lod_stripeoffset_seq_show(struct seq_file *m, void *v)
80 struct obd_device *dev = m->private;
81 struct lod_device *lod;
84 lod = lu2lod_dev(dev->obd_lu_dev);
85 return seq_printf(m, LPU64"\n",
86 lod->lod_desc.ld_default_stripe_offset);
90 lod_stripeoffset_seq_write(struct file *file, const char *buffer,
91 size_t count, loff_t *off)
93 struct seq_file *m = file->private_data;
94 struct obd_device *dev = m->private;
95 struct lod_device *lod;
100 lod = lu2lod_dev(dev->obd_lu_dev);
101 rc = lprocfs_write_u64_helper(buffer, count, &val);
105 lod->lod_desc.ld_default_stripe_offset = val;
108 LPROC_SEQ_FOPS(lod_stripeoffset);
110 static int lod_stripetype_seq_show(struct seq_file *m, void *v)
112 struct obd_device *dev = m->private;
113 struct lod_device *lod;
115 LASSERT(dev != NULL);
116 lod = lu2lod_dev(dev->obd_lu_dev);
117 return seq_printf(m, "%u\n", lod->lod_desc.ld_pattern);
121 lod_stripetype_seq_write(struct file *file, const char *buffer,
122 size_t count, loff_t *off)
124 struct seq_file *m = file->private_data;
125 struct obd_device *dev = m->private;
126 struct lod_device *lod;
129 LASSERT(dev != NULL);
130 lod = lu2lod_dev(dev->obd_lu_dev);
131 rc = lprocfs_write_helper(buffer, count, &val);
135 lod_fix_desc_pattern(&val);
136 lod->lod_desc.ld_pattern = val;
139 LPROC_SEQ_FOPS(lod_stripetype);
141 static int lod_stripecount_seq_show(struct seq_file *m, void *v)
143 struct obd_device *dev = m->private;
144 struct lod_device *lod;
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);
153 lod_stripecount_seq_write(struct file *file, const char *buffer,
154 size_t count, loff_t *off)
156 struct seq_file *m = file->private_data;
157 struct obd_device *dev = m->private;
158 struct lod_device *lod;
161 LASSERT(dev != NULL);
162 lod = lu2lod_dev(dev->obd_lu_dev);
163 rc = lprocfs_write_helper(buffer, count, &val);
167 lod_fix_desc_stripe_count(&val);
168 lod->lod_desc.ld_default_stripe_count = val;
171 LPROC_SEQ_FOPS(lod_stripecount);
173 static int lod_numobd_seq_show(struct seq_file *m, void *v)
175 struct obd_device *dev = m->private;
176 struct lod_device *lod;
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);
182 LPROC_SEQ_FOPS_RO(lod_numobd);
184 static int lod_activeobd_seq_show(struct seq_file *m, void *v)
186 struct obd_device *dev = m->private;
187 struct lod_device *lod;
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);
193 LPROC_SEQ_FOPS_RO(lod_activeobd);
195 static int lod_desc_uuid_seq_show(struct seq_file *m, void *v)
197 struct obd_device *dev = m->private;
198 struct lod_device *lod;
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);
204 LPROC_SEQ_FOPS_RO(lod_desc_uuid);
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)
209 struct obd_device *dev = m->private;
210 struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
212 LASSERT(lod != NULL);
213 return seq_printf(m, "%d%%\n",
214 (lod->lod_qos.lq_prio_free * 100 + 255) >> 8);
218 lod_qos_priofree_seq_write(struct file *file, const char __user *buffer,
219 size_t count, loff_t *off)
221 struct seq_file *m = file->private_data;
222 struct obd_device *dev = m->private;
223 struct lod_device *lod;
226 LASSERT(dev != NULL);
227 lod = lu2lod_dev(dev->obd_lu_dev);
229 rc = lprocfs_write_helper(buffer, count, &val);
235 lod->lod_qos.lq_prio_free = (val << 8) / 100;
236 lod->lod_qos.lq_dirty = 1;
237 lod->lod_qos.lq_reset = 1;
240 LPROC_SEQ_FOPS(lod_qos_priofree);
242 static int lod_qos_thresholdrr_seq_show(struct seq_file *m, void *v)
244 struct obd_device *dev = m->private;
245 struct lod_device *lod;
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);
254 lod_qos_thresholdrr_seq_write(struct file *file, const char *buffer,
255 size_t count, loff_t *off)
257 struct seq_file *m = file->private_data;
258 struct obd_device *dev = m->private;
259 struct lod_device *lod;
262 LASSERT(dev != NULL);
263 lod = lu2lod_dev(dev->obd_lu_dev);
265 rc = lprocfs_write_helper(buffer, count, &val);
269 if (val > 100 || val < 0)
272 lod->lod_qos.lq_threshold_rr = (val << 8) / 100;
273 lod->lod_qos.lq_dirty = 1;
276 LPROC_SEQ_FOPS(lod_qos_thresholdrr);
278 static int lod_qos_maxage_seq_show(struct seq_file *m, void *v)
280 struct obd_device *dev = m->private;
281 struct lod_device *lod;
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);
289 lod_qos_maxage_seq_write(struct file *file, const char *buffer,
290 size_t count, loff_t *off)
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;
302 LASSERT(dev != NULL);
303 lod = lu2lod_dev(dev->obd_lu_dev);
305 rc = lprocfs_write_helper(buffer, count, &val);
311 lod->lod_desc.ld_qos_maxage = val;
314 * propogate the value down to OSPs
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);
325 CERROR("can't set maxage on #%d: %d\n", i, rc);
327 lod_putref(lod, &lod->lod_ost_descs);
328 lustre_cfg_free(lcfg);
332 LPROC_SEQ_FOPS(lod_qos_maxage);
334 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos)
336 struct obd_device *dev = p->private;
337 struct lod_device *lod;
339 LASSERT(dev != NULL);
340 lod = lu2lod_dev(dev->obd_lu_dev);
342 lod_getref(&lod->lod_ost_descs); /* released in lod_osts_seq_stop */
343 if (*pos >= lod->lod_ost_bitmap->size)
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);
354 static void lod_osts_seq_stop(struct seq_file *p, void *v)
356 struct obd_device *dev = p->private;
357 struct lod_device *lod;
359 LASSERT(dev != NULL);
360 lod = lu2lod_dev(dev->obd_lu_dev);
361 lod_putref(lod, &lod->lod_ost_descs);
364 static void *lod_osts_seq_next(struct seq_file *p, void *v, loff_t *pos)
366 struct obd_device *dev = p->private;
367 struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
369 if (*pos >= lod->lod_ost_bitmap->size - 1)
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);
380 static int lod_osts_seq_show(struct seq_file *p, void *v)
382 struct obd_device *obd = p->private;
383 struct lod_ost_desc *ost_desc = v;
384 struct lod_device *lod;
386 struct dt_device *next;
387 struct obd_statfs sfs;
389 LASSERT(obd->obd_lu_dev);
390 lod = lu2lod_dev(obd->obd_lu_dev);
392 idx = ost_desc->ltd_index;
393 next = OST_TGT(lod,idx)->ltd_ost;
397 /* XXX: should be non-NULL env, but it's very expensive */
399 rc = dt_statfs(NULL, next, &sfs);
400 if (rc == -ENOTCONN) {
406 return seq_printf(p, "%d: %s %sACTIVE\n", idx,
407 obd_uuid2str(&ost_desc->ltd_uuid),
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,
418 static int lod_osts_seq_open(struct inode *inode, struct file *file)
420 struct seq_file *seq;
423 rc = seq_open(file, &lod_osts_sops);
427 seq = file->private_data;
428 seq->private = PDE_DATA(inode);
432 LPROC_SEQ_FOPS_RO_TYPE(lod, uuid);
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);
441 static int lod_lmv_failout_seq_show(struct seq_file *m, void *v)
443 struct obd_device *dev = m->private;
444 struct lod_device *lod;
446 LASSERT(dev != NULL);
447 lod = lu2lod_dev(dev->obd_lu_dev);
449 return seq_printf(m, "%d\n", lod->lod_lmv_failout ? 1 : 0);
453 lod_lmv_failout_seq_write(struct file *file, const char *buffer,
454 size_t count, loff_t *off)
456 struct seq_file *m = file->private_data;
457 struct obd_device *dev = m->private;
458 struct lod_device *lod;
462 LASSERT(dev != NULL);
463 lod = lu2lod_dev(dev->obd_lu_dev);
465 rc = lprocfs_write_helper(buffer, count, &val);
470 lod->lod_lmv_failout = 1;
472 lod->lod_lmv_failout = 0;
476 LPROC_SEQ_FOPS(lod_lmv_failout);
478 static struct lprocfs_seq_vars lprocfs_lod_obd_vars[] = {
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 },
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 },
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 },
516 static const struct file_operations lod_proc_target_fops = {
517 .owner = THIS_MODULE,
518 .open = lod_osts_seq_open,
521 .release = lprocfs_seq_release,
524 int lod_procfs_init(struct lod_device *lod)
526 struct obd_device *obd = lod2obd(lod);
527 struct proc_dir_entry *lov_proc_dir = NULL;
528 struct obd_type *type;
531 obd->obd_vars = lprocfs_lod_obd_vars;
532 rc = lprocfs_obd_setup(obd);
534 CERROR("%s: cannot setup procfs entry: %d\n",
539 rc = lprocfs_seq_add_vars(obd->obd_proc_entry, lprocfs_lod_osd_vars,
542 CERROR("%s: cannot setup procfs entry: %d\n",
547 rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
548 0444, &lod_proc_target_fops, obd);
550 CWARN("%s: Error adding the target_obd file %d\n",
555 lod->lod_pool_proc_entry = lprocfs_seq_register("pools",
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",
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;
573 lov_proc_dir = obd->obd_type->typ_procsym;
575 if (lov_proc_dir == NULL)
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);
587 lprocfs_obd_cleanup(obd);
592 void lod_procfs_fini(struct lod_device *lod)
594 struct obd_device *obd = lod2obd(lod);
596 if (lod->lod_symlink != NULL)
597 lprocfs_remove(&lod->lod_symlink);
599 if (lod->lod_pool_proc_entry != NULL) {
600 lprocfs_remove(&lod->lod_pool_proc_entry);
601 lod->lod_pool_proc_entry = NULL;
604 lprocfs_obd_cleanup(obd);