LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 5/7] omfs: add bitmap routines
@ 2008-03-27 0:45 Bob Copeland
2008-03-28 3:51 ` Arnd Bergmann
0 siblings, 1 reply; 6+ messages in thread
From: Bob Copeland @ 2008-03-27 0:45 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, Bob Copeland
Add block allocation and block bitmap management routines for OMFS.
Signed-off-by: Bob Copeland <me@bobcopeland.com>
---
fs/omfs/bitmap.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 200 insertions(+), 0 deletions(-)
create mode 100644 fs/omfs/bitmap.c
diff --git a/fs/omfs/bitmap.c b/fs/omfs/bitmap.c
new file mode 100644
index 0000000..7cc6fe4
--- /dev/null
+++ b/fs/omfs/bitmap.c
@@ -0,0 +1,200 @@
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <asm/div64.h>
+#include "omfs.h"
+
+static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+
+unsigned long omfs_count_free(struct super_block *sb)
+{
+ unsigned int i, j, count = 0;
+ unsigned char *map;
+ unsigned long sum = 0;
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+
+ for (i = 0; i < sbi->s_imap_size; i++) {
+ map = (unsigned char *) sbi->s_imap[i];
+ for (j = 0; j < sb->s_blocksize &&
+ count + j < sbi->s_num_blocks/8; j++)
+ sum += nibblemap[map[j] & 0xf] +
+ nibblemap[(map[j] >> 4) & 0xf];
+ count += sb->s_blocksize;
+ }
+ return sum;
+}
+
+/*
+ * Counts the run of zero bits starting at bit up to max.
+ * It handles the case where a run might spill over a buffer.
+ * Called with bitmap lock.
+ */
+static int count_run(unsigned long **addr, int nbits,
+ int addrlen, int bit, int max)
+{
+ int count = 0;
+ int x;
+
+ for (; addrlen > 0; addrlen--, addr++) {
+ x = find_next_bit(*addr, nbits, bit);
+ count += x - bit;
+
+ if (x < nbits || count > max)
+ return min(count, max);
+
+ bit = 0;
+ }
+ return min(count, max);
+}
+
+/*
+ * Sets or clears the run of count bits starting with bit.
+ * Called with bitmap lock.
+ */
+static int set_run(struct super_block *sb, int map,
+ int nbits, int bit, int count, int set)
+{
+ int i;
+ struct buffer_head *bh;
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+
+ bh = sb_bread(sb, clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
+ if (!bh)
+ goto nomem;
+
+ for (i = 0; i < count; i++, bit++) {
+ if (bit >= nbits) {
+ bit = 0;
+ map++;
+
+ mark_buffer_dirty(bh);
+ brelse(bh);
+ bh = sb_bread(sb,
+ clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
+ if (!bh)
+ goto nomem;
+ }
+ if (set) {
+ set_bit(bit, sbi->s_imap[map]);
+ set_bit(bit, (long *) bh->b_data);
+ } else {
+ clear_bit(bit, sbi->s_imap[map]);
+ clear_bit(bit, (long *) bh->b_data);
+ }
+ }
+ mark_buffer_dirty(bh);
+ brelse(bh);
+ return 0;
+nomem:
+ return -ENOMEM;
+}
+
+/*
+ * Tries to allocate exactly one block. Returns true if sucessful.
+ */
+int omfs_allocate_block(struct super_block *sb, u64 block)
+{
+ struct buffer_head *bh;
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+ int bits_per_entry = 8 * sb->s_blocksize;
+ int map, bit;
+ int ret = 1;
+ u64 tmp;
+
+ tmp = block;
+ bit = do_div(tmp, bits_per_entry);
+ map = tmp;
+
+ mutex_lock(&sbi->s_bitmap_lock);
+ if (map >= sbi->s_imap_size ||
+ test_and_set_bit(bit, sbi->s_imap[map])) {
+ ret = 0;
+ goto out;
+ }
+
+ if (sbi->s_bitmap_ino > 0) {
+ bh = sb_bread(sb, clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
+ if (!bh) {
+ ret = 0;
+ goto out;
+ }
+ set_bit(bit, (long *) bh->b_data);
+ mark_buffer_dirty(bh);
+ brelse(bh);
+ }
+out:
+ mutex_unlock(&sbi->s_bitmap_lock);
+ return ret;
+}
+
+
+/*
+ * Tries to allocate a set of blocks. The request size depends on the
+ * type: for inodes, we must allocate sbi->s_mirrors blocks, and for file
+ * blocks, we try to allocate sbi->s_clustersize, but can always get away
+ * with just one block.
+ */
+int omfs_allocate_range(struct super_block *sb,
+ int min_request,
+ int max_request,
+ u64 *return_block,
+ int *return_size)
+{
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+ int bits_per_entry = 8 * sb->s_blocksize;
+ int ret = 0;
+ int i, run, bit;
+
+ mutex_lock(&sbi->s_bitmap_lock);
+ for (i = 0; i < sbi->s_imap_size; i++) {
+ bit = 0;
+ while (bit < bits_per_entry) {
+ bit = find_next_zero_bit(sbi->s_imap[i], bits_per_entry,
+ bit);
+
+ if (bit == bits_per_entry)
+ break;
+
+ run = count_run(&sbi->s_imap[i], bits_per_entry,
+ sbi->s_imap_size-i, bit, max_request);
+
+ if (run >= min_request)
+ goto found;
+ bit += run;
+ }
+ }
+ ret = -ENOSPC;
+ goto out;
+
+found:
+ *return_block = i * bits_per_entry + bit;
+ *return_size = run;
+ ret = set_run(sb, i, bits_per_entry, bit, run, 1);
+
+out:
+ mutex_unlock(&sbi->s_bitmap_lock);
+ return ret;
+}
+
+/*
+ * Clears count bits starting at a given block.
+ */
+int omfs_clear_range(struct super_block *sb, u64 block, int count)
+{
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+ int bits_per_entry = 8 * sb->s_blocksize;
+ u64 tmp;
+ int map, bit, ret;
+
+ tmp = block;
+ bit = do_div(tmp, bits_per_entry);
+ map = tmp;
+
+ if (map >= sbi->s_imap_size)
+ return 0;
+
+ mutex_lock(&sbi->s_bitmap_lock);
+ ret = set_run(sb, map, bits_per_entry, bit, count, 0);
+ mutex_unlock(&sbi->s_bitmap_lock);
+ return ret;
+}
--
1.5.4.2.182.gb3092
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 5/7] omfs: add bitmap routines
2008-03-27 0:45 [PATCH 5/7] omfs: add bitmap routines Bob Copeland
@ 2008-03-28 3:51 ` Arnd Bergmann
2008-03-28 13:26 ` Bob Copeland
2008-03-30 3:27 ` Bob Copeland
0 siblings, 2 replies; 6+ messages in thread
From: Arnd Bergmann @ 2008-03-28 3:51 UTC (permalink / raw)
To: Bob Copeland; +Cc: linux-kernel, linux-fsdevel
On Thursday 27 March 2008, Bob Copeland wrote:
> +static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
> +
> +unsigned long omfs_count_free(struct super_block *sb)
> +{
> + unsigned int i, j, count = 0;
> + unsigned char *map;
> + unsigned long sum = 0;
> + struct omfs_sb_info *sbi = OMFS_SB(sb);
> +
> + for (i = 0; i < sbi->s_imap_size; i++) {
> + map = (unsigned char *) sbi->s_imap[i];
> + for (j = 0; j < sb->s_blocksize &&
> + count + j < sbi->s_num_blocks/8; j++)
> + sum += nibblemap[map[j] & 0xf] +
> + nibblemap[(map[j] >> 4) & 0xf];
> + count += sb->s_blocksize;
> + }
> + return sum;
> +}
I think it would be helpful to express this using hweight64.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 5/7] omfs: add bitmap routines
2008-03-28 3:51 ` Arnd Bergmann
@ 2008-03-28 13:26 ` Bob Copeland
2008-03-30 3:27 ` Bob Copeland
1 sibling, 0 replies; 6+ messages in thread
From: Bob Copeland @ 2008-03-28 13:26 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linux-kernel, linux-fsdevel
On Thu, Mar 27, 2008 at 11:51 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thursday 27 March 2008, Bob Copeland wrote:
>
> > +static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
> > +
> > +unsigned long omfs_count_free(struct super_block *sb)
>
> I think it would be helpful to express this using hweight64.
Thanks for the review.
Yes, that would probably be cleaner. FWIW minix and affs both have
this sort of code too.
-Bob
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 5/7] omfs: add bitmap routines
2008-03-28 3:51 ` Arnd Bergmann
2008-03-28 13:26 ` Bob Copeland
@ 2008-03-30 3:27 ` Bob Copeland
1 sibling, 0 replies; 6+ messages in thread
From: Bob Copeland @ 2008-03-30 3:27 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linux-kernel, linux-fsdevel
On Fri, Mar 28, 2008 at 04:51:10AM +0100, Arnd Bergmann wrote:
> On Thursday 27 March 2008, Bob Copeland wrote:
>
> > +unsigned long omfs_count_free(struct super_block *sb)
>
> I think it would be helpful to express this using hweight64.
Here's a version with hweight64:
+unsigned long omfs_count_free(struct super_block *sb)
+{
+ unsigned int i, j;
+ u64 *map;
+ unsigned long sum = 0;
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+
+ for (i = 0; i < sbi->s_imap_size; i++) {
+ map = (u64 *) sbi->s_imap[i];
+ for (j = 0; j < sb->s_blocksize / 8; j++)
+ sum += hweight64(~map[j]);
+ }
+ return sum;
+}
--
Bob Copeland %% www.bobcopeland.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 5/7] omfs: add bitmap routines
2008-04-12 22:58 Bob Copeland
@ 2008-04-13 8:09 ` Christoph Hellwig
0 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2008-04-13 8:09 UTC (permalink / raw)
To: Bob Copeland; +Cc: linux-kernel, linux-fsdevel, akpm
On Sat, Apr 12, 2008 at 06:58:39PM -0400, Bob Copeland wrote:
> Add block allocation and block bitmap management routines for OMFS.
Looks good.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 5/7] omfs: add bitmap routines
@ 2008-04-12 22:58 Bob Copeland
2008-04-13 8:09 ` Christoph Hellwig
0 siblings, 1 reply; 6+ messages in thread
From: Bob Copeland @ 2008-04-12 22:58 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-fsdevel, akpm, Bob Copeland
Add block allocation and block bitmap management routines for OMFS.
Signed-off-by: Bob Copeland <me@bobcopeland.com>
---
fs/omfs/bitmap.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 195 insertions(+), 0 deletions(-)
create mode 100644 fs/omfs/bitmap.c
diff --git a/fs/omfs/bitmap.c b/fs/omfs/bitmap.c
new file mode 100644
index 0000000..888c1ce
--- /dev/null
+++ b/fs/omfs/bitmap.c
@@ -0,0 +1,195 @@
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <asm/div64.h>
+#include "omfs.h"
+
+unsigned long omfs_count_free(struct super_block *sb)
+{
+ unsigned int i, j;
+ u64 *map;
+ unsigned long sum = 0;
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+
+ for (i = 0; i < sbi->s_imap_size; i++) {
+ map = (u64 *) sbi->s_imap[i];
+ for (j = 0; j < sb->s_blocksize / 8; j++)
+ sum += hweight64(~map[j]);
+ }
+ return sum;
+}
+
+/*
+ * Counts the run of zero bits starting at bit up to max.
+ * It handles the case where a run might spill over a buffer.
+ * Called with bitmap lock.
+ */
+static int count_run(unsigned long **addr, int nbits,
+ int addrlen, int bit, int max)
+{
+ int count = 0;
+ int x;
+
+ for (; addrlen > 0; addrlen--, addr++) {
+ x = find_next_bit(*addr, nbits, bit);
+ count += x - bit;
+
+ if (x < nbits || count > max)
+ return min(count, max);
+
+ bit = 0;
+ }
+ return min(count, max);
+}
+
+/*
+ * Sets or clears the run of count bits starting with bit.
+ * Called with bitmap lock.
+ */
+static int set_run(struct super_block *sb, int map,
+ int nbits, int bit, int count, int set)
+{
+ int i;
+ struct buffer_head *bh;
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+
+ bh = sb_bread(sb, clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
+ if (!bh)
+ goto nomem;
+
+ for (i = 0; i < count; i++, bit++) {
+ if (bit >= nbits) {
+ bit = 0;
+ map++;
+
+ mark_buffer_dirty(bh);
+ brelse(bh);
+ bh = sb_bread(sb,
+ clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
+ if (!bh)
+ goto nomem;
+ }
+ if (set) {
+ set_bit(bit, sbi->s_imap[map]);
+ set_bit(bit, (long *) bh->b_data);
+ } else {
+ clear_bit(bit, sbi->s_imap[map]);
+ clear_bit(bit, (long *) bh->b_data);
+ }
+ }
+ mark_buffer_dirty(bh);
+ brelse(bh);
+ return 0;
+nomem:
+ return -ENOMEM;
+}
+
+/*
+ * Tries to allocate exactly one block. Returns true if sucessful.
+ */
+int omfs_allocate_block(struct super_block *sb, u64 block)
+{
+ struct buffer_head *bh;
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+ int bits_per_entry = 8 * sb->s_blocksize;
+ int map, bit;
+ int ret = 1;
+ u64 tmp;
+
+ tmp = block;
+ bit = do_div(tmp, bits_per_entry);
+ map = tmp;
+
+ mutex_lock(&sbi->s_bitmap_lock);
+ if (map >= sbi->s_imap_size ||
+ test_and_set_bit(bit, sbi->s_imap[map])) {
+ ret = 0;
+ goto out;
+ }
+
+ if (sbi->s_bitmap_ino > 0) {
+ bh = sb_bread(sb, clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
+ if (!bh) {
+ ret = 0;
+ goto out;
+ }
+ set_bit(bit, (long *) bh->b_data);
+ mark_buffer_dirty(bh);
+ brelse(bh);
+ }
+out:
+ mutex_unlock(&sbi->s_bitmap_lock);
+ return ret;
+}
+
+
+/*
+ * Tries to allocate a set of blocks. The request size depends on the
+ * type: for inodes, we must allocate sbi->s_mirrors blocks, and for file
+ * blocks, we try to allocate sbi->s_clustersize, but can always get away
+ * with just one block.
+ */
+int omfs_allocate_range(struct super_block *sb,
+ int min_request,
+ int max_request,
+ u64 *return_block,
+ int *return_size)
+{
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+ int bits_per_entry = 8 * sb->s_blocksize;
+ int ret = 0;
+ int i, run, bit;
+
+ mutex_lock(&sbi->s_bitmap_lock);
+ for (i = 0; i < sbi->s_imap_size; i++) {
+ bit = 0;
+ while (bit < bits_per_entry) {
+ bit = find_next_zero_bit(sbi->s_imap[i], bits_per_entry,
+ bit);
+
+ if (bit == bits_per_entry)
+ break;
+
+ run = count_run(&sbi->s_imap[i], bits_per_entry,
+ sbi->s_imap_size-i, bit, max_request);
+
+ if (run >= min_request)
+ goto found;
+ bit += run;
+ }
+ }
+ ret = -ENOSPC;
+ goto out;
+
+found:
+ *return_block = i * bits_per_entry + bit;
+ *return_size = run;
+ ret = set_run(sb, i, bits_per_entry, bit, run, 1);
+
+out:
+ mutex_unlock(&sbi->s_bitmap_lock);
+ return ret;
+}
+
+/*
+ * Clears count bits starting at a given block.
+ */
+int omfs_clear_range(struct super_block *sb, u64 block, int count)
+{
+ struct omfs_sb_info *sbi = OMFS_SB(sb);
+ int bits_per_entry = 8 * sb->s_blocksize;
+ u64 tmp;
+ int map, bit, ret;
+
+ tmp = block;
+ bit = do_div(tmp, bits_per_entry);
+ map = tmp;
+
+ if (map >= sbi->s_imap_size)
+ return 0;
+
+ mutex_lock(&sbi->s_bitmap_lock);
+ ret = set_run(sb, map, bits_per_entry, bit, count, 0);
+ mutex_unlock(&sbi->s_bitmap_lock);
+ return ret;
+}
--
1.5.4.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-04-13 8:09 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-27 0:45 [PATCH 5/7] omfs: add bitmap routines Bob Copeland
2008-03-28 3:51 ` Arnd Bergmann
2008-03-28 13:26 ` Bob Copeland
2008-03-30 3:27 ` Bob Copeland
2008-04-12 22:58 Bob Copeland
2008-04-13 8:09 ` Christoph Hellwig
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).