Home | History | Annotate | Line # | Download | only in nilfs
nilfs_subr.c revision 1.4.2.2
      1  1.4.2.2  yamt /* $NetBSD: nilfs_subr.c,v 1.4.2.2 2009/08/19 18:48:14 yamt Exp $ */
      2  1.4.2.2  yamt 
      3  1.4.2.2  yamt /*
      4  1.4.2.2  yamt  * Copyright (c) 2008, 2009 Reinoud Zandijk
      5  1.4.2.2  yamt  * All rights reserved.
      6  1.4.2.2  yamt  *
      7  1.4.2.2  yamt  * Redistribution and use in source and binary forms, with or without
      8  1.4.2.2  yamt  * modification, are permitted provided that the following conditions
      9  1.4.2.2  yamt  * are met:
     10  1.4.2.2  yamt  * 1. Redistributions of source code must retain the above copyright
     11  1.4.2.2  yamt  *    notice, this list of conditions and the following disclaimer.
     12  1.4.2.2  yamt  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.4.2.2  yamt  *    notice, this list of conditions and the following disclaimer in the
     14  1.4.2.2  yamt  *    documentation and/or other materials provided with the distribution.
     15  1.4.2.2  yamt  *
     16  1.4.2.2  yamt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  1.4.2.2  yamt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  1.4.2.2  yamt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  1.4.2.2  yamt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  1.4.2.2  yamt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  1.4.2.2  yamt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  1.4.2.2  yamt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  1.4.2.2  yamt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  1.4.2.2  yamt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  1.4.2.2  yamt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  1.4.2.2  yamt  *
     27  1.4.2.2  yamt  */
     28  1.4.2.2  yamt 
     29  1.4.2.2  yamt #include <sys/cdefs.h>
     30  1.4.2.2  yamt #ifndef lint
     31  1.4.2.2  yamt __KERNEL_RCSID(0, "$NetBSD: nilfs_subr.c,v 1.4.2.2 2009/08/19 18:48:14 yamt Exp $");
     32  1.4.2.2  yamt #endif /* not lint */
     33  1.4.2.2  yamt 
     34  1.4.2.2  yamt #include <sys/param.h>
     35  1.4.2.2  yamt #include <sys/systm.h>
     36  1.4.2.2  yamt #include <sys/namei.h>
     37  1.4.2.2  yamt #include <sys/resourcevar.h>	/* defines plimit structure in proc struct */
     38  1.4.2.2  yamt #include <sys/kernel.h>
     39  1.4.2.2  yamt #include <sys/file.h>		/* define FWRITE ... */
     40  1.4.2.2  yamt #include <sys/stat.h>
     41  1.4.2.2  yamt #include <sys/buf.h>
     42  1.4.2.2  yamt #include <sys/proc.h>
     43  1.4.2.2  yamt #include <sys/mount.h>
     44  1.4.2.2  yamt #include <sys/vnode.h>
     45  1.4.2.2  yamt #include <sys/signalvar.h>
     46  1.4.2.2  yamt #include <sys/malloc.h>
     47  1.4.2.2  yamt #include <sys/dirent.h>
     48  1.4.2.2  yamt #include <sys/lockf.h>
     49  1.4.2.2  yamt #include <sys/kauth.h>
     50  1.4.2.2  yamt #include <sys/dirhash.h>
     51  1.4.2.2  yamt 
     52  1.4.2.2  yamt #include <miscfs/genfs/genfs.h>
     53  1.4.2.2  yamt #include <uvm/uvm_extern.h>
     54  1.4.2.2  yamt 
     55  1.4.2.2  yamt #include <fs/nilfs/nilfs_mount.h>
     56  1.4.2.2  yamt #include "nilfs.h"
     57  1.4.2.2  yamt #include "nilfs_subr.h"
     58  1.4.2.2  yamt #include "nilfs_bswap.h"
     59  1.4.2.2  yamt 
     60  1.4.2.2  yamt 
     61  1.4.2.2  yamt #define VTOI(vnode) ((struct nilfs_node *) (vnode)->v_data)
     62  1.4.2.2  yamt 
     63  1.4.2.2  yamt /* basic calculators */
     64  1.4.2.2  yamt uint64_t nilfs_get_segnum_of_block(struct nilfs_device *nilfsdev,
     65  1.4.2.2  yamt 	uint64_t blocknr)
     66  1.4.2.2  yamt {
     67  1.4.2.2  yamt 	return blocknr / nilfs_rw32(nilfsdev->super.s_blocks_per_segment);
     68  1.4.2.2  yamt }
     69  1.4.2.2  yamt 
     70  1.4.2.2  yamt 
     71  1.4.2.2  yamt void
     72  1.4.2.2  yamt nilfs_get_segment_range(struct nilfs_device *nilfsdev, uint64_t segnum,
     73  1.4.2.2  yamt         uint64_t *seg_start, uint64_t *seg_end)
     74  1.4.2.2  yamt {
     75  1.4.2.2  yamt         uint64_t blks_per_seg;
     76  1.4.2.2  yamt 
     77  1.4.2.2  yamt         blks_per_seg = nilfs_rw64(nilfsdev->super.s_blocks_per_segment);
     78  1.4.2.2  yamt         *seg_start = blks_per_seg * segnum;
     79  1.4.2.2  yamt         *seg_end   = *seg_start + blks_per_seg -1;
     80  1.4.2.2  yamt         if (segnum == 0)
     81  1.4.2.2  yamt                 *seg_start = nilfs_rw64(nilfsdev->super.s_first_data_block);
     82  1.4.2.2  yamt }
     83  1.4.2.2  yamt 
     84  1.4.2.2  yamt 
     85  1.4.2.2  yamt void nilfs_calc_mdt_consts(struct nilfs_device *nilfsdev,
     86  1.4.2.2  yamt 	struct nilfs_mdt *mdt, int entry_size)
     87  1.4.2.2  yamt {
     88  1.4.2.2  yamt 	uint32_t blocksize = nilfsdev->blocksize;
     89  1.4.2.2  yamt 
     90  1.4.2.2  yamt 	mdt->entries_per_group = blocksize * 8;	   /* bits in sector */
     91  1.4.2.2  yamt 	mdt->entries_per_block = blocksize / entry_size;
     92  1.4.2.2  yamt 
     93  1.4.2.2  yamt 	mdt->blocks_per_group  =
     94  1.4.2.2  yamt 		(mdt->entries_per_group -1) / mdt->entries_per_block + 1 + 1;
     95  1.4.2.2  yamt 	mdt->groups_per_desc_block =
     96  1.4.2.2  yamt 		blocksize / sizeof(struct nilfs_block_group_desc);
     97  1.4.2.2  yamt 	mdt->blocks_per_desc_block =
     98  1.4.2.2  yamt 		mdt->groups_per_desc_block * mdt->blocks_per_group + 1;
     99  1.4.2.2  yamt }
    100  1.4.2.2  yamt 
    101  1.4.2.2  yamt 
    102  1.4.2.2  yamt /* from NetBSD's src/sys/net/if_ethersubr.c */
    103  1.4.2.2  yamt uint32_t
    104  1.4.2.2  yamt crc32_le(uint32_t crc, const uint8_t *buf, size_t len)
    105  1.4.2.2  yamt {
    106  1.4.2.2  yamt         static const uint32_t crctab[] = {
    107  1.4.2.2  yamt                 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    108  1.4.2.2  yamt                 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    109  1.4.2.2  yamt                 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
    110  1.4.2.2  yamt                 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
    111  1.4.2.2  yamt         };
    112  1.4.2.2  yamt         size_t i;
    113  1.4.2.2  yamt 
    114  1.4.2.2  yamt         for (i = 0; i < len; i++) {
    115  1.4.2.2  yamt                 crc ^= buf[i];
    116  1.4.2.2  yamt                 crc = (crc >> 4) ^ crctab[crc & 0xf];
    117  1.4.2.2  yamt                 crc = (crc >> 4) ^ crctab[crc & 0xf];
    118  1.4.2.2  yamt         }
    119  1.4.2.2  yamt 
    120  1.4.2.2  yamt         return (crc);
    121  1.4.2.2  yamt }
    122  1.4.2.2  yamt 
    123  1.4.2.2  yamt 
    124  1.4.2.2  yamt static int
    125  1.4.2.2  yamt nilfs_calchash(uint64_t ino)
    126  1.4.2.2  yamt {
    127  1.4.2.2  yamt 	return (int) ino;
    128  1.4.2.2  yamt }
    129  1.4.2.2  yamt 
    130  1.4.2.2  yamt 
    131  1.4.2.2  yamt /* dev reading */
    132  1.4.2.2  yamt static int
    133  1.4.2.2  yamt nilfs_dev_bread(struct nilfs_device *nilfsdev, uint64_t blocknr,
    134  1.4.2.2  yamt 	struct kauth_cred *cred, int flags, struct buf **bpp)
    135  1.4.2.2  yamt {
    136  1.4.2.2  yamt 	int blk2dev = nilfsdev->blocksize / DEV_BSIZE;
    137  1.4.2.2  yamt 
    138  1.4.2.2  yamt 	return bread(nilfsdev->devvp, blocknr * blk2dev, nilfsdev->blocksize,
    139  1.4.2.2  yamt 		NOCRED, 0, bpp);
    140  1.4.2.2  yamt }
    141  1.4.2.2  yamt 
    142  1.4.2.2  yamt 
    143  1.4.2.2  yamt /* read on a node */
    144  1.4.2.2  yamt int
    145  1.4.2.2  yamt nilfs_bread(struct nilfs_node *node, uint64_t blocknr,
    146  1.4.2.2  yamt 	struct kauth_cred *cred, int flags, struct buf **bpp)
    147  1.4.2.2  yamt {
    148  1.4.2.2  yamt 	return bread(node->vnode, blocknr, node->nilfsdev->blocksize,
    149  1.4.2.2  yamt 		cred, flags, bpp);
    150  1.4.2.2  yamt }
    151  1.4.2.2  yamt 
    152  1.4.2.2  yamt 
    153  1.4.2.2  yamt /* segment-log reading */
    154  1.4.2.2  yamt int
    155  1.4.2.2  yamt nilfs_get_segment_log(struct nilfs_device *nilfsdev, uint64_t *blocknr,
    156  1.4.2.2  yamt 	uint64_t *offset, struct buf **bpp, int len, void *blob)
    157  1.4.2.2  yamt {
    158  1.4.2.2  yamt 	int blocksize = nilfsdev->blocksize;
    159  1.4.2.2  yamt 	int error;
    160  1.4.2.2  yamt 
    161  1.4.2.2  yamt 	KASSERT(len <= blocksize);
    162  1.4.2.2  yamt 
    163  1.4.2.2  yamt 	if (*offset + len > blocksize) {
    164  1.4.2.2  yamt 		*blocknr = *blocknr + 1;
    165  1.4.2.2  yamt 		*offset = 0;
    166  1.4.2.2  yamt 	}
    167  1.4.2.2  yamt 	if (*offset == 0) {
    168  1.4.2.2  yamt 		if (*bpp)
    169  1.4.2.2  yamt 			brelse(*bpp, BC_AGE);
    170  1.4.2.2  yamt 		/* read in block */
    171  1.4.2.2  yamt 		error = nilfs_dev_bread(nilfsdev, *blocknr, NOCRED, 0, bpp);
    172  1.4.2.2  yamt 		if (error)
    173  1.4.2.2  yamt 			return error;
    174  1.4.2.2  yamt 	}
    175  1.4.2.2  yamt 	memcpy(blob, ((uint8_t *) (*bpp)->b_data) + *offset, len);
    176  1.4.2.2  yamt 	*offset += len;
    177  1.4.2.2  yamt 
    178  1.4.2.2  yamt 	return 0;
    179  1.4.2.2  yamt }
    180  1.4.2.2  yamt 
    181  1.4.2.2  yamt /* -------------------------------------------------------------------------- */
    182  1.4.2.2  yamt 
    183  1.4.2.2  yamt /* btree operations */
    184  1.4.2.2  yamt 
    185  1.4.2.2  yamt static int
    186  1.4.2.2  yamt nilfs_btree_lookup_level(struct nilfs_node *node, uint64_t lblocknr,
    187  1.4.2.2  yamt 		uint64_t btree_vblknr, int level, uint64_t *vblocknr)
    188  1.4.2.2  yamt {
    189  1.4.2.2  yamt 	struct nilfs_device *nilfsdev = node->nilfsdev;
    190  1.4.2.2  yamt 	struct nilfs_btree_node *btree_hdr;
    191  1.4.2.2  yamt 	struct buf *bp;
    192  1.4.2.2  yamt 	uint64_t btree_blknr;
    193  1.4.2.2  yamt 	uint64_t *dkeys, *dptrs, child_btree_blk;
    194  1.4.2.2  yamt 	uint8_t  *pos;
    195  1.4.2.2  yamt 	int i, error, selected;
    196  1.4.2.2  yamt 
    197  1.4.2.2  yamt 	DPRINTF(TRANSLATE, ("nilfs_btree_lookup_level ino %"PRIu64", "
    198  1.4.2.2  yamt 		"lblocknr %"PRIu64", btree_vblknr %"PRIu64", level %d\n",
    199  1.4.2.2  yamt 		node->ino, lblocknr, btree_vblknr, level));
    200  1.4.2.2  yamt 
    201  1.4.2.2  yamt 	/* translate btree_vblknr */
    202  1.4.2.2  yamt 	error = nilfs_nvtop(node, 1, &btree_vblknr, &btree_blknr);
    203  1.4.2.2  yamt 	if (error)
    204  1.4.2.2  yamt 		return error;
    205  1.4.2.2  yamt 
    206  1.4.2.2  yamt 	/* get our block */
    207  1.4.2.2  yamt 	error = nilfs_dev_bread(nilfsdev, btree_blknr, NOCRED, 0, &bp);
    208  1.4.2.2  yamt 	if (error) {
    209  1.4.2.2  yamt 		brelse(bp, BC_AGE);
    210  1.4.2.2  yamt 		return error;
    211  1.4.2.2  yamt 	}
    212  1.4.2.2  yamt 
    213  1.4.2.2  yamt 	btree_hdr = (struct nilfs_btree_node *) bp->b_data;
    214  1.4.2.2  yamt 	pos =   (uint8_t *) bp->b_data +
    215  1.4.2.2  yamt 		sizeof(struct nilfs_btree_node) +
    216  1.4.2.2  yamt 		NILFS_BTREE_NODE_EXTRA_PAD_SIZE;
    217  1.4.2.2  yamt 	dkeys = (uint64_t *) pos;
    218  1.4.2.2  yamt 	dptrs = dkeys + NILFS_BTREE_NODE_NCHILDREN_MAX(nilfsdev->blocksize);
    219  1.4.2.2  yamt 
    220  1.4.2.2  yamt 	assert((btree_hdr->bn_flags & NILFS_BTREE_NODE_ROOT) == 0);
    221  1.4.2.2  yamt 
    222  1.4.2.2  yamt 	/* select matching child XXX could use binary search */
    223  1.4.2.2  yamt 	selected = 0;
    224  1.4.2.2  yamt 	for (i = 0; i < nilfs_rw16(btree_hdr->bn_nchildren); i++) {
    225  1.4.2.2  yamt 		if (dkeys[i] > lblocknr)
    226  1.4.2.2  yamt 			break;
    227  1.4.2.2  yamt 		selected = i;
    228  1.4.2.2  yamt 	}
    229  1.4.2.2  yamt 
    230  1.4.2.2  yamt 	if (level == 1) {
    231  1.4.2.2  yamt 		/* if found it mapped */
    232  1.4.2.2  yamt 		if (dkeys[selected] == lblocknr)
    233  1.4.2.2  yamt 			*vblocknr = dptrs[selected];
    234  1.4.2.2  yamt 		brelse(bp, BC_AGE);
    235  1.4.2.2  yamt 		return 0;
    236  1.4.2.2  yamt 	}
    237  1.4.2.2  yamt 
    238  1.4.2.2  yamt 	/* lookup in selected child */
    239  1.4.2.2  yamt 	assert(dkeys[selected] <= lblocknr);
    240  1.4.2.2  yamt 	child_btree_blk = dptrs[selected];
    241  1.4.2.2  yamt 	brelse(bp, BC_AGE);
    242  1.4.2.2  yamt 
    243  1.4.2.2  yamt 	return nilfs_btree_lookup_level(node, lblocknr,
    244  1.4.2.2  yamt 			child_btree_blk, btree_hdr->bn_level-1, vblocknr);
    245  1.4.2.2  yamt }
    246  1.4.2.2  yamt 
    247  1.4.2.2  yamt 
    248  1.4.2.2  yamt /* internal function */
    249  1.4.2.2  yamt static int
    250  1.4.2.2  yamt nilfs_btree_lookup(struct nilfs_node *node, uint64_t lblocknr,
    251  1.4.2.2  yamt 		uint64_t *vblocknr)
    252  1.4.2.2  yamt {
    253  1.4.2.2  yamt 	struct nilfs_inode  *inode    = &node->inode;
    254  1.4.2.2  yamt 	struct nilfs_btree_node  *btree_hdr;
    255  1.4.2.2  yamt 	uint64_t *dkeys, *dptrs, *dtrans;
    256  1.4.2.2  yamt 	int i, selected;
    257  1.4.2.2  yamt 	int error;
    258  1.4.2.2  yamt 
    259  1.4.2.2  yamt 	DPRINTF(TRANSLATE, ("nilfs_btree_lookup ino %"PRIu64", "
    260  1.4.2.2  yamt 		"lblocknr %"PRIu64"\n", node->ino, lblocknr));
    261  1.4.2.2  yamt 
    262  1.4.2.2  yamt 	btree_hdr  = (struct nilfs_btree_node *) &inode->i_bmap[0];
    263  1.4.2.2  yamt 	dkeys  = &inode->i_bmap[1];
    264  1.4.2.2  yamt 	dptrs  = dkeys + NILFS_BTREE_ROOT_NCHILDREN_MAX;
    265  1.4.2.2  yamt 	dtrans = &inode->i_bmap[1];
    266  1.4.2.2  yamt 
    267  1.4.2.2  yamt 	/* SMALL, direct lookup */
    268  1.4.2.2  yamt 	*vblocknr = 0;
    269  1.4.2.2  yamt 	if ((btree_hdr->bn_flags & NILFS_BMAP_LARGE) == 0) {
    270  1.4.2.2  yamt 		if (lblocknr < NILFS_DIRECT_NBLOCKS) {
    271  1.4.2.2  yamt 			*vblocknr = dtrans[lblocknr];
    272  1.4.2.2  yamt 			return 0;
    273  1.4.2.2  yamt 		}
    274  1.4.2.2  yamt 		/* not mapped XXX could be considered error here */
    275  1.4.2.2  yamt 		return 0;
    276  1.4.2.2  yamt 	}
    277  1.4.2.2  yamt 
    278  1.4.2.2  yamt 	/* LARGE, select matching child; XXX could use binary search */
    279  1.4.2.2  yamt 	dtrans = NULL;
    280  1.4.2.2  yamt 	error = 0;
    281  1.4.2.2  yamt 	selected = 0;
    282  1.4.2.2  yamt 	for (i = 0; i < nilfs_rw16(btree_hdr->bn_nchildren); i++) {
    283  1.4.2.2  yamt 		if (dkeys[i] > lblocknr)
    284  1.4.2.2  yamt 			break;
    285  1.4.2.2  yamt 		selected = i;
    286  1.4.2.2  yamt 	}
    287  1.4.2.2  yamt 
    288  1.4.2.2  yamt 	/* if selected key > lblocknr, its not mapped */
    289  1.4.2.2  yamt 	if (dkeys[selected] > lblocknr)
    290  1.4.2.2  yamt 		return 0;
    291  1.4.2.2  yamt 
    292  1.4.2.2  yamt 	/* overshooting? then not mapped */
    293  1.4.2.2  yamt 	if (selected == nilfs_rw16(btree_hdr->bn_nchildren))
    294  1.4.2.2  yamt 		return 0;
    295  1.4.2.2  yamt 
    296  1.4.2.2  yamt 	/* level should be > 1 or otherwise it should be a direct one */
    297  1.4.2.2  yamt 	assert(btree_hdr->bn_level > 1);
    298  1.4.2.2  yamt 
    299  1.4.2.2  yamt 	/* lookup in selected child */
    300  1.4.2.2  yamt 	assert(dkeys[selected] <= lblocknr);
    301  1.4.2.2  yamt 	error = nilfs_btree_lookup_level(node, lblocknr,
    302  1.4.2.2  yamt 			dptrs[selected], btree_hdr->bn_level-1, vblocknr);
    303  1.4.2.2  yamt 
    304  1.4.2.2  yamt 	return error;
    305  1.4.2.2  yamt }
    306  1.4.2.2  yamt 
    307  1.4.2.2  yamt 
    308  1.4.2.2  yamt /* node should be locked on entry to prevent btree changes (unlikely) */
    309  1.4.2.2  yamt int
    310  1.4.2.2  yamt nilfs_btree_nlookup(struct nilfs_node *node, uint64_t from, uint64_t blks,
    311  1.4.2.2  yamt 		uint64_t *l2vmap)
    312  1.4.2.2  yamt {
    313  1.4.2.2  yamt 	uint64_t lblocknr, *vblocknr;
    314  1.4.2.2  yamt 	int i, error;
    315  1.4.2.2  yamt 
    316  1.4.2.2  yamt 	/* TODO / OPTI multiple translations in one go possible */
    317  1.4.2.2  yamt 	error = EINVAL;
    318  1.4.2.2  yamt 	for (i = 0; i < blks; i++) {
    319  1.4.2.2  yamt 		lblocknr  = from + i;
    320  1.4.2.2  yamt 		vblocknr  = l2vmap + i;
    321  1.4.2.2  yamt 		error = nilfs_btree_lookup(node, lblocknr, vblocknr);
    322  1.4.2.2  yamt 
    323  1.4.2.2  yamt 		DPRINTF(TRANSLATE, ("btree_nlookup ino %"PRIu64", "
    324  1.4.2.2  yamt 			"lblocknr %"PRIu64" -> %"PRIu64"\n",
    325  1.4.2.2  yamt 			node->ino, lblocknr, *vblocknr));
    326  1.4.2.2  yamt 		if (error)
    327  1.4.2.2  yamt 			break;
    328  1.4.2.2  yamt 	}
    329  1.4.2.2  yamt 
    330  1.4.2.2  yamt 	return error;
    331  1.4.2.2  yamt }
    332  1.4.2.2  yamt 
    333  1.4.2.2  yamt /* --------------------------------------------------------------------- */
    334  1.4.2.2  yamt 
    335  1.4.2.2  yamt /* vtop operations */
    336  1.4.2.2  yamt 
    337  1.4.2.2  yamt /* translate index to a file block number and an entry */
    338  1.4.2.2  yamt static void
    339  1.4.2.2  yamt nilfs_mdt_trans(struct nilfs_mdt *mdt, uint64_t index,
    340  1.4.2.2  yamt 	uint64_t *blocknr, uint32_t *entry_in_block)
    341  1.4.2.2  yamt {
    342  1.4.2.2  yamt 	uint64_t blknr;
    343  1.4.2.2  yamt 	uint64_t group, group_offset, blocknr_in_group;
    344  1.4.2.2  yamt 	uint64_t desc_block, desc_offset;
    345  1.4.2.2  yamt 
    346  1.4.2.2  yamt 	/* calculate our offset in the file */
    347  1.4.2.2  yamt 	group             = index / mdt->entries_per_group;
    348  1.4.2.2  yamt 	group_offset      = index % mdt->entries_per_group;
    349  1.4.2.2  yamt 	desc_block        = group / mdt->groups_per_desc_block;
    350  1.4.2.2  yamt 	desc_offset       = group % mdt->groups_per_desc_block;
    351  1.4.2.2  yamt 	blocknr_in_group  = group_offset / mdt->entries_per_block;
    352  1.4.2.2  yamt 
    353  1.4.2.2  yamt 	/* to descgroup offset */
    354  1.4.2.2  yamt 	blknr = 1 + desc_block * mdt->blocks_per_desc_block;
    355  1.4.2.2  yamt 
    356  1.4.2.2  yamt 	/* to group offset */
    357  1.4.2.2  yamt 	blknr += desc_offset * mdt->blocks_per_group;
    358  1.4.2.2  yamt 
    359  1.4.2.2  yamt 	/* to actual file block */
    360  1.4.2.2  yamt 	blknr += 1 + blocknr_in_group;
    361  1.4.2.2  yamt 
    362  1.4.2.2  yamt 	*blocknr        = blknr;
    363  1.4.2.2  yamt 	*entry_in_block = group_offset % mdt->entries_per_block;
    364  1.4.2.2  yamt }
    365  1.4.2.2  yamt 
    366  1.4.2.2  yamt 
    367  1.4.2.2  yamt static int
    368  1.4.2.2  yamt nilfs_vtop(struct nilfs_device *nilfsdev, uint64_t vblocknr, uint64_t *pblocknr)
    369  1.4.2.2  yamt {
    370  1.4.2.2  yamt 	struct nilfs_dat_entry *entry;
    371  1.4.2.2  yamt 	struct buf *bp;
    372  1.4.2.2  yamt 	uint64_t  ldatblknr;
    373  1.4.2.2  yamt 	uint32_t  entry_in_block;
    374  1.4.2.2  yamt 	int error;
    375  1.4.2.2  yamt 
    376  1.4.2.2  yamt 	nilfs_mdt_trans(&nilfsdev->dat_mdt, vblocknr,
    377  1.4.2.2  yamt 		&ldatblknr, &entry_in_block);
    378  1.4.2.2  yamt 
    379  1.4.2.2  yamt 	error = nilfs_bread(nilfsdev->dat_node, ldatblknr, NOCRED, 0, &bp);
    380  1.4.2.2  yamt 	if (error) {
    381  1.4.2.2  yamt 		printf("vtop: can't read in DAT block %"PRIu64"!\n", ldatblknr);
    382  1.4.2.2  yamt 		brelse(bp, BC_AGE);
    383  1.4.2.2  yamt 		return error;
    384  1.4.2.2  yamt 	}
    385  1.4.2.2  yamt 
    386  1.4.2.2  yamt 	/* get our translation */
    387  1.4.2.2  yamt 	entry = ((struct nilfs_dat_entry *) bp->b_data) + entry_in_block;
    388  1.4.2.2  yamt #if 0
    389  1.4.2.2  yamt 	printf("\tvblk %4"PRIu64" -> %"PRIu64" for "
    390  1.4.2.2  yamt 		"checkpoint %"PRIu64" to %"PRIu64"\n",
    391  1.4.2.2  yamt 		vblocknr,
    392  1.4.2.2  yamt 		nilfs_rw64(entry->de_blocknr),
    393  1.4.2.2  yamt 		nilfs_rw64(entry->de_start),
    394  1.4.2.2  yamt 		nilfs_rw64(entry->de_end));
    395  1.4.2.2  yamt #endif
    396  1.4.2.2  yamt 
    397  1.4.2.2  yamt 	*pblocknr = nilfs_rw64(entry->de_blocknr);
    398  1.4.2.2  yamt 	brelse(bp, BC_AGE);
    399  1.4.2.2  yamt 
    400  1.4.2.2  yamt 	return 0;
    401  1.4.2.2  yamt }
    402  1.4.2.2  yamt 
    403  1.4.2.2  yamt 
    404  1.4.2.2  yamt int
    405  1.4.2.2  yamt nilfs_nvtop(struct nilfs_node *node, uint64_t blks, uint64_t *l2vmap,
    406  1.4.2.2  yamt 		uint64_t *v2pmap)
    407  1.4.2.2  yamt {
    408  1.4.2.2  yamt 	uint64_t vblocknr, *pblocknr;
    409  1.4.2.2  yamt 	int i, error;
    410  1.4.2.2  yamt 
    411  1.4.2.2  yamt 	/* the DAT inode is the only one not mapped virtual */
    412  1.4.2.2  yamt 	if (node->ino == NILFS_DAT_INO) {
    413  1.4.2.2  yamt 		memcpy(v2pmap, l2vmap, blks * sizeof(uint64_t));
    414  1.4.2.2  yamt 		return 0;
    415  1.4.2.2  yamt 	}
    416  1.4.2.2  yamt 
    417  1.4.2.2  yamt 	/* TODO / OPTI more translations in one go */
    418  1.4.2.2  yamt 	error = 0;
    419  1.4.2.2  yamt 	for (i = 0; i < blks; i++) {
    420  1.4.2.2  yamt 		vblocknr  = l2vmap[i];
    421  1.4.2.2  yamt 		pblocknr  = v2pmap + i;
    422  1.4.2.2  yamt 		*pblocknr = 0;
    423  1.4.2.2  yamt 
    424  1.4.2.2  yamt 		/* only translate valid vblocknrs */
    425  1.4.2.2  yamt 		if (vblocknr == 0)
    426  1.4.2.2  yamt 			continue;
    427  1.4.2.2  yamt 		error = nilfs_vtop(node->nilfsdev, vblocknr, pblocknr);
    428  1.4.2.2  yamt 		if (error)
    429  1.4.2.2  yamt 			break;
    430  1.4.2.2  yamt 	}
    431  1.4.2.2  yamt 
    432  1.4.2.2  yamt 	return error;
    433  1.4.2.2  yamt }
    434  1.4.2.2  yamt 
    435  1.4.2.2  yamt /* --------------------------------------------------------------------- */
    436  1.4.2.2  yamt 
    437  1.4.2.2  yamt struct nilfs_recover_info {
    438  1.4.2.2  yamt 	uint64_t segnum;
    439  1.4.2.2  yamt 	uint64_t pseg;
    440  1.4.2.2  yamt 
    441  1.4.2.2  yamt 	struct nilfs_segment_summary segsum;
    442  1.4.2.2  yamt 	struct nilfs_super_root      super_root;
    443  1.4.2.2  yamt 	STAILQ_ENTRY(nilfs_recover_info) next;
    444  1.4.2.2  yamt };
    445  1.4.2.2  yamt 
    446  1.4.2.2  yamt 
    447  1.4.2.2  yamt /*
    448  1.4.2.2  yamt  * Helper functions of nilfs_mount() that actually mounts the disc.
    449  1.4.2.2  yamt  */
    450  1.4.2.2  yamt static int
    451  1.4.2.2  yamt nilfs_load_segsum(struct nilfs_device *nilfsdev,
    452  1.4.2.2  yamt 	struct nilfs_recover_info *ri)
    453  1.4.2.2  yamt {
    454  1.4.2.2  yamt 	struct buf *bp;
    455  1.4.2.2  yamt 	uint64_t blocknr, offset;
    456  1.4.2.2  yamt 	uint32_t segsum_struct_size;
    457  1.4.2.2  yamt 	uint32_t magic;
    458  1.4.2.2  yamt 	int error;
    459  1.4.2.2  yamt 
    460  1.4.2.2  yamt 	segsum_struct_size = sizeof(struct nilfs_segment_summary);
    461  1.4.2.2  yamt 
    462  1.4.2.2  yamt 	/* read in segsum structure */
    463  1.4.2.2  yamt 	bp      = NULL;
    464  1.4.2.2  yamt 	blocknr = ri->pseg;
    465  1.4.2.2  yamt 	offset  = 0;
    466  1.4.2.2  yamt 	error = nilfs_get_segment_log(nilfsdev,
    467  1.4.2.2  yamt 			&blocknr, &offset, &bp,
    468  1.4.2.2  yamt 			segsum_struct_size, (void *) &ri->segsum);
    469  1.4.2.2  yamt 	if (error)
    470  1.4.2.2  yamt 		goto out;
    471  1.4.2.2  yamt 
    472  1.4.2.2  yamt 	/* sanity checks */
    473  1.4.2.2  yamt 	magic = nilfs_rw32(ri->segsum.ss_magic);
    474  1.4.2.2  yamt 	if (magic != NILFS_SEGSUM_MAGIC) {
    475  1.4.2.2  yamt 		DPRINTF(VOLUMES, ("nilfs: bad magic in pseg %"PRIu64"\n",
    476  1.4.2.2  yamt 			ri->pseg));
    477  1.4.2.2  yamt 		error = EINVAL;
    478  1.4.2.2  yamt 		goto out;
    479  1.4.2.2  yamt 	}
    480  1.4.2.2  yamt 
    481  1.4.2.2  yamt 	/* TODO check segment summary checksum */
    482  1.4.2.2  yamt 	/* TODO check data checksum */
    483  1.4.2.2  yamt 
    484  1.4.2.2  yamt 	/* adjust our walking point if we have an odd size */
    485  1.4.2.2  yamt 	if (segsum_struct_size != nilfs_rw32(ri->segsum.ss_bytes)) {
    486  1.4.2.2  yamt 		printf("nilfs: WARNING encountered segsum_struct size %d in "
    487  1.4.2.2  yamt 			"pseg %"PRIu64"\n",
    488  1.4.2.2  yamt 			nilfs_rw32(ri->segsum.ss_bytes), ri->pseg);
    489  1.4.2.2  yamt 		/* XXX report as an error? */
    490  1.4.2.2  yamt 	}
    491  1.4.2.2  yamt 
    492  1.4.2.2  yamt out:
    493  1.4.2.2  yamt 	if (bp)
    494  1.4.2.2  yamt 		brelse(bp, BC_AGE);
    495  1.4.2.2  yamt 
    496  1.4.2.2  yamt 	return error;
    497  1.4.2.2  yamt }
    498  1.4.2.2  yamt 
    499  1.4.2.2  yamt 
    500  1.4.2.2  yamt static int
    501  1.4.2.2  yamt nilfs_load_super_root(struct nilfs_device *nilfsdev,
    502  1.4.2.2  yamt 	struct nilfs_recover_info *ri)
    503  1.4.2.2  yamt {
    504  1.4.2.2  yamt 	struct nilfs_segment_summary *segsum = &ri->segsum;
    505  1.4.2.2  yamt 	struct nilfs_super_root *super_root;
    506  1.4.2.2  yamt 	struct buf *bp;
    507  1.4.2.2  yamt 	uint64_t blocknr, offset;
    508  1.4.2.2  yamt 	uint32_t segsum_size, size;
    509  1.4.2.2  yamt 	uint32_t nsumblk, nfileblk;
    510  1.4.2.2  yamt 	uint32_t super_root_crc, comp_crc;
    511  1.4.2.2  yamt 	int off, error;
    512  1.4.2.2  yamt 
    513  1.4.2.2  yamt 	/* process segment summary */
    514  1.4.2.2  yamt 	segsum_size = nilfs_rw32(segsum->ss_sumbytes);
    515  1.4.2.2  yamt 	nsumblk     = (segsum_size - 1) / nilfsdev->blocksize + 1;
    516  1.4.2.2  yamt 	nfileblk    = nilfs_rw32(segsum->ss_nblocks) - nsumblk;
    517  1.4.2.2  yamt 
    518  1.4.2.2  yamt 	/* check if there is a superroot */
    519  1.4.2.2  yamt 	if ((nilfs_rw16(segsum->ss_flags) & NILFS_SS_SR) == 0) {
    520  1.4.2.2  yamt 		DPRINTF(VOLUMES, ("nilfs: no super root in pseg %"PRIu64"\n",
    521  1.4.2.2  yamt 			ri->pseg));
    522  1.4.2.2  yamt 		return ENOENT;
    523  1.4.2.2  yamt 	}
    524  1.4.2.2  yamt 
    525  1.4.2.2  yamt 	/* get our super root, located at the end of the pseg */
    526  1.4.2.2  yamt 	blocknr = ri->pseg + nsumblk + nfileblk - 1;
    527  1.4.2.2  yamt 	offset = 0;
    528  1.4.2.2  yamt 	size = sizeof(struct nilfs_super_root);
    529  1.4.2.2  yamt 	bp = NULL;
    530  1.4.2.2  yamt 	error = nilfs_get_segment_log(nilfsdev,
    531  1.4.2.2  yamt 			&blocknr, &offset, &bp,
    532  1.4.2.2  yamt 			size, (void *) &nilfsdev->super_root);
    533  1.4.2.2  yamt 	if (bp)
    534  1.4.2.2  yamt 		brelse(bp, BC_AGE);
    535  1.4.2.2  yamt 	if (error) {
    536  1.4.2.2  yamt 		printf("read in of superroot failed\n");
    537  1.4.2.2  yamt 		return EIO;
    538  1.4.2.2  yamt 	}
    539  1.4.2.2  yamt 
    540  1.4.2.2  yamt 	/* check super root crc */
    541  1.4.2.2  yamt 	super_root = &nilfsdev->super_root;
    542  1.4.2.2  yamt 	super_root_crc = nilfs_rw32(super_root->sr_sum);
    543  1.4.2.2  yamt 	off = sizeof(super_root->sr_sum);
    544  1.4.2.2  yamt 	comp_crc = crc32_le(nilfs_rw32(nilfsdev->super.s_crc_seed),
    545  1.4.2.2  yamt 		(uint8_t *) super_root + off,
    546  1.4.2.2  yamt 		NILFS_SR_BYTES - off);
    547  1.4.2.2  yamt 	if (super_root_crc != comp_crc) {
    548  1.4.2.2  yamt 		DPRINTF(VOLUMES, ("    invalid superroot, likely from old format\n"));
    549  1.4.2.2  yamt 		return EINVAL;
    550  1.4.2.2  yamt 	}
    551  1.4.2.2  yamt 
    552  1.4.2.2  yamt 	DPRINTF(VOLUMES, ("    got valid superroot\n"));
    553  1.4.2.2  yamt 
    554  1.4.2.2  yamt 	return 0;
    555  1.4.2.2  yamt }
    556  1.4.2.2  yamt 
    557  1.4.2.2  yamt /*
    558  1.4.2.2  yamt  * Search for the last super root recorded.
    559  1.4.2.2  yamt  */
    560  1.4.2.2  yamt void
    561  1.4.2.2  yamt nilfs_search_super_root(struct nilfs_device *nilfsdev)
    562  1.4.2.2  yamt {
    563  1.4.2.2  yamt 	struct nilfs_super_block *super;
    564  1.4.2.2  yamt 	struct nilfs_segment_summary *segsum;
    565  1.4.2.2  yamt 	struct nilfs_recover_info *ri, *ori, *i_ri;
    566  1.4.2.2  yamt 	STAILQ_HEAD(,nilfs_recover_info) ri_list;
    567  1.4.2.2  yamt 	uint64_t seg_start, seg_end, cno;
    568  1.4.2.2  yamt 	uint32_t segsum_size;
    569  1.4.2.2  yamt 	uint32_t nsumblk, nfileblk;
    570  1.4.2.2  yamt 	int error;
    571  1.4.2.2  yamt 
    572  1.4.2.2  yamt 	STAILQ_INIT(&ri_list);
    573  1.4.2.2  yamt 
    574  1.4.2.2  yamt 	/* search for last super root */
    575  1.4.2.2  yamt 	ri = malloc(sizeof(struct nilfs_recover_info), M_NILFSTEMP, M_WAITOK);
    576  1.4.2.2  yamt 	memset(ri, 0, sizeof(struct nilfs_recover_info));
    577  1.4.2.2  yamt 
    578  1.4.2.2  yamt 	/* if enabled, start from the specified position */
    579  1.4.2.2  yamt 	if (0) {
    580  1.4.2.2  yamt 		/* start from set start */
    581  1.4.2.2  yamt 		nilfsdev->super.s_last_pseg = nilfsdev->super.s_first_data_block;
    582  1.4.2.2  yamt 		nilfsdev->super.s_last_cno  = nilfs_rw64(1);
    583  1.4.2.2  yamt 	}
    584  1.4.2.2  yamt 
    585  1.4.2.2  yamt 	ri->pseg   = nilfs_rw64(nilfsdev->super.s_last_pseg); /* blknr */
    586  1.4.2.2  yamt 	ri->segnum = nilfs_get_segnum_of_block(nilfsdev, ri->pseg);
    587  1.4.2.2  yamt 
    588  1.4.2.2  yamt 	error = 0;
    589  1.4.2.2  yamt 	cno = nilfs_rw64(nilfsdev->super.s_last_cno);
    590  1.4.2.2  yamt 	DPRINTF(VOLUMES, ("nilfs: seach_super_root start in pseg %"PRIu64"\n",
    591  1.4.2.2  yamt 			ri->pseg));
    592  1.4.2.2  yamt 	for (;;) {
    593  1.4.2.2  yamt 		DPRINTF(VOLUMES, (" at pseg %"PRIu64"\n", ri->pseg));
    594  1.4.2.2  yamt 		error = nilfs_load_segsum(nilfsdev, ri);
    595  1.4.2.2  yamt 		if (error)
    596  1.4.2.2  yamt 			break;
    597  1.4.2.2  yamt 
    598  1.4.2.2  yamt 		segsum = &ri->segsum;
    599  1.4.2.2  yamt 
    600  1.4.2.2  yamt 		/* try to load super root */
    601  1.4.2.2  yamt 		if (nilfs_rw16(segsum->ss_flags) & NILFS_SS_SR) {
    602  1.4.2.2  yamt 			DPRINTF(VOLUMES, (" try super root\n"));
    603  1.4.2.2  yamt 			error = nilfs_load_super_root(nilfsdev, ri);
    604  1.4.2.2  yamt 			if (error)
    605  1.4.2.2  yamt 				break;	/* confused */
    606  1.4.2.2  yamt 			/* wipe current list of ri */
    607  1.4.2.2  yamt 			while (!STAILQ_EMPTY(&ri_list)) {
    608  1.4.2.2  yamt 				i_ri = STAILQ_FIRST(&ri_list);
    609  1.4.2.2  yamt 				STAILQ_REMOVE_HEAD(&ri_list, next);
    610  1.4.2.2  yamt 				free(i_ri, M_NILFSTEMP);
    611  1.4.2.2  yamt 			}
    612  1.4.2.2  yamt 			super = &nilfsdev->super;
    613  1.4.2.2  yamt 
    614  1.4.2.2  yamt 			super->s_last_pseg = nilfs_rw64(ri->pseg);
    615  1.4.2.2  yamt 			super->s_last_cno  = cno++;
    616  1.4.2.2  yamt 			super->s_last_seq  = segsum->ss_seq;
    617  1.4.2.2  yamt 			super->s_state     = nilfs_rw16(NILFS_VALID_FS);
    618  1.4.2.2  yamt 		} else {
    619  1.4.2.2  yamt 			STAILQ_INSERT_TAIL(&ri_list, ri, next);
    620  1.4.2.2  yamt 			ori = ri;
    621  1.4.2.2  yamt 			ri = malloc(sizeof(struct nilfs_recover_info),
    622  1.4.2.2  yamt 				M_NILFSTEMP, M_WAITOK);
    623  1.4.2.2  yamt 			memset(ri, 0, sizeof(struct nilfs_recover_info));
    624  1.4.2.2  yamt 			ri->segnum = ori->segnum;
    625  1.4.2.2  yamt 			ri->pseg   = ori->pseg;
    626  1.4.2.2  yamt 			/* segsum keeps pointing to the `old' ri */
    627  1.4.2.2  yamt 		}
    628  1.4.2.2  yamt 
    629  1.4.2.2  yamt 		/* continue to the next pseg */
    630  1.4.2.2  yamt 		segsum_size = nilfs_rw32(segsum->ss_sumbytes);
    631  1.4.2.2  yamt 		nsumblk     = (segsum_size - 1) / nilfsdev->blocksize + 1;
    632  1.4.2.2  yamt 		nfileblk    = nilfs_rw32(segsum->ss_nblocks) - nsumblk;
    633  1.4.2.2  yamt 
    634  1.4.2.2  yamt 		/* calculate next partial segment location */
    635  1.4.2.2  yamt 		ri->pseg += nsumblk + nfileblk;
    636  1.4.2.2  yamt 
    637  1.4.2.2  yamt 		/* did we reach the end of the segment? if so, go to the next */
    638  1.4.2.2  yamt 		nilfs_get_segment_range(nilfsdev, ri->segnum, &seg_start, &seg_end);
    639  1.4.2.2  yamt 		if (ri->pseg >= seg_end)
    640  1.4.2.2  yamt 			ri->pseg = nilfs_rw64(segsum->ss_next);
    641  1.4.2.2  yamt 		ri->segnum = nilfs_get_segnum_of_block(nilfsdev, ri->pseg);
    642  1.4.2.2  yamt 	}
    643  1.4.2.2  yamt 
    644  1.4.2.2  yamt 	/*
    645  1.4.2.2  yamt 	 * XXX No roll-forward yet of the remaining partial segments.
    646  1.4.2.2  yamt 	 */
    647  1.4.2.2  yamt 
    648  1.4.2.2  yamt 	/* wipe current list of ri */
    649  1.4.2.2  yamt 	while (!STAILQ_EMPTY(&ri_list)) {
    650  1.4.2.2  yamt 		i_ri = STAILQ_FIRST(&ri_list);
    651  1.4.2.2  yamt 		STAILQ_REMOVE_HEAD(&ri_list, next);
    652  1.4.2.2  yamt 		printf("nilfs: ignoring pseg at %"PRIu64"\n", i_ri->pseg);
    653  1.4.2.2  yamt 		free(i_ri, M_NILFSTEMP);
    654  1.4.2.2  yamt 	}
    655  1.4.2.2  yamt 	free(ri, M_NILFSTEMP);
    656  1.4.2.2  yamt }
    657  1.4.2.2  yamt 
    658  1.4.2.2  yamt /* --------------------------------------------------------------------- */
    659  1.4.2.2  yamt 
    660  1.4.2.2  yamt /*
    661  1.4.2.2  yamt  * Genfs interfacing
    662  1.4.2.2  yamt  *
    663  1.4.2.2  yamt  * static const struct genfs_ops nilfs_genfsops = {
    664  1.4.2.2  yamt  * 	.gop_size = genfs_size,
    665  1.4.2.2  yamt  * 		size of transfers
    666  1.4.2.2  yamt  * 	.gop_alloc = nilfs_gop_alloc,
    667  1.4.2.2  yamt  * 		allocate len bytes at offset
    668  1.4.2.2  yamt  * 	.gop_write = genfs_gop_write,
    669  1.4.2.2  yamt  * 		putpages interface code
    670  1.4.2.2  yamt  * 	.gop_markupdate = nilfs_gop_markupdate,
    671  1.4.2.2  yamt  * 		set update/modify flags etc.
    672  1.4.2.2  yamt  * }
    673  1.4.2.2  yamt  */
    674  1.4.2.2  yamt 
    675  1.4.2.2  yamt /*
    676  1.4.2.2  yamt  * Callback from genfs to allocate len bytes at offset off; only called when
    677  1.4.2.2  yamt  * filling up gaps in the allocation.
    678  1.4.2.2  yamt  */
    679  1.4.2.2  yamt static int
    680  1.4.2.2  yamt nilfs_gop_alloc(struct vnode *vp, off_t off,
    681  1.4.2.2  yamt     off_t len, int flags, kauth_cred_t cred)
    682  1.4.2.2  yamt {
    683  1.4.2.2  yamt 	DPRINTF(NOTIMPL, ("nilfs_gop_alloc not implemented\n"));
    684  1.4.2.2  yamt 	DPRINTF(ALLOC, ("nilfs_gop_alloc called for %"PRIu64" bytes\n", len));
    685  1.4.2.2  yamt 
    686  1.4.2.2  yamt 	return 0;
    687  1.4.2.2  yamt }
    688  1.4.2.2  yamt 
    689  1.4.2.2  yamt 
    690  1.4.2.2  yamt /*
    691  1.4.2.2  yamt  * callback from genfs to update our flags
    692  1.4.2.2  yamt  */
    693  1.4.2.2  yamt static void
    694  1.4.2.2  yamt nilfs_gop_markupdate(struct vnode *vp, int flags)
    695  1.4.2.2  yamt {
    696  1.4.2.2  yamt 	struct nilfs_node *nilfs_node = VTOI(vp);
    697  1.4.2.2  yamt 	u_long mask = 0;
    698  1.4.2.2  yamt 
    699  1.4.2.2  yamt 	if ((flags & GOP_UPDATE_ACCESSED) != 0) {
    700  1.4.2.2  yamt 		mask = IN_ACCESS;
    701  1.4.2.2  yamt 	}
    702  1.4.2.2  yamt 	if ((flags & GOP_UPDATE_MODIFIED) != 0) {
    703  1.4.2.2  yamt 		if (vp->v_type == VREG) {
    704  1.4.2.2  yamt 			mask |= IN_CHANGE | IN_UPDATE;
    705  1.4.2.2  yamt 		} else {
    706  1.4.2.2  yamt 			mask |= IN_MODIFY;
    707  1.4.2.2  yamt 		}
    708  1.4.2.2  yamt 	}
    709  1.4.2.2  yamt 	if (mask) {
    710  1.4.2.2  yamt 		nilfs_node->i_flags |= mask;
    711  1.4.2.2  yamt 	}
    712  1.4.2.2  yamt }
    713  1.4.2.2  yamt 
    714  1.4.2.2  yamt 
    715  1.4.2.2  yamt static const struct genfs_ops nilfs_genfsops = {
    716  1.4.2.2  yamt 	.gop_size = genfs_size,
    717  1.4.2.2  yamt 	.gop_alloc = nilfs_gop_alloc,
    718  1.4.2.2  yamt 	.gop_write = genfs_gop_write_rwmap,
    719  1.4.2.2  yamt 	.gop_markupdate = nilfs_gop_markupdate,
    720  1.4.2.2  yamt };
    721  1.4.2.2  yamt 
    722  1.4.2.2  yamt /* --------------------------------------------------------------------- */
    723  1.4.2.2  yamt 
    724  1.4.2.2  yamt static void
    725  1.4.2.2  yamt nilfs_register_node(struct nilfs_node *node)
    726  1.4.2.2  yamt {
    727  1.4.2.2  yamt 	struct nilfs_mount *ump;
    728  1.4.2.2  yamt 	struct nilfs_node *chk;
    729  1.4.2.2  yamt 	uint32_t hashline;
    730  1.4.2.2  yamt 
    731  1.4.2.2  yamt 	ump = node->ump;
    732  1.4.2.2  yamt 	mutex_enter(&ump->ihash_lock);
    733  1.4.2.2  yamt 
    734  1.4.2.2  yamt 	/* add to our hash table */
    735  1.4.2.2  yamt 	hashline = nilfs_calchash(node->ino) & NILFS_INODE_HASHMASK;
    736  1.4.2.2  yamt #ifdef DEBUG
    737  1.4.2.2  yamt 	LIST_FOREACH(chk, &ump->nilfs_nodes[hashline], hashchain) {
    738  1.4.2.2  yamt 		assert(chk);
    739  1.4.2.2  yamt 		if (chk->ino == node->ino)
    740  1.4.2.2  yamt 			panic("Double node entered\n");
    741  1.4.2.2  yamt 	}
    742  1.4.2.2  yamt #else
    743  1.4.2.2  yamt 	chk = NULL;
    744  1.4.2.2  yamt #endif
    745  1.4.2.2  yamt 	LIST_INSERT_HEAD(&ump->nilfs_nodes[hashline], node, hashchain);
    746  1.4.2.2  yamt 
    747  1.4.2.2  yamt 	mutex_exit(&ump->ihash_lock);
    748  1.4.2.2  yamt }
    749  1.4.2.2  yamt 
    750  1.4.2.2  yamt 
    751  1.4.2.2  yamt static void
    752  1.4.2.2  yamt nilfs_deregister_node(struct nilfs_node *node)
    753  1.4.2.2  yamt {
    754  1.4.2.2  yamt 	struct nilfs_mount *ump;
    755  1.4.2.2  yamt 
    756  1.4.2.2  yamt 	ump = node->ump;
    757  1.4.2.2  yamt 	mutex_enter(&ump->ihash_lock);
    758  1.4.2.2  yamt 
    759  1.4.2.2  yamt 	/* remove from hash list */
    760  1.4.2.2  yamt 	LIST_REMOVE(node, hashchain);
    761  1.4.2.2  yamt 
    762  1.4.2.2  yamt 	mutex_exit(&ump->ihash_lock);
    763  1.4.2.2  yamt }
    764  1.4.2.2  yamt 
    765  1.4.2.2  yamt 
    766  1.4.2.2  yamt static struct nilfs_node *
    767  1.4.2.2  yamt nilfs_hash_lookup(struct nilfs_mount *ump, ino_t ino)
    768  1.4.2.2  yamt {
    769  1.4.2.2  yamt 	struct nilfs_node *node;
    770  1.4.2.2  yamt 	struct vnode *vp;
    771  1.4.2.2  yamt 	uint32_t hashline;
    772  1.4.2.2  yamt 
    773  1.4.2.2  yamt loop:
    774  1.4.2.2  yamt 	mutex_enter(&ump->ihash_lock);
    775  1.4.2.2  yamt 
    776  1.4.2.2  yamt 	/* search our hash table */
    777  1.4.2.2  yamt 	hashline = nilfs_calchash(ino) & NILFS_INODE_HASHMASK;
    778  1.4.2.2  yamt 	LIST_FOREACH(node, &ump->nilfs_nodes[hashline], hashchain) {
    779  1.4.2.2  yamt 		assert(node);
    780  1.4.2.2  yamt 		if (node->ino == ino) {
    781  1.4.2.2  yamt 			vp = node->vnode;
    782  1.4.2.2  yamt 			assert(vp);
    783  1.4.2.2  yamt 			mutex_enter(&vp->v_interlock);
    784  1.4.2.2  yamt 			mutex_exit(&ump->ihash_lock);
    785  1.4.2.2  yamt 			if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
    786  1.4.2.2  yamt 				goto loop;
    787  1.4.2.2  yamt 			return node;
    788  1.4.2.2  yamt 		}
    789  1.4.2.2  yamt 	}
    790  1.4.2.2  yamt 	mutex_exit(&ump->ihash_lock);
    791  1.4.2.2  yamt 
    792  1.4.2.2  yamt 	return NULL;
    793  1.4.2.2  yamt }
    794  1.4.2.2  yamt 
    795  1.4.2.2  yamt 
    796  1.4.2.2  yamt /* node action implementators */
    797  1.4.2.2  yamt extern int (**nilfs_vnodeop_p)(void *);
    798  1.4.2.2  yamt 
    799  1.4.2.2  yamt int
    800  1.4.2.2  yamt nilfs_get_node_raw(struct nilfs_device *nilfsdev, struct nilfs_mount *ump,
    801  1.4.2.2  yamt 	uint64_t ino, struct nilfs_inode *inode, struct nilfs_node **nodep)
    802  1.4.2.2  yamt {
    803  1.4.2.2  yamt 	struct nilfs_node *node;
    804  1.4.2.2  yamt 	struct vnode *nvp;
    805  1.4.2.2  yamt 	struct mount *mp;
    806  1.4.2.2  yamt 	int (**vnodeops)(void *);
    807  1.4.2.2  yamt 	int error;
    808  1.4.2.2  yamt 
    809  1.4.2.2  yamt 	*nodep = NULL;
    810  1.4.2.2  yamt 	vnodeops = nilfs_vnodeop_p;
    811  1.4.2.2  yamt 
    812  1.4.2.2  yamt 	/* associate with mountpoint if present*/
    813  1.4.2.2  yamt 	mp = ump? ump->vfs_mountp : NULL;
    814  1.4.2.2  yamt 	error = getnewvnode(VT_NILFS, mp, vnodeops, &nvp);
    815  1.4.2.2  yamt 	if (error)
    816  1.4.2.2  yamt 		return error;
    817  1.4.2.2  yamt 
    818  1.4.2.2  yamt 	/* lock node */
    819  1.4.2.2  yamt 	error = vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY);
    820  1.4.2.2  yamt 	if (error) {
    821  1.4.2.2  yamt 		nvp->v_data = NULL;
    822  1.4.2.2  yamt 		ungetnewvnode(nvp);
    823  1.4.2.2  yamt 		return error;
    824  1.4.2.2  yamt 	}
    825  1.4.2.2  yamt 
    826  1.4.2.2  yamt 	node = pool_get(&nilfs_node_pool, PR_WAITOK);
    827  1.4.2.2  yamt 	memset(node, 0, sizeof(struct nilfs_node));
    828  1.4.2.2  yamt 
    829  1.4.2.2  yamt 	/* crosslink */
    830  1.4.2.2  yamt 	node->vnode    = nvp;
    831  1.4.2.2  yamt 	node->ump      = ump;
    832  1.4.2.2  yamt 	node->nilfsdev = nilfsdev;
    833  1.4.2.2  yamt 	nvp->v_data    = node;
    834  1.4.2.2  yamt 
    835  1.4.2.2  yamt 	/* initiase nilfs node */
    836  1.4.2.2  yamt 	node->ino   = ino;
    837  1.4.2.2  yamt 	node->inode = *inode;
    838  1.4.2.2  yamt 	node->lockf = NULL;
    839  1.4.2.2  yamt 
    840  1.4.2.2  yamt 	/* needed? */
    841  1.4.2.2  yamt 	mutex_init(&node->node_mutex, MUTEX_DEFAULT, IPL_NONE);
    842  1.4.2.2  yamt 	cv_init(&node->node_lock, "nilfs_nlk");
    843  1.4.2.2  yamt 
    844  1.4.2.2  yamt 	/* initialise genfs */
    845  1.4.2.2  yamt 	genfs_node_init(nvp, &nilfs_genfsops);
    846  1.4.2.2  yamt 
    847  1.4.2.2  yamt 	/* check if we're fetching the root */
    848  1.4.2.2  yamt 	if (ino == NILFS_ROOT_INO)
    849  1.4.2.2  yamt 		nvp->v_vflag |= VV_ROOT;
    850  1.4.2.2  yamt 
    851  1.4.2.2  yamt 	/* update vnode's file type XXX is there a function for this? */
    852  1.4.2.2  yamt 	nvp->v_type = VREG;
    853  1.4.2.2  yamt 	if (S_ISDIR(inode->i_mode))
    854  1.4.2.2  yamt 		nvp->v_type = VDIR;
    855  1.4.2.2  yamt 	if (S_ISLNK(inode->i_mode))
    856  1.4.2.2  yamt 		nvp->v_type = VLNK;
    857  1.4.2.2  yamt #if 0
    858  1.4.2.2  yamt 	if (S_ISCHR(inode->i_mode))
    859  1.4.2.2  yamt 		nvp->v_type = VCHR;
    860  1.4.2.2  yamt 	if (S_ISBLK(inode->i_mode))
    861  1.4.2.2  yamt 		nvp->v_type = VBLK;
    862  1.4.2.2  yamt #endif
    863  1.4.2.2  yamt 	/* XXX what else? */
    864  1.4.2.2  yamt 
    865  1.4.2.2  yamt 	/* fixup inode size for system nodes */
    866  1.4.2.2  yamt 	if ((ino < NILFS_USER_INO) && (ino != NILFS_ROOT_INO)) {
    867  1.4.2.2  yamt 		DPRINTF(VOLUMES, ("NEED TO GET my size for inode %"PRIu64"\n",
    868  1.4.2.2  yamt 			ino));
    869  1.4.2.2  yamt 		/* for now set it to maximum, -1 is illegal */
    870  1.4.2.2  yamt 		inode->i_size = nilfs_rw64(((uint64_t) -2));
    871  1.4.2.2  yamt 	}
    872  1.4.2.2  yamt 
    873  1.4.2.2  yamt 	uvm_vnp_setsize(nvp, nilfs_rw64(inode->i_size));
    874  1.4.2.2  yamt 
    875  1.4.2.2  yamt 	if (ump)
    876  1.4.2.2  yamt 		nilfs_register_node(node);
    877  1.4.2.2  yamt 
    878  1.4.2.2  yamt 	/* return node */
    879  1.4.2.2  yamt 	*nodep = node;
    880  1.4.2.2  yamt 	return 0;
    881  1.4.2.2  yamt }
    882  1.4.2.2  yamt 
    883  1.4.2.2  yamt 
    884  1.4.2.2  yamt int
    885  1.4.2.2  yamt nilfs_get_node(struct nilfs_mount *ump, uint64_t ino, struct nilfs_node **nodep)
    886  1.4.2.2  yamt {
    887  1.4.2.2  yamt 	struct nilfs_device *nilfsdev;
    888  1.4.2.2  yamt 	struct nilfs_inode   inode, *entry;
    889  1.4.2.2  yamt 	struct buf *bp;
    890  1.4.2.2  yamt 	uint64_t ivblocknr;
    891  1.4.2.2  yamt 	uint32_t entry_in_block;
    892  1.4.2.2  yamt 	int error;
    893  1.4.2.2  yamt 
    894  1.4.2.2  yamt 	/* lookup node in hash table */
    895  1.4.2.2  yamt 	*nodep = nilfs_hash_lookup(ump, ino);
    896  1.4.2.2  yamt 	if (*nodep)
    897  1.4.2.2  yamt 		return 0;
    898  1.4.2.2  yamt 
    899  1.4.2.2  yamt 	/* lock to disallow simultanious creation of same udf_node */
    900  1.4.2.2  yamt 	mutex_enter(&ump->get_node_lock);
    901  1.4.2.2  yamt 
    902  1.4.2.2  yamt 	/* relookup since it could be created while waiting for the mutex */
    903  1.4.2.2  yamt 	*nodep = nilfs_hash_lookup(ump, ino);
    904  1.4.2.2  yamt 	if (*nodep) {
    905  1.4.2.2  yamt 		mutex_exit(&ump->get_node_lock);
    906  1.4.2.2  yamt 		return 0;
    907  1.4.2.2  yamt 	}
    908  1.4.2.2  yamt 
    909  1.4.2.2  yamt 	/* create new inode; XXX check could be handier */
    910  1.4.2.2  yamt 	if ((ino < NILFS_ATIME_INO) && (ino != NILFS_ROOT_INO)) {
    911  1.4.2.2  yamt 		printf("nilfs_get_node: system ino %"PRIu64" not in mount "
    912  1.4.2.2  yamt 			"point!\n", ino);
    913  1.4.2.2  yamt 		mutex_exit(&ump->get_node_lock);
    914  1.4.2.2  yamt 		return ENOENT;
    915  1.4.2.2  yamt 	}
    916  1.4.2.2  yamt 
    917  1.4.2.2  yamt 	/* lookup inode in the ifile */
    918  1.4.2.2  yamt 	DPRINTF(NODE, ("lookup ino %"PRIu64"\n", ino));
    919  1.4.2.2  yamt 
    920  1.4.2.2  yamt 	/* lookup inode structure in mountpoints ifile */
    921  1.4.2.2  yamt 	nilfsdev = ump->nilfsdev;
    922  1.4.2.2  yamt 	nilfs_mdt_trans(&nilfsdev->ifile_mdt, ino, &ivblocknr, &entry_in_block);
    923  1.4.2.2  yamt 
    924  1.4.2.2  yamt 	error = nilfs_bread(ump->ifile_node, ivblocknr, NOCRED, 0, &bp);
    925  1.4.2.2  yamt 	if (error) {
    926  1.4.2.2  yamt 		mutex_exit(&ump->get_node_lock);
    927  1.4.2.2  yamt 		return ENOENT;
    928  1.4.2.2  yamt 	}
    929  1.4.2.2  yamt 
    930  1.4.2.2  yamt 	/* get inode entry */
    931  1.4.2.2  yamt 	entry =  (struct nilfs_inode *) bp->b_data + entry_in_block;
    932  1.4.2.2  yamt 	inode = *entry;
    933  1.4.2.2  yamt 	brelse(bp, BC_AGE);
    934  1.4.2.2  yamt 
    935  1.4.2.2  yamt 	/* get node */
    936  1.4.2.2  yamt 	error = nilfs_get_node_raw(ump->nilfsdev, ump, ino, &inode, nodep);
    937  1.4.2.2  yamt 	mutex_exit(&ump->get_node_lock);
    938  1.4.2.2  yamt 
    939  1.4.2.2  yamt 	return error;
    940  1.4.2.2  yamt }
    941  1.4.2.2  yamt 
    942  1.4.2.2  yamt 
    943  1.4.2.2  yamt void
    944  1.4.2.2  yamt nilfs_dispose_node(struct nilfs_node **nodep)
    945  1.4.2.2  yamt {
    946  1.4.2.2  yamt 	struct vnode *vp;
    947  1.4.2.2  yamt 	struct nilfs_node *node;
    948  1.4.2.2  yamt 
    949  1.4.2.2  yamt 	/* protect against rogue values */
    950  1.4.2.2  yamt 	if (!*nodep)
    951  1.4.2.2  yamt 		return;
    952  1.4.2.2  yamt 
    953  1.4.2.2  yamt 	node = *nodep;
    954  1.4.2.2  yamt 	vp = node->vnode;
    955  1.4.2.2  yamt 
    956  1.4.2.2  yamt 	/* remove dirhash if present */
    957  1.4.2.2  yamt 	dirhash_purge(&node->dir_hash);
    958  1.4.2.2  yamt 
    959  1.4.2.2  yamt 	/* remove from our hash lookup table */
    960  1.4.2.2  yamt 	if (node->ump)
    961  1.4.2.2  yamt 		nilfs_deregister_node(node);
    962  1.4.2.2  yamt 
    963  1.4.2.2  yamt 	/* destroy our locks */
    964  1.4.2.2  yamt 	mutex_destroy(&node->node_mutex);
    965  1.4.2.2  yamt 	cv_destroy(&node->node_lock);
    966  1.4.2.2  yamt 
    967  1.4.2.2  yamt 	/* dissociate from our vnode */
    968  1.4.2.2  yamt 	genfs_node_destroy(node->vnode);
    969  1.4.2.2  yamt 	vp->v_data = NULL;
    970  1.4.2.2  yamt 
    971  1.4.2.2  yamt 	/* free our associated memory */
    972  1.4.2.2  yamt 	pool_put(&nilfs_node_pool, node);
    973  1.4.2.2  yamt 
    974  1.4.2.2  yamt 	*nodep = NULL;
    975  1.4.2.2  yamt }
    976  1.4.2.2  yamt 
    977  1.4.2.2  yamt 
    978  1.4.2.2  yamt void
    979  1.4.2.2  yamt nilfs_itimes(struct nilfs_node *node, struct timespec *acc,
    980  1.4.2.2  yamt 	struct timespec *mod, struct timespec *birth)
    981  1.4.2.2  yamt {
    982  1.4.2.2  yamt }
    983  1.4.2.2  yamt 
    984  1.4.2.2  yamt 
    985  1.4.2.2  yamt int
    986  1.4.2.2  yamt nilfs_update(struct vnode *node, struct timespec *acc,
    987  1.4.2.2  yamt 	struct timespec *mod, struct timespec *birth, int updflags)
    988  1.4.2.2  yamt {
    989  1.4.2.2  yamt 	return EROFS;
    990  1.4.2.2  yamt }
    991  1.4.2.2  yamt 
    992  1.4.2.2  yamt 
    993  1.4.2.2  yamt int
    994  1.4.2.2  yamt nilfs_chsize(struct vnode *vp, u_quad_t newsize, kauth_cred_t cred)
    995  1.4.2.2  yamt {
    996  1.4.2.2  yamt 	return EROFS;
    997  1.4.2.2  yamt }
    998  1.4.2.2  yamt 
    999  1.4.2.2  yamt 
   1000  1.4.2.2  yamt 
   1001  1.4.2.2  yamt int
   1002  1.4.2.2  yamt nilfs_grow_node(struct nilfs_node *node, uint64_t new_size)
   1003  1.4.2.2  yamt {
   1004  1.4.2.2  yamt 	return EROFS;
   1005  1.4.2.2  yamt }
   1006  1.4.2.2  yamt 
   1007  1.4.2.2  yamt 
   1008  1.4.2.2  yamt int
   1009  1.4.2.2  yamt nilfs_shrink_node(struct nilfs_node *node, uint64_t new_size)
   1010  1.4.2.2  yamt {
   1011  1.4.2.2  yamt 	return EROFS;
   1012  1.4.2.2  yamt }
   1013  1.4.2.2  yamt 
   1014  1.4.2.2  yamt 
   1015  1.4.2.2  yamt static int
   1016  1.4.2.2  yamt dirhash_fill(struct nilfs_node *dir_node)
   1017  1.4.2.2  yamt {
   1018  1.4.2.2  yamt 	struct vnode *dvp = dir_node->vnode;
   1019  1.4.2.2  yamt 	struct dirhash *dirh;
   1020  1.4.2.2  yamt 	struct nilfs_dir_entry *ndirent;
   1021  1.4.2.2  yamt 	struct dirent dirent;
   1022  1.4.2.2  yamt 	struct buf *bp;
   1023  1.4.2.2  yamt 	uint64_t file_size, diroffset, blkoff;
   1024  1.4.2.2  yamt 	uint64_t blocknr;
   1025  1.4.2.2  yamt 	uint32_t blocksize = dir_node->nilfsdev->blocksize;
   1026  1.4.2.2  yamt 	uint8_t *pos, name_len;
   1027  1.4.2.2  yamt 	int error;
   1028  1.4.2.2  yamt 
   1029  1.4.2.2  yamt 	DPRINTF(CALL, ("dirhash_fill called\n"));
   1030  1.4.2.2  yamt 
   1031  1.4.2.2  yamt 	if (dvp->v_type != VDIR)
   1032  1.4.2.2  yamt 		return ENOTDIR;
   1033  1.4.2.2  yamt 
   1034  1.4.2.2  yamt 	/* make sure we have a dirhash to work on */
   1035  1.4.2.2  yamt 	dirh = dir_node->dir_hash;
   1036  1.4.2.2  yamt 	KASSERT(dirh);
   1037  1.4.2.2  yamt 	KASSERT(dirh->refcnt > 0);
   1038  1.4.2.2  yamt 
   1039  1.4.2.2  yamt 	if (dirh->flags & DIRH_BROKEN)
   1040  1.4.2.2  yamt 		return EIO;
   1041  1.4.2.2  yamt 
   1042  1.4.2.2  yamt 	if (dirh->flags & DIRH_COMPLETE)
   1043  1.4.2.2  yamt 		return 0;
   1044  1.4.2.2  yamt 
   1045  1.4.2.2  yamt 	DPRINTF(DIRHASH, ("Filling directory hash\n"));
   1046  1.4.2.2  yamt 
   1047  1.4.2.2  yamt 	/* make sure we have a clean dirhash to add to */
   1048  1.4.2.2  yamt 	dirhash_purge_entries(dirh);
   1049  1.4.2.2  yamt 
   1050  1.4.2.2  yamt 	/* get directory filesize */
   1051  1.4.2.2  yamt 	file_size = nilfs_rw64(dir_node->inode.i_size);
   1052  1.4.2.2  yamt 
   1053  1.4.2.2  yamt 	/* walk the directory */
   1054  1.4.2.2  yamt 	error = 0;
   1055  1.4.2.2  yamt 	diroffset = 0;
   1056  1.4.2.2  yamt 
   1057  1.4.2.2  yamt 	blocknr = diroffset / blocksize;
   1058  1.4.2.2  yamt 	blkoff  = diroffset % blocksize;
   1059  1.4.2.2  yamt 	error = nilfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
   1060  1.4.2.2  yamt 	if (error) {
   1061  1.4.2.2  yamt 		dirh->flags |= DIRH_BROKEN;
   1062  1.4.2.2  yamt 		dirhash_purge_entries(dirh);
   1063  1.4.2.2  yamt 		return EIO;
   1064  1.4.2.2  yamt 	}
   1065  1.4.2.2  yamt 	while (diroffset < file_size) {
   1066  1.4.2.2  yamt 		DPRINTF(READDIR, ("filldir : offset = %"PRIu64"\n",
   1067  1.4.2.2  yamt 			diroffset));
   1068  1.4.2.2  yamt 		if (blkoff >= blocksize) {
   1069  1.4.2.2  yamt 			blkoff = 0; blocknr++;
   1070  1.4.2.2  yamt 			brelse(bp, BC_AGE);
   1071  1.4.2.2  yamt 			error = nilfs_bread(dir_node, blocknr, NOCRED, 0,
   1072  1.4.2.2  yamt 					&bp);
   1073  1.4.2.2  yamt 			if (error) {
   1074  1.4.2.2  yamt 				dirh->flags |= DIRH_BROKEN;
   1075  1.4.2.2  yamt 				dirhash_purge_entries(dirh);
   1076  1.4.2.2  yamt 				return EIO;
   1077  1.4.2.2  yamt 			}
   1078  1.4.2.2  yamt 		}
   1079  1.4.2.2  yamt 
   1080  1.4.2.2  yamt 		/* read in one dirent */
   1081  1.4.2.2  yamt 		pos = (uint8_t *) bp->b_data + blkoff;
   1082  1.4.2.2  yamt 		ndirent = (struct nilfs_dir_entry *) pos;
   1083  1.4.2.2  yamt 		name_len = ndirent->name_len;
   1084  1.4.2.2  yamt 
   1085  1.4.2.2  yamt 		memset(&dirent, 0, sizeof(struct dirent));
   1086  1.4.2.2  yamt 		dirent.d_fileno = nilfs_rw64(ndirent->inode);
   1087  1.4.2.2  yamt 		dirent.d_type   = ndirent->file_type;	/* 1:1 ? */
   1088  1.4.2.2  yamt 		dirent.d_namlen = name_len;
   1089  1.4.2.2  yamt 		strncpy(dirent.d_name, ndirent->name, name_len);
   1090  1.4.2.2  yamt 		dirent.d_reclen = _DIRENT_SIZE(&dirent);
   1091  1.4.2.2  yamt 		DPRINTF(DIRHASH, ("copying `%*.*s`\n", name_len,
   1092  1.4.2.2  yamt 			name_len, dirent.d_name));
   1093  1.4.2.2  yamt 
   1094  1.4.2.2  yamt 		/* XXX is it deleted? extra free space? */
   1095  1.4.2.2  yamt 		dirhash_enter(dirh, &dirent, diroffset,
   1096  1.4.2.2  yamt 			nilfs_rw16(ndirent->rec_len), 0);
   1097  1.4.2.2  yamt 
   1098  1.4.2.2  yamt 		/* advance */
   1099  1.4.2.2  yamt 		diroffset += nilfs_rw16(ndirent->rec_len);
   1100  1.4.2.2  yamt 		blkoff    += nilfs_rw16(ndirent->rec_len);
   1101  1.4.2.2  yamt 	}
   1102  1.4.2.2  yamt 	brelse(bp, BC_AGE);
   1103  1.4.2.2  yamt 
   1104  1.4.2.2  yamt 	dirh->flags |= DIRH_COMPLETE;
   1105  1.4.2.2  yamt 
   1106  1.4.2.2  yamt 	return 0;
   1107  1.4.2.2  yamt }
   1108  1.4.2.2  yamt 
   1109  1.4.2.2  yamt 
   1110  1.4.2.2  yamt int
   1111  1.4.2.2  yamt nilfs_lookup_name_in_dir(struct vnode *dvp, const char *name, int namelen,
   1112  1.4.2.2  yamt 		uint64_t *ino, int *found)
   1113  1.4.2.2  yamt {
   1114  1.4.2.2  yamt 	struct nilfs_node	*dir_node = VTOI(dvp);
   1115  1.4.2.2  yamt 	struct nilfs_dir_entry *ndirent;
   1116  1.4.2.2  yamt 	struct dirhash		*dirh;
   1117  1.4.2.2  yamt 	struct dirhash_entry	*dirh_ep;
   1118  1.4.2.2  yamt 	struct buf *bp;
   1119  1.4.2.2  yamt 	uint64_t diroffset, blkoff;
   1120  1.4.2.2  yamt 	uint64_t blocknr;
   1121  1.4.2.2  yamt 	uint32_t blocksize = dir_node->nilfsdev->blocksize;
   1122  1.4.2.2  yamt 	uint8_t *pos;
   1123  1.4.2.2  yamt 	int hit, error;
   1124  1.4.2.2  yamt 
   1125  1.4.2.2  yamt 	/* set default return */
   1126  1.4.2.2  yamt 	*found = 0;
   1127  1.4.2.2  yamt 
   1128  1.4.2.2  yamt 	/* get our dirhash and make sure its read in */
   1129  1.4.2.2  yamt 	dirhash_get(&dir_node->dir_hash);
   1130  1.4.2.2  yamt 	error = dirhash_fill(dir_node);
   1131  1.4.2.2  yamt 	if (error) {
   1132  1.4.2.2  yamt 		dirhash_put(dir_node->dir_hash);
   1133  1.4.2.2  yamt 		return error;
   1134  1.4.2.2  yamt 	}
   1135  1.4.2.2  yamt 	dirh = dir_node->dir_hash;
   1136  1.4.2.2  yamt 
   1137  1.4.2.2  yamt 	/* allocate temporary space for fid */
   1138  1.4.2.2  yamt 
   1139  1.4.2.2  yamt 	DPRINTF(DIRHASH, ("dirhash_lookup looking for `%*.*s`\n",
   1140  1.4.2.2  yamt 		namelen, namelen, name));
   1141  1.4.2.2  yamt 
   1142  1.4.2.2  yamt 	/* search our dirhash hits */
   1143  1.4.2.2  yamt 	*ino = 0;
   1144  1.4.2.2  yamt 	dirh_ep = NULL;
   1145  1.4.2.2  yamt 	for (;;) {
   1146  1.4.2.2  yamt 		hit = dirhash_lookup(dirh, name, namelen, &dirh_ep);
   1147  1.4.2.2  yamt 		/* if no hit, abort the search */
   1148  1.4.2.2  yamt 		if (!hit)
   1149  1.4.2.2  yamt 			break;
   1150  1.4.2.2  yamt 
   1151  1.4.2.2  yamt 		/* check this hit */
   1152  1.4.2.2  yamt 		diroffset = dirh_ep->offset;
   1153  1.4.2.2  yamt 
   1154  1.4.2.2  yamt 		blocknr = diroffset / blocksize;
   1155  1.4.2.2  yamt 		blkoff  = diroffset % blocksize;
   1156  1.4.2.2  yamt 		error = nilfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
   1157  1.4.2.2  yamt 		if (error)
   1158  1.4.2.2  yamt 			return EIO;
   1159  1.4.2.2  yamt 
   1160  1.4.2.2  yamt 		/* read in one dirent */
   1161  1.4.2.2  yamt 		pos = (uint8_t *) bp->b_data + blkoff;
   1162  1.4.2.2  yamt 		ndirent = (struct nilfs_dir_entry *) pos;
   1163  1.4.2.2  yamt 
   1164  1.4.2.2  yamt 		DPRINTF(DIRHASH, ("dirhash_lookup\tchecking `%*.*s`\n",
   1165  1.4.2.2  yamt 			ndirent->name_len, ndirent->name_len, ndirent->name));
   1166  1.4.2.2  yamt 
   1167  1.4.2.2  yamt 		/* see if its our entry */
   1168  1.4.2.2  yamt 		KASSERT(ndirent->name_len == namelen);
   1169  1.4.2.2  yamt 		if (strncmp(ndirent->name, name, namelen) == 0) {
   1170  1.4.2.2  yamt 			*found = 1;
   1171  1.4.2.2  yamt 			*ino = nilfs_rw64(ndirent->inode);
   1172  1.4.2.2  yamt 			brelse(bp, BC_AGE);
   1173  1.4.2.2  yamt 			break;
   1174  1.4.2.2  yamt 		}
   1175  1.4.2.2  yamt 		brelse(bp, BC_AGE);
   1176  1.4.2.2  yamt 	}
   1177  1.4.2.2  yamt 
   1178  1.4.2.2  yamt 	dirhash_put(dir_node->dir_hash);
   1179  1.4.2.2  yamt 
   1180  1.4.2.2  yamt 	return error;
   1181  1.4.2.2  yamt }
   1182  1.4.2.2  yamt 
   1183  1.4.2.2  yamt 
   1184  1.4.2.2  yamt int
   1185  1.4.2.2  yamt nilfs_dir_detach(struct nilfs_mount *ump, struct nilfs_node *dir_node, struct nilfs_node *node, struct componentname *cnp)
   1186  1.4.2.2  yamt {
   1187  1.4.2.2  yamt 	return EROFS;
   1188  1.4.2.2  yamt }
   1189  1.4.2.2  yamt 
   1190  1.4.2.2  yamt 
   1191  1.4.2.2  yamt int
   1192  1.4.2.2  yamt nilfs_dir_attach(struct nilfs_mount *ump, struct nilfs_node *dir_node, struct nilfs_node *node, struct vattr *vap, struct componentname *cnp)
   1193  1.4.2.2  yamt {
   1194  1.4.2.2  yamt 	return EROFS;
   1195  1.4.2.2  yamt }
   1196  1.4.2.2  yamt 
   1197  1.4.2.2  yamt 
   1198  1.4.2.2  yamt /* XXX return vnode? */
   1199  1.4.2.2  yamt int
   1200  1.4.2.2  yamt nilfs_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap, struct componentname *cnp)
   1201  1.4.2.2  yamt {
   1202  1.4.2.2  yamt 	return EROFS;
   1203  1.4.2.2  yamt }
   1204  1.4.2.2  yamt 
   1205  1.4.2.2  yamt 
   1206  1.4.2.2  yamt void
   1207  1.4.2.2  yamt nilfs_delete_node(struct nilfs_node *node)
   1208  1.4.2.2  yamt {
   1209  1.4.2.2  yamt }
   1210  1.4.2.2  yamt 
   1211  1.4.2.2  yamt 
   1212