diff options
Diffstat (limited to 'fs/fs-writeback.c')
| -rw-r--r-- | fs/fs-writeback.c | 98 |
1 files changed, 64 insertions, 34 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1e23c33ea5cf..3d06ccc953aa 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -79,6 +79,11 @@ static inline struct backing_dev_info *inode_to_bdi(struct inode *inode) | |||
| 79 | return sb->s_bdi; | 79 | return sb->s_bdi; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | static inline struct inode *wb_inode(struct list_head *head) | ||
| 83 | { | ||
| 84 | return list_entry(head, struct inode, i_wb_list); | ||
| 85 | } | ||
| 86 | |||
| 82 | static void bdi_queue_work(struct backing_dev_info *bdi, | 87 | static void bdi_queue_work(struct backing_dev_info *bdi, |
| 83 | struct wb_writeback_work *work) | 88 | struct wb_writeback_work *work) |
| 84 | { | 89 | { |
| @@ -172,11 +177,11 @@ static void redirty_tail(struct inode *inode) | |||
| 172 | if (!list_empty(&wb->b_dirty)) { | 177 | if (!list_empty(&wb->b_dirty)) { |
| 173 | struct inode *tail; | 178 | struct inode *tail; |
| 174 | 179 | ||
| 175 | tail = list_entry(wb->b_dirty.next, struct inode, i_list); | 180 | tail = wb_inode(wb->b_dirty.next); |
| 176 | if (time_before(inode->dirtied_when, tail->dirtied_when)) | 181 | if (time_before(inode->dirtied_when, tail->dirtied_when)) |
| 177 | inode->dirtied_when = jiffies; | 182 | inode->dirtied_when = jiffies; |
| 178 | } | 183 | } |
| 179 | list_move(&inode->i_list, &wb->b_dirty); | 184 | list_move(&inode->i_wb_list, &wb->b_dirty); |
| 180 | } | 185 | } |
| 181 | 186 | ||
| 182 | /* | 187 | /* |
| @@ -186,7 +191,7 @@ static void requeue_io(struct inode *inode) | |||
| 186 | { | 191 | { |
| 187 | struct bdi_writeback *wb = &inode_to_bdi(inode)->wb; | 192 | struct bdi_writeback *wb = &inode_to_bdi(inode)->wb; |
| 188 | 193 | ||
| 189 | list_move(&inode->i_list, &wb->b_more_io); | 194 | list_move(&inode->i_wb_list, &wb->b_more_io); |
| 190 | } | 195 | } |
| 191 | 196 | ||
| 192 | static void inode_sync_complete(struct inode *inode) | 197 | static void inode_sync_complete(struct inode *inode) |
| @@ -227,14 +232,14 @@ static void move_expired_inodes(struct list_head *delaying_queue, | |||
| 227 | int do_sb_sort = 0; | 232 | int do_sb_sort = 0; |
| 228 | 233 | ||
| 229 | while (!list_empty(delaying_queue)) { | 234 | while (!list_empty(delaying_queue)) { |
| 230 | inode = list_entry(delaying_queue->prev, struct inode, i_list); | 235 | inode = wb_inode(delaying_queue->prev); |
| 231 | if (older_than_this && | 236 | if (older_than_this && |
| 232 | inode_dirtied_after(inode, *older_than_this)) | 237 | inode_dirtied_after(inode, *older_than_this)) |
| 233 | break; | 238 | break; |
| 234 | if (sb && sb != inode->i_sb) | 239 | if (sb && sb != inode->i_sb) |
| 235 | do_sb_sort = 1; | 240 | do_sb_sort = 1; |
| 236 | sb = inode->i_sb; | 241 | sb = inode->i_sb; |
| 237 | list_move(&inode->i_list, &tmp); | 242 | list_move(&inode->i_wb_list, &tmp); |
| 238 | } | 243 | } |
| 239 | 244 | ||
| 240 | /* just one sb in list, splice to dispatch_queue and we're done */ | 245 | /* just one sb in list, splice to dispatch_queue and we're done */ |
| @@ -245,12 +250,11 @@ static void move_expired_inodes(struct list_head *delaying_queue, | |||
| 245 | 250 | ||
| 246 | /* Move inodes from one superblock together */ | 251 | /* Move inodes from one superblock together */ |
| 247 | while (!list_empty(&tmp)) { | 252 | while (!list_empty(&tmp)) { |
| 248 | inode = list_entry(tmp.prev, struct inode, i_list); | 253 | sb = wb_inode(tmp.prev)->i_sb; |
| 249 | sb = inode->i_sb; | ||
| 250 | list_for_each_prev_safe(pos, node, &tmp) { | 254 | list_for_each_prev_safe(pos, node, &tmp) { |
| 251 | inode = list_entry(pos, struct inode, i_list); | 255 | inode = wb_inode(pos); |
| 252 | if (inode->i_sb == sb) | 256 | if (inode->i_sb == sb) |
| 253 | list_move(&inode->i_list, dispatch_queue); | 257 | list_move(&inode->i_wb_list, dispatch_queue); |
| 254 | } | 258 | } |
| 255 | } | 259 | } |
| 256 | } | 260 | } |
| @@ -408,16 +412,13 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 408 | * completion. | 412 | * completion. |
| 409 | */ | 413 | */ |
| 410 | redirty_tail(inode); | 414 | redirty_tail(inode); |
| 411 | } else if (atomic_read(&inode->i_count)) { | ||
| 412 | /* | ||
| 413 | * The inode is clean, inuse | ||
| 414 | */ | ||
| 415 | list_move(&inode->i_list, &inode_in_use); | ||
| 416 | } else { | 415 | } else { |
| 417 | /* | 416 | /* |
| 418 | * The inode is clean, unused | 417 | * The inode is clean. At this point we either have |
| 418 | * a reference to the inode or it's on it's way out. | ||
| 419 | * No need to add it back to the LRU. | ||
| 419 | */ | 420 | */ |
| 420 | list_move(&inode->i_list, &inode_unused); | 421 | list_del_init(&inode->i_wb_list); |
| 421 | } | 422 | } |
| 422 | } | 423 | } |
| 423 | inode_sync_complete(inode); | 424 | inode_sync_complete(inode); |
| @@ -465,8 +466,7 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, | |||
| 465 | { | 466 | { |
| 466 | while (!list_empty(&wb->b_io)) { | 467 | while (!list_empty(&wb->b_io)) { |
| 467 | long pages_skipped; | 468 | long pages_skipped; |
| 468 | struct inode *inode = list_entry(wb->b_io.prev, | 469 | struct inode *inode = wb_inode(wb->b_io.prev); |
| 469 | struct inode, i_list); | ||
| 470 | 470 | ||
| 471 | if (inode->i_sb != sb) { | 471 | if (inode->i_sb != sb) { |
| 472 | if (only_this_sb) { | 472 | if (only_this_sb) { |
| @@ -487,10 +487,16 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, | |||
| 487 | return 0; | 487 | return 0; |
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | if (inode->i_state & (I_NEW | I_WILL_FREE)) { | 490 | /* |
| 491 | * Don't bother with new inodes or inodes beeing freed, first | ||
| 492 | * kind does not need peridic writeout yet, and for the latter | ||
| 493 | * kind writeout is handled by the freer. | ||
| 494 | */ | ||
| 495 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { | ||
| 491 | requeue_io(inode); | 496 | requeue_io(inode); |
| 492 | continue; | 497 | continue; |
| 493 | } | 498 | } |
| 499 | |||
| 494 | /* | 500 | /* |
| 495 | * Was this inode dirtied after sync_sb_inodes was called? | 501 | * Was this inode dirtied after sync_sb_inodes was called? |
| 496 | * This keeps sync from extra jobs and livelock. | 502 | * This keeps sync from extra jobs and livelock. |
| @@ -498,7 +504,6 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, | |||
| 498 | if (inode_dirtied_after(inode, wbc->wb_start)) | 504 | if (inode_dirtied_after(inode, wbc->wb_start)) |
| 499 | return 1; | 505 | return 1; |
| 500 | 506 | ||
| 501 | BUG_ON(inode->i_state & I_FREEING); | ||
| 502 | __iget(inode); | 507 | __iget(inode); |
| 503 | pages_skipped = wbc->pages_skipped; | 508 | pages_skipped = wbc->pages_skipped; |
| 504 | writeback_single_inode(inode, wbc); | 509 | writeback_single_inode(inode, wbc); |
| @@ -536,8 +541,7 @@ void writeback_inodes_wb(struct bdi_writeback *wb, | |||
| 536 | queue_io(wb, wbc->older_than_this); | 541 | queue_io(wb, wbc->older_than_this); |
| 537 | 542 | ||
| 538 | while (!list_empty(&wb->b_io)) { | 543 | while (!list_empty(&wb->b_io)) { |
| 539 | struct inode *inode = list_entry(wb->b_io.prev, | 544 | struct inode *inode = wb_inode(wb->b_io.prev); |
| 540 | struct inode, i_list); | ||
| 541 | struct super_block *sb = inode->i_sb; | 545 | struct super_block *sb = inode->i_sb; |
| 542 | 546 | ||
| 543 | if (!pin_sb_for_writeback(sb)) { | 547 | if (!pin_sb_for_writeback(sb)) { |
| @@ -582,7 +586,7 @@ static inline bool over_bground_thresh(void) | |||
| 582 | global_dirty_limits(&background_thresh, &dirty_thresh); | 586 | global_dirty_limits(&background_thresh, &dirty_thresh); |
| 583 | 587 | ||
| 584 | return (global_page_state(NR_FILE_DIRTY) + | 588 | return (global_page_state(NR_FILE_DIRTY) + |
| 585 | global_page_state(NR_UNSTABLE_NFS) >= background_thresh); | 589 | global_page_state(NR_UNSTABLE_NFS) > background_thresh); |
| 586 | } | 590 | } |
| 587 | 591 | ||
| 588 | /* | 592 | /* |
| @@ -675,8 +679,7 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
| 675 | */ | 679 | */ |
| 676 | spin_lock(&inode_lock); | 680 | spin_lock(&inode_lock); |
| 677 | if (!list_empty(&wb->b_more_io)) { | 681 | if (!list_empty(&wb->b_more_io)) { |
| 678 | inode = list_entry(wb->b_more_io.prev, | 682 | inode = wb_inode(wb->b_more_io.prev); |
| 679 | struct inode, i_list); | ||
| 680 | trace_wbc_writeback_wait(&wbc, wb->bdi); | 683 | trace_wbc_writeback_wait(&wbc, wb->bdi); |
| 681 | inode_wait_for_writeback(inode); | 684 | inode_wait_for_writeback(inode); |
| 682 | } | 685 | } |
| @@ -704,6 +707,17 @@ get_next_work_item(struct backing_dev_info *bdi) | |||
| 704 | return work; | 707 | return work; |
| 705 | } | 708 | } |
| 706 | 709 | ||
| 710 | /* | ||
| 711 | * Add in the number of potentially dirty inodes, because each inode | ||
| 712 | * write can dirty pagecache in the underlying blockdev. | ||
| 713 | */ | ||
| 714 | static unsigned long get_nr_dirty_pages(void) | ||
| 715 | { | ||
| 716 | return global_page_state(NR_FILE_DIRTY) + | ||
| 717 | global_page_state(NR_UNSTABLE_NFS) + | ||
| 718 | get_nr_dirty_inodes(); | ||
| 719 | } | ||
| 720 | |||
| 707 | static long wb_check_old_data_flush(struct bdi_writeback *wb) | 721 | static long wb_check_old_data_flush(struct bdi_writeback *wb) |
| 708 | { | 722 | { |
| 709 | unsigned long expired; | 723 | unsigned long expired; |
| @@ -721,9 +735,7 @@ static long wb_check_old_data_flush(struct bdi_writeback *wb) | |||
| 721 | return 0; | 735 | return 0; |
| 722 | 736 | ||
| 723 | wb->last_old_flush = jiffies; | 737 | wb->last_old_flush = jiffies; |
| 724 | nr_pages = global_page_state(NR_FILE_DIRTY) + | 738 | nr_pages = get_nr_dirty_pages(); |
| 725 | global_page_state(NR_UNSTABLE_NFS) + | ||
| 726 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); | ||
| 727 | 739 | ||
| 728 | if (nr_pages) { | 740 | if (nr_pages) { |
| 729 | struct wb_writeback_work work = { | 741 | struct wb_writeback_work work = { |
| @@ -790,7 +802,7 @@ int bdi_writeback_thread(void *data) | |||
| 790 | struct backing_dev_info *bdi = wb->bdi; | 802 | struct backing_dev_info *bdi = wb->bdi; |
| 791 | long pages_written; | 803 | long pages_written; |
| 792 | 804 | ||
| 793 | current->flags |= PF_FLUSHER | PF_SWAPWRITE; | 805 | current->flags |= PF_SWAPWRITE; |
| 794 | set_freezable(); | 806 | set_freezable(); |
| 795 | wb->last_active = jiffies; | 807 | wb->last_active = jiffies; |
| 796 | 808 | ||
| @@ -962,7 +974,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) | |||
| 962 | * dirty list. Add blockdev inodes as well. | 974 | * dirty list. Add blockdev inodes as well. |
| 963 | */ | 975 | */ |
| 964 | if (!S_ISBLK(inode->i_mode)) { | 976 | if (!S_ISBLK(inode->i_mode)) { |
| 965 | if (hlist_unhashed(&inode->i_hash)) | 977 | if (inode_unhashed(inode)) |
| 966 | goto out; | 978 | goto out; |
| 967 | } | 979 | } |
| 968 | if (inode->i_state & I_FREEING) | 980 | if (inode->i_state & I_FREEING) |
| @@ -990,7 +1002,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) | |||
| 990 | } | 1002 | } |
| 991 | 1003 | ||
| 992 | inode->dirtied_when = jiffies; | 1004 | inode->dirtied_when = jiffies; |
| 993 | list_move(&inode->i_list, &bdi->wb.b_dirty); | 1005 | list_move(&inode->i_wb_list, &bdi->wb.b_dirty); |
| 994 | } | 1006 | } |
| 995 | } | 1007 | } |
| 996 | out: | 1008 | out: |
| @@ -1103,9 +1115,7 @@ EXPORT_SYMBOL(writeback_inodes_sb_nr); | |||
| 1103 | */ | 1115 | */ |
| 1104 | void writeback_inodes_sb(struct super_block *sb) | 1116 | void writeback_inodes_sb(struct super_block *sb) |
| 1105 | { | 1117 | { |
| 1106 | return writeback_inodes_sb_nr(sb, global_page_state(NR_FILE_DIRTY) + | 1118 | return writeback_inodes_sb_nr(sb, get_nr_dirty_pages()); |
| 1107 | global_page_state(NR_UNSTABLE_NFS) + | ||
| 1108 | (inodes_stat.nr_inodes - inodes_stat.nr_unused)); | ||
| 1109 | } | 1119 | } |
| 1110 | EXPORT_SYMBOL(writeback_inodes_sb); | 1120 | EXPORT_SYMBOL(writeback_inodes_sb); |
| 1111 | 1121 | ||
| @@ -1230,3 +1240,23 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 1230 | return ret; | 1240 | return ret; |
| 1231 | } | 1241 | } |
| 1232 | EXPORT_SYMBOL(sync_inode); | 1242 | EXPORT_SYMBOL(sync_inode); |
| 1243 | |||
| 1244 | /** | ||
| 1245 | * sync_inode - write an inode to disk | ||
| 1246 | * @inode: the inode to sync | ||
| 1247 | * @wait: wait for I/O to complete. | ||
| 1248 | * | ||
| 1249 | * Write an inode to disk and adjust it's dirty state after completion. | ||
| 1250 | * | ||
| 1251 | * Note: only writes the actual inode, no associated data or other metadata. | ||
| 1252 | */ | ||
| 1253 | int sync_inode_metadata(struct inode *inode, int wait) | ||
| 1254 | { | ||
| 1255 | struct writeback_control wbc = { | ||
| 1256 | .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_NONE, | ||
| 1257 | .nr_to_write = 0, /* metadata-only */ | ||
| 1258 | }; | ||
| 1259 | |||
| 1260 | return sync_inode(inode, &wbc); | ||
| 1261 | } | ||
| 1262 | EXPORT_SYMBOL(sync_inode_metadata); | ||
