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 *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;
301 LASSERT(dev != NULL);
302 lod = lu2lod_dev(dev->obd_lu_dev);
304 rc = lprocfs_write_helper(buffer, count, &val);
310 lod->lod_desc.ld_qos_maxage = val;
313 * propogate the value down to OSPs
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);
324 CERROR("can't set maxage on #%d: %d\n", i, rc);
326 lod_putref(lod, &lod->lod_ost_descs);
327 lustre_cfg_free(lcfg);
331 LPROC_SEQ_FOPS(lod_qos_maxage);
333 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos)
335 struct obd_device *dev = p->private;
336 struct lod_device *lod;
338 LASSERT(dev != NULL);
339 lod = lu2lod_dev(dev->obd_lu_dev);
341 lod_getref(&lod->lod_ost_descs); /* released in lod_osts_seq_stop */
342 if (*pos >= lod->lod_ost_bitmap->size)
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);
353 static void lod_osts_seq_stop(struct seq_file *p, void *v)
355 struct obd_device *dev = p->private;
356 struct lod_device *lod;
358 LASSERT(dev != NULL);
359 lod = lu2lod_dev(dev->obd_lu_dev);
360 lod_putref(lod, &lod->lod_ost_descs);
363 static void *lod_osts_seq_next(struct seq_file *p, void *v, loff_t *pos)
365 struct obd_device *dev = p->private;
366 struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
368 if (*pos >= lod->lod_ost_bitmap->size - 1)
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);
379 static int lod_osts_seq_show(struct seq_file *p, void *v)
381 struct obd_device *obd = p->private;
382 struct lod_ost_desc *ost_desc = v;
383 struct lod_device *lod;
385 struct dt_device *next;
386 struct obd_statfs sfs;
388 LASSERT(obd->obd_lu_dev);
389 lod = lu2lod_dev(obd->obd_lu_dev);
391 idx = ost_desc->ltd_index;
392 next = OST_TGT(lod,idx)->ltd_ost;
396 /* XXX: should be non-NULL env, but it's very expensive */
398 rc = dt_statfs(NULL, next, &sfs);
399 if (rc == -ENOTCONN) {
405 return seq_printf(p, "%d: %s %sACTIVE\n", idx,
406 obd_uuid2str(&ost_desc->ltd_uuid),
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,
417 static int lod_osts_seq_open(struct inode *inode, struct file *file)
419 struct seq_file *seq;
422 rc = seq_open(file, &lod_osts_sops);
426 seq = file->private_data;
427 seq->private = PDE_DATA(inode);
431 LPROC_SEQ_FOPS_RO_TYPE(lod, uuid);
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);
440 static struct lprocfs_seq_vars lprocfs_lod_obd_vars[] = {
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 },
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 },
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 },
476 static const struct file_operations lod_proc_target_fops = {
477 .owner = THIS_MODULE,
478 .open = lod_osts_seq_open,
481 .release = lprocfs_seq_release,
484 int lod_procfs_init(struct lod_device *lod)
486 struct obd_device *obd = lod2obd(lod);
487 struct proc_dir_entry *lov_proc_dir = NULL;
488 struct obd_type *type;
491 obd->obd_vars = lprocfs_lod_obd_vars;
492 rc = lprocfs_seq_obd_setup(obd);
494 CERROR("%s: cannot setup procfs entry: %d\n",
499 rc = lprocfs_seq_add_vars(obd->obd_proc_entry, lprocfs_lod_osd_vars,
502 CERROR("%s: cannot setup procfs entry: %d\n",
507 rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
508 0444, &lod_proc_target_fops, obd);
510 CWARN("%s: Error adding the target_obd file %d\n",
515 lod->lod_pool_proc_entry = lprocfs_seq_register("pools",
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",
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;
533 lov_proc_dir = obd->obd_type->typ_procsym;
535 if (lov_proc_dir == NULL)
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);
547 lprocfs_obd_cleanup(obd);
552 void lod_procfs_fini(struct lod_device *lod)
554 struct obd_device *obd = lod2obd(lod);
556 if (lod->lod_symlink != NULL)
557 lprocfs_remove(&lod->lod_symlink);
559 if (lod->lod_pool_proc_entry != NULL) {
560 lprocfs_remove(&lod->lod_pool_proc_entry);
561 lod->lod_pool_proc_entry = NULL;
564 lprocfs_obd_cleanup(obd);