* [PATCH 00/19] V2 Bigalloc patches
@ 2011-05-03 22:24 Theodore Ts'o
2011-05-03 22:24 ` [PATCH 01/19] ext4: read-only support for bigalloc file systems Theodore Ts'o
` (19 more replies)
0 siblings, 20 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
This is the revised bigalloc patches. This version survives xfstests
with the -o block_validity mount option. I've attached the e2fsprogs
patches needed so that we can create an bigalloc filesystem. This is
**not** the final version of the e2fsprogs changes. Those are currently
in process of being developed.
This is primarily because some folks at the file system summit wanted to
see the in-progress patches.
This patch set is based off of the current ext4 "master" branch. (There
is a bigalloc branch on the ext4 tree which also contains these
commits.) These patches **will** conflict with the punch patches from
Allison and Mingming, so this patch set will definitely be changing
after I pull in the punch patches into the ext4 tree.
- Ted
Theodore Ts'o (19):
ext4: read-only support for bigalloc file systems
ext4: enforce bigalloc restrictions (e.g., no online resizing, etc.)
ext4: convert instances of EXT4_BLOCKS_PER_GROUP to
EXT4_CLUSTERS_PER_GROUP
ext4: factor out block group accounting into functions
ext4: split out ext4_free_blocks_after_init()
ext4: bigalloc changes to block bitmap initialization functions
ext4: convert block group-relative offsets to use clusters
ext4: teach mballoc preallocation code about bigalloc clusters
ext4: teach ext4_free_blocks() about bigalloc and clusters
ext4: teach ext4_ext_map_blocks() about the bigalloc feature
ext4: teach ext4_ext_truncate() about the bigalloc feature
ext4: convert s_freeblocks_counter to s_freeclusters_counter
ext4: convert the free_blocks field in s_flex_groups to be
free_clusters
ext4: teach ext4_statfs() to deal with clusters if bigalloc is
enabled
ext4: tune mballoc's default group prealloc size for bigalloc file
systems
ext4: enable mounting bigalloc as read/write
ext4: Rename ext4_free_blks_{count,set}() to refer to clusters
ext4: rename ext4_count_free_blocks() to ext4_count_free_clusters()
ext4: rename ext4_free_blocks_after_init() to
ext4_free_clusters_after_init()
fs/ext4/balloc.c | 302 ++++++++++++++++++++++++++++++++---------------------
fs/ext4/ext4.h | 64 ++++++++---
fs/ext4/extents.c | 241 +++++++++++++++++++++++++++++++++++++-----
fs/ext4/ialloc.c | 72 ++++++-------
fs/ext4/inode.c | 19 +++-
fs/ext4/ioctl.c | 33 +++++-
fs/ext4/mballoc.c | 256 ++++++++++++++++++++++++++++-----------------
fs/ext4/mballoc.h | 9 +-
fs/ext4/resize.c | 10 +-
fs/ext4/super.c | 139 ++++++++++++++++++-------
10 files changed, 792 insertions(+), 353 deletions(-)
--
1.7.3.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/19] ext4: read-only support for bigalloc file systems
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 02/19] ext4: enforce bigalloc restrictions (e.g., no online resizing, etc.) Theodore Ts'o
` (18 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
This adds supports for bigalloc file systems. It teaches the mount
code just enough about bigalloc superblock fields that it will mount
the file system without freaking out that the number of blocks per
group is too big.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/ext4.h | 18 ++++++++++++++--
fs/ext4/super.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 65 insertions(+), 11 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 076c5d2..b973af6 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -231,12 +231,16 @@ struct ext4_io_submit {
#define EXT4_MAX_BLOCK_LOG_SIZE 16
#ifdef __KERNEL__
# define EXT4_BLOCK_SIZE(s) ((s)->s_blocksize)
+# define EXT4_CLUSTER_SIZE(s) (EXT4_SB(s)->s_clustersize)
#else
# define EXT4_BLOCK_SIZE(s) (EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+# define EXT2_CLUSTER_SIZE(s) (EXT2_MIN_BLOCK_SIZE << \
+ (s)->s_log_cluster_size)
#endif
#define EXT4_ADDR_PER_BLOCK(s) (EXT4_BLOCK_SIZE(s) / sizeof(__u32))
#ifdef __KERNEL__
# define EXT4_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
+# define EXT4_CLUSTER_SIZE_BITS(s) (EXT4_SB(s)->s_clustersize_bits)
#else
# define EXT4_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
#endif
@@ -302,6 +306,7 @@ struct flex_groups {
#define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size)
#ifdef __KERNEL__
# define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group)
+# define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group)
# define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block)
# define EXT4_INODES_PER_GROUP(s) (EXT4_SB(s)->s_inodes_per_group)
# define EXT4_DESC_PER_BLOCK_BITS(s) (EXT4_SB(s)->s_desc_per_block_bits)
@@ -957,9 +962,9 @@ struct ext4_super_block {
/*10*/ __le32 s_free_inodes_count; /* Free inodes count */
__le32 s_first_data_block; /* First Data Block */
__le32 s_log_block_size; /* Block size */
- __le32 s_obso_log_frag_size; /* Obsoleted fragment size */
+ __le32 s_log_cluster_size; /* Allocation cluster size */
/*20*/ __le32 s_blocks_per_group; /* # Blocks per group */
- __le32 s_obso_frags_per_group; /* Obsoleted fragments per group */
+ __le32 s_clusters_per_group; /* # Clusters per group */
__le32 s_inodes_per_group; /* # Inodes per group */
__le32 s_mtime; /* Mount time */
/*30*/ __le32 s_wtime; /* Write time */
@@ -1055,7 +1060,10 @@ struct ext4_super_block {
__u8 s_last_error_func[32]; /* function where the error happened */
#define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts)
__u8 s_mount_opts[64];
- __le32 s_reserved[112]; /* Padding to the end of the block */
+ __le32 s_usr_quota_inum; /* inode for tracking user quota */
+ __le32 s_grp_quota_inum; /* inode for tracking group quota */
+ __le32 s_overhead_clusters; /* overhead blocks/clusters in fs */
+ __le32 s_reserved[109]; /* Padding to the end of the block */
};
#define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
@@ -1075,6 +1083,7 @@ struct ext4_sb_info {
unsigned long s_desc_size; /* Size of a group descriptor in bytes */
unsigned long s_inodes_per_block;/* Number of inodes per block */
unsigned long s_blocks_per_group;/* Number of blocks in a group */
+ unsigned long s_clusters_per_group; /* Number of clusters in a group */
unsigned long s_inodes_per_group;/* Number of inodes in a group */
unsigned long s_itb_per_group; /* Number of inode table blocks per group */
unsigned long s_gdb_count; /* Number of group descriptor blocks */
@@ -1083,6 +1092,8 @@ struct ext4_sb_info {
ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */
unsigned long s_overhead_last; /* Last calculated overhead */
unsigned long s_blocks_last; /* Last seen block count */
+ unsigned int s_cluster_ratio; /* Number of blocks per cluster */
+ unsigned int s_cluster_bits; /* log2 of s_cluster_ratio */
loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */
struct buffer_head * s_sbh; /* Buffer containing the super block */
struct ext4_super_block *s_es; /* Pointer to the super block in the buffer */
@@ -1338,6 +1349,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
+#define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x0200
#define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index cb22783..3f82b79 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1908,7 +1908,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
res = MS_RDONLY;
}
if (read_only)
- return res;
+ goto done;
if (!(sbi->s_mount_state & EXT4_VALID_FS))
ext4_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, "
"running e2fsck is recommended");
@@ -1939,6 +1939,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
ext4_commit_super(sb, 1);
+done:
if (test_opt(sb, DEBUG))
printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
"bpg=%lu, ipg=%lu, mo=%04x, mo2=%04x]\n",
@@ -3061,10 +3062,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
char *cp;
const char *descr;
int ret = -ENOMEM;
- int blocksize;
+ int blocksize, clustersize;
unsigned int db_count;
unsigned int i;
- int needs_recovery, has_huge_files;
+ int needs_recovery, has_huge_files, has_bigalloc;
__u64 blocks_count;
int err;
unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
@@ -3337,12 +3338,53 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sb->s_dirt = 1;
}
- if (sbi->s_blocks_per_group > blocksize * 8) {
- ext4_msg(sb, KERN_ERR,
- "#blocks per group too big: %lu",
- sbi->s_blocks_per_group);
- goto failed_mount;
+ /* Handle clustersize */
+ clustersize = BLOCK_SIZE << le32_to_cpu(es->s_log_cluster_size);
+ has_bigalloc = EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC);
+ if (has_bigalloc) {
+ if (clustersize < blocksize) {
+ ext4_msg(sb, KERN_ERR,
+ "cluster size (%d) smaller than "
+ "block size (%d)", clustersize, blocksize);
+ goto failed_mount;
+ }
+ sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
+ le32_to_cpu(es->s_log_block_size);
+ sbi->s_clusters_per_group =
+ le32_to_cpu(es->s_clusters_per_group);
+ if (sbi->s_clusters_per_group > blocksize * 8) {
+ ext4_msg(sb, KERN_ERR,
+ "#clusters per group too big: %lu",
+ sbi->s_clusters_per_group);
+ goto failed_mount;
+ }
+ if (sbi->s_blocks_per_group !=
+ (sbi->s_clusters_per_group * (clustersize / blocksize))) {
+ ext4_msg(sb, KERN_ERR, "blocks per group (%lu) and "
+ "clusters per group (%lu) inconsistent",
+ sbi->s_blocks_per_group,
+ sbi->s_clusters_per_group);
+ goto failed_mount;
+ }
+ } else {
+ if (clustersize != blocksize) {
+ ext4_warning(sb, "fragment/cluster size (%d) != "
+ "block size (%d)", clustersize,
+ blocksize);
+ clustersize = blocksize;
+ }
+ if (sbi->s_blocks_per_group > blocksize * 8) {
+ ext4_msg(sb, KERN_ERR,
+ "#blocks per group too big: %lu",
+ sbi->s_blocks_per_group);
+ goto failed_mount;
+ }
+ sbi->s_clusters_per_group = sbi->s_blocks_per_group;
+ sbi->s_cluster_bits = 0;
}
+ sbi->s_cluster_ratio = clustersize / blocksize;
+
if (sbi->s_inodes_per_group > blocksize * 8) {
ext4_msg(sb, KERN_ERR,
"#inodes per group too big: %lu",
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 02/19] ext4: enforce bigalloc restrictions (e.g., no online resizing, etc.)
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
2011-05-03 22:24 ` [PATCH 01/19] ext4: read-only support for bigalloc file systems Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 03/19] ext4: convert instances of EXT4_BLOCKS_PER_GROUP to EXT4_CLUSTERS_PER_GROUP Theodore Ts'o
` (17 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
At least initially if the bigalloc feature is enabled, we will not
support non-extent mapped inodes, online resizing, online defrag, or
the FITRIM ioctl. This simplifies the initial implementation.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/inode.c | 7 +++++++
fs/ext4/ioctl.c | 33 +++++++++++++++++++++++++++++----
fs/ext4/super.c | 7 +++++++
3 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index f2fa5e8..df7ce6a 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1009,6 +1009,13 @@ static int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
/*
* Okay, we need to do block allocation.
*/
+ if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+ EXT4_ERROR_INODE(inode, "Can't allocate blocks for "
+ "non-extent mapped inodes with bigalloc");
+ return -ENOSPC;
+ }
+
goal = ext4_find_goal(inode, map->m_lblk, partial);
/* the number of blocks need to allocate for [d,t]indirect blocks */
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 808c554..dcd0916 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -21,6 +21,7 @@
long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct inode *inode = filp->f_dentry->d_inode;
+ struct super_block *sb = inode->i_sb;
struct ext4_inode_info *ei = EXT4_I(inode);
unsigned int flags;
@@ -183,7 +184,6 @@ setversion_out:
* Returns 1 if it slept, else zero.
*/
{
- struct super_block *sb = inode->i_sb;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
@@ -199,7 +199,6 @@ setversion_out:
#endif
case EXT4_IOC_GROUP_EXTEND: {
ext4_fsblk_t n_blocks_count;
- struct super_block *sb = inode->i_sb;
int err, err2=0;
if (!capable(CAP_SYS_RESOURCE))
@@ -212,6 +211,13 @@ setversion_out:
if (err)
return err;
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+ ext4_msg(sb, KERN_ERR,
+ "Online resizing not supported with bigalloc");
+ return -EOPNOTSUPP;
+ }
+
err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
if (EXT4_SB(sb)->s_journal) {
jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
@@ -252,6 +258,13 @@ setversion_out:
if (err)
goto mext_out;
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+ ext4_msg(sb, KERN_ERR,
+ "Online defrag not supported with bigalloc");
+ return -EOPNOTSUPP;
+ }
+
err = ext4_move_extents(filp, donor_filp, me.orig_start,
me.donor_start, me.len, &me.moved_len);
mnt_drop_write(filp->f_path.mnt);
@@ -268,7 +281,6 @@ mext_out:
case EXT4_IOC_GROUP_ADD: {
struct ext4_new_group_data input;
- struct super_block *sb = inode->i_sb;
int err, err2=0;
if (!capable(CAP_SYS_RESOURCE))
@@ -282,6 +294,13 @@ mext_out:
if (err)
return err;
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+ ext4_msg(sb, KERN_ERR,
+ "Online resizing not supported with bigalloc");
+ return -EOPNOTSUPP;
+ }
+
err = ext4_group_add(sb, &input);
if (EXT4_SB(sb)->s_journal) {
jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
@@ -333,7 +352,6 @@ mext_out:
case FITRIM:
{
- struct super_block *sb = inode->i_sb;
struct request_queue *q = bdev_get_queue(sb->s_bdev);
struct fstrim_range range;
int ret = 0;
@@ -344,6 +362,13 @@ mext_out:
if (!blk_queue_discard(q))
return -EOPNOTSUPP;
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+ ext4_msg(sb, KERN_ERR,
+ "FITRIM not supported with bigalloc");
+ return -EOPNOTSUPP;
+ }
+
if (copy_from_user(&range, (struct fstrim_range *)arg,
sizeof(range)))
return -EFAULT;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 3f82b79..5ae1712 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2626,6 +2626,13 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
return 0;
}
}
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC) &&
+ !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+ ext4_msg(sb, KERN_ERR,
+ "Can't support bigalloc feature without "
+ "extents feature\n");
+ return 0;
+ }
return 1;
}
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 03/19] ext4: convert instances of EXT4_BLOCKS_PER_GROUP to EXT4_CLUSTERS_PER_GROUP
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
2011-05-03 22:24 ` [PATCH 01/19] ext4: read-only support for bigalloc file systems Theodore Ts'o
2011-05-03 22:24 ` [PATCH 02/19] ext4: enforce bigalloc restrictions (e.g., no online resizing, etc.) Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 04/19] ext4: factor out block group accounting into functions Theodore Ts'o
` (16 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
Change the places in fs/ext4/mballoc.c where EXT4_BLOCKS_PER_GROUP are
used to indicate the number of bits in a block bitmap (which is really
a cluster allocation bitmap in bigalloc file systems). There are
still some places in the ext4 codebase where usage of
EXT4_BLOCKS_PER_GROUP needs to be audited/fixed, in code paths that
aren't used given the initial restricted assumptions for bigalloc.
These will need to be fixed before we can relax those restrictions.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/mballoc.c | 48 ++++++++++++++++++++++++------------------------
1 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 730c1a7..fb9e1aa 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -651,7 +651,7 @@ static void ext4_mb_mark_free_simple(struct super_block *sb,
ext4_grpblk_t chunk;
unsigned short border;
- BUG_ON(len > EXT4_BLOCKS_PER_GROUP(sb));
+ BUG_ON(len > EXT4_CLUSTERS_PER_GROUP(sb));
border = 2 << sb->s_blocksize_bits;
@@ -703,7 +703,7 @@ void ext4_mb_generate_buddy(struct super_block *sb,
void *buddy, void *bitmap, ext4_group_t group)
{
struct ext4_group_info *grp = ext4_get_group_info(sb, group);
- ext4_grpblk_t max = EXT4_BLOCKS_PER_GROUP(sb);
+ ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb);
ext4_grpblk_t i = 0;
ext4_grpblk_t first;
ext4_grpblk_t len;
@@ -1682,8 +1682,8 @@ static void ext4_mb_measure_extent(struct ext4_allocation_context *ac,
struct ext4_free_extent *gex = &ac->ac_g_ex;
BUG_ON(ex->fe_len <= 0);
- BUG_ON(ex->fe_len > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
- BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
+ BUG_ON(ex->fe_len > EXT4_CLUSTERS_PER_GROUP(ac->ac_sb));
+ BUG_ON(ex->fe_start >= EXT4_CLUSTERS_PER_GROUP(ac->ac_sb));
BUG_ON(ac->ac_status != AC_STATUS_CONTINUE);
ac->ac_found++;
@@ -1881,8 +1881,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
while (free && ac->ac_status == AC_STATUS_CONTINUE) {
i = mb_find_next_zero_bit(bitmap,
- EXT4_BLOCKS_PER_GROUP(sb), i);
- if (i >= EXT4_BLOCKS_PER_GROUP(sb)) {
+ EXT4_CLUSTERS_PER_GROUP(sb), i);
+ if (i >= EXT4_CLUSTERS_PER_GROUP(sb)) {
/*
* IF we have corrupt bitmap, we won't find any
* free blocks even though group info says we
@@ -1945,7 +1945,7 @@ void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
do_div(a, sbi->s_stripe);
i = (a * sbi->s_stripe) - first_group_block;
- while (i < EXT4_BLOCKS_PER_GROUP(sb)) {
+ while (i < EXT4_CLUSTERS_PER_GROUP(sb)) {
if (!mb_test_bit(i, bitmap)) {
max = mb_find_extent(e4b, 0, i, sbi->s_stripe, &ex);
if (max >= sbi->s_stripe) {
@@ -3067,7 +3067,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
}
BUG_ON(start + size <= ac->ac_o_ex.fe_logical &&
start > ac->ac_o_ex.fe_logical);
- BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
+ BUG_ON(size <= 0 || size > EXT4_CLUSTERS_PER_GROUP(ac->ac_sb));
/* now prepare goal request */
@@ -3720,7 +3720,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
}
if (needed == 0)
- needed = EXT4_BLOCKS_PER_GROUP(sb) + 1;
+ needed = EXT4_CLUSTERS_PER_GROUP(sb) + 1;
INIT_LIST_HEAD(&list);
repeat:
@@ -4035,8 +4035,8 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
len = ar->len;
/* just a dirty hack to filter too big requests */
- if (len >= EXT4_BLOCKS_PER_GROUP(sb) - 10)
- len = EXT4_BLOCKS_PER_GROUP(sb) - 10;
+ if (len >= EXT4_CLUSTERS_PER_GROUP(sb) - 10)
+ len = EXT4_CLUSTERS_PER_GROUP(sb) - 10;
/* start searching from the goal */
goal = ar->goal;
@@ -4575,8 +4575,8 @@ do_more:
* Check to see if we are freeing blocks across a group
* boundary.
*/
- if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) {
- overflow = bit + count - EXT4_BLOCKS_PER_GROUP(sb);
+ if (bit + count > EXT4_CLUSTERS_PER_GROUP(sb)) {
+ overflow = bit + count - EXT4_CLUSTERS_PER_GROUP(sb);
count -= overflow;
}
bitmap_bh = ext4_read_block_bitmap(sb, block_group);
@@ -4819,7 +4819,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
struct ext4_buddy e4b;
ext4_group_t first_group, last_group;
ext4_group_t group, ngroups = ext4_get_groups_count(sb);
- ext4_grpblk_t cnt = 0, first_block, last_block;
+ ext4_grpblk_t cnt = 0, first_cluster, last_cluster;
uint64_t start, len, minlen, trimmed;
ext4_fsblk_t first_data_blk =
le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
@@ -4830,7 +4830,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
minlen = range->minlen >> sb->s_blocksize_bits;
trimmed = 0;
- if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb)))
+ if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)))
return -EINVAL;
if (start < first_data_blk) {
len -= first_data_blk - start;
@@ -4839,11 +4839,11 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
/* Determine first and last group to examine based on start and len */
ext4_get_group_no_and_offset(sb, (ext4_fsblk_t) start,
- &first_group, &first_block);
+ &first_group, &first_cluster);
ext4_get_group_no_and_offset(sb, (ext4_fsblk_t) (start + len),
- &last_group, &last_block);
+ &last_group, &last_cluster);
last_group = (last_group > ngroups - 1) ? ngroups - 1 : last_group;
- last_block = EXT4_BLOCKS_PER_GROUP(sb);
+ last_cluster = EXT4_CLUSTERS_PER_GROUP(sb);
if (first_group > last_group)
return -EINVAL;
@@ -4862,13 +4862,13 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
* change it for the last group in which case start +
* len < EXT4_BLOCKS_PER_GROUP(sb).
*/
- if (first_block + len < EXT4_BLOCKS_PER_GROUP(sb))
- last_block = first_block + len;
- len -= last_block - first_block;
+ if (first_cluster + len < EXT4_CLUSTERS_PER_GROUP(sb))
+ last_cluster = first_cluster + len;
+ len -= last_cluster - first_cluster;
if (e4b.bd_info->bb_free >= minlen) {
- cnt = ext4_trim_all_free(sb, &e4b, first_block,
- last_block, minlen);
+ cnt = ext4_trim_all_free(sb, &e4b, first_cluster,
+ last_cluster, minlen);
if (cnt < 0) {
ret = cnt;
ext4_mb_unload_buddy(&e4b);
@@ -4877,7 +4877,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
}
ext4_mb_unload_buddy(&e4b);
trimmed += cnt;
- first_block = 0;
+ first_cluster = 0;
}
range->len = trimmed * sb->s_blocksize;
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 04/19] ext4: factor out block group accounting into functions
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (2 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 03/19] ext4: convert instances of EXT4_BLOCKS_PER_GROUP to EXT4_CLUSTERS_PER_GROUP Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 05/19] ext4: split out ext4_free_blocks_after_init() Theodore Ts'o
` (15 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
This makes it easier to understand how ext4_init_block_bitmap() works,
and it will assist when we split out ext4_free_blocks_after_init() in
the next commit.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/balloc.c | 80 ++++++++++++++++++++++++++++++++---------------------
1 files changed, 48 insertions(+), 32 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 9c6cd51..743acec 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -23,6 +23,9 @@
#include <trace/events/ext4.h>
+static unsigned int num_base_meta_blocks(struct super_block *sb,
+ ext4_group_t block_group);
+
/*
* balloc.c contains the blocks allocation and deallocation routines
*/
@@ -83,14 +86,30 @@ static int ext4_group_used_meta_blocks(struct super_block *sb,
return used_blocks;
}
+static unsigned int num_blocks_in_group(struct super_block *sb,
+ ext4_group_t block_group)
+{
+ if (block_group == ext4_get_groups_count(sb) - 1) {
+ /*
+ * Even though mke2fs always initializes the first and
+ * last group, just in case some other tool was used,
+ * we need to make sure we calculate the right free
+ * blocks.
+ */
+ return ext4_blocks_count(EXT4_SB(sb)->s_es) -
+ ext4_group_first_block_no(sb, block_group);
+ } else
+ return EXT4_BLOCKS_PER_GROUP(sb);
+}
+
/* Initializes an uninitialized block bitmap if given, and returns the
* number of blocks free in the group. */
unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
ext4_group_t block_group, struct ext4_group_desc *gdp)
{
- int bit, bit_max;
+ unsigned int bit, bit_max = num_base_meta_blocks(sb, block_group);
ext4_group_t ngroups = ext4_get_groups_count(sb);
- unsigned free_blocks, group_blocks;
+ unsigned group_blocks = num_blocks_in_group(sb, block_group);
struct ext4_sb_info *sbi = EXT4_SB(sb);
if (bh) {
@@ -110,35 +129,6 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
memset(bh->b_data, 0, sb->s_blocksize);
}
- /* Check for superblock and gdt backups in this group */
- bit_max = ext4_bg_has_super(sb, block_group);
-
- if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
- block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
- sbi->s_desc_per_block) {
- if (bit_max) {
- bit_max += ext4_bg_num_gdb(sb, block_group);
- bit_max +=
- le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks);
- }
- } else { /* For META_BG_BLOCK_GROUPS */
- bit_max += ext4_bg_num_gdb(sb, block_group);
- }
-
- if (block_group == ngroups - 1) {
- /*
- * Even though mke2fs always initialize first and last group
- * if some other tool enabled the EXT4_BG_BLOCK_UNINIT we need
- * to make sure we calculate the right free blocks
- */
- group_blocks = ext4_blocks_count(sbi->s_es) -
- ext4_group_first_block_no(sb, ngroups - 1);
- } else {
- group_blocks = EXT4_BLOCKS_PER_GROUP(sb);
- }
-
- free_blocks = group_blocks - bit_max;
-
if (bh) {
ext4_fsblk_t start, tmp;
int flex_bg = 0;
@@ -176,7 +166,8 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
ext4_mark_bitmap_end(group_blocks, sb->s_blocksize * 8,
bh->b_data);
}
- return free_blocks - ext4_group_used_meta_blocks(sb, block_group, gdp);
+ return group_blocks - bit_max -
+ ext4_group_used_meta_blocks(sb, block_group, gdp);
}
@@ -739,3 +730,28 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
}
+/*
+ * This function returns the number of file system metadata blocks at
+ * the beginning of a block group, including the reserved gdt blocks.
+ */
+static unsigned int num_base_meta_blocks(struct super_block *sb,
+ ext4_group_t block_group)
+{
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ int num;
+
+ /* Check for superblock and gdt backups in this group */
+ num = ext4_bg_has_super(sb, block_group);
+
+ if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
+ block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
+ sbi->s_desc_per_block) {
+ if (num) {
+ num += ext4_bg_num_gdb(sb, block_group);
+ num += le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks);
+ }
+ } else { /* For META_BG_BLOCK_GROUPS */
+ num += ext4_bg_num_gdb(sb, block_group);
+ }
+ return num;
+}
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 05/19] ext4: split out ext4_free_blocks_after_init()
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (3 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 04/19] ext4: factor out block group accounting into functions Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 06/19] ext4: bigalloc changes to block bitmap initialization functions Theodore Ts'o
` (14 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
The function ext4_free_blocks_after_init() used to be a #define of
ext4_init_block_bitmap(). This actually made it difficult to
understand how the function worked, and made it hard make changes to
support clusters. So as an initial cleanup, I've separated out the
functionality of initializing block bitmap from calculating the number
of free blocks in the new block group.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/balloc.c | 105 ++++++++++++++++++++++++++---------------------------
fs/ext4/ext4.h | 13 ++++---
fs/ext4/ialloc.c | 19 +++-------
3 files changed, 65 insertions(+), 72 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 743acec..99ea977 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -102,74 +102,73 @@ static unsigned int num_blocks_in_group(struct super_block *sb,
return EXT4_BLOCKS_PER_GROUP(sb);
}
-/* Initializes an uninitialized block bitmap if given, and returns the
- * number of blocks free in the group. */
-unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
- ext4_group_t block_group, struct ext4_group_desc *gdp)
+/* Initializes an uninitialized block bitmap */
+void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ ext4_group_t block_group,
+ struct ext4_group_desc *gdp)
{
unsigned int bit, bit_max = num_base_meta_blocks(sb, block_group);
- ext4_group_t ngroups = ext4_get_groups_count(sb);
- unsigned group_blocks = num_blocks_in_group(sb, block_group);
struct ext4_sb_info *sbi = EXT4_SB(sb);
-
- if (bh) {
- J_ASSERT_BH(bh, buffer_locked(bh));
-
- /* If checksum is bad mark all blocks used to prevent allocation
- * essentially implementing a per-group read-only flag. */
- if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
- ext4_error(sb, "Checksum bad for group %u",
- block_group);
- ext4_free_blks_set(sb, gdp, 0);
- ext4_free_inodes_set(sb, gdp, 0);
- ext4_itable_unused_set(sb, gdp, 0);
- memset(bh->b_data, 0xff, sb->s_blocksize);
- return 0;
- }
- memset(bh->b_data, 0, sb->s_blocksize);
+ ext4_fsblk_t start, tmp;
+ int flex_bg = 0;
+
+ J_ASSERT_BH(bh, buffer_locked(bh));
+
+ /* If checksum is bad mark all blocks used to prevent allocation
+ * essentially implementing a per-group read-only flag. */
+ if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+ ext4_error(sb, "Checksum bad for group %u", block_group);
+ ext4_free_blks_set(sb, gdp, 0);
+ ext4_free_inodes_set(sb, gdp, 0);
+ ext4_itable_unused_set(sb, gdp, 0);
+ memset(bh->b_data, 0xff, sb->s_blocksize);
+ return;
}
+ memset(bh->b_data, 0, sb->s_blocksize);
- if (bh) {
- ext4_fsblk_t start, tmp;
- int flex_bg = 0;
+ for (bit = 0; bit < bit_max; bit++)
+ ext4_set_bit(bit, bh->b_data);
- for (bit = 0; bit < bit_max; bit++)
- ext4_set_bit(bit, bh->b_data);
+ start = ext4_group_first_block_no(sb, block_group);
- start = ext4_group_first_block_no(sb, block_group);
+ if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
+ flex_bg = 1;
- if (EXT4_HAS_INCOMPAT_FEATURE(sb,
- EXT4_FEATURE_INCOMPAT_FLEX_BG))
- flex_bg = 1;
+ /* Set bits for block and inode bitmaps, and inode table */
+ tmp = ext4_block_bitmap(sb, gdp);
+ if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
+ ext4_set_bit(tmp - start, bh->b_data);
- /* Set bits for block and inode bitmaps, and inode table */
- tmp = ext4_block_bitmap(sb, gdp);
- if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
- ext4_set_bit(tmp - start, bh->b_data);
+ tmp = ext4_inode_bitmap(sb, gdp);
+ if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
+ ext4_set_bit(tmp - start, bh->b_data);
- tmp = ext4_inode_bitmap(sb, gdp);
+ tmp = ext4_inode_table(sb, gdp);
+ for (; tmp < ext4_inode_table(sb, gdp) +
+ sbi->s_itb_per_group; tmp++) {
if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
ext4_set_bit(tmp - start, bh->b_data);
-
- tmp = ext4_inode_table(sb, gdp);
- for (; tmp < ext4_inode_table(sb, gdp) +
- sbi->s_itb_per_group; tmp++) {
- if (!flex_bg ||
- ext4_block_in_group(sb, tmp, block_group))
- ext4_set_bit(tmp - start, bh->b_data);
- }
- /*
- * Also if the number of blocks within the group is
- * less than the blocksize * 8 ( which is the size
- * of bitmap ), set rest of the block bitmap to 1
- */
- ext4_mark_bitmap_end(group_blocks, sb->s_blocksize * 8,
- bh->b_data);
}
- return group_blocks - bit_max -
- ext4_group_used_meta_blocks(sb, block_group, gdp);
+ /*
+ * Also if the number of blocks within the group is less than
+ * the blocksize * 8 ( which is the size of bitmap ), set rest
+ * of the block bitmap to 1
+ */
+ ext4_mark_bitmap_end(num_blocks_in_group(sb, block_group),
+ sb->s_blocksize * 8, bh->b_data);
}
+/* Return the number of free blocks in a block group. It is used when
+ * the block bitmap is uninitialized, so we can't just count the bits
+ * in the bitmap. */
+unsigned ext4_free_blocks_after_init(struct super_block *sb,
+ ext4_group_t block_group,
+ struct ext4_group_desc *gdp)
+{
+ return num_blocks_in_group(sb, block_group) -
+ num_base_meta_blocks(sb, block_group) -
+ ext4_group_used_meta_blocks(sb, block_group, gdp);
+}
/*
* The free blocks are managed by bitmaps. A file system contains several
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index b973af6..f66a566 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1677,12 +1677,13 @@ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
ext4_group_t block_group);
-extern unsigned ext4_init_block_bitmap(struct super_block *sb,
- struct buffer_head *bh,
- ext4_group_t group,
- struct ext4_group_desc *desc);
-#define ext4_free_blocks_after_init(sb, group, desc) \
- ext4_init_block_bitmap(sb, NULL, group, desc)
+extern void ext4_init_block_bitmap(struct super_block *sb,
+ struct buffer_head *bh,
+ ext4_group_t group,
+ struct ext4_group_desc *desc);
+extern unsigned ext4_free_blocks_after_init(struct super_block *sb,
+ ext4_group_t block_group,
+ struct ext4_group_desc *gdp);
/* dir.c */
extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 21bb2f6..d0770b6 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -816,7 +816,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
int ret2, err = 0;
struct inode *ret;
ext4_group_t i;
- int free = 0;
static int once = 1;
ext4_group_t flex_group;
@@ -950,26 +949,20 @@ got:
goto fail;
}
- free = 0;
- ext4_lock_group(sb, group);
+ BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
+ err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh);
+ brelse(block_bitmap_bh);
+
/* recheck and clear flag under lock if we still need to */
if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
- free = ext4_free_blocks_after_init(sb, group, gdp);
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
- ext4_free_blks_set(sb, gdp, free);
+ ext4_free_blks_set(sb, gdp,
+ ext4_free_blocks_after_init(sb, group, gdp));
gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
gdp);
}
ext4_unlock_group(sb, group);
- /* Don't need to dirty bitmap block if we didn't change it */
- if (free) {
- BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
- err = ext4_handle_dirty_metadata(handle,
- NULL, block_bitmap_bh);
- }
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 06/19] ext4: bigalloc changes to block bitmap initialization functions
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (4 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 05/19] ext4: split out ext4_free_blocks_after_init() Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 07/19] ext4: convert block group-relative offsets to use clusters Theodore Ts'o
` (13 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
Add bigalloc support to ext4_init_block_bitmap() and
ext4_free_blocks_after_init().
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/balloc.c | 131 +++++++++++++++++++++++++++++++++++++-----------------
fs/ext4/ext4.h | 13 +++++
2 files changed, 103 insertions(+), 41 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 99ea977..332854c 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -23,9 +23,6 @@
#include <trace/events/ext4.h>
-static unsigned int num_base_meta_blocks(struct super_block *sb,
- ext4_group_t block_group);
-
/*
* balloc.c contains the blocks allocation and deallocation routines
*/
@@ -58,37 +55,87 @@ static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block,
return 0;
}
-static int ext4_group_used_meta_blocks(struct super_block *sb,
- ext4_group_t block_group,
- struct ext4_group_desc *gdp)
+/* Return the number of clusters used for file system metadata; this
+ * represents the overhead needed by the file system.
+ */
+unsigned ext4_num_overhead_clusters(struct super_block *sb,
+ ext4_group_t block_group,
+ struct ext4_group_desc *gdp)
{
- ext4_fsblk_t tmp;
+ unsigned num_clusters;
+ int block_cluster = -1, inode_cluster = -1, itbl_cluster = -1, i, c;
+ ext4_fsblk_t start = ext4_group_first_block_no(sb, block_group);
+ ext4_fsblk_t itbl_blk;
struct ext4_sb_info *sbi = EXT4_SB(sb);
- /* block bitmap, inode bitmap, and inode table blocks */
- int used_blocks = sbi->s_itb_per_group + 2;
- if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
- if (!ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp),
- block_group))
- used_blocks--;
-
- if (!ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp),
- block_group))
- used_blocks--;
-
- tmp = ext4_inode_table(sb, gdp);
- for (; tmp < ext4_inode_table(sb, gdp) +
- sbi->s_itb_per_group; tmp++) {
- if (!ext4_block_in_group(sb, tmp, block_group))
- used_blocks -= 1;
+ /* This is the number of clusters used by the superblock,
+ * block group descriptors, and reserved block group
+ * descriptor blocks */
+ num_clusters = ext4_num_base_meta_clusters(sb, block_group);
+
+ /*
+ * For the allocation bitmaps and inode table, we first need
+ * to check to see if the block is in the block group. If it
+ * is, then check to see if the cluster is already accounted
+ * for in the clusters used for the base metadata cluster, or
+ * if we can increment the base metadata cluster to include
+ * that block. Otherwise, we will have to track the cluster
+ * used for the allocation bitmap or inode table explicitly.
+ * Normally all of these blocks are contiguous, so the special
+ * case handling shouldn't be necessary except for *very*
+ * unusual file system layouts.
+ */
+ if (ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), block_group)) {
+ block_cluster = EXT4_B2C(sbi, (start -
+ ext4_block_bitmap(sb, gdp)));
+ if (block_cluster < num_clusters)
+ block_cluster = -1;
+ else if (block_cluster == num_clusters) {
+ num_clusters++;
+ block_cluster = -1;
+ }
+ }
+
+ if (ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), block_group)) {
+ inode_cluster = EXT4_B2C(sbi,
+ start - ext4_inode_bitmap(sb, gdp));
+ if (inode_cluster < num_clusters)
+ inode_cluster = -1;
+ else if (inode_cluster == num_clusters) {
+ num_clusters++;
+ inode_cluster = -1;
+ }
+ }
+
+ itbl_blk = ext4_inode_table(sb, gdp);
+ for (i = 0; i < sbi->s_itb_per_group; i++) {
+ if (ext4_block_in_group(sb, itbl_blk + i, block_group)) {
+ c = EXT4_B2C(sbi, start - itbl_blk + i);
+ if ((c < num_clusters) || (c == inode_cluster) ||
+ (c == block_cluster) || (c == itbl_cluster))
+ continue;
+ if (c == num_clusters) {
+ num_clusters++;
+ continue;
+ }
+ num_clusters++;
+ itbl_cluster = c;
}
}
- return used_blocks;
+
+ if (block_cluster != -1)
+ num_clusters++;
+ if (inode_cluster != -1)
+ num_clusters++;
+
+ return num_clusters;
}
-static unsigned int num_blocks_in_group(struct super_block *sb,
- ext4_group_t block_group)
+static unsigned int num_clusters_in_group(struct super_block *sb,
+ ext4_group_t block_group)
{
+ unsigned int blocks;
+
if (block_group == ext4_get_groups_count(sb) - 1) {
/*
* Even though mke2fs always initializes the first and
@@ -96,10 +143,11 @@ static unsigned int num_blocks_in_group(struct super_block *sb,
* we need to make sure we calculate the right free
* blocks.
*/
- return ext4_blocks_count(EXT4_SB(sb)->s_es) -
+ blocks = ext4_blocks_count(EXT4_SB(sb)->s_es) -
ext4_group_first_block_no(sb, block_group);
} else
- return EXT4_BLOCKS_PER_GROUP(sb);
+ blocks = EXT4_BLOCKS_PER_GROUP(sb);
+ return EXT4_NUM_B2C(EXT4_SB(sb), blocks);
}
/* Initializes an uninitialized block bitmap */
@@ -107,7 +155,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
ext4_group_t block_group,
struct ext4_group_desc *gdp)
{
- unsigned int bit, bit_max = num_base_meta_blocks(sb, block_group);
+ unsigned int bit, bit_max;
struct ext4_sb_info *sbi = EXT4_SB(sb);
ext4_fsblk_t start, tmp;
int flex_bg = 0;
@@ -126,6 +174,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
}
memset(bh->b_data, 0, sb->s_blocksize);
+ bit_max = ext4_num_base_meta_clusters(sb, block_group);
for (bit = 0; bit < bit_max; bit++)
ext4_set_bit(bit, bh->b_data);
@@ -137,24 +186,25 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
/* Set bits for block and inode bitmaps, and inode table */
tmp = ext4_block_bitmap(sb, gdp);
if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
- ext4_set_bit(tmp - start, bh->b_data);
+ ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
tmp = ext4_inode_bitmap(sb, gdp);
if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
- ext4_set_bit(tmp - start, bh->b_data);
+ ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
tmp = ext4_inode_table(sb, gdp);
for (; tmp < ext4_inode_table(sb, gdp) +
sbi->s_itb_per_group; tmp++) {
if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
- ext4_set_bit(tmp - start, bh->b_data);
+ ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
}
+
/*
* Also if the number of blocks within the group is less than
* the blocksize * 8 ( which is the size of bitmap ), set rest
* of the block bitmap to 1
*/
- ext4_mark_bitmap_end(num_blocks_in_group(sb, block_group),
+ ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group),
sb->s_blocksize * 8, bh->b_data);
}
@@ -165,9 +215,8 @@ unsigned ext4_free_blocks_after_init(struct super_block *sb,
ext4_group_t block_group,
struct ext4_group_desc *gdp)
{
- return num_blocks_in_group(sb, block_group) -
- num_base_meta_blocks(sb, block_group) -
- ext4_group_used_meta_blocks(sb, block_group, gdp);
+ return num_clusters_in_group(sb, block_group) -
+ ext4_num_overhead_clusters(sb, block_group, gdp);
}
/*
@@ -730,14 +779,14 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
}
/*
- * This function returns the number of file system metadata blocks at
+ * This function returns the number of file system metadata clusters at
* the beginning of a block group, including the reserved gdt blocks.
*/
-static unsigned int num_base_meta_blocks(struct super_block *sb,
- ext4_group_t block_group)
+unsigned ext4_num_base_meta_clusters(struct super_block *sb,
+ ext4_group_t block_group)
{
struct ext4_sb_info *sbi = EXT4_SB(sb);
- int num;
+ unsigned num;
/* Check for superblock and gdt backups in this group */
num = ext4_bg_has_super(sb, block_group);
@@ -752,5 +801,5 @@ static unsigned int num_base_meta_blocks(struct super_block *sb,
} else { /* For META_BG_BLOCK_GROUPS */
num += ext4_bg_num_gdb(sb, block_group);
}
- return num;
+ return EXT4_NUM_B2C(sbi, num);
}
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f66a566..9fe03c0 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -258,6 +258,14 @@ struct ext4_io_submit {
#endif
#define EXT4_BLOCK_ALIGN(size, blkbits) ALIGN((size), (1 << (blkbits)))
+/* Translate a block number to a cluster number */
+#define EXT4_B2C(sbi, blk) ((blk) >> (sbi)->s_cluster_bits)
+/* Translate a cluster number to a block number */
+#define EXT4_C2B(sbi, cluster) ((cluster) << (sbi)->s_cluster_bits)
+/* Translate # of blks to # of clusters */
+#define EXT4_NUM_B2C(sbi, blks) (((blks) + (sbi)->s_cluster_ratio - 1) >> \
+ (sbi)->s_cluster_bits)
+
/*
* Structure of a blocks group descriptor
*/
@@ -1684,6 +1692,11 @@ extern void ext4_init_block_bitmap(struct super_block *sb,
extern unsigned ext4_free_blocks_after_init(struct super_block *sb,
ext4_group_t block_group,
struct ext4_group_desc *gdp);
+extern unsigned ext4_num_base_meta_clusters(struct super_block *sb,
+ ext4_group_t block_group);
+extern unsigned ext4_num_overhead_clusters(struct super_block *sb,
+ ext4_group_t block_group,
+ struct ext4_group_desc *gdp);
/* dir.c */
extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 07/19] ext4: convert block group-relative offsets to use clusters
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (5 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 06/19] ext4: bigalloc changes to block bitmap initialization functions Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 08/19] ext4: teach mballoc preallocation code about bigalloc clusters Theodore Ts'o
` (12 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
Certain parts of the ext4 code base, primarily in mballoc.c, use a
block group number and offset from the beginning of the block group.
This offset is invariably used to index into the allocation bitmap, so
change the offset to be denominated in units of clusters.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/balloc.c | 6 ++++--
fs/ext4/mballoc.h | 3 ++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 332854c..a0a86ce 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -28,7 +28,8 @@
*/
/*
- * Calculate the block group number and offset, given a block number
+ * Calculate the block group number and offset into the block/cluster
+ * allocation bitmap, given a block number
*/
void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp)
@@ -37,7 +38,8 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
ext4_grpblk_t offset;
blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
- offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb));
+ offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb)) >>
+ EXT4_SB(sb)->s_cluster_bits;
if (offsetp)
*offsetp = offset;
if (blockgrpp)
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
index 22bd4d7..1a75182 100644
--- a/fs/ext4/mballoc.h
+++ b/fs/ext4/mballoc.h
@@ -223,6 +223,7 @@ struct ext4_buddy {
static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
struct ext4_free_extent *fex)
{
- return ext4_group_first_block_no(sb, fex->fe_group) + fex->fe_start;
+ return ext4_group_first_block_no(sb, fex->fe_group) +
+ (fex->fe_start << EXT4_SB(sb)->s_cluster_bits);
}
#endif
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 08/19] ext4: teach mballoc preallocation code about bigalloc clusters
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (6 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 07/19] ext4: convert block group-relative offsets to use clusters Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 09/19] ext4: teach ext4_free_blocks() about bigalloc and clusters Theodore Ts'o
` (11 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
In most of mballoc.c, we do everything in units of clusters, since the
block allocation bitmaps and buddy bitmaps are all denominated in
clusters. The one place where we do deal with absolute block numbers
is in the code that handles the preallocation regions, since in the
case of inode-based preallocation regions, the start of the
preallocation region can't be relative to the beginning of the group.
So this adds a bit of complexity, where pa_pstart and pa_lstart are
block numbers, while pa_free, pa_len, and fe_len are denominated in
units of clusters.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/mballoc.c | 81 ++++++++++++++++++++++++++++++-----------------------
fs/ext4/mballoc.h | 4 +-
2 files changed, 48 insertions(+), 37 deletions(-)
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index fb9e1aa..3a21001 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -70,8 +70,8 @@
*
* pa_lstart -> the logical start block for this prealloc space
* pa_pstart -> the physical start block for this prealloc space
- * pa_len -> length for this prealloc space
- * pa_free -> free space available in this prealloc space
+ * pa_len -> length for this prealloc space (in clusters)
+ * pa_free -> free space available in this prealloc space (in clusters)
*
* The inode preallocation space is used looking at the _logical_ start
* block. If only the logical file block falls within the range of prealloc
@@ -458,7 +458,7 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b,
ext4_fsblk_t blocknr;
blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
- blocknr += first + i;
+ blocknr += EXT4_C2B(EXT4_SB(sb), first + i);
ext4_grp_locked_error(sb, e4b->bd_group,
inode ? inode->i_ino : 0,
blocknr,
@@ -732,7 +732,7 @@ void ext4_mb_generate_buddy(struct super_block *sb,
if (free != grp->bb_free) {
ext4_grp_locked_error(sb, group, 0, 0,
- "%u blocks in bitmap, %u in gd",
+ "%u clusters in bitmap, %u in gd",
free, grp->bb_free);
/*
* If we intent to continue, we consider group descritor
@@ -1394,7 +1394,7 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
ext4_fsblk_t blocknr;
blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
- blocknr += block;
+ blocknr += EXT4_C2B(EXT4_SB(sb), block);
ext4_grp_locked_error(sb, e4b->bd_group,
inode ? inode->i_ino : 0,
blocknr,
@@ -1889,7 +1889,7 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
* we have free blocks
*/
ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
- "%d free blocks as per "
+ "%d free clusters as per "
"group info. But bitmap says 0",
free);
break;
@@ -1899,7 +1899,7 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
BUG_ON(ex.fe_len <= 0);
if (free < ex.fe_len) {
ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
- "%d free blocks as per "
+ "%d free clusters as per "
"group info. But got %d blocks",
free, ex.fe_len);
/*
@@ -2822,7 +2822,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
- len = ac->ac_b_ex.fe_len;
+ len = EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
if (!ext4_data_block_valid(sbi, block, len)) {
ext4_error(sb, "Allocating blocks %llu-%llu which overlap "
"fs metadata\n", block, block+len);
@@ -2918,6 +2918,7 @@ static noinline_for_stack void
ext4_mb_normalize_request(struct ext4_allocation_context *ac,
struct ext4_allocation_request *ar)
{
+ struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
int bsbits, max;
ext4_lblk_t end;
loff_t size, orig_size, start_off;
@@ -2948,7 +2949,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
/* first, let's learn actual file size
* given current request is allocated */
- size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
+ size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len);
size = size << bsbits;
if (size < i_size_read(ac->ac_inode))
size = i_size_read(ac->ac_inode);
@@ -3020,7 +3021,8 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
continue;
}
- pa_end = pa->pa_lstart + pa->pa_len;
+ pa_end = pa->pa_lstart + EXT4_C2B(EXT4_SB(ac->ac_sb),
+ pa->pa_len);
/* PA must not overlap original request */
BUG_ON(!(ac->ac_o_ex.fe_logical >= pa_end ||
@@ -3050,9 +3052,11 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
rcu_read_lock();
list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
ext4_lblk_t pa_end;
+
spin_lock(&pa->pa_lock);
if (pa->pa_deleted == 0) {
- pa_end = pa->pa_lstart + pa->pa_len;
+ pa_end = pa->pa_lstart + EXT4_C2B(EXT4_SB(ac->ac_sb),
+ pa->pa_len);
BUG_ON(!(start >= pa_end || end <= pa->pa_lstart));
}
spin_unlock(&pa->pa_lock);
@@ -3074,7 +3078,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
/* XXX: is it better to align blocks WRT to logical
* placement or satisfy big request as is */
ac->ac_g_ex.fe_logical = start;
- ac->ac_g_ex.fe_len = size;
+ ac->ac_g_ex.fe_len = EXT4_NUM_B2C(sbi, size);
/* define goal start in order to merge */
if (ar->pright && (ar->lright == (start + size))) {
@@ -3143,14 +3147,16 @@ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
struct ext4_prealloc_space *pa)
{
+ struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
ext4_fsblk_t start;
ext4_fsblk_t end;
int len;
/* found preallocated blocks, use them */
start = pa->pa_pstart + (ac->ac_o_ex.fe_logical - pa->pa_lstart);
- end = min(pa->pa_pstart + pa->pa_len, start + ac->ac_o_ex.fe_len);
- len = end - start;
+ end = min(pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len),
+ start + EXT4_C2B(sbi, ac->ac_o_ex.fe_len));
+ len = EXT4_NUM_B2C(sbi, end - start);
ext4_get_group_no_and_offset(ac->ac_sb, start, &ac->ac_b_ex.fe_group,
&ac->ac_b_ex.fe_start);
ac->ac_b_ex.fe_len = len;
@@ -3158,7 +3164,7 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
ac->ac_pa = pa;
BUG_ON(start < pa->pa_pstart);
- BUG_ON(start + len > pa->pa_pstart + pa->pa_len);
+ BUG_ON(end > pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len));
BUG_ON(pa->pa_free < len);
pa->pa_free -= len;
@@ -3224,6 +3230,7 @@ ext4_mb_check_group_pa(ext4_fsblk_t goal_block,
static noinline_for_stack int
ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
{
+ struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
int order, i;
struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
struct ext4_locality_group *lg;
@@ -3241,12 +3248,14 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
/* all fields in this condition don't change,
* so we can skip locking for them */
if (ac->ac_o_ex.fe_logical < pa->pa_lstart ||
- ac->ac_o_ex.fe_logical >= pa->pa_lstart + pa->pa_len)
+ ac->ac_o_ex.fe_logical >= (pa->pa_lstart +
+ EXT4_C2B(sbi, pa->pa_len)))
continue;
/* non-extent files can't have physical blocks past 2^32 */
if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) &&
- pa->pa_pstart + pa->pa_len > EXT4_MAX_BLOCK_FILE_PHYS)
+ (pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len) >
+ EXT4_MAX_BLOCK_FILE_PHYS))
continue;
/* found preallocated blocks, use them */
@@ -3443,6 +3452,7 @@ static noinline_for_stack int
ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
{
struct super_block *sb = ac->ac_sb;
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_prealloc_space *pa;
struct ext4_group_info *grp;
struct ext4_inode_info *ei;
@@ -3474,16 +3484,18 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
winl = ac->ac_o_ex.fe_logical - ac->ac_g_ex.fe_logical;
/* also, we should cover whole original request */
- wins = ac->ac_b_ex.fe_len - ac->ac_o_ex.fe_len;
+ wins = EXT4_C2B(sbi, ac->ac_b_ex.fe_len - ac->ac_o_ex.fe_len);
/* the smallest one defines real window */
win = min(winl, wins);
- offs = ac->ac_o_ex.fe_logical % ac->ac_b_ex.fe_len;
+ offs = ac->ac_o_ex.fe_logical %
+ EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
if (offs && offs < win)
win = offs;
- ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical - win;
+ ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical -
+ EXT4_B2C(sbi, win);
BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical);
BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len);
}
@@ -3508,7 +3520,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
trace_ext4_mb_new_inode_pa(ac, pa);
ext4_mb_use_inode_pa(ac, pa);
- atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
+ atomic_add(pa->pa_free, &sbi->s_mb_preallocated);
ei = EXT4_I(ac->ac_inode);
grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group);
@@ -3623,7 +3635,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
BUG_ON(pa->pa_deleted == 0);
ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
- grp_blk_start = pa->pa_pstart - bit;
+ grp_blk_start = pa->pa_pstart - EXT4_C2B(sbi, bit);
BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
end = bit + pa->pa_len;
@@ -3639,7 +3651,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
trace_ext4_mballoc_discard(sb, NULL, group, bit, next - bit);
trace_ext4_mb_release_inode_pa(sb, pa->pa_inode, pa,
- grp_blk_start + bit, next - bit);
+ grp_blk_start + EXT4_C2B(sbi, bit), next - bit);
mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
bit = next + 1;
}
@@ -3986,7 +3998,7 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY))
return;
- size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
+ size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len);
isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1)
>> bsbits;
@@ -4047,18 +4059,15 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
/* set up allocation goals */
memset(ac, 0, sizeof(struct ext4_allocation_context));
- ac->ac_b_ex.fe_logical = ar->logical;
+ ac->ac_b_ex.fe_logical = ar->logical & ~(sbi->s_cluster_ratio - 1);
ac->ac_status = AC_STATUS_CONTINUE;
ac->ac_sb = sb;
ac->ac_inode = ar->inode;
- ac->ac_o_ex.fe_logical = ar->logical;
+ ac->ac_o_ex.fe_logical = ac->ac_b_ex.fe_logical;
ac->ac_o_ex.fe_group = group;
ac->ac_o_ex.fe_start = block;
ac->ac_o_ex.fe_len = len;
- ac->ac_g_ex.fe_logical = ar->logical;
- ac->ac_g_ex.fe_group = group;
- ac->ac_g_ex.fe_start = block;
- ac->ac_g_ex.fe_len = len;
+ ac->ac_g_ex = ac->ac_o_ex;
ac->ac_flags = ar->flags;
/* we have to define context: we'll we work with a file or
@@ -4210,13 +4219,14 @@ static void ext4_mb_add_n_trim(struct ext4_allocation_context *ac)
*/
static int ext4_mb_release_context(struct ext4_allocation_context *ac)
{
+ struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
struct ext4_prealloc_space *pa = ac->ac_pa;
if (pa) {
if (pa->pa_type == MB_GROUP_PA) {
/* see comment in ext4_mb_use_group_pa() */
spin_lock(&pa->pa_lock);
- pa->pa_pstart += ac->ac_b_ex.fe_len;
- pa->pa_lstart += ac->ac_b_ex.fe_len;
+ pa->pa_pstart += EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+ pa->pa_lstart += EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
pa->pa_free -= ac->ac_b_ex.fe_len;
pa->pa_len -= ac->ac_b_ex.fe_len;
spin_unlock(&pa->pa_lock);
@@ -4309,7 +4319,8 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
return 0;
}
reserv_blks = ar->len;
- while (ar->len && dquot_alloc_block(ar->inode, ar->len)) {
+ while (ar->len && dquot_alloc_block(ar->inode,
+ EXT4_C2B(sbi, ar->len))) {
ar->flags |= EXT4_MB_HINT_NOPREALLOC;
ar->len--;
}
@@ -4387,7 +4398,7 @@ out:
if (ac)
kmem_cache_free(ext4_ac_cachep, ac);
if (inquota && ar->len < inquota)
- dquot_free_block(ar->inode, inquota - ar->len);
+ dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
if (!ar->len) {
if (!ext4_test_inode_state(ar->inode,
EXT4_STATE_DELALLOC_RESERVED))
@@ -4693,7 +4704,7 @@ do_more:
ext4_mark_super_dirty(sb);
error_return:
if (freed)
- dquot_free_block(inode, freed);
+ dquot_free_block(inode, EXT4_C2B(sbi, freed));
brelse(bitmap_bh);
ext4_std_error(sb, err);
return;
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
index 1a75182..6990fb2 100644
--- a/fs/ext4/mballoc.h
+++ b/fs/ext4/mballoc.h
@@ -139,9 +139,9 @@ enum {
struct ext4_free_extent {
ext4_lblk_t fe_logical;
- ext4_grpblk_t fe_start;
+ ext4_grpblk_t fe_start; /* In cluster units */
ext4_group_t fe_group;
- ext4_grpblk_t fe_len;
+ ext4_grpblk_t fe_len; /* In cluster units */
};
/*
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 09/19] ext4: teach ext4_free_blocks() about bigalloc and clusters
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (7 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 08/19] ext4: teach mballoc preallocation code about bigalloc clusters Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 10/19] ext4: teach ext4_ext_map_blocks() about the bigalloc feature Theodore Ts'o
` (10 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
The ext4_free_blocks() function now has two new flags that indicate
whether a partial cluster at the beginning or the end of the block
extents should be freed or not. That will be up the caller (i.e.,
truncate), who can figure out whether partial clusters at the
beginning or the end of a block range can be freed.
We also have to update the ext4_mb_free_metadata() and
release_blocks_on_commit() machinery to be cluster-based, since it is
used by ext4_free_blocks().
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/ext4.h | 2 +
fs/ext4/mballoc.c | 86 ++++++++++++++++++++++++++++++++++++++---------------
fs/ext4/mballoc.h | 2 +-
3 files changed, 65 insertions(+), 25 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 9fe03c0..6cf000a 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -532,6 +532,8 @@ struct ext4_new_group_data {
#define EXT4_FREE_BLOCKS_METADATA 0x0001
#define EXT4_FREE_BLOCKS_FORGET 0x0002
#define EXT4_FREE_BLOCKS_VALIDATED 0x0004
+#define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0008
+#define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0010
/*
* ioctl commands
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 3a21001..e9fe35d 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2642,11 +2642,13 @@ int ext4_mb_release(struct super_block *sb)
}
static inline int ext4_issue_discard(struct super_block *sb,
- ext4_group_t block_group, ext4_grpblk_t block, int count)
+ ext4_group_t block_group, ext4_grpblk_t cluster, int count)
{
ext4_fsblk_t discard_block;
- discard_block = block + ext4_group_first_block_no(sb, block_group);
+ discard_block = (EXT4_C2B(EXT4_SB(sb), cluster) +
+ ext4_group_first_block_no(sb, block_group));
+ count = EXT4_C2B(EXT4_SB(sb), count);
trace_ext4_discard_blocks(sb,
(unsigned long long) discard_block, count);
return sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
@@ -2673,7 +2675,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
if (test_opt(sb, DISCARD))
ext4_issue_discard(sb, entry->group,
- entry->start_blk, entry->count);
+ entry->start_cluster, entry->count);
err = ext4_mb_load_buddy(sb, entry->group, &e4b);
/* we expect to find existing buddy because it's pinned */
@@ -2686,7 +2688,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
ext4_lock_group(sb, entry->group);
/* Take it out of per group rb tree */
rb_erase(&entry->node, &(db->bb_free_root));
- mb_free_blocks(NULL, &e4b, entry->start_blk, entry->count);
+ mb_free_blocks(NULL, &e4b, entry->start_cluster, entry->count);
if (!db->bb_free_root.rb_node) {
/* No more items in the per group rb tree
@@ -3331,7 +3333,7 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
while (n) {
entry = rb_entry(n, struct ext4_free_data, node);
- mb_set_bits(bitmap, entry->start_blk, entry->count);
+ mb_set_bits(bitmap, entry->start_cluster, entry->count);
n = rb_next(n);
}
return;
@@ -4422,7 +4424,7 @@ static int can_merge(struct ext4_free_data *entry1,
{
if ((entry1->t_tid == entry2->t_tid) &&
(entry1->group == entry2->group) &&
- ((entry1->start_blk + entry1->count) == entry2->start_blk))
+ ((entry1->start_cluster + entry1->count) == entry2->start_cluster))
return 1;
return 0;
}
@@ -4432,7 +4434,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
struct ext4_free_data *new_entry)
{
ext4_group_t group = e4b->bd_group;
- ext4_grpblk_t block;
+ ext4_grpblk_t cluster;
struct ext4_free_data *entry;
struct ext4_group_info *db = e4b->bd_info;
struct super_block *sb = e4b->bd_sb;
@@ -4445,7 +4447,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
BUG_ON(e4b->bd_buddy_page == NULL);
new_node = &new_entry->node;
- block = new_entry->start_blk;
+ cluster = new_entry->start_cluster;
if (!*n) {
/* first free block exent. We need to
@@ -4459,13 +4461,14 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
while (*n) {
parent = *n;
entry = rb_entry(parent, struct ext4_free_data, node);
- if (block < entry->start_blk)
+ if (cluster < entry->start_cluster)
n = &(*n)->rb_left;
- else if (block >= (entry->start_blk + entry->count))
+ else if (cluster >= (entry->start_cluster + entry->count))
n = &(*n)->rb_right;
else {
ext4_grp_locked_error(sb, group, 0,
- ext4_group_first_block_no(sb, group) + block,
+ ext4_group_first_block_no(sb, group) +
+ EXT4_C2B(sbi, cluster),
"Block already on to-be-freed list");
return 0;
}
@@ -4479,7 +4482,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
if (node) {
entry = rb_entry(node, struct ext4_free_data, node);
if (can_merge(entry, new_entry)) {
- new_entry->start_blk = entry->start_blk;
+ new_entry->start_cluster = entry->start_cluster;
new_entry->count += entry->count;
rb_erase(node, &(db->bb_free_root));
spin_lock(&sbi->s_md_lock);
@@ -4530,6 +4533,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
ext4_group_t block_group;
struct ext4_sb_info *sbi;
struct ext4_buddy e4b;
+ unsigned int count_clusters;
int err = 0;
int ret;
@@ -4578,6 +4582,38 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
if (!ext4_should_writeback_data(inode))
flags |= EXT4_FREE_BLOCKS_METADATA;
+ /*
+ * If the extent to be freed does not begin on a cluster
+ * boundary, we need to deal with partial clusters at the
+ * beginning and end of the extent. Normally we will free
+ * blocks at the beginning or the end unless we are explicitly
+ * requested to avoid doing so.
+ */
+ overflow = block & (sbi->s_cluster_ratio - 1);
+ if (overflow) {
+ if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
+ overflow = sbi->s_cluster_ratio - overflow;
+ block += overflow;
+ if (count > overflow)
+ count -= overflow;
+ else
+ return;
+ } else {
+ block -= overflow;
+ count += overflow;
+ }
+ }
+ overflow = count & (sbi->s_cluster_ratio - 1);
+ if (overflow) {
+ if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
+ if (count > overflow)
+ count -= overflow;
+ else
+ return;
+ } else
+ count += sbi->s_cluster_ratio - overflow;
+ }
+
do_more:
overflow = 0;
ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
@@ -4586,10 +4622,12 @@ do_more:
* Check to see if we are freeing blocks across a group
* boundary.
*/
- if (bit + count > EXT4_CLUSTERS_PER_GROUP(sb)) {
- overflow = bit + count - EXT4_CLUSTERS_PER_GROUP(sb);
+ if (EXT4_C2B(sbi, bit) + count > EXT4_BLOCKS_PER_GROUP(sb)) {
+ overflow = EXT4_C2B(sbi, bit) + count -
+ EXT4_BLOCKS_PER_GROUP(sb);
count -= overflow;
}
+ count_clusters = EXT4_B2C(sbi, count);
bitmap_bh = ext4_read_block_bitmap(sb, block_group);
if (!bitmap_bh) {
err = -EIO;
@@ -4604,9 +4642,9 @@ do_more:
if (in_range(ext4_block_bitmap(sb, gdp), block, count) ||
in_range(ext4_inode_bitmap(sb, gdp), block, count) ||
in_range(block, ext4_inode_table(sb, gdp),
- EXT4_SB(sb)->s_itb_per_group) ||
+ EXT4_SB(sb)->s_itb_per_group) ||
in_range(block + count - 1, ext4_inode_table(sb, gdp),
- EXT4_SB(sb)->s_itb_per_group)) {
+ EXT4_SB(sb)->s_itb_per_group)) {
ext4_error(sb, "Freeing blocks in system zone - "
"Block = %llu, count = %lu", block, count);
@@ -4631,11 +4669,11 @@ do_more:
#ifdef AGGRESSIVE_CHECK
{
int i;
- for (i = 0; i < count; i++)
+ for (i = 0; i < count_clusters; i++)
BUG_ON(!mb_test_bit(bit + i, bitmap_bh->b_data));
}
#endif
- trace_ext4_mballoc_free(sb, inode, block_group, bit, count);
+ trace_ext4_mballoc_free(sb, inode, block_group, bit, count_clusters);
err = ext4_mb_load_buddy(sb, block_group, &e4b);
if (err)
@@ -4652,13 +4690,13 @@ do_more:
err = -ENOMEM;
goto error_return;
}
- new_entry->start_blk = bit;
+ new_entry->start_cluster = bit;
new_entry->group = block_group;
- new_entry->count = count;
+ new_entry->count = count_clusters;
new_entry->t_tid = handle->h_transaction->t_tid;
ext4_lock_group(sb, block_group);
- mb_clear_bits(bitmap_bh->b_data, bit, count);
+ mb_clear_bits(bitmap_bh->b_data, bit, count_clusters);
ext4_mb_free_metadata(handle, &e4b, new_entry);
} else {
/* need to update group_info->bb_free and bitmap
@@ -4666,11 +4704,11 @@ do_more:
* them with group lock_held
*/
ext4_lock_group(sb, block_group);
- mb_clear_bits(bitmap_bh->b_data, bit, count);
- mb_free_blocks(inode, &e4b, bit, count);
+ mb_clear_bits(bitmap_bh->b_data, bit, count_clusters);
+ mb_free_blocks(inode, &e4b, bit, count_clusters);
}
- ret = ext4_free_blks_count(sb, gdp) + count;
+ ret = ext4_free_blks_count(sb, gdp) + count_clusters;
ext4_free_blks_set(sb, gdp, ret);
gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
ext4_unlock_group(sb, block_group);
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
index 6990fb2..76b048a 100644
--- a/fs/ext4/mballoc.h
+++ b/fs/ext4/mballoc.h
@@ -106,7 +106,7 @@ struct ext4_free_data {
ext4_group_t group;
/* free block extent */
- ext4_grpblk_t start_blk;
+ ext4_grpblk_t start_cluster;
ext4_grpblk_t count;
/* transaction which freed this extent */
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 10/19] ext4: teach ext4_ext_map_blocks() about the bigalloc feature
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (8 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 09/19] ext4: teach ext4_free_blocks() about bigalloc and clusters Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 11/19] ext4: teach ext4_ext_truncate() " Theodore Ts'o
` (9 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
If we need to allocate a new block in ext4_ext_map_blocks(), the
function needs to see if the cluster has already been allocated.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/extents.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 140 insertions(+), 19 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index e363f21..2730508 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1277,7 +1277,8 @@ static int ext4_ext_search_left(struct inode *inode,
*/
static int ext4_ext_search_right(struct inode *inode,
struct ext4_ext_path *path,
- ext4_lblk_t *logical, ext4_fsblk_t *phys)
+ ext4_lblk_t *logical, ext4_fsblk_t *phys,
+ struct ext4_extent **ret_ex)
{
struct buffer_head *bh = NULL;
struct ext4_extent_header *eh;
@@ -1319,9 +1320,7 @@ static int ext4_ext_search_right(struct inode *inode,
return -EIO;
}
}
- *logical = le32_to_cpu(ex->ee_block);
- *phys = ext4_ext_pblock(ex);
- return 0;
+ goto found_extent;
}
if (unlikely(*logical < (le32_to_cpu(ex->ee_block) + ee_len))) {
@@ -1334,9 +1333,7 @@ static int ext4_ext_search_right(struct inode *inode,
if (ex != EXT_LAST_EXTENT(path[depth].p_hdr)) {
/* next allocated block in this leaf */
ex++;
- *logical = le32_to_cpu(ex->ee_block);
- *phys = ext4_ext_pblock(ex);
- return 0;
+ goto found_extent;
}
/* go up and search for index to the right */
@@ -1379,9 +1376,12 @@ got_index:
return -EIO;
}
ex = EXT_FIRST_EXTENT(eh);
+found_extent:
*logical = le32_to_cpu(ex->ee_block);
*phys = ext4_ext_pblock(ex);
- put_bh(bh);
+ *ret_ex = ex;
+ if (bh)
+ put_bh(bh);
return 0;
}
@@ -1635,7 +1635,8 @@ static int ext4_ext_try_to_merge(struct inode *inode,
* such that there will be no overlap, and then returns 1.
* If there is no overlap found, it returns 0.
*/
-static unsigned int ext4_ext_check_overlap(struct inode *inode,
+static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
+ struct inode *inode,
struct ext4_extent *newext,
struct ext4_ext_path *path)
{
@@ -1649,6 +1650,7 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode,
if (!path[depth].p_ext)
goto out;
b2 = le32_to_cpu(path[depth].p_ext->ee_block);
+ b2 &= ~(sbi->s_cluster_ratio - 1);
/*
* get the next allocated block if the extent in the path
@@ -1658,6 +1660,7 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode,
b2 = ext4_ext_next_allocated_block(path);
if (b2 == EXT_MAX_BLOCK)
goto out;
+ b2 &= ~(sbi->s_cluster_ratio - 1);
}
/* check for wrap through zero on extent logical start block*/
@@ -3135,6 +3138,85 @@ out2:
}
/*
+ * get_implied_cluster_alloc - check to see if the requested
+ * allocation (in the map structure) overlaps with a cluster already
+ * allocated in an extent.
+ * @sbi The ext4-specific superblock structure
+ * @map The requested lblk->pblk mapping
+ * @ex The extent structure which might contain an implied
+ * cluster allocation
+ *
+ * This function is called by ext4_ext_map_blocks() after we failed to
+ * find blocks that were already in the inode's extent tree. Hence,
+ * we know that the beginning of the requested region cannot overlap
+ * the extent from the inode's extent tree. There are two cases we
+ * want to catch. The first is this case:
+ *
+ * |--- cluster # N--|
+ * |--- extent ---| |---- requested region ---|
+ * |==========|
+ *
+ * The second case that we need to test for is this one:
+ *
+ * |--------- cluster # N ----------------|
+ * |--- requested region --| |------- extent ----|
+ * |=======================|
+ *
+ * In each of the above two cases, we need to set the map->m_pblk and
+ * map->m_len so it corresponds to the return the extent labelled as
+ * "|====|" from cluster #N, since it is already in use for data in
+ * cluster EXT4_B2C(sbi, map->m_lblk). We will then return 1 to
+ * signal to ext4_ext_map_blocks() that map->m_pblk should be treated
+ * as a new "allocated" block region. Otherwise, we will return 0 and
+ * ext4_ext_map_blocks() will then allocate one or more new clusters
+ * by calling ext4_mb_new_blocks().
+ */
+static int get_implied_cluster_alloc(struct ext4_sb_info *sbi,
+ struct ext4_map_blocks *map,
+ struct ext4_extent *ex)
+{
+ ext4_lblk_t c_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+ ext4_lblk_t ex_cluster_start, ex_cluster_end;
+ ext4_lblk_t rr_cluster_start, rr_cluster_end;
+ ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
+ ext4_fsblk_t ee_start = ext4_ext_pblock(ex);
+ unsigned short ee_len = ext4_ext_get_actual_len(ex);
+
+ /* The extent passed in that we are trying to match */
+ ex_cluster_start = EXT4_B2C(sbi, ee_block);
+ ex_cluster_end = EXT4_B2C(sbi, ee_block + ee_len - 1);
+
+ /* The requested region passed into ext4_map_blocks() */
+ rr_cluster_start = EXT4_B2C(sbi, map->m_lblk);
+ rr_cluster_end = EXT4_B2C(sbi, map->m_lblk + map->m_len - 1);
+
+ if ((rr_cluster_start == ex_cluster_end) ||
+ (rr_cluster_start == ex_cluster_start)) {
+ if (rr_cluster_start == ex_cluster_end)
+ ee_start += ee_len - 1;
+ map->m_pblk = (ee_start & ~(sbi->s_cluster_ratio - 1)) +
+ c_offset;
+ map->m_len = min(map->m_len,
+ (unsigned) sbi->s_cluster_ratio - c_offset);
+ /*
+ * Check for and handle this case:
+ *
+ * |--------- cluster # N-------------|
+ * |------- extent ----|
+ * |--- requested region ---|
+ * |===========|
+ */
+
+ if ((map->m_lblk < ee_block) &&
+ (map->m_lblk + map->m_len > ee_block))
+ map->m_len = ee_block - map->m_lblk;
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
* Block allocation/map/preallocation routine for extents based files
*
*
@@ -3156,12 +3238,14 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
struct ext4_map_blocks *map, int flags)
{
struct ext4_ext_path *path = NULL;
- struct ext4_extent newex, *ex;
+ struct ext4_extent newex, *ex, *ex2;
+ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
ext4_fsblk_t newblock = 0;
- int err = 0, depth, ret;
- unsigned int allocated = 0;
+ int free_on_err = 0, err = 0, depth, ret;
+ unsigned int allocated = 0, offset = 0;
struct ext4_allocation_request ar;
ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
+ ext4_lblk_t cluster_offset;
ext_debug("blocks %u/%u requested for inode %lu\n",
map->m_lblk, map->m_len, inode->i_ino);
@@ -3258,9 +3342,22 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
ext4_ext_put_gap_in_cache(inode, path, map->m_lblk);
goto out2;
}
+
/*
* Okay, we need to do block allocation.
*/
+ newex.ee_block = cpu_to_le32(map->m_lblk);
+ cluster_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+ /*
+ * If we are doing bigalloc, check to see if the extent returned
+ * by ext4_ext_find_extent() implies a cluster we can use.
+ */
+ if (cluster_offset && ex &&
+ get_implied_cluster_alloc(sbi, map, ex)) {
+ ar.len = allocated = map->m_len;
+ newblock = map->m_pblk;
+ goto got_allocated_blocks;
+ }
/* find neighbour allocated blocks */
ar.lleft = map->m_lblk;
@@ -3268,10 +3365,20 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
if (err)
goto out2;
ar.lright = map->m_lblk;
- err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright);
+ ex2 = NULL;
+ err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright, &ex2);
if (err)
goto out2;
+ /* Check if the extent after searching to the right implies a
+ * cluster we can use. */
+ if ((sbi->s_cluster_ratio > 1) && ex2 &&
+ get_implied_cluster_alloc(sbi, map, ex2)) {
+ ar.len = allocated = map->m_len;
+ newblock = map->m_pblk;
+ goto got_allocated_blocks;
+ }
+
/*
* See if request is beyond maximum number of blocks we can have in
* a single extent. For an initialized extent this limit is
@@ -3286,9 +3393,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
map->m_len = EXT_UNINIT_MAX_LEN;
/* Check if we can really insert (m_lblk)::(m_lblk + m_len) extent */
- newex.ee_block = cpu_to_le32(map->m_lblk);
newex.ee_len = cpu_to_le16(map->m_len);
- err = ext4_ext_check_overlap(inode, &newex, path);
+ err = ext4_ext_check_overlap(sbi, inode, &newex, path);
if (err)
allocated = ext4_ext_get_actual_len(&newex);
else
@@ -3298,7 +3404,18 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
ar.inode = inode;
ar.goal = ext4_ext_find_goal(inode, path, map->m_lblk);
ar.logical = map->m_lblk;
- ar.len = allocated;
+ /*
+ * We calculate the offset from the beginning of the cluster
+ * for the logical block number, since when we allocate a
+ * physical cluster, the physical block should start at the
+ * same offset from the beginning of the cluster. This is
+ * needed so that future calls to get_implied_cluster_alloc()
+ * work correctly.
+ */
+ offset = map->m_lblk & (sbi->s_cluster_ratio - 1);
+ ar.len = EXT4_NUM_B2C(sbi, offset+allocated);
+ ar.goal -= offset;
+ ar.logical -= offset;
if (S_ISREG(inode->i_mode))
ar.flags = EXT4_MB_HINT_DATA;
else
@@ -3309,9 +3426,14 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
goto out2;
ext_debug("allocate new block: goal %llu, found %llu/%u\n",
ar.goal, newblock, allocated);
+ free_on_err = 1;
+ ar.len = EXT4_C2B(sbi, ar.len) - offset;
+ if (ar.len > allocated)
+ ar.len = allocated;
+got_allocated_blocks:
/* try to insert new extent into found leaf and return */
- ext4_ext_store_pblock(&newex, newblock);
+ ext4_ext_store_pblock(&newex, newblock + offset);
newex.ee_len = cpu_to_le16(ar.len);
/* Mark uninitialized */
if (flags & EXT4_GET_BLOCKS_UNINIT_EXT){
@@ -3340,7 +3462,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
goto out2;
err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
- if (err) {
+ if (err && free_on_err) {
/* free data blocks we just allocated */
/* not a good idea to call discard here directly,
* but otherwise we'd need to call it every free() */
@@ -3900,4 +4022,3 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
return error;
}
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 11/19] ext4: teach ext4_ext_truncate() about the bigalloc feature
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (9 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 10/19] ext4: teach ext4_ext_map_blocks() about the bigalloc feature Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 12/19] ext4: convert s_freeblocks_counter to s_freeclusters_counter Theodore Ts'o
` (8 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
When we are truncating (as opposed unlinking) a file, we need to worry
about partial truncates of a file, especially in the light of sparse
files. The changes here make sure that arbitrary truncates of sparse
files works correctly. Yeah, it's messy.
Note that these functions will need to be revisted when the punch
ioctl is integrated --- in fact this commit will probably have merge
conflicts with the punch changes which Allison Henders and the IBM LTC
have been working on. I will need to fix this up when either patch
hits mainline.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/extents.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 72 insertions(+), 10 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 2730508..a051adf 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2156,14 +2156,39 @@ int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
}
static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
- struct ext4_extent *ex,
- ext4_lblk_t from, ext4_lblk_t to)
+ struct ext4_extent *ex,
+ ext4_fsblk_t *partial_cluster,
+ ext4_lblk_t from, ext4_lblk_t to)
{
+ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
unsigned short ee_len = ext4_ext_get_actual_len(ex);
+ ext4_fsblk_t pblk;
int flags = EXT4_FREE_BLOCKS_FORGET;
if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
flags |= EXT4_FREE_BLOCKS_METADATA;
+ /*
+ * For bigalloc file systems, we never free a partial cluster
+ * at the beginning of the extent. Instead, we make a note
+ * that we tried freeing the cluster, and check to see if we
+ * need to free it on a subsequent call to ext4_remove_blocks,
+ * or at the end of the ext4_truncate() operation.
+ */
+ flags |= EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER;
+
+ /*
+ * If we have a partial cluster, and it's different from the
+ * cluster of the last block, we need to explicitly free the
+ * partial cluster here.
+ */
+ pblk = ext4_ext_pblock(ex) + ee_len - 1;
+ if (*partial_cluster && (EXT4_B2C(sbi, pblk) != *partial_cluster)) {
+ ext4_free_blocks(handle, inode, NULL,
+ EXT4_C2B(sbi, *partial_cluster),
+ sbi->s_cluster_ratio, flags);
+ *partial_cluster = 0;
+ }
+
#ifdef EXTENTS_STATS
{
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
@@ -2183,12 +2208,24 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
&& to == le32_to_cpu(ex->ee_block) + ee_len - 1) {
/* tail removal */
ext4_lblk_t num;
- ext4_fsblk_t start;
num = le32_to_cpu(ex->ee_block) + ee_len - from;
- start = ext4_ext_pblock(ex) + ee_len - num;
- ext_debug("free last %u blocks starting %llu\n", num, start);
- ext4_free_blocks(handle, inode, NULL, start, num, flags);
+ pblk = ext4_ext_pblock(ex) + ee_len - num;
+ ext_debug("free last %u blocks starting %llu\n", num, pblk);
+ ext4_free_blocks(handle, inode, NULL, pblk, num, flags);
+ /*
+ * If the block range to be freed didn't start at the
+ * beginning of a cluster, and we removed the entire
+ * extent, save the partial cluster here, since we
+ * might need to delete if we determine that the
+ * truncate operation has removed all of the blocks in
+ * the cluster.
+ */
+ if (pblk & (sbi->s_cluster_ratio - 1) &&
+ (ee_len == num))
+ *partial_cluster = EXT4_B2C(sbi, pblk);
+ else
+ *partial_cluster = 0;
} else if (from == le32_to_cpu(ex->ee_block)
&& to <= le32_to_cpu(ex->ee_block) + ee_len - 1) {
printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n",
@@ -2203,8 +2240,10 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
static int
ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
- struct ext4_ext_path *path, ext4_lblk_t start)
+ struct ext4_ext_path *path, ext4_fsblk_t *partial_cluster,
+ ext4_lblk_t start)
{
+ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
int err = 0, correct_index = 0;
int depth = ext_depth(inode), credits;
struct ext4_extent_header *eh;
@@ -2291,7 +2330,8 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
if (err)
goto out;
- err = ext4_remove_blocks(handle, inode, ex, a, b);
+ err = ext4_remove_blocks(handle, inode, ex, partial_cluster,
+ a, b);
if (err)
goto out;
@@ -2299,7 +2339,8 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
/* this extent is removed; mark slot entirely unused */
ext4_ext_store_pblock(ex, 0);
le16_add_cpu(&eh->eh_entries, -1);
- }
+ } else
+ *partial_cluster = 0;
ex->ee_block = cpu_to_le32(block);
ex->ee_len = cpu_to_le16(num);
@@ -2324,6 +2365,25 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
if (correct_index && eh->eh_entries)
err = ext4_ext_correct_indexes(handle, inode, path);
+ /*
+ * If there is still a entry in the leaf node, check to see if
+ * it references the partial cluster. This is the only place
+ * where it could; if it doesn't, we can free the cluster.
+ */
+ if (*partial_cluster && ex >= EXT_FIRST_EXTENT(eh) &&
+ (EXT4_B2C(sbi, ext4_ext_pblock(ex) + ex_ee_len - 1) !=
+ *partial_cluster)) {
+ int flags = EXT4_FREE_BLOCKS_FORGET;
+
+ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+ flags |= EXT4_FREE_BLOCKS_METADATA;
+
+ ext4_free_blocks(handle, inode, NULL,
+ EXT4_C2B(sbi, *partial_cluster),
+ sbi->s_cluster_ratio, flags);
+ *partial_cluster = 0;
+ }
+
/* if this leaf is free, then we should
* remove it from index block above */
if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
@@ -2359,6 +2419,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
struct super_block *sb = inode->i_sb;
int depth = ext_depth(inode);
struct ext4_ext_path *path;
+ ext4_fsblk_t partial_cluster = 0;
handle_t *handle;
int i, err;
@@ -2393,7 +2454,8 @@ again:
while (i >= 0 && err == 0) {
if (i == depth) {
/* this is leaf block */
- err = ext4_ext_rm_leaf(handle, inode, path, start);
+ err = ext4_ext_rm_leaf(handle, inode, path,
+ &partial_cluster, start);
/* root level has p_bh == NULL, brelse() eats this */
brelse(path[i].p_bh);
path[i].p_bh = NULL;
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 12/19] ext4: convert s_freeblocks_counter to s_freeclusters_counter
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (10 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 11/19] ext4: teach ext4_ext_truncate() " Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 13/19] ext4: convert the free_blocks field in s_flex_groups to be free_clusters Theodore Ts'o
` (7 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
Convert the percpu counter s_freeblocks_counter in struct
ext4_super_info to be s_freeclusters_counter.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/balloc.c | 9 +++++----
fs/ext4/ext4.h | 2 +-
fs/ext4/ialloc.c | 3 ++-
fs/ext4/inode.c | 6 ++++--
fs/ext4/mballoc.c | 4 ++--
fs/ext4/resize.c | 4 ++--
fs/ext4/super.c | 18 ++++++++++--------
7 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index a0a86ce..c0b74ca 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -495,7 +495,8 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
ext4_free_blks_set(sb, desc, blk_free_count);
desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
ext4_unlock_group(sb, block_group);
- percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed);
+ percpu_counter_add(&sbi->s_freeclusters_counter,
+ EXT4_B2C(sbi, blocks_freed));
if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
@@ -537,16 +538,16 @@ error_return:
static int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks)
{
s64 free_blocks, dirty_blocks, root_blocks;
- struct percpu_counter *fbc = &sbi->s_freeblocks_counter;
+ struct percpu_counter *fcc = &sbi->s_freeclusters_counter;
struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter;
- free_blocks = percpu_counter_read_positive(fbc);
+ free_blocks = EXT4_C2B(sbi, percpu_counter_read_positive(fcc));
dirty_blocks = percpu_counter_read_positive(dbc);
root_blocks = ext4_r_blocks_count(sbi->s_es);
if (free_blocks - (nblocks + root_blocks + dirty_blocks) <
EXT4_FREEBLOCKS_WATERMARK) {
- free_blocks = percpu_counter_sum_positive(fbc);
+ free_blocks = EXT4_C2B(sbi, percpu_counter_sum_positive(fcc));
dirty_blocks = percpu_counter_sum_positive(dbc);
}
/* Check whether we have space after
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 6cf000a..35441b3 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1127,7 +1127,7 @@ struct ext4_sb_info {
u32 s_hash_seed[4];
int s_def_hash_version;
int s_hash_unsigned; /* 3 if hash should be signed, 0 if not */
- struct percpu_counter s_freeblocks_counter;
+ struct percpu_counter s_freeclusters_counter;
struct percpu_counter s_freeinodes_counter;
struct percpu_counter s_dirs_counter;
struct percpu_counter s_dirtyblocks_counter;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index d0770b6..d95a157 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -490,7 +490,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
avefreei = freei / ngroups;
- freeb = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
+ freeb = EXT4_C2B(sbi,
+ percpu_counter_read_positive(&sbi->s_freeclusters_counter));
avefreeb = freeb;
do_div(avefreeb, ngroups);
ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index df7ce6a..cc5910d 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2211,7 +2211,8 @@ static void ext4_print_free_blocks(struct inode *inode)
ext4_count_free_blocks(inode->i_sb));
printk(KERN_CRIT "Free/Dirty block details\n");
printk(KERN_CRIT "free_blocks=%lld\n",
- (long long) percpu_counter_sum(&sbi->s_freeblocks_counter));
+ (long long) EXT4_C2B(EXT4_SB(inode->i_sb),
+ percpu_counter_sum(&sbi->s_freeclusters_counter)));
printk(KERN_CRIT "dirty_blocks=%lld\n",
(long long) percpu_counter_sum(&sbi->s_dirtyblocks_counter));
printk(KERN_CRIT "Block reservation details\n");
@@ -3087,7 +3088,8 @@ static int ext4_nonda_switch(struct super_block *sb)
* Delalloc need an accurate free block accounting. So switch
* to non delalloc when we are near to error range.
*/
- free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
+ free_blocks = EXT4_C2B(sbi,
+ percpu_counter_read_positive(&sbi->s_freeclusters_counter));
dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyblocks_counter);
if (2 * free_blocks < 3 * dirty_blocks ||
free_blocks < (dirty_blocks + EXT4_FREEBLOCKS_WATERMARK)) {
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index e9fe35d..7a9cbe1 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2864,7 +2864,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
- percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len);
+ percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len);
/*
* Now reduce the dirty block count also. Should not go negative
*/
@@ -4712,7 +4712,7 @@ do_more:
ext4_free_blks_set(sb, gdp, ret);
gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
ext4_unlock_group(sb, block_group);
- percpu_counter_add(&sbi->s_freeblocks_counter, count);
+ percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 80bbc9c..405c1cb 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -919,8 +919,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
input->reserved_blocks);
/* Update the free space counts */
- percpu_counter_add(&sbi->s_freeblocks_counter,
- input->free_blocks_count);
+ percpu_counter_add(&sbi->s_freeclusters_counter,
+ EXT4_B2C(sbi, input->free_blocks_count));
percpu_counter_add(&sbi->s_freeinodes_counter,
EXT4_INODES_PER_GROUP(sb));
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 5ae1712..6b4a3f4 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -793,7 +793,7 @@ static void ext4_put_super(struct super_block *sb)
vfree(sbi->s_flex_groups);
else
kfree(sbi->s_flex_groups);
- percpu_counter_destroy(&sbi->s_freeblocks_counter);
+ percpu_counter_destroy(&sbi->s_freeclusters_counter);
percpu_counter_destroy(&sbi->s_freeinodes_counter);
percpu_counter_destroy(&sbi->s_dirs_counter);
percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
@@ -3499,7 +3499,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_err_report.function = print_daily_error_info;
sbi->s_err_report.data = (unsigned long) sb;
- err = percpu_counter_init(&sbi->s_freeblocks_counter,
+ err = percpu_counter_init(&sbi->s_freeclusters_counter,
ext4_count_free_blocks(sb));
if (!err) {
err = percpu_counter_init(&sbi->s_freeinodes_counter,
@@ -3621,7 +3621,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
* The journal may have updated the bg summary counts, so we
* need to update the global counters.
*/
- percpu_counter_set(&sbi->s_freeblocks_counter,
+ percpu_counter_set(&sbi->s_freeclusters_counter,
ext4_count_free_blocks(sb));
percpu_counter_set(&sbi->s_freeinodes_counter,
ext4_count_free_inodes(sb));
@@ -3790,7 +3790,7 @@ failed_mount3:
else
kfree(sbi->s_flex_groups);
}
- percpu_counter_destroy(&sbi->s_freeblocks_counter);
+ percpu_counter_destroy(&sbi->s_freeclusters_counter);
percpu_counter_destroy(&sbi->s_freeinodes_counter);
percpu_counter_destroy(&sbi->s_dirs_counter);
percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
@@ -4114,8 +4114,9 @@ static int ext4_commit_super(struct super_block *sb, int sync)
else
es->s_kbytes_written =
cpu_to_le64(EXT4_SB(sb)->s_kbytes_written);
- ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
- &EXT4_SB(sb)->s_freeblocks_counter));
+ ext4_free_blocks_count_set(es,
+ EXT4_C2B(EXT4_SB(sb), percpu_counter_sum_positive(
+ &EXT4_SB(sb)->s_freeclusters_counter)));
es->s_free_inodes_count =
cpu_to_le32(percpu_counter_sum_positive(
&EXT4_SB(sb)->s_freeinodes_counter));
@@ -4562,8 +4563,9 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_type = EXT4_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
- buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) -
- percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter);
+ buf->f_bfree = EXT4_C2B(sbi,
+ percpu_counter_sum_positive(&sbi->s_freeclusters_counter)) -
+ percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter);
buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
if (buf->f_bfree < ext4_r_blocks_count(es))
buf->f_bavail = 0;
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 13/19] ext4: convert the free_blocks field in s_flex_groups to be free_clusters
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (11 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 12/19] ext4: convert s_freeblocks_counter to s_freeclusters_counter Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 14/19] ext4: teach ext4_statfs() to deal with clusters if bigalloc is enabled Theodore Ts'o
` (6 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
Convert the free_blocks to be free_clusters to make the final revised
bigalloc changes easier to read/understand.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/balloc.c | 4 ++--
fs/ext4/ext4.h | 2 +-
fs/ext4/ialloc.c | 40 +++++++++++++++++++++-------------------
fs/ext4/mballoc.c | 5 +++--
fs/ext4/resize.c | 4 ++--
fs/ext4/super.c | 2 +-
6 files changed, 30 insertions(+), 27 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index c0b74ca..7779c7b 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -500,8 +500,8 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
- atomic_add(blocks_freed,
- &sbi->s_flex_groups[flex_group].free_blocks);
+ atomic_add(EXT4_B2C(sbi, blocks_freed),
+ &sbi->s_flex_groups[flex_group].free_clusters);
}
/*
* request to reload the buddy with the
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 35441b3..57e7255 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -297,7 +297,7 @@ struct ext4_group_desc
struct flex_groups {
atomic_t free_inodes;
- atomic_t free_blocks;
+ atomic_t free_clusters;
atomic_t used_dirs;
};
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index d95a157..c93255d 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -346,7 +346,7 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
int flex_size = ext4_flex_bg_size(sbi);
ext4_group_t best_flex = parent_fbg_group;
int blocks_per_flex = sbi->s_blocks_per_group * flex_size;
- int flexbg_free_blocks;
+ int flexbg_free_clusters;
int flex_freeb_ratio;
ext4_group_t n_fbg_groups;
ext4_group_t i;
@@ -355,8 +355,9 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
sbi->s_log_groups_per_flex;
find_close_to_parent:
- flexbg_free_blocks = atomic_read(&flex_group[best_flex].free_blocks);
- flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
+ flexbg_free_clusters = atomic_read(&flex_group[best_flex].free_clusters);
+ flex_freeb_ratio = EXT4_C2B(sbi, flexbg_free_clusters) * 100 /
+ blocks_per_flex;
if (atomic_read(&flex_group[best_flex].free_inodes) &&
flex_freeb_ratio > free_block_ratio)
goto found_flexbg;
@@ -370,8 +371,9 @@ find_close_to_parent:
if (i == parent_fbg_group || i == parent_fbg_group - 1)
continue;
- flexbg_free_blocks = atomic_read(&flex_group[i].free_blocks);
- flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
+ flexbg_free_clusters = atomic_read(&flex_group[i].free_clusters);
+ flex_freeb_ratio = EXT4_C2B(sbi, flexbg_free_clusters) * 100 /
+ blocks_per_flex;
if (flex_freeb_ratio > free_block_ratio &&
(atomic_read(&flex_group[i].free_inodes))) {
@@ -380,14 +382,14 @@ find_close_to_parent:
}
if ((atomic_read(&flex_group[best_flex].free_inodes) == 0) ||
- ((atomic_read(&flex_group[i].free_blocks) >
- atomic_read(&flex_group[best_flex].free_blocks)) &&
+ ((atomic_read(&flex_group[i].free_clusters) >
+ atomic_read(&flex_group[best_flex].free_clusters)) &&
atomic_read(&flex_group[i].free_inodes)))
best_flex = i;
}
if (!atomic_read(&flex_group[best_flex].free_inodes) ||
- !atomic_read(&flex_group[best_flex].free_blocks))
+ !atomic_read(&flex_group[best_flex].free_clusters))
return -1;
found_flexbg:
@@ -407,7 +409,7 @@ out:
struct orlov_stats {
__u32 free_inodes;
- __u32 free_blocks;
+ __u32 free_clusters;
__u32 used_dirs;
};
@@ -424,7 +426,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
if (flex_size > 1) {
stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
- stats->free_blocks = atomic_read(&flex_group[g].free_blocks);
+ stats->free_clusters = atomic_read(&flex_group[g].free_clusters);
stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
return;
}
@@ -432,11 +434,11 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
desc = ext4_get_group_desc(sb, g, NULL);
if (desc) {
stats->free_inodes = ext4_free_inodes_count(sb, desc);
- stats->free_blocks = ext4_free_blks_count(sb, desc);
+ stats->free_clusters = ext4_free_blks_count(sb, desc);
stats->used_dirs = ext4_used_dirs_count(sb, desc);
} else {
stats->free_inodes = 0;
- stats->free_blocks = 0;
+ stats->free_clusters = 0;
stats->used_dirs = 0;
}
}
@@ -471,10 +473,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
ext4_group_t real_ngroups = ext4_get_groups_count(sb);
int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
unsigned int freei, avefreei;
- ext4_fsblk_t freeb, avefreeb;
+ ext4_fsblk_t freeb, avefreec;
unsigned int ndirs;
int max_dirs, min_inodes;
- ext4_grpblk_t min_blocks;
+ ext4_grpblk_t min_clusters;
ext4_group_t i, grp, g, ngroups;
struct ext4_group_desc *desc;
struct orlov_stats stats;
@@ -492,8 +494,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
avefreei = freei / ngroups;
freeb = EXT4_C2B(sbi,
percpu_counter_read_positive(&sbi->s_freeclusters_counter));
- avefreeb = freeb;
- do_div(avefreeb, ngroups);
+ avefreec = freeb;
+ do_div(avefreec, ngroups);
ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
if (S_ISDIR(mode) &&
@@ -519,7 +521,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
continue;
if (stats.free_inodes < avefreei)
continue;
- if (stats.free_blocks < avefreeb)
+ if (stats.free_clusters < avefreec)
continue;
grp = g;
ret = 0;
@@ -557,7 +559,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
min_inodes = avefreei - inodes_per_group*flex_size / 4;
if (min_inodes < 1)
min_inodes = 1;
- min_blocks = avefreeb - EXT4_BLOCKS_PER_GROUP(sb)*flex_size / 4;
+ min_clusters = avefreec - EXT4_CLUSTERS_PER_GROUP(sb)*flex_size / 4;
/*
* Start looking in the flex group where we last allocated an
@@ -576,7 +578,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
continue;
if (stats.free_inodes < min_inodes)
continue;
- if (stats.free_blocks < min_blocks)
+ if (stats.free_clusters < min_clusters)
continue;
goto found_flex_bg;
}
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 7a9cbe1..a7af56c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2876,7 +2876,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
ext4_group_t flex_group = ext4_flex_group(sbi,
ac->ac_b_ex.fe_group);
atomic_sub(ac->ac_b_ex.fe_len,
- &sbi->s_flex_groups[flex_group].free_blocks);
+ &sbi->s_flex_groups[flex_group].free_clusters);
}
err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
@@ -4716,7 +4716,8 @@ do_more:
if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
- atomic_add(count, &sbi->s_flex_groups[flex_group].free_blocks);
+ atomic_add(count_clusters,
+ &sbi->s_flex_groups[flex_group].free_clusters);
}
ext4_mb_unload_buddy(&e4b);
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 405c1cb..cef49d3 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -928,8 +928,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
sbi->s_log_groups_per_flex) {
ext4_group_t flex_group;
flex_group = ext4_flex_group(sbi, input->group);
- atomic_add(input->free_blocks_count,
- &sbi->s_flex_groups[flex_group].free_blocks);
+ atomic_add(EXT4_B2C(sbi, input->free_blocks_count),
+ &sbi->s_flex_groups[flex_group].free_clusters);
atomic_add(EXT4_INODES_PER_GROUP(sb),
&sbi->s_flex_groups[flex_group].free_inodes);
}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 6b4a3f4..002511e 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1993,7 +1993,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
atomic_add(ext4_free_inodes_count(sb, gdp),
&sbi->s_flex_groups[flex_group].free_inodes);
atomic_add(ext4_free_blks_count(sb, gdp),
- &sbi->s_flex_groups[flex_group].free_blocks);
+ &sbi->s_flex_groups[flex_group].free_clusters);
atomic_add(ext4_used_dirs_count(sb, gdp),
&sbi->s_flex_groups[flex_group].used_dirs);
}
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 14/19] ext4: teach ext4_statfs() to deal with clusters if bigalloc is enabled
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (12 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 13/19] ext4: convert the free_blocks field in s_flex_groups to be free_clusters Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 15/19] ext4: tune mballoc's default group prealloc size for bigalloc file systems Theodore Ts'o
` (5 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/super.c | 37 ++++++++++++++++++++++++-------------
1 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 002511e..e5a2e52 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4514,15 +4514,33 @@ restore_opts:
return err;
}
+/*
+ * Note: calculating the overhead so we can be compatible with
+ * historical BSD practice is quite difficult in the face of
+ * clusters/bigalloc. This is because multiple metadata blocks from
+ * different block group can end up in the same allocation cluster.
+ * Calculating the exact overhead in the face of clustered allocation
+ * requires either O(all block bitmaps) in memory or O(number of block
+ * groups**2) in time. We will still calculate the superblock for
+ * older file systems --- and if we come across with a bigalloc file
+ * system with zero in s_overhead_clusters the estimate will be close to
+ * correct especially for very large cluster sizes --- but for newer
+ * file systems, it's better to calculate this figure once at mkfs
+ * time, and store it in the superblock. If the superblock value is
+ * present (even for non-bigalloc file systems), we will use it.
+ */
static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct super_block *sb = dentry->d_sb;
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_super_block *es = sbi->s_es;
+ struct ext4_group_desc *gdp;
u64 fsid;
if (test_opt(sb, MINIX_DF)) {
sbi->s_overhead_last = 0;
+ } else if (es->s_overhead_clusters) {
+ sbi->s_overhead_last = le32_to_cpu(es->s_overhead_clusters);
} else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
ext4_group_t i, ngroups = ext4_get_groups_count(sb);
ext4_fsblk_t overhead = 0;
@@ -4537,24 +4555,16 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
* All of the blocks before first_data_block are
* overhead
*/
- overhead = le32_to_cpu(es->s_first_data_block);
+ overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block));
/*
- * Add the overhead attributed to the superblock and
- * block group descriptors. If the sparse superblocks
- * feature is turned on, then not all groups have this.
+ * Add the overhead found in each block group
*/
for (i = 0; i < ngroups; i++) {
- overhead += ext4_bg_has_super(sb, i) +
- ext4_bg_num_gdb(sb, i);
+ gdp = ext4_get_group_desc(sb, i, NULL);
+ overhead += ext4_num_overhead_clusters(sb, i, gdp);
cond_resched();
}
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 15/19] ext4: tune mballoc's default group prealloc size for bigalloc file systems
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (13 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 14/19] ext4: teach ext4_statfs() to deal with clusters if bigalloc is enabled Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 16/19] ext4: enable mounting bigalloc as read/write Theodore Ts'o
` (4 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
The default group preallocation size had been previously set to 512
blocks/clusters, regardless of the block/cluster size. This is
probably too big for large cluster sizes. So adjust the default so
that it is 2 megabytes or 32 clusters, whichever is larger.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/mballoc.c | 18 ++++++++++++++++--
1 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index a7af56c..4f8494d 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -126,7 +126,8 @@
* list. In case of inode preallocation we follow a list of heuristics
* based on file size. This can be found in ext4_mb_normalize_request. If
* we are doing a group prealloc we try to normalize the request to
- * sbi->s_mb_group_prealloc. Default value of s_mb_group_prealloc is
+ * sbi->s_mb_group_prealloc. The default value of s_mb_group_prealloc is
+ * dependent on the cluster size; for non-bigalloc file systems, it is
* 512 blocks. This can be tuned via
* /sys/fs/ext4/<partition/mb_group_prealloc. The value is represented in
* terms of number of blocks. If we have mounted the file system with -O
@@ -2531,7 +2532,20 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
sbi->s_mb_stats = MB_DEFAULT_STATS;
sbi->s_mb_stream_request = MB_DEFAULT_STREAM_THRESHOLD;
sbi->s_mb_order2_reqs = MB_DEFAULT_ORDER2_REQS;
- sbi->s_mb_group_prealloc = MB_DEFAULT_GROUP_PREALLOC;
+ /*
+ * The default group preallocation is 512, which for 4k block
+ * sizes translates to 2 megabytes. However for bigalloc file
+ * systems, this is probably too big (i.e, if the cluster size
+ * is 1 megabyte, then group preallocation size becomes half a
+ * gigabyte!). As a default, we will keep a two megabyte
+ * group pralloc size for cluster sizes up to 64k, and after
+ * that, we will force a minimum group preallocation size of
+ * 32 clusters. This translates to 8 megs when the cluster
+ * size is 256k, and 32 megs when the cluster size is 1 meg,
+ * which seems reasonable as a default.
+ */
+ sbi->s_mb_group_prealloc = max(MB_DEFAULT_GROUP_PREALLOC >>
+ sbi->s_cluster_bits, 32);
sbi->s_locality_groups = alloc_percpu(struct ext4_locality_group);
if (sbi->s_locality_groups == NULL) {
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 16/19] ext4: enable mounting bigalloc as read/write
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (14 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 15/19] ext4: tune mballoc's default group prealloc size for bigalloc file systems Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 17/19] ext4: Rename ext4_free_blks_{count,set}() to refer to clusters Theodore Ts'o
` (3 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
Now that we have implemented all of the changes needed for bigalloc,
we can finally enable it!
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/ext4.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 57e7255..c7d3eea 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1401,7 +1401,8 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
- EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+ EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC)
/*
* Default values for user and/or group using reserved blocks
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 17/19] ext4: Rename ext4_free_blks_{count,set}() to refer to clusters
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (15 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 16/19] ext4: enable mounting bigalloc as read/write Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 18/19] ext4: rename ext4_count_free_blocks() to ext4_count_free_clusters() Theodore Ts'o
` (2 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
The field bg_free_free_blocks_count_{lo,high} in the block group
descriptor has been repurposed to hold the number of free clusters for
bigalloc functions. So rename the functions so it makes it easier to
read and audit the block allocation and block freeing code.
Note: at this point in bigalloc development we doesn't support
online-resize, so this also makes it really obvious all of the places
we need to fix up to add support for online resize.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/balloc.c | 12 ++++++------
fs/ext4/ext4.h | 9 +++++----
fs/ext4/ialloc.c | 14 +++++++-------
fs/ext4/mballoc.c | 18 +++++++++---------
fs/ext4/resize.c | 2 +-
fs/ext4/super.c | 10 +++++-----
6 files changed, 33 insertions(+), 32 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 7779c7b..171dd6a 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -168,7 +168,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
* essentially implementing a per-group read-only flag. */
if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
ext4_error(sb, "Checksum bad for group %u", block_group);
- ext4_free_blks_set(sb, gdp, 0);
+ ext4_free_group_clusters_set(sb, gdp, 0);
ext4_free_inodes_set(sb, gdp, 0);
ext4_itable_unused_set(sb, gdp, 0);
memset(bh->b_data, 0xff, sb->s_blocksize);
@@ -491,8 +491,8 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
}
}
ext4_lock_group(sb, block_group);
- blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc);
- ext4_free_blks_set(sb, desc, blk_free_count);
+ blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc);
+ ext4_free_group_clusters_set(sb, desc, blk_free_count);
desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
ext4_unlock_group(sb, block_group);
percpu_counter_add(&sbi->s_freeclusters_counter,
@@ -669,7 +669,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
gdp = ext4_get_group_desc(sb, i, NULL);
if (!gdp)
continue;
- desc_count += ext4_free_blks_count(sb, gdp);
+ desc_count += ext4_free_group_clusters(sb, gdp);
brelse(bitmap_bh);
bitmap_bh = ext4_read_block_bitmap(sb, i);
if (bitmap_bh == NULL)
@@ -677,7 +677,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
x = ext4_count_free(bitmap_bh, sb->s_blocksize);
printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
- i, ext4_free_blks_count(sb, gdp), x);
+ i, ext4_free_group_clusters(sb, gdp), x);
bitmap_count += x;
}
brelse(bitmap_bh);
@@ -691,7 +691,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
gdp = ext4_get_group_desc(sb, i, NULL);
if (!gdp)
continue;
- desc_count += ext4_free_blks_count(sb, gdp);
+ desc_count += ext4_free_group_clusters(sb, gdp);
}
return desc_count;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index c7d3eea..cd2ba30 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1852,8 +1852,8 @@ extern ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
struct ext4_group_desc *bg);
extern ext4_fsblk_t ext4_inode_table(struct super_block *sb,
struct ext4_group_desc *bg);
-extern __u32 ext4_free_blks_count(struct super_block *sb,
- struct ext4_group_desc *bg);
+extern __u32 ext4_free_group_clusters(struct super_block *sb,
+ struct ext4_group_desc *bg);
extern __u32 ext4_free_inodes_count(struct super_block *sb,
struct ext4_group_desc *bg);
extern __u32 ext4_used_dirs_count(struct super_block *sb,
@@ -1866,8 +1866,9 @@ extern void ext4_inode_bitmap_set(struct super_block *sb,
struct ext4_group_desc *bg, ext4_fsblk_t blk);
extern void ext4_inode_table_set(struct super_block *sb,
struct ext4_group_desc *bg, ext4_fsblk_t blk);
-extern void ext4_free_blks_set(struct super_block *sb,
- struct ext4_group_desc *bg, __u32 count);
+extern void ext4_free_group_clusters_set(struct super_block *sb,
+ struct ext4_group_desc *bg,
+ __u32 count);
extern void ext4_free_inodes_set(struct super_block *sb,
struct ext4_group_desc *bg, __u32 count);
extern void ext4_used_dirs_set(struct super_block *sb,
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index c93255d..afe7c50 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -78,7 +78,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
* allocation, essentially implementing a per-group read-only flag. */
if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
ext4_error(sb, "Checksum bad for group %u", block_group);
- ext4_free_blks_set(sb, gdp, 0);
+ ext4_free_group_clusters_set(sb, gdp, 0);
ext4_free_inodes_set(sb, gdp, 0);
ext4_itable_unused_set(sb, gdp, 0);
memset(bh->b_data, 0xff, sb->s_blocksize);
@@ -322,8 +322,8 @@ static int find_group_dir(struct super_block *sb, struct inode *parent,
if (ext4_free_inodes_count(sb, desc) < avefreei)
continue;
if (!best_desc ||
- (ext4_free_blks_count(sb, desc) >
- ext4_free_blks_count(sb, best_desc))) {
+ (ext4_free_group_clusters(sb, desc) >
+ ext4_free_group_clusters(sb, best_desc))) {
*best_group = group;
best_desc = desc;
ret = 0;
@@ -434,7 +434,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
desc = ext4_get_group_desc(sb, g, NULL);
if (desc) {
stats->free_inodes = ext4_free_inodes_count(sb, desc);
- stats->free_clusters = ext4_free_blks_count(sb, desc);
+ stats->free_clusters = ext4_free_group_clusters(sb, desc);
stats->used_dirs = ext4_used_dirs_count(sb, desc);
} else {
stats->free_inodes = 0;
@@ -662,7 +662,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
*group = parent_group;
desc = ext4_get_group_desc(sb, *group, NULL);
if (desc && ext4_free_inodes_count(sb, desc) &&
- ext4_free_blks_count(sb, desc))
+ ext4_free_group_clusters(sb, desc))
return 0;
/*
@@ -686,7 +686,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
*group -= ngroups;
desc = ext4_get_group_desc(sb, *group, NULL);
if (desc && ext4_free_inodes_count(sb, desc) &&
- ext4_free_blks_count(sb, desc))
+ ext4_free_group_clusters(sb, desc))
return 0;
}
@@ -959,7 +959,7 @@ got:
/* recheck and clear flag under lock if we still need to */
if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
- ext4_free_blks_set(sb, gdp,
+ ext4_free_group_clusters_set(sb, gdp,
ext4_free_blocks_after_init(sb, group, gdp));
gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
gdp);
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 4f8494d..3b0d87c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2314,7 +2314,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
ext4_free_blocks_after_init(sb, group, desc);
} else {
meta_group_info[i]->bb_free =
- ext4_free_blks_count(sb, desc);
+ ext4_free_group_clusters(sb, desc);
}
INIT_LIST_HEAD(&meta_group_info[i]->bb_prealloc_list);
@@ -2830,7 +2830,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
goto out_err;
ext4_debug("using block group %u(%d)\n", ac->ac_b_ex.fe_group,
- ext4_free_blks_count(sb, gdp));
+ ext4_free_group_clusters(sb, gdp));
err = ext4_journal_get_write_access(handle, gdp_bh);
if (err)
@@ -2869,12 +2869,12 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
mb_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,ac->ac_b_ex.fe_len);
if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
- ext4_free_blks_set(sb, gdp,
- ext4_free_blocks_after_init(sb,
- ac->ac_b_ex.fe_group, gdp));
+ ext4_free_group_clusters_set(sb, gdp,
+ ext4_free_blocks_after_init(sb,
+ ac->ac_b_ex.fe_group, gdp));
}
- len = ext4_free_blks_count(sb, gdp) - ac->ac_b_ex.fe_len;
- ext4_free_blks_set(sb, gdp, len);
+ len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len;
+ ext4_free_group_clusters_set(sb, gdp, len);
gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
@@ -4722,8 +4722,8 @@ do_more:
mb_free_blocks(inode, &e4b, bit, count_clusters);
}
- ret = ext4_free_blks_count(sb, gdp) + count_clusters;
- ext4_free_blks_set(sb, gdp, ret);
+ ret = ext4_free_group_clusters(sb, gdp) + count_clusters;
+ ext4_free_group_clusters_set(sb, gdp, ret);
gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
ext4_unlock_group(sb, block_group);
percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index cef49d3..14b66ba 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -853,7 +853,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
ext4_block_bitmap_set(sb, gdp, input->block_bitmap); /* LV FIXME */
ext4_inode_bitmap_set(sb, gdp, input->inode_bitmap); /* LV FIXME */
ext4_inode_table_set(sb, gdp, input->inode_table); /* LV FIXME */
- ext4_free_blks_set(sb, gdp, input->free_blocks_count);
+ ext4_free_group_clusters_set(sb, gdp, input->free_blocks_count);
ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb));
gdp->bg_flags = cpu_to_le16(EXT4_BG_INODE_ZEROED);
gdp->bg_checksum = ext4_group_desc_csum(sbi, input->group, gdp);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index e5a2e52..30b7c81 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -133,8 +133,8 @@ ext4_fsblk_t ext4_inode_table(struct super_block *sb,
(ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
}
-__u32 ext4_free_blks_count(struct super_block *sb,
- struct ext4_group_desc *bg)
+__u32 ext4_free_group_clusters(struct super_block *sb,
+ struct ext4_group_desc *bg)
{
return le16_to_cpu(bg->bg_free_blocks_count_lo) |
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
@@ -189,8 +189,8 @@ void ext4_inode_table_set(struct super_block *sb,
bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
}
-void ext4_free_blks_set(struct super_block *sb,
- struct ext4_group_desc *bg, __u32 count)
+void ext4_free_group_clusters_set(struct super_block *sb,
+ struct ext4_group_desc *bg, __u32 count)
{
bg->bg_free_blocks_count_lo = cpu_to_le16((__u16)count);
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
@@ -1992,7 +1992,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
flex_group = ext4_flex_group(sbi, i);
atomic_add(ext4_free_inodes_count(sb, gdp),
&sbi->s_flex_groups[flex_group].free_inodes);
- atomic_add(ext4_free_blks_count(sb, gdp),
+ atomic_add(ext4_free_group_clusters(sb, gdp),
&sbi->s_flex_groups[flex_group].free_clusters);
atomic_add(ext4_used_dirs_count(sb, gdp),
&sbi->s_flex_groups[flex_group].used_dirs);
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 18/19] ext4: rename ext4_count_free_blocks() to ext4_count_free_clusters()
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (16 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 17/19] ext4: Rename ext4_free_blks_{count,set}() to refer to clusters Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [PATCH 19/19] ext4: rename ext4_free_blocks_after_init() to ext4_free_clusters_after_init() Theodore Ts'o
2011-05-03 22:24 ` [E2FSPROGS PATCH] Interim patches for e2fsprogs Theodore Ts'o
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
This function really counts the free clusters reported in the block
group descriptors, so rename it to reduce confusion.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/balloc.c | 11 ++++++-----
fs/ext4/ext4.h | 2 +-
fs/ext4/inode.c | 6 +++---
fs/ext4/super.c | 7 ++++---
4 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 171dd6a..253f80e 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -643,12 +643,12 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
}
/**
- * ext4_count_free_blocks() -- count filesystem free blocks
+ * ext4_count_free_clusters() -- count filesystem free clusters
* @sb: superblock
*
- * Adds up the number of free blocks from each block group.
+ * Adds up the number of free clusters from each block group.
*/
-ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
{
ext4_fsblk_t desc_count;
struct ext4_group_desc *gdp;
@@ -681,8 +681,9 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
bitmap_count += x;
}
brelse(bitmap_bh);
- printk(KERN_DEBUG "ext4_count_free_blocks: stored = %llu"
- ", computed = %llu, %llu\n", ext4_free_blocks_count(es),
+ printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu"
+ ", computed = %llu, %llu\n",
+ EXT4_B2C(sbi, ext4_free_blocks_count(es)),
desc_count, bitmap_count);
return bitmap_count;
#else
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index cd2ba30..f8c51bb 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1680,7 +1680,7 @@ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
extern void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
ext4_fsblk_t block, unsigned long count);
-extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *);
+extern ext4_fsblk_t ext4_count_free_clusters(struct super_block *);
extern void ext4_check_blocks_bitmap(struct super_block *);
extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
ext4_group_t block_group,
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index cc5910d..86edc01 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2208,7 +2208,8 @@ static void ext4_print_free_blocks(struct inode *inode)
{
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
printk(KERN_CRIT "Total free blocks count %lld\n",
- ext4_count_free_blocks(inode->i_sb));
+ EXT4_C2B(EXT4_SB(inode->i_sb),
+ ext4_count_free_clusters(inode->i_sb)));
printk(KERN_CRIT "Free/Dirty block details\n");
printk(KERN_CRIT "free_blocks=%lld\n",
(long long) EXT4_C2B(EXT4_SB(inode->i_sb),
@@ -2293,8 +2294,7 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
if (err == -EAGAIN)
goto submit_io;
- if (err == -ENOSPC &&
- ext4_count_free_blocks(sb)) {
+ if (err == -ENOSPC && ext4_count_free_clusters(sb)) {
mpd->retval = err;
goto submit_io;
}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 30b7c81..3ad6b3c 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2111,7 +2111,8 @@ static int ext4_check_descriptors(struct super_block *sb,
if (NULL != first_not_zeroed)
*first_not_zeroed = grp;
- ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
+ ext4_free_blocks_count_set(sbi->s_es,
+ EXT4_C2B(sbi, ext4_count_free_clusters(sb)));
sbi->s_es->s_free_inodes_count =cpu_to_le32(ext4_count_free_inodes(sb));
return 1;
}
@@ -3500,7 +3501,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_err_report.data = (unsigned long) sb;
err = percpu_counter_init(&sbi->s_freeclusters_counter,
- ext4_count_free_blocks(sb));
+ ext4_count_free_clusters(sb));
if (!err) {
err = percpu_counter_init(&sbi->s_freeinodes_counter,
ext4_count_free_inodes(sb));
@@ -3622,7 +3623,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
* need to update the global counters.
*/
percpu_counter_set(&sbi->s_freeclusters_counter,
- ext4_count_free_blocks(sb));
+ ext4_count_free_clusters(sb));
percpu_counter_set(&sbi->s_freeinodes_counter,
ext4_count_free_inodes(sb));
percpu_counter_set(&sbi->s_dirs_counter,
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 19/19] ext4: rename ext4_free_blocks_after_init() to ext4_free_clusters_after_init()
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (17 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 18/19] ext4: rename ext4_count_free_blocks() to ext4_count_free_clusters() Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
2011-05-03 22:24 ` [E2FSPROGS PATCH] Interim patches for e2fsprogs Theodore Ts'o
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
This function really returns the number of clusters after initializing
an uninitalized block bitmap has been initialized.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/balloc.c | 6 +++---
fs/ext4/ext4.h | 6 +++---
fs/ext4/ialloc.c | 2 +-
fs/ext4/mballoc.c | 4 ++--
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 253f80e..17e5af7 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -213,9 +213,9 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
/* Return the number of free blocks in a block group. It is used when
* the block bitmap is uninitialized, so we can't just count the bits
* in the bitmap. */
-unsigned ext4_free_blocks_after_init(struct super_block *sb,
- ext4_group_t block_group,
- struct ext4_group_desc *gdp)
+unsigned ext4_free_clusters_after_init(struct super_block *sb,
+ ext4_group_t block_group,
+ struct ext4_group_desc *gdp)
{
return num_clusters_in_group(sb, block_group) -
ext4_num_overhead_clusters(sb, block_group, gdp);
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f8c51bb..b376aea 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1692,9 +1692,9 @@ extern void ext4_init_block_bitmap(struct super_block *sb,
struct buffer_head *bh,
ext4_group_t group,
struct ext4_group_desc *desc);
-extern unsigned ext4_free_blocks_after_init(struct super_block *sb,
- ext4_group_t block_group,
- struct ext4_group_desc *gdp);
+extern unsigned ext4_free_clusters_after_init(struct super_block *sb,
+ ext4_group_t block_group,
+ struct ext4_group_desc *gdp);
extern unsigned ext4_num_base_meta_clusters(struct super_block *sb,
ext4_group_t block_group);
extern unsigned ext4_num_overhead_clusters(struct super_block *sb,
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index afe7c50..e0c2035 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -960,7 +960,7 @@ got:
if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
ext4_free_group_clusters_set(sb, gdp,
- ext4_free_blocks_after_init(sb, group, gdp));
+ ext4_free_clusters_after_init(sb, group, gdp));
gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
gdp);
}
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 3b0d87c..89b5096 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2311,7 +2311,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
*/
if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
meta_group_info[i]->bb_free =
- ext4_free_blocks_after_init(sb, group, desc);
+ ext4_free_clusters_after_init(sb, group, desc);
} else {
meta_group_info[i]->bb_free =
ext4_free_group_clusters(sb, desc);
@@ -2870,7 +2870,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
ext4_free_group_clusters_set(sb, gdp,
- ext4_free_blocks_after_init(sb,
+ ext4_free_clusters_after_init(sb,
ac->ac_b_ex.fe_group, gdp));
}
len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len;
--
1.7.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [E2FSPROGS PATCH] Interim patches for e2fsprogs
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
` (18 preceding siblings ...)
2011-05-03 22:24 ` [PATCH 19/19] ext4: rename ext4_free_blocks_after_init() to ext4_free_clusters_after_init() Theodore Ts'o
@ 2011-05-03 22:24 ` Theodore Ts'o
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Ts'o @ 2011-05-03 22:24 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
These are patches that allow mke2fs, dumpe2fs, and debugfs to work
with bigalloc file systems. E2fsck will blindly accept bigalloc file
systems, and return success so long as the kernel hasn't marked the
file system as containing errors (this was so I could test the kernel
patches with xfstests, relying on ext4's internal sanity checks to
detect file system corruption problems).
NOT-Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index 73cc2cf..fbcc878 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -1316,6 +1316,24 @@ print_unsupp_features:
}
#endif
+ /* HACK HACK HACK */
+ if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC) {
+ if (sb->s_state & EXT2_ERROR_FS) {
+ printf("File system has bigalloc feature and "
+ "kernel found a problem\n"
+ "This version of e2fsck can't fix it. :-(\n\n");
+ exit(FSCK_UNCORRECTED);
+ }
+ printf("File system has bigalloc feature and this version "
+ "of e2fsck doesn't yet\n"
+ "understand bigalloc. Fortunately, it is in "
+ "'Don't Worry, Be Happy' mode\n"
+ "so we can run xfstests.\n\n"
+ "There will be cake. And it will be delicious "
+ "and moist.\n\n");
+ exit(FSCK_OK);
+ }
+
/*
* If the user specified a specific superblock, presumably the
* master superblock has been trashed. So we mark the
diff --git a/lib/ext2fs/bmap64.h b/lib/ext2fs/bmap64.h
index b0aa84c..cfbdfd6 100644
--- a/lib/ext2fs/bmap64.h
+++ b/lib/ext2fs/bmap64.h
@@ -31,6 +31,10 @@ struct ext2fs_struct_generic_bitmap {
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64))
+/* Bitmap flags */
+
+#define EXT2_BMFLAG_CLUSTER 0x0001
+
struct ext2_bitmap_ops {
int type;
/* Generic bmap operators */
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index a89e33b..3557792 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -228,9 +228,13 @@ struct ext2_dx_countlimit {
#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group)
#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group)
+#define EXT2_CLUSTERS_PER_GROUP(s) (EXT2_SB(s)->s_clusters_per_group)
#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */
-#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8)
+#define EXT2_MAX_BLOCKS_PER_GROUP(s) (((1 << 16) - 8) * \
+ (EXT2_CLUSTER_SIZE(s) / \
+ EXT2_BLOCK_SIZE(s)))
+#define EXT2_MAX_CLUSTERS_PER_GROUP(s) ((1 << 16) - 8)
#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s))
#ifdef __KERNEL__
#define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block)
@@ -695,7 +699,8 @@ struct ext2_super_block {
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
- EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+ EXT2_FEATURE_RO_COMPAT_BTREE_DIR| \
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC)
/*
* Default values for user and/or group using reserved blocks
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index d3eb31d..fafb9fe 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -207,7 +207,6 @@ struct struct_ext2_filsys {
char * device_name;
struct ext2_super_block * super;
unsigned int blocksize;
- int clustersize;
dgrp_t group_desc_count;
unsigned long desc_blocks;
struct opaque_ext2_group_desc * group_desc;
@@ -232,7 +231,9 @@ struct struct_ext2_filsys {
/*
* Reserved for future expansion
*/
- __u32 reserved[7];
+ __u32 clustersize;
+ __u32 cluster_bits;
+ __u32 reserved[6];
/*
* Reserved for the use of the calling application.
@@ -553,7 +554,8 @@ typedef struct ext2_icount *ext2_icount_t;
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\
- EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC)
/*
* These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed
@@ -562,6 +564,17 @@ typedef struct ext2_icount *ext2_icount_t;
#define EXT2_LIB_SOFTSUPP_INCOMPAT (0)
#define EXT2_LIB_SOFTSUPP_RO_COMPAT (EXT4_FEATURE_RO_COMPAT_BIGALLOC)
+
+/* Translate a block number to a cluster number */
+#define EXT2FS_CLUSTER_RATIO(fs) (1 << (fs)->cluster_bits)
+#define EXT2FS_CLUSTER_MASK(fs) (EXT2FS_CLUSTER_RATIO(fs) - 1)
+#define EXT2FS_B2C(fs, blk) ((blk) >> (fs)->cluster_bits)
+/* Translate a cluster number to a block number */
+#define EXT2FS_C2B(fs, cluster) ((cluster) << (fs)->cluster_bits)
+/* Translate # of blks to # of clusters */
+#define EXT2FS_NUM_B2C(fs, blks) (((blks) + EXT2FS_CLUSTER_MASK(fs)) >> \
+ (fs)->cluster_bits)
+
/*
* function prototypes
*/
diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c
index df095ac..b25ac54 100644
--- a/lib/ext2fs/gen_bitmap64.c
+++ b/lib/ext2fs/gen_bitmap64.c
@@ -34,7 +34,7 @@
*
* In order maintain ABI compatibility with programs that don't
* understand about 64-bit blocks/inodes,
- * ext2fs_allocate_inode_bitmap() and ext2fs_allocate_block_bitmap()
+ * ext2fs_allocate_inode_bitmap() and ext2fs_allocate_block_bitmap()
* will create old-style bitmaps unless the application passes the
* flag EXT2_FLAG_64BITS to ext2fs_open(). If this flag is
* passed, then we know the application has been recompiled, so we can
@@ -559,3 +559,85 @@ int ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func)
"called %s with 64-bit bitmap", func);
#endif
}
+
+errcode_t ext2fs_allocate_cluster_bitmap(ext2_filsys fs,
+ const char *descr,
+ ext2fs_block_bitmap *ret)
+{
+ __u64 start, end, real_end;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!(fs->flags & EXT2_FLAG_64BITS))
+ return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
+
+ fs->write_bitmaps = ext2fs_write_bitmaps;
+
+ start = (fs->super->s_first_data_block >>
+ EXT2_CLUSTER_SIZE_BITS(fs->super));
+ end = EXT2FS_NUM_B2C(fs, ext2fs_blocks_count(fs->super)) - 1;
+ real_end = ((__u64) EXT2_CLUSTERS_PER_GROUP(fs->super)
+ * (__u64) fs->group_desc_count)-1 + start;
+
+ retval = ext2fs_alloc_generic_bmap(fs,
+ EXT2_ET_MAGIC_BLOCK_BITMAP64,
+ EXT2FS_BMAP64_BITARRAY,
+ start, end, real_end, descr, ret);
+ if (retval)
+ return retval;
+
+ (*ret)->flags = EXT2_BMFLAG_CLUSTER;
+
+ printf("Returning 0...\n");
+ return 0;
+}
+
+int ext2fs_is_cluster_bitmap(ext2fs_block_bitmap bm)
+{
+ if (EXT2FS_IS_32_BITMAP(bm))
+ return 0;
+
+ return (bm->flags & EXT2_BMFLAG_CLUSTER);
+}
+
+errcode_t ext2fs_convert_to_cluster_bitmap(ext2_filsys fs,
+ ext2fs_block_bitmap bmap,
+ ext2fs_block_bitmap *ret)
+{
+ ext2fs_block_bitmap cmap;
+ errcode_t retval;
+ blk64_t i, j, b_end, c_end;
+ int n;
+
+ retval = ext2fs_allocate_cluster_bitmap(fs, "converted cluster bitmap",
+ ret);
+ if (retval)
+ return retval;
+
+ cmap = *ret;
+ i = bmap->start;
+ b_end = bmap->end;
+ bmap->end = bmap->real_end;
+ j = cmap->start;
+ c_end = cmap->end;
+ cmap->end = cmap->real_end;
+ n = 0;
+ while (i < bmap->real_end) {
+ if (ext2fs_test_block_bitmap2(bmap, i)) {
+ ext2fs_mark_block_bitmap2(cmap, j);
+ i += EXT2FS_CLUSTER_RATIO(fs) - n;
+ j++;
+ n = 0;
+ continue;
+ }
+ i++; n++;
+ if (n >= EXT2FS_CLUSTER_RATIO(fs)) {
+ j++;
+ n = 0;
+ }
+ }
+ bmap->end = b_end;
+ cmap->end = c_end;
+ return 0;
+}
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index e1f229b..4200f86 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -94,6 +94,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
blk_t numblocks;
int rsv_gdt;
int csum_flag;
+ int bigalloc_flag;
int io_flags;
char *buf = 0;
char c;
@@ -134,12 +135,25 @@ errcode_t ext2fs_initialize(const char *name, int flags,
#define set_field(field, default) (super->field = param->field ? \
param->field : (default))
+#define assign_field(field) (super->field = param->field)
super->s_magic = EXT2_SUPER_MAGIC;
super->s_state = EXT2_VALID_FS;
- set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */
- set_field(s_log_cluster_size, 0);
+ bigalloc_flag = EXT2_HAS_RO_COMPAT_FEATURE(param,
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC);
+
+ assign_field(s_log_block_size);
+
+ if (bigalloc_flag) {
+ set_field(s_log_cluster_size, super->s_log_block_size+4);
+ if (super->s_log_block_size > super->s_log_cluster_size) {
+ retval = EXT2_ET_INVALID_ARGUMENT;
+ goto cleanup;
+ }
+ } else
+ super->s_log_cluster_size = super->s_log_block_size;
+
set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
set_field(s_max_mnt_count, 0);
set_field(s_errors, EXT2_ERRORS_DEFAULT);
@@ -183,14 +197,37 @@ errcode_t ext2fs_initialize(const char *name, int flags,
fs->blocksize = EXT2_BLOCK_SIZE(super);
fs->clustersize = EXT2_CLUSTER_SIZE(super);
+ fs->cluster_bits = super->s_log_cluster_size - super->s_log_block_size;
+
+ if (bigalloc_flag) {
+ if (param->s_blocks_per_group &&
+ param->s_clusters_per_group &&
+ ((param->s_clusters_per_group * EXT2FS_CLUSTER_RATIO(fs)) !=
+ param->s_blocks_per_group)) {
+ retval = EXT2_ET_INVALID_ARGUMENT;
+ goto cleanup;
+ }
+ if (param->s_clusters_per_group)
+ assign_field(s_clusters_per_group);
+ else if (param->s_blocks_per_group)
+ super->s_clusters_per_group =
+ param->s_blocks_per_group /
+ EXT2FS_CLUSTER_RATIO(fs);
+ else
+ super->s_clusters_per_group = fs->blocksize * 8;
+ if (super->s_clusters_per_group > EXT2_MAX_CLUSTERS_PER_GROUP(super))
+ super->s_blocks_per_group = EXT2_MAX_CLUSTERS_PER_GROUP(super);
+ super->s_blocks_per_group = EXT2FS_C2B(fs,
+ super->s_clusters_per_group);
+ } else {
+ set_field(s_blocks_per_group, fs->blocksize * 8);
+ if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
+ super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
+ super->s_clusters_per_group = super->s_blocks_per_group;
+ }
- /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */
- set_field(s_blocks_per_group, fs->blocksize * 8);
- if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
- super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
- super->s_clusters_per_group = super->s_blocks_per_group;
-
- ext2fs_blocks_count_set(super, ext2fs_blocks_count(param));
+ ext2fs_blocks_count_set(super, ext2fs_blocks_count(param) &
+ ~((blk64_t) EXT2FS_CLUSTER_MASK(fs)));
ext2fs_r_blocks_count_set(super, ext2fs_r_blocks_count(param));
if (ext2fs_r_blocks_count(super) >= ext2fs_blocks_count(param)) {
retval = EXT2_ET_INVALID_ARGUMENT;
@@ -246,7 +283,7 @@ retry:
*/
ipg = ext2fs_div_ceil(super->s_inodes_count, fs->group_desc_count);
if (ipg > fs->blocksize * 8) {
- if (super->s_blocks_per_group >= 256) {
+ if (!bigalloc_flag && super->s_blocks_per_group >= 256) {
/* Try again with slightly different parameters */
super->s_blocks_per_group -= 8;
ext2fs_blocks_count_set(super,
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index 90abed1..106ecf1 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -251,6 +251,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
goto cleanup;
}
fs->clustersize = EXT2_CLUSTER_SIZE(fs->super);
+ fs->cluster_bits = fs->super->s_log_cluster_size -
+ fs->super->s_log_block_size;
fs->inode_blocks_per_group = ((EXT2_INODES_PER_GROUP(fs->super) *
EXT2_INODE_SIZE(fs->super) +
EXT2_BLOCK_SIZE(fs->super) - 1) /
diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
index 3031b7d..c579f3a 100644
--- a/lib/ext2fs/rw_bitmaps.c
+++ b/lib/ext2fs/rw_bitmaps.c
@@ -37,7 +37,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
char *block_buf, *inode_buf;
int csum_flag = 0;
blk64_t blk;
- blk64_t blk_itr = fs->super->s_first_data_block;
+ blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
ext2_ino_t ino_itr = 1;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -51,7 +51,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
inode_nbytes = block_nbytes = 0;
if (do_block) {
- block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
retval = ext2fs_get_memalign(fs->blocksize, fs->blocksize,
&block_buf);
if (retval)
@@ -83,9 +83,10 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
if (i == fs->group_desc_count - 1) {
/* Force bitmap padding for the last group */
- nbits = ((ext2fs_blocks_count(fs->super)
- - (__u64) fs->super->s_first_data_block)
- % (__u64) EXT2_BLOCKS_PER_GROUP(fs->super));
+ nbits = EXT2FS_NUM_B2C(fs,
+ (ext2fs_blocks_count(fs->super) -
+ (__u64) fs->super->s_first_data_block)) %
+ (__u64) EXT2_CLUSTERS_PER_GROUP(fs->super);
if (nbits)
for (j = nbits; j < fs->blocksize * 8; j++)
ext2fs_set_bit(j, block_buf);
@@ -141,13 +142,13 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
char *block_bitmap = 0, *inode_bitmap = 0;
char *buf;
errcode_t retval;
- int block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
int csum_flag = 0;
int do_image = fs->flags & EXT2_FLAG_IMAGE_FILE;
unsigned int cnt;
blk64_t blk;
- blk64_t blk_itr = fs->super->s_first_data_block;
+ blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
blk64_t blk_cnt;
ext2_ino_t ino_itr = 1;
ext2_ino_t ino_cnt;
@@ -219,7 +220,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
}
blk = (fs->image_header->offset_blockmap /
fs->blocksize);
- blk_cnt = (blk64_t)EXT2_BLOCKS_PER_GROUP(fs->super) *
+ blk_cnt = (blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) *
fs->group_desc_count;
while (block_nbytes > 0) {
retval = io_channel_read_blk64(fs->image_io, blk++,
diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index c01ffe5..97ce503 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -71,25 +71,26 @@ static void print_range(unsigned long long a, unsigned long long b)
printf("%llu-%llu", a, b);
}
-static void print_free (unsigned long group, char * bitmap,
- unsigned long nbytes, unsigned long offset)
+static void print_free(unsigned long group, char * bitmap,
+ unsigned long nbytes, unsigned long offset, int ratio)
{
int p = 0;
unsigned long i;
unsigned long j;
+ offset /= ratio;
offset += group * nbytes;
for (i = 0; i < nbytes; i++)
if (!in_use (bitmap, i))
{
if (p)
printf (", ");
- print_number(i + offset);
+ print_number((i + offset) * ratio);
for (j = i; j < nbytes && !in_use (bitmap, j); j++)
;
if (--j != i) {
fputc('-', stdout);
- print_number(j + offset);
+ print_number((j + offset) * ratio);
i = j;
}
p = 1;
@@ -153,7 +154,7 @@ static void list_desc (ext2_filsys fs)
blk64_t blk_itr = fs->super->s_first_data_block;
ext2_ino_t ino_itr = 1;
- block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
if (fs->block_map)
@@ -238,18 +239,19 @@ static void list_desc (ext2_filsys fs)
fputs(_(" Free blocks: "), stdout);
ext2fs_get_block_bitmap_range2(fs->block_map,
blk_itr, block_nbytes << 3, block_bitmap);
- print_free (i, block_bitmap,
- fs->super->s_blocks_per_group,
- fs->super->s_first_data_block);
+ print_free(i, block_bitmap,
+ fs->super->s_clusters_per_group,
+ fs->super->s_first_data_block,
+ EXT2FS_CLUSTER_RATIO(fs));
fputc('\n', stdout);
- blk_itr += fs->super->s_blocks_per_group;
+ blk_itr += fs->super->s_clusters_per_group;
}
if (inode_bitmap) {
fputs(_(" Free inodes: "), stdout);
ext2fs_get_inode_bitmap_range2(fs->inode_map,
ino_itr, inode_nbytes << 3, inode_bitmap);
- print_free (i, inode_bitmap,
- fs->super->s_inodes_per_group, 1);
+ print_free(i, inode_bitmap,
+ fs->super->s_inodes_per_group, 1, 1);
fputc('\n', stdout);
ino_itr += fs->super->s_inodes_per_group;
}
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 9798b88..f77c92e 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -815,7 +815,8 @@ static __u32 ok_features[3] = {
EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|
- EXT4_FEATURE_RO_COMPAT_GDT_CSUM
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM|
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC
};
@@ -1252,7 +1253,7 @@ profile_error:
}
while ((c = getopt (argc, argv,
- "b:cf:g:G:i:jl:m:no:qr:s:t:vE:FI:J:KL:M:N:O:R:ST:U:V")) != EOF) {
+ "b:cg:i:jl:m:no:qr:s:t:vC:E:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) {
switch (c) {
case 'b':
blocksize = strtol(optarg, &tmp, 0);
@@ -1275,17 +1276,17 @@ profile_error:
case 'c': /* Check for bad blocks */
cflag++;
break;
- case 'f':
+ case 'C':
size = strtoul(optarg, &tmp, 0);
- if (size < EXT2_MIN_BLOCK_SIZE ||
- size > EXT2_MAX_BLOCK_SIZE || *tmp) {
+ if (size < EXT2_MIN_CLUSTER_SIZE ||
+ size > EXT2_MAX_CLUSTER_SIZE || *tmp) {
com_err(program_name, 0,
_("invalid fragment size - %s"),
optarg);
exit(1);
}
- fprintf(stderr, _("Warning: fragments not supported. "
- "Ignoring -f option\n"));
+ fs_param.s_log_cluster_size =
+ int_log2(size >> EXT2_MIN_CLUSTER_LOG_SIZE);
break;
case 'g':
fs_param.s_blocks_per_group = strtoul(optarg, &tmp, 0);
@@ -1515,8 +1516,6 @@ profile_error:
check_plausibility(device_name);
check_mount(device_name, force, _("filesystem"));
- fs_param.s_log_cluster_size = fs_param.s_log_block_size;
-
/* Determine the size of the device (if possible) */
if (noaction && fs_blocks_count) {
dev_size = fs_blocks_count;
@@ -1752,16 +1751,24 @@ profile_error:
}
}
+ fs_param.s_log_block_size =
+ int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
+ if (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC) {
+ if (fs_param.s_log_cluster_size == 0)
+ fs_param.s_log_cluster_size =
+ fs_param.s_log_block_size + 4;
+ } else
+ fs_param.s_log_cluster_size = fs_param.s_log_block_size;
+
if (inode_ratio == 0) {
inode_ratio = get_int_from_profile(fs_types, "inode_ratio",
8192);
if (inode_ratio < blocksize)
inode_ratio = blocksize;
+ if (inode_ratio < EXT2_CLUSTER_SIZE(&fs_param))
+ inode_ratio = EXT2_CLUSTER_SIZE(&fs_param);
}
- fs_param.s_log_cluster_size = fs_param.s_log_block_size =
- int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
-
#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
retval = get_device_geometry(device_name, &fs_param, psector_size);
if (retval < 0) {
@@ -2049,6 +2056,33 @@ static int mke2fs_discard_device(ext2_filsys fs)
return retval;
}
+static fix_cluster_bg_counts(ext2_filsys fs)
+{
+ blk64_t cluster, num_clusters, tot_free;
+ int grp_free, num_free, group, num;
+
+ num_clusters = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super));
+ tot_free = num_free = num = group = grp_free = 0;
+ for (cluster = EXT2FS_B2C(fs, fs->super->s_first_data_block);
+ cluster < num_clusters; cluster++) {
+ if (!ext2fs_test_block_bitmap2(fs->block_map, cluster)) {
+ grp_free++;
+ tot_free++;
+ }
+ num++;
+ if ((num == fs->super->s_clusters_per_group) ||
+ (cluster == num_clusters-1)) {
+ printf("Group %d has free #: %d\n", group, grp_free);
+ ext2fs_bg_free_blocks_count_set(fs, group, grp_free);
+ ext2fs_group_desc_csum_set(fs, group);
+ num = 0;
+ grp_free = 0;
+ group++;
+ }
+ }
+ ext2fs_free_blocks_count_set(fs->super, tot_free);
+}
+
int main (int argc, char *argv[])
{
errcode_t retval = 0;
@@ -2367,6 +2401,17 @@ int main (int argc, char *argv[])
}
no_journal:
+ if (EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+ ext2fs_block_bitmap cluster_map;
+
+ retval = ext2fs_convert_to_cluster_bitmap(fs, fs->block_map,
+ &cluster_map);
+ ext2fs_free_block_bitmap(fs->block_map);
+ fs->block_map = cluster_map;
+ fix_cluster_bg_counts(fs);
+ }
+
if (!quiet)
printf(_("Writing superblocks and "
"filesystem accounting information: "));
diff --git a/version.h b/version.h
index 7005be1..7747e26 100644
--- a/version.h
+++ b/version.h
@@ -7,5 +7,5 @@
* file may be redistributed under the GNU Public License v2.
*/
-#define E2FSPROGS_VERSION "1.41.14"
-#define E2FSPROGS_DATE "22-Dec-2010"
+#define E2FSPROGS_VERSION "1.42.BIGALLOC-2"
+#define E2FSPROGS_DATE "22-Apr-2011"
^ permalink raw reply related [flat|nested] 21+ messages in thread
end of thread, other threads:[~2011-05-03 22:24 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-03 22:24 [PATCH 00/19] V2 Bigalloc patches Theodore Ts'o
2011-05-03 22:24 ` [PATCH 01/19] ext4: read-only support for bigalloc file systems Theodore Ts'o
2011-05-03 22:24 ` [PATCH 02/19] ext4: enforce bigalloc restrictions (e.g., no online resizing, etc.) Theodore Ts'o
2011-05-03 22:24 ` [PATCH 03/19] ext4: convert instances of EXT4_BLOCKS_PER_GROUP to EXT4_CLUSTERS_PER_GROUP Theodore Ts'o
2011-05-03 22:24 ` [PATCH 04/19] ext4: factor out block group accounting into functions Theodore Ts'o
2011-05-03 22:24 ` [PATCH 05/19] ext4: split out ext4_free_blocks_after_init() Theodore Ts'o
2011-05-03 22:24 ` [PATCH 06/19] ext4: bigalloc changes to block bitmap initialization functions Theodore Ts'o
2011-05-03 22:24 ` [PATCH 07/19] ext4: convert block group-relative offsets to use clusters Theodore Ts'o
2011-05-03 22:24 ` [PATCH 08/19] ext4: teach mballoc preallocation code about bigalloc clusters Theodore Ts'o
2011-05-03 22:24 ` [PATCH 09/19] ext4: teach ext4_free_blocks() about bigalloc and clusters Theodore Ts'o
2011-05-03 22:24 ` [PATCH 10/19] ext4: teach ext4_ext_map_blocks() about the bigalloc feature Theodore Ts'o
2011-05-03 22:24 ` [PATCH 11/19] ext4: teach ext4_ext_truncate() " Theodore Ts'o
2011-05-03 22:24 ` [PATCH 12/19] ext4: convert s_freeblocks_counter to s_freeclusters_counter Theodore Ts'o
2011-05-03 22:24 ` [PATCH 13/19] ext4: convert the free_blocks field in s_flex_groups to be free_clusters Theodore Ts'o
2011-05-03 22:24 ` [PATCH 14/19] ext4: teach ext4_statfs() to deal with clusters if bigalloc is enabled Theodore Ts'o
2011-05-03 22:24 ` [PATCH 15/19] ext4: tune mballoc's default group prealloc size for bigalloc file systems Theodore Ts'o
2011-05-03 22:24 ` [PATCH 16/19] ext4: enable mounting bigalloc as read/write Theodore Ts'o
2011-05-03 22:24 ` [PATCH 17/19] ext4: Rename ext4_free_blks_{count,set}() to refer to clusters Theodore Ts'o
2011-05-03 22:24 ` [PATCH 18/19] ext4: rename ext4_count_free_blocks() to ext4_count_free_clusters() Theodore Ts'o
2011-05-03 22:24 ` [PATCH 19/19] ext4: rename ext4_free_blocks_after_init() to ext4_free_clusters_after_init() Theodore Ts'o
2011-05-03 22:24 ` [E2FSPROGS PATCH] Interim patches for e2fsprogs Theodore Ts'o
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).