Skip to content

Commit

Permalink
Merge branch 'splice' of git://brick.kernel.dk/data/git/linux-2.6-block
Browse files Browse the repository at this point in the history
* 'splice' of git://brick.kernel.dk/data/git/linux-2.6-block:
  [PATCH] vfs: add splice_write and splice_read to documentation
  [PATCH] Remove sys_ prefix of new syscalls from __NR_sys_*
  [PATCH] splice: warning fix
  [PATCH] another round of fs/pipe.c cleanups
  [PATCH] splice: comment styles
  [PATCH] splice: add Ingo as addition copyright holder
  [PATCH] splice: unlikely() optimizations
  [PATCH] splice: speedups and optimizations
  [PATCH] pipe.c/fifo.c code cleanups
  [PATCH] get rid of the PIPE_*() macros
  [PATCH] splice: speedup __generic_file_splice_read
  [PATCH] splice: add direct fd <-> fd splicing support
  [PATCH] splice: add optional input and output offsets
  [PATCH] introduce a "kernel-internal pipe object" abstraction
  [PATCH] splice: be smarter about calling do_page_cache_readahead()
  [PATCH] splice: optimize the splice buffer mapping
  [PATCH] splice: cleanup __generic_file_splice_read()
  [PATCH] splice: only call wake_up_interruptible() when we really have to
  [PATCH] splice: potential !page dereference
  [PATCH] splice: mark the io page as accessed
  • Loading branch information
Linus Torvalds committed Apr 11, 2006
2 parents 6dde432 + d1195c5 commit 88dd9c1
Show file tree
Hide file tree
Showing 16 changed files with 601 additions and 360 deletions.
12 changes: 11 additions & 1 deletion Documentation/filesystems/vfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ struct file_operations
----------------------

This describes how the VFS can manipulate an open file. As of kernel
2.6.13, the following members are defined:
2.6.17, the following members are defined:

struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
Expand Down Expand Up @@ -723,6 +723,10 @@ struct file_operations {
int (*check_flags)(int);
int (*dir_notify)(struct file *filp, unsigned long arg);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned
int);
ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned
int);
};

Again, all methods are called without any locks being held, unless
Expand Down Expand Up @@ -790,6 +794,12 @@ otherwise noted.

flock: called by the flock(2) system call

splice_write: called by the VFS to splice data from a pipe to a file. This
method is used by the splice(2) system call

splice_read: called by the VFS to splice data from file to a pipe. This
method is used by the splice(2) system call

Note that the file operations are implemented by the specific
filesystem in which the inode resides. When opening a device node
(character or block special) most filesystems will call special
Expand Down
65 changes: 35 additions & 30 deletions fs/fifo.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,35 @@
#include <linux/fs.h>
#include <linux/pipe_fs_i.h>

static void wait_for_partner(struct inode* inode, unsigned int* cnt)
static void wait_for_partner(struct inode* inode, unsigned int *cnt)
{
int cur = *cnt;
while(cur == *cnt) {
pipe_wait(inode);
if(signal_pending(current))

while (cur == *cnt) {
pipe_wait(inode->i_pipe);
if (signal_pending(current))
break;
}
}

static void wake_up_partner(struct inode* inode)
{
wake_up_interruptible(PIPE_WAIT(*inode));
wake_up_interruptible(&inode->i_pipe->wait);
}

static int fifo_open(struct inode *inode, struct file *filp)
{
struct pipe_inode_info *pipe;
int ret;

mutex_lock(PIPE_MUTEX(*inode));
if (!inode->i_pipe) {
mutex_lock(&inode->i_mutex);
pipe = inode->i_pipe;
if (!pipe) {
ret = -ENOMEM;
if(!pipe_new(inode))
pipe = alloc_pipe_info(inode);
if (!pipe)
goto err_nocleanup;
inode->i_pipe = pipe;
}
filp->f_version = 0;

Expand All @@ -53,18 +58,18 @@ static int fifo_open(struct inode *inode, struct file *filp)
* opened, even when there is no process writing the FIFO.
*/
filp->f_op = &read_fifo_fops;
PIPE_RCOUNTER(*inode)++;
if (PIPE_READERS(*inode)++ == 0)
pipe->r_counter++;
if (pipe->readers++ == 0)
wake_up_partner(inode);

if (!PIPE_WRITERS(*inode)) {
if (!pipe->writers) {
if ((filp->f_flags & O_NONBLOCK)) {
/* suppress POLLHUP until we have
* seen a writer */
filp->f_version = PIPE_WCOUNTER(*inode);
filp->f_version = pipe->w_counter;
} else
{
wait_for_partner(inode, &PIPE_WCOUNTER(*inode));
wait_for_partner(inode, &pipe->w_counter);
if(signal_pending(current))
goto err_rd;
}
Expand All @@ -78,16 +83,16 @@ static int fifo_open(struct inode *inode, struct file *filp)
* errno=ENXIO when there is no process reading the FIFO.
*/
ret = -ENXIO;
if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode))
if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
goto err;

filp->f_op = &write_fifo_fops;
PIPE_WCOUNTER(*inode)++;
if (!PIPE_WRITERS(*inode)++)
pipe->w_counter++;
if (!pipe->writers++)
wake_up_partner(inode);

if (!PIPE_READERS(*inode)) {
wait_for_partner(inode, &PIPE_RCOUNTER(*inode));
if (!pipe->readers) {
wait_for_partner(inode, &pipe->r_counter);
if (signal_pending(current))
goto err_wr;
}
Expand All @@ -102,11 +107,11 @@ static int fifo_open(struct inode *inode, struct file *filp)
*/
filp->f_op = &rdwr_fifo_fops;

PIPE_READERS(*inode)++;
PIPE_WRITERS(*inode)++;
PIPE_RCOUNTER(*inode)++;
PIPE_WCOUNTER(*inode)++;
if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1)
pipe->readers++;
pipe->writers++;
pipe->r_counter++;
pipe->w_counter++;
if (pipe->readers == 1 || pipe->writers == 1)
wake_up_partner(inode);
break;

Expand All @@ -116,27 +121,27 @@ static int fifo_open(struct inode *inode, struct file *filp)
}

/* Ok! */
mutex_unlock(PIPE_MUTEX(*inode));
mutex_unlock(&inode->i_mutex);
return 0;

err_rd:
if (!--PIPE_READERS(*inode))
wake_up_interruptible(PIPE_WAIT(*inode));
if (!--pipe->readers)
wake_up_interruptible(&pipe->wait);
ret = -ERESTARTSYS;
goto err;

err_wr:
if (!--PIPE_WRITERS(*inode))
wake_up_interruptible(PIPE_WAIT(*inode));
if (!--pipe->writers)
wake_up_interruptible(&pipe->wait);
ret = -ERESTARTSYS;
goto err;

err:
if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode))
if (!pipe->readers && !pipe->writers)
free_pipe_info(inode);

err_nocleanup:
mutex_unlock(PIPE_MUTEX(*inode));
mutex_unlock(&inode->i_mutex);
return ret;
}

Expand Down
Loading

0 comments on commit 88dd9c1

Please sign in to comment.