*
* @APPLE_LICENSE_HEADER_START@
*
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
*
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
jnl_lock_attr = lck_attr_alloc_init();
jnl_group_attr = lck_grp_attr_alloc_init();
jnl_mutex_group = lck_grp_alloc_init("jnl-mutex", jnl_group_attr);
-
- /* Turn on lock debugging */
- //lck_attr_setdebug(jnl_lock_attr);
}
static __inline__ void
return NULL;
}
+
+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;
+
+
+}
+
+
+
void
journal_close(journal *jnl)
{