* When the DNODE_MUST_BE_FREE flag is set, the "slots" parameter is used * to ensure the hole at the specified object offset is large enough to * hold the dnode being created. The slots parameter is also used to ensure * a dnode does not span multiple dnode blocks. In both of these cases, if * a failure occurs, ENOSPC is returned. Keep in mind, these failure cases * are only possible when usi
| 1276 | * succeeds even for free dnodes. |
| 1277 | */ |
| 1278 | int |
| 1279 | dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots, |
| 1280 | void *tag, dnode_t **dnp) |
| 1281 | { |
| 1282 | int epb, idx, err; |
| 1283 | int drop_struct_lock = FALSE; |
| 1284 | int type; |
| 1285 | uint64_t blk; |
| 1286 | dnode_t *mdn, *dn; |
| 1287 | dmu_buf_impl_t *db; |
| 1288 | dnode_children_t *dnc; |
| 1289 | dnode_phys_t *dn_block; |
| 1290 | dnode_handle_t *dnh; |
| 1291 | |
| 1292 | ASSERT(!(flag & DNODE_MUST_BE_ALLOCATED) || (slots == 0)); |
| 1293 | ASSERT(!(flag & DNODE_MUST_BE_FREE) || (slots > 0)); |
| 1294 | IMPLY(flag & DNODE_DRY_RUN, (tag == NULL) && (dnp == NULL)); |
| 1295 | |
| 1296 | /* |
| 1297 | * If you are holding the spa config lock as writer, you shouldn't |
| 1298 | * be asking the DMU to do *anything* unless it's the root pool |
| 1299 | * which may require us to read from the root filesystem while |
| 1300 | * holding some (not all) of the locks as writer. |
| 1301 | */ |
| 1302 | ASSERT(spa_config_held(os->os_spa, SCL_ALL, RW_WRITER) == 0 || |
| 1303 | (spa_is_root(os->os_spa) && |
| 1304 | spa_config_held(os->os_spa, SCL_STATE, RW_WRITER))); |
| 1305 | |
| 1306 | ASSERT((flag & DNODE_MUST_BE_ALLOCATED) || (flag & DNODE_MUST_BE_FREE)); |
| 1307 | |
| 1308 | if (object == DMU_USERUSED_OBJECT || object == DMU_GROUPUSED_OBJECT || |
| 1309 | object == DMU_PROJECTUSED_OBJECT) { |
| 1310 | if (object == DMU_USERUSED_OBJECT) |
| 1311 | dn = DMU_USERUSED_DNODE(os); |
| 1312 | else if (object == DMU_GROUPUSED_OBJECT) |
| 1313 | dn = DMU_GROUPUSED_DNODE(os); |
| 1314 | else |
| 1315 | dn = DMU_PROJECTUSED_DNODE(os); |
| 1316 | if (dn == NULL) |
| 1317 | return (SET_ERROR(ENOENT)); |
| 1318 | type = dn->dn_type; |
| 1319 | if ((flag & DNODE_MUST_BE_ALLOCATED) && type == DMU_OT_NONE) |
| 1320 | return (SET_ERROR(ENOENT)); |
| 1321 | if ((flag & DNODE_MUST_BE_FREE) && type != DMU_OT_NONE) |
| 1322 | return (SET_ERROR(EEXIST)); |
| 1323 | DNODE_VERIFY(dn); |
| 1324 | /* Don't actually hold if dry run, just return 0 */ |
| 1325 | if (!(flag & DNODE_DRY_RUN)) { |
| 1326 | (void) zfs_refcount_add(&dn->dn_holds, tag); |
| 1327 | *dnp = dn; |
| 1328 | } |
| 1329 | return (0); |
| 1330 | } |
| 1331 | |
| 1332 | if (object == 0 || object >= DN_MAX_OBJECT) |
| 1333 | return (SET_ERROR(EINVAL)); |
| 1334 | |
| 1335 | mdn = DMU_META_DNODE(os); |
no test coverage detected