summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <sandmann@redhat.com>2005-12-19 20:40:33 +0000
committerSøren Sandmann Pedersen <ssp@src.gnome.org>2005-12-19 20:40:33 +0000
commit00cd855468de509006f3cce2c89d5ba08ee5c476 (patch)
tree95ea40c4f7bd1ba7762e416d70c77a16e1f077c6
parentdeff3312e51f6e1159f9b1e13189e8a1c9d809d6 (diff)
Make kernel module compile with recent kernels. Delete lots of commented
Mon Dec 19 15:39:52 2005 Søren Sandmann <sandmann@redhat.com> * module/sysprof-module.c (timer_notify): Make kernel module compile with recent kernels. Delete lots of commented out code.
-rw-r--r--ChangeLog5
-rw-r--r--module/sysprof-module.c377
2 files changed, 27 insertions, 355 deletions
diff --git a/ChangeLog b/ChangeLog
index 6486e1f..f5245d5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Mon Dec 19 15:39:52 2005 Søren Sandmann <sandmann@redhat.com>
+
+ * module/sysprof-module.c (timer_notify): Make kernel module
+ compile with recent kernels. Delete lots of commented out code.
+
Sat Oct 29 14:43:00 2005 Søren Sandmann <sandmann@redhat.com>
Fix crash pointed reported by Rudi Chiarito.
diff --git a/module/sysprof-module.c b/module/sysprof-module.c
index 143f58e..8a5cb58 100644
--- a/module/sysprof-module.c
+++ b/module/sysprof-module.c
@@ -72,13 +72,6 @@ DECLARE_WAIT_QUEUE_HEAD (wait_for_exit);
# error Sysprof only supports the i386 and x86-64 architectures
#endif
-#if 0
-static void on_timer(unsigned long);
-#endif
-#if 0
-static struct timer_list timer;
-#endif
-
typedef struct userspace_reader userspace_reader;
struct userspace_reader
{
@@ -87,351 +80,34 @@ struct userspace_reader
unsigned long *cache;
};
-#if 0
-/* This function was mostly cutted and pasted from ptrace.c
- */
-
-/* Access another process' address space.
- * Source/target buffer must be kernel space,
- * Do not walk the page table directly, use get_user_pages
-*/
-static struct mm_struct *
-get_mm (struct task_struct *tsk)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
- struct mm_struct *mm;
-
- task_lock (tsk);
- mm = tsk->mm;
- task_unlock (tsk);
-
- return mm;
-#else
- return get_task_mm (tsk);
-#endif
-}
-
-static void
-put_mm (struct mm_struct *mm)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
- mmput(mm);
-#endif
-}
-#endif
-
-#if 0
-static int
-x_access_process_vm (struct task_struct *tsk,
- unsigned long addr,
- void *buf, int len, int write)
-{
- struct mm_struct *mm;
- struct vm_area_struct *vma;
- struct page *page;
- void *old_buf = buf;
-
- mm = get_mm (tsk);
-
- if (!mm)
- return 0;
-
- down_read(&mm->mmap_sem);
- /* ignore errors, just check how much was sucessfully transfered */
- while (len)
- {
- int bytes, ret, offset;
- void *maddr;
-
- ret = get_user_pages(tsk, mm, addr, 1,
- write, 1, &page, &vma);
- if (ret <= 0) {
- break;
- }
- bytes = len;
- offset = addr & (PAGE_SIZE-1);
- if (bytes > PAGE_SIZE-offset)
- bytes = PAGE_SIZE-offset;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
-
- flush_cache_page(vma, addr);
-
-#endif
-
- maddr = kmap(page);
- if (write) {
- copy_to_user_page(vma, page, addr,
- maddr + offset, buf, bytes);
- set_page_dirty_lock(page);
- } else {
- copy_from_user_page(vma, page, addr,
- buf, maddr + offset, bytes);
- }
- kunmap(page);
- page_cache_release(page);
- len -= bytes;
- buf += bytes;
- addr += bytes;
- }
- up_read(&mm->mmap_sem);
-
- put_mm (mm);
-
- return buf - old_buf;
-}
-#endif
-
-#if 0
-static int
-init_userspace_reader (userspace_reader *reader,
- struct task_struct *task)
-{
- reader->task = task;
- reader->cache = kmalloc (PAGE_SIZE, GFP_KERNEL);
- if (!reader->cache)
- return 0;
- reader->cache_address = 0x0;
- return 1;
-}
-#endif
-
-#if 0
-static int
-page_readable (userspace_reader *reader, unsigned long address)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,6,11)
- struct mm_struct *mm;
- int result = 1;
-
- mm = get_mm (reader->task);
-
- if (!mm)
- return 0;
-
- if (!check_user_page_readable (reader->task->mm, address))
- result = 0;
-
- put_mm (mm);
-
- return result;
-#endif
-
- return 1;
-}
-#endif
-
-#if 0
-static int
-read_user_space (userspace_reader *reader,
- unsigned long address,
- unsigned long *result)
-{
- unsigned long cache_address = reader->cache_address;
- int index, r;
-
- if (!cache_address || cache_address != (address & PAGE_MASK))
- {
- if (!page_readable (reader, address))
- return 0;
-
- cache_address = address & PAGE_MASK;
-
- r = x_access_process_vm (reader->task, cache_address,
- reader->cache, PAGE_SIZE, 0);
-
- if (r != PAGE_SIZE) {
- return 0;
- }
-
- reader->cache_address = cache_address;
- }
-
- index = (address - cache_address) / sizeof (unsigned long);
-
- *result = reader->cache[index];
- return 1;
-}
-#endif
-
-#if 0
-static void
-done_userspace_reader (userspace_reader *reader)
-{
- kfree (reader->cache);
-}
-#endif
-
typedef struct StackFrame StackFrame;
struct StackFrame {
unsigned long next;
unsigned long return_address;
};
-#if 0
-static int
-read_frame (userspace_reader *reader, unsigned long addr, StackFrame *frame)
-{
- if (!addr || !frame)
- return 0;
-
- frame->next = 0;
- frame->return_address = 0;
-
- if (!read_user_space (reader, addr, &(frame->next)))
- return 0;
-
- if (!read_user_space (reader, addr + 4, &(frame->return_address)))
- return 0;
-
- return 1;
-}
-#endif
+struct work_struct work;
-#if 0
-static struct pt_regs *
-get_regs (struct task_struct *task)
+static int
+read_frame (void *frame_pointer, StackFrame *frame)
{
- /* This seems to work in Linux 2.6.11 */
- void *stack_top = (void *)task->thread.esp0;
- return stack_top - sizeof(struct pt_regs);
-
#if 0
- /* This used to work, but doesn't anymore */
- return ((struct pt_regs *) (THREAD_SIZE + (unsigned long) task->thread_info)) - 1;
-#endif
-
-#if 0
- /* One might suspect that this would work, but it doesn't
+ /* This is commented out because we seem to be called with
+ * (current_thread_info()->addr_limit.seg)) == 0
+ * which means access_ok() _always_ fails.
+ *
+ * Not sure why (or if) this isn't the case for oprofile
*/
- return task_pt_regs (task);
-#endif
-}
-#endif
-
-#if 0
-static void
-generate_stack_trace(struct task_struct *task,
- SysprofStackTrace *trace)
-{
- struct pt_regs *regs = get_regs (task); // task->thread.regs;
-
- StackFrame frame;
- unsigned long addr;
- userspace_reader reader;
- int i;
-
- memset(trace, 0, sizeof (SysprofStackTrace));
-
- trace->pid = task->pid;
- trace->truncated = 0;
-
- trace->addresses[0] = (void *)regs->REG_INS_PTR;
-
- i = 1;
-
- addr = regs->REG_FRAME_PTR;
-
-#if 0
- printk (KERN_ALERT "frame pointer: %p\n", regs->REG_FRAME_PTR);
-#endif
-
- if (init_userspace_reader (&reader, task))
- {
- while (i < SYSPROF_MAX_ADDRESSES &&
- read_frame (&reader, addr, &frame) &&
- addr < START_OF_STACK && addr >= regs->REG_STACK_PTR)
- {
- trace->addresses[i++] = (void *)frame.return_address;
- addr = frame.next;
- }
-
- done_userspace_reader (&reader);
- }
-
- trace->n_addresses = i;
- if (i == SYSPROF_MAX_ADDRESSES)
- trace->truncated = 1;
- else
- trace->truncated = 0;
-}
-#endif
-
-#if 0
-static void
-do_generate (void *data)
-{
- struct task_struct *task = data;
-
- generate_stack_trace(task, head);
-
- if (head++ == &stack_traces[N_TRACES - 1])
- head = &stack_traces[0];
-
- wake_up (&wait_for_trace);
-
- /* If a task dies between the time we see it in on_timer and
- * the time we get here, it will be leaked. If __put_task_struct9)
- * was exported, then we could do this properly
- */
-
- atomic_dec (&(task)->usage);
-
- mod_timer(&timer, jiffies + INTERVAL);
-}
-#endif
-
-struct work_struct work;
-
-#if 0
-static void
-on_timer(unsigned long dong)
-{
- if (current && current->state == TASK_RUNNING && current->pid != 0)
- {
- get_task_struct (current);
-
- INIT_WORK (&work, do_generate, current);
-
- schedule_work (&work);
- }
- else
- {
- mod_timer(&timer, jiffies + INTERVAL);
- }
-}
+ if (!access_ok(VERIFY_READ, frame_pointer, sizeof(StackFrame)))
+ return 1;
#endif
-/**
- * pages_present() from OProfile
- *
- * Copyright 2002 OProfile authors
- *
- * author John Levon
- * author David Smith
- */
+ if (__copy_from_user_inatomic (
+ frame, frame_pointer, sizeof (StackFrame)))
+ return 2;
-#ifdef CONFIG_X86_4G
-/* With a 4G kernel/user split, user pages are not directly
- * accessible from the kernel, so don't try
- */
-static int pages_present(StackFrame * head)
-{
return 0;
}
-#else
-/* check that the page(s) containing the frame head are present */
-static int pages_present(StackFrame * head)
-{
- struct mm_struct * mm = current->mm;
-
- /* FIXME: only necessary once per page */
- if (!check_user_page_readable(mm, (unsigned long)head))
- return 0;
-
- return check_user_page_readable(mm, (unsigned long)(head + 1));
-}
-#endif /* CONFIG_X86_4G */
static int
timer_notify (struct pt_regs *regs)
@@ -441,7 +117,6 @@ timer_notify (struct pt_regs *regs)
#else
# define START_OF_STACK 0xBFFFFFFF
#endif
- StackFrame *frame;
static int n_samples;
SysprofStackTrace *trace = head;
int i;
@@ -471,6 +146,8 @@ timer_notify (struct pt_regs *regs)
}
else
{
+ StackFrame *frame_pointer;
+ StackFrame frame;
memset(trace, 0, sizeof (SysprofStackTrace));
trace->pid = current->pid;
@@ -480,15 +157,15 @@ timer_notify (struct pt_regs *regs)
trace->addresses[i++] = (void *)regs->REG_INS_PTR;
- frame = (StackFrame *)regs->REG_FRAME_PTR;
-
- while (pages_present (frame) &&
+ frame_pointer = (void *)regs->REG_FRAME_PTR;
+
+ while (read_frame (frame_pointer, &frame) == 0 &&
i < SYSPROF_MAX_ADDRESSES &&
- ((unsigned long)frame) < START_OF_STACK &&
- (unsigned long)frame >= regs->REG_STACK_PTR)
+ ((unsigned long)frame_pointer) < START_OF_STACK &&
+ (unsigned long)frame_pointer >= regs->REG_STACK_PTR)
{
- trace->addresses[i++] = (void *)frame->return_address;
- frame = (StackFrame *)frame->next;
+ trace->addresses[i++] = (void *)frame.return_address;
+ frame_pointer = (StackFrame *)frame.next;
}
trace->n_addresses = i;
@@ -556,12 +233,6 @@ init_module(void)
register_timer_hook (timer_notify);
-#if 0
- init_timer(&timer);
- timer.function = on_timer;
- mod_timer(&timer, jiffies + INTERVAL);
-#endif
-
printk(KERN_ALERT "sysprof: loaded\n");
return 0;
@@ -570,10 +241,6 @@ init_module(void)
void
cleanup_module(void)
{
-#if 0
- del_timer (&timer);
-#endif
-
unregister_timer_hook (timer_notify);
remove_proc_entry("sysprof-trace", &proc_root);