nilfs_subr.c revision 1.15 1 1.15 reinoud /* $NetBSD: nilfs_subr.c,v 1.15 2020/03/21 13:39:31 reinoud 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.15 reinoud __KERNEL_RCSID(0, "$NetBSD: nilfs_subr.c,v 1.15 2020/03/21 13:39:31 reinoud 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.1 reinoud DPRINTF(VOLUMES, ("nilfs: seach_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