diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 6ceda2a4791c..f7acf9680c9b 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -4074,7 +4074,7 @@ static void delayed_work(struct work_struct *work) dout("mdsc delayed_work\n"); - if (mdsc->stopping) + if (mdsc->stopping >= CEPH_MDSC_STOPPING_FLUSHED) return; mutex_lock(&mdsc->mutex); @@ -4246,7 +4246,7 @@ static void wait_requests(struct ceph_mds_client *mdsc) void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc) { dout("pre_umount\n"); - mdsc->stopping = 1; + mdsc->stopping = CEPH_MDSC_STOPPING_BEGIN; lock_unlock_sessions(mdsc); ceph_flush_dirty_caps(mdsc); diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 14c7e8c49970..4fbbc33023c9 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -348,6 +348,11 @@ struct cap_wait { int want; }; +enum { + CEPH_MDSC_STOPPING_BEGIN = 1, + CEPH_MDSC_STOPPING_FLUSHED = 2, +}; + /* * mds client state */ diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 279334f95570..0e38678d5add 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -1180,6 +1180,16 @@ static void ceph_kill_sb(struct super_block *s) ceph_mdsc_pre_umount(fsc->mdsc); flush_fs_workqueues(fsc); + /* + * Though the kill_anon_super() will finally trigger the + * sync_filesystem() anyway, we still need to do it here + * and then bump the stage of shutdown to stop the work + * queue as earlier as possible. + */ + sync_filesystem(s); + + fsc->mdsc->stopping = CEPH_MDSC_STOPPING_FLUSHED; + kill_anon_super(s); fsc->client->extra_mon_dispatch = NULL;