31 #include <sys/dsl_dataset.h> /* for dsl_dataset_block_freeable() */ |
31 #include <sys/dsl_dataset.h> /* for dsl_dataset_block_freeable() */ |
32 #include <sys/dsl_dir.h> /* for dsl_dir_tempreserve_*() */ |
32 #include <sys/dsl_dir.h> /* for dsl_dir_tempreserve_*() */ |
33 #include <sys/dsl_pool.h> |
33 #include <sys/dsl_pool.h> |
34 #include <sys/zap_impl.h> /* for fzap_default_block_shift */ |
34 #include <sys/zap_impl.h> /* for fzap_default_block_shift */ |
35 #include <sys/spa.h> |
35 #include <sys/spa.h> |
|
36 #include <sys/sa.h> |
|
37 #include <sys/sa_impl.h> |
36 #include <sys/zfs_context.h> |
38 #include <sys/zfs_context.h> |
|
39 #include <sys/varargs.h> |
37 |
40 |
38 typedef void (*dmu_tx_hold_func_t)(dmu_tx_t *tx, struct dnode *dn, |
41 typedef void (*dmu_tx_hold_func_t)(dmu_tx_t *tx, struct dnode *dn, |
39 uint64_t arg1, uint64_t arg2); |
42 uint64_t arg1, uint64_t arg2); |
40 |
43 |
41 |
44 |
1202 list_remove(cb_list, dcb); |
1210 list_remove(cb_list, dcb); |
1203 dcb->dcb_func(dcb->dcb_data, error); |
1211 dcb->dcb_func(dcb->dcb_data, error); |
1204 kmem_free(dcb, sizeof (dmu_tx_callback_t)); |
1212 kmem_free(dcb, sizeof (dmu_tx_callback_t)); |
1205 } |
1213 } |
1206 } |
1214 } |
|
1215 |
|
1216 /* |
|
1217 * Interface to hold a bunch of attributes. |
|
1218 * used for creating new files. |
|
1219 * attrsize is the total size of all attributes |
|
1220 * to be added during object creation |
|
1221 * |
|
1222 * For updating/adding a single attribute dmu_tx_hold_sa() should be used. |
|
1223 */ |
|
1224 |
|
1225 /* |
|
1226 * hold necessary attribute name for attribute registration. |
|
1227 * should be a very rare case where this is needed. If it does |
|
1228 * happen it would only happen on the first write to the file system. |
|
1229 */ |
|
1230 static void |
|
1231 dmu_tx_sa_registration_hold(sa_os_t *sa, dmu_tx_t *tx) |
|
1232 { |
|
1233 int i; |
|
1234 |
|
1235 if (!sa->sa_need_attr_registration) |
|
1236 return; |
|
1237 |
|
1238 for (i = 0; i != sa->sa_num_attrs; i++) { |
|
1239 if (!sa->sa_attr_table[i].sa_registered) { |
|
1240 if (sa->sa_reg_attr_obj) |
|
1241 dmu_tx_hold_zap(tx, sa->sa_reg_attr_obj, |
|
1242 B_TRUE, sa->sa_attr_table[i].sa_name); |
|
1243 else |
|
1244 dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, |
|
1245 B_TRUE, sa->sa_attr_table[i].sa_name); |
|
1246 } |
|
1247 } |
|
1248 } |
|
1249 |
|
1250 |
|
1251 void |
|
1252 dmu_tx_hold_spill(dmu_tx_t *tx, uint64_t object) |
|
1253 { |
|
1254 dnode_t *dn; |
|
1255 dmu_tx_hold_t *txh; |
|
1256 blkptr_t *bp; |
|
1257 |
|
1258 txh = dmu_tx_hold_object_impl(tx, tx->tx_objset, object, |
|
1259 THT_SPILL, 0, 0); |
|
1260 |
|
1261 dn = txh->txh_dnode; |
|
1262 |
|
1263 if (dn == NULL) |
|
1264 return; |
|
1265 |
|
1266 /* If blkptr doesn't exist then add space to towrite */ |
|
1267 bp = &dn->dn_phys->dn_spill; |
|
1268 if (BP_IS_HOLE(bp)) { |
|
1269 txh->txh_space_towrite += SPA_MAXBLOCKSIZE; |
|
1270 txh->txh_space_tounref = 0; |
|
1271 } else { |
|
1272 if (dsl_dataset_block_freeable(dn->dn_objset->os_dsl_dataset, |
|
1273 bp->blk_birth)) |
|
1274 txh->txh_space_tooverwrite += SPA_MAXBLOCKSIZE; |
|
1275 else |
|
1276 txh->txh_space_towrite += SPA_MAXBLOCKSIZE; |
|
1277 if (bp->blk_birth) |
|
1278 txh->txh_space_tounref += SPA_MAXBLOCKSIZE; |
|
1279 } |
|
1280 } |
|
1281 |
|
1282 void |
|
1283 dmu_tx_hold_sa_create(dmu_tx_t *tx, int attrsize) |
|
1284 { |
|
1285 sa_os_t *sa = tx->tx_objset->os_sa; |
|
1286 |
|
1287 dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); |
|
1288 |
|
1289 if (tx->tx_objset->os_sa->sa_master_obj == 0) |
|
1290 return; |
|
1291 |
|
1292 if (tx->tx_objset->os_sa->sa_layout_attr_obj) |
|
1293 dmu_tx_hold_zap(tx, sa->sa_layout_attr_obj, B_TRUE, NULL); |
|
1294 else { |
|
1295 dmu_tx_hold_zap(tx, sa->sa_master_obj, B_TRUE, SA_LAYOUTS); |
|
1296 dmu_tx_hold_zap(tx, sa->sa_master_obj, B_TRUE, SA_REGISTRY); |
|
1297 dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, B_TRUE, NULL); |
|
1298 dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, B_TRUE, NULL); |
|
1299 } |
|
1300 |
|
1301 dmu_tx_sa_registration_hold(sa, tx); |
|
1302 |
|
1303 if (attrsize <= DN_MAX_BONUSLEN && !sa->sa_force_spill) |
|
1304 return; |
|
1305 |
|
1306 (void) dmu_tx_hold_object_impl(tx, tx->tx_objset, DMU_NEW_OBJECT, |
|
1307 THT_SPILL, 0, 0); |
|
1308 } |
|
1309 |
|
1310 /* |
|
1311 * Hold SA attribute |
|
1312 * |
|
1313 * dmu_tx_hold_sa(dmu_tx_t *tx, sa_handle_t *, attribute, add, size) |
|
1314 * |
|
1315 * variable_size is the total size of all variable sized attributes |
|
1316 * passed to this function. It is not the total size of all |
|
1317 * variable size attributes that *may* exist on this object. |
|
1318 */ |
|
1319 void |
|
1320 dmu_tx_hold_sa(dmu_tx_t *tx, sa_handle_t *hdl, boolean_t may_grow) |
|
1321 { |
|
1322 uint64_t object; |
|
1323 sa_os_t *sa = tx->tx_objset->os_sa; |
|
1324 |
|
1325 ASSERT(hdl != NULL); |
|
1326 |
|
1327 object = sa_handle_object(hdl); |
|
1328 |
|
1329 dmu_tx_hold_bonus(tx, object); |
|
1330 |
|
1331 if (tx->tx_objset->os_sa->sa_master_obj == 0) |
|
1332 return; |
|
1333 |
|
1334 if (tx->tx_objset->os_sa->sa_reg_attr_obj == 0 || |
|
1335 tx->tx_objset->os_sa->sa_layout_attr_obj == 0) { |
|
1336 dmu_tx_hold_zap(tx, sa->sa_master_obj, B_TRUE, SA_LAYOUTS); |
|
1337 dmu_tx_hold_zap(tx, sa->sa_master_obj, B_TRUE, SA_REGISTRY); |
|
1338 dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, B_TRUE, NULL); |
|
1339 dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, B_TRUE, NULL); |
|
1340 } |
|
1341 |
|
1342 dmu_tx_sa_registration_hold(sa, tx); |
|
1343 |
|
1344 if (may_grow && tx->tx_objset->os_sa->sa_layout_attr_obj) |
|
1345 dmu_tx_hold_zap(tx, sa->sa_layout_attr_obj, B_TRUE, NULL); |
|
1346 |
|
1347 if (sa->sa_force_spill || may_grow || hdl->sa_spill || |
|
1348 ((dmu_buf_impl_t *)hdl->sa_bonus)->db_dnode->dn_have_spill) { |
|
1349 ASSERT(tx->tx_txg == 0); |
|
1350 dmu_tx_hold_spill(tx, object); |
|
1351 } |
|
1352 } |