mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/linux-2.6-block: cfq-iosched: do not leak ioc_data across iosched switches splice: fix infinite loop in generic_file_splice_read()
This commit is contained in:
commit
999646e3f9
@ -1214,6 +1214,8 @@ static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
|
||||
static void __cfq_exit_single_io_context(struct cfq_data *cfqd,
|
||||
struct cfq_io_context *cic)
|
||||
{
|
||||
struct io_context *ioc = cic->ioc;
|
||||
|
||||
list_del_init(&cic->queue_list);
|
||||
|
||||
/*
|
||||
@ -1223,6 +1225,9 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd,
|
||||
cic->dead_key = (unsigned long) cic->key;
|
||||
cic->key = NULL;
|
||||
|
||||
if (ioc->ioc_data == cic)
|
||||
rcu_assign_pointer(ioc->ioc_data, NULL);
|
||||
|
||||
if (cic->cfqq[ASYNC]) {
|
||||
cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]);
|
||||
cic->cfqq[ASYNC] = NULL;
|
||||
@ -1255,7 +1260,6 @@ static void cfq_exit_single_io_context(struct io_context *ioc,
|
||||
*/
|
||||
static void cfq_exit_io_context(struct io_context *ioc)
|
||||
{
|
||||
rcu_assign_pointer(ioc->ioc_data, NULL);
|
||||
call_for_each_cic(ioc, cfq_exit_single_io_context);
|
||||
}
|
||||
|
||||
@ -1478,8 +1482,7 @@ cfq_drop_dead_cic(struct cfq_data *cfqd, struct io_context *ioc,
|
||||
|
||||
spin_lock_irqsave(&ioc->lock, flags);
|
||||
|
||||
if (ioc->ioc_data == cic)
|
||||
rcu_assign_pointer(ioc->ioc_data, NULL);
|
||||
BUG_ON(ioc->ioc_data == cic);
|
||||
|
||||
radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd);
|
||||
hlist_del_rcu(&cic->cic_list);
|
||||
|
31
fs/splice.c
31
fs/splice.c
@ -370,8 +370,10 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
|
||||
* for an in-flight io page
|
||||
*/
|
||||
if (flags & SPLICE_F_NONBLOCK) {
|
||||
if (TestSetPageLocked(page))
|
||||
if (TestSetPageLocked(page)) {
|
||||
error = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
lock_page(page);
|
||||
|
||||
@ -479,9 +481,8 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
|
||||
struct pipe_inode_info *pipe, size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
ssize_t spliced;
|
||||
int ret;
|
||||
loff_t isize, left;
|
||||
int ret;
|
||||
|
||||
isize = i_size_read(in->f_mapping->host);
|
||||
if (unlikely(*ppos >= isize))
|
||||
@ -491,29 +492,9 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
|
||||
if (unlikely(left < len))
|
||||
len = left;
|
||||
|
||||
ret = 0;
|
||||
spliced = 0;
|
||||
while (len && !spliced) {
|
||||
ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
|
||||
|
||||
if (ret < 0)
|
||||
break;
|
||||
else if (!ret) {
|
||||
if (spliced)
|
||||
break;
|
||||
if (flags & SPLICE_F_NONBLOCK) {
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
|
||||
if (ret > 0)
|
||||
*ppos += ret;
|
||||
len -= ret;
|
||||
spliced += ret;
|
||||
}
|
||||
|
||||
if (spliced)
|
||||
return spliced;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user