1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6ea8dc4b6Seschrock * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 22*c717a561Smaybee * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23fa9e4066Sahrens * Use is subject to license terms. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 26fa9e4066Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27fa9e4066Sahrens 28fa9e4066Sahrens #include <sys/dsl_pool.h> 29fa9e4066Sahrens #include <sys/dsl_dataset.h> 30fa9e4066Sahrens #include <sys/dsl_dir.h> 311d452cf5Sahrens #include <sys/dsl_synctask.h> 32fa9e4066Sahrens #include <sys/dmu_tx.h> 33fa9e4066Sahrens #include <sys/dmu_objset.h> 34fa9e4066Sahrens #include <sys/arc.h> 35fa9e4066Sahrens #include <sys/zap.h> 36*c717a561Smaybee #include <sys/zio.h> 37fa9e4066Sahrens #include <sys/zfs_context.h> 38fa9e4066Sahrens #include <sys/fs/zfs.h> 39fa9e4066Sahrens 40ea8dc4b6Seschrock static int 41ea8dc4b6Seschrock dsl_pool_open_mos_dir(dsl_pool_t *dp, dsl_dir_t **ddp) 42fa9e4066Sahrens { 43fa9e4066Sahrens uint64_t obj; 44fa9e4066Sahrens int err; 45fa9e4066Sahrens 46fa9e4066Sahrens err = zap_lookup(dp->dp_meta_objset, 47fa9e4066Sahrens dp->dp_root_dir->dd_phys->dd_child_dir_zapobj, 48fa9e4066Sahrens MOS_DIR_NAME, sizeof (obj), 1, &obj); 49ea8dc4b6Seschrock if (err) 50ea8dc4b6Seschrock return (err); 51fa9e4066Sahrens 52ea8dc4b6Seschrock return (dsl_dir_open_obj(dp, obj, MOS_DIR_NAME, dp, ddp)); 53fa9e4066Sahrens } 54fa9e4066Sahrens 55fa9e4066Sahrens static dsl_pool_t * 56fa9e4066Sahrens dsl_pool_open_impl(spa_t *spa, uint64_t txg) 57fa9e4066Sahrens { 58fa9e4066Sahrens dsl_pool_t *dp; 59fa9e4066Sahrens blkptr_t *bp = spa_get_rootblkptr(spa); 60fa9e4066Sahrens 61fa9e4066Sahrens dp = kmem_zalloc(sizeof (dsl_pool_t), KM_SLEEP); 62fa9e4066Sahrens dp->dp_spa = spa; 63fa9e4066Sahrens dp->dp_meta_rootbp = *bp; 645ad82045Snd rw_init(&dp->dp_config_rwlock, NULL, RW_DEFAULT, NULL); 65fa9e4066Sahrens txg_init(dp, txg); 66fa9e4066Sahrens 67fa9e4066Sahrens txg_list_create(&dp->dp_dirty_datasets, 68fa9e4066Sahrens offsetof(dsl_dataset_t, ds_dirty_link)); 69fa9e4066Sahrens txg_list_create(&dp->dp_dirty_dirs, 70fa9e4066Sahrens offsetof(dsl_dir_t, dd_dirty_link)); 711d452cf5Sahrens txg_list_create(&dp->dp_sync_tasks, 721d452cf5Sahrens offsetof(dsl_sync_task_group_t, dstg_node)); 73fa9e4066Sahrens list_create(&dp->dp_synced_objsets, sizeof (dsl_dataset_t), 74fa9e4066Sahrens offsetof(dsl_dataset_t, ds_synced_link)); 75fa9e4066Sahrens 76fa9e4066Sahrens return (dp); 77fa9e4066Sahrens } 78fa9e4066Sahrens 79ea8dc4b6Seschrock int 80ea8dc4b6Seschrock dsl_pool_open(spa_t *spa, uint64_t txg, dsl_pool_t **dpp) 81fa9e4066Sahrens { 82fa9e4066Sahrens int err; 83fa9e4066Sahrens dsl_pool_t *dp = dsl_pool_open_impl(spa, txg); 84ea8dc4b6Seschrock objset_impl_t *osi; 85fa9e4066Sahrens 86fa9e4066Sahrens rw_enter(&dp->dp_config_rwlock, RW_READER); 87ea8dc4b6Seschrock err = dmu_objset_open_impl(spa, NULL, &dp->dp_meta_rootbp, &osi); 88ea8dc4b6Seschrock if (err) 89ea8dc4b6Seschrock goto out; 90ea8dc4b6Seschrock dp->dp_meta_objset = &osi->os; 91ea8dc4b6Seschrock 92fa9e4066Sahrens err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT, 93fa9e4066Sahrens DMU_POOL_ROOT_DATASET, sizeof (uint64_t), 1, 94fa9e4066Sahrens &dp->dp_root_dir_obj); 95ea8dc4b6Seschrock if (err) 96ea8dc4b6Seschrock goto out; 97ea8dc4b6Seschrock 98ea8dc4b6Seschrock err = dsl_dir_open_obj(dp, dp->dp_root_dir_obj, 99ea8dc4b6Seschrock NULL, dp, &dp->dp_root_dir); 100ea8dc4b6Seschrock if (err) 101ea8dc4b6Seschrock goto out; 102fa9e4066Sahrens 103ea8dc4b6Seschrock err = dsl_pool_open_mos_dir(dp, &dp->dp_mos_dir); 104ea8dc4b6Seschrock if (err) 105ea8dc4b6Seschrock goto out; 106ea8dc4b6Seschrock 107ea8dc4b6Seschrock out: 108fa9e4066Sahrens rw_exit(&dp->dp_config_rwlock); 109ea8dc4b6Seschrock if (err) 110ea8dc4b6Seschrock dsl_pool_close(dp); 111ea8dc4b6Seschrock else 112ea8dc4b6Seschrock *dpp = dp; 113fa9e4066Sahrens 114ea8dc4b6Seschrock return (err); 115fa9e4066Sahrens } 116fa9e4066Sahrens 117fa9e4066Sahrens void 118fa9e4066Sahrens dsl_pool_close(dsl_pool_t *dp) 119fa9e4066Sahrens { 120fa9e4066Sahrens /* drop our reference from dsl_pool_open() */ 121ea8dc4b6Seschrock if (dp->dp_mos_dir) 122ea8dc4b6Seschrock dsl_dir_close(dp->dp_mos_dir, dp); 123ea8dc4b6Seschrock if (dp->dp_root_dir) 124ea8dc4b6Seschrock dsl_dir_close(dp->dp_root_dir, dp); 125fa9e4066Sahrens 126fa9e4066Sahrens /* undo the dmu_objset_open_impl(mos) from dsl_pool_open() */ 127ea8dc4b6Seschrock if (dp->dp_meta_objset) 128ea8dc4b6Seschrock dmu_objset_evict(NULL, dp->dp_meta_objset->os); 129fa9e4066Sahrens 130fa9e4066Sahrens txg_list_destroy(&dp->dp_dirty_datasets); 131fa9e4066Sahrens txg_list_destroy(&dp->dp_dirty_dirs); 132fa9e4066Sahrens list_destroy(&dp->dp_synced_objsets); 133fa9e4066Sahrens 134fa9e4066Sahrens arc_flush(); 135fa9e4066Sahrens txg_fini(dp); 1365ad82045Snd rw_destroy(&dp->dp_config_rwlock); 137fa9e4066Sahrens kmem_free(dp, sizeof (dsl_pool_t)); 138fa9e4066Sahrens } 139fa9e4066Sahrens 140fa9e4066Sahrens dsl_pool_t * 141fa9e4066Sahrens dsl_pool_create(spa_t *spa, uint64_t txg) 142fa9e4066Sahrens { 143fa9e4066Sahrens int err; 144fa9e4066Sahrens dsl_pool_t *dp = dsl_pool_open_impl(spa, txg); 145fa9e4066Sahrens dmu_tx_t *tx = dmu_tx_create_assigned(dp, txg); 146fa9e4066Sahrens dp->dp_meta_objset = &dmu_objset_create_impl(spa, 147*c717a561Smaybee NULL, &dp->dp_meta_rootbp, DMU_OST_META, tx)->os; 148fa9e4066Sahrens 149fa9e4066Sahrens /* create the pool directory */ 150fa9e4066Sahrens err = zap_create_claim(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT, 151fa9e4066Sahrens DMU_OT_OBJECT_DIRECTORY, DMU_OT_NONE, 0, tx); 152fa9e4066Sahrens ASSERT3U(err, ==, 0); 153fa9e4066Sahrens 154fa9e4066Sahrens /* create and open the root dir */ 155fa9e4066Sahrens dsl_dataset_create_root(dp, &dp->dp_root_dir_obj, tx); 156ea8dc4b6Seschrock VERIFY(0 == dsl_dir_open_obj(dp, dp->dp_root_dir_obj, 157ea8dc4b6Seschrock NULL, dp, &dp->dp_root_dir)); 158fa9e4066Sahrens 159fa9e4066Sahrens /* create and open the meta-objset dir */ 1601d452cf5Sahrens (void) dsl_dir_create_sync(dp->dp_root_dir, MOS_DIR_NAME, tx); 161ea8dc4b6Seschrock VERIFY(0 == dsl_pool_open_mos_dir(dp, &dp->dp_mos_dir)); 162fa9e4066Sahrens 163fa9e4066Sahrens dmu_tx_commit(tx); 164fa9e4066Sahrens 165fa9e4066Sahrens return (dp); 166fa9e4066Sahrens } 167fa9e4066Sahrens 168fa9e4066Sahrens void 169fa9e4066Sahrens dsl_pool_sync(dsl_pool_t *dp, uint64_t txg) 170fa9e4066Sahrens { 171*c717a561Smaybee zio_t *zio; 172fa9e4066Sahrens dmu_tx_t *tx; 173*c717a561Smaybee dsl_dir_t *dd; 174*c717a561Smaybee dsl_dataset_t *ds; 175*c717a561Smaybee dsl_sync_task_group_t *dstg; 176fa9e4066Sahrens objset_impl_t *mosi = dp->dp_meta_objset->os; 177*c717a561Smaybee int err; 178fa9e4066Sahrens 179fa9e4066Sahrens tx = dmu_tx_create_assigned(dp, txg); 180fa9e4066Sahrens 181*c717a561Smaybee zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED); 182*c717a561Smaybee while (ds = txg_list_remove(&dp->dp_dirty_datasets, txg)) { 183*c717a561Smaybee if (!list_link_active(&ds->ds_synced_link)) 184*c717a561Smaybee list_insert_tail(&dp->dp_synced_objsets, ds); 185*c717a561Smaybee dsl_dataset_sync(ds, zio, tx); 186*c717a561Smaybee } 187*c717a561Smaybee err = zio_wait(zio); 188*c717a561Smaybee ASSERT(err == 0); 189*c717a561Smaybee 190*c717a561Smaybee while (dstg = txg_list_remove(&dp->dp_sync_tasks, txg)) 191*c717a561Smaybee dsl_sync_task_group_sync(dstg, tx); 192*c717a561Smaybee while (dd = txg_list_remove(&dp->dp_dirty_dirs, txg)) 193*c717a561Smaybee dsl_dir_sync(dd, tx); 194fa9e4066Sahrens 195fa9e4066Sahrens if (list_head(&mosi->os_dirty_dnodes[txg & TXG_MASK]) != NULL || 196fa9e4066Sahrens list_head(&mosi->os_free_dnodes[txg & TXG_MASK]) != NULL) { 197*c717a561Smaybee zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED); 198*c717a561Smaybee dmu_objset_sync(mosi, zio, tx); 199*c717a561Smaybee err = zio_wait(zio); 200*c717a561Smaybee ASSERT(err == 0); 201fa9e4066Sahrens dprintf_bp(&dp->dp_meta_rootbp, "meta objset rootbp is %s", ""); 202fa9e4066Sahrens spa_set_rootblkptr(dp->dp_spa, &dp->dp_meta_rootbp); 203fa9e4066Sahrens } 204fa9e4066Sahrens 205fa9e4066Sahrens dmu_tx_commit(tx); 206fa9e4066Sahrens } 207fa9e4066Sahrens 208fa9e4066Sahrens void 209fa9e4066Sahrens dsl_pool_zil_clean(dsl_pool_t *dp) 210fa9e4066Sahrens { 211fa9e4066Sahrens dsl_dataset_t *ds; 212fa9e4066Sahrens 213fa9e4066Sahrens while (ds = list_head(&dp->dp_synced_objsets)) { 214fa9e4066Sahrens list_remove(&dp->dp_synced_objsets, ds); 215fa9e4066Sahrens ASSERT(ds->ds_user_ptr != NULL); 216fa9e4066Sahrens zil_clean(((objset_impl_t *)ds->ds_user_ptr)->os_zil); 217fa9e4066Sahrens } 218fa9e4066Sahrens } 219fa9e4066Sahrens 220*c717a561Smaybee /* 221*c717a561Smaybee * TRUE if the current thread is the tx_sync_thread or if we 222*c717a561Smaybee * are being called from SPA context during pool initialization. 223*c717a561Smaybee */ 224fa9e4066Sahrens int 225fa9e4066Sahrens dsl_pool_sync_context(dsl_pool_t *dp) 226fa9e4066Sahrens { 227fa9e4066Sahrens return (curthread == dp->dp_tx.tx_sync_thread || 228*c717a561Smaybee spa_get_dsl(dp->dp_spa) == NULL); 229fa9e4066Sahrens } 230fa9e4066Sahrens 231fa9e4066Sahrens uint64_t 232fa9e4066Sahrens dsl_pool_adjustedsize(dsl_pool_t *dp, boolean_t netfree) 233fa9e4066Sahrens { 234fa9e4066Sahrens uint64_t space, resv; 235fa9e4066Sahrens 236fa9e4066Sahrens /* 23744cd46caSbillm * Reserve about 1.6% (1/64), or at least 32MB, for allocation 238fa9e4066Sahrens * efficiency. 239fa9e4066Sahrens * XXX The intent log is not accounted for, so it must fit 240fa9e4066Sahrens * within this slop. 241fa9e4066Sahrens * 242fa9e4066Sahrens * If we're trying to assess whether it's OK to do a free, 243fa9e4066Sahrens * cut the reservation in half to allow forward progress 244fa9e4066Sahrens * (e.g. make it possible to rm(1) files from a full pool). 245fa9e4066Sahrens */ 24699653d4eSeschrock space = spa_get_dspace(dp->dp_spa); 24744cd46caSbillm resv = MAX(space >> 6, SPA_MINDEVSIZE >> 1); 248fa9e4066Sahrens if (netfree) 249fa9e4066Sahrens resv >>= 1; 250fa9e4066Sahrens 251fa9e4066Sahrens return (space - resv); 252fa9e4066Sahrens } 253