aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Zanussi <zanussi@us.ibm.com>2006-01-08 04:02:23 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-08 23:13:49 -0500
commit6625b861f8f0e429902b8671b3e70792cd99074e (patch)
tree0a141b0c15d8ed012d971553acde9f7029adcfe6
parentb33291c0bcecfa44baa905964eec4b8815dcbcdf (diff)
[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>
-rw-r--r--fs/relayfs/buffers.c1
-rw-r--r--fs/relayfs/inode.c31
-rw-r--r--fs/relayfs/relay.c11
-rw-r--r--fs/relayfs/relay.h2
4 files changed, 19 insertions, 26 deletions
diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c
index 84e21ffa5ca8..667b529944c5 100644
--- a/fs/relayfs/buffers.c
+++ b/fs/relayfs/buffers.c
@@ -186,4 +186,5 @@ void relay_remove_buf(struct kref *kref)
186{ 186{
187 struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref); 187 struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
188 relayfs_remove(buf->dentry); 188 relayfs_remove(buf->dentry);
189 relay_destroy_buf(buf);
189} 190}
diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
index 0f7f88d067ad..379e07cd2b34 100644
--- a/fs/relayfs/inode.c
+++ b/fs/relayfs/inode.c
@@ -34,23 +34,13 @@ static struct backing_dev_info relayfs_backing_dev_info = {
34}; 34};
35 35
36static struct inode *relayfs_get_inode(struct super_block *sb, int mode, 36static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
37 struct rchan *chan) 37 void *data)
38{ 38{
39 struct rchan_buf *buf = NULL;
40 struct inode *inode; 39 struct inode *inode;
41 40
42 if (S_ISREG(mode)) {
43 BUG_ON(!chan);
44 buf = relay_create_buf(chan);
45 if (!buf)
46 return NULL;
47 }
48
49 inode = new_inode(sb); 41 inode = new_inode(sb);
50 if (!inode) { 42 if (!inode)
51 relay_destroy_buf(buf);
52 return NULL; 43 return NULL;
53 }
54 44
55 inode->i_mode = mode; 45 inode->i_mode = mode;
56 inode->i_uid = 0; 46 inode->i_uid = 0;
@@ -62,7 +52,7 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
62 switch (mode & S_IFMT) { 52 switch (mode & S_IFMT) {
63 case S_IFREG: 53 case S_IFREG:
64 inode->i_fop = &relayfs_file_operations; 54 inode->i_fop = &relayfs_file_operations;
65 RELAYFS_I(inode)->buf = buf; 55 RELAYFS_I(inode)->buf = data;
66 break; 56 break;
67 case S_IFDIR: 57 case S_IFDIR:
68 inode->i_op = &simple_dir_inode_operations; 58 inode->i_op = &simple_dir_inode_operations;
@@ -83,7 +73,7 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
83 * @name: the name of the file to create 73 * @name: the name of the file to create
84 * @parent: parent directory 74 * @parent: parent directory
85 * @mode: mode 75 * @mode: mode
86 * @chan: relay channel associated with the file 76 * @data: user-associated data for this file
87 * 77 *
88 * Returns the new dentry, NULL on failure 78 * Returns the new dentry, NULL on failure
89 * 79 *
@@ -92,7 +82,7 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
92static struct dentry *relayfs_create_entry(const char *name, 82static struct dentry *relayfs_create_entry(const char *name,
93 struct dentry *parent, 83 struct dentry *parent,
94 int mode, 84 int mode,
95 struct rchan *chan) 85 void *data)
96{ 86{
97 struct dentry *d; 87 struct dentry *d;
98 struct inode *inode; 88 struct inode *inode;
@@ -127,7 +117,7 @@ static struct dentry *relayfs_create_entry(const char *name,
127 goto release_mount; 117 goto release_mount;
128 } 118 }
129 119
130 inode = relayfs_get_inode(parent->d_inode->i_sb, mode, chan); 120 inode = relayfs_get_inode(parent->d_inode->i_sb, mode, data);
131 if (!inode) { 121 if (!inode) {
132 d = NULL; 122 d = NULL;
133 goto release_mount; 123 goto release_mount;
@@ -155,20 +145,20 @@ exit:
155 * @name: the name of the file to create 145 * @name: the name of the file to create
156 * @parent: parent directory 146 * @parent: parent directory
157 * @mode: mode, if not specied the default perms are used 147 * @mode: mode, if not specied the default perms are used
158 * @chan: channel associated with the file 148 * @data: user-associated data for this file
159 * 149 *
160 * Returns file dentry if successful, NULL otherwise. 150 * Returns file dentry if successful, NULL otherwise.
161 * 151 *
162 * The file will be created user r on behalf of current user. 152 * The file will be created user r on behalf of current user.
163 */ 153 */
164struct dentry *relayfs_create_file(const char *name, struct dentry *parent, 154struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
165 int mode, struct rchan *chan) 155 int mode, void *data)
166{ 156{
167 if (!mode) 157 if (!mode)
168 mode = S_IRUSR; 158 mode = S_IRUSR;
169 mode = (mode & S_IALLUGO) | S_IFREG; 159 mode = (mode & S_IALLUGO) | S_IFREG;
170 160
171 return relayfs_create_entry(name, parent, mode, chan); 161 return relayfs_create_entry(name, parent, mode, data);
172} 162}
173 163
174/** 164/**
@@ -505,9 +495,6 @@ static struct inode *relayfs_alloc_inode(struct super_block *sb)
505 */ 495 */
506static void relayfs_destroy_inode(struct inode *inode) 496static void relayfs_destroy_inode(struct inode *inode)
507{ 497{
508 if (RELAYFS_I(inode)->buf)
509 relay_destroy_buf(RELAYFS_I(inode)->buf);
510
511 kmem_cache_free(relayfs_inode_cachep, RELAYFS_I(inode)); 498 kmem_cache_free(relayfs_inode_cachep, RELAYFS_I(inode));
512} 499}
513 500
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
index 2a6f7f12b7f9..7fbda177ad8f 100644
--- a/fs/relayfs/relay.c
+++ b/fs/relayfs/relay.c
@@ -171,12 +171,17 @@ static struct rchan_buf *relay_open_buf(struct rchan *chan,
171 struct rchan_buf *buf; 171 struct rchan_buf *buf;
172 struct dentry *dentry; 172 struct dentry *dentry;
173 173
174 buf = relay_create_buf(chan);
175 if (!buf)
176 return NULL;
177
174 /* Create file in fs */ 178 /* Create file in fs */
175 dentry = relayfs_create_file(filename, parent, S_IRUSR, chan); 179 dentry = relayfs_create_file(filename, parent, S_IRUSR, buf);
176 if (!dentry) 180 if (!dentry) {
181 relay_destroy_buf(buf);
177 return NULL; 182 return NULL;
183 }
178 184
179 buf = RELAYFS_I(dentry->d_inode)->buf;
180 buf->dentry = dentry; 185 buf->dentry = dentry;
181 __relay_reset(buf, 1); 186 __relay_reset(buf, 1);
182 187
diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h
index 703503fa22b6..c325bb243549 100644
--- a/fs/relayfs/relay.h
+++ b/fs/relayfs/relay.h
@@ -4,7 +4,7 @@
4struct dentry *relayfs_create_file(const char *name, 4struct dentry *relayfs_create_file(const char *name,
5 struct dentry *parent, 5 struct dentry *parent,
6 int mode, 6 int mode,
7 struct rchan *chan); 7 void *data);
8extern int relayfs_remove(struct dentry *dentry); 8extern int relayfs_remove(struct dentry *dentry);
9extern int relay_buf_empty(struct rchan_buf *buf); 9extern int relay_buf_empty(struct rchan_buf *buf);
10extern void relay_destroy_channel(struct kref *kref); 10extern void relay_destroy_channel(struct kref *kref);