FreeBSD ZFS
The Zettabyte File System
|
00001 /* 00002 * CDDL HEADER START 00003 * 00004 * The contents of this file are subject to the terms of the 00005 * Common Development and Distribution License (the "License"). 00006 * You may not use this file except in compliance with the License. 00007 * 00008 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 00009 * or http://www.opensolaris.org/os/licensing. 00010 * See the License for the specific language governing permissions 00011 * and limitations under the License. 00012 * 00013 * When distributing Covered Code, include this CDDL HEADER in each 00014 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 00015 * If applicable, add the following below this CDDL HEADER, with the 00016 * fields enclosed by brackets "[]" replaced with your own identifying 00017 * information: Portions Copyright [yyyy] [name of copyright owner] 00018 * 00019 * CDDL HEADER END 00020 */ 00021 /* 00022 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 00023 */ 00024 00025 #include <sys/dmu.h> 00026 #include <sys/dmu_tx.h> 00027 #include <sys/dsl_pool.h> 00028 #include <sys/dsl_dir.h> 00029 #include <sys/dsl_synctask.h> 00030 #include <sys/metaslab.h> 00031 00032 #define DST_AVG_BLKSHIFT 14 00033 00034 /* ARGSUSED */ 00035 static int 00036 dsl_null_checkfunc(void *arg1, void *arg2, dmu_tx_t *tx) 00037 { 00038 return (0); 00039 } 00040 00041 dsl_sync_task_group_t * 00042 dsl_sync_task_group_create(dsl_pool_t *dp) 00043 { 00044 dsl_sync_task_group_t *dstg; 00045 00046 dstg = kmem_zalloc(sizeof (dsl_sync_task_group_t), KM_SLEEP); 00047 list_create(&dstg->dstg_tasks, sizeof (dsl_sync_task_t), 00048 offsetof(dsl_sync_task_t, dst_node)); 00049 dstg->dstg_pool = dp; 00050 00051 return (dstg); 00052 } 00053 00054 void 00055 dsl_sync_task_create(dsl_sync_task_group_t *dstg, 00056 dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc, 00057 void *arg1, void *arg2, int blocks_modified) 00058 { 00059 dsl_sync_task_t *dst; 00060 00061 if (checkfunc == NULL) 00062 checkfunc = dsl_null_checkfunc; 00063 dst = kmem_zalloc(sizeof (dsl_sync_task_t), KM_SLEEP); 00064 dst->dst_checkfunc = checkfunc; 00065 dst->dst_syncfunc = syncfunc; 00066 dst->dst_arg1 = arg1; 00067 dst->dst_arg2 = arg2; 00068 list_insert_tail(&dstg->dstg_tasks, dst); 00069 00070 dstg->dstg_space += blocks_modified << DST_AVG_BLKSHIFT; 00071 } 00072 00073 int 00074 dsl_sync_task_group_wait(dsl_sync_task_group_t *dstg) 00075 { 00076 dmu_tx_t *tx; 00077 uint64_t txg; 00078 dsl_sync_task_t *dst; 00079 00080 top: 00081 tx = dmu_tx_create_dd(dstg->dstg_pool->dp_mos_dir); 00082 VERIFY(0 == dmu_tx_assign(tx, TXG_WAIT)); 00083 00084 txg = dmu_tx_get_txg(tx); 00085 00086 /* Do a preliminary error check. */ 00087 dstg->dstg_err = 0; 00088 rw_enter(&dstg->dstg_pool->dp_config_rwlock, RW_READER); 00089 for (dst = list_head(&dstg->dstg_tasks); dst; 00090 dst = list_next(&dstg->dstg_tasks, dst)) { 00091 #ifdef ZFS_DEBUG 00092 /* 00093 * Only check half the time, otherwise, the sync-context 00094 * check will almost never fail. 00095 */ 00096 if (spa_get_random(2) == 0) 00097 continue; 00098 #endif 00099 dst->dst_err = 00100 dst->dst_checkfunc(dst->dst_arg1, dst->dst_arg2, tx); 00101 if (dst->dst_err) 00102 dstg->dstg_err = dst->dst_err; 00103 } 00104 rw_exit(&dstg->dstg_pool->dp_config_rwlock); 00105 00106 if (dstg->dstg_err) { 00107 dmu_tx_commit(tx); 00108 return (dstg->dstg_err); 00109 } 00110 00111 /* 00112 * We don't generally have many sync tasks, so pay the price of 00113 * add_tail to get the tasks executed in the right order. 00114 */ 00115 VERIFY(0 == txg_list_add_tail(&dstg->dstg_pool->dp_sync_tasks, 00116 dstg, txg)); 00117 00118 dmu_tx_commit(tx); 00119 00120 txg_wait_synced(dstg->dstg_pool, txg); 00121 00122 if (dstg->dstg_err == EAGAIN) { 00123 txg_wait_synced(dstg->dstg_pool, txg + TXG_DEFER_SIZE); 00124 goto top; 00125 } 00126 00127 return (dstg->dstg_err); 00128 } 00129 00130 void 00131 dsl_sync_task_group_nowait(dsl_sync_task_group_t *dstg, dmu_tx_t *tx) 00132 { 00133 uint64_t txg; 00134 00135 dstg->dstg_nowaiter = B_TRUE; 00136 txg = dmu_tx_get_txg(tx); 00137 /* 00138 * We don't generally have many sync tasks, so pay the price of 00139 * add_tail to get the tasks executed in the right order. 00140 */ 00141 VERIFY(0 == txg_list_add_tail(&dstg->dstg_pool->dp_sync_tasks, 00142 dstg, txg)); 00143 } 00144 00145 void 00146 dsl_sync_task_group_destroy(dsl_sync_task_group_t *dstg) 00147 { 00148 dsl_sync_task_t *dst; 00149 00150 while (dst = list_head(&dstg->dstg_tasks)) { 00151 list_remove(&dstg->dstg_tasks, dst); 00152 kmem_free(dst, sizeof (dsl_sync_task_t)); 00153 } 00154 kmem_free(dstg, sizeof (dsl_sync_task_group_t)); 00155 } 00156 00157 void 00158 dsl_sync_task_group_sync(dsl_sync_task_group_t *dstg, dmu_tx_t *tx) 00159 { 00160 dsl_sync_task_t *dst; 00161 dsl_pool_t *dp = dstg->dstg_pool; 00162 uint64_t quota, used; 00163 00164 ASSERT0(dstg->dstg_err); 00165 00166 /* 00167 * Check for sufficient space. We just check against what's 00168 * on-disk; we don't want any in-flight accounting to get in our 00169 * way, because open context may have already used up various 00170 * in-core limits (arc_tempreserve, dsl_pool_tempreserve). 00171 */ 00172 quota = dsl_pool_adjustedsize(dp, B_FALSE) - 00173 metaslab_class_get_deferred(spa_normal_class(dp->dp_spa)); 00174 used = dp->dp_root_dir->dd_phys->dd_used_bytes; 00175 /* MOS space is triple-dittoed, so we multiply by 3. */ 00176 if (dstg->dstg_space > 0 && used + dstg->dstg_space * 3 > quota) { 00177 dstg->dstg_err = ENOSPC; 00178 return; 00179 } 00180 00181 /* 00182 * Check for errors by calling checkfuncs. 00183 */ 00184 rw_enter(&dp->dp_config_rwlock, RW_WRITER); 00185 for (dst = list_head(&dstg->dstg_tasks); dst; 00186 dst = list_next(&dstg->dstg_tasks, dst)) { 00187 dst->dst_err = 00188 dst->dst_checkfunc(dst->dst_arg1, dst->dst_arg2, tx); 00189 if (dst->dst_err) 00190 dstg->dstg_err = dst->dst_err; 00191 } 00192 00193 if (dstg->dstg_err == 0) { 00194 /* 00195 * Execute sync tasks. 00196 */ 00197 for (dst = list_head(&dstg->dstg_tasks); dst; 00198 dst = list_next(&dstg->dstg_tasks, dst)) { 00199 dst->dst_syncfunc(dst->dst_arg1, dst->dst_arg2, tx); 00200 } 00201 } 00202 rw_exit(&dp->dp_config_rwlock); 00203 00204 if (dstg->dstg_nowaiter) 00205 dsl_sync_task_group_destroy(dstg); 00206 } 00207 00208 int 00209 dsl_sync_task_do(dsl_pool_t *dp, 00210 dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc, 00211 void *arg1, void *arg2, int blocks_modified) 00212 { 00213 dsl_sync_task_group_t *dstg; 00214 int err; 00215 00216 ASSERT(spa_writeable(dp->dp_spa)); 00217 00218 dstg = dsl_sync_task_group_create(dp); 00219 dsl_sync_task_create(dstg, checkfunc, syncfunc, 00220 arg1, arg2, blocks_modified); 00221 err = dsl_sync_task_group_wait(dstg); 00222 dsl_sync_task_group_destroy(dstg); 00223 return (err); 00224 } 00225 00226 void 00227 dsl_sync_task_do_nowait(dsl_pool_t *dp, 00228 dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc, 00229 void *arg1, void *arg2, int blocks_modified, dmu_tx_t *tx) 00230 { 00231 dsl_sync_task_group_t *dstg = dsl_sync_task_group_create(dp); 00232 dsl_sync_task_create(dstg, checkfunc, syncfunc, 00233 arg1, arg2, blocks_modified); 00234 dsl_sync_task_group_nowait(dstg, tx); 00235 }