1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright (c) 2012, 2017 by Delphix. All rights reserved. 24 */ 25 26 #include <sys/dmu.h> 27 #include <sys/dmu_tx.h> 28 #include <sys/dsl_pool.h> 29 #include <sys/dsl_dir.h> 30 #include <sys/dsl_synctask.h> 31 #include <sys/metaslab.h> 32 33 #define DST_AVG_BLKSHIFT 14 34 35 /* ARGSUSED */ 36 static int 37 dsl_null_checkfunc(void *arg, dmu_tx_t *tx) 38 { 39 return (0); 40 } 41 42 static int 43 dsl_sync_task_common(const char *pool, dsl_checkfunc_t *checkfunc, 44 dsl_syncfunc_t *syncfunc, dsl_sigfunc_t *sigfunc, void *arg, 45 int blocks_modified, zfs_space_check_t space_check, boolean_t early) 46 { 47 spa_t *spa; 48 dmu_tx_t *tx; 49 int err; 50 dsl_sync_task_t dst = { { { NULL } } }; 51 dsl_pool_t *dp; 52 53 err = spa_open(pool, &spa, FTAG); 54 if (err != 0) 55 return (err); 56 dp = spa_get_dsl(spa); 57 58 top: 59 tx = dmu_tx_create_dd(dp->dp_mos_dir); 60 VERIFY0(dmu_tx_assign(tx, TXG_WAIT)); 61 62 dst.dst_pool = dp; 63 dst.dst_txg = dmu_tx_get_txg(tx); 64 dst.dst_space = blocks_modified << DST_AVG_BLKSHIFT; 65 dst.dst_space_check = space_check; 66 dst.dst_checkfunc = checkfunc != NULL ? checkfunc : dsl_null_checkfunc; 67 dst.dst_syncfunc = syncfunc; 68 dst.dst_arg = arg; 69 dst.dst_error = 0; 70 dst.dst_nowaiter = B_FALSE; 71 72 dsl_pool_config_enter(dp, FTAG); 73 err = dst.dst_checkfunc(arg, tx); 74 dsl_pool_config_exit(dp, FTAG); 75 76 if (err != 0) { 77 dmu_tx_commit(tx); 78 spa_close(spa, FTAG); 79 return (err); 80 } 81 82 txg_list_t *task_list = (early) ? 83 &dp->dp_early_sync_tasks : &dp->dp_sync_tasks; 84 VERIFY(txg_list_add_tail(task_list, &dst, dst.dst_txg)); 85 86 dmu_tx_commit(tx); 87 88 if (sigfunc != NULL && txg_wait_synced_sig(dp, dst.dst_txg)) { 89 /* current contract is to call func once */ 90 sigfunc(arg, tx); 91 sigfunc = NULL; /* in case we're performing an EAGAIN retry */ 92 } 93 txg_wait_synced(dp, dst.dst_txg); 94 95 if (dst.dst_error == EAGAIN) { 96 txg_wait_synced(dp, dst.dst_txg + TXG_DEFER_SIZE); 97 goto top; 98 } 99 100 spa_close(spa, FTAG); 101 return (dst.dst_error); 102 } 103 104 /* 105 * Called from open context to perform a callback in syncing context. Waits 106 * for the operation to complete. 107 * 108 * The checkfunc will be called from open context as a preliminary check 109 * which can quickly fail. If it succeeds, it will be called again from 110 * syncing context. The checkfunc should generally be designed to work 111 * properly in either context, but if necessary it can check 112 * dmu_tx_is_syncing(tx). 113 * 114 * The synctask infrastructure enforces proper locking strategy with respect 115 * to the dp_config_rwlock -- the lock will always be held when the callbacks 116 * are called. It will be held for read during the open-context (preliminary) 117 * call to the checkfunc, and then held for write from syncing context during 118 * the calls to the check and sync funcs. 119 * 120 * A dataset or pool name can be passed as the first argument. Typically, 121 * the check func will hold, check the return value of the hold, and then 122 * release the dataset. The sync func will VERIFYO(hold()) the dataset. 123 * This is safe because no changes can be made between the check and sync funcs, 124 * and the sync func will only be called if the check func successfully opened 125 * the dataset. 126 */ 127 int 128 dsl_sync_task(const char *pool, dsl_checkfunc_t *checkfunc, 129 dsl_syncfunc_t *syncfunc, void *arg, 130 int blocks_modified, zfs_space_check_t space_check) 131 { 132 return (dsl_sync_task_common(pool, checkfunc, syncfunc, NULL, arg, 133 blocks_modified, space_check, B_FALSE)); 134 } 135 136 /* 137 * An early synctask works exactly as a standard synctask with one important 138 * difference on the way it is handled during syncing context. Standard 139 * synctasks run after we've written out all the dirty blocks of dirty 140 * datasets. Early synctasks are executed before writing out any dirty data, 141 * and thus before standard synctasks. 142 * 143 * For that reason, early synctasks can affect the process of writing dirty 144 * changes to disk for the txg that they run and should be used with caution. 145 * In addition, early synctasks should not dirty any metaslabs as this would 146 * invalidate the precondition/invariant for subsequent early synctasks. 147 * [see dsl_pool_sync() and dsl_early_sync_task_verify()] 148 */ 149 int 150 dsl_early_sync_task(const char *pool, dsl_checkfunc_t *checkfunc, 151 dsl_syncfunc_t *syncfunc, void *arg, 152 int blocks_modified, zfs_space_check_t space_check) 153 { 154 return (dsl_sync_task_common(pool, checkfunc, syncfunc, NULL, arg, 155 blocks_modified, space_check, B_TRUE)); 156 } 157 158 /* 159 * A standard synctask that can be interrupted from a signal. The sigfunc 160 * is called once if a signal occurred while waiting for the task to sync. 161 */ 162 int 163 dsl_sync_task_sig(const char *pool, dsl_checkfunc_t *checkfunc, 164 dsl_syncfunc_t *syncfunc, dsl_sigfunc_t *sigfunc, void *arg, 165 int blocks_modified, zfs_space_check_t space_check) 166 { 167 return (dsl_sync_task_common(pool, checkfunc, syncfunc, sigfunc, arg, 168 blocks_modified, space_check, B_FALSE)); 169 } 170 171 static void 172 dsl_sync_task_nowait_common(dsl_pool_t *dp, dsl_syncfunc_t *syncfunc, void *arg, 173 int blocks_modified, zfs_space_check_t space_check, dmu_tx_t *tx, 174 boolean_t early) 175 { 176 dsl_sync_task_t *dst = kmem_zalloc(sizeof (*dst), KM_SLEEP); 177 178 dst->dst_pool = dp; 179 dst->dst_txg = dmu_tx_get_txg(tx); 180 dst->dst_space = blocks_modified << DST_AVG_BLKSHIFT; 181 dst->dst_space_check = space_check; 182 dst->dst_checkfunc = dsl_null_checkfunc; 183 dst->dst_syncfunc = syncfunc; 184 dst->dst_arg = arg; 185 dst->dst_error = 0; 186 dst->dst_nowaiter = B_TRUE; 187 188 txg_list_t *task_list = (early) ? 189 &dp->dp_early_sync_tasks : &dp->dp_sync_tasks; 190 VERIFY(txg_list_add_tail(task_list, dst, dst->dst_txg)); 191 } 192 193 void 194 dsl_sync_task_nowait(dsl_pool_t *dp, dsl_syncfunc_t *syncfunc, void *arg, 195 int blocks_modified, zfs_space_check_t space_check, dmu_tx_t *tx) 196 { 197 dsl_sync_task_nowait_common(dp, syncfunc, arg, 198 blocks_modified, space_check, tx, B_FALSE); 199 } 200 201 void 202 dsl_early_sync_task_nowait(dsl_pool_t *dp, dsl_syncfunc_t *syncfunc, void *arg, 203 int blocks_modified, zfs_space_check_t space_check, dmu_tx_t *tx) 204 { 205 dsl_sync_task_nowait_common(dp, syncfunc, arg, 206 blocks_modified, space_check, tx, B_TRUE); 207 } 208 209 /* 210 * Called in syncing context to execute the synctask. 211 */ 212 void 213 dsl_sync_task_sync(dsl_sync_task_t *dst, dmu_tx_t *tx) 214 { 215 dsl_pool_t *dp = dst->dst_pool; 216 217 ASSERT0(dst->dst_error); 218 219 /* 220 * Check for sufficient space. 221 * 222 * When the sync task was created, the caller specified the 223 * type of space checking required. See the comment in 224 * zfs_space_check_t for details on the semantics of each 225 * type of space checking. 226 * 227 * We just check against what's on-disk; we don't want any 228 * in-flight accounting to get in our way, because open context 229 * may have already used up various in-core limits 230 * (arc_tempreserve, dsl_pool_tempreserve). 231 */ 232 if (dst->dst_space_check != ZFS_SPACE_CHECK_NONE) { 233 uint64_t quota = dsl_pool_unreserved_space(dp, 234 dst->dst_space_check); 235 uint64_t used = dsl_dir_phys(dp->dp_root_dir)->dd_used_bytes; 236 237 /* MOS space is triple-dittoed, so we multiply by 3. */ 238 if (used + dst->dst_space * 3 > quota) { 239 dst->dst_error = SET_ERROR(ENOSPC); 240 if (dst->dst_nowaiter) 241 kmem_free(dst, sizeof (*dst)); 242 return; 243 } 244 } 245 246 /* 247 * Check for errors by calling checkfunc. 248 */ 249 rrw_enter(&dp->dp_config_rwlock, RW_WRITER, FTAG); 250 dst->dst_error = dst->dst_checkfunc(dst->dst_arg, tx); 251 if (dst->dst_error == 0) 252 dst->dst_syncfunc(dst->dst_arg, tx); 253 rrw_exit(&dp->dp_config_rwlock, FTAG); 254 if (dst->dst_nowaiter) 255 kmem_free(dst, sizeof (*dst)); 256 } 257 258 #if defined(_KERNEL) 259 EXPORT_SYMBOL(dsl_sync_task); 260 EXPORT_SYMBOL(dsl_sync_task_nowait); 261 #endif 262