static void
zpl_inode_destroy(struct inode *ip)
{
- ASSERT(atomic_read(&ip->i_count) == 0);
+ ASSERT(atomic_read(&ip->i_count) == 0);
zfs_inode_destroy(ip);
}
+/*
+ * Called from __mark_inode_dirty() to reflect that something in the
+ * inode has changed. We use it to ensure the znode system attributes
+ * are always strictly update to date with respect to the inode.
+ */
+#ifdef HAVE_DIRTY_INODE_WITH_FLAGS
+static void
+zpl_dirty_inode(struct inode *ip, int flags)
+{
+ zfs_dirty_inode(ip, flags);
+}
+#else
+static void
+zpl_dirty_inode(struct inode *ip)
+{
+ zfs_dirty_inode(ip, 0);
+}
+#endif /* HAVE_DIRTY_INODE_WITH_FLAGS */
+
/*
* When ->drop_inode() is called its return value indicates if the
* inode should be evicted from the inode cache. If the inode is
* 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
+ * be in a state where it can simply be freed.i
+ *
+ * The ->evict_inode() callback must minimally truncate the inode pages,
+ * and call clear_inode(). For 2.6.35 and later kernels this will
+ * simply update the inode state, with the sync occurring before the
+ * truncate in evict(). For earlier kernels clear_inode() maps to
+ * end_writeback() which is responsible for completing all outstanding
+ * write back. In either case, once this is done it is safe to cleanup
+ * any remaining inode specific data via zfs_inactive().
* remaining filesystem specific data.
*/
#ifdef HAVE_EVICT_INODE
zpl_evict_inode(struct inode *ip)
{
truncate_setsize(ip, 0);
- end_writeback(ip);
+ clear_inode(ip);
zfs_inactive(ip);
}
}
/*
- * The Linux VFS automatically handles the following flags:
- * MNT_NOSUID, MNT_NODEV, MNT_NOEXEC, MNT_NOATIME, MNT_READONLY
+ * ZFS specific features must be explicitly handled here, the VFS will
+ * automatically handled the following generic functionality.
+ *
+ * MNT_NOSUID,
+ * MNT_NODEV,
+ * MNT_NOEXEC,
+ * MNT_NOATIME,
+ * MNT_NODIRATIME,
+ * MNT_READONLY,
+ * MNT_STRICTATIME,
+ * MS_SYNCHRONOUS,
+ * MS_DIRSYNC,
+ * MS_MANDLOCK.
*/
-#ifdef HAVE_SHOW_OPTIONS_WITH_DENTRY
static int
-zpl_show_options(struct seq_file *seq, struct dentry *root)
+__zpl_show_options(struct seq_file *seq, zfs_sb_t *zsb)
{
- zfs_sb_t *zsb = root->d_sb->s_fs_info;
-
seq_printf(seq, ",%s", zsb->z_flags & ZSB_XATTR ? "xattr" : "noxattr");
+#ifdef CONFIG_FS_POSIX_ACL
+ switch (zsb->z_acl_type) {
+ case ZFS_ACLTYPE_POSIXACL:
+ seq_puts(seq, ",posixacl");
+ break;
+ default:
+ seq_puts(seq, ",noacl");
+ break;
+ }
+#endif /* CONFIG_FS_POSIX_ACL */
+
return (0);
}
+
+#ifdef HAVE_SHOW_OPTIONS_WITH_DENTRY
+static int
+zpl_show_options(struct seq_file *seq, struct dentry *root)
+{
+ return (__zpl_show_options(seq, root->d_sb->s_fs_info));
+}
#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);
+ return (__zpl_show_options(seq, vfsp->mnt_sb->s_fs_info));
}
#endif /* HAVE_SHOW_OPTIONS_WITH_DENTRY */
{
zpl_mount_data_t zmd = { osname, data };
- return mount_nodev(fs_type, flags, &zmd, zpl_fill_super);
+ return (mount_nodev(fs_type, flags, &zmd, zpl_fill_super));
}
#else
static int
{
zpl_mount_data_t zmd = { osname, data };
- return get_sb_nodev(fs_type, flags, &zmd, zpl_fill_super, mnt);
+ return (get_sb_nodev(fs_type, flags, &zmd, zpl_fill_super, mnt));
}
#endif /* HAVE_MOUNT_NODEV */
{
zfs_preumount(sb);
kill_anon_super(sb);
+
+#ifdef HAVE_S_INSTANCES_LIST_HEAD
+ sb->s_instances.next = &(zpl_fs_type.fs_supers);
+#endif /* HAVE_S_INSTANCES_LIST_HEAD */
}
#ifdef HAVE_SHRINK
error = -zfs_sb_prune(sb, *(unsigned long *)arg, &objects);
ASSERT3S(error, <=, 0);
-
- return;
}
void
zpl_prune_sbs(int64_t bytes_to_scan, void *private)
{
- unsigned long nr_to_scan = (bytes_to_scan / sizeof(znode_t));
+ unsigned long nr_to_scan = (bytes_to_scan / sizeof (znode_t));
iterate_supers_type(&zpl_fs_type, zpl_prune_sb, &nr_to_scan);
kmem_reap();
void
zpl_prune_sbs(int64_t bytes_to_scan, void *private)
{
- unsigned long nr_to_scan = (bytes_to_scan / sizeof(znode_t));
+ unsigned long nr_to_scan = (bytes_to_scan / sizeof (znode_t));
- shrink_dcache_memory(nr_to_scan, GFP_KERNEL);
- shrink_icache_memory(nr_to_scan, GFP_KERNEL);
- kmem_reap();
+ shrink_dcache_memory(nr_to_scan, GFP_KERNEL);
+ shrink_icache_memory(nr_to_scan, GFP_KERNEL);
+ kmem_reap();
}
#endif /* HAVE_SHRINK */
static void
zpl_free_cached_objects(struct super_block *sb, int nr_to_scan)
{
- arc_adjust_meta(nr_to_scan * sizeof(znode_t), B_FALSE);
+ /* noop */
}
#endif /* HAVE_FREE_CACHED_OBJECTS */
const struct super_operations zpl_super_operations = {
.alloc_inode = zpl_inode_alloc,
.destroy_inode = zpl_inode_destroy,
- .dirty_inode = NULL,
+ .dirty_inode = zpl_dirty_inode,
.write_inode = NULL,
.drop_inode = NULL,
#ifdef HAVE_EVICT_INODE
.delete_inode = zpl_inode_delete,
#endif /* HAVE_EVICT_INODE */
.put_super = zpl_put_super,
- .write_super = NULL,
.sync_fs = zpl_sync_fs,
.statfs = zpl_statfs,
.remount_fs = zpl_remount_fs,