diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 8bc6a8807482..9d3618192009 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -163,6 +163,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) | |||
163 | unsigned long num_sync_run; | 163 | unsigned long num_sync_run; |
164 | unsigned long limit; | 164 | unsigned long limit; |
165 | unsigned long last_waited = 0; | 165 | unsigned long last_waited = 0; |
166 | int force_reg = 0; | ||
166 | 167 | ||
167 | bdi = blk_get_backing_dev_info(device->bdev); | 168 | bdi = blk_get_backing_dev_info(device->bdev); |
168 | fs_info = device->dev_root->fs_info; | 169 | fs_info = device->dev_root->fs_info; |
@@ -176,19 +177,22 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) | |||
176 | 177 | ||
177 | loop: | 178 | loop: |
178 | spin_lock(&device->io_lock); | 179 | spin_lock(&device->io_lock); |
179 | num_run = 0; | ||
180 | 180 | ||
181 | loop_lock: | 181 | loop_lock: |
182 | num_run = 0; | ||
182 | 183 | ||
183 | /* take all the bios off the list at once and process them | 184 | /* take all the bios off the list at once and process them |
184 | * later on (without the lock held). But, remember the | 185 | * later on (without the lock held). But, remember the |
185 | * tail and other pointers so the bios can be properly reinserted | 186 | * tail and other pointers so the bios can be properly reinserted |
186 | * into the list if we hit congestion | 187 | * into the list if we hit congestion |
187 | */ | 188 | */ |
188 | if (device->pending_sync_bios.head) | 189 | if (!force_reg && device->pending_sync_bios.head) { |
189 | pending_bios = &device->pending_sync_bios; | 190 | pending_bios = &device->pending_sync_bios; |
190 | else | 191 | force_reg = 1; |
192 | } else { | ||
191 | pending_bios = &device->pending_bios; | 193 | pending_bios = &device->pending_bios; |
194 | force_reg = 0; | ||
195 | } | ||
192 | 196 | ||
193 | pending = pending_bios->head; | 197 | pending = pending_bios->head; |
194 | tail = pending_bios->tail; | 198 | tail = pending_bios->tail; |
@@ -228,10 +232,14 @@ loop_lock: | |||
228 | while (pending) { | 232 | while (pending) { |
229 | 233 | ||
230 | rmb(); | 234 | rmb(); |
231 | if (pending_bios != &device->pending_sync_bios && | 235 | /* we want to work on both lists, but do more bios on the |
232 | device->pending_sync_bios.head && | 236 | * sync list than the regular list |
233 | num_run > 16) { | 237 | */ |
234 | cond_resched(); | 238 | if ((num_run > 32 && |
239 | pending_bios != &device->pending_sync_bios && | ||
240 | device->pending_sync_bios.head) || | ||
241 | (num_run > 64 && pending_bios == &device->pending_sync_bios && | ||
242 | device->pending_bios.head)) { | ||
235 | spin_lock(&device->io_lock); | 243 | spin_lock(&device->io_lock); |
236 | requeue_list(pending_bios, pending, tail); | 244 | requeue_list(pending_bios, pending, tail); |
237 | goto loop_lock; | 245 | goto loop_lock; |