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