1 1.16 msaitoh /* $NetBSD: nilfs_subr.c,v 1.16 2021/12/05 07:47:40 msaitoh 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.16 msaitoh __KERNEL_RCSID(0, "$NetBSD: nilfs_subr.c,v 1.16 2021/12/05 07:47:40 msaitoh 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 /* dev reading */ 129 1.1 reinoud static int 130 1.1 reinoud nilfs_dev_bread(struct nilfs_device *nilfsdev, uint64_t blocknr, 131 1.14 riastrad int flags, struct buf **bpp) 132 1.1 reinoud { 133 1.1 reinoud int blk2dev = nilfsdev->blocksize / DEV_BSIZE; 134 1.1 reinoud 135 1.1 reinoud return bread(nilfsdev->devvp, blocknr * blk2dev, nilfsdev->blocksize, 136 1.13 maxv 0, bpp); 137 1.1 reinoud } 138 1.1 reinoud 139 1.1 reinoud 140 1.1 reinoud /* read on a node */ 141 1.1 reinoud int 142 1.1 reinoud nilfs_bread(struct nilfs_node *node, uint64_t blocknr, 143 1.14 riastrad int flags, struct buf **bpp) 144 1.1 reinoud { 145 1.11 hannken struct nilfs_device *nilfsdev = node->nilfsdev; 146 1.11 hannken uint64_t vblocknr, pblockno; 147 1.5 reinoud int error; 148 1.5 reinoud 149 1.5 reinoud error = nilfs_btree_lookup(node, blocknr, &vblocknr); 150 1.5 reinoud if (error) 151 1.5 reinoud return error; 152 1.11 hannken 153 1.11 hannken /* Read special files through devvp as they have no vnode attached. */ 154 1.11 hannken if (node->ino < NILFS_USER_INO && node->ino != NILFS_ROOT_INO) { 155 1.11 hannken error = nilfs_nvtop(node, 1, &vblocknr, &pblockno); 156 1.11 hannken if (error) 157 1.11 hannken return error; 158 1.14 riastrad return nilfs_dev_bread(nilfsdev, pblockno, flags, bpp); 159 1.11 hannken } 160 1.11 hannken 161 1.5 reinoud return bread(node->vnode, vblocknr, node->nilfsdev->blocksize, 162 1.13 maxv flags, bpp); 163 1.1 reinoud } 164 1.1 reinoud 165 1.1 reinoud 166 1.1 reinoud /* segment-log reading */ 167 1.1 reinoud int 168 1.1 reinoud nilfs_get_segment_log(struct nilfs_device *nilfsdev, uint64_t *blocknr, 169 1.1 reinoud uint64_t *offset, struct buf **bpp, int len, void *blob) 170 1.1 reinoud { 171 1.1 reinoud int blocksize = nilfsdev->blocksize; 172 1.1 reinoud int error; 173 1.1 reinoud 174 1.1 reinoud KASSERT(len <= blocksize); 175 1.1 reinoud 176 1.1 reinoud if (*offset + len > blocksize) { 177 1.1 reinoud *blocknr = *blocknr + 1; 178 1.1 reinoud *offset = 0; 179 1.1 reinoud } 180 1.1 reinoud if (*offset == 0) { 181 1.1 reinoud if (*bpp) 182 1.1 reinoud brelse(*bpp, BC_AGE); 183 1.1 reinoud /* read in block */ 184 1.14 riastrad error = nilfs_dev_bread(nilfsdev, *blocknr, 0, bpp); 185 1.1 reinoud if (error) 186 1.1 reinoud return error; 187 1.1 reinoud } 188 1.1 reinoud memcpy(blob, ((uint8_t *) (*bpp)->b_data) + *offset, len); 189 1.1 reinoud *offset += len; 190 1.1 reinoud 191 1.1 reinoud return 0; 192 1.1 reinoud } 193 1.1 reinoud 194 1.1 reinoud /* -------------------------------------------------------------------------- */ 195 1.1 reinoud 196 1.1 reinoud /* btree operations */ 197 1.1 reinoud 198 1.1 reinoud static int 199 1.1 reinoud nilfs_btree_lookup_level(struct nilfs_node *node, uint64_t lblocknr, 200 1.1 reinoud uint64_t btree_vblknr, int level, uint64_t *vblocknr) 201 1.1 reinoud { 202 1.1 reinoud struct nilfs_device *nilfsdev = node->nilfsdev; 203 1.1 reinoud struct nilfs_btree_node *btree_hdr; 204 1.1 reinoud struct buf *bp; 205 1.1 reinoud uint64_t btree_blknr; 206 1.1 reinoud uint64_t *dkeys, *dptrs, child_btree_blk; 207 1.1 reinoud uint8_t *pos; 208 1.1 reinoud int i, error, selected; 209 1.1 reinoud 210 1.1 reinoud DPRINTF(TRANSLATE, ("nilfs_btree_lookup_level ino %"PRIu64", " 211 1.1 reinoud "lblocknr %"PRIu64", btree_vblknr %"PRIu64", level %d\n", 212 1.1 reinoud node->ino, lblocknr, btree_vblknr, level)); 213 1.1 reinoud 214 1.1 reinoud /* translate btree_vblknr */ 215 1.1 reinoud error = nilfs_nvtop(node, 1, &btree_vblknr, &btree_blknr); 216 1.1 reinoud if (error) 217 1.1 reinoud return error; 218 1.1 reinoud 219 1.1 reinoud /* get our block */ 220 1.14 riastrad error = nilfs_dev_bread(nilfsdev, btree_blknr, 0, &bp); 221 1.1 reinoud if (error) { 222 1.1 reinoud return error; 223 1.1 reinoud } 224 1.1 reinoud 225 1.1 reinoud btree_hdr = (struct nilfs_btree_node *) bp->b_data; 226 1.1 reinoud pos = (uint8_t *) bp->b_data + 227 1.1 reinoud sizeof(struct nilfs_btree_node) + 228 1.1 reinoud NILFS_BTREE_NODE_EXTRA_PAD_SIZE; 229 1.1 reinoud dkeys = (uint64_t *) pos; 230 1.1 reinoud dptrs = dkeys + NILFS_BTREE_NODE_NCHILDREN_MAX(nilfsdev->blocksize); 231 1.1 reinoud 232 1.1 reinoud assert((btree_hdr->bn_flags & NILFS_BTREE_NODE_ROOT) == 0); 233 1.15 reinoud assert((btree_hdr->bn_level == level)); 234 1.1 reinoud 235 1.1 reinoud /* select matching child XXX could use binary search */ 236 1.1 reinoud selected = 0; 237 1.1 reinoud for (i = 0; i < nilfs_rw16(btree_hdr->bn_nchildren); i++) { 238 1.1 reinoud if (dkeys[i] > lblocknr) 239 1.1 reinoud break; 240 1.1 reinoud selected = i; 241 1.1 reinoud } 242 1.1 reinoud 243 1.1 reinoud if (level == 1) { 244 1.1 reinoud /* if found it mapped */ 245 1.1 reinoud if (dkeys[selected] == lblocknr) 246 1.1 reinoud *vblocknr = dptrs[selected]; 247 1.1 reinoud brelse(bp, BC_AGE); 248 1.1 reinoud return 0; 249 1.1 reinoud } 250 1.1 reinoud 251 1.1 reinoud /* lookup in selected child */ 252 1.1 reinoud assert(dkeys[selected] <= lblocknr); 253 1.1 reinoud child_btree_blk = dptrs[selected]; 254 1.1 reinoud brelse(bp, BC_AGE); 255 1.1 reinoud 256 1.1 reinoud return nilfs_btree_lookup_level(node, lblocknr, 257 1.15 reinoud child_btree_blk, level-1, vblocknr); 258 1.1 reinoud } 259 1.1 reinoud 260 1.1 reinoud 261 1.1 reinoud /* internal function */ 262 1.1 reinoud static int 263 1.1 reinoud nilfs_btree_lookup(struct nilfs_node *node, uint64_t lblocknr, 264 1.1 reinoud uint64_t *vblocknr) 265 1.1 reinoud { 266 1.1 reinoud struct nilfs_inode *inode = &node->inode; 267 1.1 reinoud struct nilfs_btree_node *btree_hdr; 268 1.1 reinoud uint64_t *dkeys, *dptrs, *dtrans; 269 1.1 reinoud int i, selected; 270 1.1 reinoud int error; 271 1.1 reinoud 272 1.1 reinoud DPRINTF(TRANSLATE, ("nilfs_btree_lookup ino %"PRIu64", " 273 1.1 reinoud "lblocknr %"PRIu64"\n", node->ino, lblocknr)); 274 1.1 reinoud 275 1.1 reinoud btree_hdr = (struct nilfs_btree_node *) &inode->i_bmap[0]; 276 1.1 reinoud dkeys = &inode->i_bmap[1]; 277 1.1 reinoud dptrs = dkeys + NILFS_BTREE_ROOT_NCHILDREN_MAX; 278 1.1 reinoud dtrans = &inode->i_bmap[1]; 279 1.1 reinoud 280 1.1 reinoud /* SMALL, direct lookup */ 281 1.1 reinoud *vblocknr = 0; 282 1.1 reinoud if ((btree_hdr->bn_flags & NILFS_BMAP_LARGE) == 0) { 283 1.1 reinoud if (lblocknr < NILFS_DIRECT_NBLOCKS) { 284 1.1 reinoud *vblocknr = dtrans[lblocknr]; 285 1.1 reinoud return 0; 286 1.1 reinoud } 287 1.1 reinoud /* not mapped XXX could be considered error here */ 288 1.1 reinoud return 0; 289 1.1 reinoud } 290 1.1 reinoud 291 1.1 reinoud /* LARGE, select matching child; XXX could use binary search */ 292 1.1 reinoud dtrans = NULL; 293 1.1 reinoud error = 0; 294 1.1 reinoud selected = 0; 295 1.1 reinoud for (i = 0; i < nilfs_rw16(btree_hdr->bn_nchildren); i++) { 296 1.1 reinoud if (dkeys[i] > lblocknr) 297 1.1 reinoud break; 298 1.1 reinoud selected = i; 299 1.1 reinoud } 300 1.2 reinoud 301 1.2 reinoud /* if selected key > lblocknr, its not mapped */ 302 1.2 reinoud if (dkeys[selected] > lblocknr) 303 1.2 reinoud return 0; 304 1.2 reinoud 305 1.1 reinoud /* overshooting? then not mapped */ 306 1.1 reinoud if (selected == nilfs_rw16(btree_hdr->bn_nchildren)) 307 1.1 reinoud return 0; 308 1.1 reinoud 309 1.2 reinoud /* level should be > 1 or otherwise it should be a direct one */ 310 1.2 reinoud assert(btree_hdr->bn_level > 1); 311 1.2 reinoud 312 1.1 reinoud /* lookup in selected child */ 313 1.1 reinoud assert(dkeys[selected] <= lblocknr); 314 1.1 reinoud error = nilfs_btree_lookup_level(node, lblocknr, 315 1.1 reinoud dptrs[selected], btree_hdr->bn_level-1, vblocknr); 316 1.1 reinoud 317 1.1 reinoud return error; 318 1.1 reinoud } 319 1.1 reinoud 320 1.1 reinoud 321 1.1 reinoud /* node should be locked on entry to prevent btree changes (unlikely) */ 322 1.1 reinoud int 323 1.1 reinoud nilfs_btree_nlookup(struct nilfs_node *node, uint64_t from, uint64_t blks, 324 1.1 reinoud uint64_t *l2vmap) 325 1.1 reinoud { 326 1.1 reinoud uint64_t lblocknr, *vblocknr; 327 1.1 reinoud int i, error; 328 1.1 reinoud 329 1.1 reinoud /* TODO / OPTI multiple translations in one go possible */ 330 1.1 reinoud error = EINVAL; 331 1.1 reinoud for (i = 0; i < blks; i++) { 332 1.1 reinoud lblocknr = from + i; 333 1.1 reinoud vblocknr = l2vmap + i; 334 1.1 reinoud error = nilfs_btree_lookup(node, lblocknr, vblocknr); 335 1.1 reinoud 336 1.1 reinoud DPRINTF(TRANSLATE, ("btree_nlookup ino %"PRIu64", " 337 1.1 reinoud "lblocknr %"PRIu64" -> %"PRIu64"\n", 338 1.1 reinoud node->ino, lblocknr, *vblocknr)); 339 1.1 reinoud if (error) 340 1.1 reinoud break; 341 1.1 reinoud } 342 1.1 reinoud 343 1.1 reinoud return error; 344 1.1 reinoud } 345 1.1 reinoud 346 1.1 reinoud /* --------------------------------------------------------------------- */ 347 1.1 reinoud 348 1.1 reinoud /* vtop operations */ 349 1.1 reinoud 350 1.1 reinoud /* translate index to a file block number and an entry */ 351 1.12 hannken void 352 1.1 reinoud nilfs_mdt_trans(struct nilfs_mdt *mdt, uint64_t index, 353 1.1 reinoud uint64_t *blocknr, uint32_t *entry_in_block) 354 1.1 reinoud { 355 1.1 reinoud uint64_t blknr; 356 1.1 reinoud uint64_t group, group_offset, blocknr_in_group; 357 1.1 reinoud uint64_t desc_block, desc_offset; 358 1.1 reinoud 359 1.1 reinoud /* calculate our offset in the file */ 360 1.1 reinoud group = index / mdt->entries_per_group; 361 1.1 reinoud group_offset = index % mdt->entries_per_group; 362 1.1 reinoud desc_block = group / mdt->groups_per_desc_block; 363 1.1 reinoud desc_offset = group % mdt->groups_per_desc_block; 364 1.1 reinoud blocknr_in_group = group_offset / mdt->entries_per_block; 365 1.1 reinoud 366 1.1 reinoud /* to descgroup offset */ 367 1.1 reinoud blknr = 1 + desc_block * mdt->blocks_per_desc_block; 368 1.1 reinoud 369 1.1 reinoud /* to group offset */ 370 1.1 reinoud blknr += desc_offset * mdt->blocks_per_group; 371 1.1 reinoud 372 1.1 reinoud /* to actual file block */ 373 1.1 reinoud blknr += 1 + blocknr_in_group; 374 1.1 reinoud 375 1.1 reinoud *blocknr = blknr; 376 1.1 reinoud *entry_in_block = group_offset % mdt->entries_per_block; 377 1.1 reinoud } 378 1.1 reinoud 379 1.1 reinoud 380 1.1 reinoud static int 381 1.1 reinoud nilfs_vtop(struct nilfs_device *nilfsdev, uint64_t vblocknr, uint64_t *pblocknr) 382 1.1 reinoud { 383 1.1 reinoud struct nilfs_dat_entry *entry; 384 1.1 reinoud struct buf *bp; 385 1.1 reinoud uint64_t ldatblknr; 386 1.1 reinoud uint32_t entry_in_block; 387 1.1 reinoud int error; 388 1.1 reinoud 389 1.1 reinoud nilfs_mdt_trans(&nilfsdev->dat_mdt, vblocknr, 390 1.1 reinoud &ldatblknr, &entry_in_block); 391 1.1 reinoud 392 1.14 riastrad error = nilfs_bread(nilfsdev->dat_node, ldatblknr, 0, &bp); 393 1.1 reinoud if (error) { 394 1.1 reinoud printf("vtop: can't read in DAT block %"PRIu64"!\n", ldatblknr); 395 1.1 reinoud return error; 396 1.1 reinoud } 397 1.1 reinoud 398 1.1 reinoud /* get our translation */ 399 1.1 reinoud entry = ((struct nilfs_dat_entry *) bp->b_data) + entry_in_block; 400 1.1 reinoud #if 0 401 1.1 reinoud printf("\tvblk %4"PRIu64" -> %"PRIu64" for " 402 1.1 reinoud "checkpoint %"PRIu64" to %"PRIu64"\n", 403 1.1 reinoud vblocknr, 404 1.1 reinoud nilfs_rw64(entry->de_blocknr), 405 1.1 reinoud nilfs_rw64(entry->de_start), 406 1.1 reinoud nilfs_rw64(entry->de_end)); 407 1.1 reinoud #endif 408 1.1 reinoud 409 1.1 reinoud *pblocknr = nilfs_rw64(entry->de_blocknr); 410 1.1 reinoud brelse(bp, BC_AGE); 411 1.1 reinoud 412 1.1 reinoud return 0; 413 1.1 reinoud } 414 1.1 reinoud 415 1.1 reinoud 416 1.1 reinoud int 417 1.1 reinoud nilfs_nvtop(struct nilfs_node *node, uint64_t blks, uint64_t *l2vmap, 418 1.1 reinoud uint64_t *v2pmap) 419 1.1 reinoud { 420 1.1 reinoud uint64_t vblocknr, *pblocknr; 421 1.1 reinoud int i, error; 422 1.1 reinoud 423 1.1 reinoud /* the DAT inode is the only one not mapped virtual */ 424 1.1 reinoud if (node->ino == NILFS_DAT_INO) { 425 1.1 reinoud memcpy(v2pmap, l2vmap, blks * sizeof(uint64_t)); 426 1.1 reinoud return 0; 427 1.1 reinoud } 428 1.1 reinoud 429 1.1 reinoud /* TODO / OPTI more translations in one go */ 430 1.2 reinoud error = 0; 431 1.1 reinoud for (i = 0; i < blks; i++) { 432 1.1 reinoud vblocknr = l2vmap[i]; 433 1.1 reinoud pblocknr = v2pmap + i; 434 1.2 reinoud *pblocknr = 0; 435 1.2 reinoud 436 1.1 reinoud /* only translate valid vblocknrs */ 437 1.1 reinoud if (vblocknr == 0) 438 1.1 reinoud continue; 439 1.1 reinoud error = nilfs_vtop(node->nilfsdev, vblocknr, pblocknr); 440 1.1 reinoud if (error) 441 1.1 reinoud break; 442 1.1 reinoud } 443 1.1 reinoud 444 1.1 reinoud return error; 445 1.1 reinoud } 446 1.1 reinoud 447 1.1 reinoud /* --------------------------------------------------------------------- */ 448 1.1 reinoud 449 1.1 reinoud struct nilfs_recover_info { 450 1.1 reinoud uint64_t segnum; 451 1.1 reinoud uint64_t pseg; 452 1.1 reinoud 453 1.1 reinoud struct nilfs_segment_summary segsum; 454 1.1 reinoud struct nilfs_super_root super_root; 455 1.1 reinoud STAILQ_ENTRY(nilfs_recover_info) next; 456 1.1 reinoud }; 457 1.1 reinoud 458 1.1 reinoud 459 1.1 reinoud /* 460 1.1 reinoud * Helper functions of nilfs_mount() that actually mounts the disc. 461 1.1 reinoud */ 462 1.1 reinoud static int 463 1.1 reinoud nilfs_load_segsum(struct nilfs_device *nilfsdev, 464 1.1 reinoud struct nilfs_recover_info *ri) 465 1.1 reinoud { 466 1.1 reinoud struct buf *bp; 467 1.1 reinoud uint64_t blocknr, offset; 468 1.1 reinoud uint32_t segsum_struct_size; 469 1.1 reinoud uint32_t magic; 470 1.1 reinoud int error; 471 1.1 reinoud 472 1.1 reinoud segsum_struct_size = sizeof(struct nilfs_segment_summary); 473 1.1 reinoud 474 1.1 reinoud /* read in segsum structure */ 475 1.1 reinoud bp = NULL; 476 1.1 reinoud blocknr = ri->pseg; 477 1.1 reinoud offset = 0; 478 1.1 reinoud error = nilfs_get_segment_log(nilfsdev, 479 1.1 reinoud &blocknr, &offset, &bp, 480 1.1 reinoud segsum_struct_size, (void *) &ri->segsum); 481 1.1 reinoud if (error) 482 1.1 reinoud goto out; 483 1.1 reinoud 484 1.1 reinoud /* sanity checks */ 485 1.1 reinoud magic = nilfs_rw32(ri->segsum.ss_magic); 486 1.1 reinoud if (magic != NILFS_SEGSUM_MAGIC) { 487 1.1 reinoud DPRINTF(VOLUMES, ("nilfs: bad magic in pseg %"PRIu64"\n", 488 1.1 reinoud ri->pseg)); 489 1.1 reinoud error = EINVAL; 490 1.1 reinoud goto out; 491 1.1 reinoud } 492 1.1 reinoud 493 1.1 reinoud /* TODO check segment summary checksum */ 494 1.1 reinoud /* TODO check data checksum */ 495 1.1 reinoud 496 1.1 reinoud out: 497 1.1 reinoud if (bp) 498 1.1 reinoud brelse(bp, BC_AGE); 499 1.1 reinoud 500 1.1 reinoud return error; 501 1.1 reinoud } 502 1.1 reinoud 503 1.1 reinoud 504 1.1 reinoud static int 505 1.1 reinoud nilfs_load_super_root(struct nilfs_device *nilfsdev, 506 1.1 reinoud struct nilfs_recover_info *ri) 507 1.1 reinoud { 508 1.1 reinoud struct nilfs_segment_summary *segsum = &ri->segsum; 509 1.4 reinoud struct nilfs_super_root *super_root; 510 1.1 reinoud struct buf *bp; 511 1.1 reinoud uint64_t blocknr, offset; 512 1.1 reinoud uint32_t segsum_size, size; 513 1.1 reinoud uint32_t nsumblk, nfileblk; 514 1.4 reinoud uint32_t super_root_crc, comp_crc; 515 1.4 reinoud int off, error; 516 1.1 reinoud 517 1.1 reinoud /* process segment summary */ 518 1.1 reinoud segsum_size = nilfs_rw32(segsum->ss_sumbytes); 519 1.1 reinoud nsumblk = (segsum_size - 1) / nilfsdev->blocksize + 1; 520 1.1 reinoud nfileblk = nilfs_rw32(segsum->ss_nblocks) - nsumblk; 521 1.1 reinoud 522 1.1 reinoud /* check if there is a superroot */ 523 1.1 reinoud if ((nilfs_rw16(segsum->ss_flags) & NILFS_SS_SR) == 0) { 524 1.1 reinoud DPRINTF(VOLUMES, ("nilfs: no super root in pseg %"PRIu64"\n", 525 1.1 reinoud ri->pseg)); 526 1.4 reinoud return ENOENT; 527 1.1 reinoud } 528 1.1 reinoud 529 1.1 reinoud /* get our super root, located at the end of the pseg */ 530 1.1 reinoud blocknr = ri->pseg + nsumblk + nfileblk - 1; 531 1.1 reinoud offset = 0; 532 1.1 reinoud size = sizeof(struct nilfs_super_root); 533 1.4 reinoud bp = NULL; 534 1.1 reinoud error = nilfs_get_segment_log(nilfsdev, 535 1.1 reinoud &blocknr, &offset, &bp, 536 1.1 reinoud size, (void *) &nilfsdev->super_root); 537 1.4 reinoud if (bp) 538 1.4 reinoud brelse(bp, BC_AGE); 539 1.1 reinoud if (error) { 540 1.1 reinoud printf("read in of superroot failed\n"); 541 1.4 reinoud return EIO; 542 1.4 reinoud } 543 1.4 reinoud 544 1.4 reinoud /* check super root crc */ 545 1.4 reinoud super_root = &nilfsdev->super_root; 546 1.4 reinoud super_root_crc = nilfs_rw32(super_root->sr_sum); 547 1.4 reinoud off = sizeof(super_root->sr_sum); 548 1.4 reinoud comp_crc = crc32_le(nilfs_rw32(nilfsdev->super.s_crc_seed), 549 1.4 reinoud (uint8_t *) super_root + off, 550 1.4 reinoud NILFS_SR_BYTES - off); 551 1.4 reinoud if (super_root_crc != comp_crc) { 552 1.4 reinoud DPRINTF(VOLUMES, (" invalid superroot, likely from old format\n")); 553 1.4 reinoud return EINVAL; 554 1.1 reinoud } 555 1.1 reinoud 556 1.4 reinoud DPRINTF(VOLUMES, (" got valid superroot\n")); 557 1.1 reinoud 558 1.4 reinoud return 0; 559 1.1 reinoud } 560 1.1 reinoud 561 1.1 reinoud /* 562 1.1 reinoud * Search for the last super root recorded. 563 1.1 reinoud */ 564 1.1 reinoud void 565 1.1 reinoud nilfs_search_super_root(struct nilfs_device *nilfsdev) 566 1.1 reinoud { 567 1.1 reinoud struct nilfs_super_block *super; 568 1.1 reinoud struct nilfs_segment_summary *segsum; 569 1.1 reinoud struct nilfs_recover_info *ri, *ori, *i_ri; 570 1.1 reinoud STAILQ_HEAD(,nilfs_recover_info) ri_list; 571 1.1 reinoud uint64_t seg_start, seg_end, cno; 572 1.1 reinoud uint32_t segsum_size; 573 1.1 reinoud uint32_t nsumblk, nfileblk; 574 1.1 reinoud int error; 575 1.1 reinoud 576 1.1 reinoud STAILQ_INIT(&ri_list); 577 1.1 reinoud 578 1.1 reinoud /* search for last super root */ 579 1.1 reinoud ri = malloc(sizeof(struct nilfs_recover_info), M_NILFSTEMP, M_WAITOK); 580 1.1 reinoud memset(ri, 0, sizeof(struct nilfs_recover_info)); 581 1.1 reinoud 582 1.1 reinoud /* if enabled, start from the specified position */ 583 1.1 reinoud if (0) { 584 1.1 reinoud /* start from set start */ 585 1.1 reinoud nilfsdev->super.s_last_pseg = nilfsdev->super.s_first_data_block; 586 1.1 reinoud nilfsdev->super.s_last_cno = nilfs_rw64(1); 587 1.1 reinoud } 588 1.1 reinoud 589 1.1 reinoud ri->pseg = nilfs_rw64(nilfsdev->super.s_last_pseg); /* blknr */ 590 1.1 reinoud ri->segnum = nilfs_get_segnum_of_block(nilfsdev, ri->pseg); 591 1.1 reinoud 592 1.1 reinoud error = 0; 593 1.1 reinoud cno = nilfs_rw64(nilfsdev->super.s_last_cno); 594 1.16 msaitoh DPRINTF(VOLUMES, ("nilfs: search_super_root start in pseg %"PRIu64"\n", 595 1.1 reinoud ri->pseg)); 596 1.1 reinoud for (;;) { 597 1.1 reinoud DPRINTF(VOLUMES, (" at pseg %"PRIu64"\n", ri->pseg)); 598 1.1 reinoud error = nilfs_load_segsum(nilfsdev, ri); 599 1.1 reinoud if (error) 600 1.1 reinoud break; 601 1.1 reinoud 602 1.1 reinoud segsum = &ri->segsum; 603 1.1 reinoud 604 1.1 reinoud /* try to load super root */ 605 1.1 reinoud if (nilfs_rw16(segsum->ss_flags) & NILFS_SS_SR) { 606 1.1 reinoud DPRINTF(VOLUMES, (" try super root\n")); 607 1.1 reinoud error = nilfs_load_super_root(nilfsdev, ri); 608 1.1 reinoud if (error) 609 1.1 reinoud break; /* confused */ 610 1.1 reinoud /* wipe current list of ri */ 611 1.1 reinoud while (!STAILQ_EMPTY(&ri_list)) { 612 1.1 reinoud i_ri = STAILQ_FIRST(&ri_list); 613 1.1 reinoud STAILQ_REMOVE_HEAD(&ri_list, next); 614 1.1 reinoud free(i_ri, M_NILFSTEMP); 615 1.1 reinoud } 616 1.1 reinoud super = &nilfsdev->super; 617 1.1 reinoud 618 1.1 reinoud super->s_last_pseg = nilfs_rw64(ri->pseg); 619 1.1 reinoud super->s_last_cno = cno++; 620 1.1 reinoud super->s_last_seq = segsum->ss_seq; 621 1.1 reinoud super->s_state = nilfs_rw16(NILFS_VALID_FS); 622 1.1 reinoud } else { 623 1.1 reinoud STAILQ_INSERT_TAIL(&ri_list, ri, next); 624 1.1 reinoud ori = ri; 625 1.1 reinoud ri = malloc(sizeof(struct nilfs_recover_info), 626 1.1 reinoud M_NILFSTEMP, M_WAITOK); 627 1.1 reinoud memset(ri, 0, sizeof(struct nilfs_recover_info)); 628 1.1 reinoud ri->segnum = ori->segnum; 629 1.1 reinoud ri->pseg = ori->pseg; 630 1.1 reinoud /* segsum keeps pointing to the `old' ri */ 631 1.1 reinoud } 632 1.1 reinoud 633 1.1 reinoud /* continue to the next pseg */ 634 1.1 reinoud segsum_size = nilfs_rw32(segsum->ss_sumbytes); 635 1.1 reinoud nsumblk = (segsum_size - 1) / nilfsdev->blocksize + 1; 636 1.1 reinoud nfileblk = nilfs_rw32(segsum->ss_nblocks) - nsumblk; 637 1.1 reinoud 638 1.1 reinoud /* calculate next partial segment location */ 639 1.1 reinoud ri->pseg += nsumblk + nfileblk; 640 1.1 reinoud 641 1.1 reinoud /* did we reach the end of the segment? if so, go to the next */ 642 1.1 reinoud nilfs_get_segment_range(nilfsdev, ri->segnum, &seg_start, &seg_end); 643 1.1 reinoud if (ri->pseg >= seg_end) 644 1.1 reinoud ri->pseg = nilfs_rw64(segsum->ss_next); 645 1.1 reinoud ri->segnum = nilfs_get_segnum_of_block(nilfsdev, ri->pseg); 646 1.1 reinoud } 647 1.1 reinoud 648 1.1 reinoud /* 649 1.1 reinoud * XXX No roll-forward yet of the remaining partial segments. 650 1.1 reinoud */ 651 1.1 reinoud 652 1.1 reinoud /* wipe current list of ri */ 653 1.1 reinoud while (!STAILQ_EMPTY(&ri_list)) { 654 1.1 reinoud i_ri = STAILQ_FIRST(&ri_list); 655 1.1 reinoud STAILQ_REMOVE_HEAD(&ri_list, next); 656 1.1 reinoud printf("nilfs: ignoring pseg at %"PRIu64"\n", i_ri->pseg); 657 1.1 reinoud free(i_ri, M_NILFSTEMP); 658 1.1 reinoud } 659 1.1 reinoud free(ri, M_NILFSTEMP); 660 1.1 reinoud } 661 1.1 reinoud 662 1.1 reinoud /* --------------------------------------------------------------------- */ 663 1.1 reinoud 664 1.1 reinoud int 665 1.1 reinoud nilfs_get_node_raw(struct nilfs_device *nilfsdev, struct nilfs_mount *ump, 666 1.1 reinoud uint64_t ino, struct nilfs_inode *inode, struct nilfs_node **nodep) 667 1.1 reinoud { 668 1.1 reinoud struct nilfs_node *node; 669 1.1 reinoud 670 1.1 reinoud *nodep = NULL; 671 1.1 reinoud 672 1.1 reinoud node = pool_get(&nilfs_node_pool, PR_WAITOK); 673 1.1 reinoud memset(node, 0, sizeof(struct nilfs_node)); 674 1.1 reinoud 675 1.1 reinoud /* crosslink */ 676 1.1 reinoud node->ump = ump; 677 1.1 reinoud node->nilfsdev = nilfsdev; 678 1.1 reinoud 679 1.1 reinoud /* initiase nilfs node */ 680 1.1 reinoud node->ino = ino; 681 1.1 reinoud node->inode = *inode; 682 1.1 reinoud node->lockf = NULL; 683 1.1 reinoud 684 1.11 hannken /* initialise locks */ 685 1.1 reinoud mutex_init(&node->node_mutex, MUTEX_DEFAULT, IPL_NONE); 686 1.7 pgoyette cv_init(&node->node_lock, "nilfsnlk"); 687 1.1 reinoud 688 1.1 reinoud /* fixup inode size for system nodes */ 689 1.1 reinoud if ((ino < NILFS_USER_INO) && (ino != NILFS_ROOT_INO)) { 690 1.15 reinoud DPRINTF(VOLUMES, ("NEED TO GET my size for inode %"PRIu64"?\n", 691 1.1 reinoud ino)); 692 1.1 reinoud /* for now set it to maximum, -1 is illegal */ 693 1.15 reinoud DPRINTF(VOLUMES, (" current size of inode is %"PRIu64"\n", inode->i_size)); 694 1.1 reinoud inode->i_size = nilfs_rw64(((uint64_t) -2)); 695 1.1 reinoud } 696 1.1 reinoud 697 1.1 reinoud /* return node */ 698 1.1 reinoud *nodep = node; 699 1.1 reinoud return 0; 700 1.1 reinoud } 701 1.1 reinoud 702 1.1 reinoud void 703 1.1 reinoud nilfs_dispose_node(struct nilfs_node **nodep) 704 1.1 reinoud { 705 1.1 reinoud struct nilfs_node *node; 706 1.1 reinoud 707 1.1 reinoud /* protect against rogue values */ 708 1.1 reinoud if (!*nodep) 709 1.1 reinoud return; 710 1.1 reinoud 711 1.1 reinoud node = *nodep; 712 1.1 reinoud 713 1.1 reinoud /* remove dirhash if present */ 714 1.1 reinoud dirhash_purge(&node->dir_hash); 715 1.1 reinoud 716 1.1 reinoud /* destroy our locks */ 717 1.1 reinoud mutex_destroy(&node->node_mutex); 718 1.1 reinoud cv_destroy(&node->node_lock); 719 1.1 reinoud 720 1.1 reinoud /* free our associated memory */ 721 1.1 reinoud pool_put(&nilfs_node_pool, node); 722 1.1 reinoud 723 1.1 reinoud *nodep = NULL; 724 1.1 reinoud } 725 1.1 reinoud 726 1.1 reinoud 727 1.1 reinoud void 728 1.1 reinoud nilfs_itimes(struct nilfs_node *node, struct timespec *acc, 729 1.1 reinoud struct timespec *mod, struct timespec *birth) 730 1.1 reinoud { 731 1.1 reinoud } 732 1.1 reinoud 733 1.1 reinoud 734 1.1 reinoud int 735 1.1 reinoud nilfs_update(struct vnode *node, struct timespec *acc, 736 1.1 reinoud struct timespec *mod, struct timespec *birth, int updflags) 737 1.1 reinoud { 738 1.1 reinoud return EROFS; 739 1.1 reinoud } 740 1.1 reinoud 741 1.1 reinoud 742 1.1 reinoud int 743 1.1 reinoud nilfs_chsize(struct vnode *vp, u_quad_t newsize, kauth_cred_t cred) 744 1.1 reinoud { 745 1.1 reinoud return EROFS; 746 1.1 reinoud } 747 1.1 reinoud 748 1.1 reinoud 749 1.1 reinoud 750 1.1 reinoud int 751 1.1 reinoud nilfs_grow_node(struct nilfs_node *node, uint64_t new_size) 752 1.1 reinoud { 753 1.1 reinoud return EROFS; 754 1.1 reinoud } 755 1.1 reinoud 756 1.1 reinoud 757 1.1 reinoud int 758 1.1 reinoud nilfs_shrink_node(struct nilfs_node *node, uint64_t new_size) 759 1.1 reinoud { 760 1.1 reinoud return EROFS; 761 1.1 reinoud } 762 1.1 reinoud 763 1.1 reinoud 764 1.1 reinoud static int 765 1.1 reinoud dirhash_fill(struct nilfs_node *dir_node) 766 1.1 reinoud { 767 1.1 reinoud struct vnode *dvp = dir_node->vnode; 768 1.1 reinoud struct dirhash *dirh; 769 1.1 reinoud struct nilfs_dir_entry *ndirent; 770 1.1 reinoud struct dirent dirent; 771 1.1 reinoud struct buf *bp; 772 1.1 reinoud uint64_t file_size, diroffset, blkoff; 773 1.1 reinoud uint64_t blocknr; 774 1.1 reinoud uint32_t blocksize = dir_node->nilfsdev->blocksize; 775 1.1 reinoud uint8_t *pos, name_len; 776 1.1 reinoud int error; 777 1.1 reinoud 778 1.1 reinoud DPRINTF(CALL, ("dirhash_fill called\n")); 779 1.1 reinoud 780 1.1 reinoud if (dvp->v_type != VDIR) 781 1.1 reinoud return ENOTDIR; 782 1.1 reinoud 783 1.1 reinoud /* make sure we have a dirhash to work on */ 784 1.1 reinoud dirh = dir_node->dir_hash; 785 1.1 reinoud KASSERT(dirh); 786 1.1 reinoud KASSERT(dirh->refcnt > 0); 787 1.1 reinoud 788 1.1 reinoud if (dirh->flags & DIRH_BROKEN) 789 1.1 reinoud return EIO; 790 1.1 reinoud 791 1.1 reinoud if (dirh->flags & DIRH_COMPLETE) 792 1.1 reinoud return 0; 793 1.1 reinoud 794 1.1 reinoud DPRINTF(DIRHASH, ("Filling directory hash\n")); 795 1.1 reinoud 796 1.1 reinoud /* make sure we have a clean dirhash to add to */ 797 1.1 reinoud dirhash_purge_entries(dirh); 798 1.1 reinoud 799 1.1 reinoud /* get directory filesize */ 800 1.1 reinoud file_size = nilfs_rw64(dir_node->inode.i_size); 801 1.1 reinoud 802 1.1 reinoud /* walk the directory */ 803 1.1 reinoud error = 0; 804 1.1 reinoud diroffset = 0; 805 1.1 reinoud 806 1.1 reinoud blocknr = diroffset / blocksize; 807 1.1 reinoud blkoff = diroffset % blocksize; 808 1.14 riastrad error = nilfs_bread(dir_node, blocknr, 0, &bp); 809 1.1 reinoud if (error) { 810 1.1 reinoud dirh->flags |= DIRH_BROKEN; 811 1.1 reinoud dirhash_purge_entries(dirh); 812 1.1 reinoud return EIO; 813 1.1 reinoud } 814 1.1 reinoud while (diroffset < file_size) { 815 1.1 reinoud DPRINTF(READDIR, ("filldir : offset = %"PRIu64"\n", 816 1.1 reinoud diroffset)); 817 1.1 reinoud if (blkoff >= blocksize) { 818 1.1 reinoud blkoff = 0; blocknr++; 819 1.1 reinoud brelse(bp, BC_AGE); 820 1.14 riastrad error = nilfs_bread(dir_node, blocknr, 0, &bp); 821 1.1 reinoud if (error) { 822 1.1 reinoud dirh->flags |= DIRH_BROKEN; 823 1.1 reinoud dirhash_purge_entries(dirh); 824 1.1 reinoud return EIO; 825 1.1 reinoud } 826 1.1 reinoud } 827 1.1 reinoud 828 1.1 reinoud /* read in one dirent */ 829 1.1 reinoud pos = (uint8_t *) bp->b_data + blkoff; 830 1.1 reinoud ndirent = (struct nilfs_dir_entry *) pos; 831 1.1 reinoud name_len = ndirent->name_len; 832 1.1 reinoud 833 1.1 reinoud memset(&dirent, 0, sizeof(struct dirent)); 834 1.1 reinoud dirent.d_fileno = nilfs_rw64(ndirent->inode); 835 1.1 reinoud dirent.d_type = ndirent->file_type; /* 1:1 ? */ 836 1.1 reinoud dirent.d_namlen = name_len; 837 1.1 reinoud strncpy(dirent.d_name, ndirent->name, name_len); 838 1.1 reinoud dirent.d_reclen = _DIRENT_SIZE(&dirent); 839 1.1 reinoud DPRINTF(DIRHASH, ("copying `%*.*s`\n", name_len, 840 1.1 reinoud name_len, dirent.d_name)); 841 1.1 reinoud 842 1.1 reinoud /* XXX is it deleted? extra free space? */ 843 1.1 reinoud dirhash_enter(dirh, &dirent, diroffset, 844 1.1 reinoud nilfs_rw16(ndirent->rec_len), 0); 845 1.1 reinoud 846 1.1 reinoud /* advance */ 847 1.1 reinoud diroffset += nilfs_rw16(ndirent->rec_len); 848 1.1 reinoud blkoff += nilfs_rw16(ndirent->rec_len); 849 1.1 reinoud } 850 1.1 reinoud brelse(bp, BC_AGE); 851 1.1 reinoud 852 1.1 reinoud dirh->flags |= DIRH_COMPLETE; 853 1.1 reinoud 854 1.1 reinoud return 0; 855 1.1 reinoud } 856 1.1 reinoud 857 1.1 reinoud 858 1.1 reinoud int 859 1.1 reinoud nilfs_lookup_name_in_dir(struct vnode *dvp, const char *name, int namelen, 860 1.1 reinoud uint64_t *ino, int *found) 861 1.1 reinoud { 862 1.1 reinoud struct nilfs_node *dir_node = VTOI(dvp); 863 1.1 reinoud struct nilfs_dir_entry *ndirent; 864 1.1 reinoud struct dirhash *dirh; 865 1.1 reinoud struct dirhash_entry *dirh_ep; 866 1.1 reinoud struct buf *bp; 867 1.1 reinoud uint64_t diroffset, blkoff; 868 1.1 reinoud uint64_t blocknr; 869 1.1 reinoud uint32_t blocksize = dir_node->nilfsdev->blocksize; 870 1.1 reinoud uint8_t *pos; 871 1.1 reinoud int hit, error; 872 1.1 reinoud 873 1.1 reinoud /* set default return */ 874 1.1 reinoud *found = 0; 875 1.1 reinoud 876 1.1 reinoud /* get our dirhash and make sure its read in */ 877 1.1 reinoud dirhash_get(&dir_node->dir_hash); 878 1.1 reinoud error = dirhash_fill(dir_node); 879 1.1 reinoud if (error) { 880 1.1 reinoud dirhash_put(dir_node->dir_hash); 881 1.1 reinoud return error; 882 1.1 reinoud } 883 1.1 reinoud dirh = dir_node->dir_hash; 884 1.1 reinoud 885 1.1 reinoud /* allocate temporary space for fid */ 886 1.1 reinoud 887 1.1 reinoud DPRINTF(DIRHASH, ("dirhash_lookup looking for `%*.*s`\n", 888 1.1 reinoud namelen, namelen, name)); 889 1.1 reinoud 890 1.1 reinoud /* search our dirhash hits */ 891 1.1 reinoud *ino = 0; 892 1.1 reinoud dirh_ep = NULL; 893 1.1 reinoud for (;;) { 894 1.1 reinoud hit = dirhash_lookup(dirh, name, namelen, &dirh_ep); 895 1.1 reinoud /* if no hit, abort the search */ 896 1.1 reinoud if (!hit) 897 1.1 reinoud break; 898 1.1 reinoud 899 1.1 reinoud /* check this hit */ 900 1.1 reinoud diroffset = dirh_ep->offset; 901 1.1 reinoud 902 1.1 reinoud blocknr = diroffset / blocksize; 903 1.1 reinoud blkoff = diroffset % blocksize; 904 1.14 riastrad error = nilfs_bread(dir_node, blocknr, 0, &bp); 905 1.1 reinoud if (error) 906 1.1 reinoud return EIO; 907 1.1 reinoud 908 1.1 reinoud /* read in one dirent */ 909 1.1 reinoud pos = (uint8_t *) bp->b_data + blkoff; 910 1.1 reinoud ndirent = (struct nilfs_dir_entry *) pos; 911 1.1 reinoud 912 1.1 reinoud DPRINTF(DIRHASH, ("dirhash_lookup\tchecking `%*.*s`\n", 913 1.1 reinoud ndirent->name_len, ndirent->name_len, ndirent->name)); 914 1.1 reinoud 915 1.1 reinoud /* see if its our entry */ 916 1.1 reinoud KASSERT(ndirent->name_len == namelen); 917 1.1 reinoud if (strncmp(ndirent->name, name, namelen) == 0) { 918 1.1 reinoud *found = 1; 919 1.1 reinoud *ino = nilfs_rw64(ndirent->inode); 920 1.1 reinoud brelse(bp, BC_AGE); 921 1.1 reinoud break; 922 1.1 reinoud } 923 1.1 reinoud brelse(bp, BC_AGE); 924 1.1 reinoud } 925 1.1 reinoud 926 1.1 reinoud dirhash_put(dir_node->dir_hash); 927 1.1 reinoud 928 1.1 reinoud return error; 929 1.1 reinoud } 930 1.1 reinoud 931 1.1 reinoud 932 1.1 reinoud int 933 1.1 reinoud nilfs_dir_detach(struct nilfs_mount *ump, struct nilfs_node *dir_node, struct nilfs_node *node, struct componentname *cnp) 934 1.1 reinoud { 935 1.1 reinoud return EROFS; 936 1.1 reinoud } 937 1.1 reinoud 938 1.1 reinoud 939 1.1 reinoud int 940 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) 941 1.1 reinoud { 942 1.1 reinoud return EROFS; 943 1.1 reinoud } 944 1.1 reinoud 945 1.1 reinoud 946 1.1 reinoud /* XXX return vnode? */ 947 1.1 reinoud int 948 1.1 reinoud nilfs_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap, struct componentname *cnp) 949 1.1 reinoud { 950 1.1 reinoud return EROFS; 951 1.1 reinoud } 952 1.1 reinoud 953 1.1 reinoud 954 1.1 reinoud void 955 1.1 reinoud nilfs_delete_node(struct nilfs_node *node) 956 1.1 reinoud { 957 1.1 reinoud } 958 1.1 reinoud 959 1.1 reinoud 960