Example #1
0
int
nandfs_bmap_update_dat(struct nandfs_node *node, nandfs_daddr_t oldblk,
    struct buf *bp)
{
	struct nandfs_device *fsdev;
	nandfs_daddr_t vblk = 0;
	int error;

	if (node->nn_ino == NANDFS_DAT_INO)
		return (0);

	if (nandfs_buf_check(bp, NANDFS_VBLK_ASSIGNED)) {
		nandfs_buf_clear(bp, NANDFS_VBLK_ASSIGNED);
		return (0);
	}

	fsdev = node->nn_nandfsdev;

	/* First alloc new virtual block.... */
	error = nandfs_vblock_alloc(fsdev, &vblk);
	if (error)
		return (error);

	error = nandfs_bmap_update_block(node, bp, vblk);
	if (error)
		return (error);

	/* Then we can end up with old one */
	nandfs_vblock_end(fsdev, oldblk);

	DPRINTF(BMAP,
	    ("%s: ino %#jx block %#jx: update vblk %#jx to %#jx\n",
	    __func__, (uintmax_t)node->nn_ino, (uintmax_t)bp->b_lblkno,
	    (uintmax_t)oldblk, (uintmax_t)vblk));
	return (error);
}
Example #2
0
int
bmap_truncate_mapping(struct nandfs_node *node, nandfs_lbn_t lastblk,
    nandfs_lbn_t todo)
{
	struct nandfs_inode *ip;
	struct nandfs_indir a[NIADDR + 1], f[NIADDR], *ap;
	nandfs_daddr_t indir_lbn[NIADDR];
	nandfs_daddr_t *copy;
	int error, level;
	nandfs_lbn_t left, tosub;
	struct nandfs_device *fsdev;
	int cleaned, i;
	int num, *nump;

	DPRINTF(BMAP, ("%s: node %p lastblk %jx truncating by %jx\n", __func__,
	    node, lastblk, todo));

	ip = &node->nn_inode;
	fsdev = node->nn_nandfsdev;

	ap = a;
	nump = #

	error = bmap_getlbns(node, lastblk, ap, nump);
	if (error)
		return (error);

	indir_lbn[SINGLE] = -NDADDR;
	indir_lbn[DOUBLE] = indir_lbn[SINGLE] - MNINDIR(fsdev) - 1;
	indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - MNINDIR(fsdev)
	    * MNINDIR(fsdev) - 1;

	for (i = 0; i < NIADDR; i++) {
		f[i].in_off = MNINDIR(fsdev) - 1;
		f[i].in_lbn = 0xdeadbeef;
	}

	left = todo;

#ifdef DEBUG
	a[num].in_off = -1;
#endif

	ap++;
	num -= 2;

	if (num < 0)
		goto direct;

	copy = malloc(MNINDIR(fsdev) * sizeof(nandfs_daddr_t) * (num + 1),
	    M_NANDFSTEMP, M_WAITOK);

	for (level = num; level >= SINGLE && left > 0; level--) {
		cleaned = 0;

		if (ip->i_ib[level] == 0) {
			tosub = blocks_inside(fsdev, level, ap);
			if (tosub > left)
				left = 0;
			else
				left -= tosub;
		} else {
			if (ap == f)
				ap->in_lbn = indir_lbn[level];
			error = bmap_truncate_indirect(node, level, &left,
			    &cleaned, ap, f, copy);
			if (error) {
				nandfs_error("%s: error %d when truncate "
				    "at level %d\n", __func__, error, level);
				return (error);
			}
		}

		if (cleaned) {
			nandfs_vblock_end(fsdev, ip->i_ib[level]);
			ip->i_ib[level] = 0;
		}

		ap = f;
	}

	free(copy, M_NANDFSTEMP);

direct:
	if (num < 0)
		i = lastblk;
	else
		i = NDADDR - 1;

	for (; i >= 0 && left > 0; i--) {
		if (ip->i_db[i] != 0) {
			error = nandfs_bdestroy(node, ip->i_db[i]);
			if (error) {
				nandfs_error("%s: cannot destroy "
				    "block %jx, error %d\n", __func__,
				    (uintmax_t)ip->i_db[i], error);
				return (error);
			}
			ip->i_db[i] = 0;
		}

		left--;
	}

	KASSERT(left == 0,
	    ("truncated wrong number of blocks (%jd should be 0)", left));

	return (error);
}
Example #3
0
static int
bmap_truncate_indirect(struct nandfs_node *node, int level, nandfs_lbn_t *left,
    int *cleaned, struct nandfs_indir *ap, struct nandfs_indir *fp,
    nandfs_daddr_t *copy)
{
	struct buf *bp;
	nandfs_lbn_t i, lbn, nlbn, factor, tosub;
	struct nandfs_device *fsdev;
	int error, lcleaned, modified;

	DPRINTF(BMAP, ("%s: node %p level %d left %jx\n", __func__,
	    node, level, *left));

	fsdev = node->nn_nandfsdev;

	MPASS(ap->in_off >= 0 && ap->in_off < MNINDIR(fsdev));

	factor = lbn_offset(fsdev, level);
	lbn = ap->in_lbn;

	error = nandfs_bread_meta(node, lbn, NOCRED, 0, &bp);
	if (error) {
		brelse(bp);
		return (error);
	}

	bcopy(bp->b_data, copy, fsdev->nd_blocksize);
	bqrelse(bp);

	modified = 0;

	i = ap->in_off;

	if (ap != fp)
		ap++;
	for (nlbn = lbn + 1 - i * factor; i >= 0 && *left > 0; i--,
	    nlbn += factor) {
		lcleaned = 0;

		DPRINTF(BMAP,
		    ("%s: node %p i=%jx nlbn=%jx left=%jx ap=%p vblk %jx\n",
		    __func__, node, i, nlbn, *left, ap, copy[i]));

		if (copy[i] == 0) {
			tosub = blocks_inside(fsdev, level - 1, ap);
			if (tosub > *left)
				tosub = 0;

			*left -= tosub;
		} else {
			if (level > SINGLE) {
				if (ap == fp)
					ap->in_lbn = nlbn;

				error = bmap_truncate_indirect(node, level - 1,
				    left, &lcleaned, ap, fp,
				    copy + MNINDIR(fsdev));
				if (error)
					return (error);
			} else {
				error = nandfs_bdestroy(node, copy[i]);
				if (error)
					return (error);
				lcleaned = 1;
				*left -= 1;
			}
		}

		if (lcleaned) {
			if (level > SINGLE) {
				error = nandfs_vblock_end(fsdev, copy[i]);
				if (error)
					return (error);
			}
			copy[i] = 0;
			modified++;
		}

		ap = fp;
	}

	if (i == -1)
		*cleaned = 1;

	error = nandfs_bread_meta(node, lbn, NOCRED, 0, &bp);
	if (error) {
		brelse(bp);
		return (error);
	}
	if (modified)
		bcopy(copy, bp->b_data, fsdev->nd_blocksize);

	error = nandfs_dirty_buf_meta(bp, 0);
	if (error)
		return (error);

	return (error);
}