Exemplo n.º 1
0
static int
nandfs_process_bdesc(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
    uint64_t nmembs)
{
	struct nandfs_node *dat_node;
	struct buf *bp;
	uint64_t i;
	int error;

	dat_node = nffsdev->nd_dat_node;

	VOP_LOCK(NTOV(dat_node), LK_EXCLUSIVE);

	for (i = 0; i < nmembs; i++) {
		if (!bd[i].bd_alive)
			continue;
		DPRINTF(CLEAN, ("%s: idx %jx offset %jx\n",
		    __func__, i, bd[i].bd_offset));
		if (bd[i].bd_level) {
			error = nandfs_bread_meta(dat_node, bd[i].bd_offset,
			    NULL, 0, &bp);
			if (error) {
				nandfs_error("%s: cannot read dat node "
				    "level:%d\n", __func__, bd[i].bd_level);
				brelse(bp);
				VOP_UNLOCK(NTOV(dat_node), 0);
				return (error);
			}
			nandfs_dirty_buf_meta(bp, 1);
			nandfs_bmap_dirty_blocks(VTON(bp->b_vp), bp, 1);
		} else {
			error = nandfs_bread(dat_node, bd[i].bd_offset, NULL,
			    0, &bp);
			if (error) {
				nandfs_error("%s: cannot read dat node\n",
				    __func__);
				brelse(bp);
				VOP_UNLOCK(NTOV(dat_node), 0);
				return (error);
			}
			nandfs_dirty_buf(bp, 1);
		}
		DPRINTF(CLEAN, ("%s: bp: %p\n", __func__, bp));
	}

	VOP_UNLOCK(NTOV(dat_node), 0);

	return (0);
}
Exemplo n.º 2
0
int
bmap_dirty_meta(struct nandfs_node *node, nandfs_lbn_t lblk, int force)
{
	struct nandfs_indir a[NIADDR+1], *ap;
#ifdef DEBUG
	nandfs_daddr_t daddr;
#endif
	struct buf *bp;
	int error;
	int num, *nump;

	DPRINTF(BMAP, ("%s: node %p lblk=%jx\n", __func__, node, lblk));

	ap = a;
	nump = &num;

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

	/*
	 * Direct block, nothing to do
	 */
	if (num == 0)
		return (0);

	DPRINTF(BMAP, ("%s: node %p reading blocks\n", __func__, node));

	for (bp = NULL, ++ap; --num; ap++) {
		error = nandfs_bread_meta(node, ap->in_lbn, NOCRED, 0, &bp);
		if (error) {
			brelse(bp);
			return (error);
		}

#ifdef DEBUG
		daddr = ((nandfs_daddr_t *)bp->b_data)[ap->in_off];
		MPASS(daddr != 0 || node->nn_ino == 3);
#endif

		error = nandfs_dirty_buf_meta(bp, force);
		if (error)
			return (error);
	}

	return (0);
}
Exemplo n.º 3
0
int
bmap_lookup(struct nandfs_node *node, nandfs_lbn_t lblk, nandfs_daddr_t *vblk)
{
	struct nandfs_inode *ip;
	struct nandfs_indir a[NIADDR + 1], *ap;
	nandfs_daddr_t daddr;
	struct buf *bp;
	int error;
	int num, *nump;

	DPRINTF(BMAP, ("%s: node %p lblk %jx enter\n", __func__, node, lblk));
	ip = &node->nn_inode;

	ap = a;
	nump = &num;

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

	if (num == 0) {
		*vblk = ip->i_db[lblk];
		return (0);
	}

	DPRINTF(BMAP, ("%s: node %p lblk=%jx trying ip->i_ib[%x]\n", __func__,
	    node, lblk, ap->in_off));
	daddr = ip->i_ib[ap->in_off];
	for (bp = NULL, ++ap; --num; ap++) {
		if (daddr == 0) {
			DPRINTF(BMAP, ("%s: node %p lblk=%jx returning with "
			    "vblk 0\n", __func__, node, lblk));
			*vblk = 0;
			return (0);
		}
		if (ap->in_lbn == lblk) {
			DPRINTF(BMAP, ("%s: node %p lblk=%jx ap->in_lbn=%jx "
			    "returning address of indirect block (%jx)\n",
			    __func__, node, lblk, ap->in_lbn, daddr));
			*vblk = daddr;
			return (0);
		}

		DPRINTF(BMAP, ("%s: node %p lblk=%jx reading block "
		    "ap->in_lbn=%jx\n", __func__, node, lblk, ap->in_lbn));

		error = nandfs_bread_meta(node, ap->in_lbn, NOCRED, 0, &bp);
		if (error) {
			brelse(bp);
			return (error);
		}

		daddr = ((nandfs_daddr_t *)bp->b_data)[ap->in_off];
		brelse(bp);
	}

	DPRINTF(BMAP, ("%s: node %p lblk=%jx returning with %jx\n", __func__,
	    node, lblk, daddr));
	*vblk = daddr;

	return (0);
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
0
int
bmap_insert_block(struct nandfs_node *node, nandfs_lbn_t lblk,
    nandfs_daddr_t vblk)
{
	struct nandfs_inode *ip;
	struct nandfs_indir a[NIADDR+1], *ap;
	struct buf *bp;
	nandfs_daddr_t daddr;
	int error;
	int num, *nump, i;

	DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx\n", __func__, node, lblk,
	    vblk));

	ip = &node->nn_inode;

	ap = a;
	nump = &num;

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

	DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx got num=%d\n", __func__,
	    node, lblk, vblk, num));

	if (num == 0) {
		DPRINTF(BMAP, ("%s: node %p lblk=%jx direct block\n", __func__,
		    node, lblk));
		ip->i_db[lblk] = vblk;
		return (0);
	}

	DPRINTF(BMAP, ("%s: node %p lblk=%jx indirect block level %d\n",
	    __func__, node, lblk, ap->in_off));

	if (num == 1) {
		DPRINTF(BMAP, ("%s: node %p lblk=%jx indirect block: inserting "
		    "%jx as vblk for indirect block %d\n", __func__, node,
		    lblk, vblk, ap->in_off));
		ip->i_ib[ap->in_off] = vblk;
		return (0);
	}

	bp = NULL;
	daddr = ip->i_ib[a[0].in_off];
	for (i = 1; i < num; i++) {
		if (bp)
			brelse(bp);
		if (daddr == 0) {
			DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx create "
			    "block %jx %d\n", __func__, node, lblk, vblk,
			    a[i].in_lbn, a[i].in_off));
			error = nandfs_bcreate_meta(node, a[i].in_lbn, NOCRED,
			    0, &bp);
			if (error)
				return (error);
		} else {
			DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx read "
			    "block %jx %d\n", __func__, node, daddr, vblk,
			    a[i].in_lbn, a[i].in_off));
			error = nandfs_bread_meta(node, a[i].in_lbn, NOCRED, 0, &bp);
			if (error) {
				brelse(bp);
				return (error);
			}
		}
		daddr = ((nandfs_daddr_t *)bp->b_data)[a[i].in_off];
	}
	i--;

	DPRINTF(BMAP,
	    ("%s: bmap node %p lblk=%jx vblk=%jx inserting vblk level %d at "
	    "offset %d at %jx\n", __func__, node, lblk, vblk, i, a[i].in_off,
	    daddr));

	if (!bp) {
		nandfs_error("%s: cannot find indirect block\n", __func__);
		return (-1);
	}
	((nandfs_daddr_t *)bp->b_data)[a[i].in_off] = vblk;

	error = nandfs_dirty_buf_meta(bp, 0);
	if (error) {
		nandfs_warning("%s: dirty failed buf: %p\n", __func__, bp);
		return (error);
	}
	DPRINTF(BMAP, ("%s: exiting node %p lblk=%jx vblk=%jx\n", __func__,
	    node, lblk, vblk));

	return (error);
}