Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 143335
b: refs/heads/master
c: 328eaab
h: refs/heads/master
i:
  143333: e648ab0
  143331: 5a77f58
  143327: be3d457
v: v3
  • Loading branch information
Miklos Szeredi authored and Jens Axboe committed Apr 15, 2009
1 parent 9c68c2c commit 237b2f2
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 23 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: eb443e5a25d43996deb62b9bcee1a4ce5dea2ead
refs/heads/master: 328eaaba4e41a04c1dc4679d65bea3fee4349d86
94 changes: 74 additions & 20 deletions trunk/fs/ocfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1912,45 +1912,99 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
return written ? written : ret;
}

static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
struct file *out,
struct splice_desc *sd)
{
int ret;

ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, &sd->pos,
sd->total_len, 0, NULL);
if (ret < 0) {
mlog_errno(ret);
return ret;
}

return splice_from_pipe_feed(pipe, sd, pipe_to_file);
}

static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
struct file *out,
loff_t *ppos,
size_t len,
unsigned int flags)
{
int ret;
struct inode *inode = out->f_path.dentry->d_inode;
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
struct splice_desc sd = {
.total_len = len,
.flags = flags,
.pos = *ppos,
.u.file = out,
};

mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe,
(unsigned int)len,
out->f_path.dentry->d_name.len,
out->f_path.dentry->d_name.name);

mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
if (pipe->inode)
mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT);

ret = ocfs2_rw_lock(inode, 1);
if (ret < 0) {
mlog_errno(ret);
goto out;
}
splice_from_pipe_begin(&sd);
do {
ret = splice_from_pipe_next(pipe, &sd);
if (ret <= 0)
break;

ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, ppos, len, 0,
NULL);
if (ret < 0) {
mlog_errno(ret);
goto out_unlock;
}
mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
ret = ocfs2_rw_lock(inode, 1);
if (ret < 0)
mlog_errno(ret);
else {
ret = ocfs2_splice_to_file(pipe, out, &sd);
ocfs2_rw_unlock(inode, 1);
}
mutex_unlock(&inode->i_mutex);
} while (ret > 0);
splice_from_pipe_end(pipe, &sd);

if (pipe->inode)
mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
ret = generic_file_splice_write_nolock(pipe, out, ppos, len, flags);
if (pipe->inode)
mutex_unlock(&pipe->inode->i_mutex);

out_unlock:
ocfs2_rw_unlock(inode, 1);
out:
mutex_unlock(&inode->i_mutex);
if (sd.num_spliced)
ret = sd.num_spliced;

if (ret > 0) {
unsigned long nr_pages;

*ppos += ret;
nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;

/*
* If file or inode is SYNC and we actually wrote some data,
* sync it.
*/
if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
int err;

mutex_lock(&inode->i_mutex);
err = ocfs2_rw_lock(inode, 1);
if (err < 0) {
mlog_errno(err);
} else {
err = generic_osync_inode(inode, mapping,
OSYNC_METADATA|OSYNC_DATA);
ocfs2_rw_unlock(inode, 1);
}
mutex_unlock(&inode->i_mutex);

if (err)
ret = err;
}
balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
}

mlog_exit(ret);
return ret;
Expand Down
5 changes: 3 additions & 2 deletions trunk/fs/splice.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,8 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe,
* SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create
* a new page in the output file page cache and fill/dirty that.
*/
static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
struct splice_desc *sd)
int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
struct splice_desc *sd)
{
struct file *file = sd->u.file;
struct address_space *mapping = file->f_mapping;
Expand Down Expand Up @@ -600,6 +600,7 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
out:
return ret;
}
EXPORT_SYMBOL(pipe_to_file);

static void wakeup_pipe_writers(struct pipe_inode_info *pipe)
{
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/splice.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ extern int splice_from_pipe_next(struct pipe_inode_info *,
extern void splice_from_pipe_begin(struct splice_desc *);
extern void splice_from_pipe_end(struct pipe_inode_info *,
struct splice_desc *);
extern int pipe_to_file(struct pipe_inode_info *, struct pipe_buffer *,
struct splice_desc *);

extern ssize_t splice_to_pipe(struct pipe_inode_info *,
struct splice_pipe_desc *);
Expand Down

0 comments on commit 237b2f2

Please sign in to comment.