dmu_objset.c (177698) | dmu_objset.c (185029) |
---|---|
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 --- 5 unchanged lines hidden (view full) --- 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/* | 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 --- 5 unchanged lines hidden (view full) --- 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 2007 Sun Microsystems, Inc. All rights reserved. | 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. |
23 * Use is subject to license terms. 24 */ 25 | 23 * Use is subject to license terms. 24 */ 25 |
26#pragma ident "%Z%%M% %I% %E% SMI" 27 | 26#include <sys/cred.h> |
28#include <sys/zfs_context.h> 29#include <sys/dmu_objset.h> 30#include <sys/dsl_dir.h> 31#include <sys/dsl_dataset.h> 32#include <sys/dsl_prop.h> 33#include <sys/dsl_pool.h> 34#include <sys/dsl_synctask.h> | 27#include <sys/zfs_context.h> 28#include <sys/dmu_objset.h> 29#include <sys/dsl_dir.h> 30#include <sys/dsl_dataset.h> 31#include <sys/dsl_prop.h> 32#include <sys/dsl_pool.h> 33#include <sys/dsl_synctask.h> |
34#include <sys/dsl_deleg.h> |
|
35#include <sys/dnode.h> 36#include <sys/dbuf.h> 37#include <sys/zvol.h> 38#include <sys/dmu_tx.h> 39#include <sys/zio_checksum.h> 40#include <sys/zap.h> 41#include <sys/zil.h> 42#include <sys/dmu_impl.h> | 35#include <sys/dnode.h> 36#include <sys/dbuf.h> 37#include <sys/zvol.h> 38#include <sys/dmu_tx.h> 39#include <sys/zio_checksum.h> 40#include <sys/zap.h> 41#include <sys/zil.h> 42#include <sys/dmu_impl.h> |
43#include <sys/zfs_ioctl.h> |
|
43 | 44 |
44 | |
45spa_t * 46dmu_objset_spa(objset_t *os) 47{ 48 return (os->os->os_spa); 49} 50 51zilog_t * 52dmu_objset_zil(objset_t *os) --- 73 unchanged lines hidden (view full) --- 126 * Inheritance and range checking should have been done by now. 127 */ 128 ASSERT(newval > 0); 129 ASSERT(newval <= spa_max_replication(osi->os_spa)); 130 131 osi->os_copies = newval; 132} 133 | 45spa_t * 46dmu_objset_spa(objset_t *os) 47{ 48 return (os->os->os_spa); 49} 50 51zilog_t * 52dmu_objset_zil(objset_t *os) --- 73 unchanged lines hidden (view full) --- 126 * Inheritance and range checking should have been done by now. 127 */ 128 ASSERT(newval > 0); 129 ASSERT(newval <= spa_max_replication(osi->os_spa)); 130 131 osi->os_copies = newval; 132} 133 |
134static void 135primary_cache_changed_cb(void *arg, uint64_t newval) 136{ 137 objset_impl_t *osi = arg; 138 139 /* 140 * Inheritance and range checking should have been done by now. 141 */ 142 ASSERT(newval == ZFS_CACHE_ALL || newval == ZFS_CACHE_NONE || 143 newval == ZFS_CACHE_METADATA); 144 145 osi->os_primary_cache = newval; 146} 147 148static void 149secondary_cache_changed_cb(void *arg, uint64_t newval) 150{ 151 objset_impl_t *osi = arg; 152 153 /* 154 * Inheritance and range checking should have been done by now. 155 */ 156 ASSERT(newval == ZFS_CACHE_ALL || newval == ZFS_CACHE_NONE || 157 newval == ZFS_CACHE_METADATA); 158 159 osi->os_secondary_cache = newval; 160} 161 |
|
134void 135dmu_objset_byteswap(void *buf, size_t size) 136{ 137 objset_phys_t *osp = buf; 138 139 ASSERT(size == sizeof (objset_phys_t)); 140 dnode_byteswap(&osp->os_meta_dnode); 141 byteswap_uint64_array(&osp->os_zil_header, sizeof (zil_header_t)); 142 osp->os_type = BSWAP_64(osp->os_type); 143} 144 145int 146dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp, 147 objset_impl_t **osip) 148{ | 162void 163dmu_objset_byteswap(void *buf, size_t size) 164{ 165 objset_phys_t *osp = buf; 166 167 ASSERT(size == sizeof (objset_phys_t)); 168 dnode_byteswap(&osp->os_meta_dnode); 169 byteswap_uint64_array(&osp->os_zil_header, sizeof (zil_header_t)); 170 osp->os_type = BSWAP_64(osp->os_type); 171} 172 173int 174dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp, 175 objset_impl_t **osip) 176{ |
149 objset_impl_t *winner, *osi; 150 int i, err, checksum; | 177 objset_impl_t *osi; 178 int i, err; |
151 | 179 |
180 ASSERT(ds == NULL || MUTEX_HELD(&ds->ds_opening_lock)); 181 |
|
152 osi = kmem_zalloc(sizeof (objset_impl_t), KM_SLEEP); 153 osi->os.os = osi; 154 osi->os_dsl_dataset = ds; 155 osi->os_spa = spa; 156 osi->os_rootbp = bp; 157 if (!BP_IS_HOLE(osi->os_rootbp)) { 158 uint32_t aflags = ARC_WAIT; 159 zbookmark_t zb; 160 zb.zb_objset = ds ? ds->ds_object : 0; 161 zb.zb_object = 0; 162 zb.zb_level = -1; 163 zb.zb_blkid = 0; | 182 osi = kmem_zalloc(sizeof (objset_impl_t), KM_SLEEP); 183 osi->os.os = osi; 184 osi->os_dsl_dataset = ds; 185 osi->os_spa = spa; 186 osi->os_rootbp = bp; 187 if (!BP_IS_HOLE(osi->os_rootbp)) { 188 uint32_t aflags = ARC_WAIT; 189 zbookmark_t zb; 190 zb.zb_objset = ds ? ds->ds_object : 0; 191 zb.zb_object = 0; 192 zb.zb_level = -1; 193 zb.zb_blkid = 0; |
194 if (DMU_OS_IS_L2CACHEABLE(osi)) 195 aflags |= ARC_L2CACHE; |
|
164 165 dprintf_bp(osi->os_rootbp, "reading %s", ""); | 196 197 dprintf_bp(osi->os_rootbp, "reading %s", ""); |
166 err = arc_read(NULL, spa, osi->os_rootbp, 167 dmu_ot[DMU_OT_OBJSET].ot_byteswap, | 198 /* 199 * NB: when bprewrite scrub can change the bp, 200 * and this is called from dmu_objset_open_ds_os, the bp 201 * could change, and we'll need a lock. 202 */ 203 err = arc_read_nolock(NULL, spa, osi->os_rootbp, |
168 arc_getbuf_func, &osi->os_phys_buf, 169 ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &aflags, &zb); 170 if (err) { 171 kmem_free(osi, sizeof (objset_impl_t)); | 204 arc_getbuf_func, &osi->os_phys_buf, 205 ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &aflags, &zb); 206 if (err) { 207 kmem_free(osi, sizeof (objset_impl_t)); |
208 /* convert checksum errors into IO errors */ 209 if (err == ECKSUM) 210 err = EIO; |
|
172 return (err); 173 } 174 osi->os_phys = osi->os_phys_buf->b_data; | 211 return (err); 212 } 213 osi->os_phys = osi->os_phys_buf->b_data; |
175 arc_release(osi->os_phys_buf, &osi->os_phys_buf); | |
176 } else { 177 osi->os_phys_buf = arc_buf_alloc(spa, sizeof (objset_phys_t), 178 &osi->os_phys_buf, ARC_BUFC_METADATA); 179 osi->os_phys = osi->os_phys_buf->b_data; 180 bzero(osi->os_phys, sizeof (objset_phys_t)); 181 } 182 183 /* 184 * Note: the changed_cb will be called once before the register 185 * func returns, thus changing the checksum/compression from the | 214 } else { 215 osi->os_phys_buf = arc_buf_alloc(spa, sizeof (objset_phys_t), 216 &osi->os_phys_buf, ARC_BUFC_METADATA); 217 osi->os_phys = osi->os_phys_buf->b_data; 218 bzero(osi->os_phys, sizeof (objset_phys_t)); 219 } 220 221 /* 222 * Note: the changed_cb will be called once before the register 223 * func returns, thus changing the checksum/compression from the |
186 * default (fletcher2/off). Snapshots don't need to know, and 187 * registering would complicate clone promotion. | 224 * default (fletcher2/off). Snapshots don't need to know about 225 * checksum/compression/copies. |
188 */ | 226 */ |
189 if (ds && ds->ds_phys->ds_num_children == 0) { 190 err = dsl_prop_register(ds, "checksum", 191 checksum_changed_cb, osi); | 227 if (ds) { 228 err = dsl_prop_register(ds, "primarycache", 229 primary_cache_changed_cb, osi); |
192 if (err == 0) | 230 if (err == 0) |
193 err = dsl_prop_register(ds, "compression", 194 compression_changed_cb, osi); 195 if (err == 0) 196 err = dsl_prop_register(ds, "copies", 197 copies_changed_cb, osi); | 231 err = dsl_prop_register(ds, "secondarycache", 232 secondary_cache_changed_cb, osi); 233 if (!dsl_dataset_is_snapshot(ds)) { 234 if (err == 0) 235 err = dsl_prop_register(ds, "checksum", 236 checksum_changed_cb, osi); 237 if (err == 0) 238 err = dsl_prop_register(ds, "compression", 239 compression_changed_cb, osi); 240 if (err == 0) 241 err = dsl_prop_register(ds, "copies", 242 copies_changed_cb, osi); 243 } |
198 if (err) { 199 VERIFY(arc_buf_remove_ref(osi->os_phys_buf, 200 &osi->os_phys_buf) == 1); 201 kmem_free(osi, sizeof (objset_impl_t)); 202 return (err); 203 } 204 } else if (ds == NULL) { 205 /* It's the meta-objset. */ 206 osi->os_checksum = ZIO_CHECKSUM_FLETCHER_4; 207 osi->os_compress = ZIO_COMPRESS_LZJB; 208 osi->os_copies = spa_max_replication(spa); | 244 if (err) { 245 VERIFY(arc_buf_remove_ref(osi->os_phys_buf, 246 &osi->os_phys_buf) == 1); 247 kmem_free(osi, sizeof (objset_impl_t)); 248 return (err); 249 } 250 } else if (ds == NULL) { 251 /* It's the meta-objset. */ 252 osi->os_checksum = ZIO_CHECKSUM_FLETCHER_4; 253 osi->os_compress = ZIO_COMPRESS_LZJB; 254 osi->os_copies = spa_max_replication(spa); |
255 osi->os_primary_cache = ZFS_CACHE_ALL; 256 osi->os_secondary_cache = ZFS_CACHE_ALL; |
|
209 } 210 | 257 } 258 |
211 osi->os_zil = zil_alloc(&osi->os, &osi->os_phys->os_zil_header); | 259 osi->os_zil_header = osi->os_phys->os_zil_header; 260 osi->os_zil = zil_alloc(&osi->os, &osi->os_zil_header); |
212 | 261 |
213 /* 214 * Metadata always gets compressed and checksummed. 215 * If the data checksum is multi-bit correctable, and it's not 216 * a ZBT-style checksum, then it's suitable for metadata as well. 217 * Otherwise, the metadata checksum defaults to fletcher4. 218 */ 219 checksum = osi->os_checksum; 220 221 if (zio_checksum_table[checksum].ci_correctable && 222 !zio_checksum_table[checksum].ci_zbt) 223 osi->os_md_checksum = checksum; 224 else 225 osi->os_md_checksum = ZIO_CHECKSUM_FLETCHER_4; 226 osi->os_md_compress = ZIO_COMPRESS_LZJB; 227 | |
228 for (i = 0; i < TXG_SIZE; i++) { 229 list_create(&osi->os_dirty_dnodes[i], sizeof (dnode_t), 230 offsetof(dnode_t, dn_dirty_link[i])); 231 list_create(&osi->os_free_dnodes[i], sizeof (dnode_t), 232 offsetof(dnode_t, dn_dirty_link[i])); 233 } 234 list_create(&osi->os_dnodes, sizeof (dnode_t), 235 offsetof(dnode_t, dn_link)); 236 list_create(&osi->os_downgraded_dbufs, sizeof (dmu_buf_impl_t), 237 offsetof(dmu_buf_impl_t, db_link)); 238 239 mutex_init(&osi->os_lock, NULL, MUTEX_DEFAULT, NULL); 240 mutex_init(&osi->os_obj_lock, NULL, MUTEX_DEFAULT, NULL); | 262 for (i = 0; i < TXG_SIZE; i++) { 263 list_create(&osi->os_dirty_dnodes[i], sizeof (dnode_t), 264 offsetof(dnode_t, dn_dirty_link[i])); 265 list_create(&osi->os_free_dnodes[i], sizeof (dnode_t), 266 offsetof(dnode_t, dn_dirty_link[i])); 267 } 268 list_create(&osi->os_dnodes, sizeof (dnode_t), 269 offsetof(dnode_t, dn_link)); 270 list_create(&osi->os_downgraded_dbufs, sizeof (dmu_buf_impl_t), 271 offsetof(dmu_buf_impl_t, db_link)); 272 273 mutex_init(&osi->os_lock, NULL, MUTEX_DEFAULT, NULL); 274 mutex_init(&osi->os_obj_lock, NULL, MUTEX_DEFAULT, NULL); |
275 mutex_init(&osi->os_user_ptr_lock, NULL, MUTEX_DEFAULT, NULL); |
|
241 242 osi->os_meta_dnode = dnode_special_open(osi, 243 &osi->os_phys->os_meta_dnode, DMU_META_DNODE_OBJECT); 244 | 276 277 osi->os_meta_dnode = dnode_special_open(osi, 278 &osi->os_phys->os_meta_dnode, DMU_META_DNODE_OBJECT); 279 |
245 if (ds != NULL) { 246 winner = dsl_dataset_set_user_ptr(ds, osi, dmu_objset_evict); 247 if (winner) { 248 dmu_objset_evict(ds, osi); 249 osi = winner; 250 } | 280 /* 281 * We should be the only thread trying to do this because we 282 * have ds_opening_lock 283 */ 284 if (ds) { 285 VERIFY(NULL == dsl_dataset_set_user_ptr(ds, osi, 286 dmu_objset_evict)); |
251 } 252 253 *osip = osi; 254 return (0); 255} 256 | 287 } 288 289 *osip = osi; 290 return (0); 291} 292 |
257/* called from zpl */ 258int 259dmu_objset_open(const char *name, dmu_objset_type_t type, int mode, 260 objset_t **osp) | 293static int 294dmu_objset_open_ds_os(dsl_dataset_t *ds, objset_t *os, dmu_objset_type_t type) |
261{ | 295{ |
262 dsl_dataset_t *ds; 263 int err; 264 objset_t *os; | |
265 objset_impl_t *osi; 266 | 296 objset_impl_t *osi; 297 |
267 os = kmem_alloc(sizeof (objset_t), KM_SLEEP); 268 err = dsl_dataset_open(name, mode, os, &ds); 269 if (err) { 270 kmem_free(os, sizeof (objset_t)); 271 return (err); 272 } 273 | 298 mutex_enter(&ds->ds_opening_lock); |
274 osi = dsl_dataset_get_user_ptr(ds); 275 if (osi == NULL) { | 299 osi = dsl_dataset_get_user_ptr(ds); 300 if (osi == NULL) { |
301 int err; 302 |
|
276 err = dmu_objset_open_impl(dsl_dataset_get_spa(ds), 277 ds, &ds->ds_phys->ds_bp, &osi); 278 if (err) { | 303 err = dmu_objset_open_impl(dsl_dataset_get_spa(ds), 304 ds, &ds->ds_phys->ds_bp, &osi); 305 if (err) { |
279 dsl_dataset_close(ds, mode, os); 280 kmem_free(os, sizeof (objset_t)); | 306 mutex_exit(&ds->ds_opening_lock); |
281 return (err); 282 } 283 } | 307 return (err); 308 } 309 } |
310 mutex_exit(&ds->ds_opening_lock); |
|
284 285 os->os = osi; | 311 312 os->os = osi; |
286 os->os_mode = mode; | 313 os->os_mode = DS_MODE_NOHOLD; |
287 | 314 |
288 if (type != DMU_OST_ANY && type != os->os->os_phys->os_type) { 289 dmu_objset_close(os); | 315 if (type != DMU_OST_ANY && type != os->os->os_phys->os_type) |
290 return (EINVAL); | 316 return (EINVAL); |
291 } 292 *osp = os; | |
293 return (0); 294} 295 | 317 return (0); 318} 319 |
320int 321dmu_objset_open_ds(dsl_dataset_t *ds, dmu_objset_type_t type, objset_t **osp) 322{ 323 objset_t *os; 324 int err; 325 326 os = kmem_alloc(sizeof (objset_t), KM_SLEEP); 327 err = dmu_objset_open_ds_os(ds, os, type); 328 if (err) 329 kmem_free(os, sizeof (objset_t)); 330 else 331 *osp = os; 332 return (err); 333} 334 335/* called from zpl */ 336int 337dmu_objset_open(const char *name, dmu_objset_type_t type, int mode, 338 objset_t **osp) 339{ 340 objset_t *os; 341 dsl_dataset_t *ds; 342 int err; 343 344 ASSERT(DS_MODE_TYPE(mode) == DS_MODE_USER || 345 DS_MODE_TYPE(mode) == DS_MODE_OWNER); 346 347 os = kmem_alloc(sizeof (objset_t), KM_SLEEP); 348 if (DS_MODE_TYPE(mode) == DS_MODE_USER) 349 err = dsl_dataset_hold(name, os, &ds); 350 else 351 err = dsl_dataset_own(name, mode, os, &ds); 352 if (err) { 353 kmem_free(os, sizeof (objset_t)); 354 return (err); 355 } 356 357 err = dmu_objset_open_ds_os(ds, os, type); 358 if (err) { 359 if (DS_MODE_TYPE(mode) == DS_MODE_USER) 360 dsl_dataset_rele(ds, os); 361 else 362 dsl_dataset_disown(ds, os); 363 kmem_free(os, sizeof (objset_t)); 364 } else { 365 os->os_mode = mode; 366 *osp = os; 367 } 368 return (err); 369} 370 |
|
296void 297dmu_objset_close(objset_t *os) 298{ | 371void 372dmu_objset_close(objset_t *os) 373{ |
299 dsl_dataset_close(os->os->os_dsl_dataset, os->os_mode, os); | 374 ASSERT(DS_MODE_TYPE(os->os_mode) == DS_MODE_USER || 375 DS_MODE_TYPE(os->os_mode) == DS_MODE_OWNER || 376 DS_MODE_TYPE(os->os_mode) == DS_MODE_NOHOLD); 377 378 if (DS_MODE_TYPE(os->os_mode) == DS_MODE_USER) 379 dsl_dataset_rele(os->os->os_dsl_dataset, os); 380 else if (DS_MODE_TYPE(os->os_mode) == DS_MODE_OWNER) 381 dsl_dataset_disown(os->os->os_dsl_dataset, os); |
300 kmem_free(os, sizeof (objset_t)); 301} 302 303int | 382 kmem_free(os, sizeof (objset_t)); 383} 384 385int |
304dmu_objset_evict_dbufs(objset_t *os, int try) | 386dmu_objset_evict_dbufs(objset_t *os) |
305{ 306 objset_impl_t *osi = os->os; 307 dnode_t *dn; 308 309 mutex_enter(&osi->os_lock); 310 311 /* process the mdn last, since the other dnodes have holds on it */ 312 list_remove(&osi->os_dnodes, osi->os_meta_dnode); 313 list_insert_tail(&osi->os_dnodes, osi->os_meta_dnode); 314 315 /* 316 * Find the first dnode with holds. We have to do this dance 317 * because dnode_add_ref() only works if you already have a 318 * hold. If there are no holds then it has no dbufs so OK to 319 * skip. 320 */ 321 for (dn = list_head(&osi->os_dnodes); | 387{ 388 objset_impl_t *osi = os->os; 389 dnode_t *dn; 390 391 mutex_enter(&osi->os_lock); 392 393 /* process the mdn last, since the other dnodes have holds on it */ 394 list_remove(&osi->os_dnodes, osi->os_meta_dnode); 395 list_insert_tail(&osi->os_dnodes, osi->os_meta_dnode); 396 397 /* 398 * Find the first dnode with holds. We have to do this dance 399 * because dnode_add_ref() only works if you already have a 400 * hold. If there are no holds then it has no dbufs so OK to 401 * skip. 402 */ 403 for (dn = list_head(&osi->os_dnodes); |
322 dn && refcount_is_zero(&dn->dn_holds); | 404 dn && !dnode_add_ref(dn, FTAG); |
323 dn = list_next(&osi->os_dnodes, dn)) 324 continue; | 405 dn = list_next(&osi->os_dnodes, dn)) 406 continue; |
325 if (dn) 326 dnode_add_ref(dn, FTAG); | |
327 328 while (dn) { 329 dnode_t *next_dn = dn; 330 331 do { 332 next_dn = list_next(&osi->os_dnodes, next_dn); | 407 408 while (dn) { 409 dnode_t *next_dn = dn; 410 411 do { 412 next_dn = list_next(&osi->os_dnodes, next_dn); |
333 } while (next_dn && refcount_is_zero(&next_dn->dn_holds)); 334 if (next_dn) 335 dnode_add_ref(next_dn, FTAG); | 413 } while (next_dn && !dnode_add_ref(next_dn, FTAG)); |
336 337 mutex_exit(&osi->os_lock); | 414 415 mutex_exit(&osi->os_lock); |
338 if (dnode_evict_dbufs(dn, try)) { 339 dnode_rele(dn, FTAG); 340 if (next_dn) 341 dnode_rele(next_dn, FTAG); 342 return (1); 343 } | 416 dnode_evict_dbufs(dn); |
344 dnode_rele(dn, FTAG); 345 mutex_enter(&osi->os_lock); 346 dn = next_dn; 347 } 348 mutex_exit(&osi->os_lock); | 417 dnode_rele(dn, FTAG); 418 mutex_enter(&osi->os_lock); 419 dn = next_dn; 420 } 421 mutex_exit(&osi->os_lock); |
349 return (0); | 422 return (list_head(&osi->os_dnodes) != osi->os_meta_dnode); |
350} 351 352void 353dmu_objset_evict(dsl_dataset_t *ds, void *arg) 354{ 355 objset_impl_t *osi = arg; 356 objset_t os; 357 int i; 358 359 for (i = 0; i < TXG_SIZE; i++) { 360 ASSERT(list_head(&osi->os_dirty_dnodes[i]) == NULL); 361 ASSERT(list_head(&osi->os_free_dnodes[i]) == NULL); 362 } 363 | 423} 424 425void 426dmu_objset_evict(dsl_dataset_t *ds, void *arg) 427{ 428 objset_impl_t *osi = arg; 429 objset_t os; 430 int i; 431 432 for (i = 0; i < TXG_SIZE; i++) { 433 ASSERT(list_head(&osi->os_dirty_dnodes[i]) == NULL); 434 ASSERT(list_head(&osi->os_free_dnodes[i]) == NULL); 435 } 436 |
364 if (ds && ds->ds_phys->ds_num_children == 0) { 365 VERIFY(0 == dsl_prop_unregister(ds, "checksum", 366 checksum_changed_cb, osi)); 367 VERIFY(0 == dsl_prop_unregister(ds, "compression", 368 compression_changed_cb, osi)); 369 VERIFY(0 == dsl_prop_unregister(ds, "copies", 370 copies_changed_cb, osi)); | 437 if (ds) { 438 if (!dsl_dataset_is_snapshot(ds)) { 439 VERIFY(0 == dsl_prop_unregister(ds, "checksum", 440 checksum_changed_cb, osi)); 441 VERIFY(0 == dsl_prop_unregister(ds, "compression", 442 compression_changed_cb, osi)); 443 VERIFY(0 == dsl_prop_unregister(ds, "copies", 444 copies_changed_cb, osi)); 445 } 446 VERIFY(0 == dsl_prop_unregister(ds, "primarycache", 447 primary_cache_changed_cb, osi)); 448 VERIFY(0 == dsl_prop_unregister(ds, "secondarycache", 449 secondary_cache_changed_cb, osi)); |
371 } 372 373 /* 374 * We should need only a single pass over the dnode list, since 375 * nothing can be added to the list at this point. 376 */ 377 os.os = osi; | 450 } 451 452 /* 453 * We should need only a single pass over the dnode list, since 454 * nothing can be added to the list at this point. 455 */ 456 os.os = osi; |
378 (void) dmu_objset_evict_dbufs(&os, 0); | 457 (void) dmu_objset_evict_dbufs(&os); |
379 380 ASSERT3P(list_head(&osi->os_dnodes), ==, osi->os_meta_dnode); 381 ASSERT3P(list_tail(&osi->os_dnodes), ==, osi->os_meta_dnode); 382 ASSERT3P(list_head(&osi->os_meta_dnode->dn_dbufs), ==, NULL); 383 384 dnode_special_close(osi->os_meta_dnode); 385 zil_free(osi->os_zil); 386 387 VERIFY(arc_buf_remove_ref(osi->os_phys_buf, &osi->os_phys_buf) == 1); 388 mutex_destroy(&osi->os_lock); 389 mutex_destroy(&osi->os_obj_lock); | 458 459 ASSERT3P(list_head(&osi->os_dnodes), ==, osi->os_meta_dnode); 460 ASSERT3P(list_tail(&osi->os_dnodes), ==, osi->os_meta_dnode); 461 ASSERT3P(list_head(&osi->os_meta_dnode->dn_dbufs), ==, NULL); 462 463 dnode_special_close(osi->os_meta_dnode); 464 zil_free(osi->os_zil); 465 466 VERIFY(arc_buf_remove_ref(osi->os_phys_buf, &osi->os_phys_buf) == 1); 467 mutex_destroy(&osi->os_lock); 468 mutex_destroy(&osi->os_obj_lock); |
469 mutex_destroy(&osi->os_user_ptr_lock); |
|
390 kmem_free(osi, sizeof (objset_impl_t)); 391} 392 393/* called from dsl for meta-objset */ 394objset_impl_t * 395dmu_objset_create_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp, 396 dmu_objset_type_t type, dmu_tx_t *tx) 397{ 398 objset_impl_t *osi; 399 dnode_t *mdn; 400 401 ASSERT(dmu_tx_is_syncing(tx)); | 470 kmem_free(osi, sizeof (objset_impl_t)); 471} 472 473/* called from dsl for meta-objset */ 474objset_impl_t * 475dmu_objset_create_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp, 476 dmu_objset_type_t type, dmu_tx_t *tx) 477{ 478 objset_impl_t *osi; 479 dnode_t *mdn; 480 481 ASSERT(dmu_tx_is_syncing(tx)); |
482 if (ds) 483 mutex_enter(&ds->ds_opening_lock); |
|
402 VERIFY(0 == dmu_objset_open_impl(spa, ds, bp, &osi)); | 484 VERIFY(0 == dmu_objset_open_impl(spa, ds, bp, &osi)); |
485 if (ds) 486 mutex_exit(&ds->ds_opening_lock); |
|
403 mdn = osi->os_meta_dnode; 404 405 dnode_allocate(mdn, DMU_OT_DNODE, 1 << DNODE_BLOCK_SHIFT, 406 DN_MAX_INDBLKSHIFT, DMU_OT_NONE, 0, tx); 407 408 /* 409 * We don't want to have to increase the meta-dnode's nlevels 410 * later, because then we could do it in quescing context while --- 27 unchanged lines hidden (view full) --- 438 osi->os_phys->os_type = type; 439 440 dsl_dataset_dirty(ds, tx); 441 442 return (osi); 443} 444 445struct oscarg { | 487 mdn = osi->os_meta_dnode; 488 489 dnode_allocate(mdn, DMU_OT_DNODE, 1 << DNODE_BLOCK_SHIFT, 490 DN_MAX_INDBLKSHIFT, DMU_OT_NONE, 0, tx); 491 492 /* 493 * We don't want to have to increase the meta-dnode's nlevels 494 * later, because then we could do it in quescing context while --- 27 unchanged lines hidden (view full) --- 522 osi->os_phys->os_type = type; 523 524 dsl_dataset_dirty(ds, tx); 525 526 return (osi); 527} 528 529struct oscarg { |
446 void (*userfunc)(objset_t *os, void *arg, dmu_tx_t *tx); | 530 void (*userfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); |
447 void *userarg; 448 dsl_dataset_t *clone_parent; 449 const char *lastname; 450 dmu_objset_type_t type; | 531 void *userarg; 532 dsl_dataset_t *clone_parent; 533 const char *lastname; 534 dmu_objset_type_t type; |
535 uint64_t flags; |
|
451}; 452 | 536}; 537 |
453/* ARGSUSED */ | 538/*ARGSUSED*/ |
454static int 455dmu_objset_create_check(void *arg1, void *arg2, dmu_tx_t *tx) 456{ 457 dsl_dir_t *dd = arg1; 458 struct oscarg *oa = arg2; 459 objset_t *mos = dd->dd_pool->dp_meta_objset; 460 int err; 461 uint64_t ddobj; --- 11 unchanged lines hidden (view full) --- 473 return (EXDEV); 474 475 /* 476 * You can only clone snapshots, not the head datasets. 477 */ 478 if (oa->clone_parent->ds_phys->ds_num_children == 0) 479 return (EINVAL); 480 } | 539static int 540dmu_objset_create_check(void *arg1, void *arg2, dmu_tx_t *tx) 541{ 542 dsl_dir_t *dd = arg1; 543 struct oscarg *oa = arg2; 544 objset_t *mos = dd->dd_pool->dp_meta_objset; 545 int err; 546 uint64_t ddobj; --- 11 unchanged lines hidden (view full) --- 558 return (EXDEV); 559 560 /* 561 * You can only clone snapshots, not the head datasets. 562 */ 563 if (oa->clone_parent->ds_phys->ds_num_children == 0) 564 return (EINVAL); 565 } |
566 |
|
481 return (0); 482} 483 484static void | 567 return (0); 568} 569 570static void |
485dmu_objset_create_sync(void *arg1, void *arg2, dmu_tx_t *tx) | 571dmu_objset_create_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) |
486{ 487 dsl_dir_t *dd = arg1; 488 struct oscarg *oa = arg2; 489 dsl_dataset_t *ds; 490 blkptr_t *bp; 491 uint64_t dsobj; 492 493 ASSERT(dmu_tx_is_syncing(tx)); 494 495 dsobj = dsl_dataset_create_sync(dd, oa->lastname, | 572{ 573 dsl_dir_t *dd = arg1; 574 struct oscarg *oa = arg2; 575 dsl_dataset_t *ds; 576 blkptr_t *bp; 577 uint64_t dsobj; 578 579 ASSERT(dmu_tx_is_syncing(tx)); 580 581 dsobj = dsl_dataset_create_sync(dd, oa->lastname, |
496 oa->clone_parent, tx); | 582 oa->clone_parent, oa->flags, cr, tx); |
497 | 583 |
498 VERIFY(0 == dsl_dataset_open_obj(dd->dd_pool, dsobj, NULL, 499 DS_MODE_STANDARD | DS_MODE_READONLY, FTAG, &ds)); | 584 VERIFY(0 == dsl_dataset_hold_obj(dd->dd_pool, dsobj, FTAG, &ds)); |
500 bp = dsl_dataset_get_blkptr(ds); 501 if (BP_IS_HOLE(bp)) { 502 objset_impl_t *osi; 503 504 /* This is an empty dmu_objset; not a clone. */ 505 osi = dmu_objset_create_impl(dsl_dataset_get_spa(ds), 506 ds, bp, oa->type, tx); 507 508 if (oa->userfunc) | 585 bp = dsl_dataset_get_blkptr(ds); 586 if (BP_IS_HOLE(bp)) { 587 objset_impl_t *osi; 588 589 /* This is an empty dmu_objset; not a clone. */ 590 osi = dmu_objset_create_impl(dsl_dataset_get_spa(ds), 591 ds, bp, oa->type, tx); 592 593 if (oa->userfunc) |
509 oa->userfunc(&osi->os, oa->userarg, tx); | 594 oa->userfunc(&osi->os, oa->userarg, cr, tx); |
510 } | 595 } |
511 dsl_dataset_close(ds, DS_MODE_STANDARD | DS_MODE_READONLY, FTAG); | 596 597 spa_history_internal_log(LOG_DS_CREATE, dd->dd_pool->dp_spa, 598 tx, cr, "dataset = %llu", dsobj); 599 600 dsl_dataset_rele(ds, FTAG); |
512} 513 514int 515dmu_objset_create(const char *name, dmu_objset_type_t type, | 601} 602 603int 604dmu_objset_create(const char *name, dmu_objset_type_t type, |
516 objset_t *clone_parent, 517 void (*func)(objset_t *os, void *arg, dmu_tx_t *tx), void *arg) | 605 objset_t *clone_parent, uint64_t flags, 606 void (*func)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx), void *arg) |
518{ 519 dsl_dir_t *pdd; 520 const char *tail; 521 int err = 0; 522 struct oscarg oa = { 0 }; 523 524 ASSERT(strchr(name, '@') == NULL); 525 err = dsl_dir_open(name, FTAG, &pdd, &tail); --- 5 unchanged lines hidden (view full) --- 531 } 532 533 dprintf("name=%s\n", name); 534 535 oa.userfunc = func; 536 oa.userarg = arg; 537 oa.lastname = tail; 538 oa.type = type; | 607{ 608 dsl_dir_t *pdd; 609 const char *tail; 610 int err = 0; 611 struct oscarg oa = { 0 }; 612 613 ASSERT(strchr(name, '@') == NULL); 614 err = dsl_dir_open(name, FTAG, &pdd, &tail); --- 5 unchanged lines hidden (view full) --- 620 } 621 622 dprintf("name=%s\n", name); 623 624 oa.userfunc = func; 625 oa.userarg = arg; 626 oa.lastname = tail; 627 oa.type = type; |
628 oa.flags = flags; 629 |
|
539 if (clone_parent != NULL) { 540 /* 541 * You can't clone to a different type. 542 */ 543 if (clone_parent->os->os_phys->os_type != type) { 544 dsl_dir_close(pdd, FTAG); 545 return (EINVAL); 546 } --- 12 unchanged lines hidden (view full) --- 559 int error; 560 561 /* 562 * If it looks like we'll be able to destroy it, and there's 563 * an unplayed replay log sitting around, destroy the log. 564 * It would be nicer to do this in dsl_dataset_destroy_sync(), 565 * but the replay log objset is modified in open context. 566 */ | 630 if (clone_parent != NULL) { 631 /* 632 * You can't clone to a different type. 633 */ 634 if (clone_parent->os->os_phys->os_type != type) { 635 dsl_dir_close(pdd, FTAG); 636 return (EINVAL); 637 } --- 12 unchanged lines hidden (view full) --- 650 int error; 651 652 /* 653 * If it looks like we'll be able to destroy it, and there's 654 * an unplayed replay log sitting around, destroy the log. 655 * It would be nicer to do this in dsl_dataset_destroy_sync(), 656 * but the replay log objset is modified in open context. 657 */ |
567 error = dmu_objset_open(name, DMU_OST_ANY, DS_MODE_EXCLUSIVE, &os); | 658 error = dmu_objset_open(name, DMU_OST_ANY, 659 DS_MODE_OWNER|DS_MODE_READONLY|DS_MODE_INCONSISTENT, &os); |
568 if (error == 0) { | 660 if (error == 0) { |
661 dsl_dataset_t *ds = os->os->os_dsl_dataset; |
|
569 zil_destroy(dmu_objset_zil(os), B_FALSE); | 662 zil_destroy(dmu_objset_zil(os), B_FALSE); |
570 dmu_objset_close(os); | 663 664 error = dsl_dataset_destroy(ds, os); 665 /* 666 * dsl_dataset_destroy() closes the ds. 667 */ 668 kmem_free(os, sizeof (objset_t)); |
571 } 572 | 669 } 670 |
573 return (dsl_dataset_destroy(name)); | 671 return (error); |
574} 575 | 672} 673 |
674/* 675 * This will close the objset. 676 */ |
|
576int | 677int |
577dmu_objset_rollback(const char *name) | 678dmu_objset_rollback(objset_t *os) |
578{ 579 int err; | 679{ 680 int err; |
580 objset_t *os; | 681 dsl_dataset_t *ds; |
581 | 682 |
582 err = dmu_objset_open(name, DMU_OST_ANY, 583 DS_MODE_EXCLUSIVE | DS_MODE_INCONSISTENT, &os); 584 if (err == 0) { 585 err = zil_suspend(dmu_objset_zil(os)); 586 if (err == 0) 587 zil_resume(dmu_objset_zil(os)); 588 if (err == 0) { 589 /* XXX uncache everything? */ 590 err = dsl_dataset_rollback(os->os->os_dsl_dataset); 591 } | 683 ds = os->os->os_dsl_dataset; 684 685 if (!dsl_dataset_tryown(ds, TRUE, os)) { |
592 dmu_objset_close(os); | 686 dmu_objset_close(os); |
687 return (EBUSY); |
|
593 } | 688 } |
689 690 err = dsl_dataset_rollback(ds, os->os->os_phys->os_type); 691 692 /* 693 * NB: we close the objset manually because the rollback 694 * actually implicitly called dmu_objset_evict(), thus freeing 695 * the objset_impl_t. 696 */ 697 dsl_dataset_disown(ds, os); 698 kmem_free(os, sizeof (objset_t)); |
|
594 return (err); 595} 596 597struct snaparg { 598 dsl_sync_task_group_t *dstg; 599 char *snapname; 600 char failed[MAXPATHLEN]; | 699 return (err); 700} 701 702struct snaparg { 703 dsl_sync_task_group_t *dstg; 704 char *snapname; 705 char failed[MAXPATHLEN]; |
706 boolean_t checkperms; 707 list_t objsets; |
|
601}; 602 | 708}; 709 |
710struct osnode { 711 list_node_t node; 712 objset_t *os; 713}; 714 |
|
603static int 604dmu_objset_snapshot_one(char *name, void *arg) 605{ 606 struct snaparg *sn = arg; 607 objset_t *os; | 715static int 716dmu_objset_snapshot_one(char *name, void *arg) 717{ 718 struct snaparg *sn = arg; 719 objset_t *os; |
608 dmu_objset_stats_t stat; | |
609 int err; 610 611 (void) strcpy(sn->failed, name); 612 | 720 int err; 721 722 (void) strcpy(sn->failed, name); 723 |
613 err = dmu_objset_open(name, DMU_OST_ANY, DS_MODE_STANDARD, &os); | 724 /* 725 * Check permissions only when requested. This only applies when 726 * doing a recursive snapshot. The permission checks for the starting 727 * dataset have already been performed in zfs_secpolicy_snapshot() 728 */ 729 if (sn->checkperms == B_TRUE && 730 (err = zfs_secpolicy_snapshot_perms(name, CRED()))) 731 return (err); 732 733 err = dmu_objset_open(name, DMU_OST_ANY, DS_MODE_USER, &os); |
614 if (err != 0) 615 return (err); 616 | 734 if (err != 0) 735 return (err); 736 |
617 /* 618 * If the objset is in an inconsistent state, return busy. 619 */ 620 dmu_objset_fast_stat(os, &stat); 621 if (stat.dds_inconsistent) { | 737 /* If the objset is in an inconsistent state, return busy */ 738 if (os->os->os_dsl_dataset->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) { |
622 dmu_objset_close(os); 623 return (EBUSY); 624 } 625 626 /* 627 * NB: we need to wait for all in-flight changes to get to disk, 628 * so that we snapshot those changes. zil_suspend does this as 629 * a side effect. 630 */ 631 err = zil_suspend(dmu_objset_zil(os)); 632 if (err == 0) { | 739 dmu_objset_close(os); 740 return (EBUSY); 741 } 742 743 /* 744 * NB: we need to wait for all in-flight changes to get to disk, 745 * so that we snapshot those changes. zil_suspend does this as 746 * a side effect. 747 */ 748 err = zil_suspend(dmu_objset_zil(os)); 749 if (err == 0) { |
750 struct osnode *osn; |
|
633 dsl_sync_task_create(sn->dstg, dsl_dataset_snapshot_check, | 751 dsl_sync_task_create(sn->dstg, dsl_dataset_snapshot_check, |
634 dsl_dataset_snapshot_sync, os, sn->snapname, 3); | 752 dsl_dataset_snapshot_sync, os->os->os_dsl_dataset, 753 sn->snapname, 3); 754 osn = kmem_alloc(sizeof (struct osnode), KM_SLEEP); 755 osn->os = os; 756 list_insert_tail(&sn->objsets, osn); |
635 } else { 636 dmu_objset_close(os); 637 } 638 639 return (err); 640} 641 642int 643dmu_objset_snapshot(char *fsname, char *snapname, boolean_t recursive) 644{ 645 dsl_sync_task_t *dst; | 757 } else { 758 dmu_objset_close(os); 759 } 760 761 return (err); 762} 763 764int 765dmu_objset_snapshot(char *fsname, char *snapname, boolean_t recursive) 766{ 767 dsl_sync_task_t *dst; |
768 struct osnode *osn; |
|
646 struct snaparg sn = { 0 }; | 769 struct snaparg sn = { 0 }; |
647 char *cp; | |
648 spa_t *spa; 649 int err; 650 651 (void) strcpy(sn.failed, fsname); 652 | 770 spa_t *spa; 771 int err; 772 773 (void) strcpy(sn.failed, fsname); 774 |
653 cp = strchr(fsname, '/'); 654 if (cp) { 655 *cp = '\0'; 656 err = spa_open(fsname, &spa, FTAG); 657 *cp = '/'; 658 } else { 659 err = spa_open(fsname, &spa, FTAG); 660 } | 775 err = spa_open(fsname, &spa, FTAG); |
661 if (err) 662 return (err); 663 664 sn.dstg = dsl_sync_task_group_create(spa_get_dsl(spa)); 665 sn.snapname = snapname; | 776 if (err) 777 return (err); 778 779 sn.dstg = dsl_sync_task_group_create(spa_get_dsl(spa)); 780 sn.snapname = snapname; |
781 list_create(&sn.objsets, sizeof (struct osnode), 782 offsetof(struct osnode, node)); |
|
666 667 if (recursive) { | 783 784 if (recursive) { |
785 sn.checkperms = B_TRUE; |
|
668 err = dmu_objset_find(fsname, 669 dmu_objset_snapshot_one, &sn, DS_FIND_CHILDREN); 670 } else { | 786 err = dmu_objset_find(fsname, 787 dmu_objset_snapshot_one, &sn, DS_FIND_CHILDREN); 788 } else { |
789 sn.checkperms = B_FALSE; |
|
671 err = dmu_objset_snapshot_one(fsname, &sn); 672 } 673 674 if (err) 675 goto out; 676 677 err = dsl_sync_task_group_wait(sn.dstg); 678 679 for (dst = list_head(&sn.dstg->dstg_tasks); dst; 680 dst = list_next(&sn.dstg->dstg_tasks, dst)) { | 790 err = dmu_objset_snapshot_one(fsname, &sn); 791 } 792 793 if (err) 794 goto out; 795 796 err = dsl_sync_task_group_wait(sn.dstg); 797 798 for (dst = list_head(&sn.dstg->dstg_tasks); dst; 799 dst = list_next(&sn.dstg->dstg_tasks, dst)) { |
681 objset_t *os = dst->dst_arg1; | 800 dsl_dataset_t *ds = dst->dst_arg1; |
682 if (dst->dst_err) | 801 if (dst->dst_err) |
683 dmu_objset_name(os, sn.failed); 684 zil_resume(dmu_objset_zil(os)); 685 dmu_objset_close(os); | 802 dsl_dataset_name(ds, sn.failed); |
686 } | 803 } |
804 |
|
687out: | 805out: |
806 while (osn = list_head(&sn.objsets)) { 807 list_remove(&sn.objsets, osn); 808 zil_resume(dmu_objset_zil(osn->os)); 809 dmu_objset_close(osn->os); 810 kmem_free(osn, sizeof (struct osnode)); 811 } 812 list_destroy(&sn.objsets); 813 |
|
688 if (err) 689 (void) strcpy(fsname, sn.failed); 690 dsl_sync_task_group_destroy(sn.dstg); 691 spa_close(spa, FTAG); 692 return (err); 693} 694 695static void --- 16 unchanged lines hidden (view full) --- 712 dnode_sync(dn, tx); 713 } 714} 715 716/* ARGSUSED */ 717static void 718ready(zio_t *zio, arc_buf_t *abuf, void *arg) 719{ | 814 if (err) 815 (void) strcpy(fsname, sn.failed); 816 dsl_sync_task_group_destroy(sn.dstg); 817 spa_close(spa, FTAG); 818 return (err); 819} 820 821static void --- 16 unchanged lines hidden (view full) --- 838 dnode_sync(dn, tx); 839 } 840} 841 842/* ARGSUSED */ 843static void 844ready(zio_t *zio, arc_buf_t *abuf, void *arg) 845{ |
846 blkptr_t *bp = zio->io_bp; 847 blkptr_t *bp_orig = &zio->io_bp_orig; |
|
720 objset_impl_t *os = arg; | 848 objset_impl_t *os = arg; |
721 blkptr_t *bp = os->os_rootbp; | |
722 dnode_phys_t *dnp = &os->os_phys->os_meta_dnode; | 849 dnode_phys_t *dnp = &os->os_phys->os_meta_dnode; |
723 int i; | |
724 | 850 |
851 ASSERT(bp == os->os_rootbp); 852 ASSERT(BP_GET_TYPE(bp) == DMU_OT_OBJSET); 853 ASSERT(BP_GET_LEVEL(bp) == 0); 854 |
|
725 /* 726 * Update rootbp fill count. 727 */ 728 bp->blk_fill = 1; /* count the meta-dnode */ | 855 /* 856 * Update rootbp fill count. 857 */ 858 bp->blk_fill = 1; /* count the meta-dnode */ |
729 for (i = 0; i < dnp->dn_nblkptr; i++) | 859 for (int i = 0; i < dnp->dn_nblkptr; i++) |
730 bp->blk_fill += dnp->dn_blkptr[i].blk_fill; | 860 bp->blk_fill += dnp->dn_blkptr[i].blk_fill; |
731} | |
732 | 861 |
733/* ARGSUSED */ 734static void 735killer(zio_t *zio, arc_buf_t *abuf, void *arg) 736{ 737 objset_impl_t *os = arg; 738 739 ASSERT3U(zio->io_error, ==, 0); 740 741 BP_SET_TYPE(zio->io_bp, DMU_OT_OBJSET); 742 BP_SET_LEVEL(zio->io_bp, 0); 743 744 if (!DVA_EQUAL(BP_IDENTITY(zio->io_bp), 745 BP_IDENTITY(&zio->io_bp_orig))) { | 862 if (zio->io_flags & ZIO_FLAG_IO_REWRITE) { 863 ASSERT(DVA_EQUAL(BP_IDENTITY(bp), BP_IDENTITY(bp_orig))); 864 } else { |
746 if (zio->io_bp_orig.blk_birth == os->os_synctx->tx_txg) | 865 if (zio->io_bp_orig.blk_birth == os->os_synctx->tx_txg) |
747 dsl_dataset_block_kill(os->os_dsl_dataset, 748 &zio->io_bp_orig, NULL, os->os_synctx); 749 dsl_dataset_block_born(os->os_dsl_dataset, zio->io_bp, 750 os->os_synctx); | 866 (void) dsl_dataset_block_kill(os->os_dsl_dataset, 867 &zio->io_bp_orig, zio, os->os_synctx); 868 dsl_dataset_block_born(os->os_dsl_dataset, bp, os->os_synctx); |
751 } | 869 } |
752 arc_release(os->os_phys_buf, &os->os_phys_buf); | |
753} 754 755/* called from dsl */ 756void 757dmu_objset_sync(objset_impl_t *os, zio_t *pio, dmu_tx_t *tx) 758{ 759 int txgoff; 760 zbookmark_t zb; | 870} 871 872/* called from dsl */ 873void 874dmu_objset_sync(objset_impl_t *os, zio_t *pio, dmu_tx_t *tx) 875{ 876 int txgoff; 877 zbookmark_t zb; |
878 writeprops_t wp = { 0 }; |
|
761 zio_t *zio; 762 list_t *list; 763 dbuf_dirty_record_t *dr; | 879 zio_t *zio; 880 list_t *list; 881 dbuf_dirty_record_t *dr; |
764 int zio_flags; | |
765 766 dprintf_ds(os->os_dsl_dataset, "txg=%llu\n", tx->tx_txg); 767 768 ASSERT(dmu_tx_is_syncing(tx)); 769 /* XXX the write_done callback should really give us the tx... */ 770 os->os_synctx = tx; 771 772 if (os->os_dsl_dataset == NULL) { --- 5 unchanged lines hidden (view full) --- 778 os->os_copies = spa_max_replication(os->os_spa); 779 } 780 781 /* 782 * Create the root block IO 783 */ 784 zb.zb_objset = os->os_dsl_dataset ? os->os_dsl_dataset->ds_object : 0; 785 zb.zb_object = 0; | 882 883 dprintf_ds(os->os_dsl_dataset, "txg=%llu\n", tx->tx_txg); 884 885 ASSERT(dmu_tx_is_syncing(tx)); 886 /* XXX the write_done callback should really give us the tx... */ 887 os->os_synctx = tx; 888 889 if (os->os_dsl_dataset == NULL) { --- 5 unchanged lines hidden (view full) --- 895 os->os_copies = spa_max_replication(os->os_spa); 896 } 897 898 /* 899 * Create the root block IO 900 */ 901 zb.zb_objset = os->os_dsl_dataset ? os->os_dsl_dataset->ds_object : 0; 902 zb.zb_object = 0; |
786 zb.zb_level = -1; | 903 zb.zb_level = -1; /* for block ordering; it's level 0 on disk */ |
787 zb.zb_blkid = 0; | 904 zb.zb_blkid = 0; |
788 zio_flags = ZIO_FLAG_MUSTSUCCEED; 789 if (dmu_ot[DMU_OT_OBJSET].ot_metadata || zb.zb_level != 0) 790 zio_flags |= ZIO_FLAG_METADATA; 791 if (BP_IS_OLDER(os->os_rootbp, tx->tx_txg)) 792 dsl_dataset_block_kill(os->os_dsl_dataset, | 905 906 wp.wp_type = DMU_OT_OBJSET; 907 wp.wp_level = 0; /* on-disk BP level; see above */ 908 wp.wp_copies = os->os_copies; 909 wp.wp_oschecksum = os->os_checksum; 910 wp.wp_oscompress = os->os_compress; 911 912 if (BP_IS_OLDER(os->os_rootbp, tx->tx_txg)) { 913 (void) dsl_dataset_block_kill(os->os_dsl_dataset, |
793 os->os_rootbp, pio, tx); | 914 os->os_rootbp, pio, tx); |
794 zio = arc_write(pio, os->os_spa, os->os_md_checksum, 795 os->os_md_compress, 796 dmu_get_replication_level(os, &zb, DMU_OT_OBJSET), 797 tx->tx_txg, os->os_rootbp, os->os_phys_buf, ready, killer, os, 798 ZIO_PRIORITY_ASYNC_WRITE, zio_flags, &zb); | 915 } |
799 | 916 |
917 arc_release(os->os_phys_buf, &os->os_phys_buf); 918 zio = arc_write(pio, os->os_spa, &wp, DMU_OS_IS_L2CACHEABLE(os), 919 tx->tx_txg, os->os_rootbp, os->os_phys_buf, ready, NULL, os, 920 ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb); 921 |
|
800 /* 801 * Sync meta-dnode - the parent IO for the sync is the root block 802 */ 803 os->os_meta_dnode->dn_zio = zio; 804 dnode_sync(os->os_meta_dnode, tx); 805 806 txgoff = tx->tx_txg & TXG_MASK; 807 --- 6 unchanged lines hidden (view full) --- 814 list_remove(list, dr); 815 if (dr->dr_zio) 816 zio_nowait(dr->dr_zio); 817 } 818 /* 819 * Free intent log blocks up to this tx. 820 */ 821 zil_sync(os->os_zil, tx); | 922 /* 923 * Sync meta-dnode - the parent IO for the sync is the root block 924 */ 925 os->os_meta_dnode->dn_zio = zio; 926 dnode_sync(os->os_meta_dnode, tx); 927 928 txgoff = tx->tx_txg & TXG_MASK; 929 --- 6 unchanged lines hidden (view full) --- 936 list_remove(list, dr); 937 if (dr->dr_zio) 938 zio_nowait(dr->dr_zio); 939 } 940 /* 941 * Free intent log blocks up to this tx. 942 */ 943 zil_sync(os->os_zil, tx); |
944 os->os_phys->os_zil_header = os->os_zil_header; |
|
822 zio_nowait(zio); 823} 824 825void 826dmu_objset_space(objset_t *os, uint64_t *refdbytesp, uint64_t *availbytesp, 827 uint64_t *usedobjsp, uint64_t *availobjsp) 828{ 829 dsl_dataset_space(os->os->os_dsl_dataset, refdbytesp, availbytesp, --- 32 unchanged lines hidden (view full) --- 862{ 863 if (os->os->os_dsl_dataset != NULL) 864 return (dsl_dataset_is_snapshot(os->os->os_dsl_dataset)); 865 else 866 return (B_FALSE); 867} 868 869int | 945 zio_nowait(zio); 946} 947 948void 949dmu_objset_space(objset_t *os, uint64_t *refdbytesp, uint64_t *availbytesp, 950 uint64_t *usedobjsp, uint64_t *availobjsp) 951{ 952 dsl_dataset_space(os->os->os_dsl_dataset, refdbytesp, availbytesp, --- 32 unchanged lines hidden (view full) --- 985{ 986 if (os->os->os_dsl_dataset != NULL) 987 return (dsl_dataset_is_snapshot(os->os->os_dsl_dataset)); 988 else 989 return (B_FALSE); 990} 991 992int |
993dmu_snapshot_realname(objset_t *os, char *name, char *real, int maxlen, 994 boolean_t *conflict) 995{ 996 dsl_dataset_t *ds = os->os->os_dsl_dataset; 997 uint64_t ignored; 998 999 if (ds->ds_phys->ds_snapnames_zapobj == 0) 1000 return (ENOENT); 1001 1002 return (zap_lookup_norm(ds->ds_dir->dd_pool->dp_meta_objset, 1003 ds->ds_phys->ds_snapnames_zapobj, name, 8, 1, &ignored, MT_FIRST, 1004 real, maxlen, conflict)); 1005} 1006 1007int |
|
870dmu_snapshot_list_next(objset_t *os, int namelen, char *name, | 1008dmu_snapshot_list_next(objset_t *os, int namelen, char *name, |
871 uint64_t *idp, uint64_t *offp) | 1009 uint64_t *idp, uint64_t *offp, boolean_t *case_conflict) |
872{ 873 dsl_dataset_t *ds = os->os->os_dsl_dataset; 874 zap_cursor_t cursor; 875 zap_attribute_t attr; 876 877 if (ds->ds_phys->ds_snapnames_zapobj == 0) 878 return (ENOENT); 879 --- 9 unchanged lines hidden (view full) --- 889 if (strlen(attr.za_name) + 1 > namelen) { 890 zap_cursor_fini(&cursor); 891 return (ENAMETOOLONG); 892 } 893 894 (void) strcpy(name, attr.za_name); 895 if (idp) 896 *idp = attr.za_first_integer; | 1010{ 1011 dsl_dataset_t *ds = os->os->os_dsl_dataset; 1012 zap_cursor_t cursor; 1013 zap_attribute_t attr; 1014 1015 if (ds->ds_phys->ds_snapnames_zapobj == 0) 1016 return (ENOENT); 1017 --- 9 unchanged lines hidden (view full) --- 1027 if (strlen(attr.za_name) + 1 > namelen) { 1028 zap_cursor_fini(&cursor); 1029 return (ENAMETOOLONG); 1030 } 1031 1032 (void) strcpy(name, attr.za_name); 1033 if (idp) 1034 *idp = attr.za_first_integer; |
1035 if (case_conflict) 1036 *case_conflict = attr.za_normalization_conflict; |
|
897 zap_cursor_advance(&cursor); 898 *offp = zap_cursor_serialize(&cursor); 899 zap_cursor_fini(&cursor); 900 901 return (0); 902} 903 904int --- 28 unchanged lines hidden (view full) --- 933 *idp = attr.za_first_integer; 934 zap_cursor_advance(&cursor); 935 *offp = zap_cursor_serialize(&cursor); 936 zap_cursor_fini(&cursor); 937 938 return (0); 939} 940 | 1037 zap_cursor_advance(&cursor); 1038 *offp = zap_cursor_serialize(&cursor); 1039 zap_cursor_fini(&cursor); 1040 1041 return (0); 1042} 1043 1044int --- 28 unchanged lines hidden (view full) --- 1073 *idp = attr.za_first_integer; 1074 zap_cursor_advance(&cursor); 1075 *offp = zap_cursor_serialize(&cursor); 1076 zap_cursor_fini(&cursor); 1077 1078 return (0); 1079} 1080 |
1081struct findarg { 1082 int (*func)(char *, void *); 1083 void *arg; 1084}; 1085 1086/* ARGSUSED */ 1087static int 1088findfunc(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg) 1089{ 1090 struct findarg *fa = arg; 1091 return (fa->func((char *)dsname, fa->arg)); 1092} 1093 |
|
941/* 942 * Find all objsets under name, and for each, call 'func(child_name, arg)'. | 1094/* 1095 * Find all objsets under name, and for each, call 'func(child_name, arg)'. |
1096 * Perhaps change all callers to use dmu_objset_find_spa()? |
|
943 */ 944int 945dmu_objset_find(char *name, int func(char *, void *), void *arg, int flags) 946{ | 1097 */ 1098int 1099dmu_objset_find(char *name, int func(char *, void *), void *arg, int flags) 1100{ |
1101 struct findarg fa; 1102 fa.func = func; 1103 fa.arg = arg; 1104 return (dmu_objset_find_spa(NULL, name, findfunc, &fa, flags)); 1105} 1106 1107/* 1108 * Find all objsets under name, call func on each 1109 */ 1110int 1111dmu_objset_find_spa(spa_t *spa, const char *name, 1112 int func(spa_t *, uint64_t, const char *, void *), void *arg, int flags) 1113{ |
|
947 dsl_dir_t *dd; | 1114 dsl_dir_t *dd; |
948 objset_t *os; 949 uint64_t snapobj; | 1115 dsl_pool_t *dp; 1116 dsl_dataset_t *ds; |
950 zap_cursor_t zc; 951 zap_attribute_t *attr; 952 char *child; | 1117 zap_cursor_t zc; 1118 zap_attribute_t *attr; 1119 char *child; |
953 int do_self, err; | 1120 uint64_t thisobj; 1121 int err; |
954 | 1122 |
955 err = dsl_dir_open(name, FTAG, &dd, NULL); | 1123 if (name == NULL) 1124 name = spa_name(spa); 1125 err = dsl_dir_open_spa(spa, name, FTAG, &dd, NULL); |
956 if (err) 957 return (err); 958 | 1126 if (err) 1127 return (err); 1128 |
959 /* NB: the $MOS dir doesn't have a head dataset */ 960 do_self = (dd->dd_phys->dd_head_dataset_obj != 0); | 1129 /* Don't visit hidden ($MOS & $ORIGIN) objsets. */ 1130 if (dd->dd_myname[0] == '$') { 1131 dsl_dir_close(dd, FTAG); 1132 return (0); 1133 } 1134 1135 thisobj = dd->dd_phys->dd_head_dataset_obj; |
961 attr = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP); | 1136 attr = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP); |
1137 dp = dd->dd_pool; |
|
962 963 /* 964 * Iterate over all children. 965 */ 966 if (flags & DS_FIND_CHILDREN) { | 1138 1139 /* 1140 * Iterate over all children. 1141 */ 1142 if (flags & DS_FIND_CHILDREN) { |
967 for (zap_cursor_init(&zc, dd->dd_pool->dp_meta_objset, | 1143 for (zap_cursor_init(&zc, dp->dp_meta_objset, |
968 dd->dd_phys->dd_child_dir_zapobj); 969 zap_cursor_retrieve(&zc, attr) == 0; 970 (void) zap_cursor_advance(&zc)) { 971 ASSERT(attr->za_integer_length == sizeof (uint64_t)); 972 ASSERT(attr->za_num_integers == 1); 973 | 1144 dd->dd_phys->dd_child_dir_zapobj); 1145 zap_cursor_retrieve(&zc, attr) == 0; 1146 (void) zap_cursor_advance(&zc)) { 1147 ASSERT(attr->za_integer_length == sizeof (uint64_t)); 1148 ASSERT(attr->za_num_integers == 1); 1149 |
974 /* 975 * No separating '/' because parent's name ends in /. 976 */ | |
977 child = kmem_alloc(MAXPATHLEN, KM_SLEEP); | 1150 child = kmem_alloc(MAXPATHLEN, KM_SLEEP); |
978 /* XXX could probably just use name here */ 979 dsl_dir_name(dd, child); | 1151 (void) strcpy(child, name); |
980 (void) strcat(child, "/"); 981 (void) strcat(child, attr->za_name); | 1152 (void) strcat(child, "/"); 1153 (void) strcat(child, attr->za_name); |
982 err = dmu_objset_find(child, func, arg, flags); | 1154 err = dmu_objset_find_spa(spa, child, func, arg, flags); |
983 kmem_free(child, MAXPATHLEN); 984 if (err) 985 break; 986 } 987 zap_cursor_fini(&zc); 988 989 if (err) { 990 dsl_dir_close(dd, FTAG); 991 kmem_free(attr, sizeof (zap_attribute_t)); 992 return (err); 993 } 994 } 995 996 /* 997 * Iterate over all snapshots. 998 */ | 1155 kmem_free(child, MAXPATHLEN); 1156 if (err) 1157 break; 1158 } 1159 zap_cursor_fini(&zc); 1160 1161 if (err) { 1162 dsl_dir_close(dd, FTAG); 1163 kmem_free(attr, sizeof (zap_attribute_t)); 1164 return (err); 1165 } 1166 } 1167 1168 /* 1169 * Iterate over all snapshots. 1170 */ |
999 if ((flags & DS_FIND_SNAPSHOTS) && 1000 dmu_objset_open(name, DMU_OST_ANY, 1001 DS_MODE_STANDARD | DS_MODE_READONLY, &os) == 0) { | 1171 if (flags & DS_FIND_SNAPSHOTS) { 1172 if (!dsl_pool_sync_context(dp)) 1173 rw_enter(&dp->dp_config_rwlock, RW_READER); 1174 err = dsl_dataset_hold_obj(dp, thisobj, FTAG, &ds); 1175 if (!dsl_pool_sync_context(dp)) 1176 rw_exit(&dp->dp_config_rwlock); |
1002 | 1177 |
1003 snapobj = os->os->os_dsl_dataset->ds_phys->ds_snapnames_zapobj; 1004 dmu_objset_close(os); | 1178 if (err == 0) { 1179 uint64_t snapobj = ds->ds_phys->ds_snapnames_zapobj; 1180 dsl_dataset_rele(ds, FTAG); |
1005 | 1181 |
1006 for (zap_cursor_init(&zc, dd->dd_pool->dp_meta_objset, snapobj); 1007 zap_cursor_retrieve(&zc, attr) == 0; 1008 (void) zap_cursor_advance(&zc)) { 1009 ASSERT(attr->za_integer_length == sizeof (uint64_t)); 1010 ASSERT(attr->za_num_integers == 1); | 1182 for (zap_cursor_init(&zc, dp->dp_meta_objset, snapobj); 1183 zap_cursor_retrieve(&zc, attr) == 0; 1184 (void) zap_cursor_advance(&zc)) { 1185 ASSERT(attr->za_integer_length == 1186 sizeof (uint64_t)); 1187 ASSERT(attr->za_num_integers == 1); |
1011 | 1188 |
1012 child = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1013 /* XXX could probably just use name here */ 1014 dsl_dir_name(dd, child); 1015 (void) strcat(child, "@"); 1016 (void) strcat(child, attr->za_name); 1017 err = func(child, arg); 1018 kmem_free(child, MAXPATHLEN); 1019 if (err) 1020 break; | 1189 child = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1190 (void) strcpy(child, name); 1191 (void) strcat(child, "@"); 1192 (void) strcat(child, attr->za_name); 1193 err = func(spa, attr->za_first_integer, 1194 child, arg); 1195 kmem_free(child, MAXPATHLEN); 1196 if (err) 1197 break; 1198 } 1199 zap_cursor_fini(&zc); |
1021 } | 1200 } |
1022 zap_cursor_fini(&zc); | |
1023 } 1024 1025 dsl_dir_close(dd, FTAG); 1026 kmem_free(attr, sizeof (zap_attribute_t)); 1027 1028 if (err) 1029 return (err); 1030 1031 /* 1032 * Apply to self if appropriate. 1033 */ | 1201 } 1202 1203 dsl_dir_close(dd, FTAG); 1204 kmem_free(attr, sizeof (zap_attribute_t)); 1205 1206 if (err) 1207 return (err); 1208 1209 /* 1210 * Apply to self if appropriate. 1211 */ |
1034 if (do_self) 1035 err = func(name, arg); | 1212 err = func(spa, thisobj, name, arg); |
1036 return (err); 1037} | 1213 return (err); 1214} |
1215 1216void 1217dmu_objset_set_user(objset_t *os, void *user_ptr) 1218{ 1219 ASSERT(MUTEX_HELD(&os->os->os_user_ptr_lock)); 1220 os->os->os_user_ptr = user_ptr; 1221} 1222 1223void * 1224dmu_objset_get_user(objset_t *os) 1225{ 1226 ASSERT(MUTEX_HELD(&os->os->os_user_ptr_lock)); 1227 return (os->os->os_user_ptr); 1228} |
|