Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 84058
b: refs/heads/master
c: 877c357
h: refs/heads/master
v: v3
  • Loading branch information
Len Brown committed Feb 7, 2008
1 parent 664d1fc commit 1f7a7bb
Show file tree
Hide file tree
Showing 562 changed files with 13,420 additions and 17,875 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7c2670bbb53820d0a4fab8d74593eeccd1eef225
refs/heads/master: 877c357e7511395bc923ec9efc2e8b021a17ed79
17 changes: 17 additions & 0 deletions trunk/Documentation/BUG-HUNTING
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,23 @@ And recompile the kernel with CONFIG_DEBUG_INFO enabled:
gdb vmlinux
(gdb) p vt_ioctl
(gdb) l *(0x<address of vt_ioctl> + 0xda8)
or, as one command
(gdb) l *(vt_ioctl + 0xda8)

If you have a call trace, such as :-
>Call Trace:
> [<ffffffff8802c8e9>] :jbd:log_wait_commit+0xa3/0xf5
> [<ffffffff810482d9>] autoremove_wake_function+0x0/0x2e
> [<ffffffff8802770b>] :jbd:journal_stop+0x1be/0x1ee
> ...
this shows the problem in the :jbd: module. You can load that module in gdb
and list the relevant code.
gdb fs/jbd/jbd.ko
(gdb) p log_wait_commit
(gdb) l *(0x<address> + 0xa3)
or
(gdb) l *(log_wait_commit + 0xa3)


Another very useful option of the Kernel Hacking section in menuconfig is
Debug memory allocations. This will help you see whether data has been
Expand Down
2 changes: 1 addition & 1 deletion trunk/Documentation/DocBook/kernel-api.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ X!Ilib/string.c
!Emm/vmalloc.c
!Imm/page_alloc.c
!Emm/mempool.c
!Emm/dmapool.c
!Emm/page-writeback.c
!Emm/truncate.c
</sect1>
Expand Down Expand Up @@ -371,7 +372,6 @@ X!Iinclude/linux/device.h
!Edrivers/base/class.c
!Edrivers/base/firmware_class.c
!Edrivers/base/transport_class.c
!Edrivers/base/dmapool.c
<!-- Cannot be included, because
attribute_container_add_class_device_adapter
and attribute_container_classdev_to_container
Expand Down
32 changes: 16 additions & 16 deletions trunk/Documentation/DocBook/kernel-locking.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -717,15 +717,15 @@ used, and when it gets full, throws out the least used one.
<para>
For our first example, we assume that all operations are in user
context (ie. from system calls), so we can sleep. This means we can
use a semaphore to protect the cache and all the objects within
use a mutex to protect the cache and all the objects within
it. Here's the code:
</para>

<programlisting>
#include &lt;linux/list.h&gt;
#include &lt;linux/slab.h&gt;
#include &lt;linux/string.h&gt;
#include &lt;asm/semaphore.h&gt;
#include &lt;linux/mutex.h&gt;
#include &lt;asm/errno.h&gt;

struct object
Expand All @@ -737,7 +737,7 @@ struct object
};

/* Protects the cache, cache_num, and the objects within it */
static DECLARE_MUTEX(cache_lock);
static DEFINE_MUTEX(cache_lock);
static LIST_HEAD(cache);
static unsigned int cache_num = 0;
#define MAX_CACHE_SIZE 10
Expand Down Expand Up @@ -789,31 +789,31 @@ int cache_add(int id, const char *name)
obj-&gt;id = id;
obj-&gt;popularity = 0;

down(&amp;cache_lock);
mutex_lock(&amp;cache_lock);
__cache_add(obj);
up(&amp;cache_lock);
mutex_unlock(&amp;cache_lock);
return 0;
}

void cache_delete(int id)
{
down(&amp;cache_lock);
mutex_lock(&amp;cache_lock);
__cache_delete(__cache_find(id));
up(&amp;cache_lock);
mutex_unlock(&amp;cache_lock);
}

int cache_find(int id, char *name)
{
struct object *obj;
int ret = -ENOENT;

down(&amp;cache_lock);
mutex_lock(&amp;cache_lock);
obj = __cache_find(id);
if (obj) {
ret = 0;
strcpy(name, obj-&gt;name);
}
up(&amp;cache_lock);
mutex_unlock(&amp;cache_lock);
return ret;
}
</programlisting>
Expand Down Expand Up @@ -853,7 +853,7 @@ The change is shown below, in standard patch format: the
int popularity;
};

