overwrite code...
parent
6e333dd219
commit
1206aa80b0
113
sftl.c
113
sftl.c
|
@ -106,12 +106,11 @@ struct sftl_flush_info
|
||||||
struct bio *next_bio;
|
struct bio *next_bio;
|
||||||
u32 random_free[seg_clust];
|
u32 random_free[seg_clust];
|
||||||
u32 random_found;
|
u32 random_found;
|
||||||
};
|
u32 overwrite_last_cluster;
|
||||||
|
u32 overwrite_total;
|
||||||
struct sftl_overwrite_info
|
u32 overwrite_current;
|
||||||
{
|
char overwrite_do_write;
|
||||||
struct sftl_flush_info *flush;
|
atomic_t overwrite_pending;
|
||||||
u32 cluster;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sftl_search_free_sequence(struct sftl_dev *sftl, u32 *out_cur_first, u32 *out_cur_free)
|
static void sftl_search_free_sequence(struct sftl_dev *sftl, u32 *out_cur_first, u32 *out_cur_free)
|
||||||
|
@ -183,6 +182,69 @@ static void sftl_search_freeable_sequence(struct sftl_dev *sftl, struct sftl_flu
|
||||||
*out_min_freeable_start = min_freeable_start;
|
*out_min_freeable_start = min_freeable_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sftl_continue_overwrite_callback(struct bio *bio, int err)
|
||||||
|
{
|
||||||
|
struct sftl_flush_info *info = bio->bi_private;
|
||||||
|
sftl_continue_overwrite(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sftl_continue_overwrite(struct sftl_flush_info *info)
|
||||||
|
{
|
||||||
|
u32 i, j, k;
|
||||||
|
struct sftl_dev *sftl = info->sftl;
|
||||||
|
info->overwrite_total -= info->overwrite_current;
|
||||||
|
info->overwrite_current = info->overwrite_total < sftl->buf_max ? info->overwrite_total : sftl->buf_max;
|
||||||
|
atomic_set(&info->overwrite_pending, info->overwrite_current);
|
||||||
|
for (k = info->overwrite_last_cluster; k < sftl->next_free_end*seg_clust && sftl->buf_size < sftl->buf_max; k++)
|
||||||
|
{
|
||||||
|
if (sftl->clust_map[k])
|
||||||
|
{
|
||||||
|
// Modify maps
|
||||||
|
struct sftl_map *buf_map = (struct sftl_map *)(sftl->buf + seg_clust*clust_sz) + sftl->buf_size;
|
||||||
|
u32 cluster = sftl->clust_map[k]-1;
|
||||||
|
buf_map->magic[0] = magic[0];
|
||||||
|
buf_map->magic[1] = magic[1];
|
||||||
|
buf_map->magic[2] = magic[2];
|
||||||
|
buf_map->is_erased = 0;
|
||||||
|
buf_map->block = cluster;
|
||||||
|
buf_map->ver = sftl->ver[cluster]+1;
|
||||||
|
buf_map->checksum = sftl_map_checksum(*buf_map);
|
||||||
|
sftl->map[cluster] = sftl->free_start_seg*seg_clust + sftl->buf_size;
|
||||||
|
sftl->clust_map[sftl->map[cluster]] = 1 + cluster;
|
||||||
|
sftl->ver[cluster] = buf_map->ver;
|
||||||
|
// Read into buffer - will write back from a callback
|
||||||
|
sftl->buf_size++;
|
||||||
|
if (sftl->buf_size >= sftl->buf_max || k == sftl->next_free_end*seg_clust-1)
|
||||||
|
{
|
||||||
|
info->overwrite_last_cluster = k+1;
|
||||||
|
info->overwrite_do_write = sftl->buf_size >= sftl->buf_max;
|
||||||
|
}
|
||||||
|
bio_submit_kern_seq(sftl->blkdev, sftl->buf + (sftl->buf_size-1)*clust*sz, clust_sz, GFP_KERNEL,
|
||||||
|
(min_freeable_start+i)*(seg_clust*clust_blocks+1) + j*clust_blocks, info, sftl_overwrite_one, READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sftl_overwrite_one(struct bio *bio, int err)
|
||||||
|
{
|
||||||
|
struct sftl_flush_info *info = bio->bi_private;
|
||||||
|
struct sftl_dev *sftl = info->sftl;
|
||||||
|
bio_put(bio);
|
||||||
|
if (!atomic_dec_and_test(&info->overwrite_pending))
|
||||||
|
{
|
||||||
|
if (info->overwrite_do_write)
|
||||||
|
{
|
||||||
|
bio_submit_kern_seq(sftl->blkdev, sftl->buf, seg_clust*clust_sz + phy_sz, GFP_KERNEL,
|
||||||
|
sftl->free_start_seg*(seg_clust*clust_sz) + phy_sz, info, sftl_continue_overwrite_callback, READ);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If cleaning doesn't compose a full segment, we won't write it
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Callback called after flushing buffer the first time during flush
|
// Callback called after flushing buffer the first time during flush
|
||||||
static void sftl_continue_flush(struct bio *bio, int err)
|
static void sftl_continue_flush(struct bio *bio, int err)
|
||||||
{
|
{
|
||||||
|
@ -207,6 +269,7 @@ static void sftl_continue_flush(struct bio *bio, int err)
|
||||||
sftl->next_free_start = 0;
|
sftl->next_free_start = 0;
|
||||||
sftl->next_free_end = 0;
|
sftl->next_free_end = 0;
|
||||||
}
|
}
|
||||||
|
// Finish flushing and complete next_bio
|
||||||
}
|
}
|
||||||
else if (sftl->free_end_seg - sftl->free_start_seg <= seg_clust-1)
|
else if (sftl->free_end_seg - sftl->free_start_seg <= seg_clust-1)
|
||||||
{
|
{
|
||||||
|
@ -229,42 +292,12 @@ static void sftl_continue_flush(struct bio *bio, int err)
|
||||||
{
|
{
|
||||||
// Best freeable sequence has at least 1 free segment in total
|
// Best freeable sequence has at least 1 free segment in total
|
||||||
// Free it and continue writing
|
// Free it and continue writing
|
||||||
char *buf = sftl->buf;
|
info->overwrite_total = min_freeable_cost;
|
||||||
struct sftl_overwrite_info *ow;
|
info->overwrite_current = 0;
|
||||||
u32 cluster;
|
info->overwrite_last_cluster = min_freeable_start*seg_clust;
|
||||||
sftl->next_free_start = min_freeable_start;
|
sftl->next_free_start = min_freeable_start;
|
||||||
sftl->next_free_end = min_freeable_start+seg_clust;
|
sftl->next_free_end = min_freeable_start+seg_clust;
|
||||||
for (k = min_freeable_start*seg_clust, i = 0; i < seg_clust; i++)
|
sftl_continue_overwrite(info);
|
||||||
{
|
|
||||||
for (j = 0; j < seg_clust; j++, k++)
|
|
||||||
{
|
|
||||||
if (sftl->clust_map[k])
|
|
||||||
{
|
|
||||||
// Modify maps
|
|
||||||
struct sftl_map *buf_map = (struct sftl_map *)(sftl->buf + seg_clust*clust_sz) + sftl->buf_size;
|
|
||||||
cluster = sftl->clust_map[k]-1;
|
|
||||||
buf_map->magic[0] = magic[0];
|
|
||||||
buf_map->magic[1] = magic[1];
|
|
||||||
buf_map->magic[2] = magic[2];
|
|
||||||
buf_map->is_erased = 0;
|
|
||||||
buf_map->block = cluster;
|
|
||||||
buf_map->ver = sftl->ver[cluster]+1;
|
|
||||||
buf_map->checksum = sftl_map_checksum(*buf_map);
|
|
||||||
sftl->map[cluster] = sftl->free_start_seg*seg_clust + sftl->buf_size;
|
|
||||||
sftl->clust_map[sftl->map[cluster]] = 1 + cluster;
|
|
||||||
sftl->ver[cluster] = buf_map->ver;
|
|
||||||
// Read into buffer
|
|
||||||
ow = kmalloc(sizeof(struct sftl_overwrite_info));
|
|
||||||
ow->info = info;
|
|
||||||
ow->cluster = k;
|
|
||||||
bio_submit_kern_seq(sftl->blkdev, buf + sftl->buf_size*clust*sz, clust_sz, GFP_KERNEL,
|
|
||||||
min_freeable_start*(seg_clust*clust_blocks+1) + j*clust_blocks, ow, sftl_overwrite_one, READ);
|
|
||||||
sftl->buf_size++;
|
|
||||||
//// Then write back from a callback
|
|
||||||
//WRITE(sftl, sftl->clust_map[k]-1, buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue