diff options
Diffstat (limited to 'fs/relayfs')
-rw-r--r-- | fs/relayfs/buffers.c | 3 | ||||
-rw-r--r-- | fs/relayfs/inode.c | 226 | ||||
-rw-r--r-- | fs/relayfs/relay.c | 77 | ||||
-rw-r--r-- | fs/relayfs/relay.h | 4 |
4 files changed, 165 insertions, 145 deletions
diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c index 84e21ffa5ca8..10187812771e 100644 --- a/fs/relayfs/buffers.c +++ b/fs/relayfs/buffers.c | |||
@@ -185,5 +185,6 @@ void relay_destroy_buf(struct rchan_buf *buf) | |||
185 | void relay_remove_buf(struct kref *kref) | 185 | 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 | buf->chan->cb->remove_buf_file(buf->dentry); |
189 | relay_destroy_buf(buf); | ||
189 | } | 190 | } |
diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c index 0f7f88d067ad..383523011aad 100644 --- a/fs/relayfs/inode.c +++ b/fs/relayfs/inode.c | |||
@@ -26,31 +26,22 @@ | |||
26 | 26 | ||
27 | static struct vfsmount * relayfs_mount; | 27 | static struct vfsmount * relayfs_mount; |
28 | static int relayfs_mount_count; | 28 | static int relayfs_mount_count; |
29 | static kmem_cache_t * relayfs_inode_cachep; | ||
30 | 29 | ||
31 | static struct backing_dev_info relayfs_backing_dev_info = { | 30 | static struct backing_dev_info relayfs_backing_dev_info = { |
32 | .ra_pages = 0, /* No readahead */ | 31 | .ra_pages = 0, /* No readahead */ |
33 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, | 32 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, |
34 | }; | 33 | }; |
35 | 34 | ||
36 | static struct inode *relayfs_get_inode(struct super_block *sb, int mode, | 35 | static struct inode *relayfs_get_inode(struct super_block *sb, |
37 | struct rchan *chan) | 36 | int mode, |
37 | struct file_operations *fops, | ||
38 | void *data) | ||
38 | { | 39 | { |
39 | struct rchan_buf *buf = NULL; | ||
40 | struct inode *inode; | 40 | struct inode *inode; |
41 | 41 | ||
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); | 42 | inode = new_inode(sb); |
50 | if (!inode) { | 43 | if (!inode) |
51 | relay_destroy_buf(buf); | ||
52 | return NULL; | 44 | return NULL; |
53 | } | ||
54 | 45 | ||
55 | inode->i_mode = mode; | 46 | inode->i_mode = mode; |
56 | inode->i_uid = 0; | 47 | inode->i_uid = 0; |
@@ -61,8 +52,9 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode, | |||
61 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 52 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
62 | switch (mode & S_IFMT) { | 53 | switch (mode & S_IFMT) { |
63 | case S_IFREG: | 54 | case S_IFREG: |
64 | inode->i_fop = &relayfs_file_operations; | 55 | inode->i_fop = fops; |
65 | RELAYFS_I(inode)->buf = buf; | 56 | if (data) |
57 | inode->u.generic_ip = data; | ||
66 | break; | 58 | break; |
67 | case S_IFDIR: | 59 | case S_IFDIR: |
68 | inode->i_op = &simple_dir_inode_operations; | 60 | inode->i_op = &simple_dir_inode_operations; |
@@ -83,7 +75,8 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode, | |||
83 | * @name: the name of the file to create | 75 | * @name: the name of the file to create |
84 | * @parent: parent directory | 76 | * @parent: parent directory |
85 | * @mode: mode | 77 | * @mode: mode |
86 | * @chan: relay channel associated with the file | 78 | * @fops: file operations to use for the file |
79 | * @data: user-associated data for this file | ||
87 | * | 80 | * |
88 | * Returns the new dentry, NULL on failure | 81 | * Returns the new dentry, NULL on failure |
89 | * | 82 | * |
@@ -92,7 +85,8 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode, | |||
92 | static struct dentry *relayfs_create_entry(const char *name, | 85 | static struct dentry *relayfs_create_entry(const char *name, |
93 | struct dentry *parent, | 86 | struct dentry *parent, |
94 | int mode, | 87 | int mode, |
95 | struct rchan *chan) | 88 | struct file_operations *fops, |
89 | void *data) | ||
96 | { | 90 | { |
97 | struct dentry *d; | 91 | struct dentry *d; |
98 | struct inode *inode; | 92 | struct inode *inode; |
@@ -115,7 +109,7 @@ static struct dentry *relayfs_create_entry(const char *name, | |||
115 | } | 109 | } |
116 | 110 | ||
117 | parent = dget(parent); | 111 | parent = dget(parent); |
118 | down(&parent->d_inode->i_sem); | 112 | mutex_lock(&parent->d_inode->i_mutex); |
119 | d = lookup_one_len(name, parent, strlen(name)); | 113 | d = lookup_one_len(name, parent, strlen(name)); |
120 | if (IS_ERR(d)) { | 114 | if (IS_ERR(d)) { |
121 | d = NULL; | 115 | d = NULL; |
@@ -127,7 +121,7 @@ static struct dentry *relayfs_create_entry(const char *name, | |||
127 | goto release_mount; | 121 | goto release_mount; |
128 | } | 122 | } |
129 | 123 | ||
130 | inode = relayfs_get_inode(parent->d_inode->i_sb, mode, chan); | 124 | inode = relayfs_get_inode(parent->d_inode->i_sb, mode, fops, data); |
131 | if (!inode) { | 125 | if (!inode) { |
132 | d = NULL; | 126 | d = NULL; |
133 | goto release_mount; | 127 | goto release_mount; |
@@ -145,7 +139,7 @@ release_mount: | |||
145 | simple_release_fs(&relayfs_mount, &relayfs_mount_count); | 139 | simple_release_fs(&relayfs_mount, &relayfs_mount_count); |
146 | 140 | ||
147 | exit: | 141 | exit: |
148 | up(&parent->d_inode->i_sem); | 142 | mutex_unlock(&parent->d_inode->i_mutex); |
149 | dput(parent); | 143 | dput(parent); |
150 | return d; | 144 | return d; |
151 | } | 145 | } |
@@ -155,20 +149,26 @@ exit: | |||
155 | * @name: the name of the file to create | 149 | * @name: the name of the file to create |
156 | * @parent: parent directory | 150 | * @parent: parent directory |
157 | * @mode: mode, if not specied the default perms are used | 151 | * @mode: mode, if not specied the default perms are used |
158 | * @chan: channel associated with the file | 152 | * @fops: file operations to use for the file |
153 | * @data: user-associated data for this file | ||
159 | * | 154 | * |
160 | * Returns file dentry if successful, NULL otherwise. | 155 | * Returns file dentry if successful, NULL otherwise. |
161 | * | 156 | * |
162 | * The file will be created user r on behalf of current user. | 157 | * The file will be created user r on behalf of current user. |
163 | */ | 158 | */ |
164 | struct dentry *relayfs_create_file(const char *name, struct dentry *parent, | 159 | struct dentry *relayfs_create_file(const char *name, |
165 | int mode, struct rchan *chan) | 160 | struct dentry *parent, |
161 | int mode, | ||
162 | struct file_operations *fops, | ||
163 | void *data) | ||
166 | { | 164 | { |
165 | BUG_ON(!fops); | ||
166 | |||
167 | if (!mode) | 167 | if (!mode) |
168 | mode = S_IRUSR; | 168 | mode = S_IRUSR; |
169 | mode = (mode & S_IALLUGO) | S_IFREG; | 169 | mode = (mode & S_IALLUGO) | S_IFREG; |
170 | 170 | ||
171 | return relayfs_create_entry(name, parent, mode, chan); | 171 | return relayfs_create_entry(name, parent, mode, fops, data); |
172 | } | 172 | } |
173 | 173 | ||
174 | /** | 174 | /** |
@@ -183,7 +183,7 @@ struct dentry *relayfs_create_file(const char *name, struct dentry *parent, | |||
183 | struct dentry *relayfs_create_dir(const char *name, struct dentry *parent) | 183 | struct dentry *relayfs_create_dir(const char *name, struct dentry *parent) |
184 | { | 184 | { |
185 | int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; | 185 | int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; |
186 | return relayfs_create_entry(name, parent, mode, NULL); | 186 | return relayfs_create_entry(name, parent, mode, NULL, NULL); |
187 | } | 187 | } |
188 | 188 | ||
189 | /** | 189 | /** |
@@ -204,7 +204,7 @@ int relayfs_remove(struct dentry *dentry) | |||
204 | return -EINVAL; | 204 | return -EINVAL; |
205 | 205 | ||
206 | parent = dget(parent); | 206 | parent = dget(parent); |
207 | down(&parent->d_inode->i_sem); | 207 | mutex_lock(&parent->d_inode->i_mutex); |
208 | if (dentry->d_inode) { | 208 | if (dentry->d_inode) { |
209 | if (S_ISDIR(dentry->d_inode->i_mode)) | 209 | if (S_ISDIR(dentry->d_inode->i_mode)) |
210 | error = simple_rmdir(parent->d_inode, dentry); | 210 | error = simple_rmdir(parent->d_inode, dentry); |
@@ -215,7 +215,7 @@ int relayfs_remove(struct dentry *dentry) | |||
215 | } | 215 | } |
216 | if (!error) | 216 | if (!error) |
217 | dput(dentry); | 217 | dput(dentry); |
218 | up(&parent->d_inode->i_sem); | 218 | mutex_unlock(&parent->d_inode->i_mutex); |
219 | dput(parent); | 219 | dput(parent); |
220 | 220 | ||
221 | if (!error) | 221 | if (!error) |
@@ -225,6 +225,17 @@ int relayfs_remove(struct dentry *dentry) | |||
225 | } | 225 | } |
226 | 226 | ||
227 | /** | 227 | /** |
228 | * relayfs_remove_file - remove a file from relay filesystem | ||
229 | * @dentry: directory dentry | ||
230 | * | ||
231 | * Returns 0 if successful, negative otherwise. | ||
232 | */ | ||
233 | int relayfs_remove_file(struct dentry *dentry) | ||
234 | { | ||
235 | return relayfs_remove(dentry); | ||
236 | } | ||
237 | |||
238 | /** | ||
228 | * relayfs_remove_dir - remove a directory in the relay filesystem | 239 | * relayfs_remove_dir - remove a directory in the relay filesystem |
229 | * @dentry: directory dentry | 240 | * @dentry: directory dentry |
230 | * | 241 | * |
@@ -236,45 +247,45 @@ int relayfs_remove_dir(struct dentry *dentry) | |||
236 | } | 247 | } |
237 | 248 | ||
238 | /** | 249 | /** |
239 | * relayfs_open - open file op for relayfs files | 250 | * relay_file_open - open file op for relay files |
240 | * @inode: the inode | 251 | * @inode: the inode |
241 | * @filp: the file | 252 | * @filp: the file |
242 | * | 253 | * |
243 | * Increments the channel buffer refcount. | 254 | * Increments the channel buffer refcount. |
244 | */ | 255 | */ |
245 | static int relayfs_open(struct inode *inode, struct file *filp) | 256 | static int relay_file_open(struct inode *inode, struct file *filp) |
246 | { | 257 | { |
247 | struct rchan_buf *buf = RELAYFS_I(inode)->buf; | 258 | struct rchan_buf *buf = inode->u.generic_ip; |
248 | kref_get(&buf->kref); | 259 | kref_get(&buf->kref); |
260 | filp->private_data = buf; | ||
249 | 261 | ||
250 | return 0; | 262 | return 0; |
251 | } | 263 | } |
252 | 264 | ||
253 | /** | 265 | /** |
254 | * relayfs_mmap - mmap file op for relayfs files | 266 | * relay_file_mmap - mmap file op for relay files |
255 | * @filp: the file | 267 | * @filp: the file |
256 | * @vma: the vma describing what to map | 268 | * @vma: the vma describing what to map |
257 | * | 269 | * |
258 | * Calls upon relay_mmap_buf to map the file into user space. | 270 | * Calls upon relay_mmap_buf to map the file into user space. |
259 | */ | 271 | */ |
260 | static int relayfs_mmap(struct file *filp, struct vm_area_struct *vma) | 272 | static int relay_file_mmap(struct file *filp, struct vm_area_struct *vma) |
261 | { | 273 | { |
262 | struct inode *inode = filp->f_dentry->d_inode; | 274 | struct rchan_buf *buf = filp->private_data; |
263 | return relay_mmap_buf(RELAYFS_I(inode)->buf, vma); | 275 | return relay_mmap_buf(buf, vma); |
264 | } | 276 | } |
265 | 277 | ||
266 | /** | 278 | /** |
267 | * relayfs_poll - poll file op for relayfs files | 279 | * relay_file_poll - poll file op for relay files |
268 | * @filp: the file | 280 | * @filp: the file |
269 | * @wait: poll table | 281 | * @wait: poll table |
270 | * | 282 | * |
271 | * Poll implemention. | 283 | * Poll implemention. |
272 | */ | 284 | */ |
273 | static unsigned int relayfs_poll(struct file *filp, poll_table *wait) | 285 | static unsigned int relay_file_poll(struct file *filp, poll_table *wait) |
274 | { | 286 | { |
275 | unsigned int mask = 0; | 287 | unsigned int mask = 0; |
276 | struct inode *inode = filp->f_dentry->d_inode; | 288 | struct rchan_buf *buf = filp->private_data; |
277 | struct rchan_buf *buf = RELAYFS_I(inode)->buf; | ||
278 | 289 | ||
279 | if (buf->finalized) | 290 | if (buf->finalized) |
280 | return POLLERR; | 291 | return POLLERR; |
@@ -289,27 +300,27 @@ static unsigned int relayfs_poll(struct file *filp, poll_table *wait) | |||
289 | } | 300 | } |
290 | 301 | ||
291 | /** | 302 | /** |
292 | * relayfs_release - release file op for relayfs files | 303 | * relay_file_release - release file op for relay files |
293 | * @inode: the inode | 304 | * @inode: the inode |
294 | * @filp: the file | 305 | * @filp: the file |
295 | * | 306 | * |
296 | * Decrements the channel refcount, as the filesystem is | 307 | * Decrements the channel refcount, as the filesystem is |
297 | * no longer using it. | 308 | * no longer using it. |
298 | */ | 309 | */ |
299 | static int relayfs_release(struct inode *inode, struct file *filp) | 310 | static int relay_file_release(struct inode *inode, struct file *filp) |
300 | { | 311 | { |
301 | struct rchan_buf *buf = RELAYFS_I(inode)->buf; | 312 | struct rchan_buf *buf = filp->private_data; |
302 | kref_put(&buf->kref, relay_remove_buf); | 313 | kref_put(&buf->kref, relay_remove_buf); |
303 | 314 | ||
304 | return 0; | 315 | return 0; |
305 | } | 316 | } |
306 | 317 | ||
307 | /** | 318 | /** |
308 | * relayfs_read_consume - update the consumed count for the buffer | 319 | * relay_file_read_consume - update the consumed count for the buffer |
309 | */ | 320 | */ |
310 | static void relayfs_read_consume(struct rchan_buf *buf, | 321 | static void relay_file_read_consume(struct rchan_buf *buf, |
311 | size_t read_pos, | 322 | size_t read_pos, |
312 | size_t bytes_consumed) | 323 | size_t bytes_consumed) |
313 | { | 324 | { |
314 | size_t subbuf_size = buf->chan->subbuf_size; | 325 | size_t subbuf_size = buf->chan->subbuf_size; |
315 | size_t n_subbufs = buf->chan->n_subbufs; | 326 | size_t n_subbufs = buf->chan->n_subbufs; |
@@ -332,9 +343,9 @@ static void relayfs_read_consume(struct rchan_buf *buf, | |||
332 | } | 343 | } |
333 | 344 | ||
334 | /** | 345 | /** |
335 | * relayfs_read_avail - boolean, are there unconsumed bytes available? | 346 | * relay_file_read_avail - boolean, are there unconsumed bytes available? |
336 | */ | 347 | */ |
337 | static int relayfs_read_avail(struct rchan_buf *buf, size_t read_pos) | 348 | static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos) |
338 | { | 349 | { |
339 | size_t bytes_produced, bytes_consumed, write_offset; | 350 | size_t bytes_produced, bytes_consumed, write_offset; |
340 | size_t subbuf_size = buf->chan->subbuf_size; | 351 | size_t subbuf_size = buf->chan->subbuf_size; |
@@ -365,16 +376,16 @@ static int relayfs_read_avail(struct rchan_buf *buf, size_t read_pos) | |||
365 | if (bytes_produced == bytes_consumed) | 376 | if (bytes_produced == bytes_consumed) |
366 | return 0; | 377 | return 0; |
367 | 378 | ||
368 | relayfs_read_consume(buf, read_pos, 0); | 379 | relay_file_read_consume(buf, read_pos, 0); |
369 | 380 | ||
370 | return 1; | 381 | return 1; |
371 | } | 382 | } |
372 | 383 | ||
373 | /** | 384 | /** |
374 | * relayfs_read_subbuf_avail - return bytes available in sub-buffer | 385 | * relay_file_read_subbuf_avail - return bytes available in sub-buffer |
375 | */ | 386 | */ |
376 | static size_t relayfs_read_subbuf_avail(size_t read_pos, | 387 | static size_t relay_file_read_subbuf_avail(size_t read_pos, |
377 | struct rchan_buf *buf) | 388 | struct rchan_buf *buf) |
378 | { | 389 | { |
379 | size_t padding, avail = 0; | 390 | size_t padding, avail = 0; |
380 | size_t read_subbuf, read_offset, write_subbuf, write_offset; | 391 | size_t read_subbuf, read_offset, write_subbuf, write_offset; |
@@ -396,14 +407,14 @@ static size_t relayfs_read_subbuf_avail(size_t read_pos, | |||
396 | } | 407 | } |
397 | 408 | ||
398 | /** | 409 | /** |
399 | * relayfs_read_start_pos - find the first available byte to read | 410 | * relay_file_read_start_pos - find the first available byte to read |
400 | * | 411 | * |
401 | * If the read_pos is in the middle of padding, return the | 412 | * If the read_pos is in the middle of padding, return the |
402 | * position of the first actually available byte, otherwise | 413 | * position of the first actually available byte, otherwise |
403 | * return the original value. | 414 | * return the original value. |
404 | */ | 415 | */ |
405 | static size_t relayfs_read_start_pos(size_t read_pos, | 416 | static size_t relay_file_read_start_pos(size_t read_pos, |
406 | struct rchan_buf *buf) | 417 | struct rchan_buf *buf) |
407 | { | 418 | { |
408 | size_t read_subbuf, padding, padding_start, padding_end; | 419 | size_t read_subbuf, padding, padding_start, padding_end; |
409 | size_t subbuf_size = buf->chan->subbuf_size; | 420 | size_t subbuf_size = buf->chan->subbuf_size; |
@@ -422,11 +433,11 @@ static size_t relayfs_read_start_pos(size_t read_pos, | |||
422 | } | 433 | } |
423 | 434 | ||
424 | /** | 435 | /** |
425 | * relayfs_read_end_pos - return the new read position | 436 | * relay_file_read_end_pos - return the new read position |
426 | */ | 437 | */ |
427 | static size_t relayfs_read_end_pos(struct rchan_buf *buf, | 438 | static size_t relay_file_read_end_pos(struct rchan_buf *buf, |
428 | size_t read_pos, | 439 | size_t read_pos, |
429 | size_t count) | 440 | size_t count) |
430 | { | 441 | { |
431 | size_t read_subbuf, padding, end_pos; | 442 | size_t read_subbuf, padding, end_pos; |
432 | size_t subbuf_size = buf->chan->subbuf_size; | 443 | size_t subbuf_size = buf->chan->subbuf_size; |
@@ -445,7 +456,7 @@ static size_t relayfs_read_end_pos(struct rchan_buf *buf, | |||
445 | } | 456 | } |
446 | 457 | ||
447 | /** | 458 | /** |
448 | * relayfs_read - read file op for relayfs files | 459 | * relay_file_read - read file op for relay files |
449 | * @filp: the file | 460 | * @filp: the file |
450 | * @buffer: the userspace buffer | 461 | * @buffer: the userspace buffer |
451 | * @count: number of bytes to read | 462 | * @count: number of bytes to read |
@@ -454,23 +465,23 @@ static size_t relayfs_read_end_pos(struct rchan_buf *buf, | |||
454 | * Reads count bytes or the number of bytes available in the | 465 | * Reads count bytes or the number of bytes available in the |
455 | * current sub-buffer being read, whichever is smaller. | 466 | * current sub-buffer being read, whichever is smaller. |
456 | */ | 467 | */ |
457 | static ssize_t relayfs_read(struct file *filp, | 468 | static ssize_t relay_file_read(struct file *filp, |
458 | char __user *buffer, | 469 | char __user *buffer, |
459 | size_t count, | 470 | size_t count, |
460 | loff_t *ppos) | 471 | loff_t *ppos) |
461 | { | 472 | { |
473 | struct rchan_buf *buf = filp->private_data; | ||
462 | struct inode *inode = filp->f_dentry->d_inode; | 474 | struct inode *inode = filp->f_dentry->d_inode; |
463 | struct rchan_buf *buf = RELAYFS_I(inode)->buf; | ||
464 | size_t read_start, avail; | 475 | size_t read_start, avail; |
465 | ssize_t ret = 0; | 476 | ssize_t ret = 0; |
466 | void *from; | 477 | void *from; |
467 | 478 | ||
468 | down(&inode->i_sem); | 479 | mutex_lock(&inode->i_mutex); |
469 | if(!relayfs_read_avail(buf, *ppos)) | 480 | if(!relay_file_read_avail(buf, *ppos)) |
470 | goto out; | 481 | goto out; |
471 | 482 | ||
472 | read_start = relayfs_read_start_pos(*ppos, buf); | 483 | read_start = relay_file_read_start_pos(*ppos, buf); |
473 | avail = relayfs_read_subbuf_avail(read_start, buf); | 484 | avail = relay_file_read_subbuf_avail(read_start, buf); |
474 | if (!avail) | 485 | if (!avail) |
475 | goto out; | 486 | goto out; |
476 | 487 | ||
@@ -480,58 +491,25 @@ static ssize_t relayfs_read(struct file *filp, | |||
480 | ret = -EFAULT; | 491 | ret = -EFAULT; |
481 | goto out; | 492 | goto out; |
482 | } | 493 | } |
483 | relayfs_read_consume(buf, read_start, count); | 494 | relay_file_read_consume(buf, read_start, count); |
484 | *ppos = relayfs_read_end_pos(buf, read_start, count); | 495 | *ppos = relay_file_read_end_pos(buf, read_start, count); |
485 | out: | 496 | out: |
486 | up(&inode->i_sem); | 497 | mutex_unlock(&inode->i_mutex); |
487 | return ret; | 498 | return ret; |
488 | } | 499 | } |
489 | 500 | ||
490 | /** | 501 | struct file_operations relay_file_operations = { |
491 | * relayfs alloc_inode() implementation | 502 | .open = relay_file_open, |
492 | */ | 503 | .poll = relay_file_poll, |
493 | static struct inode *relayfs_alloc_inode(struct super_block *sb) | 504 | .mmap = relay_file_mmap, |
494 | { | 505 | .read = relay_file_read, |
495 | struct relayfs_inode_info *p = kmem_cache_alloc(relayfs_inode_cachep, SLAB_KERNEL); | ||
496 | if (!p) | ||
497 | return NULL; | ||
498 | p->buf = NULL; | ||
499 | |||
500 | return &p->vfs_inode; | ||
501 | } | ||
502 | |||
503 | /** | ||
504 | * relayfs destroy_inode() implementation | ||
505 | */ | ||
506 | static void relayfs_destroy_inode(struct inode *inode) | ||
507 | { | ||
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)); | ||
512 | } | ||
513 | |||
514 | static void init_once(void *p, kmem_cache_t *cachep, unsigned long flags) | ||
515 | { | ||
516 | struct relayfs_inode_info *i = p; | ||
517 | if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) | ||
518 | inode_init_once(&i->vfs_inode); | ||
519 | } | ||
520 | |||
521 | struct file_operations relayfs_file_operations = { | ||
522 | .open = relayfs_open, | ||
523 | .poll = relayfs_poll, | ||
524 | .mmap = relayfs_mmap, | ||
525 | .read = relayfs_read, | ||
526 | .llseek = no_llseek, | 506 | .llseek = no_llseek, |
527 | .release = relayfs_release, | 507 | .release = relay_file_release, |
528 | }; | 508 | }; |
529 | 509 | ||
530 | static struct super_operations relayfs_ops = { | 510 | static struct super_operations relayfs_ops = { |
531 | .statfs = simple_statfs, | 511 | .statfs = simple_statfs, |
532 | .drop_inode = generic_delete_inode, | 512 | .drop_inode = generic_delete_inode, |
533 | .alloc_inode = relayfs_alloc_inode, | ||
534 | .destroy_inode = relayfs_destroy_inode, | ||
535 | }; | 513 | }; |
536 | 514 | ||
537 | static int relayfs_fill_super(struct super_block * sb, void * data, int silent) | 515 | static int relayfs_fill_super(struct super_block * sb, void * data, int silent) |
@@ -544,7 +522,7 @@ static int relayfs_fill_super(struct super_block * sb, void * data, int silent) | |||
544 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 522 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
545 | sb->s_magic = RELAYFS_MAGIC; | 523 | sb->s_magic = RELAYFS_MAGIC; |
546 | sb->s_op = &relayfs_ops; | 524 | sb->s_op = &relayfs_ops; |
547 | inode = relayfs_get_inode(sb, mode, NULL); | 525 | inode = relayfs_get_inode(sb, mode, NULL, NULL); |
548 | 526 | ||
549 | if (!inode) | 527 | if (!inode) |
550 | return -ENOMEM; | 528 | return -ENOMEM; |
@@ -575,33 +553,27 @@ static struct file_system_type relayfs_fs_type = { | |||
575 | 553 | ||
576 | static int __init init_relayfs_fs(void) | 554 | static int __init init_relayfs_fs(void) |
577 | { | 555 | { |
578 | int err; | 556 | return register_filesystem(&relayfs_fs_type); |
579 | |||
580 | relayfs_inode_cachep = kmem_cache_create("relayfs_inode_cache", | ||
581 | sizeof(struct relayfs_inode_info), 0, | ||
582 | 0, init_once, NULL); | ||
583 | if (!relayfs_inode_cachep) | ||
584 | return -ENOMEM; | ||
585 | |||
586 | err = register_filesystem(&relayfs_fs_type); | ||
587 | if (err) | ||
588 | kmem_cache_destroy(relayfs_inode_cachep); | ||
589 | |||
590 | return err; | ||
591 | } | 557 | } |
592 | 558 | ||
593 | static void __exit exit_relayfs_fs(void) | 559 | static void __exit exit_relayfs_fs(void) |
594 | { | 560 | { |
561 | |||
562 | |||
563 | |||
564 | |||
565 | |||
595 | unregister_filesystem(&relayfs_fs_type); | 566 | unregister_filesystem(&relayfs_fs_type); |
596 | kmem_cache_destroy(relayfs_inode_cachep); | ||
597 | } | 567 | } |
598 | 568 | ||
599 | module_init(init_relayfs_fs) | 569 | module_init(init_relayfs_fs) |
600 | module_exit(exit_relayfs_fs) | 570 | module_exit(exit_relayfs_fs) |
601 | 571 | ||
602 | EXPORT_SYMBOL_GPL(relayfs_file_operations); | 572 | EXPORT_SYMBOL_GPL(relay_file_operations); |
603 | EXPORT_SYMBOL_GPL(relayfs_create_dir); | 573 | EXPORT_SYMBOL_GPL(relayfs_create_dir); |
604 | EXPORT_SYMBOL_GPL(relayfs_remove_dir); | 574 | EXPORT_SYMBOL_GPL(relayfs_remove_dir); |
575 | EXPORT_SYMBOL_GPL(relayfs_create_file); | ||
576 | EXPORT_SYMBOL_GPL(relayfs_remove_file); | ||
605 | 577 | ||
606 | MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>"); | 578 | MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>"); |
607 | MODULE_DESCRIPTION("Relay Filesystem"); | 579 | MODULE_DESCRIPTION("Relay Filesystem"); |
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c index 16446a15c96d..abf3ceaace49 100644 --- a/fs/relayfs/relay.c +++ b/fs/relayfs/relay.c | |||
@@ -80,11 +80,34 @@ static void buf_unmapped_default_callback(struct rchan_buf *buf, | |||
80 | { | 80 | { |
81 | } | 81 | } |
82 | 82 | ||
83 | /* | ||
84 | * create_buf_file_create() default callback. Creates file to represent buf. | ||
85 | */ | ||
86 | static struct dentry *create_buf_file_default_callback(const char *filename, | ||
87 | struct dentry *parent, | ||
88 | int mode, | ||
89 | struct rchan_buf *buf, | ||
90 | int *is_global) | ||
91 | { | ||
92 | return relayfs_create_file(filename, parent, mode, | ||
93 | &relay_file_operations, buf); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * remove_buf_file() default callback. Removes file representing relay buffer. | ||
98 | */ | ||
99 | static int remove_buf_file_default_callback(struct dentry *dentry) | ||
100 | { | ||
101 | return relayfs_remove(dentry); | ||
102 | } | ||
103 | |||
83 | /* relay channel default callbacks */ | 104 | /* relay channel default callbacks */ |
84 | static struct rchan_callbacks default_channel_callbacks = { | 105 | static struct rchan_callbacks default_channel_callbacks = { |
85 | .subbuf_start = subbuf_start_default_callback, | 106 | .subbuf_start = subbuf_start_default_callback, |
86 | .buf_mapped = buf_mapped_default_callback, | 107 | .buf_mapped = buf_mapped_default_callback, |
87 | .buf_unmapped = buf_unmapped_default_callback, | 108 | .buf_unmapped = buf_unmapped_default_callback, |
109 | .create_buf_file = create_buf_file_default_callback, | ||
110 | .remove_buf_file = remove_buf_file_default_callback, | ||
88 | }; | 111 | }; |
89 | 112 | ||
90 | /** | 113 | /** |
@@ -148,14 +171,16 @@ static inline void __relay_reset(struct rchan_buf *buf, unsigned int init) | |||
148 | void relay_reset(struct rchan *chan) | 171 | void relay_reset(struct rchan *chan) |
149 | { | 172 | { |
150 | unsigned int i; | 173 | unsigned int i; |
174 | struct rchan_buf *prev = NULL; | ||
151 | 175 | ||
152 | if (!chan) | 176 | if (!chan) |
153 | return; | 177 | return; |
154 | 178 | ||
155 | for (i = 0; i < NR_CPUS; i++) { | 179 | for (i = 0; i < NR_CPUS; i++) { |
156 | if (!chan->buf[i]) | 180 | if (!chan->buf[i] || chan->buf[i] == prev) |
157 | continue; | 181 | break; |
158 | __relay_reset(chan->buf[i], 0); | 182 | __relay_reset(chan->buf[i], 0); |
183 | prev = chan->buf[i]; | ||
159 | } | 184 | } |
160 | } | 185 | } |
161 | 186 | ||
@@ -166,17 +191,27 @@ void relay_reset(struct rchan *chan) | |||
166 | */ | 191 | */ |
167 | static struct rchan_buf *relay_open_buf(struct rchan *chan, | 192 | static struct rchan_buf *relay_open_buf(struct rchan *chan, |
168 | const char *filename, | 193 | const char *filename, |
169 | struct dentry *parent) | 194 | struct dentry *parent, |
195 | int *is_global) | ||
170 | { | 196 | { |
171 | struct rchan_buf *buf; | 197 | struct rchan_buf *buf; |
172 | struct dentry *dentry; | 198 | struct dentry *dentry; |
173 | 199 | ||
200 | if (*is_global) | ||
201 | return chan->buf[0]; | ||
202 | |||
203 | buf = relay_create_buf(chan); | ||
204 | if (!buf) | ||
205 | return NULL; | ||
206 | |||
174 | /* Create file in fs */ | 207 | /* Create file in fs */ |
175 | dentry = relayfs_create_file(filename, parent, S_IRUSR, chan); | 208 | dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR, |
176 | if (!dentry) | 209 | buf, is_global); |
210 | if (!dentry) { | ||
211 | relay_destroy_buf(buf); | ||
177 | return NULL; | 212 | return NULL; |
213 | } | ||
178 | 214 | ||
179 | buf = RELAYFS_I(dentry->d_inode)->buf; | ||
180 | buf->dentry = dentry; | 215 | buf->dentry = dentry; |
181 | __relay_reset(buf, 1); | 216 | __relay_reset(buf, 1); |
182 | 217 | ||
@@ -214,6 +249,10 @@ static inline void setup_callbacks(struct rchan *chan, | |||
214 | cb->buf_mapped = buf_mapped_default_callback; | 249 | cb->buf_mapped = buf_mapped_default_callback; |
215 | if (!cb->buf_unmapped) | 250 | if (!cb->buf_unmapped) |
216 | cb->buf_unmapped = buf_unmapped_default_callback; | 251 | cb->buf_unmapped = buf_unmapped_default_callback; |
252 | if (!cb->create_buf_file) | ||
253 | cb->create_buf_file = create_buf_file_default_callback; | ||
254 | if (!cb->remove_buf_file) | ||
255 | cb->remove_buf_file = remove_buf_file_default_callback; | ||
217 | chan->cb = cb; | 256 | chan->cb = cb; |
218 | } | 257 | } |
219 | 258 | ||
@@ -241,6 +280,7 @@ struct rchan *relay_open(const char *base_filename, | |||
241 | unsigned int i; | 280 | unsigned int i; |
242 | struct rchan *chan; | 281 | struct rchan *chan; |
243 | char *tmpname; | 282 | char *tmpname; |
283 | int is_global = 0; | ||
244 | 284 | ||
245 | if (!base_filename) | 285 | if (!base_filename) |
246 | return NULL; | 286 | return NULL; |
@@ -265,7 +305,8 @@ struct rchan *relay_open(const char *base_filename, | |||
265 | 305 | ||
266 | for_each_online_cpu(i) { | 306 | for_each_online_cpu(i) { |
267 | sprintf(tmpname, "%s%d", base_filename, i); | 307 | sprintf(tmpname, "%s%d", base_filename, i); |
268 | chan->buf[i] = relay_open_buf(chan, tmpname, parent); | 308 | chan->buf[i] = relay_open_buf(chan, tmpname, parent, |
309 | &is_global); | ||
269 | chan->buf[i]->cpu = i; | 310 | chan->buf[i]->cpu = i; |
270 | if (!chan->buf[i]) | 311 | if (!chan->buf[i]) |
271 | goto free_bufs; | 312 | goto free_bufs; |
@@ -279,6 +320,8 @@ free_bufs: | |||
279 | if (!chan->buf[i]) | 320 | if (!chan->buf[i]) |
280 | break; | 321 | break; |
281 | relay_close_buf(chan->buf[i]); | 322 | relay_close_buf(chan->buf[i]); |
323 | if (is_global) | ||
324 | break; | ||
282 | } | 325 | } |
283 | kfree(tmpname); | 326 | kfree(tmpname); |
284 | 327 | ||
@@ -333,8 +376,7 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length) | |||
333 | return length; | 376 | return length; |
334 | 377 | ||
335 | toobig: | 378 | toobig: |
336 | printk(KERN_WARNING "relayfs: event too large (%Zd)\n", length); | 379 | buf->chan->last_toobig = length; |
337 | WARN_ON(1); | ||
338 | return 0; | 380 | return 0; |
339 | } | 381 | } |
340 | 382 | ||
@@ -389,16 +431,23 @@ void relay_destroy_channel(struct kref *kref) | |||
389 | void relay_close(struct rchan *chan) | 431 | void relay_close(struct rchan *chan) |
390 | { | 432 | { |
391 | unsigned int i; | 433 | unsigned int i; |
434 | struct rchan_buf *prev = NULL; | ||
392 | 435 | ||
393 | if (!chan) | 436 | if (!chan) |
394 | return; | 437 | return; |
395 | 438 | ||
396 | for (i = 0; i < NR_CPUS; i++) { | 439 | for (i = 0; i < NR_CPUS; i++) { |
397 | if (!chan->buf[i]) | 440 | if (!chan->buf[i] || chan->buf[i] == prev) |
398 | continue; | 441 | break; |
399 | relay_close_buf(chan->buf[i]); | 442 | relay_close_buf(chan->buf[i]); |
443 | prev = chan->buf[i]; | ||
400 | } | 444 | } |
401 | 445 | ||
446 | if (chan->last_toobig) | ||
447 | printk(KERN_WARNING "relayfs: one or more items not logged " | ||
448 | "[item size (%Zd) > sub-buffer size (%Zd)]\n", | ||
449 | chan->last_toobig, chan->subbuf_size); | ||
450 | |||
402 | kref_put(&chan->kref, relay_destroy_channel); | 451 | kref_put(&chan->kref, relay_destroy_channel); |
403 | } | 452 | } |
404 | 453 | ||
@@ -411,14 +460,16 @@ void relay_close(struct rchan *chan) | |||
411 | void relay_flush(struct rchan *chan) | 460 | void relay_flush(struct rchan *chan) |
412 | { | 461 | { |
413 | unsigned int i; | 462 | unsigned int i; |
463 | struct rchan_buf *prev = NULL; | ||
414 | 464 | ||
415 | if (!chan) | 465 | if (!chan) |
416 | return; | 466 | return; |
417 | 467 | ||
418 | for (i = 0; i < NR_CPUS; i++) { | 468 | for (i = 0; i < NR_CPUS; i++) { |
419 | if (!chan->buf[i]) | 469 | if (!chan->buf[i] || chan->buf[i] == prev) |
420 | continue; | 470 | break; |
421 | relay_switch_subbuf(chan->buf[i], 0); | 471 | relay_switch_subbuf(chan->buf[i], 0); |
472 | prev = chan->buf[i]; | ||
422 | } | 473 | } |
423 | } | 474 | } |
424 | 475 | ||
diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h index 703503fa22b6..0993d3e5753b 100644 --- a/fs/relayfs/relay.h +++ b/fs/relayfs/relay.h | |||
@@ -1,10 +1,6 @@ | |||
1 | #ifndef _RELAY_H | 1 | #ifndef _RELAY_H |
2 | #define _RELAY_H | 2 | #define _RELAY_H |
3 | 3 | ||
4 | struct dentry *relayfs_create_file(const char *name, | ||
5 | struct dentry *parent, | ||
6 | int mode, | ||
7 | struct rchan *chan); | ||
8 | extern int relayfs_remove(struct dentry *dentry); | 4 | extern int relayfs_remove(struct dentry *dentry); |
9 | extern int relay_buf_empty(struct rchan_buf *buf); | 5 | extern int relay_buf_empty(struct rchan_buf *buf); |
10 | extern void relay_destroy_channel(struct kref *kref); | 6 | extern void relay_destroy_channel(struct kref *kref); |