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, &sector, &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, &sectornr, &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;
}
Esempio n. 3
0
/* 
 * 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);
}