}
-/*
- * drop all leases (and dentry refs) in preparation for umount
- */
-void ceph_mdsc_drop_leases(struct ceph_mds_client *mdsc)
-{
- int i;
-
- spin_lock(&mdsc->lock);
- for (i = 0; i < mdsc->max_sessions; i++) {
- struct ceph_mds_session *session = __get_session(mdsc, i);
- if (!session)
- continue;
- spin_unlock(&mdsc->lock);
- remove_session_leases(session);
- spin_lock(&mdsc->lock);
- }
- spin_unlock(&mdsc->lock);
-}
-
/* exported functions */
spin_lock_init(&mdsc->cap_delay_lock);
}
+/*
+ * drop all leases (and dentry refs) in preparation for umount
+ */
+static void drop_leases(struct ceph_mds_client *mdsc)
+{
+ int i;
+
+ spin_lock(&mdsc->lock);
+ for (i = 0; i < mdsc->max_sessions; i++) {
+ struct ceph_mds_session *session = __get_session(mdsc, i);
+ if (!session)
+ continue;
+ spin_unlock(&mdsc->lock);
+ remove_session_leases(session);
+ spin_lock(&mdsc->lock);
+ }
+ spin_unlock(&mdsc->lock);
+}
+
+/*
+ * called before mount is ro, and before dentries are torn down.
+ * (hmm, does this still race with new lookups?)
+ */
+void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc)
+{
+ drop_leases(mdsc);
+ check_delayed_caps(mdsc);
+}
+
+/*
+ * called after sb is ro.
+ */
void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
{
struct ceph_mds_session *session;
}
spin_unlock(&mdsc->lock);
+ dout(10, "stopped\n");
}
struct ceph_mds_session *session,
struct ceph_inode_cap *cap,
int used, int wanted, int cancel_work);
-extern void ceph_mdsc_drop_leases(struct ceph_mds_client *mdsc);
+extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc);
#endif
return 0;
}
-
-static void ceph_umount_start(struct ceph_client *cl)
+static void ceph_put_super(struct super_block *s)
{
+ struct ceph_client *cl = ceph_client(s);
int rc;
int seconds = 15;
+ dout(30, "put_super\n");
ceph_mdsc_stop(&cl->mdsc);
ceph_monc_request_umount(&cl->monc);
+
rc = wait_event_timeout(cl->mount_wq,
(cl->mount_state == CEPH_MOUNT_UNMOUNTED),
seconds*HZ);
if (rc == 0)
derr(0, "umount timed out after %d seconds\n", seconds);
-}
-static void ceph_put_super(struct super_block *s)
-{
- dout(30, "ceph_put_super\n");
- ceph_umount_start(ceph_client(s));
return;
}
{
struct ceph_client *client = ceph_sb_to_client(s);
dout(1, "kill_sb %p\n", s);
- ceph_mdsc_drop_leases(&client->mdsc);
+ ceph_mdsc_pre_umount(&client->mdsc);
kill_anon_super(s); /* will call put_super after sb is r/o */
ceph_destroy_client(client);
}