2005-11-11 16:44:59

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 0/12] relayfs: API additions and fixes

Hi,

This patch set is essentially the same as the set I previously posted,
but broken out into stepwise chunks.

The patches implement or fix 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

Tom



2005-11-11 16:46:49

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 1/12] relayfs: decouple buffer creation from inode creation

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 <[email protected]>

---

buffers.c | 1 +
inode.c | 31 +++++++++----------------------
relay.c | 11 ++++++++---
relay.h | 2 +-
4 files changed, 19 insertions(+), 26 deletions(-)

diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c
--- a/fs/relayfs/buffers.c
+++ b/fs/relayfs/buffers.c
@@ -186,4 +186,5 @@ void relay_remove_buf(struct kref *kref)
{
struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
relayfs_remove(buf->dentry);
+ relay_destroy_buf(buf);
}
diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
--- a/fs/relayfs/inode.c
+++ b/fs/relayfs/inode.c
@@ -34,23 +34,13 @@ static struct backing_dev_info relayfs_
};

static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
- struct rchan *chan)
+ void *data)
{
- struct rchan_buf *buf = NULL;
struct inode *inode;

- if (S_ISREG(mode)) {
- BUG_ON(!chan);
- buf = relay_create_buf(chan);
- if (!buf)
- return NULL;
- }
-
inode = new_inode(sb);
- if (!inode) {
- relay_destroy_buf(buf);
+ if (!inode)
return NULL;
- }

inode->i_mode = mode;
inode->i_uid = 0;
@@ -62,7 +52,7 @@ static struct inode *relayfs_get_inode(s
switch (mode & S_IFMT) {
case S_IFREG:
inode->i_fop = &relayfs_file_operations;
- RELAYFS_I(inode)->buf = buf;
+ RELAYFS_I(inode)->buf = data;
break;
case S_IFDIR:
inode->i_op = &simple_dir_inode_operations;
@@ -83,7 +73,7 @@ static struct inode *relayfs_get_inode(s
* @name: the name of the file to create
* @parent: parent directory
* @mode: mode
- * @chan: relay channel associated with the file
+ * @data: user-associated data for this file
*
* Returns the new dentry, NULL on failure
*
@@ -92,7 +82,7 @@ static struct inode *relayfs_get_inode(s
static struct dentry *relayfs_create_entry(const char *name,
struct dentry *parent,
int mode,
- struct rchan *chan)
+ void *data)
{
struct dentry *d;
struct inode *inode;
@@ -127,7 +117,7 @@ static struct dentry *relayfs_create_ent
goto release_mount;
}

- inode = relayfs_get_inode(parent->d_inode->i_sb, mode, chan);
+ inode = relayfs_get_inode(parent->d_inode->i_sb, mode, data);
if (!inode) {
d = NULL;
goto release_mount;
@@ -155,20 +145,20 @@ exit:
* @name: the name of the file to create
* @parent: parent directory
* @mode: mode, if not specied the default perms are used
- * @chan: channel associated with the file
+ * @data: user-associated data for this file
*
* Returns file dentry if successful, NULL otherwise.
*
* The file will be created user r on behalf of current user.
*/
struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
- int mode, struct rchan *chan)
+ int mode, void *data)
{
if (!mode)
mode = S_IRUSR;
mode = (mode & S_IALLUGO) | S_IFREG;

- return relayfs_create_entry(name, parent, mode, chan);
+ return relayfs_create_entry(name, parent, mode, data);
}

/**
@@ -505,9 +495,6 @@ static struct inode *relayfs_alloc_inode
*/
static void relayfs_destroy_inode(struct inode *inode)
{
- if (RELAYFS_I(inode)->buf)
- relay_destroy_buf(RELAYFS_I(inode)->buf);
-
kmem_cache_free(relayfs_inode_cachep, RELAYFS_I(inode));
}

diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
--- a/fs/relayfs/relay.c
+++ b/fs/relayfs/relay.c
@@ -171,12 +171,17 @@ static struct rchan_buf *relay_open_buf(
struct rchan_buf *buf;
struct dentry *dentry;

+ buf = relay_create_buf(chan);
+ if (!buf)
+ return NULL;
+
/* Create file in fs */
- dentry = relayfs_create_file(filename, parent, S_IRUSR, chan);
- if (!dentry)
+ dentry = relayfs_create_file(filename, parent, S_IRUSR, buf);
+ if (!dentry) {
+ relay_destroy_buf(buf);
return NULL;
+ }

- buf = RELAYFS_I(dentry->d_inode)->buf;
buf->dentry = dentry;
__relay_reset(buf, 1);

diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h
--- a/fs/relayfs/relay.h
+++ b/fs/relayfs/relay.h
@@ -4,7 +4,7 @@
struct dentry *relayfs_create_file(const char *name,
struct dentry *parent,
int mode,
- struct rchan *chan);
+ void *data);
extern int relayfs_remove(struct dentry *dentry);
extern int relay_buf_empty(struct rchan_buf *buf);
extern void relay_destroy_channel(struct kref *kref);


2005-11-11 16:47:40

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 2/12] relayfs: export relayfs_create_file() with fileops param

This patch adds a mandatory fileops param to relayfs_create_file() and
exports that function so that clients can use it to create files
defined by their own set of file operations, in relayfs. The purpose
is to allow relayfs applications to create their own set of 'control'
files alongside their relay files in relayfs rather than having to
create them in /proc or debugfs for instance. relayfs_create_file()
is also used by relay_open_buf() to create the relay files for a
channel. In this case, a pointer to relayfs_file_operations is passed
in, along with a pointer to the buffer associated with the file.

Signed-off-by: Tom Zanussi <[email protected]>

---

fs/relayfs/inode.c | 41 ++++++++++++++++++++++++++---------------
fs/relayfs/relay.c | 3 ++-
fs/relayfs/relay.h | 4 ----
include/linux/relayfs_fs.h | 7 ++++++-
4 files changed, 34 insertions(+), 21 deletions(-)

diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
--- a/fs/relayfs/inode.c
+++ b/fs/relayfs/inode.c
@@ -33,7 +33,9 @@ static struct backing_dev_info relayfs_
.capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};

-static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
+static struct inode *relayfs_get_inode(struct super_block *sb,
+ int mode,
+ struct file_operations *fops,
void *data)
{
struct inode *inode;
@@ -51,8 +53,8 @@ static struct inode *relayfs_get_inode(s
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
switch (mode & S_IFMT) {
case S_IFREG:
- inode->i_fop = &relayfs_file_operations;
- RELAYFS_I(inode)->buf = data;
+ inode->i_fop = fops;
+ RELAYFS_I(inode)->data = data;
break;
case S_IFDIR:
inode->i_op = &simple_dir_inode_operations;
@@ -73,6 +75,7 @@ static struct inode *relayfs_get_inode(s
* @name: the name of the file to create
* @parent: parent directory
* @mode: mode
+ * @fops: file operations to use for the file
* @data: user-associated data for this file
*
* Returns the new dentry, NULL on failure
@@ -82,6 +85,7 @@ static struct inode *relayfs_get_inode(s
static struct dentry *relayfs_create_entry(const char *name,
struct dentry *parent,
int mode,
+ struct file_operations *fops,
void *data)
{
struct dentry *d;
@@ -117,7 +121,7 @@ static struct dentry *relayfs_create_ent
goto release_mount;
}

- inode = relayfs_get_inode(parent->d_inode->i_sb, mode, data);
+ inode = relayfs_get_inode(parent->d_inode->i_sb, mode, fops, data);
if (!inode) {
d = NULL;
goto release_mount;
@@ -145,20 +149,26 @@ exit:
* @name: the name of the file to create
* @parent: parent directory
* @mode: mode, if not specied the default perms are used
+ * @fops: file operations to use for the file
* @data: user-associated data for this file
*
* Returns file dentry if successful, NULL otherwise.
*
* The file will be created user r on behalf of current user.
*/
-struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
- int mode, void *data)
+struct dentry *relayfs_create_file(const char *name,
+ struct dentry *parent,
+ int mode,
+ struct file_operations *fops,
+ void *data)
{
+ BUG_ON(!fops);
+
if (!mode)
mode = S_IRUSR;
mode = (mode & S_IALLUGO) | S_IFREG;

- return relayfs_create_entry(name, parent, mode, data);
+ return relayfs_create_entry(name, parent, mode, fops, data);
}

/**
@@ -173,7 +183,7 @@ struct dentry *relayfs_create_file(const
struct dentry *relayfs_create_dir(const char *name, struct dentry *parent)
{
int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
- return relayfs_create_entry(name, parent, mode, NULL);
+ return relayfs_create_entry(name, parent, mode, NULL, NULL);
}

/**
@@ -234,7 +244,7 @@ int relayfs_remove_dir(struct dentry *de
*/
static int relayfs_open(struct inode *inode, struct file *filp)
{
- struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+ struct rchan_buf *buf = RELAYFS_I(inode)->data;
kref_get(&buf->kref);

return 0;
@@ -250,7 +260,7 @@ static int relayfs_open(struct inode *in
static int relayfs_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct inode *inode = filp->f_dentry->d_inode;
- return relay_mmap_buf(RELAYFS_I(inode)->buf, vma);
+ return relay_mmap_buf(RELAYFS_I(inode)->data, vma);
}

/**
@@ -264,7 +274,7 @@ static unsigned int relayfs_poll(struct
{
unsigned int mask = 0;
struct inode *inode = filp->f_dentry->d_inode;
- struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+ struct rchan_buf *buf = RELAYFS_I(inode)->data;

if (buf->finalized)
return POLLERR;
@@ -288,7 +298,7 @@ static unsigned int relayfs_poll(struct
*/
static int relayfs_release(struct inode *inode, struct file *filp)
{
- struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+ struct rchan_buf *buf = RELAYFS_I(inode)->data;
kref_put(&buf->kref, relay_remove_buf);

return 0;
@@ -450,7 +460,7 @@ static ssize_t relayfs_read(struct file
loff_t *ppos)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+ struct rchan_buf *buf = RELAYFS_I(inode)->data;
size_t read_start, avail;
ssize_t ret = 0;
void *from;
@@ -485,7 +495,7 @@ static struct inode *relayfs_alloc_inode
struct relayfs_inode_info *p = kmem_cache_alloc(relayfs_inode_cachep, SLAB_KERNEL);
if (!p)
return NULL;
- p->buf = NULL;
+ p->data = NULL;

return &p->vfs_inode;
}
@@ -531,7 +541,7 @@ static int relayfs_fill_super(struct sup
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = RELAYFS_MAGIC;
sb->s_op = &relayfs_ops;
- inode = relayfs_get_inode(sb, mode, NULL);
+ inode = relayfs_get_inode(sb, mode, NULL, NULL);

if (!inode)
return -ENOMEM;
@@ -589,6 +599,7 @@ module_exit(exit_relayfs_fs)
EXPORT_SYMBOL_GPL(relayfs_file_operations);
EXPORT_SYMBOL_GPL(relayfs_create_dir);
EXPORT_SYMBOL_GPL(relayfs_remove_dir);
+EXPORT_SYMBOL_GPL(relayfs_create_file);

MODULE_AUTHOR("Tom Zanussi <[email protected]> and Karim Yaghmour <[email protected]>");
MODULE_DESCRIPTION("Relay Filesystem");
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
--- a/fs/relayfs/relay.c
+++ b/fs/relayfs/relay.c
@@ -176,7 +176,8 @@ static struct rchan_buf *relay_open_buf(
return NULL;

/* Create file in fs */
- dentry = relayfs_create_file(filename, parent, S_IRUSR, buf);
+ dentry = relayfs_create_file(filename, parent, S_IRUSR,
+ &relayfs_file_operations, buf);
if (!dentry) {
relay_destroy_buf(buf);
return NULL;
diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h
--- a/fs/relayfs/relay.h
+++ b/fs/relayfs/relay.h
@@ -1,10 +1,6 @@
#ifndef _RELAY_H
#define _RELAY_H

-struct dentry *relayfs_create_file(const char *name,
- struct dentry *parent,
- int mode,
- void *data);
extern int relayfs_remove(struct dentry *dentry);
extern int relay_buf_empty(struct rchan_buf *buf);
extern void relay_destroy_channel(struct kref *kref);
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
--- a/include/linux/relayfs_fs.h
+++ b/include/linux/relayfs_fs.h
@@ -69,7 +69,7 @@ struct rchan
struct relayfs_inode_info
{
struct inode vfs_inode;
- struct rchan_buf *buf;
+ void *data;
};

static inline struct relayfs_inode_info *RELAYFS_I(struct inode *inode)
@@ -147,6 +147,11 @@ extern size_t relay_switch_subbuf(struct
extern struct dentry *relayfs_create_dir(const char *name,
struct dentry *parent);
extern int relayfs_remove_dir(struct dentry *dentry);
+extern struct dentry *relayfs_create_file(const char *name,
+ struct dentry *parent,
+ int mode,
+ struct file_operations *fops,
+ void *data);

/**
* relay_write - write data into the channel


2005-11-11 16:48:34

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 3/12] relayfs: add relayfs_remove_file()

This patch adds and exports relayfs_remove_file(), for API symmetry
(with relayfs_create_file()).

Signed-off-by: Tom Zanussi <[email protected]>

---

fs/relayfs/inode.c | 12 ++++++++++++
include/linux/relayfs_fs.h | 1 +
2 files changed, 13 insertions(+)

diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
--- a/fs/relayfs/inode.c
+++ b/fs/relayfs/inode.c
@@ -225,6 +225,17 @@ int relayfs_remove(struct dentry *dentry
}

/**
+ * relayfs_remove_file - remove a file from relay filesystem
+ * @dentry: directory dentry
+ *
+ * Returns 0 if successful, negative otherwise.
+ */
+int relayfs_remove_file(struct dentry *dentry)
+{
+ return relayfs_remove(dentry);
+}
+
+/**
* relayfs_remove_dir - remove a directory in the relay filesystem
* @dentry: directory dentry
*
@@ -600,6 +611,7 @@ EXPORT_SYMBOL_GPL(relayfs_file_operation
EXPORT_SYMBOL_GPL(relayfs_create_dir);
EXPORT_SYMBOL_GPL(relayfs_remove_dir);
EXPORT_SYMBOL_GPL(relayfs_create_file);
+EXPORT_SYMBOL_GPL(relayfs_remove_file);

MODULE_AUTHOR("Tom Zanussi <[email protected]> and Karim Yaghmour <[email protected]>");
MODULE_DESCRIPTION("Relay Filesystem");
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
--- a/include/linux/relayfs_fs.h
+++ b/include/linux/relayfs_fs.h
@@ -152,6 +152,7 @@ extern struct dentry *relayfs_create_fil
int mode,
struct file_operations *fops,
void *data);
+extern int relayfs_remove_file(struct dentry *dentry);

/**
* relay_write - write data into the channel


2005-11-11 16:49:29

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 4/12] relayfs: use generic_ip for private data

Use inode->u.generic_ip instead of relayfs_inode_info to store pointer
to user data. Clients using relayfs_file_create() to create their own
files would probably more expect their data to be stored in
generic_ip; we also intend in the next set of patches to get rid of
relayfs-specific stuff in the file operations, so we might as well do
it here.

Signed-off-by: Tom Zanussi <[email protected]>

---

inode.c | 17 +++++++++--------
1 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
--- a/fs/relayfs/inode.c
+++ b/fs/relayfs/inode.c
@@ -54,7 +54,8 @@ static struct inode *relayfs_get_inode(s
switch (mode & S_IFMT) {
case S_IFREG:
inode->i_fop = fops;
- RELAYFS_I(inode)->data = data;
+ if (data)
+ inode->u.generic_ip = data;
break;
case S_IFDIR:
inode->i_op = &simple_dir_inode_operations;
@@ -255,8 +256,9 @@ int relayfs_remove_dir(struct dentry *de
*/
static int relayfs_open(struct inode *inode, struct file *filp)
{
- struct rchan_buf *buf = RELAYFS_I(inode)->data;
+ struct rchan_buf *buf = inode->u.generic_ip;
kref_get(&buf->kref);
+ filp->private_data = buf;

return 0;
}
@@ -270,8 +272,8 @@ static int relayfs_open(struct inode *in
*/
static int relayfs_mmap(struct file *filp, struct vm_area_struct *vma)
{
- struct inode *inode = filp->f_dentry->d_inode;
- return relay_mmap_buf(RELAYFS_I(inode)->data, vma);
+ struct rchan_buf *buf = filp->private_data;
+ return relay_mmap_buf(buf, vma);
}

/**
@@ -284,8 +286,7 @@ static int relayfs_mmap(struct file *fil
static unsigned int relayfs_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
- struct inode *inode = filp->f_dentry->d_inode;
- struct rchan_buf *buf = RELAYFS_I(inode)->data;
+ struct rchan_buf *buf = filp->private_data;

if (buf->finalized)
return POLLERR;
@@ -309,7 +310,7 @@ static unsigned int relayfs_poll(struct
*/
static int relayfs_release(struct inode *inode, struct file *filp)
{
- struct rchan_buf *buf = RELAYFS_I(inode)->data;
+ struct rchan_buf *buf = filp->private_data;
kref_put(&buf->kref, relay_remove_buf);

return 0;
@@ -470,8 +471,8 @@ static ssize_t relayfs_read(struct file
size_t count,
loff_t *ppos)
{
+ struct rchan_buf *buf = filp->private_data;
struct inode *inode = filp->f_dentry->d_inode;
- struct rchan_buf *buf = RELAYFS_I(inode)->data;
size_t read_start, avail;
ssize_t ret = 0;
void *from;


2005-11-11 16:50:16

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 5/12] relayfs: remove unused alloc/destroy_inode()

Since we're no longer using relayfs_inode_info, remove
relayfs_alloc_inode() and relayfs_destroy_inode() along with the
relayfs inode cache.

Signed-off-by: Tom Zanussi <[email protected]>

---

fs/relayfs/inode.c | 46 ---------------------------------------------
include/linux/relayfs_fs.h | 14 -------------
2 files changed, 1 insertion(+), 59 deletions(-)

diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
--- a/fs/relayfs/inode.c
+++ b/fs/relayfs/inode.c
@@ -26,7 +26,6 @@

static struct vfsmount * relayfs_mount;
static int relayfs_mount_count;
-static kmem_cache_t * relayfs_inode_cachep;

static struct backing_dev_info relayfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
@@ -499,34 +498,6 @@ out:
return ret;
}

-/**
- * relayfs alloc_inode() implementation
- */
-static struct inode *relayfs_alloc_inode(struct super_block *sb)
-{
- struct relayfs_inode_info *p = kmem_cache_alloc(relayfs_inode_cachep, SLAB_KERNEL);
- if (!p)
- return NULL;
- p->data = NULL;
-
- return &p->vfs_inode;
-}
-
-/**
- * relayfs destroy_inode() implementation
- */
-static void relayfs_destroy_inode(struct inode *inode)
-{
- kmem_cache_free(relayfs_inode_cachep, RELAYFS_I(inode));
-}
-
-static void init_once(void *p, kmem_cache_t *cachep, unsigned long flags)
-{
- struct relayfs_inode_info *i = p;
- if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR)
- inode_init_once(&i->vfs_inode);
-}
-
struct file_operations relayfs_file_operations = {
.open = relayfs_open,
.poll = relayfs_poll,
@@ -539,8 +510,6 @@ struct file_operations relayfs_file_oper
static struct super_operations relayfs_ops = {
.statfs = simple_statfs,
.drop_inode = generic_delete_inode,
- .alloc_inode = relayfs_alloc_inode,
- .destroy_inode = relayfs_destroy_inode,
};

static int relayfs_fill_super(struct super_block * sb, void * data, int silent)
@@ -584,25 +553,12 @@ static struct file_system_type relayfs_f

static int __init init_relayfs_fs(void)
{
- int err;
-
- relayfs_inode_cachep = kmem_cache_create("relayfs_inode_cache",
- sizeof(struct relayfs_inode_info), 0,
- 0, init_once, NULL);
- if (!relayfs_inode_cachep)
- return -ENOMEM;
-
- err = register_filesystem(&relayfs_fs_type);
- if (err)
- kmem_cache_destroy(relayfs_inode_cachep);
-
- return err;
+ return register_filesystem(&relayfs_fs_type);
}

static void __exit exit_relayfs_fs(void)
{
unregister_filesystem(&relayfs_fs_type);
- kmem_cache_destroy(relayfs_inode_cachep);
}

module_init(init_relayfs_fs)
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
--- a/include/linux/relayfs_fs.h
+++ b/include/linux/relayfs_fs.h
@@ -64,20 +64,6 @@ struct rchan
};

/*
- * Relayfs inode
- */
-struct relayfs_inode_info
-{
- struct inode vfs_inode;
- void *data;
-};
-
-static inline struct relayfs_inode_info *RELAYFS_I(struct inode *inode)
-{
- return container_of(inode, struct relayfs_inode_info, vfs_inode);
-}
-
-/*
* Relay channel client callbacks
*/
struct rchan_callbacks


2005-11-11 16:50:53

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 6/12] relayfs: add Documention for non-relay files

Documentation update for non-relay files.

Signed-off-by: Tom Zanussi <[email protected]>

---

relayfs.txt | 23 +++++++++++++++++++++++
1 files changed, 23 insertions(+)

diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt
--- a/Documentation/filesystems/relayfs.txt
+++ b/Documentation/filesystems/relayfs.txt
@@ -125,6 +125,8 @@ Here's a summary of the API relayfs prov
relay_reset(chan)
relayfs_create_dir(name, parent)
relayfs_remove_dir(dentry)
+ relayfs_create_file(name, parent, mode, fops, data)
+ relayfs_remove_file(dentry)

channel management typically called on instigation of userspace:

@@ -320,6 +322,27 @@ forces a sub-buffer switch on all the ch
to finalize and process the last sub-buffers before the channel is
closed.

+Creating non-relay files
+------------------------
+
+relay_open() automatically creates files in the relayfs filesystem to
+represent the per-cpu kernel buffers; it's often useful for
+applications to be able to create their own files alongside the relay
+files in the relayfs filesystem as well e.g. 'control' files much like
+those created in /proc or debugfs for similar purposes, used to
+communicate control information between the kernel and user sides of a
+relayfs application. For this purpose the relayfs_create_file() and
+relayfs_remove_file() API functions exist. For relayfs_create_file(),
+the caller passes in a set of user-defined file operations to be used
+for the file and an optional void * to a user-specified data item,
+which will be accessible via inode->u.generic_ip (see the relay-apps
+tarball for examples). The file_operations are a required parameter
+to relayfs_create_file() and thus the semantics of these files are
+completely defined by the caller.
+
+See the relay-apps tarball at http://relayfs.sourceforge.net for
+examples of how these non-relay files are meant to be used.
+
Misc
----



2005-11-11 16:51:38

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 7/12] relayfs: add support for relay files in other filesystems

This patch adds 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. This is to
support the creation and use of relay files in other filesystems such
as debugfs, as implied by the fact that relayfs_file_operations are
exported.

Signed-off-by: Tom Zanussi <[email protected]>

---

fs/relayfs/buffers.c | 2 +-
fs/relayfs/relay.c | 30 ++++++++++++++++++++++++++++--
include/linux/relayfs_fs.h | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c
--- a/fs/relayfs/buffers.c
+++ b/fs/relayfs/buffers.c
@@ -185,6 +185,6 @@ void relay_destroy_buf(struct rchan_buf
void relay_remove_buf(struct kref *kref)
{
struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
- relayfs_remove(buf->dentry);
+ buf->chan->cb->remove_buf_file(buf->dentry);
relay_destroy_buf(buf);
}
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
--- a/fs/relayfs/relay.c
+++ b/fs/relayfs/relay.c
@@ -80,11 +80,33 @@ static void buf_unmapped_default_callbac
{
}

+/*
+ * create_buf_file_create() default callback. Creates file to represent buf.
+ */
+static struct dentry *create_buf_file_default_callback(const char *filename,
+ struct dentry *parent,
+ int mode,
+ struct rchan_buf *buf)
+{
+ return relayfs_create_file(filename, parent, mode,
+ &relayfs_file_operations, buf);
+}
+
+/*
+ * remove_buf_file() default callback. Removes file representing relay buffer.
+ */
+static int remove_buf_file_default_callback(struct dentry *dentry)
+{
+ return relayfs_remove(dentry);
+}
+
/* relay channel default callbacks */
static struct rchan_callbacks default_channel_callbacks = {
.subbuf_start = subbuf_start_default_callback,
.buf_mapped = buf_mapped_default_callback,
.buf_unmapped = buf_unmapped_default_callback,
+ .create_buf_file = create_buf_file_default_callback,
+ .remove_buf_file = remove_buf_file_default_callback,
};

/**
@@ -176,8 +198,8 @@ static struct rchan_buf *relay_open_buf(
return NULL;

/* Create file in fs */
- dentry = relayfs_create_file(filename, parent, S_IRUSR,
- &relayfs_file_operations, buf);
+ dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR,
+ buf);
if (!dentry) {
relay_destroy_buf(buf);
return NULL;
@@ -220,6 +242,10 @@ static inline void setup_callbacks(struc
cb->buf_mapped = buf_mapped_default_callback;
if (!cb->buf_unmapped)
cb->buf_unmapped = buf_unmapped_default_callback;
+ if (!cb->create_buf_file)
+ cb->create_buf_file = create_buf_file_default_callback;
+ if (!cb->remove_buf_file)
+ cb->remove_buf_file = remove_buf_file_default_callback;
chan->cb = cb;
}

diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
--- a/include/linux/relayfs_fs.h
+++ b/include/linux/relayfs_fs.h
@@ -109,6 +109,40 @@ struct rchan_callbacks
*/
void (*buf_unmapped)(struct rchan_buf *buf,
struct file *filp);
+ /*
+ * create_buf_file - create file to represent a relayfs channel buffer
+ * @filename: the name of the file to create
+ * @parent: the parent of the file to create
+ * @mode: the mode of the file to create
+ * @buf: the channel buffer
+ *
+ * Called during relay_open(), once for each per-cpu buffer,
+ * to allow the client to create a file to be used to
+ * represent the corresponding channel buffer. If the file is
+ * created outside of relayfs, the parent must also exist in
+ * that filesystem.
+ *
+ * The callback should return the dentry of the file created
+ * to represent the relay buffer.
+ *
+ * See Documentation/filesystems/relayfs.txt for more info.
+ */
+ struct dentry *(*create_buf_file)(const char *filename,
+ struct dentry *parent,
+ int mode,
+ struct rchan_buf *buf);
+
+ /*
+ * remove_buf_file - remove file representing a relayfs channel buffer
+ * @dentry: the dentry of the file to remove
+ *
+ * Called during relay_close(), once for each per-cpu buffer,
+ * to allow the client to remove a file used to represent a
+ * channel buffer.
+ *
+ * The callback should return 0 if successful, negative if not.
+ */
+ int (*remove_buf_file)(struct dentry *dentry);
};

/*


2005-11-11 16:52:21

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 8/12] relayfs: add Documentation on relay files in other filesystems

Documentation update for creating relay files in other filesystems.

Signed-off-by: Tom Zanussi <[email protected]>

---

relayfs.txt | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+)

diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt
--- a/Documentation/filesystems/relayfs.txt
+++ b/Documentation/filesystems/relayfs.txt
@@ -143,6 +143,8 @@ Here's a summary of the API relayfs prov
subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
buf_mapped(buf, filp)
buf_unmapped(buf, filp)
+ create_buf_file(filename, parent, mode, buf)
+ remove_buf_file(dentry)

helper functions:

@@ -343,6 +345,31 @@ completely defined by the caller.
See the relay-apps tarball at http://relayfs.sourceforge.net for
examples of how these non-relay files are meant to be used.

+Creating relay files in other filesystems
+-----------------------------------------
+
+By default of course, relay_open() creates relay files in the relayfs
+filesystem. Because relay_file_operations is exported, however, it's
+also possible to create and use relay files in other pseudo-filesytems
+such as debugfs.
+
+For this purpose, two callback functions are provided,
+create_buf_file() and remove_buf_file(). create_buf_file() is called
+once for each per-cpu buffer from relay_open() to allow the client to
+create a file to be used to represent the corresponding buffer; if
+this callback is not defined, the default implementation will create
+and return a file in the relayfs filesystem to represent the buffer.
+The callback should return the dentry of the file created to represent
+the relay buffer. Note that the parent directory passed to
+relay_open() (and passed along to the callback), if specified, must
+exist in the same filesystem the new relay file is created in. If
+create_buf_file() is defined, remove_buf_file() must also be defined;
+it's responsible for deleting the file(s) created in create_buf_file()
+and is called during relay_close().
+
+See the 'exported-relayfile' examples in the relay-apps tarball for
+examples of creating and using relay files in debugfs.
+
Misc
----



2005-11-11 16:53:29

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 10/12] relayfs: add Documentation on global relay buffers

Documentation update for creating global buffers.

Signed-off-by: Tom Zanussi <[email protected]>

---

relayfs.txt | 21 ++++++++++++++++++++-
1 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt
--- a/Documentation/filesystems/relayfs.txt
+++ b/Documentation/filesystems/relayfs.txt
@@ -143,7 +143,7 @@ Here's a summary of the API relayfs prov
subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
buf_mapped(buf, filp)
buf_unmapped(buf, filp)
- create_buf_file(filename, parent, mode, buf)
+ create_buf_file(filename, parent, mode, buf, is_global)
remove_buf_file(dentry)

helper functions:
@@ -367,6 +367,25 @@ create_buf_file() is defined, remove_buf
it's responsible for deleting the file(s) created in create_buf_file()
and is called during relay_close().

+The create_buf_file() implementation can also be defined in such a way
+as to allow the creation of a single 'global' buffer instead of the
+default per-cpu set. This can be useful for applications interested
+mainly in seeing the relative ordering of system-wide events without
+the need to bother with saving explicit timestamps for the purpose of
+merging/sorting per-cpu files in a postprocessing step.
+
+To have relay_open() create a global buffer, the create_buf_file()
+implementation should set the value of the is_global outparam to a
+non-zero value in addition to creating the file that will be used to
+represent the single buffer. In the case of a global buffer,
+create_buf_file() and remove_buf_file() will be called only once. The
+normal channel-writing functions e.g. relay_write() can still be used
+- writes from any cpu will transparently end up in the global buffer -
+but since it is a global buffer, callers should make sure they use the
+proper locking for such a buffer, either by wrapping writes in a
+spinlock, or by copying a write function from relayfs_fs.h and
+creating a local version that internally does the proper locking.
+
See the 'exported-relayfile' examples in the relay-apps tarball for
examples of creating and using relay files in debugfs.



2005-11-11 16:52:53

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 9/12] relayfs: add support for global relay buffers

This patch adds the optional is_global outparam to the
create_buf_file() callback. This 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.

Signed-off-by: Tom Zanussi <[email protected]>

---

fs/relayfs/relay.c | 35 +++++++++++++++++++++++++----------
include/linux/relayfs_fs.h | 8 +++++++-
2 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
--- a/fs/relayfs/relay.c
+++ b/fs/relayfs/relay.c
@@ -86,7 +86,8 @@ static void buf_unmapped_default_callbac
static struct dentry *create_buf_file_default_callback(const char *filename,
struct dentry *parent,
int mode,
- struct rchan_buf *buf)
+ struct rchan_buf *buf,
+ int *is_global)
{
return relayfs_create_file(filename, parent, mode,
&relayfs_file_operations, buf);
@@ -170,14 +171,16 @@ static inline void __relay_reset(struct
void relay_reset(struct rchan *chan)
{
unsigned int i;
+ struct rchan_buf *prev = NULL;

if (!chan)
return;

for (i = 0; i < NR_CPUS; i++) {
- if (!chan->buf[i])
- continue;
+ if (!chan->buf[i] || chan->buf[i] == prev)
+ break;
__relay_reset(chan->buf[i], 0);
+ prev = chan->buf[i];
}
}

@@ -188,18 +191,22 @@ void relay_reset(struct rchan *chan)
*/
static struct rchan_buf *relay_open_buf(struct rchan *chan,
const char *filename,
- struct dentry *parent)
+ struct dentry *parent,
+ int *is_global)
{
struct rchan_buf *buf;
struct dentry *dentry;

+ if (*is_global)
+ return chan->buf[0];
+
buf = relay_create_buf(chan);
if (!buf)
return NULL;

/* Create file in fs */
dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR,
- buf);
+ buf, is_global);
if (!dentry) {
relay_destroy_buf(buf);
return NULL;
@@ -273,6 +280,7 @@ struct rchan *relay_open(const char *bas
unsigned int i;
struct rchan *chan;
char *tmpname;
+ int is_global = 0;

if (!base_filename)
return NULL;
@@ -297,7 +305,8 @@ struct rchan *relay_open(const char *bas

for_each_online_cpu(i) {
sprintf(tmpname, "%s%d", base_filename, i);
- chan->buf[i] = relay_open_buf(chan, tmpname, parent);
+ chan->buf[i] = relay_open_buf(chan, tmpname, parent,
+ &is_global);
chan->buf[i]->cpu = i;
if (!chan->buf[i])
goto free_bufs;
@@ -311,6 +320,8 @@ free_bufs:
if (!chan->buf[i])
break;
relay_close_buf(chan->buf[i]);
+ if (is_global)
+ break;
}
kfree(tmpname);

@@ -421,14 +432,16 @@ void relay_destroy_channel(struct kref *
void relay_close(struct rchan *chan)
{
unsigned int i;
+ struct rchan_buf *prev = NULL;

if (!chan)
return;

for (i = 0; i < NR_CPUS; i++) {
- if (!chan->buf[i])
- continue;
+ if (!chan->buf[i] || chan->buf[i] == prev)
+ break;
relay_close_buf(chan->buf[i]);
+ prev = chan->buf[i];
}

kref_put(&chan->kref, relay_destroy_channel);
@@ -443,14 +456,16 @@ void relay_close(struct rchan *chan)
void relay_flush(struct rchan *chan)
{
unsigned int i;
+ struct rchan_buf *prev = NULL;

if (!chan)
return;

for (i = 0; i < NR_CPUS; i++) {
- if (!chan->buf[i])
- continue;
+ if (!chan->buf[i] || chan->buf[i] == prev)
+ break;
relay_switch_subbuf(chan->buf[i], 0);
+ prev = chan->buf[i];
}
}

diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
--- a/include/linux/relayfs_fs.h
+++ b/include/linux/relayfs_fs.h
@@ -115,6 +115,7 @@ struct rchan_callbacks
* @parent: the parent of the file to create
* @mode: the mode of the file to create
* @buf: the channel buffer
+ * @is_global: outparam - set non-zero if the buffer should be global
*
* Called during relay_open(), once for each per-cpu buffer,
* to allow the client to create a file to be used to
@@ -125,12 +126,17 @@ struct rchan_callbacks
* The callback should return the dentry of the file created
* to represent the relay buffer.
*
+ * Setting the is_global outparam to a non-zero value will
+ * cause relay_open() to create a single global buffer rather
+ * than the default set of per-cpu buffers.
+ *
* See Documentation/filesystems/relayfs.txt for more info.
*/
struct dentry *(*create_buf_file)(const char *filename,
struct dentry *parent,
int mode,
- struct rchan_buf *buf);
+ struct rchan_buf *buf,
+ int *is_global);

/*
* remove_buf_file - remove file representing a relayfs channel buffer


2005-11-11 16:54:37

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 12/12] relayfs: Documentation cleanup, remove obsolete info

librelay and relay-app.h have been retired - update Documentation to
reflect that.

Signed-off-by: Tom Zanussi <[email protected]>

---

relayfs.txt | 55 +++++++++++++++++++++++++++++++++----------------------
1 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt
--- a/Documentation/filesystems/relayfs.txt
+++ b/Documentation/filesystems/relayfs.txt
@@ -44,30 +44,41 @@ relayfs can operate in a mode where it w
collected by userspace, and not wait for it to consume it.

relayfs itself does not provide for communication of such data between
-userspace and kernel, allowing the kernel side to remain simple and not
-impose a single interface on userspace. It does provide a separate
-helper though, described below.
+userspace and kernel, allowing the kernel side to remain simple and
+not impose a single interface on userspace. It does provide a set of
+examples and a separate helper though, described below.
+
+klog and relay-apps example code
+================================
+
+relayfs itself is ready to use, but to make things easier, a couple
+simple utility functions and a set of examples are provided.
+
+The relay-apps example tarball, available on the relayfs sourceforge
+site, contains a set of self-contained examples, each consisting of a
+pair of .c files containing boilerplate code for each of the user and
+kernel sides of a relayfs application; combined these two sets of
+boilerplate code provide glue to easily stream data to disk, without
+having to bother with mundane housekeeping chores.
+
+The 'klog debugging functions' patch (klog.patch in the relay-apps
+tarball) provides a couple of high-level logging functions to the
+kernel which allow writing formatted text or raw data to a channel,
+regardless of whether a channel to write into exists or not, or
+whether relayfs is compiled into the kernel or is configured as a
+module. These functions allow you to put unconditional 'trace'
+statements anywhere in the kernel or kernel modules; only when there
+is a 'klog handler' registered will data actually be logged (see the
+klog and kleak examples for details).
+
+It is of course possible to use relayfs from scratch i.e. without
+using any of the relay-apps example code or klog, but you'll have to
+implement communication between userspace and kernel, allowing both to
+convey the state of buffers (full, empty, amount of padding).

-klog, relay-app & librelay
-==========================
-
-relayfs itself is ready to use, but to make things easier, two
-additional systems are provided. klog is a simple wrapper to make
-writing formatted text or raw data to a channel simpler, regardless of
-whether a channel to write into exists or not, or whether relayfs is
-compiled into the kernel or is configured as a module. relay-app is
-the kernel counterpart of userspace librelay.c, combined these two
-files provide glue to easily stream data to disk, without having to
-bother with housekeeping. klog and relay-app can be used together,
-with klog providing high-level logging functions to the kernel and
-relay-app taking care of kernel-user control and disk-logging chores.
-
-It is possible to use relayfs without relay-app & librelay, but you'll
-have to implement communication between userspace and kernel, allowing
-both to convey the state of buffers (full, empty, amount of padding).
+klog and the relay-apps examples can be found in the relay-apps
+tarball on http://relayfs.sourceforge.net

-klog, relay-app and librelay can be found in the relay-apps tarball on
-http://relayfs.sourceforge.net

The relayfs user space API
==========================


2005-11-11 16:54:05

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 11/12] relayfs: cleanup, change relayfs_file_* to relay_file_*

This patch renames relayfs_file_operations to relay_file_operations,
and the file operations themselves from relayfs_XXX to relay_file_XXX,
to make it more clear that they refer to relay files.

Signed-off-by: Tom Zanussi <[email protected]>

---

fs/relayfs/inode.c | 89 +++++++++++++++++++++++----------------------
fs/relayfs/relay.c | 2 -
include/linux/relayfs_fs.h | 5 +-
3 files changed, 50 insertions(+), 46 deletions(-)

diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
--- a/fs/relayfs/inode.c
+++ b/fs/relayfs/inode.c
@@ -247,13 +247,13 @@ int relayfs_remove_dir(struct dentry *de
}

/**
- * relayfs_open - open file op for relayfs files
+ * relay_file_open - open file op for relay files
* @inode: the inode
* @filp: the file
*
* Increments the channel buffer refcount.
*/
-static int relayfs_open(struct inode *inode, struct file *filp)
+static int relay_file_open(struct inode *inode, struct file *filp)
{
struct rchan_buf *buf = inode->u.generic_ip;
kref_get(&buf->kref);
@@ -263,26 +263,26 @@ static int relayfs_open(struct inode *in
}

/**
- * relayfs_mmap - mmap file op for relayfs files
+ * relay_file_mmap - mmap file op for relay files
* @filp: the file
* @vma: the vma describing what to map
*
* Calls upon relay_mmap_buf to map the file into user space.
*/
-static int relayfs_mmap(struct file *filp, struct vm_area_struct *vma)
+static int relay_file_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct rchan_buf *buf = filp->private_data;
return relay_mmap_buf(buf, vma);
}

/**
- * relayfs_poll - poll file op for relayfs files
+ * relay_file_poll - poll file op for relay files
* @filp: the file
* @wait: poll table
*
* Poll implemention.
*/
-static unsigned int relayfs_poll(struct file *filp, poll_table *wait)
+static unsigned int relay_file_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
struct rchan_buf *buf = filp->private_data;
@@ -300,14 +300,14 @@ static unsigned int relayfs_poll(struct
}

/**
- * relayfs_release - release file op for relayfs files
+ * relay_file_release - release file op for relay files
* @inode: the inode
* @filp: the file
*
* Decrements the channel refcount, as the filesystem is
* no longer using it.
*/
-static int relayfs_release(struct inode *inode, struct file *filp)
+static int relay_file_release(struct inode *inode, struct file *filp)
{
struct rchan_buf *buf = filp->private_data;
kref_put(&buf->kref, relay_remove_buf);
@@ -316,11 +316,11 @@ static int relayfs_release(struct inode
}

/**
- * relayfs_read_consume - update the consumed count for the buffer
+ * relay_file_read_consume - update the consumed count for the buffer
*/
-static void relayfs_read_consume(struct rchan_buf *buf,
- size_t read_pos,
- size_t bytes_consumed)
+static void relay_file_read_consume(struct rchan_buf *buf,
+ size_t read_pos,
+ size_t bytes_consumed)
{
size_t subbuf_size = buf->chan->subbuf_size;
size_t n_subbufs = buf->chan->n_subbufs;
@@ -343,9 +343,9 @@ static void relayfs_read_consume(struct
}

/**
- * relayfs_read_avail - boolean, are there unconsumed bytes available?
+ * relay_file_read_avail - boolean, are there unconsumed bytes available?
*/
-static int relayfs_read_avail(struct rchan_buf *buf, size_t read_pos)
+static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
{
size_t bytes_produced, bytes_consumed, write_offset;
size_t subbuf_size = buf->chan->subbuf_size;
@@ -376,16 +376,16 @@ static int relayfs_read_avail(struct rch
if (bytes_produced == bytes_consumed)
return 0;

- relayfs_read_consume(buf, read_pos, 0);
+ relay_file_read_consume(buf, read_pos, 0);

return 1;
}

/**
- * relayfs_read_subbuf_avail - return bytes available in sub-buffer
+ * relay_file_read_subbuf_avail - return bytes available in sub-buffer
*/
-static size_t relayfs_read_subbuf_avail(size_t read_pos,
- struct rchan_buf *buf)
+static size_t relay_file_read_subbuf_avail(size_t read_pos,
+ struct rchan_buf *buf)
{
size_t padding, avail = 0;
size_t read_subbuf, read_offset, write_subbuf, write_offset;
@@ -407,14 +407,14 @@ static size_t relayfs_read_subbuf_avail(
}

/**
- * relayfs_read_start_pos - find the first available byte to read
+ * relay_file_read_start_pos - find the first available byte to read
*
* If the read_pos is in the middle of padding, return the
* position of the first actually available byte, otherwise
* return the original value.
*/
-static size_t relayfs_read_start_pos(size_t read_pos,
- struct rchan_buf *buf)
+static size_t relay_file_read_start_pos(size_t read_pos,
+ struct rchan_buf *buf)
{
size_t read_subbuf, padding, padding_start, padding_end;
size_t subbuf_size = buf->chan->subbuf_size;
@@ -433,11 +433,11 @@ static size_t relayfs_read_start_pos(siz
}

/**
- * relayfs_read_end_pos - return the new read position
+ * relay_file_read_end_pos - return the new read position
*/
-static size_t relayfs_read_end_pos(struct rchan_buf *buf,
- size_t read_pos,
- size_t count)
+static size_t relay_file_read_end_pos(struct rchan_buf *buf,
+ size_t read_pos,
+ size_t count)
{
size_t read_subbuf, padding, end_pos;
size_t subbuf_size = buf->chan->subbuf_size;
@@ -456,7 +456,7 @@ static size_t relayfs_read_end_pos(struc
}

/**
- * relayfs_read - read file op for relayfs files
+ * relay_file_read - read file op for relay files
* @filp: the file
* @buffer: the userspace buffer
* @count: number of bytes to read
@@ -465,10 +465,10 @@ static size_t relayfs_read_end_pos(struc
* Reads count bytes or the number of bytes available in the
* current sub-buffer being read, whichever is smaller.
*/
-static ssize_t relayfs_read(struct file *filp,
- char __user *buffer,
- size_t count,
- loff_t *ppos)
+static ssize_t relay_file_read(struct file *filp,
+ char __user *buffer,
+ size_t count,
+ loff_t *ppos)
{
struct rchan_buf *buf = filp->private_data;
struct inode *inode = filp->f_dentry->d_inode;
@@ -477,11 +477,11 @@ static ssize_t relayfs_read(struct file
void *from;

down(&inode->i_sem);
- if(!relayfs_read_avail(buf, *ppos))
+ if(!relay_file_read_avail(buf, *ppos))
goto out;

- read_start = relayfs_read_start_pos(*ppos, buf);
- avail = relayfs_read_subbuf_avail(read_start, buf);
+ read_start = relay_file_read_start_pos(*ppos, buf);
+ avail = relay_file_read_subbuf_avail(read_start, buf);
if (!avail)
goto out;

@@ -491,20 +491,20 @@ static ssize_t relayfs_read(struct file
ret = -EFAULT;
goto out;
}
- relayfs_read_consume(buf, read_start, count);
- *ppos = relayfs_read_end_pos(buf, read_start, count);
+ relay_file_read_consume(buf, read_start, count);
+ *ppos = relay_file_read_end_pos(buf, read_start, count);
out:
up(&inode->i_sem);
return ret;
}

-struct file_operations relayfs_file_operations = {
- .open = relayfs_open,
- .poll = relayfs_poll,
- .mmap = relayfs_mmap,
- .read = relayfs_read,
+struct file_operations relay_file_operations = {
+ .open = relay_file_open,
+ .poll = relay_file_poll,
+ .mmap = relay_file_mmap,
+ .read = relay_file_read,
.llseek = no_llseek,
- .release = relayfs_release,
+ .release = relay_file_release,
};

static struct super_operations relayfs_ops = {
@@ -558,13 +558,18 @@ static int __init init_relayfs_fs(void)

static void __exit exit_relayfs_fs(void)
{
+
+
+
+
+
unregister_filesystem(&relayfs_fs_type);
}

module_init(init_relayfs_fs)
module_exit(exit_relayfs_fs)

-EXPORT_SYMBOL_GPL(relayfs_file_operations);
+EXPORT_SYMBOL_GPL(relay_file_operations);
EXPORT_SYMBOL_GPL(relayfs_create_dir);
EXPORT_SYMBOL_GPL(relayfs_remove_dir);
EXPORT_SYMBOL_GPL(relayfs_create_file);
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
--- a/fs/relayfs/relay.c
+++ b/fs/relayfs/relay.c
@@ -90,7 +90,7 @@ static struct dentry *create_buf_file_de
int *is_global)
{
return relayfs_create_file(filename, parent, mode,
- &relayfs_file_operations, buf);
+ &relay_file_operations, buf);
}

/*
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
--- a/include/linux/relayfs_fs.h
+++ b/include/linux/relayfs_fs.h
@@ -278,10 +278,9 @@ static inline void subbuf_start_reserve(
}

/*
- * exported relayfs file operations, fs/relayfs/inode.c
+ * exported relay file operations, fs/relayfs/inode.c
*/
-
-extern struct file_operations relayfs_file_operations;
+extern struct file_operations relay_file_operations;

#endif /* _LINUX_RELAYFS_FS_H */



2005-11-11 19:37:56

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 2/12] relayfs: export relayfs_create_file() with fileops param

On Fri, Nov 11, 2005 at 10:47:03AM -0600, Tom Zanussi wrote:
> This patch adds a mandatory fileops param to relayfs_create_file() and
> exports that function so that clients can use it to create files
> defined by their own set of file operations, in relayfs. The purpose
> is to allow relayfs applications to create their own set of 'control'
> files alongside their relay files in relayfs rather than having to
> create them in /proc or debugfs for instance. relayfs_create_file()
> is also used by relay_open_buf() to create the relay files for a
> channel. In this case, a pointer to relayfs_file_operations is passed
> in, along with a pointer to the buffer associated with the file.

Again, NACK, control files don't belong into relayfs.

2005-11-11 19:49:44

by Tom Zanussi

[permalink] [raw]
Subject: Re: [PATCH 2/12] relayfs: export relayfs_create_file() with fileops param

Christoph Hellwig writes:
> On Fri, Nov 11, 2005 at 10:47:03AM -0600, Tom Zanussi wrote:
> > This patch adds a mandatory fileops param to relayfs_create_file() and
> > exports that function so that clients can use it to create files
> > defined by their own set of file operations, in relayfs. The purpose
> > is to allow relayfs applications to create their own set of 'control'
> > files alongside their relay files in relayfs rather than having to
> > create them in /proc or debugfs for instance. relayfs_create_file()
> > is also used by relay_open_buf() to create the relay files for a
> > channel. In this case, a pointer to relayfs_file_operations is passed
> > in, along with a pointer to the buffer associated with the file.
>
> Again, NACK, control files don't belong into relayfs.
>

Sure, applications could just as easily create these same files in
/proc, /sys, or /debug, but since relayfs is a filesystem, too, it
seems to me to make sense to take advantage of that and allow them to
be created alongside the relay files they're associated with, in
relayfs.

Tom


2005-11-12 02:10:16

by Baruch Even

[permalink] [raw]
Subject: Re: [PATCH 2/12] relayfs: export relayfs_create_file() with fileops param

Christoph Hellwig wrote:
> On Fri, Nov 11, 2005 at 10:47:03AM -0600, Tom Zanussi wrote:
>
>>This patch adds a mandatory fileops param to relayfs_create_file() and
>>exports that function so that clients can use it to create files
>>defined by their own set of file operations, in relayfs. The purpose
>>is to allow relayfs applications to create their own set of 'control'
>>files alongside their relay files in relayfs rather than having to
>>create them in /proc or debugfs for instance. relayfs_create_file()
>>is also used by relay_open_buf() to create the relay files for a
>>channel. In this case, a pointer to relayfs_file_operations is passed
>>in, along with a pointer to the buffer associated with the file.
>
>
> Again, NACK, control files don't belong into relayfs.

I'm a user of relayfs and I do think the control files should go with
their channels, FWIW.

Where else would they go? Some other completely unrelated place?

IMO It makes a lot of sense to have a single place, and preferably a
simple api like the relay-apps that Tom already did so as to to make the
simple case easy.

A control file is part of the relay channel, it's the way the kernel and
user mode parts communicate to do fast mmap transfers of the data. It is
possible to do the signalling by using simple file read/write but the
mmap method provides for a lot less copying around.

Baruch

2005-12-06 17:29:22

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 2/12] relayfs: export relayfs_create_file() with fileops param

On Fri, Nov 11, 2005 at 01:49:05PM -0600, Tom Zanussi wrote:
> Christoph Hellwig writes:
> > On Fri, Nov 11, 2005 at 10:47:03AM -0600, Tom Zanussi wrote:
> > > This patch adds a mandatory fileops param to relayfs_create_file() and
> > > exports that function so that clients can use it to create files
> > > defined by their own set of file operations, in relayfs. The purpose
> > > is to allow relayfs applications to create their own set of 'control'
> > > files alongside their relay files in relayfs rather than having to
> > > create them in /proc or debugfs for instance. relayfs_create_file()
> > > is also used by relay_open_buf() to create the relay files for a
> > > channel. In this case, a pointer to relayfs_file_operations is passed
> > > in, along with a pointer to the buffer associated with the file.
> >
> > Again, NACK, control files don't belong into relayfs.
> >
>
> Sure, applications could just as easily create these same files in
> /proc, /sys, or /debug, but since relayfs is a filesystem, too, it
> seems to me to make sense to take advantage of that and allow them to
> be created alongside the relay files they're associated with, in
> relayfs.

Didn't we have that discussion before? If we want a mix-and-match fs
just redo relayfs into a library of file operations for debugfs
(or anything else that can use file_operations for that matter)

2005-12-06 18:59:30

by Tom Zanussi

[permalink] [raw]
Subject: Re: [PATCH 2/12] relayfs: export relayfs_create_file() with fileops param

Christoph Hellwig writes:
> On Fri, Nov 11, 2005 at 01:49:05PM -0600, Tom Zanussi wrote:
> > Christoph Hellwig writes:
> > > On Fri, Nov 11, 2005 at 10:47:03AM -0600, Tom Zanussi wrote:
> > > > This patch adds a mandatory fileops param to relayfs_create_file() and
> > > > exports that function so that clients can use it to create files
> > > > defined by their own set of file operations, in relayfs. The purpose
> > > > is to allow relayfs applications to create their own set of 'control'
> > > > files alongside their relay files in relayfs rather than having to
> > > > create them in /proc or debugfs for instance. relayfs_create_file()
> > > > is also used by relay_open_buf() to create the relay files for a
> > > > channel. In this case, a pointer to relayfs_file_operations is passed
> > > > in, along with a pointer to the buffer associated with the file.
> > >
> > > Again, NACK, control files don't belong into relayfs.
> > >
> >
> > Sure, applications could just as easily create these same files in
> > /proc, /sys, or /debug, but since relayfs is a filesystem, too, it
> > seems to me to make sense to take advantage of that and allow them to
> > be created alongside the relay files they're associated with, in
> > relayfs.
>
> Didn't we have that discussion before? If we want a mix-and-match fs
> just redo relayfs into a library of file operations for debugfs
> (or anything else that can use file_operations for that matter)
>

Yes, it did come up but never went anywhere; the sticking point at the
time was the perception that debugfs is only for kernel debugging and
therefore wouldn't be configured into most kernels (whereas relayfs
presumably would), leaving non-debugging relayfs applications high and
dry if the fs part of relayfs was removed.

Other than that, it doesn't really matter whether relay files live in
relayfs or debugfs. At one point I even had a preliminary patch that
would convert fs/relayfs/* -> fs/relay_file.c. I could resurrect that
patch if it makes sense - from a user standpoint, the only differences
would be be that userspace would open and read relay files in
/mnt/debug instead of /mnt/relay and the kernel side would use the
debugfs directory creation functions instead of the relayfs
counterparts.

Or just leave relayfs as is, except that in that case, I do still
think these patches make sense.

Tom