aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2013-12-04 20:34:34 +0900
committerDaniel Phillips <daniel@tux3.org>2013-12-04 20:34:34 +0900
commitf3b1992d6b453a42a124a9e820d63d644fd8d63f (patch)
treeb858961436b505882c7b8237efc51135c0f85727
parent99887d424554eacd1ec361b75d5926af36e362ca (diff)
downloadlinux-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.c52
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,