-static DECLARE_MUTEX(cache_lock);
-static DEFINE_MUTEX(cache_lock);
+static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED;
static LIST_HEAD(cache);
static unsigned int cache_num = 0;
Expand All @@ -870,22 +870,22 @@ The change is shown below, in standard patch format: the
obj-&gt;id = id;
obj-&gt;popularity = 0;

- down(&amp;cache_lock);
- mutex_lock(&amp;cache_lock);
+ spin_lock_irqsave(&amp;cache_lock, flags);
__cache_add(obj);
- up(&amp;cache_lock);
- mutex_unlock(&amp;cache_lock);
+ spin_unlock_irqrestore(&amp;cache_lock, flags);
return 0;
}

void cache_delete(int id)
{
- down(&amp;cache_lock);
- mutex_lock(&amp;cache_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&amp;cache_lock, flags);
__cache_delete(__cache_find(id));
- up(&amp;cache_lock);
- mutex_unlock(&amp;cache_lock);
+ spin_unlock_irqrestore(&amp;cache_lock, flags);
}

Expand All @@ -895,14 +895,14 @@ The change is shown below, in standard patch format: the
int ret = -ENOENT;
+ unsigned long flags;

- down(&amp;cache_lock);
- mutex_lock(&amp;cache_lock);
+ spin_lock_irqsave(&amp;cache_lock, flags);
obj = __cache_find(id);
if (obj) {
ret = 0;
strcpy(name, obj-&gt;name);
}
- up(&amp;cache_lock);
- mutex_unlock(&amp;cache_lock);
+ spin_unlock_irqrestore(&amp;cache_lock, flags);
return ret;
}
Expand Down
6 changes: 3 additions & 3 deletions trunk/Documentation/fb/deferred_io.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ IO. The following example may be a useful explanation of how one such setup
works:

- userspace app like Xfbdev mmaps framebuffer
- deferred IO and driver sets up nopage and page_mkwrite handlers
- deferred IO and driver sets up fault and page_mkwrite handlers
- userspace app tries to write to mmaped vaddress
- we get pagefault and reach nopage handler
- nopage handler finds and returns physical page
- we get pagefault and reach fault handler
- fault handler finds and returns physical page
- we get page_mkwrite where we add this page to a list
- schedule a workqueue task to be run after a delay
- app continues writing to that page with no additional cost. this is
Expand Down
7 changes: 0 additions & 7 deletions trunk/Documentation/feature-removal-schedule.txt
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,6 @@ Who: Randy Dunlap <randy.dunlap@oracle.com>

---------------------------

What: drivers depending on OSS_OBSOLETE
When: options in 2.6.23, code in 2.6.25
Why: obsolete OSS drivers
Who: Adrian Bunk <bunk@stusta.de>

---------------------------

What: libata spindown skipping and warning
When: Dec 2008
Why: Some halt(8) implementations synchronize caches for and spin
Expand Down
8 changes: 8 additions & 0 deletions trunk/Documentation/filesystems/proc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,14 @@ nr_inodes
Denotes the number of inodes the system has allocated. This number will
grow and shrink dynamically.

nr_open
-------

Denotes the maximum number of file-handles a process can
allocate. Default value is 1024*1024 (1048576) which should be
enough for most machines. Actual limit depends on RLIMIT_NOFILE
resource limit.

nr_free_inodes
--------------

Expand Down
3 changes: 3 additions & 0 deletions trunk/Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,9 @@ and is between 256 and 4096 characters. It is defined in the file
loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
as idle=poll.

ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
Claim all unknown PCI IDE storage controllers.

ignore_loglevel [KNL]
Ignore loglevel setting - this will print /all/
kernel messages to the console. Useful for debugging.
Expand Down
81 changes: 69 additions & 12 deletions trunk/Documentation/kprobes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ or in registers (e.g., for x86_64 or for an i386 fastcall function).
The jprobe will work in either case, so long as the handler's
prototype matches that of the probed function.

1.3 How Does a Return Probe Work?
1.3 Return Probes

1.3.1 How Does a Return Probe Work?

When you call register_kretprobe(), Kprobes establishes a kprobe at
the entry to the function. When the probed function is called and this
Expand All @@ -107,9 +109,9 @@ At boot time, Kprobes registers a kprobe at the trampoline.

