aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2013-01-19 20:03:34 +0900
committerDaniel Phillips <daniel@tux3.org>2013-01-19 20:03:34 +0900
commita7db9df0ba2a90483477a02cafe73c4b0346f068 (patch)
treeae55f4f28dc28506a918b76f0476f44163c6f86f
parentd7cadd6e99a06a7c7bd9566cda388b9eccd74b97 (diff)
downloadlinux-tux3-a7db9df0ba2a90483477a02cafe73c4b0346f068.tar.gz
tux3: Don't pin log blocks, instead, use dirty state to pin
Now, log buffer was dirtied to write. So, we don't need to pin log buffers explicitly. Instead, we have to clear dirty to discard log buffers. To discard log buffers, this adds new parameter for log_finish_cycle(). If "discard" was specified, it clear dirty of log buffers. So, as usual, clean log buffers are not written. Also, as usual, dirty state prevents buffers to be reclaimed. So, we don't need to pin log buffers anymore. But, replay path doesn't dirty log buffers, so it has to pin buffer. Now, replay pins buffers explicitly. Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r--fs/tux3/commit.c4
-rw-r--r--fs/tux3/log.c27
-rw-r--r--fs/tux3/replay.c39
-rw-r--r--fs/tux3/tux3.h4
4 files changed, 42 insertions, 32 deletions
diff --git a/fs/tux3/commit.c b/fs/tux3/commit.c
index 117a73de512e1..8ada5989c75c4 100644
--- a/fs/tux3/commit.c
+++ b/fs/tux3/commit.c
@@ -183,7 +183,7 @@ static void new_cycle_log(struct sb *sb)
/* Discard the logs generated by frontend. */
log_finish(sb);
- log_finish_cycle(sb);
+ log_finish_cycle(sb, 1);
#endif
/* Initialize logcount to count log blocks on new rollup cycle. */
sb->super.logcount = 0;
@@ -298,7 +298,7 @@ static int write_log(struct sb *sb)
{
/* Finish to logging in this delta */
log_finish(sb);
- log_finish_cycle(sb);
+ log_finish_cycle(sb, 0);
return tux3_flush_inode_internal(sb->logmap, TUX3_INIT_DELTA);
}
diff --git a/fs/tux3/log.c b/fs/tux3/log.c
index bb4e5a830fd47..95f716b6e5f30 100644
--- a/fs/tux3/log.c
+++ b/fs/tux3/log.c
@@ -83,14 +83,12 @@ unsigned log_size[] = {
[LOG_DELTA] = 1,
};
-void log_next(struct sb *sb, int pin)
+void log_next(struct sb *sb)
{
/* FIXME: error handling of blockget() */
sb->logbuf = blockget(mapping(sb->logmap), sb->lognext++);
sb->logpos = bufdata(sb->logbuf) + sizeof(struct logblock);
sb->logtop = bufdata(sb->logbuf) + sb->blocksize;
- if (pin)
- get_bh(sb->logbuf);
}
void log_drop(struct sb *sb)
@@ -111,19 +109,22 @@ void log_finish(struct sb *sb)
}
}
-void log_finish_cycle(struct sb *sb)
+void log_finish_cycle(struct sb *sb, int discard)
{
- struct buffer_head *logbuf;
- unsigned count = sb->lognext;
-
/* ->logbuf must be finished */
assert(sb->logbuf == NULL);
- for (int i = 0; i < count; i++) {
- logbuf = blockget(mapping(sb->logmap), i);
- blockput(logbuf);
- blockput(logbuf); /* unpin */
+ if (discard) {
+ struct buffer_head *logbuf;
+ unsigned i, logcount = sb->lognext;
+
+ /* Clear dirty of buffer */
+ for (i = 0; i < logcount; i++) {
+ logbuf = blockget(mapping(sb->logmap), i);
+ blockput_free(sb, logbuf);
+ }
}
+
/* Initialize for new delta cycle */
sb->lognext = 0;
}
@@ -133,11 +134,13 @@ static void *log_begin(struct sb *sb, unsigned bytes)
mutex_lock(&sb->loglock);
if (sb->logpos + bytes > sb->logtop) {
log_finish(sb);
- log_next(sb, 1);
+ log_next(sb);
*(struct logblock *)bufdata(sb->logbuf) = (struct logblock){
.magic = cpu_to_be16(TUX3_MAGIC_LOG),
};
+
+ /* Dirty for write, and prevent to be reclaimed */
tux3_mark_buffer_dirty(sb->logbuf);
}
return sb->logpos;
diff --git a/fs/tux3/replay.c b/fs/tux3/replay.c
index 2ad444ad557f8..d6936a0af80da 100644
--- a/fs/tux3/replay.c
+++ b/fs/tux3/replay.c
@@ -96,11 +96,26 @@ static int replay_check_log(struct replay *rp, struct buffer_head *logbuf)
return 0;
}
+/* Unpin logblocks. */
+static void replay_unpin_logblocks(struct sb *sb, unsigned i, unsigned logcount)
+{
+ struct buffer_head *logbuf;
+
+ while (i < logcount) {
+ logbuf = blockget(mapping(sb->logmap), i);
+ assert(logbuf != NULL);
+ blockput(logbuf);
+ blockput(logbuf); /* Unpin */
+
+ i++;
+ }
+}
+
/* Prepare log info for replay and pin logblocks. */
static struct replay *replay_prepare(struct sb *sb)
{
block_t logchain = be64_to_cpu(sb->super.logchain);
- unsigned j, i, logcount = be32_to_cpu(sb->super.logcount);
+ unsigned i, logcount = be32_to_cpu(sb->super.logcount);
struct replay *rp;
struct buffer_head *buffer;
int err;
@@ -119,21 +134,18 @@ static struct replay *replay_prepare(struct sb *sb)
buffer = blockget(mapping(sb->logmap), i);
if (!buffer) {
+ i++;
err = -ENOMEM;
goto error;
}
assert(bufindex(buffer) == i);
err = blockio(READ, sb, buffer, logchain);
- if (err) {
- blockput(buffer);
+ if (err)
goto error;
- }
err = replay_check_log(rp, buffer);
- if (err) {
- blockput(buffer);
+ if (err)
goto error;
- }
/* Store index => blocknr map */
rp->blocknrs[bufindex(buffer)] = logchain;
@@ -146,14 +158,8 @@ static struct replay *replay_prepare(struct sb *sb)
error:
free_replay(rp);
+ replay_unpin_logblocks(sb, i, logcount);
- j = logcount;
- while (--j > i) {
- buffer = blockget(mapping(sb->logmap), j);
- assert(buffer != NULL);
- blockput(buffer);
- blockput(buffer);
- }
return ERR_PTR(err);
}
@@ -166,7 +172,8 @@ static void replay_done(struct replay *rp)
free_replay(rp);
sb->lognext = be32_to_cpu(sb->super.logcount);
- log_finish_cycle(sb);
+ replay_unpin_logblocks(sb, 0, sb->lognext);
+ log_finish_cycle(sb, 0);
}
typedef int (*replay_log_t)(struct replay *, struct buffer_head *);
@@ -504,7 +511,7 @@ static int replay_logblocks(struct replay *rp, replay_log_t replay_log_func)
sb->lognext = 0;
while (sb->lognext < logcount) {
trace("log block %i, blocknr %Lx, rollup %Lx", sb->lognext, rp->blocknrs[sb->lognext], rp->rollup_index);
- log_next(sb, 0);
+ log_next(sb);
err = replay_log_func(rp, sb->logbuf);
log_drop(sb);
diff --git a/fs/tux3/tux3.h b/fs/tux3/tux3.h
index c0bfb2a83037d..07405fdb6791a 100644
--- a/fs/tux3/tux3.h
+++ b/fs/tux3/tux3.h
@@ -793,10 +793,10 @@ void iget_if_dirty(struct inode *inode);
/* log.c */
extern unsigned log_size[];
-void log_next(struct sb *sb, int pin);
+void log_next(struct sb *sb);
void log_drop(struct sb *sb);
void log_finish(struct sb *sb);
-void log_finish_cycle(struct sb *sb);
+void log_finish_cycle(struct sb *sb, int discard);
int tux3_logmap_io(int rw, struct bufvec *bufvec);
void log_balloc(struct sb *sb, block_t block, unsigned count);
void log_bfree(struct sb *sb, block_t block, unsigned count);