summaryrefslogtreecommitdiffstats
path: root/sys/fs/nandfs/nandfs_bmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/nandfs/nandfs_bmap.c')
-rw-r--r--sys/fs/nandfs/nandfs_bmap.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/sys/fs/nandfs/nandfs_bmap.c b/sys/fs/nandfs/nandfs_bmap.c
new file mode 100644
index 0000000..9f800b8
--- /dev/null
+++ b/sys/fs/nandfs/nandfs_bmap.c
@@ -0,0 +1,230 @@
+/*-
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/kernel.h>
+#include <sys/stat.h>
+#include <sys/buf.h>
+#include <sys/bio.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/signalvar.h>
+#include <sys/malloc.h>
+#include <sys/dirent.h>
+#include <sys/lockf.h>
+#include <sys/ktr.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_object.h>
+#include <vm/vnode_pager.h>
+
+#include <machine/_inttypes.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_object.h>
+#include <vm/vnode_pager.h>
+
+#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);
+}
OpenPOWER on IntegriCloud