aboutsummaryrefslogtreecommitdiff
path: root/ext2fs/hyper.c
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-04-24 17:44:14 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-05-13 16:45:51 +0200
commit134b450cb65b1986c78e0b292cff78c2f1882a2b (patch)
tree331c2a170decbe42ae34b0df2bc609942744ab6b /ext2fs/hyper.c
parent261d957ebe4cf16aed76eed24b5bfd32f1f5a79a (diff)
downloadhurd-134b450cb65b1986c78e0b292cff78c2f1882a2b.tar.gz
hurd-134b450cb65b1986c78e0b292cff78c2f1882a2b.tar.bz2
hurd-134b450cb65b1986c78e0b292cff78c2f1882a2b.zip
ext2fs: cache the superblock
Previously, the superblock was mmaped and a pointer stored in sblock by map_hypermetadata. This memory is backed by our disk pager. This is rather unfortunate, as this means that whenever we read a value from that location, we might generate a request our disk pager. This amplifies the so-called thread-storm problem. Rather than relying on a mmaped region of memory, just use the data loaded by get_hypermetadata. * ext2fs/hyper.c (get_hypermetadata): Do not free sblock. (mapped_sblock): New variable. (map_hypermetadata): Map the superblock to mapped_sblock instead. (diskfs_set_hypermetadata): Copy superblock into mapped_superblock. * ext2fs/ext2fs.h (get_hypermetadata, map_hypermetadata): Adjust comments accordingly.
Diffstat (limited to 'ext2fs/hyper.c')
-rw-r--r--ext2fs/hyper.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/ext2fs/hyper.c b/ext2fs/hyper.c
index 5bcc2abe..5f288bf1 100644
--- a/ext2fs/hyper.c
+++ b/ext2fs/hyper.c
@@ -61,7 +61,9 @@ get_hypermetadata (void)
error_t err;
size_t read = 0;
- assert (! sblock);
+ if (sblock != NULL)
+ munmap (sblock, SBLOCK_SIZE);
+
err = store_read (store, SBLOCK_OFFS >> store->log2_block_size,
SBLOCK_SIZE, (void **)&sblock, &read);
if (err || read != SBLOCK_SIZE)
@@ -161,19 +163,19 @@ get_hypermetadata (void)
zeroblock = (vm_address_t) mmap (0, block_size, PROT_READ, MAP_ANON, 0, 0);
assert (zeroblock != (vm_address_t) MAP_FAILED);
}
-
- munmap (sblock, SBLOCK_SIZE);
- sblock = NULL;
}
+static struct ext2_super_block *mapped_sblock;
+
void
map_hypermetadata (void)
{
- sblock = (struct ext2_super_block *) boffs_ptr (SBLOCK_OFFS);
+ mapped_sblock = (struct ext2_super_block *) boffs_ptr (SBLOCK_OFFS);
/* Cache a convenient pointer to the block group descriptors for allocation.
These are stored in the filesystem blocks following the superblock. */
- group_desc_image = (struct ext2_group_desc *) bptr (bptr_block (sblock) + 1);
+ group_desc_image =
+ (struct ext2_group_desc *) bptr (bptr_block (mapped_sblock) + 1);
}
error_t
@@ -196,8 +198,9 @@ diskfs_set_hypermetadata (int wait, int clean)
if (sblock_dirty)
{
sblock_dirty = 0;
- disk_cache_block_ref_ptr (sblock);
- record_global_poke (sblock);
+ memcpy (mapped_sblock, sblock, SBLOCK_SIZE);
+ disk_cache_block_ref_ptr (mapped_sblock);
+ record_global_poke (mapped_sblock);
}
sync_global (wait);