Skip to content
Snippets Groups Projects
Commit c9eb2c85 authored by alex's avatar alex
Browse files

- initial implementation of batching block allocator for ext3

  lots of tweaking to be done yet
parent 95542db7
No related branches found
No related tags found
No related merge requests found
Index: linux-2.4.24/fs/ext3/balloc.c
===================================================================
--- linux-2.4.24.orig/fs/ext3/balloc.c 2004-01-10 17:04:42.000000000 +0300
+++ linux-2.4.24/fs/ext3/balloc.c 2004-01-29 17:27:54.000000000 +0300
@@ -1007,3 +1007,294 @@
bitmap_count);
}
#endif
+
+#define MBDEBUG_
+#ifdef MBDEBUG
+#define mbdebug(fmt,a...) printk(fmt, ##a)
+#else
+#define mbdebug(fmt,a...)
+#endif
+
+/*
+ * in alloc_status we track allocation: the best found extent, how many
+ * extents we've skipped, etc
+ */
+struct alloc_status {
+ struct super_block *sb;
+ int goal; /* goal for allocation */
+ int target_len; /* goal for len */
+ int start, len; /* the best found extent */
+ int num; /* number of extent: to limit searching */
+};
+
+/*
+ * ext3_test_extent() compares requested extent with existing in as.
+ * if requested extent is better than that, then replace old one.
+ * then it tries to understand is new extent suitable or not
+ * return 1 if caller can complete searching
+ */
+inline int ext3_test_extent(struct alloc_status *as, int group,
+ int start, int len)
+{
+ struct ext3_super_block * es = EXT3_SB(as->sb)->s_es;
+ unsigned long tmp;
+
+ J_ASSERT(as->target_len >= len);
+
+ mbdebug("found extent %d:%d\n", start, len);
+ tmp = start + group * EXT3_BLOCKS_PER_GROUP(as->sb)
+ + le32_to_cpu(es->s_first_data_block);
+
+ /* account requests in order to limit searching */
+ as->num++;
+
+ if (as->num == 20)
+ return 1;
+
+ /* if hit goal, then searching may complete right now */
+ if (tmp == as->goal) {
+nice:
+ as->start = tmp;
+ as->len = len;
+ return 1;
+ }
+
+ /* if found extent has lenght we need, return it right now */
+ if (as->target_len == len)
+ goto nice;
+
+ /* first, check is found extent better than we have in as */
+ if (as->len > len) {
+better:
+ as->start = tmp;
+ as->len = len;
+ return 0;
+ }
+
+ /* FIXME: more checks! */
+ as->start = tmp;
+ as->len = len;
+
+ /* 1) closeness to goal */
+
+ /* 2) extent lenght */
+ /* 3) number of tested extent (we check all found extents) */
+ /* */
+ return 0;
+}
+
+/*
+ * this routine tries to find upto *len free contig. blocks
+ * return number of found block (+ lenght of extent in *len)
+ * or -1 if no free blocks at all
+ */
+int ext3_find_free_extent(struct buffer_head *bh, int goal, int *len, int max)
+{
+ int i, l = 0;
+
+repeat:
+ if (goal >= max)
+ return -1;
+ /* find first free block */
+ i = ext3_find_next_zero_bit(bh->b_data, max, goal);
+ if (i >= max) {
+ /* no free block */
+ return -1;
+ }
+ /* check upto len block for ability to be allocated */
+ while (l < *len && i + l < max) {
+ if (!ext3_test_allocatable(i + l, bh))
+ break;
+ l++;
+ }
+ if (l == 0) {
+ goal = i + 1;
+ goto repeat;
+ }
+ *len = l;
+ return i;
+}
+
+/*
+ * this routine loops over group, finds free extents and tests them
+ * for some criterias
+ * it may return negative value if group can't be loaded, 0 - if
+ * no good extent can be found, 1 - if good extent found
+ */
+int ext3_find_extent_in_group(struct alloc_status *as, int group,
+ unsigned long goal, int len)
+{
+ int k, i, l, bitmap_nr, found = 0;
+ struct super_block *sb = as->sb;
+ int max = EXT3_BLOCKS_PER_GROUP(sb);
+ struct buffer_head *bh, *bmbh;
+ struct ext3_group_desc *gdp;
+
+ mbdebug("look for %d blocks in group %d starting from %lu\n",
+ len, group, goal);
+
+ gdp = ext3_get_group_desc(as->sb, group, &bh);
+ if (!gdp)
+ return -EIO;
+
+ if (le16_to_cpu(gdp->bg_free_blocks_count) == 0)
+ return 0;
+
+ bitmap_nr = load_block_bitmap(as->sb, group);
+ if (bitmap_nr < 0)
+ return -EIO;
+
+ bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
+
+ i = goal;
+ /* scan from goal to the end */
+repeat:
+ while (i < max) {
+ l = len;
+ k = ext3_find_free_extent(bmbh, i, &l, max);
+ i = k + l;
+ if (k < 0)
+ break;
+ if (ext3_test_extent(as, group, k, l)) {
+ found = 1;
+ goto out;
+ }
+ }
+
+ if (goal) {
+ /* scan from 0 upto goal */
+ mbdebug("repeat from %lu in %d\n", goal, group);
+ max = goal - 1;
+ goal = i = 0;
+ goto repeat;
+ }
+out:
+ return found;
+}
+
+#define check_in_committed(bh,j) \
+ J_ASSERT_BH((bh), !ext3_test_bit((j), bh2jh((bh))->b_committed_data))
+
+int ext3_new_blocks(handle_t *handle, struct inode *inode, int *num,
+ unsigned long goal, int *errp)
+{
+ struct super_block *sb = inode->i_sb;
+ int first_group, group, bitmap_nr;
+ struct buffer_head *bh, *bmbh;
+ struct ext3_super_block *es;
+ struct ext3_group_desc *gdp;
+ struct alloc_status as;
+ int err, bit, i;
+
+ int scaned = 0;
+
+ J_ASSERT(num && *num > 0);
+
+ if (DQUOT_ALLOC_BLOCK(inode, *num)) {
+ *errp = -EDQUOT;
+ return 0;
+ }
+
+ es = EXT3_SB(inode->i_sb)->s_es;
+
+ *errp = 0;
+ as.target_len = *num;
+ as.sb = sb;
+ as.goal = goal;
+ as.start = -1;
+ as.len = 0;
+ as.num = 0;
+
+ lock_super(sb);
+ first_group = (goal - le32_to_cpu(es->s_first_data_block)) /
+ EXT3_BLOCKS_PER_GROUP(sb);
+ goal = (goal - le32_to_cpu(es->s_first_data_block)) %
+ EXT3_BLOCKS_PER_GROUP(sb);
+ group = first_group;
+ do {
+ scaned++;
+ err = ext3_find_extent_in_group(&as, group, goal, *num);
+ if (err < 0)
+ goto error_out;
+ else if (err)
+ break;
+
+ /* reset goal for next groups */
+ goal = 0;
+
+ /* try next group */
+ if (++group == EXT3_SB(sb)->s_groups_count)
+ group = 0;
+ } while (group != first_group);
+
+ if (as.len == 0) {
+ err = -ENOSPC;
+ goto error_out;
+ }
+
+ /* in the end we've found something, allocate it */
+ mbdebug("best extent: %u:%u\n", as.start, as.len);
+
+ group = (as.start - le32_to_cpu(es->s_first_data_block)) /
+ EXT3_BLOCKS_PER_GROUP(sb);
+ bit = (as.start - le32_to_cpu(es->s_first_data_block)) %
+ EXT3_BLOCKS_PER_GROUP(sb);
+ gdp = ext3_get_group_desc(sb, group, &bh);
+ if (!gdp) {
+ err = -EIO;
+ goto error_out;
+ }
+
+ /* mark block(s) used in bitmap ... */
+ bitmap_nr = load_block_bitmap(sb, group);
+ if (bitmap_nr < 0) {
+ err = -EIO;
+ goto error_out;
+ }
+ bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
+ if (err)
+ goto error_out;
+ err = ext3_journal_get_write_access(handle, bmbh);
+ if (err)
+ goto error_out;
+ err = ext3_journal_get_write_access(handle, bh);
+ if (err)
+ goto error_out;
+ for (i = 0; i < as.len; i++) {
+ J_ASSERT(!ext3_test_bit(bit + i, bmbh->b_data));
+ if (buffer_jbd(bmbh) && bh2jh(bmbh)->b_committed_data)
+ check_in_committed(bmbh, bit + i);
+ set_bit(bit + i, bmbh->b_data);
+ }
+ err = ext3_journal_dirty_metadata(handle, bmbh);
+ if (err)
+ goto error_out;
+
+ /* ... and correct group descriptor */
+ gdp->bg_free_blocks_count =
+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - as.len);
+ es->s_free_blocks_count =
+ cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - as.len);
+ err = ext3_journal_dirty_metadata(handle, bmbh);
+ if (err)
+ goto error_out;
+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
+ if (err)
+ goto error_out;
+ sb->s_dirt = 1;
+
+ if (*num != as.len)
+ DQUOT_FREE_BLOCK(inode, *num - as.len);
+ *num = as.len;
+
+out:
+ unlock_super(sb);
+ return as.start;
+
+error_out:
+ as.start = 0;
+ *errp = err;
+ goto out;
+}
+
Index: linux-2.4.24/fs/ext3/file.c
===================================================================
--- linux-2.4.24.orig/fs/ext3/file.c 2004-01-12 20:36:32.000000000 +0300
+++ linux-2.4.24/fs/ext3/file.c 2004-01-29 18:26:23.000000000 +0300
@@ -69,6 +69,18 @@
int err;
struct inode *inode = file->f_dentry->d_inode;
+#if 0
+ /* allocate all the space to be written */
+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {
+ int blocksize = inode->i_sb->s_blocksize;
+ unsigned long start, end;
+
+ start = (unsigned long) *ppos / blocksize;
+ end = ((unsigned long) *ppos + count + blocksize - 1)
+ / blocksize;
+ ext3_ext_allocate_nblocks(inode, start, end - start);
+ }
+#endif
ret = generic_file_write(file, buf, count, ppos);
/* Skip file flushing code if there was an error, or if nothing
Index: linux-2.4.24/include/linux/ext3_fs.h
===================================================================
--- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-01-26 23:17:19.000000000 +0300
+++ linux-2.4.24/include/linux/ext3_fs.h 2004-01-29 16:29:36.000000000 +0300
@@ -58,6 +58,8 @@
#define ext3_debug(f, a...) do {} while (0)
#endif
+#define EXT3_MULTIBLOCK_ALLOCATOR 1
+
/*
* Special inodes numbers
*/
@@ -667,6 +669,7 @@
extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
unsigned int block_group,
struct buffer_head ** bh);
+extern int ext3_new_blocks(handle_t*, struct inode*, int*, unsigned long, int*);
/* dir.c */
extern int ext3_check_dir_entry(const char *, struct inode *,
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment