Add Hooks for Linux Super Block Operations
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 26 Jan 2011 20:09:10 +0000 (12:09 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 10 Feb 2011 17:27:21 +0000 (09:27 -0800)
The Linux specific super block operations have all been located in the
file zpl_super.c.  These functions primarily rely on the reworked
zfs_* functions to do their job.  They are also responsible for
converting the possible Solaris style error codes to negative
Linux errors.

module/zfs/zpl_super.c [new file with mode: 0644]

diff --git a/module/zfs/zpl_super.c b/module/zfs/zpl_super.c
new file mode 100644 (file)
index 0000000..bbb7bea
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2011, Lawrence Livermore National Security, LLC.
+ */
+
+
+#include <sys/zfs_vfsops.h>
+#include <sys/zfs_vnops.h>
+#include <sys/zfs_znode.h>
+#include <sys/zpl.h>
+
+
+static struct inode *
+zpl_inode_alloc(struct super_block *sb)
+{
+       struct inode *ip;
+
+       VERIFY3S(zfs_inode_alloc(sb, &ip), ==, 0);
+       ip->i_version = 1;
+
+       return (ip);
+}
+
+static void
+zpl_inode_destroy(struct inode *ip)
+{
+        ASSERT(atomic_read(&ip->i_count) == 0);
+       zfs_inode_destroy(ip);
+}
+
+static void
+zpl_inode_delete(struct inode *ip)
+{
+       loff_t oldsize = i_size_read(ip);
+
+       i_size_write(ip, 0);
+       truncate_pagecache(ip, oldsize, 0);
+       clear_inode(ip);
+}
+
+static void
+zpl_evict_inode(struct inode *ip)
+{
+       zfs_inactive(ip);
+}
+
+static void
+zpl_put_super(struct super_block *sb)
+{
+       int error;
+
+       error = -zfs_umount(sb);
+       ASSERT3S(error, <=, 0);
+}
+
+static int
+zpl_statfs(struct dentry *dentry, struct kstatfs *statp)
+{
+       int error;
+
+       error = -zfs_statvfs(dentry, statp);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp)
+{
+       struct super_block *sb = vfsp->mnt_sb;
+       zfs_sb_t *zsb = sb->s_fs_info;
+
+       /*
+        * The Linux VFS automatically handles the following flags:
+        * MNT_NOSUID, MNT_NODEV, MNT_NOEXEC, MNT_NOATIME, MNT_READONLY
+        */
+
+       if (zsb->z_flags & ZSB_XATTR_USER)
+               seq_printf(seq, ",%s", "xattr");
+
+       return (0);
+}
+
+static int
+zpl_fill_super(struct super_block *sb, void *data, int silent)
+{
+       int error;
+
+       error = -zfs_domount(sb, data, silent);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+zpl_get_sb(struct file_system_type *fs_type, int flags,
+    const char *osname, void *data, struct vfsmount *mnt)
+{
+       zpl_mount_data_t zmd = { osname, data, mnt };
+
+       return get_sb_nodev(fs_type, flags, &zmd, zpl_fill_super, mnt);
+}
+
+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 */
+
+       kill_anon_super(sb);
+}
+
+const struct super_operations zpl_super_operations = {
+       .alloc_inode    = zpl_inode_alloc,
+       .destroy_inode  = zpl_inode_destroy,
+       .delete_inode   = zpl_inode_delete,
+       .dirty_inode    = NULL,
+       .write_inode    = NULL,
+       .drop_inode     = NULL,
+       .clear_inode    = zpl_evict_inode,
+       .put_super      = zpl_put_super,
+       .write_super    = NULL,
+       .sync_fs        = NULL,
+       .freeze_fs      = NULL,
+       .unfreeze_fs    = NULL,
+       .statfs         = zpl_statfs,
+       .remount_fs     = NULL,
+       .show_options   = zpl_show_options,
+       .show_stats     = NULL,
+};
+
+#if 0
+const struct export_operations zpl_export_operations = {
+       .fh_to_dentry   = NULL,
+       .fh_to_parent   = NULL,
+       .get_parent     = NULL,
+};
+#endif
+
+struct file_system_type zpl_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = ZFS_DRIVER,
+       .get_sb         = zpl_get_sb,
+       .kill_sb        = zpl_kill_sb,
+};