diff options
author | Chris Mason <chris.mason@oracle.com> | 2010-10-29 11:16:17 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2010-10-29 11:25:29 -0400 |
commit | 3259f8bed2f0f57c2fdcdac1b510c3fa319ef97e (patch) | |
tree | 5f06f6c83413ca2fc7aec85ba0811a8c91904097 | |
parent | cb44921a09221f0a90217b44044448f63190f3e5 (diff) |
Add new functions for triggering inode writeback
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.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/fs-writeback.c | 52 | ||||
-rw-r--r-- | include/linux/writeback.h | 2 |
2 files changed, 44 insertions, 10 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ab38fef1c9a1..1e23c33ea5cf 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -1069,33 +1069,44 @@ static void wait_sb_inodes(struct super_block *sb) | |||
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 | * @sb: the superblock | 1073 | * @sb: the superblock |
1074 | * @nr: the number of pages to write | ||
1074 | * | 1075 | * |
1075 | * Start writeback on some inodes on this super_block. No guarantees are made | 1076 | * Start writeback on some inodes on this super_block. No guarantees are made |
1076 | * on how many (if any) will be written, and this function does not wait | 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 | * for IO completion of submitted IO. |
1078 | * returned. | ||
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 | DECLARE_COMPLETION_ONSTACK(done); | 1082 | DECLARE_COMPLETION_ONSTACK(done); |
1085 | struct wb_writeback_work work = { | 1083 | struct wb_writeback_work work = { |
1086 | .sb = sb, | 1084 | .sb = sb, |
1087 | .sync_mode = WB_SYNC_NONE, | 1085 | .sync_mode = WB_SYNC_NONE, |
1088 | .done = &done, | 1086 | .done = &done, |
1087 | .nr_pages = nr, | ||
1089 | }; | 1088 | }; |
1090 | 1089 | ||
1091 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | 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 | bdi_queue_work(sb->s_bdi, &work); | 1091 | bdi_queue_work(sb->s_bdi, &work); |
1097 | wait_for_completion(&done); | 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 | EXPORT_SYMBOL(writeback_inodes_sb); | 1110 | EXPORT_SYMBOL(writeback_inodes_sb); |
1100 | 1111 | ||
1101 | /** | 1112 | /** |
@@ -1118,6 +1129,27 @@ int writeback_inodes_sb_if_idle(struct super_block *sb) | |||
1118 | EXPORT_SYMBOL(writeback_inodes_sb_if_idle); | 1129 | EXPORT_SYMBOL(writeback_inodes_sb_if_idle); |
1119 | 1130 | ||
1120 | /** | 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 | |||
1152 | /** | ||
1121 | * sync_inodes_sb - sync sb inode pages | 1153 | * sync_inodes_sb - sync sb inode pages |
1122 | * @sb: the superblock | 1154 | * @sb: the superblock |
1123 | * | 1155 | * |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 72a5d647a5f2..a4cf84511e79 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -60,7 +60,9 @@ struct writeback_control { | |||
60 | struct bdi_writeback; | 60 | struct bdi_writeback; |
61 | int inode_wait(void *); | 61 | int inode_wait(void *); |
62 | void writeback_inodes_sb(struct super_block *); | 62 | void writeback_inodes_sb(struct super_block *); |
63 | void writeback_inodes_sb_nr(struct super_block *, unsigned long nr); | ||
63 | int writeback_inodes_sb_if_idle(struct super_block *); | 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 | void sync_inodes_sb(struct super_block *); | 66 | void sync_inodes_sb(struct super_block *); |
65 | void writeback_inodes_wb(struct bdi_writeback *wb, | 67 | void writeback_inodes_wb(struct bdi_writeback *wb, |
66 | struct writeback_control *wbc); | 68 | struct writeback_control *wbc); |