Linux 3.1 compat, super_block->s_shrink
[zfs.git] / module / zfs / zfs_vfsops.c
index 0ee5413..fb319a5 100644 (file)
@@ -140,10 +140,16 @@ xattr_changed_cb(void *arg, uint64_t newval)
 {
        zfs_sb_t *zsb = arg;
 
-       if (newval == TRUE)
-               zsb->z_flags |= ZSB_XATTR;
-       else
+       if (newval == ZFS_XATTR_OFF) {
                zsb->z_flags &= ~ZSB_XATTR;
+       } else {
+               zsb->z_flags |= ZSB_XATTR;
+
+               if (newval == ZFS_XATTR_SA)
+                       zsb->z_xattr_sa = B_TRUE;
+               else
+                       zsb->z_xattr_sa = B_FALSE;
+       }
 }
 
 static void
@@ -600,12 +606,6 @@ zfs_sb_create(const char *osname, zfs_sb_t **zsbp)
        zsb->z_show_ctldir = ZFS_SNAPDIR_VISIBLE;
        zsb->z_os = os;
 
-       error = -bdi_init(&zsb->z_bdi);
-       if (error) {
-               kmem_free(zsb, sizeof (zfs_sb_t));
-               return (error);
-       }
-
        error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zsb->z_version);
        if (error) {
                goto out;
@@ -646,7 +646,11 @@ zfs_sb_create(const char *osname, zfs_sb_t **zsbp)
                error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1,
                    &sa_obj);
                if (error)
-                       return (error);
+                       goto out;
+
+               error = zfs_get_zplprop(os, ZFS_PROP_XATTR, &zval);
+               if ((error == 0) && (zval == ZFS_XATTR_SA))
+                       zsb->z_xattr_sa = B_TRUE;
        } else {
                /*
                 * Pre SA versions file systems should never touch
@@ -715,8 +719,9 @@ out:
        kmem_free(zsb, sizeof (zfs_sb_t));
        return (error);
 }
+EXPORT_SYMBOL(zfs_sb_create);
 
-static int
+int
 zfs_sb_setup(zfs_sb_t *zsb, boolean_t mounting)
 {
        int error;
@@ -797,6 +802,7 @@ zfs_sb_setup(zfs_sb_t *zsb, boolean_t mounting)
 
        return (0);
 }
+EXPORT_SYMBOL(zfs_sb_setup);
 
 void
 zfs_sb_free(zfs_sb_t *zsb)
@@ -805,7 +811,6 @@ zfs_sb_free(zfs_sb_t *zsb)
 
        zfs_fuid_destroy(zsb);
 
-       bdi_destroy(&zsb->z_bdi);
        mutex_destroy(&zsb->z_znodes_lock);
        mutex_destroy(&zsb->z_lock);
        list_destroy(&zsb->z_all_znodes);
@@ -816,6 +821,7 @@ zfs_sb_free(zfs_sb_t *zsb)
                mutex_destroy(&zsb->z_hold_mtx[i]);
        kmem_free(zsb, sizeof (zfs_sb_t));
 }
+EXPORT_SYMBOL(zfs_sb_free);
 
 static void
 zfs_set_fuid_feature(zfs_sb_t *zsb)
@@ -899,6 +905,7 @@ zfs_check_global_label(const char *dsname, const char *hexsl)
        }
        return (EACCES);
 }
+EXPORT_SYMBOL(zfs_check_global_label);
 #endif /* HAVE_MLSLABEL */
 
 int
@@ -979,6 +986,26 @@ zfs_root(zfs_sb_t *zsb, struct inode **ipp)
 }
 EXPORT_SYMBOL(zfs_root);
 
+#ifdef HAVE_SHRINK
+int
+zfs_sb_prune(struct super_block *sb, unsigned long nr_to_scan, int *objects)
+{
+       zfs_sb_t *zsb = sb->s_fs_info;
+       struct shrinker *shrinker = &sb->s_shrink;
+       struct shrink_control sc = {
+               .nr_to_scan = nr_to_scan,
+               .gfp_mask = GFP_KERNEL,
+       };
+
+       ZFS_ENTER(zsb);
+       *objects = (*shrinker->shrink)(shrinker, &sc);
+       ZFS_EXIT(zsb);
+
+       return (0);
+}
+EXPORT_SYMBOL(zfs_sb_prune);
+#endif /* HAVE_SHRINK */
+
 /*
  * Teardown the zfs_sb_t::z_os.
  *
@@ -986,7 +1013,7 @@ EXPORT_SYMBOL(zfs_root);
  * and 'z_teardown_inactive_lock' held.
  */
 int
