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