Convert algorithm into commented-out not-working-yet code :)
parent
73351b46dc
commit
d9a12d2ace
181
sftl.c
181
sftl.c
|
@ -141,7 +141,7 @@ static void sftl_make_request(struct request_queue *q, struct bio *bio)
|
|||
}
|
||||
else
|
||||
{
|
||||
// cluster on the disk
|
||||
// cluster needs to be read from disk
|
||||
struct block_device *bdev = sftl->blkdev;
|
||||
struct request_queue *q = bdev_get_queue(bdev);
|
||||
struct bio *bb = bio_alloc(GFP_KERNEL, 1);
|
||||
|
@ -205,54 +205,163 @@ static void sftl_make_request(struct request_queue *q, struct bio *bio)
|
|||
sftl->freesegs--;
|
||||
// FIXME Correctly adjust free segment address
|
||||
sftl->free_start_seg++;
|
||||
// Algorithm:
|
||||
// 0) If no free clusters are left on the device except reserved ones => goto FAIL
|
||||
// 1) If more than N-1 free segments are left in current sequence => goto END
|
||||
// 2) Try to find a free sequence of N segments
|
||||
// If there is one => remember it as "next free sequence", goto END
|
||||
// 3) Try to find a freeable sequence of N segments
|
||||
// If there is one => free it using current N-1 free segments,
|
||||
// and remember it as the current.
|
||||
// 4) Move data from a segment adjacent to current free sequence
|
||||
// to random free places on the device. This operation ensures that
|
||||
// reserved segments are never fragmented. It may fail if nearly ALL
|
||||
// clusters are occupied on the device. This should be ignored,
|
||||
// because we have N-1 segments reserved and we know that we'll
|
||||
// definitely have at least N free clusters on the device after writing
|
||||
// one segment of the reserved ones.
|
||||
// END) Continue writing as usual - into a next free segment in sequence.
|
||||
// FAIL) This shouldn't happen. Abort writing.
|
||||
/*
|
||||
u32 defrag[seg_clust];
|
||||
u32 prev = sftl->free_start_seg;
|
||||
int n = 0, m, n_defrag = 0;
|
||||
while (n < seg_clust)
|
||||
Algorithm:
|
||||
1) If less than reserved clusters are free on the device
|
||||
=> This shouldn't happen. Abort writing.
|
||||
2) If a "next free sequence" is already remembered, and there are
|
||||
no free segments left in current free sequence
|
||||
=> Switch free sequence to "next", write as usual
|
||||
3) If more than N-1 free segments are left in current sequence,
|
||||
or if a "next free sequence" is already remembered
|
||||
=> Write as usual
|
||||
4) Try to find a free sequence of N segments. If there is one
|
||||
=> Remember it as a "next free sequence", write as usual
|
||||
5) Try to find a freeable sequence of N segments. If there is one
|
||||
=> Free it using current N-1 free segments, make it current
|
||||
and write as usual
|
||||
6) If there is no complete freeable sequence found
|
||||
=> Move data from a segment adjacent to current free sequence
|
||||
to random free clusters on the device.
|
||||
|
||||
This operation ensures that reserved segments are never fragmented.
|
||||
It may fail if nearly ALL clusters are occupied on the device.
|
||||
This is OK because we know that we'll definitely have at least N
|
||||
free clusters on the device after writing any of the reserved segments.
|
||||
*/
|
||||
/*
|
||||
BUG_ON(dev->freeclust < dev->reserved_segs*seg_clust);
|
||||
if (sftl->next_free_end)
|
||||
{
|
||||
i = prev;
|
||||
do
|
||||
if (sftl->free_end_seg <= sftl->free_start_seg)
|
||||
{
|
||||
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;
|
||||
sftl->free_start_seg = sftl->next_free_start;
|
||||
sftl->free_end_seg = sftl->next_free_end;
|
||||
sftl->next_free_start = 0;
|
||||
sftl->next_free_end = 0;
|
||||
}
|
||||
}
|
||||
if (n_defrag > 1)
|
||||
else if (sftl->free_end_seg - sftl->free_start_seg <= seg_clust-1)
|
||||
{
|
||||
// Next free segment is fragmented
|
||||
for (i = 0; i < n_defrag; i++)
|
||||
// Search for a sequence of at least @seg_clust free segments
|
||||
u32 i, j, cur_first = 0, cur_free = 0;
|
||||
for (i = 0; i < sftl->segs; i++)
|
||||
{
|
||||
for (j = 0; j < seg_clust; j++)
|
||||
{
|
||||
if (virt = sftl->clust_map[defrag[i]*seg_clust+j])
|
||||
if (sftl->clust_map[i*seg_clust+j])
|
||||
{
|
||||
@read(sftl, virt, buf);
|
||||
@write(sftl, virt, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == seg_clust)
|
||||
{
|
||||
if (cur_free)
|
||||
{
|
||||
cur_free++;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_first = i;
|
||||
cur_free = 1;
|
||||
}
|
||||
}
|
||||
else if (cur_free >= seg_clust)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_free = 0;
|
||||
}
|
||||
}
|
||||
if (cur_free)
|
||||
{
|
||||
// If found, remember as next and continue writing into current sequence
|
||||
sftl->next_free_start = cur_first;
|
||||
sftl->next_free_end = cur_first+cur_free;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search for a freeable sequence
|
||||
u32 random_free[seg_clust], random_found = 0;
|
||||
u32 min_freeable_start = 0, min_freeable_cost = seg_clust*seg_clust, cur_freeable_cost = 0;
|
||||
for (i = 0; i < sftl->segs; i++)
|
||||
{
|
||||
for (j = 0; j < seg_clust; j++)
|
||||
{
|
||||
if (i >= seg_clust && sftl->clust_map[i*seg_clust+j - seg_clust*seg_clust])
|
||||
{
|
||||
cur_freeable--;
|
||||
}
|
||||
if (sftl->clust_map[i*seg_clust+j])
|
||||
{
|
||||
cur_freeable++;
|
||||
}
|
||||
else if (random_found < seg_clust)
|
||||
{
|
||||
random_free[random_found++] = i*seg_clust+j;
|
||||
}
|
||||
}
|
||||
if (i >= seg_clust-1 && cur_freeable_cost < min_freeable_cost)
|
||||
{
|
||||
min_freeable_cost = cur_freeable_cost;
|
||||
min_freeable_start = i-seg_clust+1;
|
||||
}
|
||||
}
|
||||
if (min_freeable_cost < seg_clust*(seg_clust-1))
|
||||
{
|
||||
// Best freeable sequence found -> free it and continue writing
|
||||
sftl->next_free_start = min_freeable_start;
|
||||
sftl->next_free_end = min_freeable_start+seg_clust;
|
||||
for (k = min_freeable_start*seg_clust, i = 0; i < seg_clust; i++)
|
||||
{
|
||||
for (j = 0; j < seg_clust; j++, k++)
|
||||
{
|
||||
if (sftl->clust_map[k])
|
||||
{
|
||||
READ(sftl, sftl->clust_map[k]-1, buf);
|
||||
WRITE(sftl, sftl->clust_map[k]-1, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move data into random free clusters
|
||||
if (sftl->free_end_seg < sftl->segs)
|
||||
{
|
||||
next_seg = sftl->free_end_seg;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_seg = sftl->free_start_seg-1;
|
||||
}
|
||||
for (j = 0, i = 0; i < seg_clust && j < random_found; i++)
|
||||
{
|
||||
if (sftl->clust_map[next_seg*seg_clust + i])
|
||||
{
|
||||
u32 mv = sftl->clust_map[next_seg*seg_clust + i]-1;
|
||||
READ(sftl, mv, buf);
|
||||
WRITE_SINGLE(sftl, mv, random_free[j++], buf);
|
||||
}
|
||||
}
|
||||
if (i >= seg_clust)
|
||||
{
|
||||
// Adjacent segment freed!
|
||||
sftl->freesegs++;
|
||||
if (sftl->free_end_seg < sftl->segs)
|
||||
{
|
||||
sftl->free_end_seg++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sftl->free_start_seg--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sftl->free_start_seg = defrag[0];
|
||||
*/
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue