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 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
38 * Author: Eric Barton <eeb@clusterfs.com>
42 # define EXPORT_SYMTAB
45 #ifndef AUTOCONF_INCLUDED
46 #include <linux/config.h>
48 #include <linux/module.h>
49 #include <linux/kmod.h>
50 #include <linux/kernel.h>
51 #include <linux/kernel.h>
53 #include <linux/string.h>
54 #include <linux/stat.h>
55 #include <linux/errno.h>
56 #include <linux/smp_lock.h>
57 #include <linux/unistd.h>
58 #include <linux/interrupt.h>
59 #include <asm/system.h>
60 #include <asm/uaccess.h>
62 #define DEBUG_SUBSYSTEM S_LNET
64 #include <libcfs/libcfs.h>
70 lwt_cpu_t lwt_cpus[NR_CPUS];
73 int lwt_pages_per_cpu;
75 /* NB only root is allowed to retrieve LWT info; it's an open door into the
79 lwt_lookup_string (int *size, char *knl_ptr,
80 char *user_ptr, int user_size)
84 /* knl_ptr was retrieved from an LWT snapshot and the caller wants to
85 * turn it into a string. NB we can crash with an access violation
86 * trying to determine the string length, so we're trusting our
89 if (!capable(CAP_SYS_ADMIN))
96 *size = strnlen (knl_ptr, maxsize - 1) + 1;
98 if (user_ptr != NULL) {
102 if (copy_to_user (user_ptr, knl_ptr, *size))
105 /* Did I truncate the string? */
106 if (knl_ptr[*size - 1] != 0)
107 copy_to_user (user_ptr + *size - 4, "...", 4);
114 lwt_control (int enable, int clear)
120 if (!capable(CAP_SYS_ADMIN))
127 /* give people some time to stop adding traces */
128 schedule_timeout(10);
131 for (i = 0; i < num_online_cpus(); i++) {
132 p = lwt_cpus[i].lwtc_current_page;
140 for (j = 0; j < lwt_pages_per_cpu; j++) {
141 memset (p->lwtp_events, 0, CFS_PAGE_SIZE);
143 p = list_entry (p->lwtp_list.next,
144 lwt_page_t, lwtp_list);
158 lwt_snapshot (cycles_t *now, int *ncpu, int *total_size,
159 void *user_ptr, int user_size)
161 const int events_per_page = CFS_PAGE_SIZE / sizeof(lwt_event_t);
162 const int bytes_per_page = events_per_page * sizeof(lwt_event_t);
167 if (!capable(CAP_SYS_ADMIN))
170 *ncpu = num_online_cpus();
171 *total_size = num_online_cpus() * lwt_pages_per_cpu * bytes_per_page;
174 if (user_ptr == NULL)
177 for (i = 0; i < num_online_cpus(); i++) {
178 p = lwt_cpus[i].lwtc_current_page;
183 for (j = 0; j < lwt_pages_per_cpu; j++) {
184 if (copy_to_user(user_ptr, p->lwtp_events,
188 user_ptr = ((char *)user_ptr) + bytes_per_page;
189 p = list_entry(p->lwtp_list.next,
190 lwt_page_t, lwtp_list);
204 for (i = 0; i < num_online_cpus(); i++)
205 if (lwt_cpus[i].lwtc_current_page != NULL)
208 LASSERT (!lwt_enabled);
210 /* NULL pointers, zero scalars */
211 memset (lwt_cpus, 0, sizeof (lwt_cpus));
212 lwt_pages_per_cpu = LWT_MEMORY / (num_online_cpus() * CFS_PAGE_SIZE);
214 for (i = 0; i < num_online_cpus(); i++)
215 for (j = 0; j < lwt_pages_per_cpu; j++) {
216 struct page *page = alloc_page (GFP_KERNEL);
220 CERROR ("Can't allocate page\n");
225 LIBCFS_ALLOC(lwtp, sizeof (*lwtp));
227 CERROR ("Can't allocate lwtp\n");
233 lwtp->lwtp_page = page;
234 lwtp->lwtp_events = page_address(page);
235 memset (lwtp->lwtp_events, 0, CFS_PAGE_SIZE);
238 INIT_LIST_HEAD (&lwtp->lwtp_list);
239 lwt_cpus[i].lwtc_current_page = lwtp;
241 list_add (&lwtp->lwtp_list,
242 &lwt_cpus[i].lwtc_current_page->lwtp_list);
261 for (i = 0; i < num_online_cpus(); i++)
262 while (lwt_cpus[i].lwtc_current_page != NULL) {
263 lwt_page_t *lwtp = lwt_cpus[i].lwtc_current_page;
265 if (list_empty (&lwtp->lwtp_list)) {
266 lwt_cpus[i].lwtc_current_page = NULL;
268 lwt_cpus[i].lwtc_current_page =
269 list_entry (lwtp->lwtp_list.next,
270 lwt_page_t, lwtp_list);
272 list_del (&lwtp->lwtp_list);
275 __free_page (lwtp->lwtp_page);
276 LIBCFS_FREE (lwtp, sizeof (*lwtp));
280 EXPORT_SYMBOL(lwt_enabled);
281 EXPORT_SYMBOL(lwt_cpus);
283 EXPORT_SYMBOL(lwt_init);
284 EXPORT_SYMBOL(lwt_fini);
285 EXPORT_SYMBOL(lwt_lookup_string);
286 EXPORT_SYMBOL(lwt_control);
287 EXPORT_SYMBOL(lwt_snapshot);