-zfsvfs_teardown(zfs_sb_t *zsb, boolean_t unmounting)
+zfs_sb_teardown(zfs_sb_t *zsb, boolean_t unmounting)
 {
        znode_t *zp;
 
@@ -1083,10 +1110,11 @@ zfsvfs_teardown(zfs_sb_t *zsb, boolean_t unmounting)
 
        return (0);
 }
+EXPORT_SYMBOL(zfs_sb_teardown);
 
-#ifdef HAVE_BDI
-static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
-#endif /* HAVE_BDI */
+#if defined(HAVE_BDI) && !defined(HAVE_BDI_SETUP_AND_REGISTER)
+atomic_long_t zfs_bdi_seq = ATOMIC_LONG_INIT(0);
+#endif /* HAVE_BDI && !HAVE_BDI_SETUP_AND_REGISTER */
 
 int
 zfs_domount(struct super_block *sb, void *data, int silent)
@@ -1113,7 +1141,23 @@ zfs_domount(struct super_block *sb, void *data, int silent)
        sb->s_time_gran = 1;
        sb->s_blocksize = recordsize;
        sb->s_blocksize_bits = ilog2(recordsize);
-       bdi_put_sb(sb, NULL);
+
+#ifdef HAVE_BDI
+       /*
+        * 2.6.32 API change,
+        * Added backing_device_info (BDI) per super block interfaces.  A BDI
+        * must be configured when using a non-device backed filesystem for
+        * proper writeback.  This is not required for older pdflush kernels.
+        *
+        * NOTE: Linux read-ahead is disabled in favor of zfs read-ahead.
+        */
+       zsb->z_bdi.ra_pages = 0;
+       sb->s_bdi = &zsb->z_bdi;
+
+       error = -bdi_setup_and_register(&zsb->z_bdi, "zfs", BDI_CAP_MAP_COPY);
+       if (error)
+               goto out;
+#endif /* HAVE_BDI */
 
        /* Set callback operations for the file system. */
        sb->s_op = &zpl_super_operations;
@@ -1138,16 +1182,6 @@ zfs_domount(struct super_block *sb, void *data, int silent)
                dmu_objset_set_user(zsb->z_os, zsb);
                mutex_exit(&zsb->z_os->os_user_ptr_lock);
        } else {
-               /* Disable Linux read-ahead handled by lower layers */
-               zsb->z_bdi.ra_pages = 0;
-
-               error = -bdi_register(&zsb->z_bdi, NULL, "zfs-%d",
-                   atomic_long_inc_return(&bdi_seq));
-               if (error)
-                       goto out;
-
-               bdi_put_sb(sb, &zsb->z_bdi);
-
                error = zfs_sb_setup(zsb, B_TRUE);
 #ifdef HAVE_SNAPSHOT
                (void) zfs_snap_create(zsb);
@@ -1185,13 +1219,12 @@ zfs_umount(struct super_block *sb)
        zfs_sb_t *zsb = sb->s_fs_info;
        objset_t *os;
 
-       VERIFY(zfsvfs_teardown(zsb, B_TRUE) == 0);
+       VERIFY(zfs_sb_teardown(zsb, B_TRUE) == 0);
        os = zsb->z_os;
 
-       if (bdi_get_sb(sb)) {
-               bdi_unregister(bdi_get_sb(sb));
-               bdi_put_sb(sb, NULL);
-       }
+#ifdef HAVE_BDI
+       bdi_destroy(sb->s_bdi);
+#endif /* HAVE_BDI */
 
        /*
         * z_os will be NULL if there was an error in
@@ -1332,7 +1365,7 @@ zfs_suspend_fs(zfs_sb_t *zsb)
 {
        int error;
 
-       if ((error = zfsvfs_teardown(zsb, B_FALSE)) != 0)
+       if ((error = zfs_sb_teardown(zsb, B_FALSE)) != 0)
                return (error);
        dmu_objset_disown(zsb->z_os, zsb);
 
@@ -1512,6 +1545,7 @@ zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
        }
        return (error);
 }
+EXPORT_SYMBOL(zfs_get_zplprop);
 
 void
 zfs_init(void)
@@ -1519,6 +1553,7 @@ zfs_init(void)
        zfs_znode_init();
        dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb);
        register_filesystem(&zpl_fs_type);
+       (void) arc_add_prune_callback(zpl_prune_sbs, NULL);
 }
 
 void