diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2013-01-19 20:03:34 +0900 |
---|---|---|
committer | Daniel Phillips <daniel@tux3.org> | 2013-01-19 20:03:34 +0900 |
commit | a7db9df0ba2a90483477a02cafe73c4b0346f068 (patch) | |
tree | ae55f4f28dc28506a918b76f0476f44163c6f86f | |
parent | d7cadd6e99a06a7c7bd9566cda388b9eccd74b97 (diff) | |
download | linux-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.c | 4 | ||||
-rw-r--r-- | fs/tux3/log.c | 27 | ||||
-rw-r--r-- | fs/tux3/replay.c | 39 | ||||
-rw-r--r-- | fs/tux3/tux3.h | 4 |
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); |