diff options
Diffstat (limited to 'fs/fs-writeback.c')
| -rw-r--r-- | fs/fs-writeback.c | 68 |
1 files changed, 52 insertions, 16 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index aed881a76b22..3d06ccc953aa 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -707,6 +707,17 @@ get_next_work_item(struct backing_dev_info *bdi) | |||
| 707 | return work; | 707 | return work; |
| 708 | } | 708 | } |
| 709 | 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 | |||
| 710 | static long wb_check_old_data_flush(struct bdi_writeback *wb) | 721 | static long wb_check_old_data_flush(struct bdi_writeback *wb) |
| 711 | { | 722 | { |
| 712 | unsigned long expired; | 723 | unsigned long expired; |
| @@ -724,13 +735,7 @@ static long wb_check_old_data_flush(struct bdi_writeback *wb) | |||
| 724 | return 0; | 735 | return 0; |
| 725 | 736 | ||
| 726 | wb->last_old_flush = jiffies; | 737 | wb->last_old_flush = jiffies; |
| 727 | /* | 738 | nr_pages = get_nr_dirty_pages(); |
| 728 | * Add in the number of potentially dirty inodes, because each inode | ||
| 729 | * write can dirty pagecache in the underlying blockdev. | ||
| 730 | */ | ||
| 731 | nr_pages = global_page_state(NR_FILE_DIRTY) + | ||
| 732 | global_page_state(NR_UNSTABLE_NFS) + | ||
| 733 | get_nr_dirty_inodes(); | ||
| 734 | 739 | ||
| 735 | if (nr_pages) { | 740 | if (nr_pages) { |
| 736 | struct wb_writeback_work work = { | 741 | struct wb_writeback_work work = { |
| @@ -1076,32 +1081,42 @@ static void wait_sb_inodes(struct super_block *sb) | |||
| 1076 | } | 1081 | } |
| 1077 | 1082 | ||
| 1078 | /** | 1083 | /** |
| 1079 | * writeback_inodes_sb - writeback dirty inodes from given super_block | 1084 | * writeback_inodes_sb_nr - writeback dirty inodes from given super_block |
| 1080 | * @sb: the superblock | 1085 | * @sb: the superblock |
| 1086 | * @nr: the number of pages to write | ||
| 1081 | * | 1087 | * |
| 1082 | * Start writeback on some inodes on this super_block. No guarantees are made | 1088 | * Start writeback on some inodes on this super_block. No guarantees are made |
| 1083 | * on how many (if any) will be written, and this function does not wait | 1089 | * on how many (if any) will be written, and this function does not wait |
| 1084 | * for IO completion of submitted IO. The number of pages submitted is | 1090 | * for IO completion of submitted IO. |
| 1085 | * returned. | ||
| 1086 | */ | 1091 | */ |
| 1087 | void writeback_inodes_sb(struct super_block *sb) | 1092 | void writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr) |
| 1088 | { | 1093 | { |
| 1089 | unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY); | ||
| 1090 | unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS); | ||
| 1091 | DECLARE_COMPLETION_ONSTACK(done); | 1094 | DECLARE_COMPLETION_ONSTACK(done); |
| 1092 | struct wb_writeback_work work = { | 1095 | struct wb_writeback_work work = { |
| 1093 | .sb = sb, | 1096 | .sb = sb, |
| 1094 | .sync_mode = WB_SYNC_NONE, | 1097 | .sync_mode = WB_SYNC_NONE, |
| 1095 | .done = &done, | 1098 | .done = &done, |
| 1099 | .nr_pages = nr, | ||
| 1096 | }; | 1100 | }; |
| 1097 | 1101 | ||
| 1098 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | 1102 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
| 1099 | |||
| 1100 | work.nr_pages = nr_dirty + nr_unstable + get_nr_dirty_inodes(); | ||
| 1101 | |||
| 1102 | bdi_queue_work(sb->s_bdi, &work); | 1103 | bdi_queue_work(sb->s_bdi, &work); |
| 1103 | wait_for_completion(&done); | 1104 | wait_for_completion(&done); |
| 1104 | } | 1105 | } |
| 1106 | EXPORT_SYMBOL(writeback_inodes_sb_nr); | ||
| 1107 | |||
| 1108 | /** | ||
| 1109 | * writeback_inodes_sb - writeback dirty inodes from given super_block | ||
| 1110 | * @sb: the superblock | ||
| 1111 | * | ||
| 1112 | * Start writeback on some inodes on this super_block. No guarantees are made | ||
| 1113 | * on how many (if any) will be written, and this function does not wait | ||
| 1114 | * for IO completion of submitted IO. | ||
| 1115 | */ | ||
| 1116 | void writeback_inodes_sb(struct super_block *sb) | ||
| 1117 | { | ||
| 1118 | return writeback_inodes_sb_nr(sb, get_nr_dirty_pages()); | ||
| 1119 | } | ||
| 1105 | EXPORT_SYMBOL(writeback_inodes_sb); | 1120 | EXPORT_SYMBOL(writeback_inodes_sb); |
| 1106 | 1121 | ||
| 1107 | /** | 1122 | /** |
| @@ -1124,6 +1139,27 @@ int writeback_inodes_sb_if_idle(struct super_block *sb) | |||
| 1124 | EXPORT_SYMBOL(writeback_inodes_sb_if_idle); | 1139 | EXPORT_SYMBOL(writeback_inodes_sb_if_idle); |
| 1125 | 1140 | ||
| 1126 | /** | 1141 | /** |
| 1142 | * writeback_inodes_sb_if_idle - start writeback if none underway | ||
| 1143 | * @sb: the superblock | ||
| 1144 | * @nr: the number of pages to write | ||
| 1145 | * | ||
| 1146 | * Invoke writeback_inodes_sb if no writeback is currently underway. | ||
| 1147 | * Returns 1 if writeback was started, 0 if not. | ||
| 1148 | */ | ||
| 1149 | int writeback_inodes_sb_nr_if_idle(struct super_block *sb, | ||
| 1150 | unsigned long nr) | ||
| 1151 | { | ||
| 1152 | if (!writeback_in_progress(sb->s_bdi)) { | ||
| 1153 | down_read(&sb->s_umount); | ||
| 1154 | writeback_inodes_sb_nr(sb, nr); | ||
| 1155 | up_read(&sb->s_umount); | ||
| 1156 | return 1; | ||
| 1157 | } else | ||
| 1158 | return 0; | ||
| 1159 | } | ||
| 1160 | EXPORT_SYMBOL(writeback_inodes_sb_nr_if_idle); | ||
| 1161 | |||
| 1162 | /** | ||
| 1127 | * sync_inodes_sb - sync sb inode pages | 1163 | * sync_inodes_sb - sync sb inode pages |
| 1128 | * @sb: the superblock | 1164 | * @sb: the superblock |
| 1129 | * | 1165 | * |
