Illumos #3137 L2ARC compression
[zfs.git] / module / zfs / dmu_objset.c
index b3a8302..52d55d5 100644 (file)
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
  */
 
 /* Portions Copyright 2010 Robert Milkowski */
@@ -262,7 +263,7 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
 
        ASSERT(ds == NULL || MUTEX_HELD(&ds->ds_opening_lock));
 
-       os = kmem_zalloc(sizeof (objset_t), KM_SLEEP);
+       os = kmem_zalloc(sizeof (objset_t), KM_PUSHPAGE);
        os->os_dsl_dataset = ds;
        os->os_spa = spa;
        os->os_rootbp = bp;
@@ -274,14 +275,11 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
 
                if (DMU_OS_IS_L2CACHEABLE(os))
                        aflags |= ARC_L2CACHE;
+               if (DMU_OS_IS_L2COMPRESSIBLE(os))
+                       aflags |= ARC_L2COMPRESS;
 
                dprintf_bp(os->os_rootbp, "reading %s", "");
-               /*
-                * XXX when bprewrite scrub can change the bp,
-                * and this is called from dmu_objset_open_ds_os, the bp
-                * could change, and we'll need a lock.
-                */
-               err = dsl_read_nolock(NULL, spa, os->os_rootbp,
+               err = arc_read(NULL, spa, os->os_rootbp,
                    arc_getbuf_func, &os->os_phys_buf,
                    ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &aflags, &zb);
                if (err) {
@@ -848,7 +846,7 @@ snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
                if (strlen(sn->htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
                        return (E2BIG);
 
-               sn->ha = kmem_alloc(sizeof (struct dsl_ds_holdarg), KM_SLEEP);
+               sn->ha = kmem_alloc(sizeof(struct dsl_ds_holdarg), KM_PUSHPAGE);
                sn->ha->temphold = B_TRUE;
                sn->ha->htag = sn->htag;
        }
@@ -946,16 +944,19 @@ dmu_objset_snapshot(char *fsname, char *snapname, char *tag,
     nvlist_t *props, boolean_t recursive, boolean_t temporary, int cleanup_fd)
 {
        dsl_sync_task_t *dst;
-       struct snaparg sn;
+       struct snaparg *sn;
        spa_t *spa;
        minor_t minor;
        int err;
 
-       (void) strcpy(sn.failed, fsname);
+       sn = kmem_alloc(sizeof (struct snaparg), KM_SLEEP);
+       (void) strcpy(sn->failed, fsname);
 
        err = spa_open(fsname, &spa, FTAG);
-       if (err)
+       if (err) {
+               kmem_free(sn, sizeof (struct snaparg));
                return (err);
+       }
 
        if (temporary) {
                if (cleanup_fd < 0) {
@@ -968,46 +969,47 @@ dmu_objset_snapshot(char *fsname, char *snapname, char *tag,
                }
        }
 
-       sn.dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
-       sn.snapname = snapname;
-       sn.htag = tag;
-       sn.props = props;
-       sn.recursive = recursive;
-       sn.needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
-       sn.temporary = temporary;
-       sn.ha = NULL;
-       sn.newds = NULL;
+       sn->dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
+       sn->snapname = snapname;
+       sn->htag = tag;
+       sn->props = props;
+       sn->recursive = recursive;
+       sn->needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
+       sn->temporary = temporary;
+       sn->ha = NULL;
+       sn->newds = NULL;
 
        if (recursive) {
                err = dmu_objset_find(fsname,
-                   dmu_objset_snapshot_one, &sn, DS_FIND_CHILDREN);
+                   dmu_objset_snapshot_one, sn, DS_FIND_CHILDREN);
        } else {
-               err = dmu_objset_snapshot_one(fsname, &sn);
+               err = dmu_objset_snapshot_one(fsname, sn);
        }
 
        if (err == 0)
-               err = dsl_sync_task_group_wait(sn.dstg);
+               err = dsl_sync_task_group_wait(sn->dstg);
 
-       for (dst = list_head(&sn.dstg->dstg_tasks); dst;
-           dst = list_next(&sn.dstg->dstg_tasks, dst)) {
+       for (dst = list_head(&sn->dstg->dstg_tasks); dst;
+           dst = list_next(&sn->dstg->dstg_tasks, dst)) {
                objset_t *os = dst->dst_arg1;
                dsl_dataset_t *ds = os->os_dsl_dataset;
                if (dst->dst_err) {
-                       dsl_dataset_name(ds, sn.failed);
+                       dsl_dataset_name(ds, sn->failed);
                } else if (temporary) {
-                       dsl_register_onexit_hold_cleanup(sn.newds, tag, minor);
+                       dsl_register_onexit_hold_cleanup(sn->newds, tag, minor);
                }
-               if (sn.needsuspend)
+               if (sn->needsuspend)
                        zil_resume(dmu_objset_zil(os));
-               dmu_objset_rele(os, &sn);
+               dmu_objset_rele(os, sn);
        }
 
        if (err)
-               (void) strcpy(fsname, sn.failed);
+               (void) strcpy(fsname, sn->failed);
        if (temporary)
                zfs_onexit_fd_rele(cleanup_fd);
-       dsl_sync_task_group_destroy(sn.dstg);
+       dsl_sync_task_group_destroy(sn->dstg);
        spa_close(spa, FTAG);
+       kmem_free(sn, sizeof (struct snaparg));
        return (err);
 }
 
@@ -1115,15 +1117,15 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
        SET_BOOKMARK(&zb, os->os_dsl_dataset ?
            os->os_dsl_dataset->ds_object : DMU_META_OBJSET,
            ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID);
-       VERIFY3U(0, ==, arc_release_bp(os->os_phys_buf, &os->os_phys_buf,
-           os->os_rootbp, os->os_spa, &zb));
+       arc_release(os->os_phys_buf, &os->os_phys_buf);
 
        dmu_write_policy(os, NULL, 0, 0, &zp);
 
        zio = arc_write(pio, os->os_spa, tx->tx_txg,
-           os->os_rootbp, os->os_phys_buf, DMU_OS_IS_L2CACHEABLE(os), &zp,
-           dmu_objset_write_ready, dmu_objset_write_done, os,
-           ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
+           os->os_rootbp, os->os_phys_buf, DMU_OS_IS_L2CACHEABLE(os),
+           DMU_OS_IS_L2COMPRESSIBLE(os), &zp, dmu_objset_write_ready,
+           dmu_objset_write_done, os, ZIO_PRIORITY_ASYNC_WRITE,
+           ZIO_FLAG_MUSTSUCCEED, &zb);
 
        /*
         * Sync special dnodes - the parent IO for the sync is the root block
@@ -1178,17 +1180,6 @@ dmu_objset_is_dirty(objset_t *os, uint64_t txg)
            !list_is_empty(&os->os_free_dnodes[txg & TXG_MASK]));
 }
 
-boolean_t
-dmu_objset_is_dirty_anywhere(objset_t *os)
-{
-       int t;
-
-       for (t = 0; t < TXG_SIZE; t++)
-               if (dmu_objset_is_dirty(os, t))
-                       return (B_TRUE);
-       return (B_FALSE);
-}
-
 static objset_used_cb_t *used_cbs[DMU_OST_NUMTYPES];
 
 void
@@ -1331,7 +1322,7 @@ dmu_objset_userquota_get_ids(dnode_t *dn, boolean_t before, dmu_tx_t *tx)
        objset_t *os = dn->dn_objset;
        void *data = NULL;
        dmu_buf_impl_t *db = NULL;
-       uint64_t *user, *group;
+       uint64_t *user = NULL, *group = NULL;
        int flags = dn->dn_id_flags;
        int error;
        boolean_t have_spill = B_FALSE;
@@ -1581,6 +1572,12 @@ dmu_snapshot_list_next(objset_t *os, int namelen, char *name,
 }
 
 int
+dmu_snapshot_lookup(objset_t *os, const char *name, uint64_t *value)
+{
+       return dsl_dataset_snap_lookup(os->os_dsl_dataset, name, value);
+}
+
+int
 dmu_dir_list_next(objset_t *os, int namelen, char *name,
     uint64_t *idp, uint64_t *offp)
 {
@@ -1673,7 +1670,7 @@ dmu_objset_find_spa(spa_t *spa, const char *name,
        }
 
        thisobj = dd->dd_phys->dd_head_dataset_obj;
-       attr = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
+       attr = kmem_alloc(sizeof (zap_attribute_t), KM_PUSHPAGE);
        dp = dd->dd_pool;
 
        /*
@@ -1766,7 +1763,7 @@ dmu_objset_prefetch(const char *name, void *arg)
                        SET_BOOKMARK(&zb, ds->ds_object, ZB_ROOT_OBJECT,
                            ZB_ROOT_LEVEL, ZB_ROOT_BLKID);
 
-                       (void) dsl_read_nolock(NULL, dsl_dataset_get_spa(ds),
+                       (void) arc_read(NULL, dsl_dataset_get_spa(ds),
                            &ds->ds_phys->ds_bp, NULL, NULL,
                            ZIO_PRIORITY_ASYNC_READ,
                            ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE,
@@ -1792,3 +1789,43 @@ dmu_objset_get_user(objset_t *os)
        ASSERT(MUTEX_HELD(&os->os_user_ptr_lock));
        return (os->os_user_ptr);
 }
+
+#if defined(_KERNEL) && defined(HAVE_SPL)
+EXPORT_SYMBOL(dmu_objset_zil);
+EXPORT_SYMBOL(dmu_objset_pool);
+EXPORT_SYMBOL(dmu_objset_ds);
+EXPORT_SYMBOL(dmu_objset_type);
+EXPORT_SYMBOL(dmu_objset_name);
+EXPORT_SYMBOL(dmu_objset_hold);
+EXPORT_SYMBOL(dmu_objset_own);
+EXPORT_SYMBOL(dmu_objset_rele);
+EXPORT_SYMBOL(dmu_objset_disown);
+EXPORT_SYMBOL(dmu_objset_from_ds);
+EXPORT_SYMBOL(dmu_objset_create);
+EXPORT_SYMBOL(dmu_objset_clone);
+EXPORT_SYMBOL(dmu_objset_destroy);
+EXPORT_SYMBOL(dmu_objset_snapshot);
+EXPORT_SYMBOL(dmu_objset_stats);
+EXPORT_SYMBOL(dmu_objset_fast_stat);
+EXPORT_SYMBOL(dmu_objset_spa);
+EXPORT_SYMBOL(dmu_objset_space);
+EXPORT_SYMBOL(dmu_objset_fsid_guid);
+EXPORT_SYMBOL(dmu_objset_find);
+EXPORT_SYMBOL(dmu_objset_find_spa);
+EXPORT_SYMBOL(dmu_objset_prefetch);
+EXPORT_SYMBOL(dmu_objset_byteswap);
+EXPORT_SYMBOL(dmu_objset_evict_dbufs);
+EXPORT_SYMBOL(dmu_objset_snap_cmtime);
+
+EXPORT_SYMBOL(dmu_objset_sync);
+EXPORT_SYMBOL(dmu_objset_is_dirty);
+EXPORT_SYMBOL(dmu_objset_create_impl);
+EXPORT_SYMBOL(dmu_objset_open_impl);
+EXPORT_SYMBOL(dmu_objset_evict);
+EXPORT_SYMBOL(dmu_objset_register_type);
+EXPORT_SYMBOL(dmu_objset_do_userquota_updates);
+EXPORT_SYMBOL(dmu_objset_userquota_get_ids);
+EXPORT_SYMBOL(dmu_objset_userused_enabled);
+EXPORT_SYMBOL(dmu_objset_userspace_upgrade);
+EXPORT_SYMBOL(dmu_objset_userspace_present);
+#endif