WIP
parent
b39ce6cd68
commit
8ecb27b379
2
STL
2
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.
|
* 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
|
(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
|
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
|
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
|
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>.
|
moving or skipping blocks based on <skip cost> and <full move cost>.
|
||||||
|
|
44
sftl.c
44
sftl.c
|
@ -55,10 +55,10 @@ struct sftl_dev {
|
||||||
u32 segs; // device size in segments
|
u32 segs; // device size in segments
|
||||||
u32 reserved_segs; // segments reserved for defragmentation during write
|
u32 reserved_segs; // segments reserved for defragmentation during write
|
||||||
u32 *map; // virtual-to-real cluster map
|
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 *ver; // cluster versions indexed by their virtual positions
|
||||||
u32 freeclust, freesegs; // free cluster count, free segment count
|
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
|
// Buffer to hold pending writes - will hold up to a complete segment
|
||||||
char *buf;
|
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->ver = sftl->ver[bio->bi_sector/clust_blocks]+1;
|
||||||
buf_map->checksum = sftl_map_checksum(*buf_map);
|
buf_map->checksum = sftl_map_checksum(*buf_map);
|
||||||
sftl->map[bio->bi_sector/clust_blocks] = sftl->nextfreeseg*seg_clust + sftl->buf_size;
|
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->ver[bio->bi_sector/clust_blocks] = buf_map->ver;
|
||||||
sftl->buf_size++;
|
sftl->buf_size++;
|
||||||
INFO("Write request (starting sector = %lu, count = %lu)",
|
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);
|
kfree(info);
|
||||||
}
|
}
|
||||||
// FIXME Correctly adjust free segment address
|
// 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
|
else
|
||||||
bio_endio(bio, 0);
|
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...
|
// FIXME: Need to defragment free space on the device...
|
||||||
}
|
}
|
||||||
// We'll start writing into a free segment
|
// 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);
|
INFO("Next free segment = %d", dev->nextfreeseg);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue