[PATCH 1/4] relayfs: add support for non-relay files

From: Tom Zanussi
Date: Wed Nov 09 2005 - 16:50:32 EST


Hi,

Currently, the relayfs API only supports the creation of directories
(relayfs_create_dir()) and relay files (relay_open()). This patch
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. 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 can be found
here:

http://prdownloads.sourceforge.net/relayfs/relay-apps-0.9.tar.gz?download

Signed-off-by: Tom Zanussi <zanussi@xxxxxxxxxx>

---

fs/relayfs/inode.c | 86 ++++++++++++++++++++++++++++++++++++---------
fs/relayfs/relay.c | 2 -
fs/relayfs/relay.h | 8 ++--
include/linux/relayfs_fs.h | 6 +++
4 files changed, 81 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,14 +33,15 @@ 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,
- struct rchan *chan)
+static struct inode *relayfs_get_inode(struct super_block *sb,
+ int mode,
+ struct rchan *chan,
+ struct file_operations *fops)
{
struct rchan_buf *buf = NULL;
struct inode *inode;

- if (S_ISREG(mode)) {
- BUG_ON(!chan);
+ if (S_ISREG(mode) && chan) {
buf = relay_create_buf(chan);
if (!buf)
return NULL;
@@ -48,7 +49,8 @@ static struct inode *relayfs_get_inode(s

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

@@ -61,7 +63,7 @@ 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;
+ inode->i_fop = fops;
RELAYFS_I(inode)->buf = buf;
break;
case S_IFDIR:
@@ -92,7 +94,8 @@ static struct inode *relayfs_get_inode(s
static struct dentry *relayfs_create_entry(const char *name,
struct dentry *parent,
int mode,
- struct rchan *chan)
+ struct rchan *chan,
+ struct file_operations *fops)
{
struct dentry *d;
struct inode *inode;
@@ -127,7 +130,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, chan, fops);
if (!inode) {
d = NULL;
goto release_mount;
@@ -151,24 +154,62 @@ exit:
}

/**
- * relayfs_create_file - create a file in the relay filesystem
+ * relayfs_create_file - create a file in relay filesystem
* @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
+ * @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.
+ * The file will be created user r on behalf of current user if
+ * mode is not specified.
+ *
*/
-struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
- int mode, struct rchan *chan)
+struct dentry *relayfs_create_file(const char *name,
+ struct dentry *parent,
+ int mode,
+ struct file_operations *fops,
+ void *data)
{
+ struct dentry *d;
+ BUG_ON(!fops);
+
if (!mode)
mode = S_IRUSR;
mode = (mode & S_IALLUGO) | S_IFREG;

- return relayfs_create_entry(name, parent, mode, chan);
+ d = relayfs_create_entry(name, parent, mode, NULL, fops);
+ if (d)
+ d->d_inode->u.generic_ip = data;
+
+ return d;
+}
+
+/**
+ * relayfs_create_relay_file - create a relay file in the relay filesystem
+ * @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
+ *
+ * Returns file dentry if successful, NULL otherwise.
+ *
+ * The file will be created user r on behalf of current user if
+ * mode is not specified.
+ */
+struct dentry *relayfs_create_relay_file(const char *name,
+ struct dentry *parent,
+ int mode,
+ struct rchan *chan)
+{
+ if (!mode)
+ mode = S_IRUSR;
+ mode = (mode & S_IALLUGO) | S_IFREG;
+
+ return relayfs_create_entry(name, parent, mode, chan,
+ &relayfs_file_operations);
}

/**
@@ -183,7 +224,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);
}

/**
@@ -225,6 +266,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
*
@@ -544,7 +596,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;
@@ -602,6 +654,8 @@ 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);
+EXPORT_SYMBOL_GPL(relayfs_remove_file);

MODULE_AUTHOR("Tom Zanussi <zanussi@xxxxxxxxxx> and Karim Yaghmour <karim@xxxxxxxxxxx>");
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
@@ -172,7 +172,7 @@ static struct rchan_buf *relay_open_buf(
struct dentry *dentry;

/* Create file in fs */
- dentry = relayfs_create_file(filename, parent, S_IRUSR, chan);
+ dentry = relayfs_create_relay_file(filename, parent, S_IRUSR, chan);
if (!dentry)
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,10 @@
#ifndef _RELAY_H
#define _RELAY_H

-struct dentry *relayfs_create_file(const char *name,
- struct dentry *parent,
- int mode,
- struct rchan *chan);
+struct dentry *relayfs_create_relay_file(const char *name,
+ struct dentry *parent,
+ int mode,
+ struct rchan *chan);
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
@@ -147,6 +147,12 @@ 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);
+extern int relayfs_remove_file(struct dentry *dentry);

/**
* relay_write - write data into the channel


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/