1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define DEBUG_SUBSYSTEM S_CLASS
24 #include <linux/version.h>
25 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
26 #include <asm/statfs.h>
28 #include <linux/obd.h>
29 #include <linux/obd_class.h>
30 #include <linux/lprocfs_status.h>
31 #include "mds_internal.h"
34 struct lprocfs_vars lprocfs_mds_obd_vars[] = { {0} };
35 struct lprocfs_vars lprocfs_mds_module_vars[] = { {0} };
36 struct lprocfs_vars lprocfs_mdt_obd_vars[] = { {0} };
37 struct lprocfs_vars lprocfs_mdt_module_vars[] = { {0} };
39 atomic_t * lprocfs_alloc_mds_counters()
43 void lprocfs_free_mds_counters(atomic_t *ptr)
50 struct ll_mdscounters_opcode {
53 } ll_mdscounters_opcode_table[MDS_LAST_OPC_COUNT] = {
54 { MDS_OPEN_COUNT, "mds_open" },
55 { MDS_CREATE_COUNT, "mds_create" },
56 { MDS_CLOSE_COUNT, "mds_close" },
57 { MDS_LINK_COUNT, "mds_link" },
58 { MDS_UNLINK_COUNT, "mds_unlink" },
59 { MDS_GETATTR_COUNT, "mds_getattr" },
60 { MDS_GETATTR_NAME_COUNT, "mds_getattr_name" },
61 { MDS_SETATTR_COUNT, "mds_setattr" },
62 { MDS_RENAME_COUNT, "mds_rename" },
63 { MDS_STATFS_COUNT, "mds_statfs" },
66 const char* ll_mds_count_opcode2str(__u32 opcode)
68 __u32 offset = opcode;
70 LASSERT(offset < MDS_LAST_OPC_COUNT);
71 LASSERT(ll_mdscounters_opcode_table[offset].opcode == opcode);
72 return ll_mdscounters_opcode_table[offset].opname;
75 struct lprocfs_stats * lprocfs_alloc_mds_counters()
77 struct lprocfs_stats *counters;
80 counters = lprocfs_alloc_stats(MDS_LAST_OPC_COUNT);
82 for (i = 0; i < MDS_LAST_OPC_COUNT; i ++) {
83 lprocfs_counter_init(counters, i, 0,
84 (char *)ll_mds_count_opcode2str(i), "reqs");
89 void lprocfs_free_mds_counters(struct lprocfs_stats *ptr)
91 lprocfs_free_stats(ptr);
94 static int lprocfs_mds_rd_mntdev(char *page, char **start, off_t off, int count,
97 struct obd_device* obd = (struct obd_device *)data;
100 LASSERT(obd->u.mds.mds_vfsmnt->mnt_devname);
103 return snprintf(page, count, "%s\n",obd->u.mds.mds_vfsmnt->mnt_devname);
106 static int lprocfs_mds_rd_recovery_status(char *page, char **start, off_t off,
107 int count, int *eof, void *data)
109 struct obd_device *obd = data;
111 connected = obd->obd_connected_clients,
112 max_recoverable = obd->obd_max_recoverable_clients,
113 recoverable = obd->obd_recoverable_clients,
114 completed = max_recoverable - recoverable,
115 queue_len = obd->obd_requests_queued_for_recovery,
116 replayed = obd->obd_replayed_requests;
117 __u64 next_transno = obd->obd_next_recovery_transno;
119 LASSERT(obd != NULL);
122 n = snprintf(page, count, "status: ");
123 page += n; len += n; count -= n;
124 if (obd->obd_max_recoverable_clients == 0) {
125 n = snprintf(page, count, "INACTIVE\n");
129 if (obd->obd_recoverable_clients == 0) {
130 n = snprintf(page, count, "COMPLETE\n");
131 page += n; len += n; count -= n;
132 n = snprintf(page, count, "recovered_clients: %d\n",
134 page += n; len += n; count -= n;
135 n = snprintf(page, count, "last_transno: "LPD64"\n",
137 page += n; len += n; count -= n;
138 n = snprintf(page, count, "replayed_requests: %d\n", replayed);
142 /* sampled unlocked, but really... */
143 if (obd->obd_recovering == 0) {
144 n = snprintf(page, count, "ABORTED\n");
148 n = snprintf(page, count, "RECOVERING\n");
149 page += n; len += n; count -= n;
150 n = snprintf(page, count, "connected_clients: %d/%d\n",
151 connected, max_recoverable);
152 page += n; len += n; count -= n;
153 n = snprintf(page, count, "completed_clients: %d/%d\n",
154 completed, max_recoverable);
155 page += n; len += n; count -= n;
156 n = snprintf(page, count, "replayed_requests: %d/??\n", replayed);
157 page += n; len += n; count -= n;
158 n = snprintf(page, count, "queued_requests: %d\n", queue_len);
159 page += n; len += n; count -= n;
160 n = snprintf(page, count, "next_transno: "LPD64"\n", next_transno);
164 static int lprocfs_rd_mds_counters(char *page, char **start, off_t off,
165 int count, int *eof, void *data)
167 struct obd_device* obd = (struct obd_device *)data;
168 int len = 0, n, i, j;
169 struct lprocfs_counter t, ret = { .lc_min = ~(__u64)0 };
170 struct lprocfs_stats *stats;
173 LASSERT(obd != NULL);
174 if (obd->u.mds.mds_counters == NULL)
177 do_gettimeofday(&now);
179 n = snprintf(page, count, "%-25s %lu.%lu secs.usecs\n",
180 "snapshot_time", now.tv_sec, now.tv_usec);
181 page += n; len +=n; count -=n;
183 stats = obd->u.mds.mds_counters;
186 for (i = 0; i < MDS_LAST_OPC_COUNT; i ++) {
188 for (j = 0; j < num_online_cpus(); j++) {
189 struct lprocfs_counter *percpu_cntr =
190 &(stats->ls_percpu[j])->lp_cntr[i];
194 atomic_read(&percpu_cntr->lc_cntl.la_entry);
195 t.lc_count = percpu_cntr->lc_count;
197 atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
199 atomic_read(&percpu_cntr->lc_cntl.la_exit));
200 ret.lc_count += t.lc_count;
202 n = snprintf(page, count, "%-25s "LPU64" \n",
203 ll_mds_count_opcode2str(i), ret.lc_count);
204 page += n; len +=n; count -=n;
209 static int lprocfs_mds_wr_evict_client(struct file *file, const char *buffer,
210 unsigned long count, void *data)
212 struct obd_device *obd = data;
213 struct obd_export *doomed_exp = NULL;
214 struct obd_uuid doomed;
216 char tmpbuf[sizeof(doomed)];
218 sscanf(buffer, "%40s", tmpbuf);
219 obd_str2uuid(&doomed, tmpbuf);
221 spin_lock(&obd->obd_dev_lock);
222 list_for_each(p, &obd->obd_exports) {
223 doomed_exp = list_entry(p, struct obd_export, exp_obd_chain);
224 if (obd_uuid_equals(&doomed, &doomed_exp->exp_client_uuid)) {
225 class_export_get(doomed_exp);
230 spin_unlock(&obd->obd_dev_lock);
232 if (doomed_exp == NULL) {
233 CERROR("can't disconnect %s: no export found\n",
236 CERROR("evicting %s at adminstrative request\n",
238 ptlrpc_fail_export(doomed_exp);
239 class_export_put(doomed_exp);
244 static int lprocfs_mds_wr_config_update(struct file *file, const char *buffer,
245 unsigned long count, void *data)
247 struct obd_device *obd = data;
250 RETURN(mds_lov_update_config(obd, 0));
253 struct lprocfs_vars lprocfs_mds_obd_vars[] = {
254 { "uuid", lprocfs_rd_uuid, 0, 0 },
255 { "blocksize", lprocfs_rd_blksize, 0, 0 },
256 { "kbytestotal", lprocfs_rd_kbytestotal, 0, 0 },
257 { "kbytesfree", lprocfs_rd_kbytesfree, 0, 0 },
258 { "kbytesavail", lprocfs_rd_kbytesavail, 0, 0 },
259 { "fstype", lprocfs_rd_fstype, 0, 0 },
260 { "filestotal", lprocfs_rd_filestotal, 0, 0 },
261 { "filesfree", lprocfs_rd_filesfree, 0, 0 },
262 { "mntdev", lprocfs_mds_rd_mntdev, 0, 0 },
263 { "recovery_status", lprocfs_mds_rd_recovery_status, 0, 0 },
264 { "evict_client", 0, lprocfs_mds_wr_evict_client, 0 },
265 { "config_update", 0, lprocfs_mds_wr_config_update, 0 },
266 { "num_exports", lprocfs_rd_num_exports, 0, 0 },
267 { "counters", lprocfs_rd_mds_counters, 0, 0 },
271 struct lprocfs_vars lprocfs_mds_module_vars[] = {
272 { "num_refs", lprocfs_rd_numrefs, 0, 0 },
276 struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
277 { "uuid", lprocfs_rd_uuid, 0, 0 },
281 struct lprocfs_vars lprocfs_mdt_module_vars[] = {
282 { "num_refs", lprocfs_rd_numrefs, 0, 0 },
289 struct lprocfs_static_vars lprocfs_array_vars[] = { {lprocfs_mds_module_vars,
290 lprocfs_mds_obd_vars},
291 {lprocfs_mdt_module_vars,
292 lprocfs_mdt_obd_vars}};
294 LPROCFS_INIT_MULTI_VARS(lprocfs_array_vars,
295 (sizeof(lprocfs_array_vars) /
296 sizeof(struct lprocfs_static_vars)))