diff options
Diffstat (limited to 'fs/fs-writeback.c')
-rw-r--r-- | fs/fs-writeback.c | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 4b37f7cea4dd..1d1088f48bc2 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -42,9 +42,9 @@ struct wb_writeback_args { | |||
42 | long nr_pages; | 42 | long nr_pages; |
43 | struct super_block *sb; | 43 | struct super_block *sb; |
44 | enum writeback_sync_modes sync_mode; | 44 | enum writeback_sync_modes sync_mode; |
45 | int for_kupdate:1; | 45 | unsigned int for_kupdate:1; |
46 | int range_cyclic:1; | 46 | unsigned int range_cyclic:1; |
47 | int for_background:1; | 47 | unsigned int for_background:1; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | /* | 50 | /* |
@@ -398,11 +398,11 @@ static void inode_wait_for_writeback(struct inode *inode) | |||
398 | wait_queue_head_t *wqh; | 398 | wait_queue_head_t *wqh; |
399 | 399 | ||
400 | wqh = bit_waitqueue(&inode->i_state, __I_SYNC); | 400 | wqh = bit_waitqueue(&inode->i_state, __I_SYNC); |
401 | do { | 401 | while (inode->i_state & I_SYNC) { |
402 | spin_unlock(&inode_lock); | 402 | spin_unlock(&inode_lock); |
403 | __wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE); | 403 | __wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE); |
404 | spin_lock(&inode_lock); | 404 | spin_lock(&inode_lock); |
405 | } while (inode->i_state & I_SYNC); | 405 | } |
406 | } | 406 | } |
407 | 407 | ||
408 | /* | 408 | /* |
@@ -452,11 +452,9 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
452 | 452 | ||
453 | BUG_ON(inode->i_state & I_SYNC); | 453 | BUG_ON(inode->i_state & I_SYNC); |
454 | 454 | ||
455 | /* Set I_SYNC, reset I_DIRTY */ | 455 | /* Set I_SYNC, reset I_DIRTY_PAGES */ |
456 | dirty = inode->i_state & I_DIRTY; | ||
457 | inode->i_state |= I_SYNC; | 456 | inode->i_state |= I_SYNC; |
458 | inode->i_state &= ~I_DIRTY; | 457 | inode->i_state &= ~I_DIRTY_PAGES; |
459 | |||
460 | spin_unlock(&inode_lock); | 458 | spin_unlock(&inode_lock); |
461 | 459 | ||
462 | ret = do_writepages(mapping, wbc); | 460 | ret = do_writepages(mapping, wbc); |
@@ -472,6 +470,15 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
472 | ret = err; | 470 | ret = err; |
473 | } | 471 | } |
474 | 472 | ||
473 | /* | ||
474 | * Some filesystems may redirty the inode during the writeback | ||
475 | * due to delalloc, clear dirty metadata flags right before | ||
476 | * write_inode() | ||
477 | */ | ||
478 | spin_lock(&inode_lock); | ||
479 | dirty = inode->i_state & I_DIRTY; | ||
480 | inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC); | ||
481 | spin_unlock(&inode_lock); | ||
475 | /* Don't write the inode if only I_DIRTY_PAGES was set */ | 482 | /* Don't write the inode if only I_DIRTY_PAGES was set */ |
476 | if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { | 483 | if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { |
477 | int err = write_inode(inode, wbc); | 484 | int err = write_inode(inode, wbc); |
@@ -852,6 +859,12 @@ static long wb_check_old_data_flush(struct bdi_writeback *wb) | |||
852 | unsigned long expired; | 859 | unsigned long expired; |
853 | long nr_pages; | 860 | long nr_pages; |
854 | 861 | ||
862 | /* | ||
863 | * When set to zero, disable periodic writeback | ||
864 | */ | ||
865 | if (!dirty_writeback_interval) | ||
866 | return 0; | ||
867 | |||
855 | expired = wb->last_old_flush + | 868 | expired = wb->last_old_flush + |
856 | msecs_to_jiffies(dirty_writeback_interval * 10); | 869 | msecs_to_jiffies(dirty_writeback_interval * 10); |
857 | if (time_before(jiffies, expired)) | 870 | if (time_before(jiffies, expired)) |
@@ -947,8 +960,17 @@ int bdi_writeback_task(struct bdi_writeback *wb) | |||
947 | break; | 960 | break; |
948 | } | 961 | } |
949 | 962 | ||
950 | wait_jiffies = msecs_to_jiffies(dirty_writeback_interval * 10); | 963 | if (dirty_writeback_interval) { |
951 | schedule_timeout_interruptible(wait_jiffies); | 964 | wait_jiffies = msecs_to_jiffies(dirty_writeback_interval * 10); |
965 | schedule_timeout_interruptible(wait_jiffies); | ||
966 | } else { | ||
967 | set_current_state(TASK_INTERRUPTIBLE); | ||
968 | if (list_empty_careful(&wb->bdi->work_list) && | ||
969 | !kthread_should_stop()) | ||
970 | schedule(); | ||
971 | __set_current_state(TASK_RUNNING); | ||
972 | } | ||
973 | |||
952 | try_to_freeze(); | 974 | try_to_freeze(); |
953 | } | 975 | } |
954 | 976 | ||