/*- * Copyright (c) 2010-2012 Semihalf * Copyright (c) 2008, 2009 Reinoud Zandijk * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * From: NetBSD: nilfs_subr.c,v 1.4 2009/07/29 17:06:57 reinoud */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nandfs_mount.h" #include "nandfs.h" #include "nandfs_subr.h" #include "bmap.h" nandfs_lbn_t nandfs_get_maxfilesize(struct nandfs_device *fsdev) { return (get_maxfilesize(fsdev)); } int nandfs_bmap_lookup(struct nandfs_node *node, nandfs_lbn_t lblk, nandfs_daddr_t *vblk) { int error = 0; if (node->nn_ino == NANDFS_GC_INO && lblk >= 0) *vblk = lblk; else error = bmap_lookup(node, lblk, vblk); DPRINTF(TRANSLATE, ("%s: error %d ino %#jx lblocknr %#jx -> %#jx\n", __func__, error, (uintmax_t)node->nn_ino, (uintmax_t)lblk, (uintmax_t)*vblk)); if (error) nandfs_error("%s: returned %d", __func__, error); return (error); } int nandfs_bmap_insert_block(struct nandfs_node *node, nandfs_lbn_t lblk, struct buf *bp) { struct nandfs_device *fsdev; nandfs_daddr_t vblk; int error; fsdev = node->nn_nandfsdev; vblk = 0; if (node->nn_ino != NANDFS_DAT_INO) { error = nandfs_vblock_alloc(fsdev, &vblk); if (error) return (error); } nandfs_buf_set(bp, NANDFS_VBLK_ASSIGNED); nandfs_vblk_set(bp, vblk); error = bmap_insert_block(node, lblk, vblk); if (error) { nandfs_vblock_free(fsdev, vblk); return (error); } return (0); } int nandfs_bmap_dirty_blocks(struct nandfs_node *node, struct buf *bp, int force) { int error; error = bmap_dirty_meta(node, bp->b_lblkno, force); if (error) nandfs_error("%s: cannot dirty buffer %p\n", __func__, bp); return (error); } static int nandfs_bmap_update_mapping(struct nandfs_node *node, nandfs_lbn_t lblk, nandfs_daddr_t blknr) { int error; DPRINTF(BMAP, ("%s: node: %p ino: %#jx lblk: %#jx vblk: %#jx\n", __func__, node, (uintmax_t)node->nn_ino, (uintmax_t)lblk, (uintmax_t)blknr)); error = bmap_insert_block(node, lblk, blknr); return (error); } int nandfs_bmap_update_block(struct nandfs_node *node, struct buf *bp, nandfs_lbn_t blknr) { nandfs_lbn_t lblk; int error; lblk = bp->b_lblkno; nandfs_vblk_set(bp, blknr); DPRINTF(BMAP, ("%s: node: %p ino: %#jx bp: %p lblk: %#jx blk: %#jx\n", __func__, node, (uintmax_t)node->nn_ino, bp, (uintmax_t)lblk, (uintmax_t)blknr)); error = nandfs_bmap_update_mapping(node, lblk, blknr); if (error) { nandfs_error("%s: cannot update lblk:%jx to blk:%jx for " "node:%p, error:%d\n", __func__, (uintmax_t)lblk, (uintmax_t)blknr, node, error); return (error); } return (error); } 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); } int nandfs_bmap_truncate_mapping(struct nandfs_node *node, nandfs_lbn_t oblk, nandfs_lbn_t nblk) { nandfs_lbn_t todo; int error; todo = oblk - nblk; DPRINTF(BMAP, ("%s: node %p oblk %jx nblk %jx truncate by %jx\n", __func__, node, oblk, nblk, todo)); error = bmap_truncate_mapping(node, oblk, todo); if (error) return (error); return (error); }