diff options
-rw-r--r-- | fs/block_dev.c | 16 | ||||
-rw-r--r-- | fs/fs-writeback.c | 97 | ||||
-rw-r--r-- | fs/inode.c | 5 | ||||
-rw-r--r-- | include/linux/backing-dev.h | 2 | ||||
-rw-r--r-- | include/linux/writeback.h | 2 | ||||
-rw-r--r-- | mm/backing-dev.c | 21 | ||||
-rw-r--r-- | mm/filemap.c | 6 | ||||
-rw-r--r-- | mm/rmap.c | 4 |
8 files changed, 85 insertions, 68 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 1a2421f908f0..3c9a03e51b62 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -44,24 +44,28 @@ inline struct block_device *I_BDEV(struct inode *inode) | |||
44 | { | 44 | { |
45 | return &BDEV_I(inode)->bdev; | 45 | return &BDEV_I(inode)->bdev; |
46 | } | 46 | } |
47 | |||
48 | EXPORT_SYMBOL(I_BDEV); | 47 | EXPORT_SYMBOL(I_BDEV); |
49 | 48 | ||
50 | /* | 49 | /* |
51 | * move the inode from it's current bdi to the a new bdi. if the inode is dirty | 50 | * Move the inode from its current bdi to a new bdi. If the inode is dirty we |
52 | * we need to move it onto the dirty list of @dst so that the inode is always | 51 | * need to move it onto the dirty list of @dst so that the inode is always on |
53 | * on the right list. | 52 | * the right list. |
54 | */ | 53 | */ |
55 | static void bdev_inode_switch_bdi(struct inode *inode, | 54 | static void bdev_inode_switch_bdi(struct inode *inode, |
56 | struct backing_dev_info *dst) | 55 | struct backing_dev_info *dst) |
57 | { | 56 | { |
58 | spin_lock(&inode_wb_list_lock); | 57 | struct backing_dev_info *old = inode->i_data.backing_dev_info; |
58 | |||
59 | if (unlikely(dst == old)) /* deadlock avoidance */ | ||
60 | return; | ||
61 | bdi_lock_two(&old->wb, &dst->wb); | ||
59 | spin_lock(&inode->i_lock); | 62 | spin_lock(&inode->i_lock); |
60 | inode->i_data.backing_dev_info = dst; | 63 | inode->i_data.backing_dev_info = dst; |
61 | if (inode->i_state & I_DIRTY) | 64 | if (inode->i_state & I_DIRTY) |
62 | list_move(&inode->i_wb_list, &dst->wb.b_dirty); | 65 | list_move(&inode->i_wb_list, &dst->wb.b_dirty); |
63 | spin_unlock(&inode->i_lock); | 66 | spin_unlock(&inode->i_lock); |
64 | spin_unlock(&inode_wb_list_lock); | 67 | spin_unlock(&old->wb.list_lock); |
68 | spin_unlock(&dst->wb.list_lock); | ||
65 | } | 69 | } |
66 | 70 | ||
67 | static sector_t max_block(struct block_device *bdev) | 71 | static sector_t max_block(struct block_device *bdev) |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 664acdb2e7ef..36a30917e0dc 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -181,12 +181,13 @@ void bdi_start_background_writeback(struct backing_dev_info *bdi) | |||
181 | */ | 181 | */ |
182 | void inode_wb_list_del(struct inode *inode) | 182 | void inode_wb_list_del(struct inode *inode) |
183 | { | 183 | { |
184 | spin_lock(&inode_wb_list_lock); | 184 | struct backing_dev_info *bdi = inode_to_bdi(inode); |
185 | |||
186 | spin_lock(&bdi->wb.list_lock); | ||
185 | list_del_init(&inode->i_wb_list); | 187 | list_del_init(&inode->i_wb_list); |
186 | spin_unlock(&inode_wb_list_lock); | 188 | spin_unlock(&bdi->wb.list_lock); |
187 | } | 189 | } |
188 | 190 | ||
189 | |||
190 | /* | 191 | /* |
191 | * Redirty an inode: set its when-it-was dirtied timestamp and move it to the | 192 | * Redirty an inode: set its when-it-was dirtied timestamp and move it to the |
192 | * furthest end of its superblock's dirty-inode list. | 193 | * furthest end of its superblock's dirty-inode list. |
@@ -196,11 +197,9 @@ void inode_wb_list_del(struct inode *inode) | |||
196 | * the case then the inode must have been redirtied while it was being written | 197 | * the case then the inode must have been redirtied while it was being written |
197 | * out and we don't reset its dirtied_when. | 198 | * out and we don't reset its dirtied_when. |
198 | */ | 199 | */ |
199 | static void redirty_tail(struct inode *inode) | 200 | static void redirty_tail(struct inode *inode, struct bdi_writeback *wb) |
200 | { | 201 | { |
201 | struct bdi_writeback *wb = &inode_to_bdi(inode)->wb; | 202 | assert_spin_locked(&wb->list_lock); |
202 | |||
203 | assert_spin_locked(&inode_wb_list_lock); | ||
204 | if (!list_empty(&wb->b_dirty)) { | 203 | if (!list_empty(&wb->b_dirty)) { |
205 | struct inode *tail; | 204 | struct inode *tail; |
206 | 205 | ||
@@ -214,11 +213,9 @@ static void redirty_tail(struct inode *inode) | |||
214 | /* | 213 | /* |
215 | * requeue inode for re-scanning after bdi->b_io list is exhausted. | 214 | * requeue inode for re-scanning after bdi->b_io list is exhausted. |
216 | */ | 215 | */ |
217 | static void requeue_io(struct inode *inode) | 216 | static void requeue_io(struct inode *inode, struct bdi_writeback *wb) |
218 | { | 217 | { |
219 | struct bdi_writeback *wb = &inode_to_bdi(inode)->wb; | 218 | assert_spin_locked(&wb->list_lock); |
220 | |||
221 | assert_spin_locked(&inode_wb_list_lock); | ||
222 | list_move(&inode->i_wb_list, &wb->b_more_io); | 219 | list_move(&inode->i_wb_list, &wb->b_more_io); |
223 | } | 220 | } |
224 | 221 | ||
@@ -226,7 +223,7 @@ static void inode_sync_complete(struct inode *inode) | |||
226 | { | 223 | { |
227 | /* | 224 | /* |
228 | * Prevent speculative execution through | 225 | * Prevent speculative execution through |
229 | * spin_unlock(&inode_wb_list_lock); | 226 | * spin_unlock(&wb->list_lock); |
230 | */ | 227 | */ |
231 | 228 | ||
232 | smp_mb(); | 229 | smp_mb(); |
@@ -302,7 +299,7 @@ static void move_expired_inodes(struct list_head *delaying_queue, | |||
302 | */ | 299 | */ |
303 | static void queue_io(struct bdi_writeback *wb, unsigned long *older_than_this) | 300 | static void queue_io(struct bdi_writeback *wb, unsigned long *older_than_this) |
304 | { | 301 | { |
305 | assert_spin_locked(&inode_wb_list_lock); | 302 | assert_spin_locked(&wb->list_lock); |
306 | list_splice_init(&wb->b_more_io, &wb->b_io); | 303 | list_splice_init(&wb->b_more_io, &wb->b_io); |
307 | move_expired_inodes(&wb->b_dirty, &wb->b_io, older_than_this); | 304 | move_expired_inodes(&wb->b_dirty, &wb->b_io, older_than_this); |
308 | } | 305 | } |
@@ -317,7 +314,8 @@ static int write_inode(struct inode *inode, struct writeback_control *wbc) | |||
317 | /* | 314 | /* |
318 | * Wait for writeback on an inode to complete. | 315 | * Wait for writeback on an inode to complete. |
319 | */ | 316 | */ |
320 | static void inode_wait_for_writeback(struct inode *inode) | 317 | static void inode_wait_for_writeback(struct inode *inode, |
318 | struct bdi_writeback *wb) | ||
321 | { | 319 | { |
322 | DEFINE_WAIT_BIT(wq, &inode->i_state, __I_SYNC); | 320 | DEFINE_WAIT_BIT(wq, &inode->i_state, __I_SYNC); |
323 | wait_queue_head_t *wqh; | 321 | wait_queue_head_t *wqh; |
@@ -325,15 +323,15 @@ static void inode_wait_for_writeback(struct inode *inode) | |||
325 | wqh = bit_waitqueue(&inode->i_state, __I_SYNC); | 323 | wqh = bit_waitqueue(&inode->i_state, __I_SYNC); |
326 | while (inode->i_state & I_SYNC) { | 324 | while (inode->i_state & I_SYNC) { |
327 | spin_unlock(&inode->i_lock); | 325 | spin_unlock(&inode->i_lock); |
328 | spin_unlock(&inode_wb_list_lock); | 326 | spin_unlock(&wb->list_lock); |
329 | __wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE); | 327 | __wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE); |
330 | spin_lock(&inode_wb_list_lock); | 328 | spin_lock(&wb->list_lock); |
331 | spin_lock(&inode->i_lock); | 329 | spin_lock(&inode->i_lock); |
332 | } | 330 | } |
333 | } | 331 | } |
334 | 332 | ||
335 | /* | 333 | /* |
336 | * Write out an inode's dirty pages. Called under inode_wb_list_lock and | 334 | * Write out an inode's dirty pages. Called under wb->list_lock and |
337 | * inode->i_lock. Either the caller has an active reference on the inode or | 335 | * inode->i_lock. Either the caller has an active reference on the inode or |
338 | * the inode has I_WILL_FREE set. | 336 | * the inode has I_WILL_FREE set. |
339 | * | 337 | * |
@@ -344,13 +342,14 @@ static void inode_wait_for_writeback(struct inode *inode) | |||
344 | * livelocks, etc. | 342 | * livelocks, etc. |
345 | */ | 343 | */ |
346 | static int | 344 | static int |
347 | writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | 345 | writeback_single_inode(struct inode *inode, struct bdi_writeback *wb, |
346 | struct writeback_control *wbc) | ||
348 | { | 347 | { |
349 | struct address_space *mapping = inode->i_mapping; | 348 | struct address_space *mapping = inode->i_mapping; |
350 | unsigned dirty; | 349 | unsigned dirty; |
351 | int ret; | 350 | int ret; |
352 | 351 | ||
353 | assert_spin_locked(&inode_wb_list_lock); | 352 | assert_spin_locked(&wb->list_lock); |
354 | assert_spin_locked(&inode->i_lock); | 353 | assert_spin_locked(&inode->i_lock); |
355 | 354 | ||
356 | if (!atomic_read(&inode->i_count)) | 355 | if (!atomic_read(&inode->i_count)) |
@@ -368,14 +367,14 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
368 | * completed a full scan of b_io. | 367 | * completed a full scan of b_io. |
369 | */ | 368 | */ |
370 | if (wbc->sync_mode != WB_SYNC_ALL) { | 369 | if (wbc->sync_mode != WB_SYNC_ALL) { |
371 | requeue_io(inode); | 370 | requeue_io(inode, wb); |
372 | return 0; | 371 | return 0; |
373 | } | 372 | } |
374 | 373 | ||
375 | /* | 374 | /* |
376 | * It's a data-integrity sync. We must wait. | 375 | * It's a data-integrity sync. We must wait. |
377 | */ | 376 | */ |
378 | inode_wait_for_writeback(inode); | 377 | inode_wait_for_writeback(inode, wb); |
379 | } | 378 | } |
380 | 379 | ||
381 | BUG_ON(inode->i_state & I_SYNC); | 380 | BUG_ON(inode->i_state & I_SYNC); |
@@ -384,7 +383,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
384 | inode->i_state |= I_SYNC; | 383 | inode->i_state |= I_SYNC; |
385 | inode->i_state &= ~I_DIRTY_PAGES; | 384 | inode->i_state &= ~I_DIRTY_PAGES; |
386 | spin_unlock(&inode->i_lock); | 385 | spin_unlock(&inode->i_lock); |
387 | spin_unlock(&inode_wb_list_lock); | 386 | spin_unlock(&wb->list_lock); |
388 | 387 | ||
389 | ret = do_writepages(mapping, wbc); | 388 | ret = do_writepages(mapping, wbc); |
390 | 389 | ||
@@ -415,7 +414,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
415 | ret = err; | 414 | ret = err; |
416 | } | 415 | } |
417 | 416 | ||
418 | spin_lock(&inode_wb_list_lock); | 417 | spin_lock(&wb->list_lock); |
419 | spin_lock(&inode->i_lock); | 418 | spin_lock(&inode->i_lock); |
420 | inode->i_state &= ~I_SYNC; | 419 | inode->i_state &= ~I_SYNC; |
421 | if (!(inode->i_state & I_FREEING)) { | 420 | if (!(inode->i_state & I_FREEING)) { |
@@ -438,7 +437,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
438 | /* | 437 | /* |
439 | * slice used up: queue for next turn | 438 | * slice used up: queue for next turn |
440 | */ | 439 | */ |
441 | requeue_io(inode); | 440 | requeue_io(inode, wb); |
442 | } else { | 441 | } else { |
443 | /* | 442 | /* |
444 | * Writeback blocked by something other than | 443 | * Writeback blocked by something other than |
@@ -447,7 +446,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
447 | * retrying writeback of the dirty page/inode | 446 | * retrying writeback of the dirty page/inode |
448 | * that cannot be performed immediately. | 447 | * that cannot be performed immediately. |
449 | */ | 448 | */ |
450 | redirty_tail(inode); | 449 | redirty_tail(inode, wb); |
451 | } | 450 | } |
452 | } else if (inode->i_state & I_DIRTY) { | 451 | } else if (inode->i_state & I_DIRTY) { |
453 | /* | 452 | /* |
@@ -456,7 +455,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
456 | * submission or metadata updates after data IO | 455 | * submission or metadata updates after data IO |
457 | * completion. | 456 | * completion. |
458 | */ | 457 | */ |
459 | redirty_tail(inode); | 458 | redirty_tail(inode, wb); |
460 | } else { | 459 | } else { |
461 | /* | 460 | /* |
462 | * The inode is clean. At this point we either have | 461 | * The inode is clean. At this point we either have |
@@ -521,7 +520,7 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, | |||
521 | * superblock, move all inodes not belonging | 520 | * superblock, move all inodes not belonging |
522 | * to it back onto the dirty list. | 521 | * to it back onto the dirty list. |
523 | */ | 522 | */ |
524 | redirty_tail(inode); | 523 | redirty_tail(inode, wb); |
525 | continue; | 524 | continue; |
526 | } | 525 | } |
527 | 526 | ||
@@ -541,7 +540,7 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, | |||
541 | spin_lock(&inode->i_lock); | 540 | spin_lock(&inode->i_lock); |
542 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { | 541 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { |
543 | spin_unlock(&inode->i_lock); | 542 | spin_unlock(&inode->i_lock); |
544 | requeue_io(inode); | 543 | requeue_io(inode, wb); |
545 | continue; | 544 | continue; |
546 | } | 545 | } |
547 | 546 | ||
@@ -557,19 +556,19 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, | |||
557 | __iget(inode); | 556 | __iget(inode); |
558 | 557 | ||
559 | pages_skipped = wbc->pages_skipped; | 558 | pages_skipped = wbc->pages_skipped; |
560 | writeback_single_inode(inode, wbc); | 559 | writeback_single_inode(inode, wb, wbc); |
561 | if (wbc->pages_skipped != pages_skipped) { | 560 | if (wbc->pages_skipped != pages_skipped) { |
562 | /* | 561 | /* |
563 | * writeback is not making progress due to locked | 562 | * writeback is not making progress due to locked |
564 | * buffers. Skip this inode for now. | 563 | * buffers. Skip this inode for now. |
565 | */ | 564 | */ |
566 | redirty_tail(inode); | 565 | redirty_tail(inode, wb); |
567 | } | 566 | } |
568 | spin_unlock(&inode->i_lock); | 567 | spin_unlock(&inode->i_lock); |
569 | spin_unlock(&inode_wb_list_lock); | 568 | spin_unlock(&wb->list_lock); |
570 | iput(inode); | 569 | iput(inode); |
571 | cond_resched(); | 570 | cond_resched(); |
572 | spin_lock(&inode_wb_list_lock); | 571 | spin_lock(&wb->list_lock); |
573 | if (wbc->nr_to_write <= 0) { | 572 | if (wbc->nr_to_write <= 0) { |
574 | wbc->more_io = 1; | 573 | wbc->more_io = 1; |
575 | return 1; | 574 | return 1; |
@@ -588,7 +587,7 @@ void writeback_inodes_wb(struct bdi_writeback *wb, | |||
588 | 587 | ||
589 | if (!wbc->wb_start) | 588 | if (!wbc->wb_start) |
590 | wbc->wb_start = jiffies; /* livelock avoidance */ | 589 | wbc->wb_start = jiffies; /* livelock avoidance */ |
591 | spin_lock(&inode_wb_list_lock); | 590 | spin_lock(&wb->list_lock); |
592 | 591 | ||
593 | if (list_empty(&wb->b_io)) | 592 | if (list_empty(&wb->b_io)) |
594 | queue_io(wb, wbc->older_than_this); | 593 | queue_io(wb, wbc->older_than_this); |
@@ -598,7 +597,7 @@ void writeback_inodes_wb(struct bdi_writeback *wb, | |||
598 | struct super_block *sb = inode->i_sb; | 597 | struct super_block *sb = inode->i_sb; |
599 | 598 | ||
600 | if (!pin_sb_for_writeback(sb)) { | 599 | if (!pin_sb_for_writeback(sb)) { |
601 | requeue_io(inode); | 600 | requeue_io(inode, wb); |
602 | continue; | 601 | continue; |
603 | } | 602 | } |
604 | ret = writeback_sb_inodes(sb, wb, wbc, false); | 603 | ret = writeback_sb_inodes(sb, wb, wbc, false); |
@@ -607,7 +606,7 @@ void writeback_inodes_wb(struct bdi_writeback *wb, | |||
607 | if (ret) | 606 | if (ret) |
608 | break; | 607 | break; |
609 | } | 608 | } |
610 | spin_unlock(&inode_wb_list_lock); | 609 | spin_unlock(&wb->list_lock); |
611 | /* Leave any unwritten inodes on b_io */ | 610 | /* Leave any unwritten inodes on b_io */ |
612 | } | 611 | } |
613 | 612 | ||
@@ -616,11 +615,11 @@ static void __writeback_inodes_sb(struct super_block *sb, | |||
616 | { | 615 | { |
617 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | 616 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
618 | 617 | ||
619 | spin_lock(&inode_wb_list_lock); | 618 | spin_lock(&wb->list_lock); |
620 | if (list_empty(&wb->b_io)) | 619 | if (list_empty(&wb->b_io)) |
621 | queue_io(wb, wbc->older_than_this); | 620 | queue_io(wb, wbc->older_than_this); |
622 | writeback_sb_inodes(sb, wb, wbc, true); | 621 | writeback_sb_inodes(sb, wb, wbc, true); |
623 | spin_unlock(&inode_wb_list_lock); | 622 | spin_unlock(&wb->list_lock); |
624 | } | 623 | } |
625 | 624 | ||
626 | /* | 625 | /* |
@@ -762,15 +761,15 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
762 | * become available for writeback. Otherwise | 761 | * become available for writeback. Otherwise |
763 | * we'll just busyloop. | 762 | * we'll just busyloop. |
764 | */ | 763 | */ |
765 | spin_lock(&inode_wb_list_lock); | 764 | spin_lock(&wb->list_lock); |
766 | if (!list_empty(&wb->b_more_io)) { | 765 | if (!list_empty(&wb->b_more_io)) { |
767 | inode = wb_inode(wb->b_more_io.prev); | 766 | inode = wb_inode(wb->b_more_io.prev); |
768 | trace_wbc_writeback_wait(&wbc, wb->bdi); | 767 | trace_wbc_writeback_wait(&wbc, wb->bdi); |
769 | spin_lock(&inode->i_lock); | 768 | spin_lock(&inode->i_lock); |
770 | inode_wait_for_writeback(inode); | 769 | inode_wait_for_writeback(inode, wb); |
771 | spin_unlock(&inode->i_lock); | 770 | spin_unlock(&inode->i_lock); |
772 | } | 771 | } |
773 | spin_unlock(&inode_wb_list_lock); | 772 | spin_unlock(&wb->list_lock); |
774 | } | 773 | } |
775 | 774 | ||
776 | return wrote; | 775 | return wrote; |
@@ -1104,10 +1103,10 @@ void __mark_inode_dirty(struct inode *inode, int flags) | |||
1104 | } | 1103 | } |
1105 | 1104 | ||
1106 | spin_unlock(&inode->i_lock); | 1105 | spin_unlock(&inode->i_lock); |
1107 | spin_lock(&inode_wb_list_lock); | 1106 | spin_lock(&bdi->wb.list_lock); |
1108 | inode->dirtied_when = jiffies; | 1107 | inode->dirtied_when = jiffies; |
1109 | list_move(&inode->i_wb_list, &bdi->wb.b_dirty); | 1108 | list_move(&inode->i_wb_list, &bdi->wb.b_dirty); |
1110 | spin_unlock(&inode_wb_list_lock); | 1109 | spin_unlock(&bdi->wb.list_lock); |
1111 | 1110 | ||
1112 | if (wakeup_bdi) | 1111 | if (wakeup_bdi) |
1113 | bdi_wakeup_thread_delayed(bdi); | 1112 | bdi_wakeup_thread_delayed(bdi); |
@@ -1309,6 +1308,7 @@ EXPORT_SYMBOL(sync_inodes_sb); | |||
1309 | */ | 1308 | */ |
1310 | int write_inode_now(struct inode *inode, int sync) | 1309 | int write_inode_now(struct inode *inode, int sync) |
1311 | { | 1310 | { |
1311 | struct bdi_writeback *wb = &inode_to_bdi(inode)->wb; | ||
1312 | int ret; | 1312 | int ret; |
1313 | struct writeback_control wbc = { | 1313 | struct writeback_control wbc = { |
1314 | .nr_to_write = LONG_MAX, | 1314 | .nr_to_write = LONG_MAX, |
@@ -1321,11 +1321,11 @@ int write_inode_now(struct inode *inode, int sync) | |||
1321 | wbc.nr_to_write = 0; | 1321 | wbc.nr_to_write = 0; |
1322 | 1322 | ||
1323 | might_sleep(); | 1323 | might_sleep(); |
1324 | spin_lock(&inode_wb_list_lock); | 1324 | spin_lock(&wb->list_lock); |
1325 | spin_lock(&inode->i_lock); | 1325 | spin_lock(&inode->i_lock); |
1326 | ret = writeback_single_inode(inode, &wbc); | 1326 | ret = writeback_single_inode(inode, wb, &wbc); |
1327 | spin_unlock(&inode->i_lock); | 1327 | spin_unlock(&inode->i_lock); |
1328 | spin_unlock(&inode_wb_list_lock); | 1328 | spin_unlock(&wb->list_lock); |
1329 | if (sync) | 1329 | if (sync) |
1330 | inode_sync_wait(inode); | 1330 | inode_sync_wait(inode); |
1331 | return ret; | 1331 | return ret; |
@@ -1345,13 +1345,14 @@ EXPORT_SYMBOL(write_inode_now); | |||
1345 | */ | 1345 | */ |
1346 | int sync_inode(struct inode *inode, struct writeback_control *wbc) | 1346 | int sync_inode(struct inode *inode, struct writeback_control *wbc) |
1347 | { | 1347 | { |
1348 | struct bdi_writeback *wb = &inode_to_bdi(inode)->wb; | ||
1348 | int ret; | 1349 | int ret; |
1349 | 1350 | ||
1350 | spin_lock(&inode_wb_list_lock); | 1351 | spin_lock(&wb->list_lock); |
1351 | spin_lock(&inode->i_lock); | 1352 | spin_lock(&inode->i_lock); |
1352 | ret = writeback_single_inode(inode, wbc); | 1353 | ret = writeback_single_inode(inode, wb, wbc); |
1353 | spin_unlock(&inode->i_lock); | 1354 | spin_unlock(&inode->i_lock); |
1354 | spin_unlock(&inode_wb_list_lock); | 1355 | spin_unlock(&wb->list_lock); |
1355 | return ret; | 1356 | return ret; |
1356 | } | 1357 | } |
1357 | EXPORT_SYMBOL(sync_inode); | 1358 | EXPORT_SYMBOL(sync_inode); |
diff --git a/fs/inode.c b/fs/inode.c index 0f7e88a7803f..4be128cbc754 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -37,7 +37,7 @@ | |||
37 | * inode_lru, inode->i_lru | 37 | * inode_lru, inode->i_lru |
38 | * inode_sb_list_lock protects: | 38 | * inode_sb_list_lock protects: |
39 | * sb->s_inodes, inode->i_sb_list | 39 | * sb->s_inodes, inode->i_sb_list |
40 | * inode_wb_list_lock protects: | 40 | * bdi->wb.list_lock protects: |
41 | * bdi->wb.b_{dirty,io,more_io}, inode->i_wb_list | 41 | * bdi->wb.b_{dirty,io,more_io}, inode->i_wb_list |
42 | * inode_hash_lock protects: | 42 | * inode_hash_lock protects: |
43 | * inode_hashtable, inode->i_hash | 43 | * inode_hashtable, inode->i_hash |
@@ -48,7 +48,7 @@ | |||
48 | * inode->i_lock | 48 | * inode->i_lock |
49 | * inode_lru_lock | 49 | * inode_lru_lock |
50 | * | 50 | * |
51 | * inode_wb_list_lock | 51 | * bdi->wb.list_lock |
52 | * inode->i_lock | 52 | * inode->i_lock |
53 | * | 53 | * |
54 | * inode_hash_lock | 54 | * inode_hash_lock |
@@ -68,7 +68,6 @@ static LIST_HEAD(inode_lru); | |||
68 | static DEFINE_SPINLOCK(inode_lru_lock); | 68 | static DEFINE_SPINLOCK(inode_lru_lock); |
69 | 69 | ||
70 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock); | 70 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock); |
71 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_wb_list_lock); | ||
72 | 71 | ||
73 | /* | 72 | /* |
74 | * iprune_sem provides exclusion between the icache shrinking and the | 73 | * iprune_sem provides exclusion between the icache shrinking and the |
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 96f4094b706d..47feb2c4706a 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h | |||
@@ -57,6 +57,7 @@ struct bdi_writeback { | |||
57 | struct list_head b_dirty; /* dirty inodes */ | 57 | struct list_head b_dirty; /* dirty inodes */ |
58 | struct list_head b_io; /* parked for writeback */ | 58 | struct list_head b_io; /* parked for writeback */ |
59 | struct list_head b_more_io; /* parked for more writeback */ | 59 | struct list_head b_more_io; /* parked for more writeback */ |
60 | spinlock_t list_lock; /* protects the b_* lists */ | ||
60 | }; | 61 | }; |
61 | 62 | ||
62 | struct backing_dev_info { | 63 | struct backing_dev_info { |
@@ -106,6 +107,7 @@ int bdi_writeback_thread(void *data); | |||
106 | int bdi_has_dirty_io(struct backing_dev_info *bdi); | 107 | int bdi_has_dirty_io(struct backing_dev_info *bdi); |
107 | void bdi_arm_supers_timer(void); | 108 | void bdi_arm_supers_timer(void); |
108 | void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi); | 109 | void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi); |
110 | void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2); | ||
109 | 111 | ||
110 | extern spinlock_t bdi_lock; | 112 | extern spinlock_t bdi_lock; |
111 | extern struct list_head bdi_list; | 113 | extern struct list_head bdi_list; |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 7df9026f7129..c2d957fb38d3 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -9,8 +9,6 @@ | |||
9 | 9 | ||
10 | struct backing_dev_info; | 10 | struct backing_dev_info; |
11 | 11 | ||
12 | extern spinlock_t inode_wb_list_lock; | ||
13 | |||
14 | /* | 12 | /* |
15 | * fs/fs-writeback.c | 13 | * fs/fs-writeback.c |
16 | */ | 14 | */ |
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index f032e6e1e09a..5f6553ef1ba7 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -45,6 +45,17 @@ static struct timer_list sync_supers_timer; | |||
45 | static int bdi_sync_supers(void *); | 45 | static int bdi_sync_supers(void *); |
46 | static void sync_supers_timer_fn(unsigned long); | 46 | static void sync_supers_timer_fn(unsigned long); |
47 | 47 | ||
48 | void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2) | ||
49 | { | ||
50 | if (wb1 < wb2) { | ||
51 | spin_lock(&wb1->list_lock); | ||
52 | spin_lock_nested(&wb2->list_lock, 1); | ||
53 | } else { | ||
54 | spin_lock(&wb2->list_lock); | ||
55 | spin_lock_nested(&wb1->list_lock, 1); | ||
56 | } | ||
57 | } | ||
58 | |||
48 | #ifdef CONFIG_DEBUG_FS | 59 | #ifdef CONFIG_DEBUG_FS |
49 | #include <linux/debugfs.h> | 60 | #include <linux/debugfs.h> |
50 | #include <linux/seq_file.h> | 61 | #include <linux/seq_file.h> |
@@ -67,14 +78,14 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v) | |||
67 | struct inode *inode; | 78 | struct inode *inode; |
68 | 79 | ||
69 | nr_dirty = nr_io = nr_more_io = 0; | 80 | nr_dirty = nr_io = nr_more_io = 0; |
70 | spin_lock(&inode_wb_list_lock); | 81 | spin_lock(&wb->list_lock); |
71 | list_for_each_entry(inode, &wb->b_dirty, i_wb_list) | 82 | list_for_each_entry(inode, &wb->b_dirty, i_wb_list) |
72 | nr_dirty++; | 83 | nr_dirty++; |
73 | list_for_each_entry(inode, &wb->b_io, i_wb_list) | 84 | list_for_each_entry(inode, &wb->b_io, i_wb_list) |
74 | nr_io++; | 85 | nr_io++; |
75 | list_for_each_entry(inode, &wb->b_more_io, i_wb_list) | 86 | list_for_each_entry(inode, &wb->b_more_io, i_wb_list) |
76 | nr_more_io++; | 87 | nr_more_io++; |
77 | spin_unlock(&inode_wb_list_lock); | 88 | spin_unlock(&wb->list_lock); |
78 | 89 | ||
79 | global_dirty_limits(&background_thresh, &dirty_thresh); | 90 | global_dirty_limits(&background_thresh, &dirty_thresh); |
80 | bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh); | 91 | bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh); |
@@ -628,6 +639,7 @@ static void bdi_wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi) | |||
628 | INIT_LIST_HEAD(&wb->b_dirty); | 639 | INIT_LIST_HEAD(&wb->b_dirty); |
629 | INIT_LIST_HEAD(&wb->b_io); | 640 | INIT_LIST_HEAD(&wb->b_io); |
630 | INIT_LIST_HEAD(&wb->b_more_io); | 641 | INIT_LIST_HEAD(&wb->b_more_io); |
642 | spin_lock_init(&wb->list_lock); | ||
631 | setup_timer(&wb->wakeup_timer, wakeup_timer_fn, (unsigned long)bdi); | 643 | setup_timer(&wb->wakeup_timer, wakeup_timer_fn, (unsigned long)bdi); |
632 | } | 644 | } |
633 | 645 | ||
@@ -676,11 +688,12 @@ void bdi_destroy(struct backing_dev_info *bdi) | |||
676 | if (bdi_has_dirty_io(bdi)) { | 688 | if (bdi_has_dirty_io(bdi)) { |
677 | struct bdi_writeback *dst = &default_backing_dev_info.wb; | 689 | struct bdi_writeback *dst = &default_backing_dev_info.wb; |
678 | 690 | ||
679 | spin_lock(&inode_wb_list_lock); | 691 | bdi_lock_two(&bdi->wb, dst); |
680 | list_splice(&bdi->wb.b_dirty, &dst->b_dirty); | 692 | list_splice(&bdi->wb.b_dirty, &dst->b_dirty); |
681 | list_splice(&bdi->wb.b_io, &dst->b_io); | 693 | list_splice(&bdi->wb.b_io, &dst->b_io); |
682 | list_splice(&bdi->wb.b_more_io, &dst->b_more_io); | 694 | list_splice(&bdi->wb.b_more_io, &dst->b_more_io); |
683 | spin_unlock(&inode_wb_list_lock); | 695 | spin_unlock(&bdi->wb.list_lock); |
696 | spin_unlock(&dst->list_lock); | ||
684 | } | 697 | } |
685 | 698 | ||
686 | bdi_unregister(bdi); | 699 | bdi_unregister(bdi); |
diff --git a/mm/filemap.c b/mm/filemap.c index d7b10578a64b..1e492c3dd6f8 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -81,7 +81,7 @@ | |||
81 | * ->i_mutex | 81 | * ->i_mutex |
82 | * ->i_alloc_sem (various) | 82 | * ->i_alloc_sem (various) |
83 | * | 83 | * |
84 | * inode_wb_list_lock | 84 | * bdi->wb.list_lock |
85 | * sb_lock (fs/fs-writeback.c) | 85 | * sb_lock (fs/fs-writeback.c) |
86 | * ->mapping->tree_lock (__sync_single_inode) | 86 | * ->mapping->tree_lock (__sync_single_inode) |
87 | * | 87 | * |
@@ -99,9 +99,9 @@ | |||
99 | * ->zone.lru_lock (check_pte_range->isolate_lru_page) | 99 | * ->zone.lru_lock (check_pte_range->isolate_lru_page) |
100 | * ->private_lock (page_remove_rmap->set_page_dirty) | 100 | * ->private_lock (page_remove_rmap->set_page_dirty) |
101 | * ->tree_lock (page_remove_rmap->set_page_dirty) | 101 | * ->tree_lock (page_remove_rmap->set_page_dirty) |
102 | * inode_wb_list_lock (page_remove_rmap->set_page_dirty) | 102 | * bdi.wb->list_lock (page_remove_rmap->set_page_dirty) |
103 | * ->inode->i_lock (page_remove_rmap->set_page_dirty) | 103 | * ->inode->i_lock (page_remove_rmap->set_page_dirty) |
104 | * inode_wb_list_lock (zap_pte_range->set_page_dirty) | 104 | * bdi.wb->list_lock (zap_pte_range->set_page_dirty) |
105 | * ->inode->i_lock (zap_pte_range->set_page_dirty) | 105 | * ->inode->i_lock (zap_pte_range->set_page_dirty) |
106 | * ->private_lock (zap_pte_range->__set_page_dirty_buffers) | 106 | * ->private_lock (zap_pte_range->__set_page_dirty_buffers) |
107 | * | 107 | * |
@@ -32,11 +32,11 @@ | |||
32 | * mmlist_lock (in mmput, drain_mmlist and others) | 32 | * mmlist_lock (in mmput, drain_mmlist and others) |
33 | * mapping->private_lock (in __set_page_dirty_buffers) | 33 | * mapping->private_lock (in __set_page_dirty_buffers) |
34 | * inode->i_lock (in set_page_dirty's __mark_inode_dirty) | 34 | * inode->i_lock (in set_page_dirty's __mark_inode_dirty) |
35 | * inode_wb_list_lock (in set_page_dirty's __mark_inode_dirty) | 35 | * bdi.wb->list_lock (in set_page_dirty's __mark_inode_dirty) |
36 | * sb_lock (within inode_lock in fs/fs-writeback.c) | 36 | * sb_lock (within inode_lock in fs/fs-writeback.c) |
37 | * mapping->tree_lock (widely used, in set_page_dirty, | 37 | * mapping->tree_lock (widely used, in set_page_dirty, |
38 | * in arch-dependent flush_dcache_mmap_lock, | 38 | * in arch-dependent flush_dcache_mmap_lock, |
39 | * within inode_wb_list_lock in __sync_single_inode) | 39 | * within bdi.wb->list_lock in __sync_single_inode) |
40 | * | 40 | * |
41 | * (code doesn't rely on that order so it could be switched around) | 41 | * (code doesn't rely on that order so it could be switched around) |
42 | * ->tasklist_lock | 42 | * ->tasklist_lock |