When the probed function executes its return instruction, control
passes to the trampoline and that probe is hit. Kprobes' trampoline
handler calls the user-specified handler associated with the kretprobe,
then sets the saved instruction pointer to the saved return address,
and that's where execution resumes upon return from the trap.
handler calls the user-specified return handler associated with the
kretprobe, then sets the saved instruction pointer to the saved return
address, and that's where execution resumes upon return from the trap.

While the probed function is executing, its return address is
stored in an object of type kretprobe_instance. Before calling
Expand All @@ -131,6 +133,30 @@ zero when the return probe is registered, and is incremented every
time the probed function is entered but there is no kretprobe_instance
object available for establishing the return probe.

1.3.2 Kretprobe entry-handler

Kretprobes also provides an optional user-specified handler which runs
on function entry. This handler is specified by setting the entry_handler
field of the kretprobe struct. Whenever the kprobe placed by kretprobe at the
function entry is hit, the user-defined entry_handler, if any, is invoked.
If the entry_handler returns 0 (success) then a corresponding return handler
is guaranteed to be called upon function return. If the entry_handler
returns a non-zero error then Kprobes leaves the return address as is, and
the kretprobe has no further effect for that particular function instance.

Multiple entry and return handler invocations are matched using the unique
kretprobe_instance object associated with them. Additionally, a user
may also specify per return-instance private data to be part of each
kretprobe_instance object. This is especially useful when sharing private
data between corresponding user entry and return handlers. The size of each
private data object can be specified at kretprobe registration time by
setting the data_size field of the kretprobe struct. This data can be
accessed through the data field of each kretprobe_instance object.

In case probed function is entered but there is no kretprobe_instance
object available, then in addition to incrementing the nmissed count,
the user entry_handler invocation is also skipped.

2. Architectures Supported

Kprobes, jprobes, and return probes are implemented on the following
Expand Down Expand Up @@ -274,6 +300,8 @@ of interest:
- ret_addr: the return address
- rp: points to the corresponding kretprobe object
- task: points to the corresponding task struct
- data: points to per return-instance private data; see "Kretprobe
entry-handler" for details.

The regs_return_value(regs) macro provides a simple abstraction to
extract the return value from the appropriate register as defined by
Expand Down Expand Up @@ -556,23 +584,52 @@ report failed calls to sys_open().
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/ktime.h>

/* per-instance private data */
struct my_data {
ktime_t entry_stamp;
};

static const char *probed_func = "sys_open";

/* Return-probe handler: If the probed function fails, log the return value. */
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
/* Timestamp function entry. */
static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
struct my_data *data;

if(!current->mm)
return 1; /* skip kernel threads */

data = (struct my_data *)ri->data;
data->entry_stamp = ktime_get();
return 0;
}

/* If the probed function failed, log the return value and duration.
* Duration may turn out to be zero consistently, depending upon the
* granularity of time accounting on the platform. */
static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
int retval = regs_return_value(regs);
struct my_data *data = (struct my_data *)ri->data;
s64 delta;
ktime_t now;

if (retval < 0) {
printk("%s returns %d\n", probed_func, retval);
now = ktime_get();
delta = ktime_to_ns(ktime_sub(now, data->entry_stamp));
printk("%s: return val = %d (duration = %lld ns)\n",
probed_func, retval, delta);
}
return 0;
}

static struct kretprobe my_kretprobe = {
.handler = ret_handler,
/* Probe up to 20 instances concurrently. */
.maxactive = 20
.handler = return_handler,
.entry_handler = entry_handler,
.data_size = sizeof(struct my_data),
.maxactive = 20, /* probe up to 20 instances concurrently */
};

static int __init kretprobe_init(void)
Expand All @@ -584,7 +641,7 @@ static int __init kretprobe_init(void)
printk("register_kretprobe failed, returned %d\n", ret);
return -1;
}
printk("Planted return probe at %p\n", my_kretprobe.kp.addr);
printk("Kretprobe active on %s\n", my_kretprobe.kp.symbol_name);
return 0;
}

Expand All @@ -594,7 +651,7 @@ static void __exit kretprobe_exit(void)
printk("kretprobe unregistered\n");
/* nmissed > 0 suggests that maxactive was set too low. */
printk("Missed probing %d instances of %s\n",
my_kretprobe.nmissed, probed_func);
my_kretprobe.nmissed, probed_func);
}

module_init(kretprobe_init)
Expand Down
Loading

0 comments on commit 1f7a7bb

Please sign in to comment.