diff options
author | Gary King <gking@nvidia.com> | 2010-06-09 21:33:15 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-06-11 09:43:06 -0700 |
commit | 18362ebbdb53cca48ec201bece4e3a31680671e4 (patch) | |
tree | 65bf1fd6c00adcc05fb33367b91d36e3f681405a /fs | |
parent | 113698fce657e304b2b389df701718d29958a8d7 (diff) |
fs: writeback: do not sync superblocks if bdi tasks are freezing
during a system suspend operation without MMC_UNSAFE_RESUME, the mmc stack
removes all of the cards on the bus so that they can be redetected during
resume
for data cards, the remove operation causes calls to sync the file
systems on the mounted partitions
however, since this happens during the device driver suspend path,
tasks will already be frozen, including the bdi flusher task which are
responsible for performing all of the queued operations to sync the removed
card's file system. since the superblock sync is a blocking operation, this
causes a deadlock, as the suspend operation is blocked on a frozen task
this patch causes the fs-writeback code to skip the superblock sync if
the bdi flusher tasks are freezing or already frozen, to prevent the
deadlock
Change-Id: I5970ac9a50f1968ba5f413a46be0c2e16222581c
Reviewed-on: http://git-master/r/2373
Reviewed-by: Pavan Kunapuli <pkunapuli@nvidia.com>
Tested-by: Pavan Kunapuli <pkunapuli@nvidia.com>
Reviewed-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fs-writeback.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index b1ff16fec7f2..25aaf5efe6fa 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1199,12 +1199,17 @@ static void wait_sb_inodes(struct super_block *sb) * for IO completion of submitted IO. The number of pages submitted is * returned. */ +#define freezing_or_frozen(x) (freezing(x) || frozen(x)) + void writeback_inodes_sb(struct super_block *sb) { unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY); unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS); long nr_to_write; + if (unlikely(freezing_or_frozen(default_backing_dev_info.wb.task))) + return; + nr_to_write = nr_dirty + nr_unstable + (inodes_stat.nr_inodes - inodes_stat.nr_unused); @@ -1221,6 +1226,9 @@ EXPORT_SYMBOL(writeback_inodes_sb); */ void sync_inodes_sb(struct super_block *sb) { + if (unlikely(freezing_or_frozen(default_backing_dev_info.wb.task))) + return; + bdi_sync_writeback(sb->s_bdi, sb); wait_sb_inodes(sb); } |