/* Fetching and storing the hypermetadata (superblock and bg summary info). Copyright (C) 1994, 1995 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "ext2fs.h" #define SBSIZE (sizeof (struct ext2_super_block)) void get_hypermetadata (void) { sblock = malloc (SBSIZE); disk_sblock = baddr(1); assert (!diskfs_catch_exception ()); bcopy (disk_sblock, sblock, SBSIZE); diskfs_end_catch_exception (); if (sblock->s_magic != EXT2_SUPER_MAGIC #ifdef EXT2FS_PRE_02B_COMPAT && sblock->s_magic != EXT2_PRE_02B_MAGIC #endif ) ext2_panic("Bad magic number %#lx (should be %#x)", sblock->s_magic, EXT2_SUPER_MAGIC); block_size = EXT2_MIN_BLOCK_SIZE << sblock->s_log_block_size; if (block_size != BLOCK_SIZE && (sb->s_block_size == 1024 || sb->s_block_size == 2048 || sb->s_block_size == 4096)) { int offset = (sb_block_num * BLOCK_SIZE) % block_size; unsigned long logical_sb_block_num = (sb_block_num * BLOCK_SIZE) / block_size; disk_sblock = baddr(logical_sb_block_num) + offset; assert (!diskfs_catch_exception ()); bcopy (disk_sblock, sblock, SBSIZE); diskfs_end_catch_exception (); if (sblock->s_magic != EXT2_SUPER_MAGIC) ext2_panic("Bad magic number %#lx (should be %#x)" " in logical superblock!", sblock->s_magic, EXT2_SUPER_MAGIC); } if (block_size > 8192) ext2_panic("Block size %ld is too big (max is 8192 bytes)", block_size); if (block_size < SBSIZE) ext2_panic ("Block size %ld is too small (min is %ld bytes)", block_size, SBSIZE); assert ((vm_page_size % DEV_BSIZE) == 0); assert ((sblock->fs_bsize % DEV_BSIZE) == 0); assert (vm_page_size <= sblock->fs_bsize); /* Set these handy variables. */ inodes_per_block = block_size / sizeof (struct ext2_inode); frag_size = EXT2_MIN_FRAG_SIZE << sblock->s_log_frag_size; if (frag_size) frags_per_block = block_size / frag_size; else ext2_panic("Frag size is zero!"); groups_count = ((sblock->s_blocks_count - sblock->s_first_data_block + sblock->s_blocks_per_group - 1) / sblock->s_blocks_per_group); itb_per_group = sblock->inodes_per_group / inodes_per_block; desc_per_block = block_size / sizeof (struct ext2_group_desc); addr_per_block = block_size / sizeof (u32); db_per_group = (groups_count + desc_per_block - 1) / desc_per_block; } /* Write the csum data. This isn't backed by a pager because it is taken from ordinary data blocks and might not be an even number of pages; in that case writing it through the pager would nuke whatever pages came after it on the disk and were backed by file pagers. */ void diskfs_set_hypermetadata (int wait, int clean) { #if 0 vm_address_t buf; vm_size_t bufsize; error_t err; spin_lock (&alloclock); if (!csum_dirty) { spin_unlock (&alloclock); return; } /* Copy into a page-aligned buffer to avoid bugs in kernel device code. */ bufsize = round_page (fragroundup (sblock, sblock->fs_cssize)); err = dev_read_sync (fsbtodb (sblock, sblock->fs_csaddr), &buf, bufsize); if (!err) { bcopy (csum, (void *) buf, sblock->fs_cssize); dev_write_sync (fsbtodb (sblock, sblock->fs_csaddr), buf, bufsize); csum_dirty = 0; vm_deallocate (mach_task_self (), buf, bufsize); } spin_unlock (&alloclock); #endif } /* Copy the sblock into the disk */ void copy_sblock () { int clean = 1; /* XXX wrong... */ assert (!diskfs_catch_exception ()); spin_lock (&alloclock); if (clean && !diskfs_readonly) { sblock->s_state |= EXT2_VALID_FS; sblock_dirty = 1; } if (sblock_dirty) { bcopy (sblock, disk_sblock, SBSIZE); record_poke (disk_sblock, SBSIZE); sblock_dirty = 0; } if (clean && !diskfs_readonly) { sblock->s_state &= ~EXT2_VALID_FS; sblock_dirty = 1; } spin_unlock (&alloclock); diskfs_end_catch_exception (); }