1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
30 * Use is subject to license terms.
32 * Copyright (c) 2011 Whamcloud, Inc.
36 * This file is part of Lustre, http://www.lustre.org/
37 * Lustre is a trademark of Sun Microsystems, Inc.
39 * lustre/mdt/mdt_lproc.c
41 * Author: Lai Siyao <lsy@clusterfs.com>
42 * Author: Fan Yong <fanyong@clusterfs.com>
46 # define EXPORT_SYMTAB
48 #define DEBUG_SUBSYSTEM S_MDS
50 #include <linux/version.h>
51 #include <asm/statfs.h>
53 #include <linux/module.h>
55 /* LUSTRE_VERSION_CODE */
56 #include <lustre_ver.h>
58 * struct OBD_{ALLOC,FREE}*()
61 #include <obd_support.h>
62 /* struct obd_export */
63 #include <lustre_export.h>
64 /* struct obd_device */
66 #include <obd_class.h>
67 #include <lustre_mds.h>
68 #include <lustre_mdt.h>
69 #include <lprocfs_status.h>
71 #include "mdt_internal.h"
72 #include <lnet/lib-lnet.h>
77 static const char *mdt_proc_names[LPROC_MDT_NR] = {
81 * The rename stats output would be YAML formats, like
83 * - snapshot_time: 1234567890.123456
85 * 4kB: { samples: 1230, pct: 33, cum_pct: 45 }
86 * 8kB: { samples: 1242, pct: 33, cum_pct: 78 }
87 * 16kB: { samples: 132, pct: 3, cum_pct: 81 }
89 * 4kB: { samples: 123, pct: 33, cum_pct: 45 }
90 * 8kB: { samples: 124, pct: 33, cum_pct: 78 }
91 * 16kB: { samples: 12, pct: 3, cum_pct: 81 }
93 * 4kB: { samples: 123, pct: 33, cum_pct: 45 }
94 * 8kB: { samples: 124, pct: 33, cum_pct: 78 }
95 * 16kB: { samples: 12, pct: 3, cum_pct: 81 }
98 #define pct(a, b) (b ? a * 100 / b : 0)
100 static void display_rename_stats(struct seq_file *seq, char *name,
101 struct obd_histogram *hist)
103 unsigned long tot, t, cum = 0;
106 tot = lprocfs_oh_sum(hist);
108 seq_printf(seq, "- %-15s\n", name);
109 /* dir size start from 4K, start i from 10(2^10) here */
110 for (i = 0; i < OBD_HIST_MAX; i++) {
111 t = hist->oh_buckets[i];
117 seq_printf(seq, "%6s%d%s", " ", 1<< i, "bytes:");
119 seq_printf(seq, "%6s%d%s", " ", 1<<(i-10), "KB:");
121 seq_printf(seq, "%6s%d%s", " ", 1<<(i-20), "MB:");
123 seq_printf(seq, " { sample: %3lu, pct: %3lu, cum_pct: %3lu }\n",
124 t, pct(t, tot), pct(cum, tot));
131 static void rename_stats_show(struct seq_file *seq,
132 struct rename_stats *rename_stats)
136 /* this sampling races with updates */
137 do_gettimeofday(&now);
138 seq_printf(seq, "rename_stats:\n");
139 seq_printf(seq, "- %-15s %lu.%lu\n", "snapshot_time:",
140 now.tv_sec, now.tv_usec);
142 display_rename_stats(seq, "same_dir",
143 &rename_stats->hist[RENAME_SAMEDIR_SIZE]);
144 display_rename_stats(seq, "crossdir_src",
145 &rename_stats->hist[RENAME_CROSSDIR_SRC_SIZE]);
146 display_rename_stats(seq, "crossdir_tgt",
147 &rename_stats->hist[RENAME_CROSSDIR_TGT_SIZE]);
152 static int mdt_rename_stats_seq_show(struct seq_file *seq, void *v)
154 struct mdt_device *mdt = seq->private;
156 rename_stats_show(seq, &mdt->mdt_rename_stats);
161 static ssize_t mdt_rename_stats_seq_write(struct file *file, const char *buf,
162 size_t len, loff_t *off)
164 struct seq_file *seq = file->private_data;
165 struct mdt_device *mdt = seq->private;
168 for (i = 0; i < RENAME_LAST; i++)
169 lprocfs_oh_clear(&mdt->mdt_rename_stats.hist[i]);
174 LPROC_SEQ_FOPS(mdt_rename_stats);
176 static int lproc_mdt_attach_rename_seqstat(struct mdt_device *mdt)
178 struct lu_device *ld = &mdt->mdt_md_dev.md_lu_dev;
179 struct obd_device *obd = ld->ld_obd;
182 for (i = 0; i < RENAME_LAST; i++)
183 spin_lock_init(&mdt->mdt_rename_stats.hist[i].oh_lock);
185 return lprocfs_obd_seq_create(obd, "rename_stats", 0444,
186 &mdt_rename_stats_fops, mdt);
189 void mdt_rename_counter_tally(struct mdt_thread_info *info,
190 struct mdt_device *mdt,
191 struct obd_export *exp,
192 struct mdt_object *src,
193 struct mdt_object *tgt)
195 struct md_attr *ma = &info->mti_attr;
196 struct rename_stats *rstats = &mdt->mdt_rename_stats;
199 ma->ma_need = MA_INODE;
201 rc = mo_attr_get(info->mti_env, mdt_object_child(src), ma);
203 CERROR("%s: "DFID" attr_get, rc = %d\n",
204 exp->exp_obd->obd_name, PFID(mdt_object_fid(src)), rc);
209 mdt_counter_incr(exp, LPROC_MDT_SAMEDIR_RENAME);
210 lprocfs_oh_tally_log2(&rstats->hist[RENAME_SAMEDIR_SIZE],
211 (unsigned int)ma->ma_attr.la_size);
215 mdt_counter_incr(exp, LPROC_MDT_CROSSDIR_RENAME);
216 lprocfs_oh_tally_log2(&rstats->hist[RENAME_CROSSDIR_SRC_SIZE],
217 (unsigned int)ma->ma_attr.la_size);
219 ma->ma_need = MA_INODE;
221 rc = mo_attr_get(info->mti_env, mdt_object_child(tgt), ma);
223 CERROR("%s: "DFID" attr_get, rc = %d\n",
224 exp->exp_obd->obd_name, PFID(mdt_object_fid(tgt)), rc);
228 lprocfs_oh_tally_log2(&rstats->hist[RENAME_CROSSDIR_TGT_SIZE],
229 (unsigned int)ma->ma_attr.la_size);
232 int mdt_procfs_init(struct mdt_device *mdt, const char *name)
234 struct lu_device *ld = &mdt->mdt_md_dev.md_lu_dev;
235 struct obd_device *obd = ld->ld_obd;
236 struct lprocfs_static_vars lvars;
240 LASSERT(name != NULL);
242 lprocfs_mdt_init_vars(&lvars);
243 rc = lprocfs_obd_setup(obd, lvars.obd_vars);
245 CERROR("Can't init lprocfs, rc %d\n", rc);
248 ptlrpc_lprocfs_register_obd(obd);
250 mdt->mdt_proc_entry = obd->obd_proc_entry;
251 LASSERT(mdt->mdt_proc_entry != NULL);
253 rc = lu_time_init(&mdt->mdt_stats, mdt->mdt_proc_entry,
254 mdt_proc_names, ARRAY_SIZE(mdt_proc_names));
256 rc = lu_time_named_init(&ld->ld_site->ls_time_stats,
257 "site_time", mdt->mdt_proc_entry,
259 ARRAY_SIZE(lu_time_names));
263 obd->obd_proc_exports_entry = proc_mkdir("exports",
264 obd->obd_proc_entry);
265 if (obd->obd_proc_exports_entry)
266 lprocfs_add_simple(obd->obd_proc_exports_entry,
267 "clear", lprocfs_nid_stats_clear_read,
268 lprocfs_nid_stats_clear_write, obd, NULL);
269 rc = lprocfs_alloc_md_stats(obd, LPROC_MDT_LAST);
271 mdt_stats_counter_init(obd->md_stats);
273 rc = lproc_mdt_attach_rename_seqstat(mdt);
275 CERROR("%s: MDT can not create rename stats rc = %d\n",
281 int mdt_procfs_fini(struct mdt_device *mdt)
283 struct lu_device *ld = &mdt->mdt_md_dev.md_lu_dev;
284 struct obd_device *obd = ld->ld_obd;
286 if (obd->obd_proc_exports_entry) {
287 lprocfs_remove_proc_entry("clear", obd->obd_proc_exports_entry);
288 obd->obd_proc_exports_entry = NULL;
290 lprocfs_free_per_client_stats(obd);
291 lprocfs_obd_cleanup(obd);
292 ptlrpc_lprocfs_unregister_obd(obd);
293 if (mdt->mdt_proc_entry) {
294 lu_time_fini(&ld->ld_site->ls_time_stats);
295 lu_time_fini(&mdt->mdt_stats);
296 mdt->mdt_proc_entry = NULL;
298 lprocfs_free_md_stats(obd);
299 lprocfs_free_obd_stats(obd);
304 void mdt_time_start(const struct mdt_thread_info *info)
306 lu_lprocfs_time_start(info->mti_env);
309 void mdt_time_end(const struct mdt_thread_info *info, int idx)
311 lu_lprocfs_time_end(info->mti_env, info->mti_mdt->mdt_stats, idx);
314 static int lprocfs_rd_identity_expire(char *page, char **start, off_t off,
315 int count, int *eof, void *data)
317 struct obd_device *obd = data;
318 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
321 return snprintf(page, count, "%u\n",
322 mdt->mdt_identity_cache->uc_entry_expire);
325 static int lprocfs_wr_identity_expire(struct file *file, const char *buffer,
326 unsigned long count, void *data)
328 struct obd_device *obd = data;
329 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
332 rc = lprocfs_write_helper(buffer, count, &val);
336 mdt->mdt_identity_cache->uc_entry_expire = val;
340 static int lprocfs_rd_identity_acquire_expire(char *page, char **start,
341 off_t off, int count, int *eof,
344 struct obd_device *obd = data;
345 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
348 return snprintf(page, count, "%u\n",
349 mdt->mdt_identity_cache->uc_acquire_expire);
352 static int lprocfs_wr_identity_acquire_expire(struct file *file,
357 struct obd_device *obd = data;
358 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
361 rc = lprocfs_write_helper(buffer, count, &val);
365 mdt->mdt_identity_cache->uc_acquire_expire = val;
369 static int lprocfs_rd_identity_upcall(char *page, char **start, off_t off,
370 int count, int *eof, void *data)
372 struct obd_device *obd = data;
373 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
374 struct upcall_cache *hash = mdt->mdt_identity_cache;
378 cfs_read_lock(&hash->uc_upcall_rwlock);
379 len = snprintf(page, count, "%s\n", hash->uc_upcall);
380 cfs_read_unlock(&hash->uc_upcall_rwlock);
384 static int lprocfs_wr_identity_upcall(struct file *file, const char *buffer,
385 unsigned long count, void *data)
387 struct obd_device *obd = data;
388 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
389 struct upcall_cache *hash = mdt->mdt_identity_cache;
393 if (count >= UC_CACHE_UPCALL_MAXPATH) {
394 CERROR("%s: identity upcall too long\n", obd->obd_name);
397 OBD_ALLOC(kernbuf, count + 1);
399 GOTO(failed, rc = -ENOMEM);
400 if (cfs_copy_from_user(kernbuf, buffer, count))
401 GOTO(failed, rc = -EFAULT);
403 /* Remove any extraneous bits from the upcall (e.g. linefeeds) */
404 cfs_write_lock(&hash->uc_upcall_rwlock);
405 sscanf(kernbuf, "%s", hash->uc_upcall);
406 cfs_write_unlock(&hash->uc_upcall_rwlock);
408 if (strcmp(hash->uc_name, obd->obd_name) != 0)
409 CWARN("%s: write to upcall name %s\n",
410 obd->obd_name, hash->uc_upcall);
412 if (strcmp(hash->uc_upcall, "NONE") == 0 && mdt->mdt_opts.mo_acl)
413 CWARN("%s: disable \"identity_upcall\" with ACL enabled maybe "
414 "cause unexpected \"EACCESS\"\n", obd->obd_name);
416 CWARN("%s: identity upcall set to %s\n", obd->obd_name, hash->uc_upcall);
417 OBD_FREE(kernbuf, count + 1);
422 OBD_FREE(kernbuf, count + 1);
426 static int lprocfs_wr_identity_flush(struct file *file, const char *buffer,
427 unsigned long count, void *data)
429 struct obd_device *obd = data;
430 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
433 rc = lprocfs_write_helper(buffer, count, &uid);
437 mdt_flush_identity(mdt->mdt_identity_cache, uid);
441 static int lprocfs_wr_identity_info(struct file *file, const char *buffer,
442 unsigned long count, void *data)
444 struct obd_device *obd = data;
445 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
446 struct identity_downcall_data *param;
447 int size = sizeof(*param), rc, checked = 0;
451 CERROR("%s: invalid data count = %lu, size = %d\n",
452 obd->obd_name, count, size);
456 OBD_ALLOC(param, size);
460 if (cfs_copy_from_user(param, buffer, size)) {
461 CERROR("%s: bad identity data\n", obd->obd_name);
462 GOTO(out, rc = -EFAULT);
467 if (param->idd_magic != IDENTITY_DOWNCALL_MAGIC) {
468 CERROR("%s: MDS identity downcall bad params\n",
470 GOTO(out, rc = -EINVAL);
473 if (param->idd_nperms > N_PERMS_MAX) {
474 CERROR("%s: perm count %d more than maximum %d\n",
475 obd->obd_name, param->idd_nperms, N_PERMS_MAX);
476 GOTO(out, rc = -EINVAL);
479 if (param->idd_ngroups > NGROUPS_MAX) {
480 CERROR("%s: group count %d more than maximum %d\n",
481 obd->obd_name, param->idd_ngroups, NGROUPS_MAX);
482 GOTO(out, rc = -EINVAL);
485 if (param->idd_ngroups) {
486 rc = param->idd_ngroups; /* save idd_ngroups */
487 OBD_FREE(param, size);
488 size = offsetof(struct identity_downcall_data,
494 rc = upcall_cache_downcall(mdt->mdt_identity_cache, param->idd_err,
495 param->idd_uid, param);
499 OBD_FREE(param, size);
501 return rc ? rc : count;
505 static int lprocfs_rd_capa(char *page, char **start, off_t off,
506 int count, int *eof, void *data)
508 struct obd_device *obd = data;
509 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
511 return snprintf(page, count, "capability on: %s %s\n",
512 mdt->mdt_opts.mo_oss_capa ? "oss" : "",
513 mdt->mdt_opts.mo_mds_capa ? "mds" : "");
516 static int lprocfs_wr_capa(struct file *file, const char *buffer,
517 unsigned long count, void *data)
519 struct obd_device *obd = data;
520 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
523 rc = lprocfs_write_helper(buffer, count, &val);
527 if (val < 0 || val > 3) {
528 CERROR("invalid capability mode, only 0/2/3 is accepted.\n"
529 " 0: disable fid capability\n"
530 " 2: enable MDS fid capability\n"
531 " 3: enable both MDS and OSS fid capability\n");
535 /* OSS fid capability needs enable both MDS and OSS fid capability on
538 CERROR("can't enable OSS fid capability only, you should use "
539 "'3' to enable both MDS and OSS fid capability.\n");
543 mdt->mdt_opts.mo_oss_capa = (val & 0x1);
544 mdt->mdt_opts.mo_mds_capa = !!(val & 0x2);
545 mdt->mdt_capa_conf = 1;
546 LCONSOLE_INFO("MDS %s %s MDS fid capability.\n",
548 mdt->mdt_opts.mo_mds_capa ? "enabled" : "disabled");
549 LCONSOLE_INFO("MDS %s %s OSS fid capability.\n",
551 mdt->mdt_opts.mo_oss_capa ? "enabled" : "disabled");
555 static int lprocfs_rd_capa_count(char *page, char **start, off_t off,
556 int count, int *eof, void *data)
558 return snprintf(page, count, "%d %d\n",
559 capa_count[CAPA_SITE_CLIENT],
560 capa_count[CAPA_SITE_SERVER]);
563 static int lprocfs_rd_site_stats(char *page, char **start, off_t off,
564 int count, int *eof, void *data)
566 struct obd_device *obd = data;
567 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
569 return lu_site_stats_print(mdt_lu_site(mdt), page, count);
572 static int lprocfs_rd_capa_timeout(char *page, char **start, off_t off,
573 int count, int *eof, void *data)
575 struct obd_device *obd = data;
576 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
578 return snprintf(page, count, "%lu\n", mdt->mdt_capa_timeout);
581 static int lprocfs_wr_capa_timeout(struct file *file, const char *buffer,
582 unsigned long count, void *data)
584 struct obd_device *obd = data;
585 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
588 rc = lprocfs_write_helper(buffer, count, &val);
592 mdt->mdt_capa_timeout = (unsigned long)val;
593 mdt->mdt_capa_conf = 1;
597 static int lprocfs_rd_ck_timeout(char *page, char **start, off_t off, int count,
598 int *eof, void *data)
600 struct obd_device *obd = data;
601 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
603 return snprintf(page, count, "%lu\n", mdt->mdt_ck_timeout);
606 static int lprocfs_wr_ck_timeout(struct file *file, const char *buffer,
607 unsigned long count, void *data)
609 struct obd_device *obd = data;
610 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
613 rc = lprocfs_write_helper(buffer, count, &val);
617 mdt->mdt_ck_timeout = (unsigned long)val;
618 mdt->mdt_capa_conf = 1;
622 static int lprocfs_mdt_wr_evict_client(struct file *file, const char *buffer,
623 unsigned long count, void *data)
625 char tmpbuf[sizeof(struct obd_uuid)];
627 sscanf(buffer, "%40s", tmpbuf);
629 if (strncmp(tmpbuf, "nid:", 4) != 0)
630 return lprocfs_wr_evict_client(file, buffer, count, data);
632 CERROR("NOT implement evict client by nid %s\n", tmpbuf);
637 static int lprocfs_rd_sec_level(char *page, char **start, off_t off,
638 int count, int *eof, void *data)
640 struct obd_device *obd = data;
641 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
643 return snprintf(page, count, "%d\n", mdt->mdt_sec_level);
646 static int lprocfs_wr_sec_level(struct file *file, const char *buffer,
647 unsigned long count, void *data)
649 struct obd_device *obd = data;
650 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
653 rc = lprocfs_write_helper(buffer, count, &val);
657 if (val > LUSTRE_SEC_ALL || val < LUSTRE_SEC_NONE)
660 if (val == LUSTRE_SEC_SPECIFY) {
661 CWARN("security level %d will be supported in future.\n",
666 mdt->mdt_sec_level = val;
670 static int lprocfs_rd_cos(char *page, char **start, off_t off,
671 int count, int *eof, void *data)
673 struct obd_device *obd = data;
674 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
676 return snprintf(page, count, "%u\n", mdt_cos_is_enabled(mdt));
679 static int lprocfs_wr_cos(struct file *file, const char *buffer,
680 unsigned long count, void *data)
682 struct obd_device *obd = data;
683 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
686 rc = lprocfs_write_helper(buffer, count, &val);
689 mdt_enable_cos(mdt, val);
693 static int lprocfs_rd_root_squash(char *page, char **start, off_t off,
694 int count, int *eof, void *data)
696 struct obd_device *obd = data;
697 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
699 return snprintf(page, count, "%u:%u\n", mdt->mdt_squash_uid,
700 mdt->mdt_squash_gid);
703 static int safe_strtoul(const char *str, char **endp, unsigned long *res)
707 *res = simple_strtoul(str, endp, 0);
711 sprintf(n, "%lu", *res);
712 if (strncmp(n, str, *endp - str))
718 static int lprocfs_wr_root_squash(struct file *file, const char *buffer,
719 unsigned long count, void *data)
721 struct obd_device *obd = data;
722 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
724 char kernbuf[50], *tmp, *end, *errmsg;
725 unsigned long uid, gid;
729 if (count >= sizeof(kernbuf)) {
730 errmsg = "string too long";
731 GOTO(failed, rc = -EINVAL);
733 if (cfs_copy_from_user(kernbuf, buffer, count)) {
734 errmsg = "bad address";
735 GOTO(failed, rc = -EFAULT);
737 kernbuf[count] = '\0';
740 if (safe_strtoul(buffer, &tmp, &uid)) {
741 uid = mdt->mdt_squash_uid;
748 if (safe_strtoul(tmp, &end, &gid)) {
749 gid = mdt->mdt_squash_gid;
753 gid = mdt->mdt_squash_gid;
757 mdt->mdt_squash_uid = uid;
758 mdt->mdt_squash_gid = gid;
760 if (nouid && nogid) {
761 errmsg = "needs uid:gid format";
762 GOTO(failed, rc = -EINVAL);
765 LCONSOLE_INFO("%s: root_squash is set to %u:%u\n",
767 mdt->mdt_squash_uid, mdt->mdt_squash_gid);
771 CWARN("%s: failed to set root_squash to \"%s\", %s: rc %d\n",
772 obd->obd_name, buffer, errmsg, rc);
776 static int lprocfs_rd_nosquash_nids(char *page, char **start, off_t off,
777 int count, int *eof, void *data)
779 struct obd_device *obd = data;
780 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
782 if (mdt->mdt_nosquash_str)
783 return snprintf(page, count, "%s\n", mdt->mdt_nosquash_str);
784 return snprintf(page, count, "NONE\n");
787 static int lprocfs_wr_nosquash_nids(struct file *file, const char *buffer,
788 unsigned long count, void *data)
790 struct obd_device *obd = data;
791 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
793 char *kernbuf, *errmsg;
797 OBD_ALLOC(kernbuf, count + 1);
798 if (kernbuf == NULL) {
799 errmsg = "no memory";
800 GOTO(failed, rc = -ENOMEM);
802 if (cfs_copy_from_user(kernbuf, buffer, count)) {
803 errmsg = "bad address";
804 GOTO(failed, rc = -EFAULT);
806 kernbuf[count] = '\0';
808 if (!strcmp(kernbuf, "NONE") || !strcmp(kernbuf, "clear")) {
809 /* empty string is special case */
810 cfs_down_write(&mdt->mdt_squash_sem);
811 if (!cfs_list_empty(&mdt->mdt_nosquash_nids)) {
812 cfs_free_nidlist(&mdt->mdt_nosquash_nids);
813 OBD_FREE(mdt->mdt_nosquash_str,
814 mdt->mdt_nosquash_strlen);
815 mdt->mdt_nosquash_str = NULL;
816 mdt->mdt_nosquash_strlen = 0;
818 cfs_up_write(&mdt->mdt_squash_sem);
819 LCONSOLE_INFO("%s: nosquash_nids is cleared\n",
821 OBD_FREE(kernbuf, count + 1);
825 CFS_INIT_LIST_HEAD(&tmp);
826 if (cfs_parse_nidlist(kernbuf, count, &tmp) <= 0) {
827 errmsg = "can't parse";
828 GOTO(failed, rc = -EINVAL);
831 cfs_down_write(&mdt->mdt_squash_sem);
832 if (!cfs_list_empty(&mdt->mdt_nosquash_nids)) {
833 cfs_free_nidlist(&mdt->mdt_nosquash_nids);
834 OBD_FREE(mdt->mdt_nosquash_str, mdt->mdt_nosquash_strlen);
836 mdt->mdt_nosquash_str = kernbuf;
837 mdt->mdt_nosquash_strlen = count + 1;
838 cfs_list_splice(&tmp, &mdt->mdt_nosquash_nids);
840 LCONSOLE_INFO("%s: nosquash_nids is set to %s\n",
841 obd->obd_name, kernbuf);
842 cfs_up_write(&mdt->mdt_squash_sem);
846 CWARN("%s: failed to set nosquash_nids to \"%s\", %s: rc %d\n",
847 obd->obd_name, kernbuf, errmsg, rc);
849 OBD_FREE(kernbuf, count + 1);
853 static int lprocfs_rd_mdt_som(char *page, char **start, off_t off,
854 int count, int *eof, void *data)
856 struct obd_device *obd = data;
857 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
859 return snprintf(page, count, "%sabled\n",
860 mdt->mdt_som_conf ? "en" : "dis");
863 static int lprocfs_wr_mdt_som(struct file *file, const char *buffer,
864 unsigned long count, void *data)
866 struct obd_export *exp;
867 struct obd_device *obd = data;
868 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
870 unsigned long val = 0;
872 if (count > (sizeof(kernbuf) - 1))
875 if (cfs_copy_from_user(kernbuf, buffer, count))
878 kernbuf[count] = '\0';
880 if (!strcmp(kernbuf, "enabled"))
882 else if (strcmp(kernbuf, "disabled"))
885 if (mdt->mdt_som_conf == val)
888 if (!obd->obd_process_conf) {
889 CERROR("Temporary SOM change is not supported, use lctl "
890 "conf_param for permanent setting\n");
894 /* 1 stands for self export. */
895 cfs_list_for_each_entry(exp, &obd->obd_exports, exp_obd_chain) {
896 if (exp == obd->obd_self_export)
898 if (exp->exp_connect_flags & OBD_CONNECT_MDS_MDS)
900 /* Some clients are already connected, skip the change */
901 LCONSOLE_INFO("%s is already connected, SOM will be %s on "
902 "the next mount\n", exp->exp_client_uuid.uuid,
903 val ? "enabled" : "disabled");
907 mdt->mdt_som_conf = val;
908 LCONSOLE_INFO("Enabling SOM\n");
913 /* Temporary; for testing purposes only */
914 static int lprocfs_mdt_wr_mdc(struct file *file, const char *buffer,
915 unsigned long count, void *data)
917 struct obd_device *obd = data;
918 struct obd_export *exp = NULL;
919 struct obd_uuid uuid;
920 char tmpbuf[sizeof(struct obd_uuid)];
922 sscanf(buffer, "%40s", tmpbuf);
924 obd_str2uuid(&uuid, tmpbuf);
925 exp = cfs_hash_lookup(obd->obd_uuid_hash, &uuid);
927 CERROR("%s: no export %s found\n",
928 obd->obd_name, obd_uuid2str(&uuid));
930 mdt_hsm_copytool_send(exp);
931 class_export_put(exp);
937 static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
938 { "uuid", lprocfs_rd_uuid, 0, 0 },
939 { "recovery_status", lprocfs_obd_rd_recovery_status, 0, 0 },
940 { "num_exports", lprocfs_rd_num_exports, 0, 0 },
941 { "identity_expire", lprocfs_rd_identity_expire,
942 lprocfs_wr_identity_expire, 0 },
943 { "identity_acquire_expire", lprocfs_rd_identity_acquire_expire,
944 lprocfs_wr_identity_acquire_expire, 0 },
945 { "identity_upcall", lprocfs_rd_identity_upcall,
946 lprocfs_wr_identity_upcall, 0 },
947 { "identity_flush", 0, lprocfs_wr_identity_flush, 0 },
948 { "identity_info", 0, lprocfs_wr_identity_info, 0 },
949 { "capa", lprocfs_rd_capa,
950 lprocfs_wr_capa, 0 },
951 { "capa_timeout", lprocfs_rd_capa_timeout,
952 lprocfs_wr_capa_timeout, 0 },
953 { "capa_key_timeout", lprocfs_rd_ck_timeout,
954 lprocfs_wr_ck_timeout, 0 },
955 { "capa_count", lprocfs_rd_capa_count, 0, 0 },
956 { "site_stats", lprocfs_rd_site_stats, 0, 0 },
957 { "evict_client", 0, lprocfs_mdt_wr_evict_client, 0 },
958 { "hash_stats", lprocfs_obd_rd_hash, 0, 0 },
959 { "sec_level", lprocfs_rd_sec_level,
960 lprocfs_wr_sec_level, 0 },
961 { "commit_on_sharing", lprocfs_rd_cos, lprocfs_wr_cos, 0 },
962 { "root_squash", lprocfs_rd_root_squash,
963 lprocfs_wr_root_squash, 0 },
964 { "nosquash_nids", lprocfs_rd_nosquash_nids,
965 lprocfs_wr_nosquash_nids, 0 },
966 { "som", lprocfs_rd_mdt_som,
967 lprocfs_wr_mdt_som, 0 },
968 { "mdccomm", 0, lprocfs_mdt_wr_mdc, 0 },
969 { "instance", lprocfs_target_rd_instance, 0 },
970 { "ir_factor", lprocfs_obd_rd_ir_factor,
971 lprocfs_obd_wr_ir_factor, 0 },
975 static struct lprocfs_vars lprocfs_mdt_module_vars[] = {
976 { "num_refs", lprocfs_rd_numrefs, 0, 0 },
980 void lprocfs_mdt_init_vars(struct lprocfs_static_vars *lvars)
982 lvars->module_vars = lprocfs_mdt_module_vars;
983 lvars->obd_vars = lprocfs_mdt_obd_vars;
986 void mdt_counter_incr(struct obd_export *exp, int opcode)
988 if (exp->exp_obd && exp->exp_obd->md_stats)
989 lprocfs_counter_incr(exp->exp_obd->md_stats, opcode);
990 if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats != NULL)
991 lprocfs_counter_incr(exp->exp_nid_stats->nid_stats, opcode);
995 void mdt_stats_counter_init(struct lprocfs_stats *stats)
997 lprocfs_counter_init(stats, LPROC_MDT_OPEN, 0, "open", "reqs");
998 lprocfs_counter_init(stats, LPROC_MDT_CLOSE, 0, "close", "reqs");
999 lprocfs_counter_init(stats, LPROC_MDT_MKNOD, 0, "mknod", "reqs");
1000 lprocfs_counter_init(stats, LPROC_MDT_LINK, 0, "link", "reqs");
1001 lprocfs_counter_init(stats, LPROC_MDT_UNLINK, 0, "unlink", "reqs");
1002 lprocfs_counter_init(stats, LPROC_MDT_MKDIR, 0, "mkdir", "reqs");
1003 lprocfs_counter_init(stats, LPROC_MDT_RMDIR, 0, "rmdir", "reqs");
1004 lprocfs_counter_init(stats, LPROC_MDT_RENAME, 0, "rename", "reqs");
1005 lprocfs_counter_init(stats, LPROC_MDT_GETATTR, 0, "getattr", "reqs");
1006 lprocfs_counter_init(stats, LPROC_MDT_SETATTR, 0, "setattr", "reqs");
1007 lprocfs_counter_init(stats, LPROC_MDT_GETXATTR, 0, "getxattr", "reqs");
1008 lprocfs_counter_init(stats, LPROC_MDT_SETXATTR, 0, "setxattr", "reqs");
1009 lprocfs_counter_init(stats, LPROC_MDT_STATFS, 0, "statfs", "reqs");
1010 lprocfs_counter_init(stats, LPROC_MDT_SYNC, 0, "sync", "reqs");
1011 lprocfs_counter_init(stats, LPROC_MDT_SAMEDIR_RENAME, 0,
1012 "samedir_rename", "reqs");
1013 lprocfs_counter_init(stats, LPROC_MDT_CROSSDIR_RENAME, 0,
1014 "crossdir_rename", "reqs");