Whamcloud - gitweb
- landing of b_hd_cleanup_merge to HEAD.
[fs/lustre-release.git] / lustre / portals / libcfs / tracefile.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2004 Cluster File Systems, Inc.
5  *   Author: Zach Brown <zab@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/init.h>
27 #include <linux/rwsem.h>
28 #include <linux/proc_fs.h>
29 #include <linux/file.h>
30 #include <linux/smp.h>
31 #include <linux/ctype.h>
32 #include <asm/uaccess.h>
33 #ifdef HAVE_MM_INLINE
34 #include <linux/mm_inline.h>
35 #endif
36
37 #define DEBUG_SUBSYSTEM S_PORTALS
38
39 #include <linux/kp30.h>
40 #include <linux/portals_compat25.h>
41 #include <linux/lustre_compat25.h>
42 #include <linux/libcfs.h>
43
44 #define TCD_MAX_PAGES 1280
45
46 /* XXX move things up to the top, comment */
47
48 static union {
49         struct trace_cpu_data {
50                 struct list_head        tcd_pages;
51                 unsigned long           tcd_cur_pages;
52
53                 struct list_head        tcd_daemon_pages;
54                 unsigned long           tcd_cur_daemon_pages;
55
56                 unsigned long           tcd_max_pages;
57                 int                     tcd_shutting_down;
58         } tcd;
59         char __pad[SMP_CACHE_BYTES];
60 } trace_data[NR_CPUS] __cacheline_aligned;
61
62 struct page_collection {
63         struct list_head        pc_pages;
64         spinlock_t              pc_lock;
65         int                     pc_want_daemon_pages;
66 };
67
68 struct tracefiled_ctl {
69         struct completion        tctl_start;
70         struct completion        tctl_stop;
71         wait_queue_head_t        tctl_waitq;
72         pid_t                    tctl_pid;
73         atomic_t                 tctl_shutdown;
74 };
75
76 static DECLARE_RWSEM(tracefile_sem);
77 static char *tracefile = NULL;
78 static struct tracefiled_ctl trace_tctl;
79 static DECLARE_MUTEX(trace_thread_sem);
80 static int thread_running = 0;
81
82 #ifndef get_cpu
83 #define get_cpu() smp_processor_id()
84 #define put_cpu() do { } while (0)
85 #endif
86
87 #define trace_get_tcd(FLAGS) ({                 \
88         struct trace_cpu_data *__ret;           \
89         int __cpu = get_cpu();                  \
90         local_irq_save(FLAGS);                  \
91         __ret = &trace_data[__cpu].tcd;         \
92         __ret;                                  \
93 })
94
95 #define trace_put_tcd(TCD, FLAGS) do {          \
96         local_irq_restore(FLAGS);               \
97         put_cpu();                              \
98 } while (0)
99
100 static void put_pages_on_daemon_list_on_cpu(void *info);
101
102 /* return a page that has 'len' bytes left at the end */
103 static struct page *trace_get_page(struct trace_cpu_data *tcd,
104                                    unsigned long len)
105 {
106         struct page *page = NULL;
107
108         if (len > PAGE_SIZE) {
109                 printk(KERN_ERR "cowardly refusing to write %lu bytes in a "
110                        "page\n", len);
111                 return NULL;
112         }
113
114         if (!list_empty(&tcd->tcd_pages)) {
115                 page = list_entry(tcd->tcd_pages.prev, struct page,
116                                   PAGE_LIST_ENTRY);
117                 if (page->index + len <= PAGE_SIZE)
118                         return page;
119         }
120
121         if (tcd->tcd_cur_pages < tcd->tcd_max_pages) {
122                 page = alloc_page(GFP_ATOMIC);
123                 if (page == NULL) {
124                         /* the kernel should print a message for us.  fall back
125                          * to using the last page in the ring buffer. */
126                         goto ring_buffer;
127                         return NULL;
128                 }
129                 page->index = 0;
130                 page->mapping = (void *)(long)smp_processor_id();
131                 list_add_tail(&PAGE_LIST(page), &tcd->tcd_pages);
132                 tcd->tcd_cur_pages++;
133
134                 if (tcd->tcd_cur_pages > 8 && thread_running) {
135                         struct tracefiled_ctl *tctl = &trace_tctl;
136                         wake_up(&tctl->tctl_waitq);
137                 }
138                 return page;
139         }
140
141  ring_buffer:
142         if (thread_running) {
143                 int pgcount = tcd->tcd_cur_pages / 10;
144                 struct page_collection pc;
145                 struct list_head *pos, *tmp;
146                 printk(KERN_WARNING "debug daemon buffer overflowed; discarding"
147                        " 10%% of pages (%d)\n", pgcount + 1);
148
149                 INIT_LIST_HEAD(&pc.pc_pages);
150                 spin_lock_init(&pc.pc_lock);
151
152                 list_for_each_safe(pos, tmp, &tcd->tcd_pages) {
153                         struct page *page;
154
155                         if (pgcount-- == 0)
156                                 break;
157
158                         page = list_entry(pos, struct page, PAGE_LIST_ENTRY);
159                         list_del(&PAGE_LIST(page));
160                         list_add_tail(&PAGE_LIST(page), &pc.pc_pages);
161                         tcd->tcd_cur_pages--;
162                 }
163                 put_pages_on_daemon_list_on_cpu(&pc);
164         }
165         LASSERT(!list_empty(&tcd->tcd_pages));
166
167         page = list_entry(tcd->tcd_pages.next, struct page, PAGE_LIST_ENTRY);
168         page->index = 0;
169
170         list_del(&PAGE_LIST(page));
171         list_add_tail(&PAGE_LIST(page), &tcd->tcd_pages);
172         return page;
173 }
174
175 static void print_to_console(struct ptldebug_header *hdr, int mask, char *buf,
176                              int len, char *file, const char *fn)
177 {
178         char *prefix = NULL, *ptype = NULL;
179
180         if ((mask & D_EMERG) != 0) {
181                 prefix = "LustreError";
182                 ptype = KERN_EMERG;
183         } else if ((mask & D_ERROR) != 0) {
184                 prefix = "LustreError";
185                 ptype = KERN_ERR;
186         } else if ((mask & D_WARNING) != 0) {
187                 prefix = "Lustre";
188                 ptype = KERN_WARNING;
189         } else if (portal_printk) {
190                 prefix = "Lustre";
191                 ptype = KERN_INFO;
192         }
193         
194         printk("%s%s: %d:%d:(%s:%d:%s()) %.*s", ptype, prefix, hdr->ph_pid,
195                hdr->ph_extern_pid, file, hdr->ph_line_num, fn, len, buf);
196 }
197
198 void portals_debug_msg(int subsys, int mask, char *file, const char *fn,
199                        const int line, unsigned long stack, char *format, ...)
200 {
201         struct trace_cpu_data *tcd;
202         struct ptldebug_header header;
203         struct page *page;
204         char *debug_buf;
205         int known_size, needed, max_nob;
206         va_list       ap;
207         unsigned long flags;
208         struct timeval tv;
209
210         if (*(format + strlen(format) - 1) != '\n')
211                 printk(KERN_INFO "format at %s:%d:%s doesn't end in newline\n",
212                        file, line, fn);
213
214         tcd = trace_get_tcd(flags);
215         if (tcd->tcd_shutting_down)
216                 goto out;
217
218         do_gettimeofday(&tv);
219
220         header.ph_subsys = subsys;
221         header.ph_mask = mask;
222         header.ph_cpu_id = smp_processor_id();
223         header.ph_sec = (__u32)tv.tv_sec;
224         header.ph_usec = tv.tv_usec;
225         header.ph_stack = stack;
226         header.ph_pid = current->pid;
227         header.ph_line_num = line;
228
229 #if defined(__arch_um__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20))
230         header.ph_extern_pid = current->thread.extern_pid;
231 #elif defined(__arch_um__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
232         header.ph_extern_pid = current->thread.mode.tt.extern_pid;
233 #else
234         header.ph_extern_pid = 0;
235 #endif
236
237         known_size = sizeof(header) + strlen(file) + strlen(fn) + 2; // nulls
238
239         page = trace_get_page(tcd, known_size + 40); /* slop */
240  retry:
241         if (page == NULL)
242                 goto out;
243
244         debug_buf = page_address(page) + page->index + known_size;
245
246         va_start(ap, format);
247         max_nob = PAGE_SIZE - page->index - known_size;
248         LASSERT(max_nob > 0);
249         needed = vsnprintf(debug_buf, max_nob, format, ap);
250         va_end(ap);
251
252         if (needed > max_nob) {
253                 /* overflow.  oh poop. */
254                 page = trace_get_page(tcd, needed + known_size);
255                 goto retry;
256         }
257
258         header.ph_len = known_size + needed;
259         debug_buf = page_address(page) + page->index;
260
261         memcpy(debug_buf, &header, sizeof(header));
262         page->index += sizeof(header);
263         debug_buf += sizeof(header);
264
265         strcpy(debug_buf, file);
266         page->index += strlen(file) + 1;
267         debug_buf += strlen(file) + 1;
268
269         strcpy(debug_buf, fn);
270         page->index += strlen(fn) + 1;
271         debug_buf += strlen(fn) + 1;
272
273         page->index += needed;
274         if (page->index > PAGE_SIZE)
275                 printk(KERN_EMERG "page->index == %lu in portals_debug_msg\n",
276                        page->index);
277
278         if ((mask & (D_EMERG | D_ERROR | D_WARNING)) || portal_printk)
279                 print_to_console(&header, mask, debug_buf, needed, file, fn);
280
281  out:
282         trace_put_tcd(tcd, flags);
283 }
284 EXPORT_SYMBOL(portals_debug_msg);
285
286 static void collect_pages_on_cpu(void *info)
287 {
288         struct trace_cpu_data *tcd;
289         unsigned long flags;
290         struct page_collection *pc = info;
291
292         tcd = trace_get_tcd(flags);
293
294         spin_lock(&pc->pc_lock);
295         list_splice(&tcd->tcd_pages, &pc->pc_pages);
296         INIT_LIST_HEAD(&tcd->tcd_pages);
297         tcd->tcd_cur_pages = 0;
298         if (pc->pc_want_daemon_pages) {
299                 list_splice(&tcd->tcd_daemon_pages, &pc->pc_pages);
300                 INIT_LIST_HEAD(&tcd->tcd_daemon_pages);
301                 tcd->tcd_cur_daemon_pages = 0;
302         }
303         spin_unlock(&pc->pc_lock);
304
305         trace_put_tcd(tcd, flags);
306 }
307
308 static void collect_pages(struct page_collection *pc)
309 {
310         /* needs to be fixed up for preempt */
311         INIT_LIST_HEAD(&pc->pc_pages);
312         collect_pages_on_cpu(pc);
313         smp_call_function(collect_pages_on_cpu, pc, 0, 1);
314 }
315
316 static void put_pages_back_on_cpu(void *info)
317 {
318         struct page_collection *pc = info;
319         struct trace_cpu_data *tcd;
320         struct list_head *pos, *tmp, *cur_head;
321         unsigned long flags;
322
323         tcd = trace_get_tcd(flags);
324
325         cur_head = tcd->tcd_pages.next;
326
327         spin_lock(&pc->pc_lock);
328         list_for_each_safe(pos, tmp, &pc->pc_pages) {
329                 struct page *page;
330
331                 page = list_entry(pos, struct page, PAGE_LIST_ENTRY);
332                 LASSERT(page->index <= PAGE_SIZE);
333                 LASSERT(page_count(page) > 0);
334
335                 if ((unsigned long)page->mapping != smp_processor_id())
336                         continue;
337
338                 list_del(&PAGE_LIST(page));
339                 list_add_tail(&PAGE_LIST(page), cur_head);
340                 tcd->tcd_cur_pages++;
341         }
342         spin_unlock(&pc->pc_lock);
343
344         trace_put_tcd(tcd, flags);
345 }
346
347 static void put_pages_back(struct page_collection *pc)
348 {
349         /* needs to be fixed up for preempt */
350         put_pages_back_on_cpu(pc);
351         smp_call_function(put_pages_back_on_cpu, pc, 0, 1);
352 }
353
354 /* Add pages to a per-cpu debug daemon ringbuffer.  This buffer makes sure that
355  * we have a good amount of data at all times for dumping during an LBUG, even
356  * if we have been steadily writing (and otherwise discarding) pages via the
357  * debug daemon. */
358 static void put_pages_on_daemon_list_on_cpu(void *info)
359 {
360         struct page_collection *pc = info;
361         struct trace_cpu_data *tcd;
362         struct list_head *pos, *tmp;
363         unsigned long flags;
364
365         tcd = trace_get_tcd(flags);
366
367         spin_lock(&pc->pc_lock);
368         list_for_each_safe(pos, tmp, &pc->pc_pages) {
369                 struct page *page;
370
371                 page = list_entry(pos, struct page, PAGE_LIST_ENTRY);
372                 LASSERT(page->index <= PAGE_SIZE);
373                 LASSERT(page_count(page) > 0);
374                 if ((unsigned long)page->mapping != smp_processor_id())
375                         continue;
376
377                 list_del(&PAGE_LIST(page));
378                 list_add_tail(&PAGE_LIST(page), &tcd->tcd_daemon_pages);
379                 tcd->tcd_cur_daemon_pages++;
380
381                 if (tcd->tcd_cur_daemon_pages > tcd->tcd_max_pages) {
382                         LASSERT(!list_empty(&tcd->tcd_daemon_pages));
383                         page = list_entry(tcd->tcd_daemon_pages.next,
384                                           struct page, PAGE_LIST_ENTRY);
385
386                         LASSERT(page->index <= PAGE_SIZE);
387                         LASSERT(page_count(page) > 0);
388
389                         page->index = 0;
390                         list_del(&PAGE_LIST(page));
391                         page->mapping = NULL;
392                         __free_page(page);
393                         tcd->tcd_cur_daemon_pages--;
394                 }
395         }
396         spin_unlock(&pc->pc_lock);
397
398         trace_put_tcd(tcd, flags);
399 }
400
401 static void put_pages_on_daemon_list(struct page_collection *pc)
402 {
403         put_pages_on_daemon_list_on_cpu(pc);
404         smp_call_function(put_pages_on_daemon_list_on_cpu, pc, 0, 1);
405 }
406
407 void trace_debug_print(void)
408 {
409         struct page_collection pc;
410         struct list_head *pos, *tmp;
411
412         spin_lock_init(&pc.pc_lock);
413
414         collect_pages(&pc);
415         list_for_each_safe(pos, tmp, &pc.pc_pages) {
416                 struct page *page;
417                 char *p, *file, *fn;
418
419                 page = list_entry(pos, struct page, PAGE_LIST_ENTRY);
420                 LASSERT(page->index <= PAGE_SIZE);
421                 LASSERT(page_count(page) > 0);
422
423                 p = page_address(page);
424                 while (p < ((char *)page_address(page) + PAGE_SIZE)) {
425                         struct ptldebug_header *hdr;
426                         int len;
427                         hdr = (void *)p;
428                         p += sizeof(*hdr);
429                         file = p;
430                         p += strlen(file) + 1;
431                         fn = p;
432                         p += strlen(fn) + 1;
433                         len = hdr->ph_len - (p - (char *)hdr);
434
435                         print_to_console(hdr, D_EMERG, p, len, file, fn);
436                 }
437
438                 list_del(&PAGE_LIST(page));
439                 page->mapping = NULL;
440                 __free_page(page);
441         }
442 }
443
444 int tracefile_dump_all_pages(char *filename)
445 {
446         struct page_collection pc;
447         struct file *filp;
448         struct list_head *pos, *tmp;
449         mm_segment_t oldfs;
450         int rc;
451
452         down_write(&tracefile_sem);
453
454         filp = filp_open(filename, O_CREAT|O_EXCL|O_WRONLY, 0600);
455         if (IS_ERR(filp)) {
456                 rc = PTR_ERR(filp);
457                 printk(KERN_ERR "LustreError: can't open %s for dump: rc %d\n",
458                       filename, rc);
459                 goto out;
460         }
461
462         spin_lock_init(&pc.pc_lock);
463         pc.pc_want_daemon_pages = 1;
464         collect_pages(&pc);
465         if (list_empty(&pc.pc_pages)) {
466                 rc = 0;
467                 goto close;
468         }
469
470         /* ok, for now, just write the pages.  in the future we'll be building
471          * iobufs with the pages and calling generic_direct_IO */
472         oldfs = get_fs();
473         set_fs(get_ds());
474         list_for_each_safe(pos, tmp, &pc.pc_pages) {
475                 struct page *page;
476
477                 page = list_entry(pos, struct page, PAGE_LIST_ENTRY);
478                 LASSERT(page->index <= PAGE_SIZE);
479                 LASSERT(page_count(page) > 0);
480
481                 rc = filp->f_op->write(filp, page_address(page), page->index,
482                                        &filp->f_pos);
483                 if (rc != page->index) {
484                         printk(KERN_WARNING "wanted to write %lu but wrote "
485                                "%d\n", page->index, rc);
486                         put_pages_back(&pc);
487                         break;
488                 }
489                 list_del(&PAGE_LIST(page));
490                 page->mapping = NULL;
491                 __free_page(page);
492         }
493         set_fs(oldfs);
494         rc = filp->f_op->fsync(filp, filp->f_dentry, 1);
495         if (rc)
496                 printk(KERN_ERR "sync returns %d\n", rc);
497  close:
498         filp_close(filp, 0);
499  out:
500         up_write(&tracefile_sem);
501         return rc;
502 }
503
504 void trace_flush_pages(void)
505 {
506         struct page_collection pc;
507         struct list_head *pos, *tmp;
508
509         spin_lock_init(&pc.pc_lock);
510
511         collect_pages(&pc);
512         list_for_each_safe(pos, tmp, &pc.pc_pages) {
513                 struct page *page;
514
515                 page = list_entry(pos, struct page, PAGE_LIST_ENTRY);
516                 LASSERT(page->index <= PAGE_SIZE);
517                 LASSERT(page_count(page) > 0);
518
519                 list_del(&PAGE_LIST(page));
520                 page->mapping = NULL;
521                 __free_page(page);
522         }
523 }
524
525 int trace_dk(struct file *file, const char *buffer, unsigned long count,
526              void *data)
527 {
528         char *name;
529         unsigned long off;
530         int rc;
531
532         name = kmalloc(count + 1, GFP_KERNEL);
533         if (name == NULL)
534                 return -ENOMEM;
535
536         if (copy_from_user(name, buffer, count)) {
537                 rc = -EFAULT;
538                 goto out;
539         }
540
541         if (name[0] != '/') {
542                 rc = -EINVAL;
543                 goto out;
544         }
545
546         /* be nice and strip out trailing '\n' */
547         for (off = count ; off > 2 && isspace(name[off - 1]); off--)
548                 ;
549
550         name[off] = '\0';
551         rc = tracefile_dump_all_pages(name);
552 out:
553         if (name)
554                 kfree(name);
555         return count;
556 }
557 EXPORT_SYMBOL(trace_dk);
558
559 static int tracefiled(void *arg)
560 {
561         struct page_collection pc;
562         struct tracefiled_ctl *tctl = arg;
563         struct list_head *pos, *tmp;
564         struct ptldebug_header *hdr;
565         struct file *filp;
566         struct page *page;
567         mm_segment_t oldfs;
568         int rc;
569
570         /* we're started late enough that we pick up init's fs context */
571         /* this is so broken in uml?  what on earth is going on? */
572         kportal_daemonize("ktracefiled");
573         reparent_to_init();
574
575         spin_lock_init(&pc.pc_lock);
576         complete(&tctl->tctl_start);
577
578         while (1) {
579                 wait_queue_t __wait;
580
581                 init_waitqueue_entry(&__wait, current);
582                 add_wait_queue(&tctl->tctl_waitq, &__wait);
583                 set_current_state(TASK_INTERRUPTIBLE);
584                 schedule_timeout(HZ);
585                 remove_wait_queue(&tctl->tctl_waitq, &__wait);
586
587                 if (atomic_read(&tctl->tctl_shutdown))
588                         break;
589
590                 pc.pc_want_daemon_pages = 0;
591                 collect_pages(&pc);
592                 if (list_empty(&pc.pc_pages))
593                         continue;
594
595                 filp = NULL;
596                 down_read(&tracefile_sem);
597                 if (tracefile != NULL) {
598                         filp = filp_open(tracefile, O_CREAT|O_RDWR|O_APPEND|O_LARGEFILE,
599                                         0600);
600                         if (IS_ERR(filp)) {
601                                 printk("couldn't open %s: %ld\n", tracefile,
602                                        PTR_ERR(filp));
603                                 filp = NULL;
604                         }
605                 }
606                 up_read(&tracefile_sem);
607                 if (filp == NULL) {
608                         put_pages_on_daemon_list(&pc);
609                         continue;
610                 }
611
612                 oldfs = get_fs();
613                 set_fs(get_ds());
614
615                 /* mark the first header, so we can sort in chunks */
616                 page = list_entry(pc.pc_pages.next, struct page,
617                                   PAGE_LIST_ENTRY);
618                 LASSERT(page->index <= PAGE_SIZE);
619                 LASSERT(page_count(page) > 0);
620
621                 hdr = page_address(page);
622                 hdr->ph_flags |= PH_FLAG_FIRST_RECORD;
623
624                 list_for_each_safe(pos, tmp, &pc.pc_pages) {
625                         page = list_entry(pos, struct page, PAGE_LIST_ENTRY);
626                         LASSERT(page->index <= PAGE_SIZE);
627                         LASSERT(page_count(page) > 0);
628
629                         rc = filp->f_op->write(filp, page_address(page),
630                                         page->index, &filp->f_pos);
631                         if (rc != page->index) {
632                                 printk(KERN_WARNING "wanted to write %lu but "
633                                        "wrote %d\n", page->index, rc);
634                                 put_pages_back(&pc);
635                         }
636                 }
637                 set_fs(oldfs);
638                 filp_close(filp, 0);
639
640                 put_pages_on_daemon_list(&pc);
641         }
642         complete(&tctl->tctl_stop);
643         return 0;
644 }
645
646 int trace_start_thread(void)
647 {
648         struct tracefiled_ctl *tctl = &trace_tctl;
649         int rc = 0;
650
651         down(&trace_thread_sem);
652         if (thread_running)
653                 goto out;
654
655         init_completion(&tctl->tctl_start);
656         init_completion(&tctl->tctl_stop);
657         init_waitqueue_head(&tctl->tctl_waitq);
658         atomic_set(&tctl->tctl_shutdown, 0);
659
660         if (kernel_thread(tracefiled, tctl, 0) < 0) {
661                 rc = -ECHILD;
662                 goto out;
663         }
664
665         wait_for_completion(&tctl->tctl_start);
666         thread_running = 1;
667 out:
668         up(&trace_thread_sem);
669         return rc;
670 }
671
672 void trace_stop_thread(void)
673 {
674         struct tracefiled_ctl *tctl = &trace_tctl;
675
676         down(&trace_thread_sem);
677         if (thread_running) {
678                 printk(KERN_INFO "Shutting down debug daemon thread...\n");
679                 atomic_set(&tctl->tctl_shutdown, 1);
680                 wait_for_completion(&tctl->tctl_stop);
681                 thread_running = 0;
682         }
683         up(&trace_thread_sem);
684 }
685
686 int trace_write_daemon_file(struct file *file, const char *buffer,
687                             unsigned long count, void *data)
688 {
689         char *name;
690         unsigned long off;
691         int rc;
692
693         name = kmalloc(count + 1, GFP_KERNEL);
694         if (name == NULL)
695                 return -ENOMEM;
696
697         if (copy_from_user(name, buffer, count)) {
698                 rc = -EFAULT;
699                 goto out;
700         }
701
702         /* be nice and strip out trailing '\n' */
703         for (off = count ; off > 2 && isspace(name[off - 1]); off--)
704                 ;
705
706         name[off] = '\0';
707
708         down_write(&tracefile_sem);
709         if (strcmp(name, "stop") == 0) {
710                 tracefile = NULL;
711                 trace_stop_thread();
712                 goto out_sem;
713         }
714
715         if (name[0] != '/') {
716                 rc = -EINVAL;
717                 goto out_sem;
718         }
719
720         if (tracefile != NULL)
721                 kfree(tracefile);
722
723         tracefile = name;
724         name = NULL;
725         trace_start_thread();
726
727  out_sem:
728         up_write(&tracefile_sem);
729
730  out:
731         if (name)
732                 kfree(name);
733         return count;
734 }
735
736 int trace_read_daemon_file(char *page, char **start, off_t off, int count,
737                            int *eof, void *data)
738 {
739         int rc;
740
741         down_read(&tracefile_sem);
742         rc = snprintf(page, count, "%s", tracefile);
743         up_read(&tracefile_sem);
744
745         return rc;
746 }
747
748 int trace_write_debug_size(struct file *file, const char *buffer,
749                            unsigned long count, void *data)
750 {
751         char *string;
752         int rc, i, max;
753
754         string = kmalloc(count + 1, GFP_KERNEL);
755         if (string == NULL)
756                 return -ENOMEM;
757
758         if (copy_from_user(string, buffer, count)) {
759                 rc = -EFAULT;
760                 goto out;
761         }
762
763         max = simple_strtoul(string, NULL, 0);
764         if (max == 0) {
765                 rc = -EINVAL;
766                 goto out;
767         }
768         max /= smp_num_cpus;
769
770         if (max > num_physpages / 5 * 4) {
771                 printk(KERN_ERR "Lustre: Refusing to set debug buffer size to "
772                        "%d pages, which is more than 80%% of physical pages "
773                        "(%lu).\n", max * smp_num_cpus, num_physpages / 5 * 4);
774                 return count;
775         }
776         for (i = 0; i < NR_CPUS; i++) {
777                 struct trace_cpu_data *tcd;
778                 tcd = &trace_data[i].tcd;
779                 tcd->tcd_max_pages = max;
780         }
781  out:
782         kfree(string);
783         return count;
784 }
785
786 int trace_read_debug_size(char *page, char **start, off_t off, int count,
787                           int *eof, void *data)
788 {
789         struct trace_cpu_data *tcd;
790         unsigned long flags;
791         int rc;
792
793         tcd = trace_get_tcd(flags);
794         rc = snprintf(page, count, "%lu", tcd->tcd_max_pages);
795         trace_put_tcd(tcd, flags);
796
797         return rc;
798 }
799
800 int tracefile_init(void)
801 {
802         struct trace_cpu_data *tcd;
803         int i;
804
805         for (i = 0; i < NR_CPUS; i++) {
806                 tcd = &trace_data[i].tcd;
807                 INIT_LIST_HEAD(&tcd->tcd_pages);
808                 INIT_LIST_HEAD(&tcd->tcd_daemon_pages);
809                 tcd->tcd_cur_pages = 0;
810                 tcd->tcd_cur_daemon_pages = 0;
811                 tcd->tcd_max_pages = TCD_MAX_PAGES;
812                 tcd->tcd_shutting_down = 0;
813         }
814         return 0;
815 }
816
817 static void trace_cleanup_on_cpu(void *info)
818 {
819         struct trace_cpu_data *tcd;
820         struct list_head *pos, *tmp;
821         unsigned long flags;
822
823         tcd = trace_get_tcd(flags);
824
825         tcd->tcd_shutting_down = 1;
826
827         list_for_each_safe(pos, tmp, &tcd->tcd_pages) {
828                 struct page *page;
829
830                 page = list_entry(pos, struct page, PAGE_LIST_ENTRY);
831                 LASSERT(page->index <= PAGE_SIZE);
832                 LASSERT(page_count(page) > 0);
833
834                 list_del(&PAGE_LIST(page));
835                 page->mapping = NULL;
836                 __free_page(page);
837         }
838         tcd->tcd_cur_pages = 0;
839
840         trace_put_tcd(tcd, flags);
841 }
842
843 static void trace_cleanup(void)
844 {
845         struct page_collection pc;
846
847         INIT_LIST_HEAD(&pc.pc_pages);
848         spin_lock_init(&pc.pc_lock);
849
850         trace_cleanup_on_cpu(&pc);
851         smp_call_function(trace_cleanup_on_cpu, &pc, 0, 1);
852 }
853
854 void tracefile_exit(void)
855 {
856         trace_stop_thread();
857         trace_cleanup();
858 }