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()

+12 -28
+6 -3
block/cfq-iosched.c
··· 1214 static void __cfq_exit_single_io_context(struct cfq_data *cfqd, 1215 struct cfq_io_context *cic) 1216 { 1217 list_del_init(&cic->queue_list); 1218 1219 /* ··· 1224 smp_wmb(); 1225 cic->dead_key = (unsigned long) cic->key; 1226 cic->key = NULL; 1227 1228 if (cic->cfqq[ASYNC]) { 1229 cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]); ··· 1260 */ 1261 static void cfq_exit_io_context(struct io_context *ioc) 1262 { 1263 - rcu_assign_pointer(ioc->ioc_data, NULL); 1264 call_for_each_cic(ioc, cfq_exit_single_io_context); 1265 } 1266 ··· 1482 1483 spin_lock_irqsave(&ioc->lock, flags); 1484 1485 - if (ioc->ioc_data == cic) 1486 - rcu_assign_pointer(ioc->ioc_data, NULL); 1487 1488 radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd); 1489 hlist_del_rcu(&cic->cic_list);
··· 1214 static void __cfq_exit_single_io_context(struct cfq_data *cfqd, 1215 struct cfq_io_context *cic) 1216 { 1217 + struct io_context *ioc = cic->ioc; 1218 + 1219 list_del_init(&cic->queue_list); 1220 1221 /* ··· 1222 smp_wmb(); 1223 cic->dead_key = (unsigned long) cic->key; 1224 cic->key = NULL; 1225 + 1226 + if (ioc->ioc_data == cic) 1227 + rcu_assign_pointer(ioc->ioc_data, NULL); 1228 1229 if (cic->cfqq[ASYNC]) { 1230 cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]); ··· 1255 */ 1256 static void cfq_exit_io_context(struct io_context *ioc) 1257 { 1258 call_for_each_cic(ioc, cfq_exit_single_io_context); 1259 } 1260 ··· 1478 1479 spin_lock_irqsave(&ioc->lock, flags); 1480 1481 + BUG_ON(ioc->ioc_data == cic); 1482 1483 radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd); 1484 hlist_del_rcu(&cic->cic_list);
+6 -25
fs/splice.c
··· 370 * for an in-flight io page 371 */ 372 if (flags & SPLICE_F_NONBLOCK) { 373 - if (TestSetPageLocked(page)) 374 break; 375 } else 376 lock_page(page); 377 ··· 481 struct pipe_inode_info *pipe, size_t len, 482 unsigned int flags) 483 { 484 - ssize_t spliced; 485 - int ret; 486 loff_t isize, left; 487 488 isize = i_size_read(in->f_mapping->host); 489 if (unlikely(*ppos >= isize)) ··· 492 if (unlikely(left < len)) 493 len = left; 494 495 - ret = 0; 496 - spliced = 0; 497 - while (len && !spliced) { 498 - ret = __generic_file_splice_read(in, ppos, pipe, len, flags); 499 - 500 - if (ret < 0) 501 - break; 502 - else if (!ret) { 503 - if (spliced) 504 - break; 505 - if (flags & SPLICE_F_NONBLOCK) { 506 - ret = -EAGAIN; 507 - break; 508 - } 509 - } 510 - 511 *ppos += ret; 512 - len -= ret; 513 - spliced += ret; 514 - } 515 - 516 - if (spliced) 517 - return spliced; 518 519 return ret; 520 }
··· 370 * for an in-flight io page 371 */ 372 if (flags & SPLICE_F_NONBLOCK) { 373 + if (TestSetPageLocked(page)) { 374 + error = -EAGAIN; 375 break; 376 + } 377 } else 378 lock_page(page); 379 ··· 479 struct pipe_inode_info *pipe, size_t len, 480 unsigned int flags) 481 { 482 loff_t isize, left; 483 + int ret; 484 485 isize = i_size_read(in->f_mapping->host); 486 if (unlikely(*ppos >= isize)) ··· 491 if (unlikely(left < len)) 492 len = left; 493 494 + ret = __generic_file_splice_read(in, ppos, pipe, len, flags); 495 + if (ret > 0) 496 *ppos += ret; 497 498 return ret; 499 }