@@ -44,6 +44,7 @@ struct wb_writeback_args {
int for_kupdate:1;
int range_cyclic:1;
int for_background:1;
+ int locked:1;
};
/*
@@ -251,13 +252,14 @@ static void bdi_sync_writeback(struct backing_dev_info *bdi,
*
*/
void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
- long nr_pages)
+ long nr_pages, int locked)
{
struct wb_writeback_args args = {
.sb = sb,
.sync_mode = WB_SYNC_NONE,
.nr_pages = nr_pages,
.range_cyclic = 1,
+ .locked = locked,
};
/*
@@ -584,7 +586,7 @@ static int pin_sb_for_writeback(struct writeback_control *wbc,
/*
* Caller must already hold the ref for this
*/
- if (wbc->sync_mode == WB_SYNC_ALL) {
+ if (wbc->sync_mode == WB_SYNC_ALL || wbc->locked) {
WARN_ON(!rwsem_is_locked(&sb->s_umount));
return 0;
}
@@ -757,6 +759,7 @@ static long wb_writeback(struct bdi_writeback *wb,
.older_than_this = NULL,
.for_kupdate = args->for_kupdate,
.range_cyclic = args->range_cyclic,
+ .locked = args->locked,
};
unsigned long oldest_jif;
long wrote = 0;
@@ -905,7 +908,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
* If this isn't a data integrity operation, just notify
* that we have seen this work and we are now starting it.
*/
- if (args.sync_mode == WB_SYNC_NONE)
+ if (args.sync_mode == WB_SYNC_NONE && !args.locked)
wb_clear_pending(wb, work);
wrote += wb_writeback(wb, &args);
@@ -914,7 +917,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
* This is a data integrity writeback, so only do the
* notification when we have completed the work.
*/
- if (args.sync_mode == WB_SYNC_ALL)
+ if (args.sync_mode == WB_SYNC_ALL || args.locked)
wb_clear_pending(wb, work);
}
@@ -1193,13 +1196,14 @@ static void wait_sb_inodes(struct super_block *sb)
/**
* writeback_inodes_sb - writeback dirty inodes from given super_block
* @sb: the superblock
+ * @locked: sb already pinned
*
* Start writeback on some inodes on this super_block. No guarantees are made
* on how many (if any) will be written, and this function does not wait
* for IO completion of submitted IO. The number of pages submitted is
* returned.
*/
-void writeback_inodes_sb(struct super_block *sb)
+void writeback_inodes_sb(struct super_block *sb, int locked)
{
unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY);
unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS);
@@ -1208,7 +1212,7 @@ void writeback_inodes_sb(struct super_block *sb)
nr_to_write = nr_dirty + nr_unstable +
(inodes_stat.nr_inodes - inodes_stat.nr_unused);
- bdi_start_writeback(sb->s_bdi, sb, nr_to_write);
+ bdi_start_writeback(sb->s_bdi, sb, nr_to_write, locked);
}
EXPORT_SYMBOL(writeback_inodes_sb);
@@ -37,7 +37,7 @@ static int __sync_filesystem(struct super_block *sb, int wait)
/* Avoid doing twice syncing and cache pruning for quota sync */
if (!wait) {
writeout_quota_sb(sb, -1);
- writeback_inodes_sb(sb);
+ writeback_inodes_sb(sb, 1);
} else {
sync_quota_sb(sb, -1);
sync_inodes_sb(sb);
@@ -62,7 +62,7 @@
*/
static void shrink_liability(struct ubifs_info *c, int nr_to_write)
{
- writeback_inodes_sb(c->vfs_sb);
+ writeback_inodes_sb(c->vfs_sb, 0);
}
/**
@@ -102,7 +102,7 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent,
int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
void bdi_unregister(struct backing_dev_info *bdi);
void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
- long nr_pages);
+ long nr_pages, int locked);
int bdi_writeback_task(struct bdi_writeback *wb);
int bdi_has_dirty_io(struct backing_dev_info *bdi);
@@ -52,6 +52,8 @@ struct writeback_control {
unsigned for_reclaim:1; /* Invoked from the page allocator */
unsigned range_cyclic:1; /* range_start is cyclic */
unsigned more_io:1; /* more io to be dispatched */
+ unsigned locked:1; /* sb pinned for WB_SYNC_NONE */
+
/*
* write_cache_pages() won't update wbc->nr_to_write and
* mapping->writeback_index if no_nrwrite_index_update
@@ -68,7 +70,7 @@ struct writeback_control {
*/
struct bdi_writeback;
int inode_wait(void *);
-void writeback_inodes_sb(struct super_block *);
+void writeback_inodes_sb(struct super_block *, int);
void sync_inodes_sb(struct super_block *);
void writeback_inodes_wbc(struct writeback_control *wbc);
long wb_do_writeback(struct bdi_writeback *wb, int force_wait);
@@ -597,7 +597,7 @@ static void balance_dirty_pages(struct address_space *mapping,
(!laptop_mode && ((global_page_state(NR_FILE_DIRTY)
+ global_page_state(NR_UNSTABLE_NFS))
> background_thresh)))
- bdi_start_writeback(bdi, NULL, 0);
+ bdi_start_writeback(bdi, NULL, 0, 0);
}
void set_page_dirty_balance(struct page *page, int page_mkwrite)