+ /*
+ * If the embedded volume doesn't start on a block
+ * boundary, then switch the device to a 512-byte
+ * block size so everything will line up on a block
+ * boundary.
+ */
+ if ((embeddedOffset % blksize) != 0) {
+ printf("HFS Mount: embedded volume offset not"
+ " a multiple of physical block size (%d);"
+ " switching to 512\n", blksize);
+ blksize = 512;
+ if (VOP_IOCTL(devvp, DKIOCSETBLOCKSIZE,
+ (caddr_t)&blksize, FWRITE, cred, p)) {
+ retval = ENXIO;
+ goto error_exit;
+ }
+ if (VOP_IOCTL(devvp, DKIOCGETBLOCKCOUNT,
+ (caddr_t)&blkcnt, 0, cred, p)) {
+ retval = ENXIO;
+ goto error_exit;
+ }
+ /* XXX do we need to call vfs_init_io_attributes again? */
+ devvp->v_specsize = blksize;
+ /* Note: relative block count adjustment */
+ hfsmp->hfs_phys_block_count *=
+ hfsmp->hfs_phys_block_size / blksize;
+ hfsmp->hfs_phys_block_size = blksize;
+ }
+
+ disksize = (u_int64_t)SWAP_BE16(mdbp->drEmbedExtent.blockCount) *
+ (u_int64_t)SWAP_BE32(mdbp->drAlBlkSiz);
+
+ hfsmp->hfs_phys_block_count = disksize / blksize;
+
+ mdb_offset = (embeddedOffset / blksize) + HFS_PRI_SECTOR(blksize);
+ retval = meta_bread(devvp, mdb_offset, blksize, cred, &bp);
+ if (retval)
+ goto error_exit;
+ bcopy(bp->b_data + HFS_PRI_OFFSET(blksize), mdbp, 512);
+ brelse(bp);
+ bp = NULL;
+ vhp = (HFSPlusVolumeHeader*) mdbp;
+
+ } else /* pure HFS+ */ {
+ embeddedOffset = 0;
+ vhp = (HFSPlusVolumeHeader*) mdbp;
+ }
+
+ // XXXdbg
+ //
+ hfsmp->jnl = NULL;
+ hfsmp->jvp = NULL;
+ if (args != NULL && (args->flags & HFSFSMNT_EXTENDED_ARGS) && args->journal_disable) {
+ jnl_disable = 1;
+ }
+
+ //
+ // We only initialize the journal here if the last person
+ // to mount this volume was journaling aware. Otherwise
+ // we delay journal initialization until later at the end
+ // of hfs_MountHFSPlusVolume() because the last person who
+ // mounted it could have messed things up behind our back
+ // (so we need to go find the .journal file, make sure it's
+ // the right size, re-sync up if it was moved, etc).
+ //
+ if ( (SWAP_BE32(vhp->lastMountedVersion) == kHFSJMountVersion)
+ && (SWAP_BE32(vhp->attributes) & kHFSVolumeJournaledMask)
+ && !jnl_disable) {
+
+ // if we're able to init the journal, mark the mount
+ // point as journaled.
+ //
+ if (hfs_early_journal_init(hfsmp, vhp, args, embeddedOffset, mdb_offset, mdbp, cred) == 0) {
+ mp->mnt_flag |= MNT_JOURNALED;
+ } else {
+ retval = EINVAL;
+ goto error_exit;
+ }
+ }
+ // XXXdbg
+
+ (void) hfs_getconverter(0, &hfsmp->hfs_get_unicode, &hfsmp->hfs_get_hfsname);
+
+ retval = hfs_MountHFSPlusVolume(hfsmp, vhp, embeddedOffset, disksize, p, args);
+ /*
+ * If the backend didn't like our physical blocksize
+ * then retry with physical blocksize of 512.
+ */
+ if ((retval == ENXIO) && (blksize > 512) && (blksize != minblksize)) {
+ printf("HFS Mount: could not use physical block size "
+ "(%d) switching to 512\n", blksize);
+ blksize = 512;
+ if (VOP_IOCTL(devvp, DKIOCSETBLOCKSIZE, (caddr_t)&blksize, FWRITE, cred, p)) {
+ retval = ENXIO;
+ goto error_exit;
+ }
+ if (VOP_IOCTL(devvp, DKIOCGETBLOCKCOUNT, (caddr_t)&blkcnt, 0, cred, p)) {
+ retval = ENXIO;
+ goto error_exit;
+ }
+ devvp->v_specsize = blksize;
+ /* Note: relative block count adjustment (in case this is an embedded volume). */
+ hfsmp->hfs_phys_block_count *= hfsmp->hfs_phys_block_size / blksize;
+ hfsmp->hfs_phys_block_size = blksize;
+
+ /* Try again with a smaller block size... */
+ retval = hfs_MountHFSPlusVolume(hfsmp, vhp, embeddedOffset, disksize, p, args);
+ }
+ if (retval)
+ (void) hfs_relconverter(0);
+ }