nandfs_subr.c revision 264657
196136Sobrien/*- 2150234Skan * Copyright (c) 2010-2012 Semihalf 3150234Skan * Copyright (c) 2008, 2009 Reinoud Zandijk 4150234Skan * All rights reserved. 596340Sobrien * 6132751Skan * Redistribution and use in source and binary forms, with or without 7132751Skan * modification, are permitted provided that the following conditions 896340Sobrien * are met: 9132751Skan * 1. Redistributions of source code must retain the above copyright 1096340Sobrien * notice, this list of conditions and the following disclaimer. 1196340Sobrien * 2. Redistributions in binary form must reproduce the above copyright 12132751Skan * notice, this list of conditions and the following disclaimer in the 1396340Sobrien * documentation and/or other materials provided with the distribution. 1496340Sobrien * 15132751Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1696340Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1796340Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18132751Skan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1996340Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2096340Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21132751Skan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2296340Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2396340Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24132751Skan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25246857Sdim * 2696340Sobrien * From: NetBSD: nilfs_subr.c,v 1.4 2009/07/29 17:06:57 reinoud 27132751Skan */ 2896340Sobrien 2996340Sobrien#include <sys/cdefs.h> 30132751Skan__FBSDID("$FreeBSD: head/sys/fs/nandfs/nandfs_subr.c 264657 2014-04-18 17:03:35Z imp $"); 3196340Sobrien 3296340Sobrien#include <sys/param.h> 33132751Skan#include <sys/systm.h> 3496340Sobrien#include <sys/namei.h> 3596340Sobrien#include <sys/resourcevar.h> 36132751Skan#include <sys/kernel.h> 37140864Skan#include <sys/file.h> 3896340Sobrien#include <sys/stat.h> 39169718Skan#include <sys/buf.h> 40169718Skan#include <sys/bio.h> 41169718Skan#include <sys/proc.h> 42132751Skan#include <sys/mount.h> 4396340Sobrien#include <sys/vnode.h> 4496340Sobrien#include <sys/signalvar.h> 45132751Skan#include <sys/malloc.h> 4696340Sobrien#include <sys/dirent.h> 4796340Sobrien#include <sys/lockf.h> 48132751Skan#include <sys/libkern.h> 49132751Skan 5096340Sobrien#include <geom/geom.h> 51132751Skan#include <geom/geom_vfs.h> 5296340Sobrien 5396340Sobrien#include <vm/vm.h> 54132751Skan#include <vm/vm_extern.h> 5596340Sobrien 5696340Sobrien#include <machine/_inttypes.h> 57132751Skan#include "nandfs_mount.h" 5896340Sobrien#include "nandfs.h" 5996340Sobrien#include "nandfs_subr.h" 60132751Skan 6196340SobrienMALLOC_DEFINE(M_NANDFSMNT, "nandfs_mount", "NANDFS mount"); 6296340SobrienMALLOC_DEFINE(M_NANDFSTEMP, "nandfs_tmt", "NANDFS tmp"); 63132751Skan 64132751Skanuma_zone_t nandfs_node_zone; 6596340Sobrien 66132751Skanvoid nandfs_bdflush(struct bufobj *bo, struct buf *bp); 6796340Sobrienint nandfs_bufsync(struct bufobj *bo, int waitfor); 6896340Sobrien 69132751Skanstruct buf_ops buf_ops_nandfs = { 70246857Sdim .bop_name = "buf_ops_nandfs", 7196340Sobrien .bop_write = bufwrite, 72132751Skan .bop_strategy = bufstrategy, 7396340Sobrien .bop_sync = nandfs_bufsync, 7496340Sobrien .bop_bdflush = nandfs_bdflush, 75132751Skan}; 76132751Skan 7796340Sobrienint 78169718Skannandfs_bufsync(struct bufobj *bo, int waitfor) 79169718Skan{ 8096340Sobrien struct vnode *vp; 81132751Skan int error = 0; 8296340Sobrien 8396340Sobrien vp = bo->__bo_vnode; 84132751Skan 8596340Sobrien ASSERT_VOP_LOCKED(vp, __func__); 8696340Sobrien error = nandfs_sync_file(vp); 87132751Skan if (error) 8896340Sobrien nandfs_warning("%s: cannot flush buffers err:%d\n", 8996340Sobrien __func__, error); 90132751Skan 91132751Skan return (error); 92132751Skan} 93132751Skan 9496340Sobrienvoid 9596340Sobriennandfs_bdflush(bo, bp) 96132751Skan struct bufobj *bo; 97140861Skan struct buf *bp; 9896340Sobrien{ 99132751Skan struct vnode *vp; 10096340Sobrien int error; 10196340Sobrien 102132751Skan if (bo->bo_dirty.bv_cnt <= ((dirtybufthresh * 8) / 10)) 103246857Sdim return; 10496340Sobrien 105132751Skan vp = bp->b_vp; 10696340Sobrien if (NANDFS_SYS_NODE(VTON(vp)->nn_ino)) 10796340Sobrien return; 108132751Skan 109132751Skan if (NANDFS_IS_INDIRECT(bp)) 110132751Skan return; 111132751Skan 11296340Sobrien error = nandfs_sync_file(vp); 11396340Sobrien if (error) 114132751Skan nandfs_warning("%s: cannot flush buffers err:%d\n", 115144140Sdas __func__, error); 11696340Sobrien} 117132751Skan 118132751Skanint 119132751Skannandfs_init(struct vfsconf *vfsp) 120169718Skan{ 121169718Skan 122169718Skan nandfs_node_zone = uma_zcreate("nandfs node zone", 123132751Skan sizeof(struct nandfs_node), NULL, NULL, NULL, NULL, 0, 0); 12496340Sobrien 12596340Sobrien return (0); 126169718Skan} 127169718Skan 128169718Skanint 12996340Sobriennandfs_uninit(struct vfsconf *vfsp) 130132751Skan{ 13196340Sobrien 13296340Sobrien uma_zdestroy(nandfs_node_zone); 133132751Skan return (0); 13496340Sobrien} 13596340Sobrien 136132751Skan/* Basic calculators */ 137246857Sdimuint64_t 13896340Sobriennandfs_get_segnum_of_block(struct nandfs_device *nandfsdev, 139132751Skan nandfs_daddr_t blocknr) 140169718Skan{ 14196340Sobrien uint64_t segnum, blks_per_seg; 142132751Skan 143169718Skan MPASS(blocknr >= nandfsdev->nd_fsdata.f_first_data_block); 14496340Sobrien 145132751Skan blks_per_seg = nandfsdev->nd_fsdata.f_blocks_per_segment; 146169718Skan 14796340Sobrien segnum = blocknr / blks_per_seg; 148132751Skan segnum -= nandfsdev->nd_fsdata.f_first_data_block / blks_per_seg; 149132751Skan 150111116Skan DPRINTF(SYNC, ("%s: returning blocknr %jx -> segnum %jx\n", __func__, 151169718Skan blocknr, segnum)); 152169718Skan 153169718Skan return (segnum); 154132751Skan} 155132751Skan 156132751Skanvoid 157132751Skannandfs_get_segment_range(struct nandfs_device *nandfsdev, uint64_t segnum, 15896340Sobrien uint64_t *seg_start, uint64_t *seg_end) 15996340Sobrien{ 160132751Skan uint64_t blks_per_seg; 16196340Sobrien 16296340Sobrien blks_per_seg = nandfsdev->nd_fsdata.f_blocks_per_segment; 163132751Skan *seg_start = nandfsdev->nd_fsdata.f_first_data_block + 16496340Sobrien blks_per_seg * segnum; 16596340Sobrien if (seg_end != NULL) 166132751Skan *seg_end = *seg_start + blks_per_seg -1; 16796340Sobrien} 16896340Sobrien 169132751Skanvoid nandfs_calc_mdt_consts(struct nandfs_device *nandfsdev, 17096340Sobrien struct nandfs_mdt *mdt, int entry_size) 17196340Sobrien{ 172132751Skan uint32_t blocksize = nandfsdev->nd_blocksize; 17396340Sobrien 17496340Sobrien mdt->entries_per_group = blocksize * 8; 175169718Skan mdt->entries_per_block = blocksize / entry_size; 176132751Skan 177132751Skan mdt->blocks_per_group = 178169718Skan (mdt->entries_per_group -1) / mdt->entries_per_block + 1 + 1; 179169718Skan mdt->groups_per_desc_block = 180169718Skan blocksize / sizeof(struct nandfs_block_group_desc); 181132751Skan mdt->blocks_per_desc_block = 18296340Sobrien mdt->groups_per_desc_block * mdt->blocks_per_group + 1; 18396340Sobrien} 184132751Skan 185144140Sdasint 18696340Sobriennandfs_dev_bread(struct nandfs_device *nandfsdev, nandfs_lbn_t blocknr, 187132751Skan struct ucred *cred, int flags, struct buf **bpp) 188132751Skan{ 189132751Skan int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE; 190132751Skan int error; 191132751Skan 192132751Skan DPRINTF(BLOCK, ("%s: read from block %jx vp %p\n", __func__, 193162553Skan blocknr * blk2dev, nandfsdev->nd_devvp)); 194162553Skan error = bread(nandfsdev->nd_devvp, blocknr * blk2dev, 195162553Skan nandfsdev->nd_blocksize, NOCRED, bpp); 196162553Skan if (error) 197162553Skan nandfs_error("%s: cannot read from device - blk:%jx\n", 198162553Skan __func__, blocknr); 199162553Skan return (error); 200162553Skan} 201162553Skan 202162553Skan/* Read on a node */ 203162553Skanint 204162553Skannandfs_bread(struct nandfs_node *node, nandfs_lbn_t blocknr, 205162553Skan struct ucred *cred, int flags, struct buf **bpp) 206162553Skan{ 207162553Skan nandfs_daddr_t vblk; 208132751Skan int error; 209132751Skan 210132751Skan DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node), 211132751Skan blocknr)); 21296340Sobrien 21396340Sobrien error = bread(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize, 214132751Skan cred, bpp); 215254295Spfg 21696340Sobrien KASSERT(error == 0, ("%s: vp:%p lbn:%#jx err:%d\n", __func__, 217132751Skan NTOV(node), blocknr, error)); 21896340Sobrien 21996340Sobrien if (!nandfs_vblk_get(*bpp) && 220132751Skan ((*bpp)->b_flags & B_CACHE) && node->nn_ino != NANDFS_DAT_INO) { 221254295Spfg nandfs_bmap_lookup(node, blocknr, &vblk); 22296340Sobrien nandfs_vblk_set(*bpp, vblk); 223132751Skan } 224132751Skan return (error); 225132751Skan} 226132751Skan 227132751Skanint 228132751Skannandfs_bread_meta(struct nandfs_node *node, nandfs_lbn_t blocknr, 229169718Skan struct ucred *cred, int flags, struct buf **bpp) 230169718Skan{ 23196340Sobrien nandfs_daddr_t vblk; 232132751Skan int error; 233132751Skan 234132751Skan DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node), 235132751Skan blocknr)); 236132751Skan 237132751Skan error = bread(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize, 238169718Skan cred, bpp); 239169718Skan 240169718Skan KASSERT(error == 0, ("%s: vp:%p lbn:%#jx err:%d\n", __func__, 241132751Skan NTOV(node), blocknr, error)); 24296340Sobrien 24396340Sobrien if (!nandfs_vblk_get(*bpp) && 244132751Skan ((*bpp)->b_flags & B_CACHE) && node->nn_ino != NANDFS_DAT_INO) { 245169718Skan nandfs_bmap_lookup(node, blocknr, &vblk); 24696340Sobrien nandfs_vblk_set(*bpp, vblk); 247132751Skan } 248132751Skan 24996340Sobrien return (error); 250132751Skan} 25196340Sobrien 25296340Sobrienint 253169718Skannandfs_bdestroy(struct nandfs_node *node, nandfs_daddr_t vblk) 254169718Skan{ 255169718Skan int error; 256132751Skan 25796340Sobrien if (!NANDFS_SYS_NODE(node->nn_ino)) 25896340Sobrien NANDFS_WRITEASSERT(node->nn_nandfsdev); 259132751Skan 26096340Sobrien error = nandfs_vblock_end(node->nn_nandfsdev, vblk); 26196340Sobrien if (error) { 262132751Skan nandfs_error("%s: ending vblk: %jx failed\n", 26396340Sobrien __func__, (uintmax_t)vblk); 26496340Sobrien return (error); 265132751Skan } 26696340Sobrien node->nn_inode.i_blocks--; 26796340Sobrien 268132751Skan return (0); 269132751Skan} 270132751Skan 271132751Skanint 27296340Sobriennandfs_bcreate(struct nandfs_node *node, nandfs_lbn_t blocknr, 27396340Sobrien struct ucred *cred, int flags, struct buf **bpp) 274132751Skan{ 27596340Sobrien int error; 27696340Sobrien 277132751Skan ASSERT_VOP_LOCKED(NTOV(node), __func__); 27896340Sobrien if (!NANDFS_SYS_NODE(node->nn_ino)) 27996340Sobrien NANDFS_WRITEASSERT(node->nn_nandfsdev); 280132751Skan 28196340Sobrien DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node), 28296340Sobrien blocknr)); 283132751Skan 28496340Sobrien *bpp = getblk(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize, 28596340Sobrien 0, 0, 0); 286132751Skan 28796340Sobrien KASSERT((*bpp), ("%s: vp:%p lbn:%#jx\n", __func__, 28896340Sobrien NTOV(node), blocknr)); 289132751Skan 29096340Sobrien if (*bpp) { 29196340Sobrien vfs_bio_clrbuf(*bpp); 292132751Skan (*bpp)->b_blkno = ~(0); /* To avoid VOP_BMAP in bdwrite */ 29396340Sobrien error = nandfs_bmap_insert_block(node, blocknr, *bpp); 29496340Sobrien if (error) { 295132751Skan nandfs_warning("%s: failed bmap insert node:%p" 296246857Sdim " blk:%jx\n", __func__, node, blocknr); 29796340Sobrien brelse(*bpp); 298169718Skan return (error); 299169718Skan } 300169718Skan node->nn_inode.i_blocks++; 301132751Skan 302132751Skan return (0); 303132751Skan } 304132751Skan 305132751Skan return (-1); 306132751Skan} 307246857Sdim 308246857Sdimint 309246857Sdimnandfs_bcreate_meta(struct nandfs_node *node, nandfs_lbn_t blocknr, 310246857Sdim struct ucred *cred, int flags, struct buf **bpp) 311246857Sdim{ 312246857Sdim struct nandfs_device *fsdev; 313132751Skan nandfs_daddr_t vblk; 314132751Skan int error; 315132751Skan 316132751Skan ASSERT_VOP_LOCKED(NTOV(node), __func__); 317132751Skan NANDFS_WRITEASSERT(node->nn_nandfsdev); 318132751Skan 319132751Skan DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node), 320114037Sobrien blocknr)); 32196340Sobrien 322132751Skan fsdev = node->nn_nandfsdev; 323114037Sobrien 32496340Sobrien *bpp = getblk(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize, 325246857Sdim 0, 0, 0); 326246857Sdim 327246857Sdim KASSERT((*bpp), ("%s: vp:%p lbn:%#jx\n", __func__, 328132751Skan NTOV(node), blocknr)); 329132751Skan 330132751Skan memset((*bpp)->b_data, 0, fsdev->nd_blocksize); 331132751Skan 332132751Skan vfs_bio_clrbuf(*bpp); 333132751Skan (*bpp)->b_blkno = ~(0); /* To avoid VOP_BMAP in bdwrite */ 334169718Skan 335169718Skan nandfs_buf_set(*bpp, NANDFS_VBLK_ASSIGNED); 336169718Skan 337132751Skan if (node->nn_ino != NANDFS_DAT_INO) { 338132751Skan error = nandfs_vblock_alloc(fsdev, &vblk); 339132751Skan if (error) { 340132751Skan nandfs_buf_clear(*bpp, NANDFS_VBLK_ASSIGNED); 341132751Skan brelse(*bpp); 342132751Skan return (error); 343132751Skan } 344132751Skan } else 345132751Skan vblk = fsdev->nd_fakevblk++; 346132751Skan 347132751Skan nandfs_vblk_set(*bpp, vblk); 348132751Skan 349169718Skan nandfs_bmap_insert_block(node, blocknr, *bpp); 350169718Skan return (0); 351169718Skan} 352132751Skan 353132751Skan/* Translate index to a file block number and an entry */ 354132751Skanvoid 355132751Skannandfs_mdt_trans(struct nandfs_mdt *mdt, uint64_t index, 356132751Skan nandfs_lbn_t *blocknr, uint32_t *entry_in_block) 357132751Skan{ 358132751Skan uint64_t blknr; 359132751Skan uint64_t group, group_offset, blocknr_in_group; 360132751Skan uint64_t desc_block, desc_offset; 361132751Skan 362132751Skan /* Calculate our offset in the file */ 363132751Skan group = index / mdt->entries_per_group; 364169718Skan group_offset = index % mdt->entries_per_group; 365169718Skan desc_block = group / mdt->groups_per_desc_block; 366169718Skan desc_offset = group % mdt->groups_per_desc_block; 367169718Skan blocknr_in_group = group_offset / mdt->entries_per_block; 368169718Skan 369169718Skan /* To descgroup offset */ 370132751Skan blknr = 1 + desc_block * mdt->blocks_per_desc_block; 37196340Sobrien 37296340Sobrien /* To group offset */ 373132751Skan blknr += desc_offset * mdt->blocks_per_group; 37496340Sobrien 37596340Sobrien /* To actual file block */ 376132751Skan blknr += 1 + blocknr_in_group; 37796340Sobrien 37896340Sobrien *blocknr = blknr; 379132751Skan *entry_in_block = group_offset % mdt->entries_per_block; 38096340Sobrien} 38196340Sobrien 382169718Skanvoid 383237098Smariusnandfs_mdt_trans_blk(struct nandfs_mdt *mdt, uint64_t index, 384169718Skan uint64_t *desc, uint64_t *bitmap, nandfs_lbn_t *blocknr, 385169718Skan uint32_t *entry_in_block) 38696340Sobrien{ 387132751Skan uint64_t blknr; 388132751Skan uint64_t group, group_offset, blocknr_in_group; 389132751Skan uint64_t desc_block, desc_offset; 390150233Skan 391169718Skan /* Calculate our offset in the file */ 392107615Sobrien group = index / mdt->entries_per_group; 39396340Sobrien group_offset = index % mdt->entries_per_group; 394169718Skan desc_block = group / mdt->groups_per_desc_block; 395107615Sobrien desc_offset = group % mdt->groups_per_desc_block; 39696340Sobrien blocknr_in_group = group_offset / mdt->entries_per_block; 397169718Skan 398107615Sobrien /* To descgroup offset */ 399169718Skan *desc = desc_block * mdt->blocks_per_desc_block; 40096340Sobrien blknr = 1 + desc_block * mdt->blocks_per_desc_block; 401132751Skan 402132751Skan /* To group offset */ 403132751Skan blknr += desc_offset * mdt->blocks_per_group; 404150233Skan *bitmap = blknr; 405169718Skan 406114037Sobrien /* To actual file block */ 407169718Skan blknr += 1 + blocknr_in_group; 40896340Sobrien 409132751Skan *blocknr = blknr; 410132751Skan *entry_in_block = group_offset % mdt->entries_per_block; 411132751Skan 412169718Skan DPRINTF(ALLOC, 413169718Skan ("%s: desc_buf: %jx bitmap_buf: %jx entry_buf: %jx entry: %x\n", 41496340Sobrien __func__, (uintmax_t)*desc, (uintmax_t)*bitmap, 415132751Skan (uintmax_t)*blocknr, *entry_in_block)); 416132751Skan} 41796340Sobrien 418132751Skanint 419132751Skannandfs_vtop(struct nandfs_node *node, nandfs_daddr_t vblocknr, 42096340Sobrien nandfs_daddr_t *pblocknr) 421132751Skan{ 422132751Skan struct nandfs_node *dat_node; 42396340Sobrien struct nandfs_dat_entry *entry; 424132751Skan struct buf *bp; 425132751Skan nandfs_lbn_t ldatblknr; 42696340Sobrien uint32_t entry_in_block; 427132751Skan int locked, error; 428132751Skan 42996340Sobrien if (node->nn_ino == NANDFS_DAT_INO || node->nn_ino == NANDFS_GC_INO) { 430132751Skan *pblocknr = vblocknr; 431132751Skan return (0); 43296340Sobrien } 433132751Skan 434132751Skan /* only translate valid vblocknrs */ 43596340Sobrien if (vblocknr == 0) 436132751Skan return (0); 437132751Skan 43896340Sobrien dat_node = node->nn_nandfsdev->nd_dat_node; 439132751Skan nandfs_mdt_trans(&node->nn_nandfsdev->nd_dat_mdt, vblocknr, &ldatblknr, 440132751Skan &entry_in_block); 44196340Sobrien 442132751Skan locked = NANDFS_VOP_ISLOCKED(NTOV(dat_node)); 443132751Skan if (!locked) 44496340Sobrien VOP_LOCK(NTOV(dat_node), LK_SHARED); 445132751Skan error = nandfs_bread(dat_node, ldatblknr, NOCRED, 0, &bp); 446132751Skan if (error) { 44796340Sobrien DPRINTF(TRANSLATE, ("vtop: can't read in DAT block %#jx!\n", 448132751Skan (uintmax_t)ldatblknr)); 449132751Skan brelse(bp); 450107615Sobrien VOP_UNLOCK(NTOV(dat_node), 0); 451132751Skan return (error); 452132751Skan } 453117428Skan 454132751Skan /* Get our translation */ 455132751Skan entry = ((struct nandfs_dat_entry *) bp->b_data) + entry_in_block; 456117428Skan DPRINTF(TRANSLATE, ("\tentry %p data %p entry_in_block %x\n", 457132751Skan entry, bp->b_data, entry_in_block)) 458132751Skan DPRINTF(TRANSLATE, ("\tvblk %#jx -> %#jx for cp [%#jx-%#jx]\n", 45996340Sobrien (uintmax_t)vblocknr, (uintmax_t)entry->de_blocknr, 460132751Skan (uintmax_t)entry->de_start, (uintmax_t)entry->de_end)); 461132751Skan 46296340Sobrien *pblocknr = entry->de_blocknr; 463132751Skan brelse(bp); 464132751Skan if (!locked) 46596340Sobrien VOP_UNLOCK(NTOV(dat_node), 0); 466132751Skan 467132751Skan MPASS(*pblocknr >= node->nn_nandfsdev->nd_fsdata.f_first_data_block || 46896340Sobrien *pblocknr == 0); 469132751Skan 470132751Skan return (0); 471117428Skan} 472132751Skan 473132751Skanint 47496340Sobriennandfs_segsum_valid(struct nandfs_segment_summary *segsum) 475132751Skan{ 476132751Skan 47796340Sobrien return (segsum->ss_magic == NANDFS_SEGSUM_MAGIC); 478132751Skan} 479132751Skan 48096340Sobrienint 481132751Skannandfs_load_segsum(struct nandfs_device *fsdev, nandfs_daddr_t blocknr, 482132751Skan struct nandfs_segment_summary *segsum) 48396340Sobrien{ 484132751Skan struct buf *bp; 485132751Skan int error; 48696340Sobrien 487132751Skan DPRINTF(VOLUMES, ("nandfs: try segsum at block %jx\n", 488132751Skan (uintmax_t)blocknr)); 48996340Sobrien 490132751Skan error = nandfs_dev_bread(fsdev, blocknr, NOCRED, 0, &bp); 491132751Skan if (error) 49296340Sobrien return (error); 493132751Skan 494132751Skan memcpy(segsum, bp->b_data, sizeof(struct nandfs_segment_summary)); 49596340Sobrien brelse(bp); 496132751Skan 497132751Skan if (!nandfs_segsum_valid(segsum)) { 49896340Sobrien DPRINTF(VOLUMES, ("%s: bad magic pseg:%jx\n", __func__, 499132751Skan blocknr)); 500132751Skan return (EINVAL); 50196340Sobrien } 502132751Skan 503132751Skan return (error); 50496340Sobrien} 505132751Skan 506132751Skanstatic int 50796340Sobriennandfs_load_super_root(struct nandfs_device *nandfsdev, 508132751Skan struct nandfs_segment_summary *segsum, uint64_t pseg) 509132751Skan{ 51096340Sobrien struct nandfs_super_root super_root; 511132751Skan struct buf *bp; 512132751Skan uint64_t blocknr; 513132751Skan uint32_t super_root_crc, comp_crc; 514132751Skan int off, error; 515132751Skan 516132751Skan /* Check if there is a superroot */ 517132751Skan if ((segsum->ss_flags & NANDFS_SS_SR) == 0) { 518132751Skan DPRINTF(VOLUMES, ("%s: no super root in pseg:%jx\n", __func__, 519132751Skan pseg)); 520132751Skan return (ENOENT); 521132751Skan } 522132751Skan 523132751Skan /* Get our super root, located at the end of the pseg */ 524132751Skan blocknr = pseg + segsum->ss_nblocks - 1; 525132751Skan DPRINTF(VOLUMES, ("%s: try at %#jx\n", __func__, (uintmax_t)blocknr)); 526132751Skan 527132751Skan error = nandfs_dev_bread(nandfsdev, blocknr, NOCRED, 0, &bp); 528132751Skan if (error) 529132751Skan return (error); 530132751Skan 531132751Skan memcpy(&super_root, bp->b_data, sizeof(struct nandfs_super_root)); 532132751Skan brelse(bp); 533132751Skan 534132751Skan /* Check super root CRC */ 535132751Skan super_root_crc = super_root.sr_sum; 536132751Skan off = sizeof(super_root.sr_sum); 537132751Skan comp_crc = crc32((uint8_t *)&super_root + off, 538132751Skan NANDFS_SR_BYTES - off); 539132751Skan 540132751Skan if (super_root_crc != comp_crc) { 541132751Skan DPRINTF(VOLUMES, ("%s: invalid crc:%#x [expect:%#x]\n", 542132751Skan __func__, super_root_crc, comp_crc)); 543132751Skan return (EINVAL); 544132751Skan } 545132751Skan 546132751Skan nandfsdev->nd_super_root = super_root; 547132751Skan DPRINTF(VOLUMES, ("%s: got valid superroot\n", __func__)); 548132751Skan 549132751Skan return (0); 550169718Skan} 551169718Skan 552169718Skan/* 553132751Skan * Search for the last super root recorded. 554132751Skan */ 555132751Skanint 556132751Skannandfs_search_super_root(struct nandfs_device *nandfsdev) 557132751Skan{ 558132751Skan struct nandfs_super_block *super; 559132751Skan struct nandfs_segment_summary segsum; 560132751Skan uint64_t seg_start, seg_end, cno, seq, create, pseg; 561132751Skan uint64_t segnum; 562132751Skan int error, found; 563132751Skan 564132751Skan error = found = 0; 565132751Skan 566132751Skan /* Search for last super root */ 567132751Skan pseg = nandfsdev->nd_super.s_last_pseg; 568132751Skan segnum = nandfs_get_segnum_of_block(nandfsdev, pseg); 569132751Skan 570132751Skan cno = nandfsdev->nd_super.s_last_cno; 571132751Skan create = seq = 0; 572132751Skan DPRINTF(VOLUMES, ("%s: start in pseg %#jx\n", __func__, 573132751Skan (uintmax_t)pseg)); 574132751Skan 575132751Skan for (;;) { 576132751Skan error = nandfs_load_segsum(nandfsdev, pseg, &segsum); 577132751Skan if (error) 578132751Skan break; 579132751Skan 580132751Skan if (segsum.ss_seq < seq || segsum.ss_create < create) 581132751Skan break; 582132751Skan 583132751Skan /* Try to load super root */ 584132751Skan if (segsum.ss_flags & NANDFS_SS_SR) { 585132751Skan error = nandfs_load_super_root(nandfsdev, &segsum, pseg); 586132751Skan if (error) 587132751Skan break; /* confused */ 588132751Skan found = 1; 589132751Skan 590132751Skan super = &nandfsdev->nd_super; 591132751Skan nandfsdev->nd_last_segsum = segsum; 592132751Skan super->s_last_pseg = pseg; 593132751Skan super->s_last_cno = cno++; 594132751Skan super->s_last_seq = segsum.ss_seq; 595132751Skan super->s_state = NANDFS_VALID_FS; 596132751Skan seq = segsum.ss_seq; 597132751Skan create = segsum.ss_create; 598132751Skan } else { 599132751Skan seq = segsum.ss_seq; 600132751Skan create = segsum.ss_create; 601132751Skan } 602132751Skan 603132751Skan /* Calculate next partial segment location */ 604132751Skan pseg += segsum.ss_nblocks; 605132751Skan DPRINTF(VOLUMES, ("%s: next partial seg is %jx\n", __func__, 606132751Skan (uintmax_t)pseg)); 607169718Skan 608169718Skan /* Did we reach the end of the segment? if so, go to the next */ 609169718Skan nandfs_get_segment_range(nandfsdev, segnum, &seg_start, 610169718Skan &seg_end); 611169718Skan if (pseg >= seg_end) { 612169718Skan pseg = segsum.ss_next; 613169718Skan DPRINTF(VOLUMES, 614169718Skan (" partial seg oor next is %jx[%jx - %jx]\n", 615169718Skan (uintmax_t)pseg, (uintmax_t)seg_start, 616169718Skan (uintmax_t)seg_end)); 617169718Skan } 618169718Skan segnum = nandfs_get_segnum_of_block(nandfsdev, pseg); 619169718Skan } 620169718Skan 621169718Skan if (error && !found) 622169718Skan return (error); 623169718Skan 624169718Skan return (0); 625169718Skan} 626169718Skan 627169718Skanint 628169718Skannandfs_get_node_raw(struct nandfs_device *nandfsdev, struct nandfsmount *nmp, 629169718Skan uint64_t ino, struct nandfs_inode *inode, struct nandfs_node **nodep) 630169718Skan{ 631169718Skan struct nandfs_node *node; 632169718Skan struct vnode *nvp; 633169718Skan struct mount *mp; 634169718Skan int error; 635169718Skan 636169718Skan *nodep = NULL; 637169718Skan 638169718Skan /* Associate with mountpoint if present */ 639169718Skan if (nmp) { 640169718Skan mp = nmp->nm_vfs_mountp; 641169718Skan error = getnewvnode("nandfs", mp, &nandfs_vnodeops, &nvp); 642169718Skan if (error) { 643169718Skan return (error); 644169718Skan } 645169718Skan } else { 646169718Skan mp = NULL; 647169718Skan error = getnewvnode("snandfs", mp, &nandfs_system_vnodeops, 648169718Skan &nvp); 649132751Skan if (error) { 650132751Skan return (error); 651132751Skan } 652132751Skan } 653140864Skan 654132751Skan if (mp) 655132751Skan NANDFS_WRITELOCK(nandfsdev); 656140864Skan 657132751Skan DPRINTF(IFILE, ("%s: ino: %#jx -> vp: %p\n", 658169718Skan __func__, (uintmax_t)ino, nvp)); 659169718Skan /* Lock node */ 660169718Skan lockmgr(nvp->v_vnlock, LK_EXCLUSIVE, NULL); 661132751Skan 662132751Skan if (mp) { 663132751Skan error = insmntque(nvp, mp); 664132751Skan if (error != 0) { 665132751Skan *nodep = NULL; 666132751Skan return (error); 667132751Skan } 668132751Skan } 669132751Skan 670132751Skan node = uma_zalloc(nandfs_node_zone, M_WAITOK | M_ZERO); 671132751Skan 672132751Skan /* Crosslink */ 673132751Skan node->nn_vnode = nvp; 674132751Skan nvp->v_bufobj.bo_ops = &buf_ops_nandfs; 675132751Skan node->nn_nmp = nmp; 676132751Skan node->nn_nandfsdev = nandfsdev; 677132751Skan nvp->v_data = node; 678132751Skan 679169718Skan /* Initiase NANDFS node */ 680169718Skan node->nn_ino = ino; 681169718Skan if (inode != NULL) 682169718Skan node->nn_inode = *inode; 683227215Sdim 684169718Skan nandfs_vinit(nvp, ino); 685169718Skan 686169718Skan /* Return node */ 687169718Skan *nodep = node; 688169718Skan DPRINTF(IFILE, ("%s: ino:%#jx vp:%p node:%p\n", 689169718Skan __func__, (uintmax_t)ino, nvp, *nodep)); 690169718Skan 691169718Skan return (0); 692169718Skan} 693132751Skan 694132751Skanint 695132751Skannandfs_get_node(struct nandfsmount *nmp, uint64_t ino, 696169718Skan struct nandfs_node **nodep) 697169718Skan{ 69896340Sobrien struct nandfs_device *nandfsdev; 699169718Skan struct nandfs_inode inode, *entry; 700169718Skan struct vnode *nvp, *vpp; 701169718Skan struct thread *td; 70296340Sobrien struct buf *bp; 70396340Sobrien uint64_t ivblocknr; 704169718Skan uint32_t entry_in_block; 705169718Skan int error; 70696340Sobrien 707169718Skan /* Look up node in hash table */ 708169718Skan td = curthread; 709169718Skan *nodep = NULL; 71096340Sobrien 71196340Sobrien if ((ino < NANDFS_ATIME_INO) && (ino != NANDFS_ROOT_INO)) { 712169718Skan printf("nandfs_get_node: system ino %"PRIu64" not in mount " 713169718Skan "point!\n", ino); 71496340Sobrien return (ENOENT); 715169718Skan } 716169718Skan 71796340Sobrien error = vfs_hash_get(nmp->nm_vfs_mountp, ino, LK_EXCLUSIVE, td, &nvp, 718169718Skan NULL, NULL); 719169718Skan if (error) 72096340Sobrien return (error); 721169718Skan 722169718Skan if (nvp != NULL) { 72396340Sobrien *nodep = (struct nandfs_node *)nvp->v_data; 724169718Skan return (0); 725169718Skan } 72696340Sobrien 727169718Skan /* Look up inode structure in mountpoints ifile */ 728169718Skan nandfsdev = nmp->nm_nandfsdev; 729169718Skan nandfs_mdt_trans(&nandfsdev->nd_ifile_mdt, ino, &ivblocknr, 730169718Skan &entry_in_block); 731169718Skan 732169718Skan VOP_LOCK(NTOV(nmp->nm_ifile_node), LK_SHARED); 733169718Skan error = nandfs_bread(nmp->nm_ifile_node, ivblocknr, NOCRED, 0, &bp); 734169718Skan if (error) { 735169718Skan brelse(bp); 736169718Skan VOP_UNLOCK(NTOV(nmp->nm_ifile_node), 0); 737169718Skan return (ENOENT); 738169718Skan } 739169718Skan 740169718Skan /* Get inode entry */ 741169718Skan entry = (struct nandfs_inode *) bp->b_data + entry_in_block; 742169718Skan memcpy(&inode, entry, sizeof(struct nandfs_inode)); 743169718Skan brelse(bp); 744169718Skan VOP_UNLOCK(NTOV(nmp->nm_ifile_node), 0); 745169718Skan 746169718Skan /* Get node */ 747169718Skan error = nandfs_get_node_raw(nmp->nm_nandfsdev, nmp, ino, &inode, nodep); 748169718Skan if (error) { 749169718Skan *nodep = NULL; 750169718Skan return (error); 751169718Skan } 752169718Skan 753169718Skan nvp = (*nodep)->nn_vnode; 754169718Skan error = vfs_hash_insert(nvp, ino, 0, td, &vpp, NULL, NULL); 755169718Skan if (error) { 756169718Skan *nodep = NULL; 757169718Skan return (error); 758169718Skan } 759169718Skan 760169718Skan return (error); 761169718Skan} 762169718Skan 763169718Skanvoid 764169718Skannandfs_dispose_node(struct nandfs_node **nodep) 765169718Skan{ 766169718Skan struct nandfs_node *node; 767169718Skan struct vnode *vp; 768169718Skan 769169718Skan /* Protect against rogue values */ 770169718Skan node = *nodep; 771169718Skan if (!node) { 772169718Skan return; 773169718Skan } 774169718Skan DPRINTF(NODE, ("nandfs_dispose_node: %p\n", *nodep)); 775169718Skan 776169718Skan vp = NTOV(node); 777169718Skan vp->v_data = NULL; 778169718Skan 779169718Skan /* Free our associated memory */ 780169718Skan uma_zfree(nandfs_node_zone, node); 781169718Skan 782169718Skan *nodep = NULL; 783169718Skan} 78496340Sobrien 78596340Sobrienint 78696340Sobriennandfs_lookup_name_in_dir(struct vnode *dvp, const char *name, int namelen, 78796340Sobrien uint64_t *ino, int *found, uint64_t *off) 78896340Sobrien{ 78996340Sobrien struct nandfs_node *dir_node = VTON(dvp); 79096340Sobrien struct nandfs_dir_entry *ndirent; 79196340Sobrien struct buf *bp; 79296340Sobrien uint64_t file_size, diroffset, blkoff; 79396340Sobrien uint64_t blocknr; 79496340Sobrien uint32_t blocksize = dir_node->nn_nandfsdev->nd_blocksize; 79596340Sobrien uint8_t *pos, name_len; 79696340Sobrien int error; 79796340Sobrien 79896340Sobrien *found = 0; 79996340Sobrien 80096340Sobrien DPRINTF(VNCALL, ("%s: %s file\n", __func__, name)); 80196340Sobrien if (dvp->v_type != VDIR) { 80296340Sobrien return (ENOTDIR); 80396340Sobrien } 804169718Skan 805169718Skan /* Get directory filesize */ 806169718Skan file_size = dir_node->nn_inode.i_size; 807169718Skan 808169718Skan /* Walk the directory */ 809169718Skan diroffset = 0; 810169718Skan blocknr = 0; 811169718Skan blkoff = 0; 812169718Skan error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp); 813169718Skan if (error) { 81496340Sobrien brelse(bp); 81596340Sobrien return (EIO); 81696340Sobrien } 81796340Sobrien 81896340Sobrien while (diroffset < file_size) { 81996340Sobrien if (blkoff >= blocksize) { 82096340Sobrien blkoff = 0; blocknr++; 82196340Sobrien brelse(bp); 82296340Sobrien error = nandfs_bread(dir_node, blocknr, NOCRED, 0, 82396340Sobrien &bp); 82496340Sobrien if (error) { 82596340Sobrien brelse(bp); 826169718Skan return (EIO); 82796340Sobrien } 82896340Sobrien } 82996340Sobrien 83096340Sobrien /* Read in one dirent */ 831169718Skan pos = (uint8_t *) bp->b_data + blkoff; 83296340Sobrien ndirent = (struct nandfs_dir_entry *) pos; 83396340Sobrien name_len = ndirent->name_len; 834169718Skan 835169718Skan if ((name_len == namelen) && 836169718Skan (strncmp(name, ndirent->name, name_len) == 0) && 83796340Sobrien (ndirent->inode != 0)) { 83896340Sobrien *ino = ndirent->inode; 839169718Skan *off = diroffset; 840169718Skan DPRINTF(LOOKUP, ("found `%.*s` with ino %"PRIx64"\n", 841169718Skan name_len, ndirent->name, *ino)); 84296340Sobrien *found = 1; 84396340Sobrien break; 844169718Skan } 845169718Skan 846169718Skan /* Advance */ 84796340Sobrien diroffset += ndirent->rec_len; 84896340Sobrien blkoff += ndirent->rec_len; 849169718Skan } 850169718Skan brelse(bp); 851169718Skan 852169718Skan return (error); 853169718Skan} 85496340Sobrien 85596340Sobrienint 85696340Sobriennandfs_get_fsinfo(struct nandfsmount *nmp, struct nandfs_fsinfo *fsinfo) 85796340Sobrien{ 85896340Sobrien struct nandfs_device *fsdev; 859169718Skan 860169718Skan fsdev = nmp->nm_nandfsdev; 861169718Skan 862169718Skan memcpy(&fsinfo->fs_fsdata, &fsdev->nd_fsdata, sizeof(fsdev->nd_fsdata)); 863169718Skan memcpy(&fsinfo->fs_super, &fsdev->nd_super, sizeof(fsdev->nd_super)); 86496340Sobrien snprintf(fsinfo->fs_dev, sizeof(fsinfo->fs_dev), 86596340Sobrien "%s", nmp->nm_vfs_mountp->mnt_stat.f_mntfromname); 86696340Sobrien 86796340Sobrien return (0); 86896340Sobrien} 86996340Sobrien 87096340Sobrienvoid 87196340Sobriennandfs_inode_init(struct nandfs_inode *inode, uint16_t mode) 87296340Sobrien{ 87396340Sobrien struct timespec ts; 87496340Sobrien 87596340Sobrien vfs_timestamp(&ts); 87696340Sobrien 87796340Sobrien inode->i_blocks = 0; 87896340Sobrien inode->i_size = 0; 87996340Sobrien inode->i_ctime = ts.tv_sec; 88096340Sobrien inode->i_ctime_nsec = ts.tv_nsec; 88196340Sobrien inode->i_mtime = ts.tv_sec; 88296340Sobrien inode->i_mtime_nsec = ts.tv_nsec; 88396340Sobrien inode->i_mode = mode; 884169718Skan inode->i_links_count = 1; 885169718Skan if (S_ISDIR(mode)) 886169718Skan inode->i_links_count = 2; 887169718Skan inode->i_flags = 0; 888169718Skan 889169718Skan inode->i_special = 0; 890169718Skan memset(inode->i_db, 0, sizeof(inode->i_db)); 891169718Skan memset(inode->i_ib, 0, sizeof(inode->i_ib)); 892169718Skan} 893169718Skan 894169718Skanvoid 895169718Skannandfs_inode_destroy(struct nandfs_inode *inode) 896169718Skan{ 897169718Skan 898169718Skan MPASS(inode->i_blocks == 0); 89996340Sobrien bzero(inode, sizeof(*inode)); 90096340Sobrien} 90196340Sobrien 90296340Sobrienint 90396340Sobriennandfs_fs_full(struct nandfs_device *nffsdev) 90496340Sobrien{ 90596340Sobrien uint64_t space, bps; 90696340Sobrien 90796340Sobrien bps = nffsdev->nd_fsdata.f_blocks_per_segment; 90896340Sobrien space = (nffsdev->nd_clean_segs - 1) * bps; 90996340Sobrien 91096340Sobrien DPRINTF(BUF, ("%s: bufs:%jx space:%jx\n", __func__, 91196340Sobrien (uintmax_t)nffsdev->nd_dirty_bufs, (uintmax_t)space)); 91296340Sobrien 91396340Sobrien if (nffsdev->nd_dirty_bufs + (nffsdev->nd_segs_reserved * bps) >= space) 91496340Sobrien return (1); 91596340Sobrien 91696340Sobrien return (0); 91796340Sobrien} 91896340Sobrien 919169718Skanstatic int 920169718Skan_nandfs_dirty_buf(struct buf *bp, int dirty_meta, int force) 921169718Skan{ 922169718Skan struct nandfs_device *nffsdev; 923169718Skan struct nandfs_node *node; 92496340Sobrien uint64_t ino, bps; 92596340Sobrien 92696340Sobrien if (NANDFS_ISGATHERED(bp)) { 92796340Sobrien bqrelse(bp); 92896340Sobrien return (0); 92996340Sobrien } 93096340Sobrien if ((bp->b_flags & (B_MANAGED | B_DELWRI)) == (B_MANAGED | B_DELWRI)) { 93196340Sobrien bqrelse(bp); 93296340Sobrien return (0); 93396340Sobrien } 934169718Skan 935169718Skan node = VTON(bp->b_vp); 936169718Skan nffsdev = node->nn_nandfsdev; 937169718Skan DPRINTF(BUF, ("%s: buf:%p\n", __func__, bp)); 938169718Skan ino = node->nn_ino; 939169718Skan 940169718Skan if (nandfs_fs_full(nffsdev) && !NANDFS_SYS_NODE(ino) && !force) { 941169718Skan brelse(bp); 942169718Skan return (ENOSPC); 943169718Skan } 944169718Skan 945169718Skan bp->b_flags |= B_MANAGED; 946169718Skan bdwrite(bp); 947169718Skan 948169718Skan nandfs_dirty_bufs_increment(nffsdev); 949169718Skan 950169718Skan KASSERT((bp->b_vp), ("vp missing for bp")); 951169718Skan KASSERT((nandfs_vblk_get(bp) || ino == NANDFS_DAT_INO), 952169718Skan ("bp vblk is 0")); 953169718Skan 954169718Skan /* 955169718Skan * To maintain consistency of FS we need to force making 956169718Skan * meta buffers dirty, even if free space is low. 957169718Skan */ 958169718Skan if (dirty_meta && ino != NANDFS_GC_INO) 959169718Skan nandfs_bmap_dirty_blocks(VTON(bp->b_vp), bp, 1); 960169718Skan 961169718Skan bps = nffsdev->nd_fsdata.f_blocks_per_segment; 962169718Skan 963169718Skan if (nffsdev->nd_dirty_bufs >= (bps * nandfs_max_dirty_segs)) { 964169718Skan mtx_lock(&nffsdev->nd_sync_mtx); 965169718Skan if (nffsdev->nd_syncing == 0) { 966169718Skan DPRINTF(SYNC, ("%s: wakeup gc\n", __func__)); 967169718Skan nffsdev->nd_syncing = 1; 968169718Skan wakeup(&nffsdev->nd_syncing); 969169718Skan } 970169718Skan mtx_unlock(&nffsdev->nd_sync_mtx); 971169718Skan } 972169718Skan 973169718Skan return (0); 974169718Skan} 975169718Skan 976169718Skanint 977169718Skannandfs_dirty_buf(struct buf *bp, int force) 978169718Skan{ 97996340Sobrien 98096340Sobrien return (_nandfs_dirty_buf(bp, 1, force)); 98196340Sobrien} 98296340Sobrien 98396340Sobrienint 98496340Sobriennandfs_dirty_buf_meta(struct buf *bp, int force) 98596340Sobrien{ 98696340Sobrien 98796340Sobrien return (_nandfs_dirty_buf(bp, 0, force)); 98896340Sobrien} 98996340Sobrien 99096340Sobrienvoid 99196340Sobriennandfs_undirty_buf_fsdev(struct nandfs_device *nffsdev, struct buf *bp) 99296340Sobrien{ 99396340Sobrien 994169718Skan BUF_ASSERT_HELD(bp); 995169718Skan 996169718Skan if (bp->b_flags & B_DELWRI) { 997169718Skan bp->b_flags &= ~(B_DELWRI|B_MANAGED); 998169718Skan nandfs_dirty_bufs_decrement(nffsdev); 999169718Skan } 1000169718Skan /* 1001169718Skan * Since it is now being written, we can clear its deferred write flag. 1002169718Skan */ 1003169718Skan bp->b_flags &= ~B_DEFERRED; 100496340Sobrien 100596340Sobrien brelse(bp); 100696340Sobrien} 100796340Sobrien 100896340Sobrienvoid 1009169718Skannandfs_undirty_buf(struct buf *bp) 1010169718Skan{ 1011169718Skan struct nandfs_node *node; 1012169718Skan 1013169718Skan node = VTON(bp->b_vp); 1014169718Skan 1015169718Skan nandfs_undirty_buf_fsdev(node->nn_nandfsdev, bp); 1016169718Skan} 1017169718Skan 1018169718Skanvoid 1019169718Skannandfs_vblk_set(struct buf *bp, nandfs_daddr_t blocknr) 1020169718Skan{ 1021169718Skan 1022169718Skan nandfs_daddr_t *vblk = (nandfs_daddr_t *)(&bp->b_fsprivate1); 1023169718Skan *vblk = blocknr; 102496340Sobrien} 102596340Sobrien 102696340Sobriennandfs_daddr_t 102796340Sobriennandfs_vblk_get(struct buf *bp) 102896340Sobrien{ 1029169718Skan 1030169718Skan nandfs_daddr_t *vblk = (nandfs_daddr_t *)(&bp->b_fsprivate1); 1031169718Skan return (*vblk); 103296340Sobrien} 103396340Sobrien 1034169718Skanvoid 1035169718Skannandfs_buf_set(struct buf *bp, uint32_t bits) 1036169718Skan{ 103796340Sobrien uintptr_t flags; 103896340Sobrien 1039169718Skan flags = (uintptr_t)bp->b_fsprivate3; 1040169718Skan flags |= (uintptr_t)bits; 1041169718Skan bp->b_fsprivate3 = (void *)flags; 104296340Sobrien} 104396340Sobrien 1044169718Skanvoid 1045169718Skannandfs_buf_clear(struct buf *bp, uint32_t bits) 1046169718Skan{ 1047169718Skan uintptr_t flags; 1048169718Skan 1049169718Skan flags = (uintptr_t)bp->b_fsprivate3; 1050169718Skan flags &= ~(uintptr_t)bits; 1051169718Skan bp->b_fsprivate3 = (void *)flags; 1052169718Skan} 1053169718Skan 105496340Sobrienint 105596340Sobriennandfs_buf_check(struct buf *bp, uint32_t bits) 105696340Sobrien{ 105796340Sobrien uintptr_t flags; 105896340Sobrien 105996340Sobrien flags = (uintptr_t)bp->b_fsprivate3; 106096340Sobrien if (flags & bits) 106196340Sobrien return (1); 106296340Sobrien return (0); 106396340Sobrien} 1064169718Skan 1065169718Skanint 1066169718Skannandfs_erase(struct nandfs_device *fsdev, off_t offset, size_t size) 1067169718Skan{ 1068169718Skan struct buf *bp; 106996340Sobrien int read_size, error, i; 107096340Sobrien 107196340Sobrien DPRINTF(BLOCK, ("%s: performing erase at offset %jx size %zx\n", 107296340Sobrien __func__, offset, size)); 107396340Sobrien 107496340Sobrien MPASS(size % fsdev->nd_erasesize == 0); 107596340Sobrien 107696340Sobrien if (fsdev->nd_is_nand) { 107796340Sobrien error = g_delete_data(fsdev->nd_gconsumer, offset, size); 107896340Sobrien return (error); 107996340Sobrien } 108096340Sobrien 108196340Sobrien if (size > MAXBSIZE) 108296340Sobrien read_size = MAXBSIZE; 108396340Sobrien else 108496340Sobrien read_size = size; 108596340Sobrien 108696340Sobrien error = 0; 108796340Sobrien for (i = 0; i < size / MAXBSIZE; i++) { 108896340Sobrien error = bread(fsdev->nd_devvp, btodb(offset + i * read_size), 108996340Sobrien read_size, NOCRED, &bp); 109096340Sobrien if (error) { 109196340Sobrien brelse(bp); 109296340Sobrien return (error); 109396340Sobrien } 1094169718Skan memset(bp->b_data, 0xff, read_size); 1095169718Skan error = bwrite(bp); 1096169718Skan if (error) { 109796340Sobrien nandfs_error("%s: err:%d from bwrite\n", 109896340Sobrien __func__, error); 1099169718Skan return (error); 1100169718Skan } 1101169718Skan } 110296340Sobrien 110396340Sobrien return (error); 1104169718Skan} 1105169718Skan 1106169718Skanint 110796340Sobriennandfs_vop_islocked(struct vnode *vp) 110896340Sobrien{ 1109169718Skan int islocked; 1110169718Skan 1111169718Skan islocked = VOP_ISLOCKED(vp); 111296340Sobrien return (islocked == LK_EXCLUSIVE || islocked == LK_SHARED); 1113} 1114 1115nandfs_daddr_t 1116nandfs_block_to_dblock(struct nandfs_device *fsdev, nandfs_lbn_t block) 1117{ 1118 1119 return (btodb(block * fsdev->nd_blocksize)); 1120} 1121