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 | } |
