static int udf_read_logvol_dscr_seq(struct udf_strat_args *args) { union dscrptr **dscrptr = &args->dscr; union dscrptr *tmpdscr; struct udf_mount *ump = args->ump; struct long_ad *icb = args->icb; struct strat_private *priv = PRIV(ump); uint32_t lb_size; uint32_t sector, dummy; int error; lb_size = udf_rw32(ump->logical_vol->lb_size); error = udf_translate_vtop(ump, icb, §or, &dummy); if (error) return error; /* try to read in fe/efe */ error = udf_read_phys_dscr(ump, sector, M_UDFTEMP, &tmpdscr); if (error) return error; *dscrptr = pool_get(&priv->desc_pool, PR_WAITOK); memcpy(*dscrptr, tmpdscr, lb_size); free(tmpdscr, M_UDFTEMP); return 0; }
static int udf_write_logvol_dscr_seq(struct udf_strat_args *args) { union dscrptr *dscr = args->dscr; struct udf_mount *ump = args->ump; struct udf_node *udf_node = args->udf_node; struct long_ad *icb = args->icb; int waitfor = args->waitfor; uint32_t logsectornr, sectornr, dummy; int error, vpart; /* * we have to decide if we write it out sequential or at its fixed * position by examining the partition its (to be) written on. */ vpart = udf_rw16(udf_node->loc.loc.part_num); logsectornr = udf_rw32(icb->loc.lb_num); sectornr = 0; if (ump->vtop_tp[vpart] != UDF_VTOP_TYPE_VIRT) { error = udf_translate_vtop(ump, icb, §ornr, &dummy); if (error) goto out; } /* add reference to the vnode to prevent recycling */ vhold(udf_node->vnode); if (waitfor) { DPRINTF(WRITE, ("udf_write_logvol_dscr: sync write\n")); error = udf_write_phys_dscr_sync(ump, udf_node, UDF_C_NODE, dscr, sectornr, logsectornr); } else { DPRINTF(WRITE, ("udf_write_logvol_dscr: no wait, async write\n")); error = udf_write_phys_dscr_async(ump, udf_node, UDF_C_NODE, dscr, sectornr, logsectornr, udf_wr_nodedscr_callback); /* will be UNLOCKED in call back */ return error; } holdrele(udf_node->vnode); out: udf_node->outstanding_nodedscr--; if (udf_node->outstanding_nodedscr == 0) { UDF_UNLOCK_NODE(udf_node, 0); wakeup(&udf_node->outstanding_nodedscr); } return error; }
/* * This is a simplified version of the udf_translate_file_extent function. */ int udf_bmap_translate(struct udf_node *udf_node, uint32_t block, int *exttype, uint64_t *lsector, uint32_t *maxblks) { struct udf_mount *ump; struct icb_tag *icbtag; struct long_ad s_ad, t_ad; uint64_t foffset, new_foffset; int addr_type, eof, error, flags, icbflags, slot; uint32_t ext_offset, ext_remain, lb_num, lb_size, len, transsec32; uint32_t translen; uint16_t vpart_num; if (udf_node == NULL) return (ENOENT); KASSERT(num_lb > 0,("num_lb > 0")); UDF_LOCK_NODE(udf_node, 0); /* initialise derivative vars */ ump = udf_node->ump; lb_size = le32toh(ump->logical_vol->lb_size); if (udf_node->fe != NULL) icbtag = &udf_node->fe->icbtag; else icbtag = &udf_node->efe->icbtag; icbflags = le16toh(icbtag->flags); addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; /* do the work */ if (addr_type == UDF_ICB_INTERN_ALLOC) { *exttype = UDF_TRAN_INTERN; *maxblks = 1; UDF_UNLOCK_NODE(udf_node, 0); return (0); } /* find first overlapping extent */ foffset = 0; slot = 0; for (;;) { udf_get_adslot(udf_node, slot, &s_ad, &eof); if (eof) { UDF_UNLOCK_NODE(udf_node, 0); return (EINVAL); } len = le32toh(s_ad.len); flags = UDF_EXT_FLAGS(len); len = UDF_EXT_LEN(len); if (flags == UDF_EXT_REDIRECT) { slot++; continue; } new_foffset = foffset + len; if (new_foffset > block * lb_size) break; /* found */ foffset = new_foffset; slot++; } /* found overlapping slot */ lb_num = le32toh(s_ad.loc.lb_num); vpart_num = le16toh(s_ad.loc.part_num); ext_offset = block * lb_size - foffset; lb_num += (ext_offset + lb_size - 1) / lb_size; ext_remain = (len - ext_offset + lb_size - 1) / lb_size; /* * note that the while(){} is nessisary for the extent that * the udf_translate_vtop() returns doens't have to span the * whole extent. */ switch (flags) { case UDF_EXT_FREE: case UDF_EXT_ALLOCATED_BUT_NOT_USED: *exttype = UDF_TRAN_ZERO; *maxblks = ext_remain; break; case UDF_EXT_ALLOCATED: *exttype = UDF_TRAN_EXTERNAL; t_ad.loc.lb_num = htole32(lb_num); t_ad.loc.part_num = htole16(vpart_num); error = udf_translate_vtop(ump, &t_ad, &transsec32, &translen); if (error != 0) { UDF_UNLOCK_NODE(udf_node, 0); return (error); } *lsector = transsec32; *maxblks = MIN(ext_remain, translen); break; default: UDF_UNLOCK_NODE(udf_node, 0); return (EINVAL); } UDF_UNLOCK_NODE(udf_node, 0); return (0); }