summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1995-04-18 03:38:25 +0000
committerMiles Bader <miles@gnu.org>1995-04-18 03:38:25 +0000
commit9c0f5ecbaf8a79545296c6859ecfb380b1089bf6 (patch)
tree7f6069a93ce3f57ef26a63847f1155321bcd0597
parent805340157b863ecf18475973189bbc36eb08351f (diff)
Formerly hyper.c.~8~
-rw-r--r--ext2fs/hyper.c41
1 files changed, 28 insertions, 13 deletions
diff --git a/ext2fs/hyper.c b/ext2fs/hyper.c
index d60b5c34..7b17f10e 100644
--- a/ext2fs/hyper.c
+++ b/ext2fs/hyper.c
@@ -20,12 +20,15 @@
#include <stdio.h>
#include "ext2fs.h"
-void
+error_t
get_hypermetadata (void)
{
- assert (!diskfs_catch_exception ());
+ error_t err = diskfs_catch_exception ();
+
+ if (err)
+ return err;
- sblock = boffs_ptr(SBLOCK_OFFS);
+ sblock = (struct ext2_super_block *)boffs_ptr (SBLOCK_OFFS);
if (sblock->s_magic != EXT2_SUPER_MAGIC
#ifdef EXT2FS_PRE_02B_COMPAT
@@ -41,10 +44,6 @@ get_hypermetadata (void)
if (block_size > 8192)
ext2_panic("get_hypermetadata",
"Block size %ld is too big (max is 8192 bytes)", block_size);
- if (block_size < SBLOCK_SIZE)
- ext2_panic ("get_hypermetadata",
- "Block size %ld is too small (min is %ld bytes)",
- block_size, SBLOCK_SIZE);
log2_dev_blocks_per_fs_block = 0;
while ((device_block_size << log2_dev_blocks_per_fs_block) < block_size)
@@ -62,6 +61,21 @@ get_hypermetadata (void)
ext2_panic("get_hypermetadata",
"Block size %ld isn't a power of two!", block_size);
+ if (!diskfs_readonly && block_size < vm_page_size)
+ /* If the block size is too small, we have to take extra care when
+ writing out pages from the global pager, to make sure we don't stomp
+ on any file pager blocks. In this case use a bitmap to record which
+ global blocks are actually modified so the pager can write only them.
+ Since small block sizes are probably used on smaller media (to save
+ space), this shouldn't be too much of a problem. */
+ {
+ /* One bit per filesystem block. */
+ vm_allocate (mach_task_self (), (vm_address_t *)&modified_global_blocks,
+ (sblock->s_blocks_count >> log2_block_size) >> 3, 1);
+ }
+ else
+ modified_global_blocks = 0;
+
/* Set these handy variables. */
inodes_per_block = block_size / sizeof (struct ext2_inode);
@@ -82,6 +96,8 @@ get_hypermetadata (void)
db_per_group = (groups_count + desc_per_block - 1) / desc_per_block;
diskfs_end_catch_exception ();
+
+ return 0;
}
void
@@ -91,11 +107,10 @@ diskfs_set_hypermetadata (int wait, int clean)
/* The filesystem is clean, so we need to set the clean flag. We
just write the superblock directly, without using the paged copy. */
{
- struct ext2_super_block clean_sblock;
-
- bcopy (sblock, clean_sblock, SBLOCK_SIZE);
- clean_sblock->s_state |= EXT2_VALID_FS;
- dev_write_sync (SBLOCK_OFFS / device_block_size,
- (vm_address_t)clean_sblock, SBLOCK_SIZE);
+ vm_address_t page_buf = get_page_buf ();
+ bcopy (sblock, (void *)page_buf, SBLOCK_SIZE);
+ ((struct ext2_super_block *)page_buf)->s_state |= EXT2_VALID_FS;
+ dev_write_sync (SBLOCK_OFFS / device_block_size, page_buf, block_size);
+ free_page_buf (page_buf);
}
}