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