]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vfs/vfs_journal.c
xnu-792.10.96.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_journal.c
index 6e47742b1a55815857416cbc47aeab3cdb1b2938..dba9c0b3cbc2c2938811059d0d847a0211250d8d 100644 (file)
@@ -3,20 +3,19 @@
  *
  * @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@
  */
@@ -198,9 +197,6 @@ journal_init()
        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
@@ -1508,6 +1504,110 @@ journal_open(struct vnode *jvp,
     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)
 {