Linux compat 2.6.39: mount_nodev()
[zfs.git] / module / zfs / zpl_super.c
index bbb7bea..650e9c0 100644 (file)
@@ -47,23 +47,55 @@ zpl_inode_destroy(struct inode *ip)
        zfs_inode_destroy(ip);
 }
 
+/*
+ * When ->drop_inode() is called its return value indicates if the
+ * inode should be evicted from the inode cache.  If the inode is
+ * unhashed and has no links the default policy is to evict it
+ * immediately.
+ *
+ * Prior to 2.6.36 this eviction was accomplished by the vfs calling
+ * ->delete_inode().  It was ->delete_inode()'s responsibility to
+ * truncate the inode pages and call clear_inode().  The call to
+ * clear_inode() synchronously invalidates all the buffers and
+ * calls ->clear_inode().  It was ->clear_inode()'s responsibility
+ * to cleanup and filesystem specific data before freeing the inode.
+ *
+ * This elaborate mechanism was replaced by ->evict_inode() which
+ * does the job of both ->delete_inode() and ->clear_inode().  It
+ * will be called exactly once, and when it returns the inode must
+ * be in a state where it can simply be freed.  The ->evict_inode()
+ * callback must minimally truncate the inode pages, and call
+ * end_writeback() to complete all outstanding writeback for the
+ * inode.  After this is complete evict inode can cleanup any
+ * remaining filesystem specific data.
+ */
+#ifdef HAVE_EVICT_INODE
 static void
-zpl_inode_delete(struct inode *ip)
+zpl_evict_inode(struct inode *ip)
 {
-       loff_t oldsize = i_size_read(ip);
-
-       i_size_write(ip, 0);
-       truncate_pagecache(ip, oldsize, 0);
-       clear_inode(ip);
+       truncate_setsize(ip, 0);
+       end_writeback(ip);
+       zfs_inactive(ip);
 }
 
+#else
+
 static void
-zpl_evict_inode(struct inode *ip)
+zpl_clear_inode(struct inode *ip)
 {
        zfs_inactive(ip);
 }
 
 static void
+zpl_inode_delete(struct inode *ip)
+{
+       truncate_setsize(ip, 0);
+       clear_inode(ip);
+}
+
+#endif /* HAVE_EVICT_INODE */
+
+static void
 zpl_put_super(struct super_block *sb)
 {
        int error;
@@ -73,6 +105,20 @@ zpl_put_super(struct super_block *sb)
 }
 
 static int
+zpl_sync_fs(struct super_block *sb, int wait)
+{
+       cred_t *cr = CRED();
+       int error;
+
+       crhold(cr);
+       error = -zfs_sync(sb, wait, cr);
+       crfree(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
 zpl_statfs(struct dentry *dentry, struct kstatfs *statp)
 {
        int error;
@@ -84,6 +130,16 @@ zpl_statfs(struct dentry *dentry, struct kstatfs *statp)
 }
 
 static int
+zpl_remount_fs(struct super_block *sb, int *flags, char *data)
+{
+       int error;
+       error = -zfs_remount(sb, flags, data);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
 zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp)
 {
        struct super_block *sb = vfsp->mnt_sb;
@@ -94,8 +150,7 @@ zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp)
         * MNT_NOSUID, MNT_NODEV, MNT_NOEXEC, MNT_NOATIME, MNT_READONLY
         */
 
-       if (zsb->z_flags & ZSB_XATTR_USER)
-               seq_printf(seq, ",%s", "xattr");
+       seq_printf(seq, ",%s", zsb->z_flags & ZSB_XATTR ? "xattr" : "noxattr");
 
        return (0);
 }
@@ -111,14 +166,25 @@ zpl_fill_super(struct super_block *sb, void *data, int silent)
        return (error);
 }
 
+#ifdef HAVE_MOUNT_NODEV
+static struct dentry *
+zpl_mount(struct file_system_type *fs_type, int flags,
+    const char *osname, void *data)
+{
+       zpl_mount_data_t zmd = { osname, data };
+
+       return mount_nodev(fs_type, flags, &zmd, zpl_fill_super);
+}
+#else
 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 };
+       zpl_mount_data_t zmd = { osname, data };
 
        return get_sb_nodev(fs_type, flags, &zmd, zpl_fill_super, mnt);
 }
+#endif /* HAVE_MOUNT_NODEV */
 
 static void
 zpl_kill_sb(struct super_block *sb)
@@ -136,33 +202,31 @@ zpl_kill_sb(struct super_block *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,
+#ifdef HAVE_EVICT_INODE
+       .evict_inode    = zpl_evict_inode,
+#else
+       .clear_inode    = zpl_clear_inode,
+       .delete_inode   = zpl_inode_delete,
+#endif /* HAVE_EVICT_INODE */
        .put_super      = zpl_put_super,
        .write_super    = NULL,
-       .sync_fs        = NULL,
-       .freeze_fs      = NULL,
-       .unfreeze_fs    = NULL,
+       .sync_fs        = zpl_sync_fs,
        .statfs         = zpl_statfs,
-       .remount_fs     = NULL,
+       .remount_fs     = zpl_remount_fs,
        .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,
+#ifdef HAVE_MOUNT_NODEV
+       .mount          = zpl_mount,
+#else
        .get_sb         = zpl_get_sb,
+#endif /* HAVE_MOUNT_NODEV */
        .kill_sb        = zpl_kill_sb,
 };