summaryrefslogtreecommitdiff
path: root/debian/patches/ext2fs-cache-superblock.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/ext2fs-cache-superblock.patch')
-rw-r--r--debian/patches/ext2fs-cache-superblock.patch73
1 files changed, 73 insertions, 0 deletions
diff --git a/debian/patches/ext2fs-cache-superblock.patch b/debian/patches/ext2fs-cache-superblock.patch
new file mode 100644
index 00000000..27bf494e
--- /dev/null
+++ b/debian/patches/ext2fs-cache-superblock.patch
@@ -0,0 +1,73 @@
+commit a3ccff628fcd9d9866bac415758be8d55d6cf13f
+Author: Justus Winter <4winter@informatik.uni-hamburg.de>
+Date: Thu Apr 24 17:44:14 2014 +0200
+
+ 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.
+
+diff --git a/ext2fs/hyper.c b/ext2fs/hyper.c
+index 5bcc2ab..5f288bf 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);