1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2003 Cluster File Systems, Inc.
5 * Author: Eric Barton <eeb@clusterfs.com>
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 # define EXPORT_SYMTAB
27 #include <linux/config.h>
28 #include <linux/module.h>
29 #include <linux/kmod.h>
30 #include <linux/kernel.h>
31 #include <linux/kernel.h>
33 #include <linux/string.h>
34 #include <linux/stat.h>
35 #include <linux/errno.h>
36 #include <linux/smp_lock.h>
37 #include <linux/unistd.h>
38 #include <linux/interrupt.h>
39 #include <asm/system.h>
40 #include <asm/uaccess.h>
42 #define DEBUG_SUBSYSTEM S_PORTALS
44 #include <linux/kp30.h>
48 #define LWT_MEMORY (1<<20) /* 1Mb of trace memory */
49 #define LWT_MAX_CPUS 4
52 int lwt_pages_per_cpu;
53 lwt_cpu_t lwt_cpus[LWT_MAX_CPUS];
55 /* NB only root is allowed to retrieve LWT info; it's an open door into the
59 lwt_lookup_string (int *size, char *knl_ptr,
60 char *user_ptr, int user_size)
64 /* knl_ptr was retrieved from an LWT snapshot and the caller wants to
65 * turn it into a string. NB we can crash with an access violation
66 * trying to determine the string length, so we're trusting our
69 if (!capable(CAP_SYS_ADMIN))
76 *size = strnlen (knl_ptr, maxsize - 1) + 1;
78 if (user_ptr != NULL) {
82 if (copy_to_user (user_ptr, knl_ptr, *size))
85 /* Did I truncate the string? */
86 if (knl_ptr[*size - 1] != 0)
87 copy_to_user (user_ptr + *size - 4, "...", 4);
94 lwt_control (int enable, int clear)
100 if (!capable(CAP_SYS_ADMIN))
104 for (i = 0; i < num_online_cpus(); i++) {
105 p = lwt_cpus[i].lwtc_current_page;
107 for (j = 0; j < lwt_pages_per_cpu; j++) {
108 memset (p->lwtp_events, 0, PAGE_SIZE);
110 p = list_entry (p->lwtp_list.next,
111 lwt_page_t, lwtp_list);
115 lwt_enabled = enable;
118 /* give people some time to stop adding traces */
119 schedule_timeout(10);
126 lwt_snapshot (int *ncpu, int *total_size, void *user_ptr, int user_size)
128 const int events_per_page = PAGE_SIZE / sizeof(lwt_event_t);
129 const int bytes_per_page = events_per_page * sizeof(lwt_event_t);
134 if (!capable(CAP_SYS_ADMIN))
137 *ncpu = num_online_cpus();
138 *total_size = num_online_cpus() * lwt_pages_per_cpu * bytes_per_page;
140 if (user_ptr == NULL)
143 for (i = 0; i < num_online_cpus(); i++) {
144 p = lwt_cpus[i].lwtc_current_page;
146 for (j = 0; j < lwt_pages_per_cpu; j++) {
147 if (copy_to_user(user_ptr, p->lwtp_events,
151 user_ptr = ((char *)user_ptr) + bytes_per_page;
152 p = list_entry(p->lwtp_list.next,
153 lwt_page_t, lwtp_list);
167 if (num_online_cpus() > LWT_MAX_CPUS) {
168 CERROR ("Too many CPUs\n");
172 /* NULL pointers, zero scalars */
173 memset (lwt_cpus, 0, sizeof (lwt_cpus));
174 lwt_pages_per_cpu = LWT_MEMORY / (num_online_cpus() * PAGE_SIZE);
176 for (i = 0; i < num_online_cpus(); i++)
177 for (j = 0; j < lwt_pages_per_cpu; j++) {
178 struct page *page = alloc_page (GFP_KERNEL);
182 CERROR ("Can't allocate page\n");
187 PORTAL_ALLOC(lwtp, sizeof (*lwtp));
189 CERROR ("Can't allocate lwtp\n");
195 lwtp->lwtp_page = page;
196 lwtp->lwtp_events = page_address(page);
197 memset (lwtp->lwtp_events, 0, PAGE_SIZE);
200 INIT_LIST_HEAD (&lwtp->lwtp_list);
201 lwt_cpus[i].lwtc_current_page = lwtp;
203 list_add (&lwtp->lwtp_list,
204 &lwt_cpus[i].lwtc_current_page->lwtp_list);
219 if (num_online_cpus() > LWT_MAX_CPUS)
222 for (i = 0; i < num_online_cpus(); i++)
223 while (lwt_cpus[i].lwtc_current_page != NULL) {
224 lwt_page_t *lwtp = lwt_cpus[i].lwtc_current_page;
226 if (list_empty (&lwtp->lwtp_list)) {
227 lwt_cpus[i].lwtc_current_page = NULL;
229 lwt_cpus[i].lwtc_current_page =
230 list_entry (lwtp->lwtp_list.next,
231 lwt_page_t, lwtp_list);
233 list_del (&lwtp->lwtp_list);
236 __free_page (lwtp->lwtp_page);
237 PORTAL_FREE (lwtp, sizeof (*lwtp));
241 EXPORT_SYMBOL(lwt_enabled);
242 EXPORT_SYMBOL(lwt_cpus);
244 EXPORT_SYMBOL(lwt_init);
245 EXPORT_SYMBOL(lwt_fini);
246 EXPORT_SYMBOL(lwt_lookup_string);
247 EXPORT_SYMBOL(lwt_control);
248 EXPORT_SYMBOL(lwt_snapshot);