diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2013-12-04 20:34:34 +0900 |
---|---|---|
committer | Daniel Phillips <daniel@tux3.org> | 2013-12-04 20:34:34 +0900 |
commit | f3b1992d6b453a42a124a9e820d63d644fd8d63f (patch) | |
tree | b858961436b505882c7b8237efc51135c0f85727 | |
parent | 99887d424554eacd1ec361b75d5926af36e362ca (diff) | |
download | linux-tux3-f3b1992d6b453a42a124a9e820d63d644fd8d63f.tar.gz |
tux3: Rewrite overwrite mode by btree_write()
New overwrite mode is handled by dleaf2_pre_write(). So, we don't need
to care overwrite mode in map_region2() anymore.
To implement, this adds "stop_at_hole" to __dleaf2_read(). If
"stop_at_hole" == true, __dleaf2_read() stops after read hole. With
this, we can get seg[] filled by order of non-hole range => hole range.
By using "stop_at_hole", we implement overwrite mode by following new
strategy,
1) read seg[] (after hole) by __dleaf2_read() in dleaf2_pre_write()
2) pass hole range to dleaf2_write()
Hole range can be handled by same way with rewrite mode. So, after
dleaf2_pre_write(), we adjust the key range to include only hole range.
With this, dleaf2_write() doesn't need to care about overwrite mode
almost all.
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r-- | fs/tux3/dleaf2.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/fs/tux3/dleaf2.c b/fs/tux3/dleaf2.c index fa77b8d262c33a..d3163a3dd22e6c 100644 --- a/fs/tux3/dleaf2.c +++ b/fs/tux3/dleaf2.c @@ -387,7 +387,8 @@ static int dleaf2_chop(struct btree *btree, tuxkey_t start, u64 len, void *leaf) /* Read extents */ static unsigned __dleaf2_read(struct btree *btree, tuxkey_t key_bottom, tuxkey_t key_limit, - struct dleaf2 *dleaf, struct btree_key_range *key) + struct dleaf2 *dleaf, struct btree_key_range *key, + int stop_at_hole) { struct dleaf_req *rq = container_of(key, struct dleaf_req, key); tuxkey_t key_start = key->start; @@ -434,6 +435,12 @@ static unsigned __dleaf2_read(struct btree *btree, tuxkey_t key_bottom, key_start += seg->count; key_len -= seg->count; rq->seg_cnt++; + + /* Stop if current is hole and next is segment */ + if (stop_at_hole) { + if (!seg->block && physical) + break; + } } while (key_len && rq->seg_cnt < rq->seg_max && dex + 1 < dex_limit); fill_seg: @@ -461,13 +468,52 @@ static int dleaf2_read(struct btree *btree, tuxkey_t key_bottom, struct dleaf2 *dleaf = leaf; unsigned len; - len = __dleaf2_read(btree, key_bottom, key_limit, dleaf, key); + len = __dleaf2_read(btree, key_bottom, key_limit, dleaf, key, 0); key->start += len; key->len -= len; return 0; } +static int dleaf2_pre_write(struct btree *btree, tuxkey_t key_bottom, + tuxkey_t key_limit, void *leaf, + struct btree_key_range *key) +{ + struct dleaf_req *rq = container_of(key, struct dleaf_req, key); + struct dleaf2 *dleaf = leaf; + + /* + * If overwrite mode, read exists segments. Then, if there are + * hole, allocate segment. + */ + if (rq->overwrite) { + unsigned len; + int last, hole_len; + + len = __dleaf2_read(btree, key_bottom, key_limit, dleaf, key,1); + last = rq->seg_cnt; + + /* Remove hole from seg[] */ + hole_len = 0; + while (last > rq->seg_idx && !rq->seg[last - 1].block) { + len -= rq->seg[last - 1].count; + hole_len += rq->seg[last - 1].count; + last--; + } + key->start += len; + key->len = hole_len; + rq->seg_idx = last; + rq->seg_cnt = last; + + /* If there is no hole, return exists segments */ + if (!hole_len) + return BTREE_DO_RETRY; + } + + return BTREE_DO_DIRTY; +} + + /* Resize dleaf2 from head */ static void dleaf2_resize(struct dleaf2 *dleaf, struct diskextent2 *head, int diff) @@ -789,7 +835,7 @@ struct btree_ops dtree2_ops = { .leaf_split = dleaf2_split, .leaf_merge = dleaf2_merge, .leaf_chop = dleaf2_chop, - .leaf_pre_write = noop_pre_write, + .leaf_pre_write = dleaf2_pre_write, .leaf_write = dleaf2_write, .leaf_read = dleaf2_read, .balloc = balloc, |