X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/ff6e181ae92fc6f1e89841290f461d1f2f9badd9..c0fea4742e91338fffdcf79f86a7c1d5e2b97eb1:/bsd/vfs/vfs_journal.c diff --git a/bsd/vfs/vfs_journal.c b/bsd/vfs/vfs_journal.c index 6e47742b1..dba9c0b3c 100644 --- a/bsd/vfs/vfs_journal.c +++ b/bsd/vfs/vfs_journal.c @@ -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) {