[PATCH] relayfs
Here's the latest version of relayfs, against linux-2.6.11-mm2. I'm hoping
you'll consider putting this version back into your tree - the previous
rounds of comment seem to have shaken out all the API issues and the number
of comments on the code itself have also steadily dwindled.
This patch is essentially the same as the relayfs redux part 5 patch, with
some minor changes based on reviewer comments. Thanks again to Pekka
Enberg for those. The patch size without documentation is now a little
smaller at just over 40k. Here's a detailed list of the changes:
- removed the attribute_flags in relay open and changed it to a
boolean specifying either overwrite or no-overwrite mode, and removed
everything referencing the attribute flags.
- added a check for NULL names in relayfs_create_entry()
- got rid of the unnecessary multiple labels in relay_create_buf()
- some minor simplification of relay_alloc_buf() which got rid of a
couple params
- updated the Documentation
In addition, this version (through code contained in the relay-apps tarball
linked to below, not as part of the relayfs patch) tries to make it as easy
as possible to create the cooperating kernel/user pieces of a typical and
common type of logging application, one where kernel logging is kicked off
when a user space data collection app starts and stops when the collection
app exits, with the data being automatically logged to disk in between. To
create this type of application, you basically just include a header file
(relay-app.h, included in the relay-apps tarball) in your kernel module,
define a couple of callbacks and call an initialization function, and on
the user side call a single function that sets up and continuously monitors
the buffers, and writes data to files as it becomes available. Channels
are created when the collection app is started and destroyed when it exits,
not when the kernel module is inserted, so different channel buffer sizes
can be specified for each separate run via command-line options. See the
README in the relay-apps tarball for details.
Also included in the relay-apps tarball are a couple examples
demonstrating how you can use this to create quick and dirty kernel
logging/debugging applications. They are:
- tprintk, short for 'tee printk', which temporarily puts a kprobe on
printk() and writes a duplicate stream of printk output to a relayfs
channel. This could be used anywhere there's printk() debugging code
in the kernel which you'd like to exercise, but would rather not have
your system logs cluttered with debugging junk. You'd probably want
to kill klogd while you do this, otherwise there wouldn't be much
point (since putting a kprobe on printk() doesn't change the output
of printk()). I've used this method to temporarily divert the packet
logging output of the iptables LOG target from the system logs to
relayfs files instead, for instance.
- klog, which just provides a printk-like formatted logging function
on top of relayfs. Again, you can use this to keep stuff out of your
system logs if used in place of printk.
The example applications can be found here:
http://prdownloads.sourceforge.net/dprobes/relay-apps.tar.gz?download
From: Christoph Hellwig <hch@lst.de>
avoid lookup_hash usage in relayfs
Signed-off-by: Tom Zanussi <zanussi@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-07 06:16:30 +08:00
|
|
|
/*
|
|
|
|
* RelayFS buffer management code.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
|
|
|
|
* Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
|
|
|
|
*
|
|
|
|
* This file is released under the GPL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/vmalloc.h>
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/relayfs_fs.h>
|
|
|
|
#include "relay.h"
|
|
|
|
#include "buffers.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* close() vm_op implementation for relayfs file mapping.
|
|
|
|
*/
|
|
|
|
static void relay_file_mmap_close(struct vm_area_struct *vma)
|
|
|
|
{
|
|
|
|
struct rchan_buf *buf = vma->vm_private_data;
|
|
|
|
buf->chan->cb->buf_unmapped(buf, vma->vm_file);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* nopage() vm_op implementation for relayfs file mapping.
|
|
|
|
*/
|
|
|
|
static struct page *relay_buf_nopage(struct vm_area_struct *vma,
|
|
|
|
unsigned long address,
|
|
|
|
int *type)
|
|
|
|
{
|
|
|
|
struct page *page;
|
|
|
|
struct rchan_buf *buf = vma->vm_private_data;
|
|
|
|
unsigned long offset = address - vma->vm_start;
|
|
|
|
|
|
|
|
if (address > vma->vm_end)
|
|
|
|
return NOPAGE_SIGBUS; /* Disallow mremap */
|
|
|
|
if (!buf)
|
|
|
|
return NOPAGE_OOM;
|
|
|
|
|
|
|
|
page = vmalloc_to_page(buf->start + offset);
|
|
|
|
if (!page)
|
|
|
|
return NOPAGE_OOM;
|
|
|
|
get_page(page);
|
|
|
|
|
|
|
|
if (type)
|
|
|
|
*type = VM_FAULT_MINOR;
|
|
|
|
|
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* vm_ops for relay file mappings.
|
|
|
|
*/
|
|
|
|
static struct vm_operations_struct relay_file_mmap_ops = {
|
|
|
|
.nopage = relay_buf_nopage,
|
|
|
|
.close = relay_file_mmap_close,
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* relay_mmap_buf: - mmap channel buffer to process address space
|
|
|
|
* @buf: relay channel buffer
|
|
|
|
* @vma: vm_area_struct describing memory to be mapped
|
|
|
|
*
|
|
|
|
* Returns 0 if ok, negative on error
|
|
|
|
*
|
|
|
|
* Caller should already have grabbed mmap_sem.
|
|
|
|
*/
|
|
|
|
int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
|
|
|
|
{
|
|
|
|
unsigned long length = vma->vm_end - vma->vm_start;
|
|
|
|
struct file *filp = vma->vm_file;
|
|
|
|
|
|
|
|
if (!buf)
|
|
|
|
return -EBADF;
|
|
|
|
|
|
|
|
if (length != (unsigned long)buf->chan->alloc_size)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
vma->vm_ops = &relay_file_mmap_ops;
|
|
|
|
vma->vm_private_data = buf;
|
|
|
|
buf->chan->cb->buf_mapped(buf, filp);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* relay_alloc_buf - allocate a channel buffer
|
|
|
|
* @buf: the buffer struct
|
|
|
|
* @size: total size of the buffer
|
|
|
|
*
|
|
|
|
* Returns a pointer to the resulting buffer, NULL if unsuccessful
|
|
|
|
*/
|
|
|
|
static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size)
|
|
|
|
{
|
|
|
|
void *mem;
|
|
|
|
unsigned int i, j, n_pages;
|
|
|
|
|
|
|
|
size = PAGE_ALIGN(size);
|
|
|
|
n_pages = size >> PAGE_SHIFT;
|
|
|
|
|
|
|
|
buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL);
|
|
|
|
if (!buf->page_array)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < n_pages; i++) {
|
|
|
|
buf->page_array[i] = alloc_page(GFP_KERNEL);
|
|
|
|
if (unlikely(!buf->page_array[i]))
|
|
|
|
goto depopulate;
|
|
|
|
}
|
2005-10-09 23:41:32 +08:00
|
|
|
mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL);
|
[PATCH] relayfs
Here's the latest version of relayfs, against linux-2.6.11-mm2. I'm hoping
you'll consider putting this version back into your tree - the previous
rounds of comment seem to have shaken out all the API issues and the number
of comments on the code itself have also steadily dwindled.
This patch is essentially the same as the relayfs redux part 5 patch, with
some minor changes based on reviewer comments. Thanks again to Pekka
Enberg for those. The patch size without documentation is now a little
smaller at just over 40k. Here's a detailed list of the changes:
- removed the attribute_flags in relay open and changed it to a
boolean specifying either overwrite or no-overwrite mode, and removed
everything referencing the attribute flags.
- added a check for NULL names in relayfs_create_entry()
- got rid of the unnecessary multiple labels in relay_create_buf()
- some minor simplification of relay_alloc_buf() which got rid of a
couple params
- updated the Documentation
In addition, this version (through code contained in the relay-apps tarball
linked to below, not as part of the relayfs patch) tries to make it as easy
as possible to create the cooperating kernel/user pieces of a typical and
common type of logging application, one where kernel logging is kicked off
when a user space data collection app starts and stops when the collection
app exits, with the data being automatically logged to disk in between. To
create this type of application, you basically just include a header file
(relay-app.h, included in the relay-apps tarball) in your kernel module,
define a couple of callbacks and call an initialization function, and on
the user side call a single function that sets up and continuously monitors
the buffers, and writes data to files as it becomes available. Channels
are created when the collection app is started and destroyed when it exits,
not when the kernel module is inserted, so different channel buffer sizes
can be specified for each separate run via command-line options. See the
README in the relay-apps tarball for details.
Also included in the relay-apps tarball are a couple examples
demonstrating how you can use this to create quick and dirty kernel
logging/debugging applications. They are:
- tprintk, short for 'tee printk', which temporarily puts a kprobe on
printk() and writes a duplicate stream of printk output to a relayfs
channel. This could be used anywhere there's printk() debugging code
in the kernel which you'd like to exercise, but would rather not have
your system logs cluttered with debugging junk. You'd probably want
to kill klogd while you do this, otherwise there wouldn't be much
point (since putting a kprobe on printk() doesn't change the output
of printk()). I've used this method to temporarily divert the packet
logging output of the iptables LOG target from the system logs to
relayfs files instead, for instance.
- klog, which just provides a printk-like formatted logging function
on top of relayfs. Again, you can use this to keep stuff out of your
system logs if used in place of printk.
The example applications can be found here:
http://prdownloads.sourceforge.net/dprobes/relay-apps.tar.gz?download
From: Christoph Hellwig <hch@lst.de>
avoid lookup_hash usage in relayfs
Signed-off-by: Tom Zanussi <zanussi@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-07 06:16:30 +08:00
|
|
|
if (!mem)
|
|
|
|
goto depopulate;
|
|
|
|
|
|
|
|
memset(mem, 0, size);
|
|
|
|
buf->page_count = n_pages;
|
|
|
|
return mem;
|
|
|
|
|
|
|
|
depopulate:
|
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
__free_page(buf->page_array[j]);
|
|
|
|
kfree(buf->page_array);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* relay_create_buf - allocate and initialize a channel buffer
|
|
|
|
* @alloc_size: size of the buffer to allocate
|
|
|
|
* @n_subbufs: number of sub-buffers in the channel
|
|
|
|
*
|
|
|
|
* Returns channel buffer if successful, NULL otherwise
|
|
|
|
*/
|
|
|
|
struct rchan_buf *relay_create_buf(struct rchan *chan)
|
|
|
|
{
|
|
|
|
struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL);
|
|
|
|
if (!buf)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);
|
|
|
|
if (!buf->padding)
|
|
|
|
goto free_buf;
|
|
|
|
|
|
|
|
buf->start = relay_alloc_buf(buf, chan->alloc_size);
|
|
|
|
if (!buf->start)
|
|
|
|
goto free_buf;
|
|
|
|
|
|
|
|
buf->chan = chan;
|
|
|
|
kref_get(&buf->chan->kref);
|
|
|
|
return buf;
|
|
|
|
|
|
|
|
free_buf:
|
|
|
|
kfree(buf->padding);
|
|
|
|
kfree(buf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* relay_destroy_buf - destroy an rchan_buf struct and associated buffer
|
|
|
|
* @buf: the buffer struct
|
|
|
|
*/
|
|
|
|
void relay_destroy_buf(struct rchan_buf *buf)
|
|
|
|
{
|
|
|
|
struct rchan *chan = buf->chan;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (likely(buf->start)) {
|
|
|
|
vunmap(buf->start);
|
|
|
|
for (i = 0; i < buf->page_count; i++)
|
|
|
|
__free_page(buf->page_array[i]);
|
|
|
|
kfree(buf->page_array);
|
|
|
|
}
|
|
|
|
kfree(buf->padding);
|
|
|
|
kfree(buf);
|
|
|
|
kref_put(&chan->kref, relay_destroy_channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* relay_remove_buf - remove a channel buffer
|
|
|
|
*
|
|
|
|
* Removes the file from the relayfs fileystem, which also frees the
|
|
|
|
* rchan_buf_struct and the channel buffer. Should only be called from
|
|
|
|
* kref_put().
|
|
|
|
*/
|
|
|
|
void relay_remove_buf(struct kref *kref)
|
|
|
|
{
|
|
|
|
struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
|
2006-01-08 17:02:28 +08:00
|
|
|
buf->chan->cb->remove_buf_file(buf->dentry);
|
[PATCH] relayfs: decouple buffer creation from inode creation
The patch series implementa or fixes 3 things that were specifically requested
or suggested by relayfs users:
- support for non-relay files (patches 1-6)
Currently, the relayfs API only supports the creation of directories
(relayfs_create_dir()) and relay files (relay_open()). These patches adds
support for non-relay files (relayfs_create_file()). This is so relayfs
applications can create 'control files' in relayfs itself rather than in /proc
or via a netlink channel, as is currently done in the relay-app examples.
Basically what this amounts to is exporting relayfs_create_file() with an
additional file_ops param that clients can use to supply file operations for
their own special-purpose files in relayfs.
- make exported relay file ops useful (patches 7-8)
The relayfs relay_file_operations have always been exported, the intent being
to make it possible to create relay files in other filesystems such as
debugfs. The problem, though, is that currently the file operations are too
tightly coupled to relayfs to actually be used for this purpose. This patch
fixes that by adding a couple of callback functions that allow a client to
hook into relay_open()/close() and supply the files that will be used to
represent the channel buffers; the default implementation if no callbacks are
defined is to create the files in relayfs.
- add an option to create global relay buffer (patches 9-10) The file creation
callback also supplies an optional param, is_global, that can be used by
clients to create a single global relayfs buffer instead of the default
per-cpu buffers. This was suggested as being useful for certain debugging
applications where it's more convenient to be able to get all the data from a
single channel without having to go to the bother of dealing with per-cpu
files.
- cleanup, some renaming and Documentation updates (patches 11-12)
There were several comments that the use of netlink in the example code was
non-intuitive and in fact the whole relay-app business was needlessly
confusing. Based on that feedback, the example code has been completely
converted over to relayfs control files as supported by this patch, and have
also been made completely self-contained.
The converted examples along with a couple of new examples that demonstrate
using exported relay files can be found in relay-apps tarball:
http://prdownloads.sourceforge.net/relayfs/relay-apps-0.9.tar.gz?download
This patch:
Separate buffer create/destroy from inode create/destroy. We want to be able
to associate other data and not just relay buffers with inodes. Buffer
create/destroy is moved out of inode.c and into relayfs core code.
Signed-off-by: Tom Zanussi <zanussi@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-08 17:02:23 +08:00
|
|
|
relay_destroy_buf(buf);
|
[PATCH] relayfs
Here's the latest version of relayfs, against linux-2.6.11-mm2. I'm hoping
you'll consider putting this version back into your tree - the previous
rounds of comment seem to have shaken out all the API issues and the number
of comments on the code itself have also steadily dwindled.
This patch is essentially the same as the relayfs redux part 5 patch, with
some minor changes based on reviewer comments. Thanks again to Pekka
Enberg for those. The patch size without documentation is now a little
smaller at just over 40k. Here's a detailed list of the changes:
- removed the attribute_flags in relay open and changed it to a
boolean specifying either overwrite or no-overwrite mode, and removed
everything referencing the attribute flags.
- added a check for NULL names in relayfs_create_entry()
- got rid of the unnecessary multiple labels in relay_create_buf()
- some minor simplification of relay_alloc_buf() which got rid of a
couple params
- updated the Documentation
In addition, this version (through code contained in the relay-apps tarball
linked to below, not as part of the relayfs patch) tries to make it as easy
as possible to create the cooperating kernel/user pieces of a typical and
common type of logging application, one where kernel logging is kicked off
when a user space data collection app starts and stops when the collection
app exits, with the data being automatically logged to disk in between. To
create this type of application, you basically just include a header file
(relay-app.h, included in the relay-apps tarball) in your kernel module,
define a couple of callbacks and call an initialization function, and on
the user side call a single function that sets up and continuously monitors
the buffers, and writes data to files as it becomes available. Channels
are created when the collection app is started and destroyed when it exits,
not when the kernel module is inserted, so different channel buffer sizes
can be specified for each separate run via command-line options. See the
README in the relay-apps tarball for details.
Also included in the relay-apps tarball are a couple examples
demonstrating how you can use this to create quick and dirty kernel
logging/debugging applications. They are:
- tprintk, short for 'tee printk', which temporarily puts a kprobe on
printk() and writes a duplicate stream of printk output to a relayfs
channel. This could be used anywhere there's printk() debugging code
in the kernel which you'd like to exercise, but would rather not have
your system logs cluttered with debugging junk. You'd probably want
to kill klogd while you do this, otherwise there wouldn't be much
point (since putting a kprobe on printk() doesn't change the output
of printk()). I've used this method to temporarily divert the packet
logging output of the iptables LOG target from the system logs to
relayfs files instead, for instance.
- klog, which just provides a printk-like formatted logging function
on top of relayfs. Again, you can use this to keep stuff out of your
system logs if used in place of printk.
The example applications can be found here:
http://prdownloads.sourceforge.net/dprobes/relay-apps.tar.gz?download
From: Christoph Hellwig <hch@lst.de>
avoid lookup_hash usage in relayfs
Signed-off-by: Tom Zanussi <zanussi@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-07 06:16:30 +08:00
|
|
|
}
|