nandfs_bmap.c revision 296373
1/*- 2 * Copyright (c) 2010-2012 Semihalf 3 * Copyright (c) 2008, 2009 Reinoud Zandijk 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * From: NetBSD: nilfs_subr.c,v 1.4 2009/07/29 17:06:57 reinoud 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: releng/10.3/sys/fs/nandfs/nandfs_bmap.c 235537 2012-05-17 10:11:18Z gber $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/namei.h> 35#include <sys/kernel.h> 36#include <sys/stat.h> 37#include <sys/buf.h> 38#include <sys/bio.h> 39#include <sys/proc.h> 40#include <sys/mount.h> 41#include <sys/vnode.h> 42#include <sys/signalvar.h> 43#include <sys/malloc.h> 44#include <sys/dirent.h> 45#include <sys/lockf.h> 46#include <sys/ktr.h> 47 48#include <vm/vm.h> 49#include <vm/vm_extern.h> 50#include <vm/vm_object.h> 51#include <vm/vnode_pager.h> 52 53#include <machine/_inttypes.h> 54 55#include <vm/vm.h> 56#include <vm/vm_extern.h> 57#include <vm/vm_object.h> 58#include <vm/vnode_pager.h> 59 60#include "nandfs_mount.h" 61#include "nandfs.h" 62#include "nandfs_subr.h" 63#include "bmap.h" 64 65nandfs_lbn_t 66nandfs_get_maxfilesize(struct nandfs_device *fsdev) 67{ 68 69 return (get_maxfilesize(fsdev)); 70} 71 72int 73nandfs_bmap_lookup(struct nandfs_node *node, nandfs_lbn_t lblk, 74 nandfs_daddr_t *vblk) 75{ 76 int error = 0; 77 78 if (node->nn_ino == NANDFS_GC_INO && lblk >= 0) 79 *vblk = lblk; 80 else 81 error = bmap_lookup(node, lblk, vblk); 82 83 DPRINTF(TRANSLATE, ("%s: error %d ino %#jx lblocknr %#jx -> %#jx\n", 84 __func__, error, (uintmax_t)node->nn_ino, (uintmax_t)lblk, 85 (uintmax_t)*vblk)); 86 87 if (error) 88 nandfs_error("%s: returned %d", __func__, error); 89 90 return (error); 91} 92 93int 94nandfs_bmap_insert_block(struct nandfs_node *node, nandfs_lbn_t lblk, 95 struct buf *bp) 96{ 97 struct nandfs_device *fsdev; 98 nandfs_daddr_t vblk; 99 int error; 100 101 fsdev = node->nn_nandfsdev; 102 103 vblk = 0; 104 if (node->nn_ino != NANDFS_DAT_INO) { 105 error = nandfs_vblock_alloc(fsdev, &vblk); 106 if (error) 107 return (error); 108 } 109 110 nandfs_buf_set(bp, NANDFS_VBLK_ASSIGNED); 111 nandfs_vblk_set(bp, vblk); 112 113 error = bmap_insert_block(node, lblk, vblk); 114 if (error) { 115 nandfs_vblock_free(fsdev, vblk); 116 return (error); 117 } 118 119 return (0); 120} 121 122int 123nandfs_bmap_dirty_blocks(struct nandfs_node *node, struct buf *bp, int force) 124{ 125 int error; 126 127 error = bmap_dirty_meta(node, bp->b_lblkno, force); 128 if (error) 129 nandfs_error("%s: cannot dirty buffer %p\n", 130 __func__, bp); 131 132 return (error); 133} 134 135static int 136nandfs_bmap_update_mapping(struct nandfs_node *node, nandfs_lbn_t lblk, 137 nandfs_daddr_t blknr) 138{ 139 int error; 140 141 DPRINTF(BMAP, 142 ("%s: node: %p ino: %#jx lblk: %#jx vblk: %#jx\n", 143 __func__, node, (uintmax_t)node->nn_ino, (uintmax_t)lblk, 144 (uintmax_t)blknr)); 145 146 error = bmap_insert_block(node, lblk, blknr); 147 148 return (error); 149} 150 151int 152nandfs_bmap_update_block(struct nandfs_node *node, struct buf *bp, 153 nandfs_lbn_t blknr) 154{ 155 nandfs_lbn_t lblk; 156 int error; 157 158 lblk = bp->b_lblkno; 159 nandfs_vblk_set(bp, blknr); 160 161 DPRINTF(BMAP, ("%s: node: %p ino: %#jx bp: %p lblk: %#jx blk: %#jx\n", 162 __func__, node, (uintmax_t)node->nn_ino, bp, 163 (uintmax_t)lblk, (uintmax_t)blknr)); 164 165 error = nandfs_bmap_update_mapping(node, lblk, blknr); 166 if (error) { 167 nandfs_error("%s: cannot update lblk:%jx to blk:%jx for " 168 "node:%p, error:%d\n", __func__, (uintmax_t)lblk, 169 (uintmax_t)blknr, node, error); 170 return (error); 171 } 172 173 return (error); 174} 175 176int 177nandfs_bmap_update_dat(struct nandfs_node *node, nandfs_daddr_t oldblk, 178 struct buf *bp) 179{ 180 struct nandfs_device *fsdev; 181 nandfs_daddr_t vblk = 0; 182 int error; 183 184 if (node->nn_ino == NANDFS_DAT_INO) 185 return (0); 186 187 if (nandfs_buf_check(bp, NANDFS_VBLK_ASSIGNED)) { 188 nandfs_buf_clear(bp, NANDFS_VBLK_ASSIGNED); 189 return (0); 190 } 191 192 fsdev = node->nn_nandfsdev; 193 194 /* First alloc new virtual block.... */ 195 error = nandfs_vblock_alloc(fsdev, &vblk); 196 if (error) 197 return (error); 198 199 error = nandfs_bmap_update_block(node, bp, vblk); 200 if (error) 201 return (error); 202 203 /* Then we can end up with old one */ 204 nandfs_vblock_end(fsdev, oldblk); 205 206 DPRINTF(BMAP, 207 ("%s: ino %#jx block %#jx: update vblk %#jx to %#jx\n", 208 __func__, (uintmax_t)node->nn_ino, (uintmax_t)bp->b_lblkno, 209 (uintmax_t)oldblk, (uintmax_t)vblk)); 210 return (error); 211} 212 213int 214nandfs_bmap_truncate_mapping(struct nandfs_node *node, nandfs_lbn_t oblk, 215 nandfs_lbn_t nblk) 216{ 217 nandfs_lbn_t todo; 218 int error; 219 220 todo = oblk - nblk; 221 222 DPRINTF(BMAP, ("%s: node %p oblk %jx nblk %jx truncate by %jx\n", 223 __func__, node, oblk, nblk, todo)); 224 225 error = bmap_truncate_mapping(node, oblk, todo); 226 if (error) 227 return (error); 228 229 return (error); 230} 231