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