master
Vitaliy Filippov 2013-05-21 03:16:18 +04:00
parent b39ce6cd68
commit 8ecb27b379
2 changed files with 40 additions and 6 deletions

2
STL
View File

@ -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 <skip cost> and <full move cost>.

44
sftl.c
View File

@ -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);
}