|
@@ -1468,6 +1468,37 @@ static int do_umount(struct mount *mnt, int flags)
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * __detach_mounts - lazily unmount all mounts on the specified dentry
|
|
|
+ *
|
|
|
+ * During unlink, rmdir, and d_drop it is possible to loose the path
|
|
|
+ * to an existing mountpoint, and wind up leaking the mount.
|
|
|
+ * detach_mounts allows lazily unmounting those mounts instead of
|
|
|
+ * leaking them.
|
|
|
+ *
|
|
|
+ * The caller may hold dentry->d_inode->i_mutex.
|
|
|
+ */
|
|
|
+void __detach_mounts(struct dentry *dentry)
|
|
|
+{
|
|
|
+ struct mountpoint *mp;
|
|
|
+ struct mount *mnt;
|
|
|
+
|
|
|
+ namespace_lock();
|
|
|
+ mp = lookup_mountpoint(dentry);
|
|
|
+ if (!mp)
|
|
|
+ goto out_unlock;
|
|
|
+
|
|
|
+ lock_mount_hash();
|
|
|
+ while (!hlist_empty(&mp->m_list)) {
|
|
|
+ mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
|
|
|
+ umount_tree(mnt, 2);
|
|
|
+ }
|
|
|
+ unlock_mount_hash();
|
|
|
+ put_mountpoint(mp);
|
|
|
+out_unlock:
|
|
|
+ namespace_unlock();
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Is the caller allowed to modify his namespace?
|
|
|
*/
|