#include <sys/zfs_vfsops.h>
#include <sys/zfs_vnops.h>
#include <sys/zfs_znode.h>
+#include <sys/zfs_ctldir.h>
#include <sys/zpl.h>
return (error);
}
-static int
-zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp)
+static void
+zpl_umount_begin(struct super_block *sb)
{
- struct super_block *sb = vfsp->mnt_sb;
zfs_sb_t *zsb = sb->s_fs_info;
+ int count;
/*
- * The Linux VFS automatically handles the following flags:
- * MNT_NOSUID, MNT_NODEV, MNT_NOEXEC, MNT_NOATIME, MNT_READONLY
+ * Best effort to unmount snapshots in .zfs/snapshot/. Normally this
+ * isn't required because snapshots have the MNT_SHRINKABLE flag set.
*/
+ if (zsb->z_ctldir)
+ (void) zfsctl_unmount_snapshots(zsb, MNT_FORCE, &count);
+}
+
+/*
+ * The Linux VFS automatically handles the following flags:
+ * MNT_NOSUID, MNT_NODEV, MNT_NOEXEC, MNT_NOATIME, MNT_READONLY
+ */
+#ifdef HAVE_SHOW_OPTIONS_WITH_DENTRY
+static int
+zpl_show_options(struct seq_file *seq, struct dentry *root)
+{
+ zfs_sb_t *zsb = root->d_sb->s_fs_info;
seq_printf(seq, ",%s", zsb->z_flags & ZSB_XATTR ? "xattr" : "noxattr");
return (0);
}
+#else
+static int
+zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp)
+{
+ zfs_sb_t *zsb = vfsp->mnt_sb->s_fs_info;
+
+ seq_printf(seq, ",%s", zsb->z_flags & ZSB_XATTR ? "xattr" : "noxattr");
+
+ return (0);
+}
+#endif /* HAVE_SHOW_OPTIONS_WITH_DENTRY */
static int
zpl_fill_super(struct super_block *sb, void *data, int silent)
static void
zpl_kill_sb(struct super_block *sb)
{
-#ifdef HAVE_SNAPSHOT
- zfs_sb_t *zsb = sb->s_fs_info;
-
- if (zsb && dmu_objset_is_snapshot(zsb->z_os))
- zfs_snap_destroy(zsb);
-#endif /* HAVE_SNAPSHOT */
-
+ zfs_preumount(sb);
kill_anon_super(sb);
}
.sync_fs = zpl_sync_fs,
.statfs = zpl_statfs,
.remount_fs = zpl_remount_fs,
+ .umount_begin = zpl_umount_begin,
.show_options = zpl_show_options,
.show_stats = NULL,
#ifdef HAVE_NR_CACHED_OBJECTS