hammer2 - initial mkdir skeleton
[dragonfly.git] / sys / vfs / hammer2 / hammer2_vfsops.c
CommitLineData
47902fef 1/*-
703720e4
MD
2 * Copyright (c) 2011, 2012 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
703720e4
MD
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/kernel.h>
37#include <sys/nlookup.h>
38#include <sys/vnode.h>
39#include <sys/mount.h>
40#include <sys/fcntl.h>
41#include <sys/buf.h>
42#include <sys/uuid.h>
a74bc66c 43#include <sys/vfsops.h>
703720e4
MD
44
45#include "hammer2.h"
46#include "hammer2_disk.h"
47#include "hammer2_mount.h"
48
066e00cc
MD
49static int hammer2_vfs_init(struct vfsconf *conf);
50static int hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
703720e4
MD
51 struct ucred *cred);
52static int hammer2_remount(struct mount *, char *, struct vnode *,
53 struct ucred *);
066e00cc
MD
54static int hammer2_vfs_unmount(struct mount *mp, int mntflags);
55static int hammer2_vfs_root(struct mount *mp, struct vnode **vpp);
56static int hammer2_vfs_statfs(struct mount *mp, struct statfs *sbp,
703720e4 57 struct ucred *cred);
066e00cc 58static int hammer2_vfs_statvfs(struct mount *mp, struct statvfs *sbp,
703720e4 59 struct ucred *cred);
066e00cc
MD
60static int hammer2_vfs_sync(struct mount *mp, int waitfor);
61static int hammer2_vfs_vget(struct mount *mp, struct vnode *dvp,
703720e4 62 ino_t ino, struct vnode **vpp);
066e00cc 63static int hammer2_vfs_fhtovp(struct mount *mp, struct vnode *rootvp,
703720e4 64 struct fid *fhp, struct vnode **vpp);
066e00cc
MD
65static int hammer2_vfs_vptofh(struct vnode *vp, struct fid *fhp);
66static int hammer2_vfs_checkexp(struct mount *mp, struct sockaddr *nam,
703720e4
MD
67 int *exflagsp, struct ucred **credanonp);
68
50e4f8f4
MD
69static int hammer2_install_volume_header(hammer2_mount_t *hmp);
70
703720e4
MD
71/*
72 * HAMMER2 vfs operations.
73 */
74static struct vfsops hammer2_vfsops = {
066e00cc
MD
75 .vfs_init = hammer2_vfs_init,
76 .vfs_sync = hammer2_vfs_sync,
77 .vfs_mount = hammer2_vfs_mount,
78 .vfs_unmount = hammer2_vfs_unmount,
79 .vfs_root = hammer2_vfs_root,
80 .vfs_statfs = hammer2_vfs_statfs,
81 .vfs_statvfs = hammer2_vfs_statvfs,
82 .vfs_vget = hammer2_vfs_vget,
83 .vfs_vptofh = hammer2_vfs_vptofh,
84 .vfs_fhtovp = hammer2_vfs_fhtovp,
85 .vfs_checkexp = hammer2_vfs_checkexp
703720e4
MD
86};
87
703720e4
MD
88MALLOC_DEFINE(M_HAMMER2, "HAMMER2-mount", "");
89
90VFS_SET(hammer2_vfsops, hammer2, 0);
91MODULE_VERSION(hammer2, 1);
92
e118c14f
MD
93static
94int
066e00cc 95hammer2_vfs_init(struct vfsconf *conf)
703720e4
MD
96{
97 int error;
98
99 error = 0;
100
0e92b724 101 if (HAMMER2_BLOCKREF_BYTES != sizeof(struct hammer2_blockref))
703720e4 102 error = EINVAL;
0e92b724 103 if (HAMMER2_INODE_BYTES != sizeof(struct hammer2_inode_data))
703720e4 104 error = EINVAL;
0e92b724 105 if (HAMMER2_ALLOCREF_BYTES != sizeof(struct hammer2_allocref))
703720e4 106 error = EINVAL;
0e92b724 107 if (HAMMER2_VOLUME_BYTES != sizeof(struct hammer2_volume_data))
703720e4
MD
108 error = EINVAL;
109
110 if (error)
111 kprintf("HAMMER2 structure size mismatch; cannot continue.\n");
112
113 return (error);
114}
115
116/*
117 * Mount or remount HAMMER2 fileystem from physical media
118 *
119 * mountroot
120 * mp mount point structure
121 * path NULL
122 * data <unused>
123 * cred <unused>
124 *
125 * mount
126 * mp mount point structure
127 * path path to mount point
128 * data pointer to argument structure in user space
129 * volume volume path (device@LABEL form)
130 * hflags user mount flags
131 * cred user credentials
132 *
133 * RETURNS: 0 Success
134 * !0 error number
135 */
e118c14f
MD
136static
137int
066e00cc 138hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
703720e4
MD
139 struct ucred *cred)
140{
141 struct hammer2_mount_info info;
54eb943b 142 hammer2_mount_t *hmp;
7cfa8da5 143 hammer2_key_t lhc;
703720e4
MD
144 struct vnode *devvp;
145 struct nlookupdata nd;
5c23d7f1 146 hammer2_chain_t *parent;
7cfa8da5
MD
147 hammer2_chain_t *schain;
148 hammer2_chain_t *rchain;
703720e4
MD
149 char devstr[MNAMELEN];
150 size_t size;
151 size_t done;
50e4f8f4
MD
152 char *dev;
153 char *label;
54eb943b 154 int ronly = 1;
703720e4 155 int error;
703720e4
MD
156
157 hmp = NULL;
50e4f8f4
MD
158 dev = NULL;
159 label = NULL;
703720e4
MD
160 devvp = NULL;
161
162 kprintf("hammer2_mount\n");
163
164 if (path == NULL) {
165 /*
166 * Root mount
167 */
703720e4
MD
168 return (EOPNOTSUPP);
169 } else {
170 /*
171 * Non-root mount or updating a mount
172 */
703720e4
MD
173 error = copyin(data, &info, sizeof(info));
174 if (error)
175 return (error);
176
177 error = copyinstr(info.volume, devstr, MNAMELEN - 1, &done);
178 if (error)
179 return (error);
180
181 /* Extract device and label */
182 dev = devstr;
183 label = strchr(devstr, '@');
184 if (label == NULL ||
50e4f8f4 185 ((label + 1) - dev) > done) {
703720e4 186 return (EINVAL);
50e4f8f4 187 }
703720e4
MD
188 *label = '\0';
189 label++;
190 if (*label == '\0')
191 return (EINVAL);
192
193 if (mp->mnt_flag & MNT_UPDATE) {
194 /* Update mount */
195 /* HAMMER2 implements NFS export via mountctl */
196 hmp = MPTOH2(mp);
54eb943b
MD
197 devvp = hmp->devvp;
198 error = hammer2_remount(mp, path, devvp, cred);
199 return error;
703720e4
MD
200 }
201 }
202
203 /*
204 * New non-root mount
205 */
206 /* Lookup name and verify it refers to a block device */
207 error = nlookup_init(&nd, dev, UIO_SYSSPACE, NLC_FOLLOW);
54eb943b
MD
208 if (error == 0)
209 error = nlookup(&nd);
210 if (error == 0)
211 error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
703720e4
MD
212 nlookup_done(&nd);
213
54eb943b
MD
214 if (error == 0) {
215 if (vn_isdisk(devvp, &error))
216 error = vfs_mountedon(devvp);
703720e4 217 }
54eb943b
MD
218 if (error == 0 && vcount(devvp) > 0)
219 error = EBUSY;
703720e4
MD
220
221 /*
54eb943b 222 * Now open the device
703720e4 223 */
54eb943b
MD
224 if (error == 0) {
225 ronly = ((mp->mnt_flag & MNT_RDONLY) != 0);
226 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
227 error = vinvalbuf(devvp, V_SAVE, 0, 0);
228 if (error == 0) {
229 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD | FWRITE,
230 FSCRED, NULL);
231 }
232 vn_unlock(devvp);
703720e4 233 }
54eb943b 234 if (error && devvp) {
703720e4 235 vrele(devvp);
54eb943b 236 devvp = NULL;
703720e4 237 }
54eb943b
MD
238 if (error)
239 return error;
703720e4
MD
240
241 /*
54eb943b
MD
242 * Block device opened successfully, finish initializing the
243 * mount structure.
244 *
245 * From this point on we have to call hammer2_unmount() on failure.
703720e4 246 */
703720e4 247 hmp = kmalloc(sizeof(*hmp), M_HAMMER2, M_WAITOK | M_ZERO);
54eb943b
MD
248 mp->mnt_data = (qaddr_t)hmp;
249 hmp->mp = mp;
250 hmp->ronly = ronly;
251 hmp->devvp = devvp;
5c23d7f1
MD
252 kmalloc_create(&hmp->minode, "HAMMER2-inodes");
253 kmalloc_create(&hmp->mchain, "HAMMER2-chains");
74d91941 254
f0206a67 255 mp->mnt_flag = MNT_LOCAL;
50e4f8f4
MD
256 mp->mnt_kern_flag |= MNTK_ALL_MPSAFE; /* all entry pts are SMP */
257
5c23d7f1
MD
258 /*
259 * vchain setup. vchain.data is special cased to NULL. vchain.refs
260 * is initialized and will never drop to 0.
261 */
232a50f9 262 hmp->vchain.bref.type = HAMMER2_BREF_TYPE_VOLUME;
5c23d7f1
MD
263 hmp->vchain.refs = 1;
264 /* hmp->vchain.data is special cased to NULL */
265 lockinit(&hmp->vchain.lk, "volume", 0, LK_CANRECURSE);
232a50f9 266
50e4f8f4
MD
267 /*
268 * Install the volume header
269 */
270 error = hammer2_install_volume_header(hmp);
271 if (error) {
066e00cc 272 hammer2_vfs_unmount(mp, MNT_FORCE);
50e4f8f4
MD
273 return error;
274 }
703720e4
MD
275
276 /*
50e4f8f4 277 * required mount structure initializations
703720e4 278 */
50e4f8f4
MD
279 mp->mnt_stat.f_iosize = HAMMER2_PBUFSIZE;
280 mp->mnt_stat.f_bsize = HAMMER2_PBUFSIZE;
281
282 mp->mnt_vstat.f_frsize = HAMMER2_PBUFSIZE;
283 mp->mnt_vstat.f_bsize = HAMMER2_PBUFSIZE;
284
285 /*
7cfa8da5
MD
286 * First locate the super-root inode, which is key 0 relative to the
287 * volume header's blockset.
288 *
289 * Then locate the root inode by scanning the directory keyspace
290 * represented by the label.
50e4f8f4 291 */
7cfa8da5 292 lhc = hammer2_dirhash(label, strlen(label));
5c23d7f1
MD
293 parent = &hmp->vchain;
294 hammer2_chain_ref(hmp, parent);
295 hammer2_chain_lock(hmp, parent);
296 schain = hammer2_chain_lookup(hmp, &parent,
e028fa74 297 HAMMER2_SROOT_KEY, HAMMER2_SROOT_KEY);
5c23d7f1 298 hammer2_chain_put(hmp, parent);
7cfa8da5
MD
299 if (schain == NULL) {
300 kprintf("hammer2_mount: invalid super-root\n");
066e00cc 301 hammer2_vfs_unmount(mp, MNT_FORCE);
7cfa8da5
MD
302 return EINVAL;
303 }
5c23d7f1
MD
304
305 parent = schain;
9c2e0de0 306 hammer2_chain_ref(hmp, parent); /* parent: lock+ref, schain: ref */
5c23d7f1 307 rchain = hammer2_chain_lookup(hmp, &parent,
e028fa74 308 lhc, lhc + HAMMER2_DIRHASH_LOMASK);
7cfa8da5
MD
309 while (rchain) {
310 if (rchain->bref.type == HAMMER2_BREF_TYPE_INODE &&
311 rchain->u.ip &&
5c23d7f1 312 strcmp(label, rchain->data->ipdata.filename) == 0) {
7cfa8da5
MD
313 break;
314 }
5c23d7f1 315 rchain = hammer2_chain_next(hmp, &parent, rchain,
e028fa74 316 lhc, lhc + HAMMER2_DIRHASH_LOMASK);
7cfa8da5 317 }
5c23d7f1 318 hammer2_chain_put(hmp, parent);
7cfa8da5
MD
319 if (rchain == NULL) {
320 kprintf("hammer2_mount: root label not found\n");
321 hammer2_chain_drop(hmp, schain);
9c2e0de0 322 hammer2_vfs_unmount(mp, MNT_FORCE);
7cfa8da5
MD
323 return EINVAL;
324 }
9c2e0de0 325 hammer2_chain_unlock(hmp, rchain); /* rchain: ref */
5c23d7f1
MD
326
327 hmp->schain = schain; /* left held & unlocked */
328 hmp->rchain = rchain; /* left held & unlocked */
329 hmp->iroot = rchain->u.ip; /* implied hold from rchain */
df9ea374 330 kprintf("iroot %p\n", rchain->u.ip);
703720e4 331
f0206a67
VS
332 vfs_getnewfsid(mp);
333 vfs_add_vnodeops(mp, &hammer2_vnode_vops, &mp->mnt_vn_norm_ops);
334 vfs_add_vnodeops(mp, &hammer2_spec_vops, &mp->mnt_vn_spec_ops);
335 vfs_add_vnodeops(mp, &hammer2_fifo_vops, &mp->mnt_vn_fifo_ops);
703720e4 336
54f522df 337 copyinstr(info.volume, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size);
703720e4
MD
338 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
339 bzero(mp->mnt_stat.f_mntonname, sizeof(mp->mnt_stat.f_mntonname));
340 copyinstr(path, mp->mnt_stat.f_mntonname,
341 sizeof(mp->mnt_stat.f_mntonname) - 1,
342 &size);
343
066e00cc 344 hammer2_vfs_statfs(mp, &mp->mnt_stat, cred);
703720e4 345
47902fef 346 return 0;
703720e4
MD
347}
348
e118c14f
MD
349static
350int
703720e4
MD
351hammer2_remount(struct mount *mp, char *path, struct vnode *devvp,
352 struct ucred *cred)
353{
354 return (0);
355}
356
e118c14f
MD
357static
358int
066e00cc 359hammer2_vfs_unmount(struct mount *mp, int mntflags)
703720e4 360{
54eb943b 361 hammer2_mount_t *hmp;
703720e4 362 int flags;
50e4f8f4 363 int error = 0;
54eb943b
MD
364 int ronly = ((mp->mnt_flag & MNT_RDONLY) != 0);
365 struct vnode *devvp;
703720e4
MD
366
367 kprintf("hammer2_unmount\n");
368
369 hmp = MPTOH2(mp);
370 flags = 0;
371
372 if (mntflags & MNT_FORCE)
373 flags |= FORCECLOSE;
374
375 hammer2_mount_exlock(hmp);
376
50e4f8f4
MD
377 /*
378 * If mount initialization proceeded far enough we must flush
379 * its vnodes.
380 */
df9ea374 381 kprintf("iroot %p\n", hmp->iroot);
50e4f8f4
MD
382 if (hmp->iroot)
383 error = vflush(mp, 0, flags);
384
385 if (error)
386 return error;
703720e4
MD
387
388 /*
389 * Work to do:
390 * 1) Wait on the flusher having no work; heat up if needed
391 * 2) Scan inode RB tree till all the inodes are free
392 * 3) Destroy the kmalloc inode zone
393 * 4) Free the mount point
394 */
5c23d7f1 395 hmp->iroot = NULL;
7cfa8da5 396 if (hmp->rchain) {
5c23d7f1 397 KKASSERT(hmp->rchain->refs == 1);
7cfa8da5
MD
398 hammer2_chain_drop(hmp, hmp->rchain);
399 hmp->rchain = NULL;
400 }
401 if (hmp->schain) {
5c23d7f1 402 KKASSERT(hmp->schain->refs == 1);
7cfa8da5
MD
403 hammer2_chain_drop(hmp, hmp->schain);
404 hmp->schain = NULL;
405 }
54eb943b
MD
406 if ((devvp = hmp->devvp) != NULL) {
407 vinvalbuf(devvp, (ronly ? 0 : V_SAVE), 0, 0);
408 hmp->devvp = NULL;
409 VOP_CLOSE(devvp, (ronly ? FREAD : FREAD|FWRITE));
410 vrele(devvp);
411 devvp = NULL;
412 }
703720e4 413
5c23d7f1
MD
414 kmalloc_destroy(&hmp->minode);
415 kmalloc_destroy(&hmp->mchain);
703720e4 416
54eb943b 417 hammer2_mount_unlock(hmp);
703720e4 418
54eb943b
MD
419 mp->mnt_data = NULL;
420 hmp->mp = NULL;
421 kfree(hmp, M_HAMMER2);
703720e4
MD
422
423 return (error);
424}
425
e118c14f
MD
426static
427int
066e00cc 428hammer2_vfs_vget(struct mount *mp, struct vnode *dvp,
703720e4
MD
429 ino_t ino, struct vnode **vpp)
430{
431 kprintf("hammer2_vget\n");
432 return (EOPNOTSUPP);
433}
434
e118c14f
MD
435static
436int
066e00cc 437hammer2_vfs_root(struct mount *mp, struct vnode **vpp)
703720e4 438{
54eb943b 439 hammer2_mount_t *hmp;
703720e4
MD
440 int error;
441 struct vnode *vp;
442
443 kprintf("hammer2_root\n");
444
445 hmp = MPTOH2(mp);
e118c14f 446 hammer2_mount_exlock(hmp);
54eb943b 447 if (hmp->iroot == NULL) {
703720e4
MD
448 *vpp = NULL;
449 error = EINVAL;
450 } else {
54eb943b 451 vp = hammer2_igetv(hmp->iroot, &error);
703720e4
MD
452 *vpp = vp;
453 if (vp == NULL)
454 kprintf("vnodefail\n");
455 }
456 hammer2_mount_unlock(hmp);
457
458 return (error);
459}
460
e118c14f
MD
461static
462int
066e00cc 463hammer2_vfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
703720e4 464{
54eb943b 465 hammer2_mount_t *hmp;
703720e4 466
703720e4
MD
467 hmp = MPTOH2(mp);
468
50e4f8f4
MD
469 mp->mnt_stat.f_files = 10;
470 mp->mnt_stat.f_bfree = 10;
471 mp->mnt_stat.f_bavail = mp->mnt_stat.f_bfree;
703720e4 472
50e4f8f4 473 *sbp = mp->mnt_stat;
703720e4
MD
474 return (0);
475}
476
e118c14f
MD
477static
478int
066e00cc 479hammer2_vfs_statvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred)
703720e4 480{
50e4f8f4
MD
481 hammer2_mount_t *hmp;
482
483 hmp = MPTOH2(mp);
484
485 mp->mnt_vstat.f_files = 10;
486 mp->mnt_vstat.f_bfree = 10;
487 mp->mnt_vstat.f_bavail = mp->mnt_stat.f_bfree;
488
489 *sbp = mp->mnt_vstat;
490 return (0);
703720e4
MD
491}
492
493/*
494 * Sync the entire filesystem; this is called from the filesystem syncer
495 * process periodically and whenever a user calls sync(1) on the hammer
496 * mountpoint.
497 *
498 * Currently is actually called from the syncer! \o/
499 *
500 * This task will have to snapshot the state of the dirty inode chain.
501 * From that, it will have to make sure all of the inodes on the dirty
502 * chain have IO initiated. We make sure that io is initiated for the root
503 * block.
504 *
505 * If waitfor is set, we wait for media to acknowledge the new rootblock.
506 *
507 * THINKS: side A vs side B, to have sync not stall all I/O?
508 */
e118c14f
MD
509static
510int
066e00cc 511hammer2_vfs_sync(struct mount *mp, int waitfor)
703720e4 512{
e118c14f 513#if 0
54eb943b
MD
514 hammer2_mount_t *hmp;
515 hammer2_inode_t *ip;
e118c14f 516#endif
703720e4
MD
517
518 kprintf("hammer2_sync \n");
519
e118c14f
MD
520#if 0
521 hmp = MPTOH2(mp);
522#endif
703720e4
MD
523
524 return (0);
525}
526
e118c14f
MD
527static
528int
066e00cc 529hammer2_vfs_vptofh(struct vnode *vp, struct fid *fhp)
703720e4
MD
530{
531 return (0);
532}
533
e118c14f
MD
534static
535int
066e00cc 536hammer2_vfs_fhtovp(struct mount *mp, struct vnode *rootvp,
703720e4
MD
537 struct fid *fhp, struct vnode **vpp)
538{
539 return (0);
540}
541
e118c14f
MD
542static
543int
066e00cc 544hammer2_vfs_checkexp(struct mount *mp, struct sockaddr *nam,
703720e4
MD
545 int *exflagsp, struct ucred **credanonp)
546{
547 return (0);
548}
50e4f8f4
MD
549
550/*
551 * Support code for hammer2_mount(). Read, verify, and install the volume
552 * header into the HMP
553 *
554 * XXX read four volhdrs and use the one with the highest TID whos CRC
555 * matches.
556 *
557 * XXX check iCRCs.
57381c9e
VS
558 *
559 * XXX For filesystems w/ less than 4 volhdrs, make sure to not write to
560 * nonexistant locations.
561 *
562 * XXX Record selected volhdr and ring updates to each of 4 volhdrs
50e4f8f4
MD
563 */
564static
565int
566hammer2_install_volume_header(hammer2_mount_t *hmp)
567{
568 hammer2_volume_data_t *vd;
99924359 569 struct buf *bp;
0b3147ba 570 hammer2_crc32_t ccrc, crc;
99924359
MD
571 int error_reported;
572 int error;
0b3147ba
VS
573 int valid;
574 int i;
50e4f8f4 575
99924359 576 error_reported = 0;
0b3147ba
VS
577 error = 0;
578 valid = 0;
99924359 579 bp = NULL;
0b3147ba 580
99924359
MD
581 /*
582 * There are up to 4 copies of the volume header (syncs iterate
583 * between them so there is no single master). We don't trust the
584 * volu_size field so we don't know precisely how large the filesystem
585 * is, so depend on the OS to return an error if we go beyond the
586 * block device's EOF.
587 */
0b3147ba
VS
588 for (i = 0; i < HAMMER2_NUM_VOLHDRS; i++) {
589 error = bread(hmp->devvp, i * HAMMER2_RESERVE_BYTES64,
99924359 590 HAMMER2_VOLUME_BYTES, &bp);
0b3147ba 591 if (error) {
99924359
MD
592 brelse(bp);
593 bp = NULL;
0b3147ba
VS
594 continue;
595 }
596
99924359 597 vd = (struct hammer2_volume_data *)bp->b_data;
0b3147ba
VS
598 if (vd->magic != HAMMER2_VOLUME_ID_HBO)
599 continue;
600
601 crc = vd->icrc_sects[HAMMER2_VOL_ICRC_SECT0];
99924359
MD
602 ccrc = hammer2_icrc32(bp->b_data + HAMMER2_VOLUME_ICRC0_OFF,
603 HAMMER2_VOLUME_ICRC0_SIZE);
0b3147ba 604 if (ccrc != crc) {
99924359
MD
605 kprintf("hammer2 volume header crc "
606 "mismatch copy #%d\t%08x %08x",
607 i, ccrc, crc);
608 error_reported = 1;
609 brelse(bp);
610 bp = NULL;
0b3147ba
VS
611 continue;
612 }
99924359
MD
613 if (valid == 0 || hmp->voldata.last_tid < vd->last_tid) {
614 valid = 1;
615 hmp->voldata = *vd;
0b3147ba 616 }
99924359
MD
617 brelse(bp);
618 bp = NULL;
50e4f8f4 619 }
0b3147ba 620 if (valid) {
57381c9e 621 error = 0;
99924359
MD
622 if (error_reported)
623 kprintf("hammer2: a valid volume header was found\n");
0b3147ba
VS
624 } else {
625 error = EINVAL;
99924359 626 kprintf("hammer2: no valid volume headers found!\n");
0b3147ba 627 }
0b3147ba 628 return (error);
50e4f8f4 629}
0b3147ba 630