Merge branch 'splice-2.6.22' of git://git.kernel.dk/data/git/linux-2.6-block
* 'splice-2.6.22' of git://git.kernel.dk/data/git/linux-2.6-block: splice: __generic_file_splice_read: fix read/truncate race splice: __generic_file_splice_read: fix i_size_read() length checks splice: move balance_dirty_pages_ratelimited() outside of splice actor pipe: move pipe_inode_info structure decleration up before it's used splice: remove do_splice_direct() symbol export splice: move inode size check into generic_file_splice_read()
This commit is contained in:
commit
5212c555be
70
fs/splice.c
70
fs/splice.c
|
@ -272,7 +272,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
|
|||
struct page *page;
|
||||
pgoff_t index, end_index;
|
||||
loff_t isize;
|
||||
size_t total_len;
|
||||
int error, page_nr;
|
||||
struct splice_pipe_desc spd = {
|
||||
.pages = pages,
|
||||
|
@ -298,7 +297,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
|
|||
* Now fill in the holes:
|
||||
*/
|
||||
error = 0;
|
||||
total_len = 0;
|
||||
|
||||
/*
|
||||
* Lookup the (hopefully) full range of pages we need.
|
||||
|
@ -415,43 +413,47 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
|
|||
|
||||
break;
|
||||
}
|
||||
}
|
||||
fill_it:
|
||||
/*
|
||||
* i_size must be checked after PageUptodate.
|
||||
*/
|
||||
isize = i_size_read(mapping->host);
|
||||
end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
|
||||
if (unlikely(!isize || index > end_index))
|
||||
break;
|
||||
|
||||
/*
|
||||
* if this is the last page, see if we need to shrink
|
||||
* the length and stop
|
||||
*/
|
||||
if (end_index == index) {
|
||||
unsigned int plen;
|
||||
|
||||
/*
|
||||
* i_size must be checked after ->readpage().
|
||||
* max good bytes in this page
|
||||
*/
|
||||
isize = i_size_read(mapping->host);
|
||||
end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
|
||||
if (unlikely(!isize || index > end_index))
|
||||
plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
|
||||
if (plen <= loff)
|
||||
break;
|
||||
|
||||
/*
|
||||
* if this is the last page, see if we need to shrink
|
||||
* the length and stop
|
||||
* force quit after adding this page
|
||||
*/
|
||||
if (end_index == index) {
|
||||
loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK);
|
||||
if (total_len + loff > isize)
|
||||
break;
|
||||
/*
|
||||
* force quit after adding this page
|
||||
*/
|
||||
len = this_len;
|
||||
this_len = min(this_len, loff);
|
||||
loff = 0;
|
||||
}
|
||||
this_len = min(this_len, plen - loff);
|
||||
len = this_len;
|
||||
}
|
||||
fill_it:
|
||||
|
||||
partial[page_nr].offset = loff;
|
||||
partial[page_nr].len = this_len;
|
||||
len -= this_len;
|
||||
total_len += this_len;
|
||||
loff = 0;
|
||||
spd.nr_pages++;
|
||||
index++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release any pages at the end, if we quit early. 'i' is how far
|
||||
* Release any pages at the end, if we quit early. 'page_nr' is how far
|
||||
* we got, 'nr_pages' is how many pages are in the map.
|
||||
*/
|
||||
while (page_nr < nr_pages)
|
||||
|
@ -478,10 +480,18 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
|
|||
{
|
||||
ssize_t spliced;
|
||||
int ret;
|
||||
loff_t isize, left;
|
||||
|
||||
isize = i_size_read(in->f_mapping->host);
|
||||
if (unlikely(*ppos >= isize))
|
||||
return 0;
|
||||
|
||||
left = isize - *ppos;
|
||||
if (unlikely(left < len))
|
||||
len = left;
|
||||
|
||||
ret = 0;
|
||||
spliced = 0;
|
||||
|
||||
while (len) {
|
||||
ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
|
||||
|
||||
|
@ -644,7 +654,6 @@ find_page:
|
|||
* accessed, we are now done!
|
||||
*/
|
||||
mark_page_accessed(page);
|
||||
balance_dirty_pages_ratelimited(mapping);
|
||||
out:
|
||||
page_cache_release(page);
|
||||
unlock_page(page);
|
||||
|
@ -815,6 +824,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
|
|||
if (err)
|
||||
ret = err;
|
||||
}
|
||||
balance_dirty_pages_ratelimited(mapping);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -868,6 +878,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
|
|||
if (err)
|
||||
ret = err;
|
||||
}
|
||||
balance_dirty_pages_ratelimited(mapping);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -922,7 +933,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
|
|||
struct pipe_inode_info *pipe, size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
loff_t isize, left;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!in->f_op || !in->f_op->splice_read))
|
||||
|
@ -935,14 +945,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
|
|||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
||||
isize = i_size_read(in->f_mapping->host);
|
||||
if (unlikely(*ppos >= isize))
|
||||
return 0;
|
||||
|
||||
left = isize - *ppos;
|
||||
if (unlikely(left < len))
|
||||
len = left;
|
||||
|
||||
return in->f_op->splice_read(in, ppos, pipe, len, flags);
|
||||
}
|
||||
|
||||
|
@ -1058,8 +1060,6 @@ out_release:
|
|||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(do_splice_direct);
|
||||
|
||||
/*
|
||||
* After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
|
||||
* location, so checking ->i_pipe is not enough to verify that this is a
|
||||
|
|
|
@ -16,6 +16,21 @@ struct pipe_buffer {
|
|||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct pipe_inode_info {
|
||||
wait_queue_head_t wait;
|
||||
unsigned int nrbufs, curbuf;
|
||||
struct page *tmp_page;
|
||||
unsigned int readers;
|
||||
unsigned int writers;
|
||||
unsigned int waiting_writers;
|
||||
unsigned int r_counter;
|
||||
unsigned int w_counter;
|
||||
struct fasync_struct *fasync_readers;
|
||||
struct fasync_struct *fasync_writers;
|
||||
struct inode *inode;
|
||||
struct pipe_buffer bufs[PIPE_BUFFERS];
|
||||
};
|
||||
|
||||
/*
|
||||
* Note on the nesting of these functions:
|
||||
*
|
||||
|
@ -38,21 +53,6 @@ struct pipe_buf_operations {
|
|||
void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
|
||||
};
|
||||
|
||||
struct pipe_inode_info {
|
||||
wait_queue_head_t wait;
|
||||
unsigned int nrbufs, curbuf;
|
||||
struct page *tmp_page;
|
||||
unsigned int readers;
|
||||
unsigned int writers;
|
||||
unsigned int waiting_writers;
|
||||
unsigned int r_counter;
|
||||
unsigned int w_counter;
|
||||
struct fasync_struct *fasync_readers;
|
||||
struct fasync_struct *fasync_writers;
|
||||
struct inode *inode;
|
||||
struct pipe_buffer bufs[PIPE_BUFFERS];
|
||||
};
|
||||
|
||||
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
|
||||
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */
|
||||
#define PIPE_SIZE PAGE_SIZE
|
||||
|
|
Loading…
Reference in New Issue