1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Lustre Time Tracking.
6 * Copyright (C) 2006 Cluster File Systems, Inc.
7 * Author: Nikita Danilov <nikita@clusterfs.com>
9 * This file is part of the Lustre file system, http://www.lustre.org
10 * Lustre is a trademark of Cluster File Systems, Inc.
12 * You may have signed or agreed to another license before downloading
13 * this software. If so, you are bound by the terms and conditions
14 * of that agreement, and the following does not apply to you. See the
15 * LICENSE file included with this distribution for more information.
17 * If you did not agree to a different license, then this copy of Lustre
18 * is open source software; you can redistribute it and/or modify it
19 * under the terms of version 2 of the GNU General Public License as
20 * published by the Free Software Foundation.
22 * In either case, Lustre is distributed in the hope that it will be
23 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
24 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * license text for more details.
27 * These are the only exported functions, they provide some generic
28 * infrastructure for managing object devices
31 #define DEBUG_SUBSYSTEM S_CLASS
33 # define EXPORT_SYMTAB
36 /* OBD_{ALLOC,FREE}_PTR() */
37 #include <obd_support.h>
38 #include <lprocfs_status.h>
39 #include <lu_object.h>
43 LU_TIME_DEPTH_MAX = 16
47 int ltd_tos; /* top of the stack */
48 unsigned long long ltd_timestamp[LU_TIME_DEPTH_MAX];
51 LU_KEY_INIT_FINI(lu_time, struct lu_time_data);
53 void lu_time_key_exit(const struct lu_context *ctx,
54 struct lu_context_key *key, void *data)
56 struct lu_time_data *value = data;
57 LASSERT(value->ltd_tos == 0);
61 * Key, holding temporary buffer. This key is registered very early by
64 static struct lu_context_key lu_time_key = {
65 .lct_tags = LCT_MD_THREAD|LCT_DT_THREAD|LCT_CL_THREAD,
66 .lct_init = lu_time_key_init,
67 .lct_fini = lu_time_key_fini,
68 .lct_exit = lu_time_key_exit
71 int lu_time_global_init(void)
73 LU_CONTEXT_KEY_INIT(&lu_time_key);
74 return lu_context_key_register(&lu_time_key);
77 void lu_time_global_fini(void)
79 lu_context_key_degister(&lu_time_key);
82 int lu_time_named_init(struct lprocfs_stats **stats, const char *name,
83 cfs_proc_dir_entry_t *entry,
84 const char **names, int nr)
95 *stats = lprocfs_alloc_stats(nr, 0);
97 result = lprocfs_register_stats(entry, name, *stats);
99 for (i = 0; i < nr; ++i) {
100 lprocfs_counter_init(*stats, i,
101 LPROCFS_CNTR_AVGMINMAX,
113 EXPORT_SYMBOL(lu_time_named_init);
115 int lu_time_init(struct lprocfs_stats **stats, cfs_proc_dir_entry_t *entry,
116 const char **names, int nr)
118 return lu_time_named_init(stats, "stats", entry, names, nr);
120 EXPORT_SYMBOL(lu_time_init);
122 void lu_time_fini(struct lprocfs_stats **stats)
124 if (*stats != NULL) {
125 lprocfs_free_stats(stats);
129 EXPORT_SYMBOL(lu_time_fini);
131 static inline struct lu_time_data *lu_time_data_get(const struct lu_env *env)
133 return lu_context_key_get(&env->le_ctx, &lu_time_key);
136 int lu_time_is_clean(const struct lu_env *env)
138 return lu_time_data_get(env)->ltd_tos == 0;
140 EXPORT_SYMBOL(lu_time_is_clean);
142 /* from sleepometer by Andrew Morton */
143 unsigned long long lu_time_stamp_get(void)
146 * Return timestamp with microsecond precision. This has to be cheap.
149 #if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
151 * do_gettimeofday() goes backwards sometimes :(. Usethe TSC
153 unsigned long long ret;
156 do_div(ret, cpu_khz / 1000);
160 unsigned long long ret;
162 do_gettimeofday(&now);
170 * Export it, but do not advertise in headers. This is limited use only.
172 EXPORT_SYMBOL(lu_time_stamp_get);
174 void lu_lprocfs_time_start(const struct lu_env *env)
176 struct lu_time_data *ltd = lu_time_data_get(env);
178 LASSERT(0 <= ltd->ltd_tos);
179 LASSERT(ltd->ltd_tos < ARRAY_SIZE(ltd->ltd_timestamp));
180 ltd->ltd_timestamp[ltd->ltd_tos++] = lu_time_stamp_get();
182 EXPORT_SYMBOL(lu_lprocfs_time_start);
184 void lu_lprocfs_time_end(const struct lu_env *env,
185 struct lprocfs_stats *stats, int idx)
187 struct lu_time_data *ltd = lu_time_data_get(env);
191 LASSERT(0 <= ltd->ltd_tos);
192 LASSERT(ltd->ltd_tos < ARRAY_SIZE(ltd->ltd_timestamp));
193 diff = lu_time_stamp_get() - ltd->ltd_timestamp[ltd->ltd_tos];
194 if (diff >= 0 && stats != NULL)
195 lprocfs_counter_add(stats, idx, diff);
197 EXPORT_SYMBOL(lu_lprocfs_time_end);