When btrfs is running low on metadata space, it needs to force delayed allocation pages to disk. It currently does this with a suboptimal walk of a private list of inodes with delayed allocation, and it would be much better if we used the generic flusher threads. writeback_inodes_sb_if_idle would be ideal, but it waits for the flusher thread to start IO on all the dirty pages in the FS before it returns. This adds variants of writeback_inodes_sb* that allow the caller to control how many pages get sent down.
Unified · Split
| @@ -1069,33 +1069,44 @@ static void wait_sb_inodes(struct super_block *sb) · 1068 unmodified lines | ||
| 1069 | 1069 | } |
| 1070 | 1070 | |
| 1071 | 1071 | /** |
| 1072 | − * writeback_inodes_sb - writeback dirty inodes from given super_block | |
| 1072 | + * writeback_inodes_sb_nr - writeback dirty inodes from given super_block | |
| 1073 | 1073 | * @sb: the superblock |
| 1074 | + * @nr: the number of pages to write | |
| 1074 | 1075 | * |
| 1075 | 1076 | * Start writeback on some inodes on this super_block. No guarantees are made |
| 1076 | 1077 | * on how many (if any) will be written, and this function does not wait |
| 1077 | − * for IO completion of submitted IO. The number of pages submitted is | |
| 1078 | − * returned. | |
| 1078 | + * for IO completion of submitted IO. | |
| 1079 | 1079 | */ |
| 1080 | −void writeback_inodes_sb(struct super_block *sb) | |
| 1080 | +void writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr) | |
| 1081 | 1081 | { |
| 1082 | − unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY); | |
| 1083 | − unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS); | |
| 1084 | 1082 | DECLARE_COMPLETION_ONSTACK(done); |
| 1085 | 1083 | struct wb_writeback_work work = { |
| 1086 | 1084 | .sb = sb, |
| 1087 | 1085 | .sync_mode = WB_SYNC_NONE, |
| 1088 | 1086 | .done = &done, |
| 1087 | + .nr_pages = nr, | |
| 1089 | 1088 | }; |
| 1090 | 1089 | |
| 1091 | 1090 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
| 1092 | − | |
| 1093 | − work.nr_pages = nr_dirty + nr_unstable + | |
| 1094 | − (inodes_stat.nr_inodes - inodes_stat.nr_unused); | |
| 1095 | − | |
| 1096 | 1091 | bdi_queue_work(sb->s_bdi, &work); |
| 1097 | 1092 | wait_for_completion(&done); |
| 1098 | 1093 | } |
| 1094 | +EXPORT_SYMBOL(writeback_inodes_sb_nr); | |
| 1095 | + | |
| 1096 | +/** | |
| 1097 | + * writeback_inodes_sb - writeback dirty inodes from given super_block | |
| 1098 | + * @sb: the superblock | |
| 1099 | + * | |
| 1100 | + * Start writeback on some inodes on this super_block. No guarantees are made | |
| 1101 | + * on how many (if any) will be written, and this function does not wait | |
| 1102 | + * for IO completion of submitted IO. | |
| 1103 | + */ | |
| 1104 | +void writeback_inodes_sb(struct super_block *sb) | |
| 1105 | +{ | |
| 1106 | + return writeback_inodes_sb_nr(sb, global_page_state(NR_FILE_DIRTY) + | |
| 1107 | + global_page_state(NR_UNSTABLE_NFS) + | |
| 1108 | + (inodes_stat.nr_inodes - inodes_stat.nr_unused)); | |
| 1109 | +} | |
| 1099 | 1110 | EXPORT_SYMBOL(writeback_inodes_sb); |
| 1100 | 1111 | |
| 1101 | 1112 | /** |
| @@ -1117,6 +1128,27 @@ int writeback_inodes_sb_if_idle(struct super_block *sb) · 15 unmodified lines | ||
| 1117 | 1128 | } |
| 1118 | 1129 | EXPORT_SYMBOL(writeback_inodes_sb_if_idle); |
| 1119 | 1130 | |
| 1131 | +/** | |
| 1132 | + * writeback_inodes_sb_if_idle - start writeback if none underway | |
| 1133 | + * @sb: the superblock | |
| 1134 | + * @nr: the number of pages to write | |
| 1135 | + * | |
| 1136 | + * Invoke writeback_inodes_sb if no writeback is currently underway. | |
| 1137 | + * Returns 1 if writeback was started, 0 if not. | |
| 1138 | + */ | |
| 1139 | +int writeback_inodes_sb_nr_if_idle(struct super_block *sb, | |
| 1140 | + unsigned long nr) | |
| 1141 | +{ | |
| 1142 | + if (!writeback_in_progress(sb->s_bdi)) { | |
| 1143 | + down_read(&sb->s_umount); | |
| 1144 | + writeback_inodes_sb_nr(sb, nr); | |
| 1145 | + up_read(&sb->s_umount); | |
| 1146 | + return 1; | |
| 1147 | + } else | |
| 1148 | + return 0; | |
| 1149 | +} | |
| 1150 | +EXPORT_SYMBOL(writeback_inodes_sb_nr_if_idle); | |
| 1151 | + | |
| 1120 | 1152 | /** |
| 1121 | 1153 | * sync_inodes_sb - sync sb inode pages |
| 1122 | 1154 | * @sb: the superblock |
| @@ -60,7 +60,9 @@ struct writeback_control { · 59 unmodified lines | ||
| 60 | 60 | struct bdi_writeback; |
| 61 | 61 | int inode_wait(void *); |
| 62 | 62 | void writeback_inodes_sb(struct super_block *); |
| 63 | +void writeback_inodes_sb_nr(struct super_block *, unsigned long nr); | |
| 63 | 64 | int writeback_inodes_sb_if_idle(struct super_block *); |
| 65 | +int writeback_inodes_sb_nr_if_idle(struct super_block *, unsigned long nr); | |
| 64 | 66 | void sync_inodes_sb(struct super_block *); |
| 65 | 67 | void writeback_inodes_wb(struct bdi_writeback *wb, |
| 66 | 68 | struct writeback_control *wbc); |