diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-04-24 17:44:14 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-13 16:45:51 +0200 |
commit | 134b450cb65b1986c78e0b292cff78c2f1882a2b (patch) | |
tree | 331c2a170decbe42ae34b0df2bc609942744ab6b | |
parent | 261d957ebe4cf16aed76eed24b5bfd32f1f5a79a (diff) |
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.
-rw-r--r-- | ext2fs/ext2fs.h | 8 | ||||
-rw-r--r-- | ext2fs/hyper.c | 19 |
2 files changed, 17 insertions, 10 deletions
diff --git a/ext2fs/ext2fs.h b/ext2fs/ext2fs.h index e01d1a59..3422af2f 100644 --- a/ext2fs/ext2fs.h +++ b/ext2fs/ext2fs.h @@ -297,10 +297,14 @@ unsigned log2_stat_blocks_per_fs_block; /* A handy page of page-aligned zeros. */ vm_address_t zeroblock; -/* Get the superblock from the disk, & setup various global info from it. */ +/* Get the superblock from the disk, point `sblock' to it, and setup + various global info from it. */ void get_hypermetadata (); -/* Map `sblock' and `group_desc_image' pointers to disk cache. */ +/* Map `group_desc_image' pointers to disk cache. Also, establish a + non-exported mapping to the superblock that will be used by + diskfs_set_hypermetadata to update the superblock from the cache + `sblock' points to. */ void map_hypermetadata (); /* ---------------------------------------------------------------- */ 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); |