Commit 907f2c77 authored by Tom Zanussi's avatar Tom Zanussi Committed by Linus Torvalds

[PATCH] 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: default avatarTom Zanussi <zanussi@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6625b861
...@@ -33,7 +33,9 @@ static struct backing_dev_info relayfs_backing_dev_info = { ...@@ -33,7 +33,9 @@ static struct backing_dev_info relayfs_backing_dev_info = {
.capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, .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) void *data)
{ {
struct inode *inode; struct inode *inode;
...@@ -51,8 +53,8 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode, ...@@ -51,8 +53,8 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
switch (mode & S_IFMT) { switch (mode & S_IFMT) {
case S_IFREG: case S_IFREG:
inode->i_fop = &relayfs_file_operations; inode->i_fop = fops;
RELAYFS_I(inode)->buf = data; RELAYFS_I(inode)->data = data;
break; break;
case S_IFDIR: case S_IFDIR:
inode->i_op = &simple_dir_inode_operations; inode->i_op = &simple_dir_inode_operations;
...@@ -73,6 +75,7 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode, ...@@ -73,6 +75,7 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
* @name: the name of the file to create * @name: the name of the file to create
* @parent: parent directory * @parent: parent directory
* @mode: mode * @mode: mode
* @fops: file operations to use for the file
* @data: user-associated data for this file * @data: user-associated data for this file
* *
* Returns the new dentry, NULL on failure * Returns the new dentry, NULL on failure
...@@ -82,6 +85,7 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode, ...@@ -82,6 +85,7 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
static struct dentry *relayfs_create_entry(const char *name, static struct dentry *relayfs_create_entry(const char *name,
struct dentry *parent, struct dentry *parent,
int mode, int mode,
struct file_operations *fops,
void *data) void *data)
{ {
struct dentry *d; struct dentry *d;
...@@ -117,7 +121,7 @@ static struct dentry *relayfs_create_entry(const char *name, ...@@ -117,7 +121,7 @@ static struct dentry *relayfs_create_entry(const char *name,
goto release_mount; 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) { if (!inode) {
d = NULL; d = NULL;
goto release_mount; goto release_mount;
...@@ -145,20 +149,26 @@ exit: ...@@ -145,20 +149,26 @@ exit:
* @name: the name of the file to create * @name: the name of the file to create
* @parent: parent directory * @parent: parent directory
* @mode: mode, if not specied the default perms are used * @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 * @data: user-associated data for this file
* *
* Returns file dentry if successful, NULL otherwise. * 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.
*/ */
struct dentry *relayfs_create_file(const char *name, struct dentry *parent, struct dentry *relayfs_create_file(const char *name,
int mode, void *data) struct dentry *parent,
int mode,
struct file_operations *fops,
void *data)
{ {
BUG_ON(!fops);
if (!mode) if (!mode)
mode = S_IRUSR; mode = S_IRUSR;
mode = (mode & S_IALLUGO) | S_IFREG; 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 char *name, struct dentry *parent, ...@@ -173,7 +183,7 @@ struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
struct dentry *relayfs_create_dir(const char *name, struct dentry *parent) struct dentry *relayfs_create_dir(const char *name, struct dentry *parent)
{ {
int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; 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 *dentry) ...@@ -234,7 +244,7 @@ int relayfs_remove_dir(struct dentry *dentry)
*/ */
static int relayfs_open(struct inode *inode, struct file *filp) 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); kref_get(&buf->kref);
return 0; return 0;
...@@ -250,7 +260,7 @@ static int relayfs_open(struct inode *inode, struct file *filp) ...@@ -250,7 +260,7 @@ static int relayfs_open(struct inode *inode, struct file *filp)
static int relayfs_mmap(struct file *filp, struct vm_area_struct *vma) static int relayfs_mmap(struct file *filp, struct vm_area_struct *vma)
{ {
struct inode *inode = filp->f_dentry->d_inode; 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 file *filp, poll_table *wait) ...@@ -264,7 +274,7 @@ static unsigned int relayfs_poll(struct file *filp, poll_table *wait)
{ {
unsigned int mask = 0; unsigned int mask = 0;
struct inode *inode = filp->f_dentry->d_inode; 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) if (buf->finalized)
return POLLERR; return POLLERR;
...@@ -288,7 +298,7 @@ static unsigned int relayfs_poll(struct file *filp, poll_table *wait) ...@@ -288,7 +298,7 @@ static unsigned int relayfs_poll(struct file *filp, poll_table *wait)
*/ */
static int relayfs_release(struct inode *inode, struct file *filp) 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); kref_put(&buf->kref, relay_remove_buf);
return 0; return 0;
...@@ -450,7 +460,7 @@ static ssize_t relayfs_read(struct file *filp, ...@@ -450,7 +460,7 @@ static ssize_t relayfs_read(struct file *filp,
loff_t *ppos) loff_t *ppos)
{ {
struct inode *inode = filp->f_dentry->d_inode; 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; size_t read_start, avail;
ssize_t ret = 0; ssize_t ret = 0;
void *from; void *from;
...@@ -485,7 +495,7 @@ static struct inode *relayfs_alloc_inode(struct super_block *sb) ...@@ -485,7 +495,7 @@ static struct inode *relayfs_alloc_inode(struct super_block *sb)
struct relayfs_inode_info *p = kmem_cache_alloc(relayfs_inode_cachep, SLAB_KERNEL); struct relayfs_inode_info *p = kmem_cache_alloc(relayfs_inode_cachep, SLAB_KERNEL);
if (!p) if (!p)
return NULL; return NULL;
p->buf = NULL; p->data = NULL;
return &p->vfs_inode; return &p->vfs_inode;
} }
...@@ -531,7 +541,7 @@ static int relayfs_fill_super(struct super_block * sb, void * data, int silent) ...@@ -531,7 +541,7 @@ static int relayfs_fill_super(struct super_block * sb, void * data, int silent)
sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = RELAYFS_MAGIC; sb->s_magic = RELAYFS_MAGIC;
sb->s_op = &relayfs_ops; sb->s_op = &relayfs_ops;
inode = relayfs_get_inode(sb, mode, NULL); inode = relayfs_get_inode(sb, mode, NULL, NULL);
if (!inode) if (!inode)
return -ENOMEM; return -ENOMEM;
...@@ -589,6 +599,7 @@ module_exit(exit_relayfs_fs) ...@@ -589,6 +599,7 @@ module_exit(exit_relayfs_fs)
EXPORT_SYMBOL_GPL(relayfs_file_operations); EXPORT_SYMBOL_GPL(relayfs_file_operations);
EXPORT_SYMBOL_GPL(relayfs_create_dir); EXPORT_SYMBOL_GPL(relayfs_create_dir);
EXPORT_SYMBOL_GPL(relayfs_remove_dir); EXPORT_SYMBOL_GPL(relayfs_remove_dir);
EXPORT_SYMBOL_GPL(relayfs_create_file);
MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>"); MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>");
MODULE_DESCRIPTION("Relay Filesystem"); MODULE_DESCRIPTION("Relay Filesystem");
......
...@@ -176,7 +176,8 @@ static struct rchan_buf *relay_open_buf(struct rchan *chan, ...@@ -176,7 +176,8 @@ static struct rchan_buf *relay_open_buf(struct rchan *chan,
return NULL; return NULL;
/* Create file in fs */ /* 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) { if (!dentry) {
relay_destroy_buf(buf); relay_destroy_buf(buf);
return NULL; return NULL;
......
#ifndef _RELAY_H #ifndef _RELAY_H
#define _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 relayfs_remove(struct dentry *dentry);
extern int relay_buf_empty(struct rchan_buf *buf); extern int relay_buf_empty(struct rchan_buf *buf);
extern void relay_destroy_channel(struct kref *kref); extern void relay_destroy_channel(struct kref *kref);
......
...@@ -70,7 +70,7 @@ struct rchan ...@@ -70,7 +70,7 @@ struct rchan
struct relayfs_inode_info struct relayfs_inode_info
{ {
struct inode vfs_inode; struct inode vfs_inode;
struct rchan_buf *buf; void *data;
}; };
static inline struct relayfs_inode_info *RELAYFS_I(struct inode *inode) static inline struct relayfs_inode_info *RELAYFS_I(struct inode *inode)
...@@ -148,6 +148,11 @@ extern size_t relay_switch_subbuf(struct rchan_buf *buf, ...@@ -148,6 +148,11 @@ extern size_t relay_switch_subbuf(struct rchan_buf *buf,
extern struct dentry *relayfs_create_dir(const char *name, extern struct dentry *relayfs_create_dir(const char *name,
struct dentry *parent); struct dentry *parent);
extern int relayfs_remove_dir(struct dentry *dentry); 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 * relay_write - write data into the channel
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment