aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2013-12-03 20:16:03 +0900
committerDaniel Phillips <daniel@tux3.org>2013-12-03 20:16:03 +0900
commit71827018ba15f847402ba838a1ce0bb354545619 (patch)
tree284f1684284644dd5ac6a88ba24ed917fdd98753
parent8e29513e2ceb618e6d9443138c7c7e522e32ec30 (diff)
downloadlinux-tux3-71827018ba15f847402ba838a1ce0bb354545619.tar.gz
tux3: Implement ->seg_find() and ->seg_alloc() for new dleaf2_write()
This implements ->seg_find() and ->seg_alloc() for new dleaf2_write(). FIXME: current implement is using bfree() to shrink seg[]. However, we should avoid to modify bitmap. For example, ->seg_find() just check available blocks, and ->seg_alloc() modify bitmap actually. Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r--fs/tux3/filemap.c107
1 files changed, 54 insertions, 53 deletions
diff --git a/fs/tux3/filemap.c b/fs/tux3/filemap.c
index 9023d7d53a5127..5d054fe68d4d0c 100644
--- a/fs/tux3/filemap.c
+++ b/fs/tux3/filemap.c
@@ -357,78 +357,79 @@ static void seg_free(struct btree *btree, block_t block, unsigned count)
}
/*
- * Callback to allocate blocks to ->seg. dleaf is doing to write segs,
- * now we have to assign physical address to segs.
+ * FIXME: Use balloc_find() and balloc_modify(). Use multiple segment
+ * allocation
*/
-static int seg_alloc(struct btree *btree, struct dleaf_req *rq,
- int write_segs, int seg_state)
+static int seg_find(struct btree *btree, struct dleaf_req *rq,
+ int space, unsigned seg_len, unsigned *alloc_len)
{
struct sb *sb = btree->sb;
- struct block_segment tmp, *seg = rq->seg;
- int i, partial = 0;
+ struct block_segment *seg, *limit;
+ int seg_state, len = seg_len;
+ int err = 0;
- assert(rq->seg_idx + write_segs <= rq->seg_max);
+ assert(rq->seg_idx == rq->seg_cnt);
- for (i = rq->seg_idx; i < rq->seg_idx + write_segs; i++) {
- int err;
+ /* If overwrite mode, set SEG_NEW to allocated seg */
+ seg_state = rq->overwrite ? BLOCK_SEG_NEW : 0;
- if (seg[i].state != BLOCK_SEG_HOLE)
- continue;
+ limit = min(rq->seg + rq->seg_idx + space, rq->seg + rq->seg_max);
+ for (seg = rq->seg + rq->seg_idx; seg < limit && len; seg++) {
+ struct block_segment tmp;
- err = balloc_partial(sb, seg[i].count, &tmp, 1);
+ err = balloc_partial(sb, len, &tmp, 1);
if (err) {
assert(err != -ENOSPC); /* frontend reservation bug */
- return err;
- }
-
- /*
- * Partially allocated. Make space and adjust for
- * separated segments.
- */
- if (tmp.count != seg[i].count) {
- int size;
-
- if (rq->seg_cnt == rq->seg_max)
- size = (rq->seg_cnt - i - 1) * sizeof(*seg);
- else {
- size = (rq->seg_cnt - i) * sizeof(*seg);
- rq->seg_cnt++;
- write_segs++;
- }
- memmove(&seg[i + 1], &seg[i], size);
- /* Update a rest of separated segment */
- seg[i + 1].count = seg[i].count - tmp.count;
-
- partial = 1;
+ rq->seg_cnt = rq->seg_idx;
+ break;
}
- seg[i] = tmp;
- log_balloc(sb, seg[i].block, seg[i].count);
+ seg->block = tmp.block;
+ seg->count = tmp.count;
+ seg->state = seg_state;
- seg[i].state = seg_state;
+ len -= tmp.count;
+ }
+ if (err) {
+ struct block_segment *p;
+ for (p = rq->seg + rq->seg_idx; p < seg; p++)
+ bfree(sb, p->block, p->count);
+ return err;
}
- return partial;
-}
+ rq->seg_cnt = seg - rq->seg;
+ *alloc_len = seg_len - len;
-static int overwrite_seg_alloc(struct btree *btree, struct dleaf_req *rq,
- unsigned write_segs)
-{
- /* If overwrite mode, set SEG_NEW to allocated seg */
- return seg_alloc(btree, rq, write_segs, BLOCK_SEG_NEW);
+ return 0;
}
-static int redirect_seg_alloc(struct btree *btree, struct dleaf_req *rq,
- unsigned write_segs)
+/*
+ * Callback to allocate blocks to ->seg. dleaf is doing to write segs,
+ * now we have to assign physical address to segs.
+ */
+static int seg_alloc(struct btree *btree, struct dleaf_req *rq,
+ unsigned seg_len)
{
- /* If redirect mode, doesn't set SEG_NEW to allocated seg */
- return seg_alloc(btree, rq, write_segs, 0);
-}
+ struct sb *sb = btree->sb;
+ struct block_segment *seg = rq->seg + rq->seg_idx;
+ struct block_segment *limit = rq->seg + rq->seg_cnt;
+
+ while (seg < limit) {
+ if (seg_len) {
+ log_balloc(sb, seg->block, seg->count);
+ assert(seg_len >= seg->count);
+ seg_len -= seg->count;
+ } else {
+ /* FIXME: replace with balloc_modify() */
+ bfree(sb, seg->block, seg->count);
+ sb->nextblock = seg->block;
+ rq->seg_cnt--;
+ }
+ seg++;
+ }
-static int (*seg_alloc_funs[])(struct btree *, struct dleaf_req *, unsigned) = {
- [MAP_WRITE] = overwrite_seg_alloc,
- [MAP_REDIRECT] = redirect_seg_alloc,
-};
+ return 0;
+}
/* map_region() by using dleaf2 */
static int map_region2(struct inode *inode, block_t start, unsigned count,