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);
158 struct upcall_cache *hash = mdt->mdt_identity_cache;
162 read_lock(&hash->uc_upcall_rwlock);
163 len = snprintf(page, count, "%s\n", hash->uc_upcall);
164 read_unlock(&hash->uc_upcall_rwlock);
168 static int lprocfs_wr_identity_upcall(struct file *file, const char *buffer,
169 unsigned long count, void *data)
171 struct obd_device *obd = data;
172 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
173 struct upcall_cache *hash = mdt->mdt_identity_cache;
174 char kernbuf[UC_CACHE_UPCALL_MAXPATH] = { '\0' };
176 if (count >= UC_CACHE_UPCALL_MAXPATH) {
177 CERROR("%s: identity upcall too long\n", obd->obd_name);
181 if (copy_from_user(kernbuf, buffer,
182 min(count, UC_CACHE_UPCALL_MAXPATH - 1)))
185 /* Remove any extraneous bits from the upcall (e.g. linefeeds) */
186 write_lock(&hash->uc_upcall_rwlock);
187 sscanf(kernbuf, "%s", hash->uc_upcall);
188 write_unlock(&hash->uc_upcall_rwlock);
190 if (strcmp(hash->uc_name, obd->obd_name) != 0)
191 CWARN("%s: write to upcall name %s\n",
192 obd->obd_name, hash->uc_upcall);
194 if (strcmp(hash->uc_upcall, "NONE") == 0 && mdt->mdt_opts.mo_acl)
195 CWARN("%s: disable \"identity_upcall\" with ACL enabled maybe "
196 "cause unexpected \"EACCESS\"\n", obd->obd_name);
198 CWARN("%s: identity upcall set to %s\n", obd->obd_name, hash->uc_upcall);
202 static int lprocfs_wr_identity_flush(struct file *file, const char *buffer,
203 unsigned long count, void *data)
205 struct obd_device *obd = data;
206 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
209 rc = lprocfs_write_helper(buffer, count, &uid);
213 mdt_flush_identity(mdt->mdt_identity_cache, uid);
217 static int lprocfs_wr_identity_info(struct file *file, const char *buffer,
218 unsigned long count, void *data)
220 struct obd_device *obd = data;
221 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
222 struct identity_downcall_data sparam, *param = &sparam;
223 int size = 0, rc = 0;
225 if (count < sizeof(*param)) {
226 CERROR("%s: invalid data size %lu\n", obd->obd_name, count);
230 if (copy_from_user(&sparam, buffer, sizeof(sparam))) {
231 CERROR("%s: bad identity data\n", obd->obd_name);
232 GOTO(out, rc = -EFAULT);
235 if (sparam.idd_magic != IDENTITY_DOWNCALL_MAGIC) {
236 CERROR("%s: MDS identity downcall bad params\n", obd->obd_name);
237 GOTO(out, rc = -EINVAL);
240 if (sparam.idd_nperms > N_PERMS_MAX) {
241 CERROR("%s: perm count %d more than maximum %d\n",
242 obd->obd_name, sparam.idd_nperms, N_PERMS_MAX);
243 GOTO(out, rc = -EINVAL);
246 if (sparam.idd_ngroups > NGROUPS_MAX) {
247 CERROR("%s: group count %d more than maximum %d\n",
248 obd->obd_name, sparam.idd_ngroups, NGROUPS_MAX);
249 GOTO(out, rc = -EINVAL);
252 if (sparam.idd_ngroups) {
253 size = offsetof(struct identity_downcall_data,
254 idd_groups[sparam.idd_ngroups]);
255 OBD_ALLOC(param, size);
257 CERROR("%s: fail to alloc %d bytes for uid %u"
258 " with %d groups\n", obd->obd_name, size,
259 sparam.idd_uid, sparam.idd_ngroups);
261 param->idd_ngroups = 0;
262 } else if (copy_from_user(param, buffer, size)) {
263 CERROR("%s: uid %u bad supplementary group data\n",
264 obd->obd_name, sparam.idd_uid);
265 OBD_FREE(param, size);
267 param->idd_ngroups = 0;
271 rc = upcall_cache_downcall(mdt->mdt_identity_cache, param->idd_err,
272 param->idd_uid, param);
275 if (param && (param != &sparam))
276 OBD_FREE(param, size);
282 static int lprocfs_rd_capa(char *page, char **start, off_t off,
283 int count, int *eof, void *data)
285 struct obd_device *obd = data;
286 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
288 return snprintf(page, count, "capability on: %s %s\n",
289 mdt->mdt_opts.mo_oss_capa ? "oss" : "",
290 mdt->mdt_opts.mo_mds_capa ? "mds" : "");
293 static int lprocfs_wr_capa(struct file *file, const char *buffer,
294 unsigned long count, void *data)
296 struct obd_device *obd = data;
297 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
300 rc = lprocfs_write_helper(buffer, count, &val);
304 if (val < 0 || val > 3) {
305 CERROR("invalid capability mode, only 0/2/3 is accepted.\n"
306 " 0: disable fid capability\n"
307 " 2: enable MDS fid capability\n"
308 " 3: enable both MDS and OSS fid capability\n");
312 /* OSS fid capability needs enable both MDS and OSS fid capability on
315 CERROR("can't enable OSS fid capability only, you should use "
316 "'3' to enable both MDS and OSS fid capability.\n");
320 mdt->mdt_opts.mo_oss_capa = (val & 0x1);
321 mdt->mdt_opts.mo_mds_capa = !!(val & 0x2);
322 mdt->mdt_capa_conf = 1;
323 LCONSOLE_INFO("MDS %s %s MDS fid capability.\n",
325 mdt->mdt_opts.mo_mds_capa ? "enabled" : "disabled");
326 LCONSOLE_INFO("MDS %s %s OSS fid capability.\n",
328 mdt->mdt_opts.mo_oss_capa ? "enabled" : "disabled");
332 static int lprocfs_rd_capa_count(char *page, char **start, off_t off,
333 int count, int *eof, void *data)
335 return snprintf(page, count, "%d %d\n",
336 capa_count[CAPA_SITE_CLIENT],
337 capa_count[CAPA_SITE_SERVER]);
340 static int lprocfs_rd_site_stats(char *page, char **start, off_t off,
341 int count, int *eof, void *data)
343 struct obd_device *obd = data;
344 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
345 struct lu_site *s = mdt->mdt_md_dev.md_lu_dev.ld_site;
350 * How many hash buckets are not-empty? Don't bother with locks: it's
351 * an estimation anyway.
353 for (i = 0, populated = 0; i < s->ls_hash_size; i++)
354 populated += !hlist_empty(&s->ls_hash[i]);
356 return snprintf(page, count, "%d %d %d/%d %d %d %d %d %d %d\n",
361 s->ls_stats.s_created,
362 s->ls_stats.s_cache_hit,
363 s->ls_stats.s_cache_miss,
364 s->ls_stats.s_cache_check,
365 s->ls_stats.s_cache_race,
366 s->ls_stats.s_lru_purged);
369 static int lprocfs_rd_capa_timeout(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);
375 return snprintf(page, count, "%lu\n", mdt->mdt_capa_timeout);
378 static int lprocfs_wr_capa_timeout(struct file *file, const char *buffer,
379 unsigned long count, void *data)
381 struct obd_device *obd = data;
382 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
385 rc = lprocfs_write_helper(buffer, count, &val);
389 mdt->mdt_capa_timeout = (unsigned long)val;
390 mdt->mdt_capa_conf = 1;
394 static int lprocfs_rd_ck_timeout(char *page, char **start, off_t off, int count,
395 int *eof, void *data)
397 struct obd_device *obd = data;
398 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
400 return snprintf(page, count, "%lu\n", mdt->mdt_ck_timeout);
403 static int lprocfs_wr_ck_timeout(struct file *file, const char *buffer,
404 unsigned long count, void *data)
406 struct obd_device *obd = data;
407 struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
410 rc = lprocfs_write_helper(buffer, count, &val);
414 mdt->mdt_ck_timeout = (unsigned long)val;
415 mdt->mdt_capa_conf = 1;
419 static int lprocfs_mdt_wr_evict_client(struct file *file, const char *buffer,
420 unsigned long count, void *data)
422 char tmpbuf[sizeof(struct obd_uuid)];
424 sscanf(buffer, "%40s", tmpbuf);
426 if (strncmp(tmpbuf, "nid:", 4) != 0)
427 return lprocfs_wr_evict_client(file, buffer, count, data);
429 CERROR("NOT implement evict client by nid %s\n", tmpbuf);
434 static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
435 { "uuid", lprocfs_rd_uuid, 0, 0 },
436 { "recovery_status", lprocfs_obd_rd_recovery_status, 0, 0 },
437 { "num_exports", lprocfs_rd_num_exports, 0, 0 },
438 { "identity_expire", lprocfs_rd_identity_expire,
439 lprocfs_wr_identity_expire, 0 },
440 { "identity_acquire_expire", lprocfs_rd_identity_acquire_expire,
441 lprocfs_wr_identity_acquire_expire, 0 },
442 { "identity_upcall", lprocfs_rd_identity_upcall,
443 lprocfs_wr_identity_upcall, 0 },
444 { "identity_flush", 0, lprocfs_wr_identity_flush, 0 },
445 { "identity_info", 0, lprocfs_wr_identity_info, 0 },
446 { "capa", lprocfs_rd_capa,
447 lprocfs_wr_capa, 0 },
448 { "capa_timeout", lprocfs_rd_capa_timeout,
449 lprocfs_wr_capa_timeout, 0 },
450 { "capa_key_timeout", lprocfs_rd_ck_timeout,
451 lprocfs_wr_ck_timeout, 0 },
452 { "capa_count", lprocfs_rd_capa_count, 0, 0 },
453 { "site_stats", lprocfs_rd_site_stats, 0, 0 },
454 { "evict_client", 0, lprocfs_mdt_wr_evict_client, 0 },
458 static struct lprocfs_vars lprocfs_mdt_module_vars[] = {
459 { "num_refs", lprocfs_rd_numrefs, 0, 0 },
463 void lprocfs_mdt_init_vars(struct lprocfs_static_vars *lvars)
465 lvars->module_vars = lprocfs_mdt_module_vars;
466 lvars->obd_vars = lprocfs_mdt_obd_vars;