Merge "Pin block bitmaps in RAM based on mount option"
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 0084ef9..3c8fc16 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -928,6 +928,7 @@
#define EXT4_MOUNT_POSIX_ACL 0x08000 /* POSIX Access Control Lists */
#define EXT4_MOUNT_NO_AUTO_DA_ALLOC 0x10000 /* No auto delalloc mapping */
#define EXT4_MOUNT_BARRIER 0x20000 /* Use block barriers */
+#define EXT4_MOUNT_PIN_BLOCK_BITMAPS 0x40000 /* Pin block bitmaps */
#define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */
#define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */
#define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */
@@ -2137,6 +2138,7 @@
#ifdef DOUBLE_CHECK
void *bb_bitmap;
#endif
+ struct buffer_head *bb_bh;
struct rw_semaphore alloc_sem;
ext4_grpblk_t bb_counters[]; /* Nr of free power-of-two-block
* regions, index is order.
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 4e99e1d..cebbab3 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -753,6 +753,33 @@
}
/*
+ * Manage pinning (and unpinning) block bitmaps
+ */
+static void ext4_pin_block_bitmaps(struct super_block *sb)
+{
+ ext4_group_t i, ngroups = ext4_get_groups_count(sb);
+ struct ext4_group_info *grinfo;
+
+ for (i = 0; i < ngroups; i++) {
+ grinfo = ext4_get_group_info(sb, i);
+ if (!grinfo->bb_bh)
+ grinfo->bb_bh = ext4_read_block_bitmap(sb, i);
+ }
+}
+
+static void ext4_unpin_block_bitmaps(struct super_block *sb)
+{
+ ext4_group_t i, ngroups = ext4_get_groups_count(sb);
+ struct ext4_group_info *grinfo;
+
+ for (i = 0; i < ngroups; i++) {
+ grinfo = ext4_get_group_info(sb, i);
+ brelse(grinfo->bb_bh);
+ grinfo->bb_bh = NULL;
+ }
+}
+
+/*
* Release the journal device
*/
static int ext4_blkdev_put(struct block_device *bdev)
@@ -821,6 +848,7 @@
del_timer(&sbi->s_err_report);
ext4_release_system_zone(sb);
+ ext4_unpin_block_bitmaps(sb);
ext4_mb_release(sb);
ext4_ext_release(sb);
ext4_xattr_put_super(sb);
@@ -1164,6 +1192,9 @@
if (sbi->no_hide_stale_gid != -1)
seq_printf(seq, ",nohide_stale_gid=%u", sbi->no_hide_stale_gid);
+ if (test_opt(sb, PIN_BLOCK_BITMAPS))
+ seq_puts(seq, ",pin_block_bitmaps");
+
ext4_show_quota_options(seq, sb);
return 0;
@@ -1339,6 +1370,7 @@
Opt_dioread_nolock, Opt_dioread_lock,
Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
Opt_nohide_stale_gid,
+ Opt_pin_block_bitmaps, Opt_nopin_block_bitmaps,
};
static const match_table_t tokens = {
@@ -1415,6 +1447,8 @@
{Opt_init_itable, "init_itable"},
{Opt_noinit_itable, "noinit_itable"},
{Opt_nohide_stale_gid, "nohide_stale_gid=%u"},
+ {Opt_pin_block_bitmaps, "pin_block_bitmaps"},
+ {Opt_nopin_block_bitmaps, "nopin_block_bitmaps"},
{Opt_err, NULL},
};
@@ -1917,6 +1951,12 @@
case Opt_noinit_itable:
clear_opt(sb, INIT_INODE_TABLE);
break;
+ case Opt_pin_block_bitmaps:
+ set_opt(sb, PIN_BLOCK_BITMAPS);
+ break;
+ case Opt_nopin_block_bitmaps:
+ clear_opt(sb, PIN_BLOCK_BITMAPS);
+ break;
default:
ext4_msg(sb, KERN_ERR,
"Unrecognized mount option \"%s\" "
@@ -3937,6 +3977,8 @@
} else
descr = "out journal";
+ if (test_opt(sb, PIN_BLOCK_BITMAPS))
+ ext4_pin_block_bitmaps(sb);
ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
"Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
*sbi->s_es->s_mount_opts ? "; " : "", orig_data);
@@ -4679,6 +4721,11 @@
if (enable_quota)
dquot_resume(sb, -1);
+ if (test_opt(sb, PIN_BLOCK_BITMAPS))
+ ext4_pin_block_bitmaps(sb);
+ if (!test_opt(sb, PIN_BLOCK_BITMAPS))
+ ext4_unpin_block_bitmaps(sb);
+
ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data);
kfree(orig_data);
return 0;