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); }
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 = # 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); }
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); }
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 = # 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); }