+
+int
+journal_is_clean(struct vnode *jvp,
+ off_t offset,
+ off_t journal_size,
+ struct vnode *fsvp,
+ size_t min_fs_block_size)
+{
+ journal jnl;
+ int phys_blksz, ret;
+ int orig_checksum, checksum;
+ struct vfs_context context;
+
+ context.vc_proc = current_proc();
+ context.vc_ucred = FSCRED;
+
+ /* Get the real physical block size. */
+ if (VNOP_IOCTL(jvp, DKIOCGETBLOCKSIZE, (caddr_t)&phys_blksz, 0, &context)) {
+ printf("jnl: is_clean: failed to get device block size.\n");
+ return EINVAL;
+ }
+
+ if (phys_blksz > min_fs_block_size) {
+ printf("jnl: is_clean: error: phys blksize %d bigger than min fs blksize %d\n",
+ phys_blksz, min_fs_block_size);
+ return EINVAL;
+ }
+
+ if ((journal_size % phys_blksz) != 0) {
+ printf("jnl: is_clean: journal size 0x%llx is not an even multiple of block size 0x%x\n",
+ journal_size, phys_blksz);
+ return EINVAL;
+ }
+
+ memset(&jnl, 0, sizeof(jnl));
+
+ if (kmem_alloc(kernel_map, (vm_offset_t *)&jnl.header_buf, phys_blksz)) {
+ printf("jnl: is_clean: could not allocate space for header buffer (%d bytes)\n", phys_blksz);
+ return ENOMEM;
+ }
+
+ jnl.jhdr = (journal_header *)jnl.header_buf;
+ memset(jnl.jhdr, 0, sizeof(journal_header)+4);
+
+ jnl.jdev = jvp;
+ jnl.jdev_offset = offset;
+ jnl.fsdev = fsvp;
+
+ // we have to set this up here so that do_journal_io() will work
+ jnl.jhdr->jhdr_size = phys_blksz;
+
+ if (read_journal_header(&jnl, jnl.jhdr, phys_blksz) != phys_blksz) {
+ printf("jnl: is_clean: could not read %d bytes for the journal header.\n",
+ phys_blksz);
+ ret = EINVAL;
+ goto get_out;
+ }
+
+ orig_checksum = jnl.jhdr->checksum;
+ jnl.jhdr->checksum = 0;
+
+ if (jnl.jhdr->magic == SWAP32(JOURNAL_HEADER_MAGIC)) {
+ // do this before the swap since it's done byte-at-a-time
+ orig_checksum = SWAP32(orig_checksum);
+ checksum = calc_checksum((char *)jnl.jhdr, sizeof(struct journal_header));
+ swap_journal_header(&jnl);
+ jnl.flags |= JOURNAL_NEED_SWAP;
+ } else {
+ checksum = calc_checksum((char *)jnl.jhdr, sizeof(struct journal_header));
+ }
+
+ if (jnl.jhdr->magic != JOURNAL_HEADER_MAGIC && jnl.jhdr->magic != OLD_JOURNAL_HEADER_MAGIC) {
+ printf("jnl: is_clean: journal magic is bad (0x%x != 0x%x)\n",
+ jnl.jhdr->magic, JOURNAL_HEADER_MAGIC);
+ ret = EINVAL;
+ goto get_out;
+ }
+
+ if (orig_checksum != checksum) {
+ printf("jnl: is_clean: journal checksum is bad (0x%x != 0x%x)\n", orig_checksum, checksum);
+ ret = EINVAL;
+ goto get_out;
+ }
+
+ //
+ // if the start and end are equal then the journal is clean.
+ // otherwise it's not clean and therefore an error.
+ //
+ if (jnl.jhdr->start == jnl.jhdr->end) {
+ ret = 0;
+ } else {
+ ret = EINVAL;
+ }
+
+ get_out:
+ kmem_free(kernel_map, (vm_offset_t)jnl.header_buf, phys_blksz);
+
+ return ret;
+
+
+}
+
+
+