aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Phillips <daniel@tux3.org>2014-02-19 03:51:49 +0900
committerDaniel Phillips <daniel@tux3.org>2014-02-19 03:51:49 +0900
commita70ba0b40a3938a7dd962f36afa122f8fb84a786 (patch)
tree74962943edaf5b741f7301b0ca1c0915d2a1dd3f
parent18d5bc21bb104c99e8ecdd57153663238dbe8869 (diff)
downloadlinux-tux3-a70ba0b40a3938a7dd962f36afa122f8fb84a786.tar.gz
tux3: Group count update operation using media format
Group count update operation using media format, working in block buffers. Pin the most recently accessed group count table block buffer in cache to avoid repeated blockread (should do the same for the bitmap table). Signed-off-by: Daniel Phillips <d.phillips@partner.samsung.com> Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r--fs/tux3/balloc.c64
-rw-r--r--fs/tux3/commit.c1
-rw-r--r--fs/tux3/super.c2
-rw-r--r--fs/tux3/tux3.h9
4 files changed, 74 insertions, 2 deletions
diff --git a/fs/tux3/balloc.c b/fs/tux3/balloc.c
index c5148086a7aedf..c1b17082da2964 100644
--- a/fs/tux3/balloc.c
+++ b/fs/tux3/balloc.c
@@ -15,6 +15,68 @@
#define trace trace_on
#endif
+/*
+ * Group counts
+ */
+
+static int countmap_load(struct sb *sb, block_t group)
+{
+ block_t block = group >> (sb->blockbits - 1);
+ struct countmap_pin *pin = &sb->countmap_pin;
+
+ if (!pin->buffer || bufindex(pin->buffer) != block) {
+ if (pin->buffer)
+ blockput(pin->buffer);
+ pin->buffer = blockread(mapping(sb->countmap), block);
+ if (!pin->buffer) {
+ tux3_err(sb, "block read failed");
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+static int countmap_add(struct sb *sb, block_t group, int count)
+{
+ unsigned offset = group & (sb->blockmask >> 1);
+ struct buffer_head *clone;
+ __be16 *p;
+ int err;
+
+ err = countmap_load(sb, group);
+ if (err)
+ return err;
+ trace("add %d to group %Lu", count, group);
+ /*
+ * The countmap is modified only by backend. blockdirty()
+ * should never return -EAGAIN.
+ */
+ clone = blockdirty(sb->countmap_pin.buffer, sb->unify);
+ if (IS_ERR(clone)) {
+ err = PTR_ERR(clone);
+ assert(err != -EAGAIN);
+ return err;
+ }
+ sb->countmap_pin.buffer = clone;
+
+ p = bufdata(sb->countmap_pin.buffer);
+ be16_add_cpu(p + offset, count);
+
+ return 0;
+}
+
+void countmap_put(struct countmap_pin *pin)
+{
+ if (pin->buffer) {
+ blockput(pin->buffer);
+ pin->buffer = NULL;
+ }
+}
+
+/*
+ * Bitmap
+ */
+
#ifndef __KERNEL__
block_t count_range(struct inode *inode, block_t start, block_t count)
{
@@ -200,7 +262,7 @@ static int __bitmap_modify(struct sb *sb, block_t start, unsigned blocks,
blocks -= len;
}
- return 0;
+ return countmap_add(sb, start >> sb->groupbits, set ? blocks : -blocks);
}
static int bitmap_modify(struct sb *sb, block_t start, unsigned blocks, int set)
diff --git a/fs/tux3/commit.c b/fs/tux3/commit.c
index 5cb0040e077498..da846fd5ecd530 100644
--- a/fs/tux3/commit.c
+++ b/fs/tux3/commit.c
@@ -84,6 +84,7 @@ static void __setup_sb(struct sb *sb, struct disksuper *super)
sb->blocksize = 1 << sb->blockbits;
sb->blockmask = (1 << sb->blockbits) - 1;
+ sb->groupbits = 13; // FIXME: put in disk super?
sb->entries_per_node = calc_entries_per_node(sb->blocksize);
/* Initialize base indexes for atable */
atable_init_base(sb);
diff --git a/fs/tux3/super.c b/fs/tux3/super.c
index 522a98da530bd2..08b5aa120fedd2 100644
--- a/fs/tux3/super.c
+++ b/fs/tux3/super.c
@@ -108,6 +108,8 @@ static void __tux3_put_super(struct sb *sbi)
destroy_defer_bfree(&sbi->deunify);
destroy_defer_bfree(&sbi->defree);
+ countmap_put(&sbi->countmap_pin);
+
iput(sbi->rootdir);
sbi->rootdir = NULL;
iput(sbi->atable);
diff --git a/fs/tux3/tux3.h b/fs/tux3/tux3.h
index e9941f9840ecf8..b10c8723d167be 100644
--- a/fs/tux3/tux3.h
+++ b/fs/tux3/tux3.h
@@ -227,6 +227,11 @@ struct sb_delta_dirty {
struct list_head dirty_inodes; /* dirty inodes list */
};
+/* Pin a block in cache and keep a pointer to it */
+struct countmap_pin {
+ struct buffer_head *buffer;
+};
+
/* Tux3-specific sb is a handle for the entire volume state */
struct sb {
union {
@@ -267,7 +272,7 @@ struct sb {
struct inode *vtable; /* version table special file */
struct inode *atable; /* xattr atom special file */
- unsigned blocksize, blockbits, blockmask;
+ unsigned blocksize, blockbits, blockmask, groupbits;
u64 freeinodes; /* Number of free inode numbers. This is
* including the deferred allocated inodes */
block_t volblocks, freeblocks, nextblock;
@@ -303,6 +308,7 @@ struct sb {
/*
* For frontend and backend
*/
+ struct countmap_pin countmap_pin;
struct list_head alloc_inodes; /* deferred inum allocation inodes */
spinlock_t forked_buffers_lock;
@@ -697,6 +703,7 @@ struct buffer_head *blockget(struct address_space *mapping, block_t iblock);
#endif /* !__KERNEL__ */
/* balloc.c */
+void countmap_put(struct countmap_pin *countmap_pin);
block_t bitmap_dump(struct inode *inode, block_t start, block_t count);
int balloc_find_range(struct sb *sb,
struct block_segment *seg, int maxsegs, int *segs,