From 8ecb27b379215f68513ffecc41ba992f1d1cbd13 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Tue, 21 May 2013 03:16:18 +0400 Subject: [PATCH] WIP --- STL | 2 +- sftl.c | 44 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/STL b/STL index 012baa6..69c8f0a 100644 --- a/STL +++ b/STL @@ -26,7 +26,7 @@ N = index block size / 16 = phys block size / 16 = 32 * When we wrap around the ring buffer end, we must find free place to continue writing. (and ideally it should be exactly after the previous end). There will always be enough reserved space to move blocks, because each partially occupied segment has at least 1 - free block, and we have N segments reserved. We just find first available segments that + free block, and we have N-1 segments reserved. We just find first available segments that have at least N free blocks in total, and move them to reserved space. If there is an offset between first moved block and the previous end of ring buffer, we decide between moving or skipping blocks based on and . diff --git a/sftl.c b/sftl.c index 11d5d94..97269a6 100644 --- a/sftl.c +++ b/sftl.c @@ -55,10 +55,10 @@ struct sftl_dev { u32 segs; // device size in segments u32 reserved_segs; // segments reserved for defragmentation during write u32 *map; // virtual-to-real cluster map - u32 *clust_map; // real-to-virtual cluster map + u32 *clust_map; // real-to-virtual cluster map, value=(1+virtual cluster number), 0 means empty u32 *ver; // cluster versions indexed by their virtual positions u32 freeclust, freesegs; // free cluster count, free segment count - u32 nextfreeseg; // next free available segment + u32 free_start, free_size; // current free segment sequence, always contains at least @seg_clust-1 segments // Buffer to hold pending writes - will hold up to a complete segment char *buf; @@ -159,7 +159,7 @@ static void sftl_make_request(struct request_queue *q, struct bio *bio) buf_map->ver = sftl->ver[bio->bi_sector/clust_blocks]+1; buf_map->checksum = sftl_map_checksum(*buf_map); sftl->map[bio->bi_sector/clust_blocks] = sftl->nextfreeseg*seg_clust + sftl->buf_size; - sftl->clust_map[sftl->nextfreeseg*seg_clust + sftl->buf_size] = bio->bi_sector/clust_blocks; + sftl->clust_map[sftl->nextfreeseg*seg_clust + sftl->buf_size] = 1 + bio->bi_sector/clust_blocks; sftl->ver[bio->bi_sector/clust_blocks] = buf_map->ver; sftl->buf_size++; INFO("Write request (starting sector = %lu, count = %lu)", @@ -184,7 +184,40 @@ static void sftl_make_request(struct request_queue *q, struct bio *bio) kfree(info); } // FIXME Correctly adjust free segment address - sftl->nextfreeseg++; + sftl->freeclust -= seg_clust; + sftl->freesegs--; + // Find @seg_clust free clusters to form a free segment + u32 defrag[seg_clust]; + u32 prev = sftl->nextfreeseg; + int n = 0, m, n_defrag = 0; + while (n < seg_clust) + { + i = prev; + do + { + i = (i+1) % sftl->segs; + } while (i != prev && !(m = free_clusters_count(i))); + BUG_ON(i == prev); // infinite loop prevented + n += m; + defrag[n_defrag++] = prev = i; + } + if (n_defrag > 1) + { + // Next free segment is fragmented + for (i = 0; i < n_defrag; i++) + { + for (j = 0; j < seg_clust; j++) + { + if (virt = sftl->clust_map[defrag[i]*seg_clust+j]) + { + @read(sftl, virt, buf); + @write(sftl, virt, buf); + Алё, а куда писать-то? + } + } + } + } + sftl->nextfreeseg = defrag[0]; } else bio_endio(bio, 0); @@ -516,7 +549,8 @@ static void read_maps(struct sftl_dev *dev) // FIXME: Need to defragment free space on the device... } // We'll start writing into a free segment - dev->nextfreeseg = (cur_free > max_free ? cur_first : max_first); + dev->free_start = (cur_free > max_free ? cur_first : max_first); + dev->free_size = (cur_free > max_free ? cur_free : max_free); INFO("Next free segment = %d", dev->nextfreeseg); kfree(buf); }