diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-10 16:39:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-10 16:39:07 -0400 |
commit | 999646e3f953c734f8eced551fc1ea28719ba7a7 (patch) | |
tree | 303e37c8a848534331640d7a5c7fd177537534b1 | |
parent | 76b0c26af2736b7e5b87e6ed7ab63901483d5736 (diff) | |
parent | 4faa3c8150c1d4f7b38d962eda7851083e218e3f (diff) |
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()
-rw-r--r-- | block/cfq-iosched.c | 9 | ||||
-rw-r--r-- | fs/splice.c | 31 |
2 files changed, 12 insertions, 28 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index f26da2bfcc15..f4e1006c253d 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -1214,6 +1214,8 @@ static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
1214 | static void __cfq_exit_single_io_context(struct cfq_data *cfqd, | 1214 | static void __cfq_exit_single_io_context(struct cfq_data *cfqd, |
1215 | struct cfq_io_context *cic) | 1215 | struct cfq_io_context *cic) |
1216 | { | 1216 | { |
1217 | struct io_context *ioc = cic->ioc; | ||
1218 | |||
1217 | list_del_init(&cic->queue_list); | 1219 | list_del_init(&cic->queue_list); |
1218 | 1220 | ||
1219 | /* | 1221 | /* |
@@ -1223,6 +1225,9 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, | |||
1223 | cic->dead_key = (unsigned long) cic->key; | 1225 | cic->dead_key = (unsigned long) cic->key; |
1224 | cic->key = NULL; | 1226 | cic->key = NULL; |
1225 | 1227 | ||
1228 | if (ioc->ioc_data == cic) | ||
1229 | rcu_assign_pointer(ioc->ioc_data, NULL); | ||
1230 | |||
1226 | if (cic->cfqq[ASYNC]) { | 1231 | if (cic->cfqq[ASYNC]) { |
1227 | cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]); | 1232 | cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]); |
1228 | cic->cfqq[ASYNC] = NULL; | 1233 | cic->cfqq[ASYNC] = NULL; |
@@ -1255,7 +1260,6 @@ static void cfq_exit_single_io_context(struct io_context *ioc, | |||
1255 | */ | 1260 | */ |
1256 | static void cfq_exit_io_context(struct io_context *ioc) | 1261 | static void cfq_exit_io_context(struct io_context *ioc) |
1257 | { | 1262 | { |
1258 | rcu_assign_pointer(ioc->ioc_data, NULL); | ||
1259 | call_for_each_cic(ioc, cfq_exit_single_io_context); | 1263 | call_for_each_cic(ioc, cfq_exit_single_io_context); |
1260 | } | 1264 | } |
1261 | 1265 | ||
@@ -1478,8 +1482,7 @@ cfq_drop_dead_cic(struct cfq_data *cfqd, struct io_context *ioc, | |||
1478 | 1482 | ||
1479 | spin_lock_irqsave(&ioc->lock, flags); | 1483 | spin_lock_irqsave(&ioc->lock, flags); |
1480 | 1484 | ||
1481 | if (ioc->ioc_data == cic) | 1485 | BUG_ON(ioc->ioc_data == cic); |
1482 | rcu_assign_pointer(ioc->ioc_data, NULL); | ||
1483 | 1486 | ||
1484 | radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd); | 1487 | radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd); |
1485 | hlist_del_rcu(&cic->cic_list); | 1488 | hlist_del_rcu(&cic->cic_list); |
diff --git a/fs/splice.c b/fs/splice.c index a861bb318ac8..eeb1a86a7014 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -370,8 +370,10 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
370 | * for an in-flight io page | 370 | * for an in-flight io page |
371 | */ | 371 | */ |
372 | if (flags & SPLICE_F_NONBLOCK) { | 372 | if (flags & SPLICE_F_NONBLOCK) { |
373 | if (TestSetPageLocked(page)) | 373 | if (TestSetPageLocked(page)) { |
374 | error = -EAGAIN; | ||
374 | break; | 375 | break; |
376 | } | ||
375 | } else | 377 | } else |
376 | lock_page(page); | 378 | lock_page(page); |
377 | 379 | ||
@@ -479,9 +481,8 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, | |||
479 | struct pipe_inode_info *pipe, size_t len, | 481 | struct pipe_inode_info *pipe, size_t len, |
480 | unsigned int flags) | 482 | unsigned int flags) |
481 | { | 483 | { |
482 | ssize_t spliced; | ||
483 | int ret; | ||
484 | loff_t isize, left; | 484 | loff_t isize, left; |
485 | int ret; | ||
485 | 486 | ||
486 | isize = i_size_read(in->f_mapping->host); | 487 | isize = i_size_read(in->f_mapping->host); |
487 | if (unlikely(*ppos >= isize)) | 488 | if (unlikely(*ppos >= isize)) |
@@ -491,29 +492,9 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, | |||
491 | if (unlikely(left < len)) | 492 | if (unlikely(left < len)) |
492 | len = left; | 493 | len = left; |
493 | 494 | ||
494 | ret = 0; | 495 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); |
495 | spliced = 0; | 496 | if (ret > 0) |
496 | while (len && !spliced) { | ||
497 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); | ||
498 | |||
499 | if (ret < 0) | ||
500 | break; | ||
501 | else if (!ret) { | ||
502 | if (spliced) | ||
503 | break; | ||
504 | if (flags & SPLICE_F_NONBLOCK) { | ||
505 | ret = -EAGAIN; | ||
506 | break; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | *ppos += ret; | 497 | *ppos += ret; |
511 | len -= ret; | ||
512 | spliced += ret; | ||
513 | } | ||
514 | |||
515 | if (spliced) | ||
516 | return spliced; | ||
517 | 498 | ||
518 | return ret; | 499 | return ret; |
519 | } | 500 | } |