Merge branches 'hammer2' and 'master' of ssh://crater.dragonflybsd.org/repository...
[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
49static int hammer2_init(struct vfsconf *conf);
50static int hammer2_mount(struct mount *mp, char *path, caddr_t data,
51 struct ucred *cred);
52static int hammer2_remount(struct mount *, char *, struct vnode *,
53 struct ucred *);
54static int hammer2_unmount(struct mount *mp, int mntflags);
55static int hammer2_root(struct mount *mp, struct vnode **vpp);
56static int hammer2_statfs(struct mount *mp, struct statfs *sbp,
57 struct ucred *cred);
58static int hammer2_statvfs(struct mount *mp, struct statvfs *sbp,
59 struct ucred *cred);
60static int hammer2_sync(struct mount *mp, int waitfor);
61static int hammer2_vget(struct mount *mp, struct vnode *dvp,
62 ino_t ino, struct vnode **vpp);
63static int hammer2_fhtovp(struct mount *mp, struct vnode *rootvp,
64 struct fid *fhp, struct vnode **vpp);
65static int hammer2_vptofh(struct vnode *vp, struct fid *fhp);
66static int hammer2_checkexp(struct mount *mp, struct sockaddr *nam,
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 = {
703720e4
MD
75 .vfs_init = hammer2_init,
76 .vfs_sync = hammer2_sync,
77 .vfs_mount = hammer2_mount,
78 .vfs_unmount = hammer2_unmount,
703720e4 79 .vfs_root = hammer2_root,
703720e4 80 .vfs_statfs = hammer2_statfs,
47902fef 81 .vfs_statvfs = hammer2_statvfs,
703720e4
MD
82 .vfs_vget = hammer2_vget,
83 .vfs_vptofh = hammer2_vptofh,
84 .vfs_fhtovp = hammer2_fhtovp,
85 .vfs_checkexp = hammer2_checkexp
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
703720e4
MD
95hammer2_init(struct vfsconf *conf)
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
703720e4
MD
138hammer2_mount(struct mount *mp, char *path, caddr_t data,
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) {
272 hammer2_unmount(mp, MNT_FORCE);
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,
297 HAMMER2_SROOT_KEY, (hammer2_key_t)-1);
298 hammer2_chain_put(hmp, parent);
7cfa8da5
MD
299 if (schain == NULL) {
300 kprintf("hammer2_mount: invalid super-root\n");
301 hammer2_unmount(mp, MNT_FORCE);
302 return EINVAL;
303 }
5c23d7f1
MD
304
305 parent = schain;
306 hammer2_chain_ref(hmp, parent);
307 rchain = hammer2_chain_lookup(hmp, &parent,
308 lhc, HAMMER2_DIRHASH_HIMASK);
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
MD
315 rchain = hammer2_chain_next(hmp, &parent, rchain,
316 lhc, HAMMER2_DIRHASH_HIMASK);
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);
322 hammer2_unmount(mp, MNT_FORCE);
323 return EINVAL;
324 }
5c23d7f1
MD
325
326 hmp->schain = schain; /* left held & unlocked */
327 hmp->rchain = rchain; /* left held & unlocked */
328 hmp->iroot = rchain->u.ip; /* implied hold from rchain */
df9ea374 329 kprintf("iroot %p\n", rchain->u.ip);
703720e4 330
f0206a67
VS
331 vfs_getnewfsid(mp);
332 vfs_add_vnodeops(mp, &hammer2_vnode_vops, &mp->mnt_vn_norm_ops);
333 vfs_add_vnodeops(mp, &hammer2_spec_vops, &mp->mnt_vn_spec_ops);
334 vfs_add_vnodeops(mp, &hammer2_fifo_vops, &mp->mnt_vn_fifo_ops);
703720e4 335
54f522df 336 copyinstr(info.volume, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size);
703720e4
MD
337 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
338 bzero(mp->mnt_stat.f_mntonname, sizeof(mp->mnt_stat.f_mntonname));
339 copyinstr(path, mp->mnt_stat.f_mntonname,
340 sizeof(mp->mnt_stat.f_mntonname) - 1,
341 &size);
342
343 hammer2_statfs(mp, &mp->mnt_stat, cred);
344
47902fef 345 return 0;
703720e4
MD
346}
347
e118c14f
MD
348static
349int
703720e4
MD
350hammer2_remount(struct mount *mp, char *path, struct vnode *devvp,
351 struct ucred *cred)
352{
353 return (0);
354}
355
e118c14f
MD
356static
357int
703720e4
MD
358hammer2_unmount(struct mount *mp, int mntflags)
359{
54eb943b 360 hammer2_mount_t *hmp;
703720e4 361 int flags;
50e4f8f4 362 int error = 0;
54eb943b
MD
363 int ronly = ((mp->mnt_flag & MNT_RDONLY) != 0);
364 struct vnode *devvp;
703720e4
MD
365
366 kprintf("hammer2_unmount\n");
367
368 hmp = MPTOH2(mp);
369 flags = 0;
370
371 if (mntflags & MNT_FORCE)
372 flags |= FORCECLOSE;
373
374 hammer2_mount_exlock(hmp);
375
50e4f8f4
MD
376 /*
377 * If mount initialization proceeded far enough we must flush
378 * its vnodes.
379 */
df9ea374 380 kprintf("iroot %p\n", hmp->iroot);
50e4f8f4
MD
381 if (hmp->iroot)
382 error = vflush(mp, 0, flags);
383
384 if (error)
385 return error;
703720e4
MD
386
387 /*
388 * Work to do:
389 * 1) Wait on the flusher having no work; heat up if needed
390 * 2) Scan inode RB tree till all the inodes are free
391 * 3) Destroy the kmalloc inode zone
392 * 4) Free the mount point
393 */
5c23d7f1 394 hmp->iroot = NULL;
7cfa8da5 395 if (hmp->rchain) {
5c23d7f1 396 KKASSERT(hmp->rchain->refs == 1);
7cfa8da5
MD
397 hammer2_chain_drop(hmp, hmp->rchain);
398 hmp->rchain = NULL;
399 }
400 if (hmp->schain) {
5c23d7f1 401 KKASSERT(hmp->schain->refs == 1);
7cfa8da5
MD
402 hammer2_chain_drop(hmp, hmp->schain);
403 hmp->schain = NULL;
404 }
54eb943b
MD
405 if ((devvp = hmp->devvp) != NULL) {
406 vinvalbuf(devvp, (ronly ? 0 : V_SAVE), 0, 0);
407 hmp->devvp = NULL;
408 VOP_CLOSE(devvp, (ronly ? FREAD : FREAD|FWRITE));
409 vrele(devvp);
410 devvp = NULL;
411 }
703720e4 412
5c23d7f1
MD
413 kmalloc_destroy(&hmp->minode);
414 kmalloc_destroy(&hmp->mchain);
703720e4 415
54eb943b 416 hammer2_mount_unlock(hmp);
703720e4 417
54eb943b
MD
418 mp->mnt_data = NULL;
419 hmp->mp = NULL;
420 kfree(hmp, M_HAMMER2);
703720e4
MD
421
422 return (error);
423}
424
e118c14f
MD
425static
426int
703720e4
MD
427hammer2_vget(struct mount *mp, struct vnode *dvp,
428 ino_t ino, struct vnode **vpp)
429{
430 kprintf("hammer2_vget\n");
431 return (EOPNOTSUPP);
432}
433
e118c14f
MD
434static
435int
703720e4
MD
436hammer2_root(struct mount *mp, struct vnode **vpp)
437{
54eb943b 438 hammer2_mount_t *hmp;
703720e4
MD
439 int error;
440 struct vnode *vp;
441
442 kprintf("hammer2_root\n");
443
444 hmp = MPTOH2(mp);
e118c14f 445 hammer2_mount_exlock(hmp);
54eb943b 446 if (hmp->iroot == NULL) {
703720e4
MD
447 *vpp = NULL;
448 error = EINVAL;
449 } else {
54eb943b 450 vp = hammer2_igetv(hmp->iroot, &error);
703720e4
MD
451 *vpp = vp;
452 if (vp == NULL)
453 kprintf("vnodefail\n");
454 }
455 hammer2_mount_unlock(hmp);
456
457 return (error);
458}
459
e118c14f
MD
460static
461int
703720e4
MD
462hammer2_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
463{
54eb943b 464 hammer2_mount_t *hmp;
703720e4 465
703720e4
MD
466 hmp = MPTOH2(mp);
467
50e4f8f4
MD
468 mp->mnt_stat.f_files = 10;
469 mp->mnt_stat.f_bfree = 10;
470 mp->mnt_stat.f_bavail = mp->mnt_stat.f_bfree;
703720e4 471
50e4f8f4 472 *sbp = mp->mnt_stat;
703720e4
MD
473 return (0);
474}
475
e118c14f
MD
476static
477int
703720e4
MD
478hammer2_statvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred)
479{
50e4f8f4
MD
480 hammer2_mount_t *hmp;
481
482 hmp = MPTOH2(mp);
483
484 mp->mnt_vstat.f_files = 10;
485 mp->mnt_vstat.f_bfree = 10;
486 mp->mnt_vstat.f_bavail = mp->mnt_stat.f_bfree;
487
488 *sbp = mp->mnt_vstat;
489 return (0);
703720e4
MD
490}
491
492/*
493 * Sync the entire filesystem; this is called from the filesystem syncer
494 * process periodically and whenever a user calls sync(1) on the hammer
495 * mountpoint.
496 *
497 * Currently is actually called from the syncer! \o/
498 *
499 * This task will have to snapshot the state of the dirty inode chain.
500 * From that, it will have to make sure all of the inodes on the dirty
501 * chain have IO initiated. We make sure that io is initiated for the root
502 * block.
503 *
504 * If waitfor is set, we wait for media to acknowledge the new rootblock.
505 *
506 * THINKS: side A vs side B, to have sync not stall all I/O?
507 */
e118c14f
MD
508static
509int
703720e4
MD
510hammer2_sync(struct mount *mp, int waitfor)
511{
e118c14f 512#if 0
54eb943b
MD
513 hammer2_mount_t *hmp;
514 hammer2_inode_t *ip;
e118c14f 515#endif
703720e4
MD
516
517 kprintf("hammer2_sync \n");
518
e118c14f
MD
519#if 0
520 hmp = MPTOH2(mp);
521#endif
703720e4
MD
522
523 return (0);
524}
525
e118c14f
MD
526static
527int
703720e4
MD
528hammer2_vptofh(struct vnode *vp, struct fid *fhp)
529{
530 return (0);
531}
532
e118c14f
MD
533static
534int
703720e4
MD
535hammer2_fhtovp(struct mount *mp, struct vnode *rootvp,
536 struct fid *fhp, struct vnode **vpp)
537{
538 return (0);
539}
540
e118c14f
MD
541static
542int
703720e4
MD
543hammer2_checkexp(struct mount *mp, struct sockaddr *nam,
544 int *exflagsp, struct ucred **credanonp)
545{
546 return (0);
547}
50e4f8f4
MD
548
549/*
550 * Support code for hammer2_mount(). Read, verify, and install the volume
551 * header into the HMP
552 *
553 * XXX read four volhdrs and use the one with the highest TID whos CRC
554 * matches.
555 *
556 * XXX check iCRCs.
57381c9e
VS
557 *
558 * XXX For filesystems w/ less than 4 volhdrs, make sure to not write to
559 * nonexistant locations.
560 *
561 * XXX Record selected volhdr and ring updates to each of 4 volhdrs
50e4f8f4
MD
562 */
563static
564int
565hammer2_install_volume_header(hammer2_mount_t *hmp)
566{
567 hammer2_volume_data_t *vd;
99924359 568 struct buf *bp;
0b3147ba 569 hammer2_crc32_t ccrc, crc;
99924359
MD
570 int error_reported;
571 int error;
0b3147ba
VS
572 int valid;
573 int i;
50e4f8f4 574
99924359 575 error_reported = 0;
0b3147ba
VS
576 error = 0;
577 valid = 0;
99924359 578 bp = NULL;
0b3147ba 579
99924359
MD
580 /*
581 * There are up to 4 copies of the volume header (syncs iterate
582 * between them so there is no single master). We don't trust the
583 * volu_size field so we don't know precisely how large the filesystem
584 * is, so depend on the OS to return an error if we go beyond the
585 * block device's EOF.
586 */
0b3147ba
VS
587 for (i = 0; i < HAMMER2_NUM_VOLHDRS; i++) {
588 error = bread(hmp->devvp, i * HAMMER2_RESERVE_BYTES64,
99924359 589 HAMMER2_VOLUME_BYTES, &bp);
0b3147ba 590 if (error) {
99924359
MD
591 brelse(bp);
592 bp = NULL;
0b3147ba
VS
593 continue;
594 }
595
99924359 596 vd = (struct hammer2_volume_data *)bp->b_data;
0b3147ba
VS
597 if (vd->magic != HAMMER2_VOLUME_ID_HBO)
598 continue;
599
600 crc = vd->icrc_sects[HAMMER2_VOL_ICRC_SECT0];
99924359
MD
601 ccrc = hammer2_icrc32(bp->b_data + HAMMER2_VOLUME_ICRC0_OFF,
602 HAMMER2_VOLUME_ICRC0_SIZE);
0b3147ba 603 if (ccrc != crc) {
99924359
MD
604 kprintf("hammer2 volume header crc "
605 "mismatch copy #%d\t%08x %08x",
606 i, ccrc, crc);
607 error_reported = 1;
608 brelse(bp);
609 bp = NULL;
0b3147ba
VS
610 continue;
611 }
99924359
MD
612 if (valid == 0 || hmp->voldata.last_tid < vd->last_tid) {
613 valid = 1;
614 hmp->voldata = *vd;
0b3147ba 615 }
99924359
MD
616 brelse(bp);
617 bp = NULL;
50e4f8f4 618 }
0b3147ba 619 if (valid) {
57381c9e 620 error = 0;
99924359
MD
621 if (error_reported)
622 kprintf("hammer2: a valid volume header was found\n");
0b3147ba
VS
623 } else {
624 error = EINVAL;
99924359 625 kprintf("hammer2: no valid volume headers found!\n");
0b3147ba 626 }
0b3147ba 627 return (error);
50e4f8f4 628}
0b3147ba 629