summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-06-09 21:33:15 -0700
committerGary King <gking@nvidia.com>2010-06-11 09:43:06 -0700
commit18362ebbdb53cca48ec201bece4e3a31680671e4 (patch)
tree65bf1fd6c00adcc05fb33367b91d36e3f681405a /fs
parent113698fce657e304b2b389df701718d29958a8d7 (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.c8
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);
}