diff options
| author | Jonathan Corbet <corbet@lwn.net> | 2008-07-14 15:29:34 -0600 | 
|---|---|---|
| committer | Jonathan Corbet <corbet@lwn.net> | 2008-07-14 15:29:34 -0600 | 
| commit | 2fceef397f9880b212a74c418290ce69e7ac00eb (patch) | |
| tree | d9cc09ab992825ef7fede4a688103503e3caf655 /fs/splice.c | |
| parent | feae1ef116ed381625d3731c5ae4f4ebcb3fa302 (diff) | |
| parent | bce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff) | |
| download | linux-2fceef397f9880b212a74c418290ce69e7ac00eb.tar.bz2 | |
Merge commit 'v2.6.26' into bkl-removal
Diffstat (limited to 'fs/splice.c')
| -rw-r--r-- | fs/splice.c | 17 | 
1 files changed, 11 insertions, 6 deletions
| diff --git a/fs/splice.c b/fs/splice.c index 78150038b584..aa5f6f60b305 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -58,8 +58,8 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe,  		 */  		wait_on_page_writeback(page); -		if (PagePrivate(page)) -			try_to_release_page(page, GFP_KERNEL); +		if (PagePrivate(page) && !try_to_release_page(page, GFP_KERNEL)) +			goto out_unlock;  		/*  		 * If we succeeded in removing the mapping, set LRU flag @@ -75,6 +75,7 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe,  	 * Raced with truncate or failed to remove page from current  	 * address space, unlock and return failure.  	 */ +out_unlock:  	unlock_page(page);  	return 1;  } @@ -983,7 +984,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,  	while (len) {  		size_t read_len; -		loff_t pos = sd->pos; +		loff_t pos = sd->pos, prev_pos = pos;  		ret = do_splice_to(in, &pos, pipe, len, flags);  		if (unlikely(ret <= 0)) @@ -998,15 +999,19 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,  		 * could get stuck data in the internal pipe:  		 */  		ret = actor(pipe, sd); -		if (unlikely(ret <= 0)) +		if (unlikely(ret <= 0)) { +			sd->pos = prev_pos;  			goto out_release; +		}  		bytes += ret;  		len -= ret;  		sd->pos = pos; -		if (ret < read_len) +		if (ret < read_len) { +			sd->pos = prev_pos + ret;  			goto out_release; +		}  	}  done: @@ -1072,7 +1077,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,  	ret = splice_direct_to_actor(in, &sd, direct_splice_actor);  	if (ret > 0) -		*ppos += ret; +		*ppos = sd.pos;  	return ret;  } |