* in order to compress/encrypt/etc the data. We therefor need to
* make sure that there is sufficient available memory for this.
*/
- if ((error = arc_memory_throttle(reserve, txg)))
- if (error = arc_memory_throttle(reserve, anon_size, txg))
++ if ((error = arc_memory_throttle(reserve, anon_size, txg)))
return (error);
/*
os->os_meta_dnode->dn_zio = zio;
dnode_sync(os->os_meta_dnode, tx);
+ os->os_phys->os_flags = os->os_flags;
+
+ if (os->os_userused_dnode &&
+ os->os_userused_dnode->dn_type != DMU_OT_NONE) {
+ os->os_userused_dnode->dn_zio = zio;
+ dnode_sync(os->os_userused_dnode, tx);
+ os->os_groupused_dnode->dn_zio = zio;
+ dnode_sync(os->os_groupused_dnode, tx);
+ }
+
txgoff = tx->tx_txg & TXG_MASK;
- dmu_objset_sync_dnodes(&os->os_free_dnodes[txgoff], tx);
- dmu_objset_sync_dnodes(&os->os_dirty_dnodes[txgoff], tx);
+ if (dmu_objset_userused_enabled(os)) {
+ newlist = &os->os_synced_dnodes;
+ /*
+ * We must create the list here because it uses the
+ * dn_dirty_link[] of this txg.
+ */
+ list_create(newlist, sizeof (dnode_t),
+ offsetof(dnode_t, dn_dirty_link[txgoff]));
+ }
+
+ dmu_objset_sync_dnodes(&os->os_free_dnodes[txgoff], newlist, tx);
+ dmu_objset_sync_dnodes(&os->os_dirty_dnodes[txgoff], newlist, tx);
list = &os->os_meta_dnode->dn_dirty_records[txgoff];
- while (dr = list_head(list)) {
+ while ((dr = list_head(list))) {
ASSERT(dr->dr_dbuf->db_level == 0);
list_remove(list, dr);
if (dr->dr_zio)
tx = dmu_tx_create_assigned(dp, txg);
dp->dp_read_overhead = 0;
+ start = gethrtime();
+
zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
- while (ds = txg_list_remove(&dp->dp_dirty_datasets, txg)) {
+ while ((ds = txg_list_remove(&dp->dp_dirty_datasets, txg))) {
- if (!list_link_active(&ds->ds_synced_link))
- list_insert_tail(&dp->dp_synced_datasets, ds);
- else
- dmu_buf_rele(ds->ds_dbuf, ds);
+ /*
+ * We must not sync any non-MOS datasets twice, because
+ * we may have taken a snapshot of them. However, we
+ * may sync newly-created datasets on pass 2.
+ */
+ ASSERT(!list_link_active(&ds->ds_synced_link));
+ list_insert_tail(&dp->dp_synced_datasets, ds);
dsl_dataset_sync(ds, zio, tx);
}
DTRACE_PROBE(pool_sync__1setup);
ASSERT(err == 0);
DTRACE_PROBE(pool_sync__2rootzio);
- while ((dstg = txg_list_remove(&dp->dp_sync_tasks, txg)))
+ for (ds = list_head(&dp->dp_synced_datasets); ds;
+ ds = list_next(&dp->dp_synced_datasets, ds))
+ dmu_objset_do_userquota_callbacks(ds->ds_user_ptr, tx);
+
+ /*
+ * Sync the datasets again to push out the changes due to
+ * userquota updates. This must be done before we process the
+ * sync tasks, because that could cause a snapshot of a dataset
+ * whose ds_bp will be rewritten when we do this 2nd sync.
+ */
+ zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
- while (ds = txg_list_remove(&dp->dp_dirty_datasets, txg)) {
++ while ((ds = txg_list_remove(&dp->dp_dirty_datasets, txg))) {
+ ASSERT(list_link_active(&ds->ds_synced_link));
+ dmu_buf_rele(ds->ds_dbuf, ds);
+ dsl_dataset_sync(ds, zio, tx);
+ }
+ err = zio_wait(zio);
+
- while (dstg = txg_list_remove(&dp->dp_sync_tasks, txg)) {
++ while ((dstg = txg_list_remove(&dp->dp_sync_tasks, txg))) {
+ /*
+ * No more sync tasks should have been added while we
+ * were syncing.
+ */
+ ASSERT(spa_sync_pass(dp->dp_spa) == 1);
dsl_sync_task_group_sync(dstg, tx);
+ }
DTRACE_PROBE(pool_sync__3task);
start = gethrtime();
return (0);
}
- /*
- * Import a root pool.
- *
- * For x86. devpath_list will consist of devid and/or physpath name of
- * the vdev (e.g. "id1,sd@SSEAGATE..." or "/pci@1f,0/ide@d/disk@0,0:a").
- * The GRUB "findroot" command will return the vdev we should boot.
- *
- * For Sparc, devpath_list consists the physpath name of the booting device
- * no matter the rootpool is a single device pool or a mirrored pool.
- * e.g.
- * "/pci@1f,0/ide@d/disk@0,0:a"
- */
- int
- spa_import_rootpool(char *devpath, char *devid)
- {
- nvlist_t *conf = NULL;
- char *pname;
- int error;
-
- /*
- * Get the vdev pathname and configuation from the most
- * recently updated vdev (highest txg).
- */
- if ((error = spa_get_rootconf(devpath, devid, &conf)))
- goto msg_out;
-
- /*
- * Add type "root" vdev to the config.
- */
- spa_build_rootpool_config(conf);
-
- VERIFY(nvlist_lookup_string(conf, ZPOOL_CONFIG_POOL_NAME, &pname) == 0);
-
- /*
- * We specify 'allowfaulted' for this to be treated like spa_open()
- * instead of spa_import(). This prevents us from marking vdevs as
- * persistently unavailable, and generates FMA ereports as if it were a
- * pool open, not import.
- */
- error = spa_import_common(pname, conf, NULL, B_TRUE, B_TRUE);
- ASSERT(error != EEXIST);
-
- nvlist_free(conf);
- return (error);
-
- msg_out:
- cmn_err(CE_NOTE, "\n"
- " *************************************************** \n"
- " * This device is not bootable! * \n"
- " * It is either offlined or detached or faulted. * \n"
- " * Please try to boot from a different device. * \n"
- " *************************************************** ");
-
- return (error);
- }
- #endif
-
- /*
- * Import a non-root pool into the system.
- */
- int
- spa_import(const char *pool, nvlist_t *config, nvlist_t *props)
- {
- return (spa_import_common(pool, config, props, B_FALSE, B_FALSE));
- }
-
- int
- spa_import_faulted(const char *pool, nvlist_t *config, nvlist_t *props)
- {
- return (spa_import_common(pool, config, props, B_FALSE, B_TRUE));
- }
-
--
/*
* This (illegal) pool name is used when temporarily importing a spa_t in order
* to get the vdev stats associated with the imported devices.
nvlist_t *zplprops = NULL;
char *buf;
- if ((error = get_nvlist(zc->zc_nvlist_conf,
- zc->zc_nvlist_conf_size, &config)))
- if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
- zc->zc_iflags, &config))
++ if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
++ zc->zc_iflags, &config)))
return (error);
if (zc->zc_nvlist_src_size != 0 && (error =