1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2004-2006 Cluster File Systems, Inc.
5 * Author: Lai Siyao <lsy@clusterfs.com>
6 * Author: Fan Yong <fanyong@clusterfs.com>
8 * This file is part of the Lustre file system, http://www.lustre.org
9 * Lustre is a trademark of Cluster File Systems, Inc.
11 * You may have signed or agreed to another license before downloading
12 * this software. If so, you are bound by the terms and conditions
13 * of that agreement, and the following does not apply to you. See the
14 * LICENSE file included with this distribution for more information.
16 * If you did not agree to a different license, then this copy of Lustre
17 * is open source software; you can redistribute it and/or modify it
18 * under the terms of version 2 of the GNU General Public License as
19 * published by the Free Software Foundation.
21 * In either case, Lustre is distributed in the hope that it will be
22 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
23 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * license text for more details.
29 # define EXPORT_SYMTAB
31 #define DEBUG_SUBSYSTEM S_MDS
33 #include <linux/version.h>
34 #include <asm/statfs.h>
36 #include <linux/module.h>
38 /* LUSTRE_VERSION_CODE */
39 #include <lustre_ver.h>
41 * struct OBD_{ALLOC,FREE}*()
44 #include <obd_support.h>
45 /* struct obd_export */
46 #include <lustre_export.h>
47 /* struct obd_device */
49 #include <obd_class.h>
50 #include <lustre_mds.h>
51 #include <lustre_mdt.h>
52 #include <lprocfs_status.h>
54 #include "mdt_internal.h"
56 static const char *mdt_proc_names[LPROC_MDT_NR] = {
59 int mdt_procfs_init(struct mdt_device *mdt, const char *name)
61 struct lu_device *ld = &mdt->mdt_md_dev.md_lu_dev;
65 LASSERT(name != NULL);
66 mdt->mdt_proc_entry = ld->ld_obd->obd_proc_entry;
67 LASSERT(mdt->mdt_proc_entry != NULL);
69 result = lu_time_init(&mdt->mdt_stats, mdt->mdt_proc_entry,
70 mdt_proc_names, ARRAY_SIZE(mdt_proc_names));
72 result = lu_time_named_init(&ld->ld_site->ls_time_stats,
73 "site_time", mdt->mdt_proc_entry,
75 ARRAY_SIZE(lu_time_names));
79 int mdt_procfs_fini(struct mdt_device *mdt)
81 struct lu_device *ld = &mdt->mdt_md_dev.md_lu_dev;
82 lu_time_fini(&ld->ld_site->ls_time_stats);
83 lu_time_fini(&mdt->mdt_stats);
84 mdt->mdt_proc_entry = NULL;
88 void mdt_time_start(const struct mdt_thread_info *info)
90 lu_lprocfs_time_start(info->mti_env);
93 void mdt_time_end(const struct mdt_thread_info *info, int idx)
95 lu_lprocfs_time_end(info->mti_env, info->mti_mdt->mdt_stats, idx);
98 static int lprocfs_rd_identity_expire(char *page, char **start, off_t off,
99 int count, int *eof, void *data)
101 struct obd_device *obd = data;
102 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
105 return snprintf(page, count, "%lu\n",
106 mdt->mdt_identity_cache->uc_entry_expire / HZ);
109 static int lprocfs_wr_identity_expire(struct file *file, const char *buffer,
110 unsigned long count, void *data)
112 struct obd_device *obd = data;
113 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
116 rc = lprocfs_write_helper(buffer, count, &val);
120 mdt->mdt_identity_cache->uc_entry_expire = val * HZ;
124 static int lprocfs_rd_identity_acquire_expire(char *page, char **start,
125 off_t off, int count, int *eof,
128 struct obd_device *obd = data;
129 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
132 return snprintf(page, count, "%lu\n",
133 mdt->mdt_identity_cache->uc_acquire_expire / HZ);
136 static int lprocfs_wr_identity_acquire_expire(struct file *file,
141 struct obd_device *obd = data;
142 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
145 rc = lprocfs_write_helper(buffer, count, &val);
149 mdt->mdt_identity_cache->uc_acquire_expire = val * HZ;
153 static int lprocfs_rd_identity_upcall(char *page, char **start, off_t off,
154 int count, int *eof, void *data)
156 struct obd_device *obd = data;
157 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
160 return snprintf(page, count, "%s\n",
161 mdt->mdt_identity_cache->uc_upcall);
164 static int lprocfs_wr_identity_upcall(struct file *file, const char *buffer,
165 unsigned long count, void *data)
167 struct obd_device *obd = data;
168 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
169 struct upcall_cache *hash = mdt->mdt_identity_cache;
170 char kernbuf[UC_CACHE_UPCALL_MAXPATH] = { '\0' };
172 if (count >= UC_CACHE_UPCALL_MAXPATH) {
173 CERROR("%s: identity upcall too long\n", obd->obd_name);
177 if (copy_from_user(kernbuf, buffer,
178 min(count, UC_CACHE_UPCALL_MAXPATH - 1)))
181 /* Remove any extraneous bits from the upcall (e.g. linefeeds) */
182 sscanf(kernbuf, "%s", hash->uc_upcall);
184 if (strcmp(hash->uc_name, obd->obd_name) != 0)
185 CWARN("%s: write to upcall name %s\n",
186 obd->obd_name, hash->uc_upcall);
187 CWARN("%s: identity upcall set to %s\n", obd->obd_name, hash->uc_upcall);
192 static int lprocfs_wr_identity_flush(struct file *file, const char *buffer,
193 unsigned long count, void *data)
195 struct obd_device *obd = data;
196 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
199 rc = lprocfs_write_helper(buffer, count, &uid);
203 mdt_flush_identity(mdt->mdt_identity_cache, uid);
207 static int lprocfs_wr_identity_info(struct file *file, const char *buffer,
208 unsigned long count, void *data)
210 struct obd_device *obd = data;
211 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
212 struct identity_downcall_data sparam, *param = &sparam;
213 int size = 0, rc = 0;
215 if (count < sizeof(*param)) {
216 CERROR("%s: invalid data size %lu\n", obd->obd_name, count);
220 if (copy_from_user(&sparam, buffer, sizeof(sparam))) {
221 CERROR("%s: bad identity data\n", obd->obd_name);
222 GOTO(out, rc = -EFAULT);
225 if (sparam.idd_magic != IDENTITY_DOWNCALL_MAGIC) {
226 CERROR("%s: MDS identity downcall bad params\n", obd->obd_name);
227 GOTO(out, rc = -EINVAL);
230 if (sparam.idd_nperms > N_PERMS_MAX) {
231 CERROR("%s: perm count %d more than maximum %d\n",
232 obd->obd_name, sparam.idd_nperms, N_PERMS_MAX);
233 GOTO(out, rc = -EINVAL);
236 if (sparam.idd_ngroups > NGROUPS_MAX) {
237 CERROR("%s: group count %d more than maximum %d\n",
238 obd->obd_name, sparam.idd_ngroups, NGROUPS_MAX);
239 GOTO(out, rc = -EINVAL);
242 if (sparam.idd_ngroups) {
243 size = offsetof(struct identity_downcall_data,
244 idd_groups[sparam.idd_ngroups]);
245 OBD_ALLOC(param, size);
247 CERROR("%s: fail to alloc %d bytes for uid %u"
248 " with %d groups\n", obd->obd_name, size,
249 sparam.idd_uid, sparam.idd_ngroups);
251 param->idd_ngroups = 0;
252 } else if (copy_from_user(param, buffer, size)) {
253 CERROR("%s: uid %u bad supplementary group data\n",
254 obd->obd_name, sparam.idd_uid);
255 OBD_FREE(param, size);
257 param->idd_ngroups = 0;
261 rc = upcall_cache_downcall(mdt->mdt_identity_cache, param->idd_err,
262 param->idd_uid, param);
265 if (param && (param != &sparam))
266 OBD_FREE(param, size);
272 static int lprocfs_rd_capa(char *page, char **start, off_t off,
273 int count, int *eof, void *data)
275 struct obd_device *obd = data;
276 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
278 return snprintf(page, count, "capability on: %s %s\n",
279 mdt->mdt_opts.mo_oss_capa ? "oss" : "",
280 mdt->mdt_opts.mo_mds_capa ? "mds" : "");
283 static int lprocfs_wr_capa(struct file *file, const char *buffer,
284 unsigned long count, void *data)
286 struct obd_device *obd = data;
287 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
290 rc = lprocfs_write_helper(buffer, count, &val);
294 if (val < 0 || val > 3) {
295 CERROR("invalid capability mode, only 0/2/3 is accepted.\n"
296 " 0: disable fid capability\n"
297 " 2: enable MDS fid capability\n"
298 " 3: enable both MDS and OSS fid capability\n");
302 /* OSS fid capability needs enable both MDS and OSS fid capability on
305 CERROR("can't enable OSS fid capability only, you should use "
306 "'3' to enable both MDS and OSS fid capability.\n");
310 mdt->mdt_opts.mo_oss_capa = (val & 0x1);
311 mdt->mdt_opts.mo_mds_capa = !!(val & 0x2);
312 mdt->mdt_capa_conf = 1;
313 LCONSOLE_INFO("MDS %s %s MDS fid capability.\n",
315 mdt->mdt_opts.mo_mds_capa ? "enabled" : "disabled");
316 LCONSOLE_INFO("MDS %s %s OSS fid capability.\n",
318 mdt->mdt_opts.mo_oss_capa ? "enabled" : "disabled");
322 static int lprocfs_rd_capa_count(char *page, char **start, off_t off,
323 int count, int *eof, void *data)
325 return snprintf(page, count, "%d %d\n",
326 capa_count[CAPA_SITE_CLIENT],
327 capa_count[CAPA_SITE_SERVER]);
330 static int lprocfs_rd_site_stats(char *page, char **start, off_t off,
331 int count, int *eof, void *data)
333 struct obd_device *obd = data;
334 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
335 struct lu_site *s = mdt->mdt_md_dev.md_lu_dev.ld_site;
340 * How many hash buckets are not-empty? Don't bother with locks: it's
341 * an estimation anyway.
343 for (i = 0, populated = 0; i < s->ls_hash_size; i++)
344 populated += !hlist_empty(&s->ls_hash[i]);
346 return snprintf(page, count, "%d %d %d/%d %d %d %d %d %d %d\n",
351 s->ls_stats.s_created,
352 s->ls_stats.s_cache_hit,
353 s->ls_stats.s_cache_miss,
354 s->ls_stats.s_cache_check,
355 s->ls_stats.s_cache_race,
356 s->ls_stats.s_lru_purged);
359 static int lprocfs_rd_capa_timeout(char *page, char **start, off_t off,
360 int count, int *eof, void *data)
362 struct obd_device *obd = data;
363 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
365 return snprintf(page, count, "%lu\n", mdt->mdt_capa_timeout);
368 static int lprocfs_wr_capa_timeout(struct file *file, const char *buffer,
369 unsigned long count, void *data)
371 struct obd_device *obd = data;
372 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
375 rc = lprocfs_write_helper(buffer, count, &val);
379 mdt->mdt_capa_timeout = (unsigned long)val;
380 mdt->mdt_capa_conf = 1;
384 static int lprocfs_rd_ck_timeout(char *page, char **start, off_t off, int count,
385 int *eof, void *data)
387 struct obd_device *obd = data;
388 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
390 return snprintf(page, count, "%lu\n", mdt->mdt_ck_timeout);
393 static int lprocfs_wr_ck_timeout(struct file *file, const char *buffer,
394 unsigned long count, void *data)
396 struct obd_device *obd = data;
397 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
400 rc = lprocfs_write_helper(buffer, count, &val);
404 mdt->mdt_ck_timeout = (unsigned long)val;
405 mdt->mdt_capa_conf = 1;
409 static int lprocfs_mdt_wr_evict_client(struct file *file, const char *buffer,
410 unsigned long count, void *data)
412 char tmpbuf[sizeof(struct obd_uuid)];
414 sscanf(buffer, "%40s", tmpbuf);
416 if (strncmp(tmpbuf, "nid:", 4) != 0)
417 return lprocfs_wr_evict_client(file, buffer, count, data);
419 CERROR("NOT implement evict client by nid %s\n", tmpbuf);
424 static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
425 { "uuid", lprocfs_rd_uuid, 0, 0 },
426 { "recovery_status", lprocfs_obd_rd_recovery_status, 0, 0 },
427 { "num_exports", lprocfs_rd_num_exports, 0, 0 },
428 { "identity_expire", lprocfs_rd_identity_expire,
429 lprocfs_wr_identity_expire, 0 },
430 { "identity_acquire_expire", lprocfs_rd_identity_acquire_expire,
431 lprocfs_wr_identity_acquire_expire, 0 },
432 { "identity_upcall", lprocfs_rd_identity_upcall,
433 lprocfs_wr_identity_upcall, 0 },
434 { "identity_flush", 0, lprocfs_wr_identity_flush, 0 },
435 { "identity_info", 0, lprocfs_wr_identity_info, 0 },
436 { "capa", lprocfs_rd_capa,
437 lprocfs_wr_capa, 0 },
438 { "capa_timeout", lprocfs_rd_capa_timeout,
439 lprocfs_wr_capa_timeout, 0 },
440 { "capa_key_timeout", lprocfs_rd_ck_timeout,
441 lprocfs_wr_ck_timeout, 0 },
442 { "capa_count", lprocfs_rd_capa_count, 0, 0 },
443 { "site_stats", lprocfs_rd_site_stats, 0, 0 },
444 { "evict_client", 0, lprocfs_mdt_wr_evict_client, 0 },
448 static struct lprocfs_vars lprocfs_mdt_module_vars[] = {
449 { "num_refs", lprocfs_rd_numrefs, 0, 0 },
453 void lprocfs_mdt_init_vars(struct lprocfs_static_vars *lvars)
455 lvars->module_vars = lprocfs_mdt_module_vars;
456 lvars->obd_vars = lprocfs_mdt_obd_vars;