Skip to content

Commit

Permalink
Merge pull request dlbeer#12 from FreddieChopin/cache-improvements
Browse files Browse the repository at this point in the history
Cache improvements
  • Loading branch information
dlbeer authored Sep 13, 2019
2 parents 5f95bf2 + 140fe00 commit e55cfb3
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 34 deletions.
61 changes: 40 additions & 21 deletions ufat.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,21 @@ int ufat_cache_evict(struct ufat *uf, ufat_block_t start, ufat_block_t count)
return 0;
}

int ufat_cache_open(struct ufat *uf, ufat_block_t blk_index)
void ufat_cache_invalidate(struct ufat *uf, ufat_block_t start,
ufat_block_t count)
{
unsigned int i;

for (i = 0; i < uf->cache_size; i++) {
struct ufat_cache_desc *d = &uf->cache_desc[i];

if ((d->flags & UFAT_CACHE_FLAG_PRESENT) &&
d->index >= start && d->index < start + count)
d->flags = 0;
}
}

int ufat_cache_open(struct ufat *uf, ufat_block_t blk_index, int skip_read)
{
unsigned int i;
int oldest = -1;
Expand Down Expand Up @@ -139,22 +153,27 @@ int ufat_cache_open(struct ufat *uf, ufat_block_t blk_index)
i = oldest;
}

/* Read it in */
err = uf->dev->read(uf->dev, blk_index, 1, ufat_cache_data(uf, i));
if (err < 0) {
uf->cache_desc[i].flags = 0;
return err;
} else {
struct ufat_cache_desc *d = &uf->cache_desc[i];
if (skip_read == 0) {
/* Read it in */
err = uf->dev->read(uf->dev, blk_index, 1,
ufat_cache_data(uf, i));
if (err < 0) {
uf->cache_desc[i].flags = 0;
return err;
}

d->flags = UFAT_CACHE_FLAG_PRESENT;
d->index = blk_index;
d->seq = uf->next_seq++;
}
uf->stat.read++;
uf->stat.read_blocks++;
} else
memset(ufat_cache_data(uf, i), 0,
1 << uf->dev->log2_block_size);

struct ufat_cache_desc *d = &uf->cache_desc[i];
d->flags = UFAT_CACHE_FLAG_PRESENT;
d->index = blk_index;
d->seq = uf->next_seq++;

uf->stat.cache_miss++;
uf->stat.read++;
uf->stat.read_blocks++;

return i;
}
Expand Down Expand Up @@ -270,7 +289,7 @@ static int read_bpb(struct ufat *uf)
{
int idx;

idx = ufat_cache_open(uf, 0);
idx = ufat_cache_open(uf, 0, 0);
if (idx < 0)
return idx;

Expand Down Expand Up @@ -382,7 +401,7 @@ static int read_fat_byte(struct ufat *uf, unsigned int offset, uint8_t *out)
unsigned int r = offset & ((1 << uf->dev->log2_block_size) - 1);
int idx;

idx = ufat_cache_open(uf, uf->bpb.fat_start + b);
idx = ufat_cache_open(uf, uf->bpb.fat_start + b, 0);
if (idx < 0)
return idx;

Expand Down Expand Up @@ -439,7 +458,7 @@ static int read_fat16(struct ufat *uf, ufat_cluster_t index,
const unsigned int shift = uf->dev->log2_block_size - 1;
const unsigned int b = index >> shift;
const unsigned int r = index & ((1 << shift) - 1);
int i = ufat_cache_open(uf, uf->bpb.fat_start + b);
int i = ufat_cache_open(uf, uf->bpb.fat_start + b, 0);
uint16_t raw;

if (i < 0)
Expand Down Expand Up @@ -467,7 +486,7 @@ static int read_fat32(struct ufat *uf, ufat_cluster_t index,
const unsigned int shift = uf->dev->log2_block_size - 2;
const unsigned int b = index >> shift;
const unsigned int r = index & ((1 << shift) - 1);
int i = ufat_cache_open(uf, uf->bpb.fat_start + b);
int i = ufat_cache_open(uf, uf->bpb.fat_start + b, 0);
uint32_t raw;

if (i < 0)
Expand Down Expand Up @@ -512,7 +531,7 @@ static int write_fat_byte(struct ufat *uf, unsigned int offset,
int idx;
uint8_t *data;

idx = ufat_cache_open(uf, uf->bpb.fat_start + b);
idx = ufat_cache_open(uf, uf->bpb.fat_start + b, 0);
if (idx < 0)
return idx;

Expand Down Expand Up @@ -552,7 +571,7 @@ static int write_fat16(struct ufat *uf, ufat_cluster_t index,
const unsigned int shift = uf->dev->log2_block_size - 1;
const unsigned int b = index >> shift;
const unsigned int r = index & ((1 << shift) - 1);
int i = ufat_cache_open(uf, uf->bpb.fat_start + b);
int i = ufat_cache_open(uf, uf->bpb.fat_start + b, 0);

if (i < 0)
return i;
Expand All @@ -569,7 +588,7 @@ static int write_fat32(struct ufat *uf, ufat_cluster_t index,
const unsigned int shift = uf->dev->log2_block_size - 2;
const unsigned int b = index >> shift;
const unsigned int r = index & ((1 << shift) - 1);
int i = ufat_cache_open(uf, uf->bpb.fat_start + b);
int i = ufat_cache_open(uf, uf->bpb.fat_start + b, 0);

if (i < 0)
return i;
Expand Down
2 changes: 1 addition & 1 deletion ufat_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ static int create_empty_dir(struct ufat_directory *parent,

/* Get the first block of the dirent */
idx = ufat_cache_open(parent->uf,
cluster_to_block(&parent->uf->bpb, c));
cluster_to_block(&parent->uf->bpb, c), 0);
if (idx < 0) {
ufat_free_chain(parent->uf, c);
return idx;
Expand Down
8 changes: 4 additions & 4 deletions ufat_ent.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int ufat_write_raw_dirent(struct ufat_directory *dir,
if (dir->cur_block == UFAT_BLOCK_NONE)
return -UFAT_ERR_IO;

idx = ufat_cache_open(dir->uf, dir->cur_block);
idx = ufat_cache_open(dir->uf, dir->cur_block, 0);
if (idx < 0)
return idx;

Expand Down Expand Up @@ -140,7 +140,7 @@ int ufat_read_raw_dirent(struct ufat_directory *dir, uint8_t *data)
if (dir->cur_block == UFAT_BLOCK_NONE)
return 1;

idx = ufat_cache_open(dir->uf, dir->cur_block);
idx = ufat_cache_open(dir->uf, dir->cur_block, 0);
if (idx < 0)
return idx;

Expand Down Expand Up @@ -210,7 +210,7 @@ int ufat_init_dirent_cluster(struct ufat *uf, ufat_cluster_t c)
int i;

for (i = count - 1; i >= 0; i--) {
int idx = ufat_cache_open(uf, start + i);
int idx = ufat_cache_open(uf, start + i, 1);

if (idx < 0)
return idx;
Expand Down Expand Up @@ -644,7 +644,7 @@ int ufat_compare_name(const char *search_name, const char *dir_name,

int ufat_update_attributes(struct ufat *uf, struct ufat_dirent *ent)
{
int idx = ufat_cache_open(uf, ent->dirent_block);
int idx = ufat_cache_open(uf, ent->dirent_block, 0);
uint8_t *data;
struct ufat_dirent old;

Expand Down
12 changes: 5 additions & 7 deletions ufat_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ static int read_block_fragment(struct ufat_file *f, char *buf, ufat_size_t size)
if (!UFAT_CLUSTER_IS_PTR(f->cur_cluster))
return -UFAT_ERR_INVALID_CLUSTER;

i = ufat_cache_open(f->uf, cur_block);
i = ufat_cache_open(f->uf, cur_block, 0);
if (i < 0)
return i;

Expand Down Expand Up @@ -223,7 +223,7 @@ int ufat_file_read(struct ufat_file *f, void *buf, ufat_size_t size)

static int set_size(struct ufat_file *f, ufat_size_t s)
{
int idx = ufat_cache_open(f->uf, f->dirent_block);
int idx = ufat_cache_open(f->uf, f->dirent_block, 0);

if (idx < 0)
return idx;
Expand All @@ -238,7 +238,7 @@ static int set_size(struct ufat_file *f, ufat_size_t s)

static int set_start(struct ufat_file *f, ufat_cluster_t s)
{
int idx = ufat_cache_open(f->uf, f->dirent_block);
int idx = ufat_cache_open(f->uf, f->dirent_block, 0);
uint8_t *data;

if (idx < 0)
Expand Down Expand Up @@ -305,7 +305,7 @@ static int write_block_fragment(struct ufat_file *f, const char *buf,
((f->cur_pos >> log2_block_size) &
((1 << bpb->log2_blocks_per_cluster) - 1));

i = ufat_cache_open(f->uf, cur_block);
i = ufat_cache_open(f->uf, cur_block, 0);
if (i < 0)
return i;

Expand Down Expand Up @@ -347,9 +347,7 @@ static int write_blocks(struct ufat_file *f, const char *buf, ufat_size_t size)
* cache and perform a single large write.
*/
starting_block = cluster_to_block(bpb, f->cur_cluster) + block_offset;
i = ufat_cache_evict(uf, starting_block, requested_blocks);
if (i < 0)
return i;
ufat_cache_invalidate(uf, starting_block, requested_blocks);

i = uf->dev->write(uf->dev, starting_block, requested_blocks, buf);
if (i < 0)
Expand Down
49 changes: 48 additions & 1 deletion ufat_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,56 @@ static inline ufat_cluster_t block_to_cluster(const struct ufat_bpb *bpb,
}

/* Block IO via internal cache */
int ufat_cache_open(struct ufat *uf, ufat_block_t blk_index);

/**
* \brief Opens a block via cache.
*
* \pre `uf` is a valid pointer.
* \pre The filesystem pointed by `uf` is opened.
*
* \param [in] uf is a pointer to the filesystem
* \param [in] blk_index is the index of block which should be opened
* \param [in] skip_read selects the behavior when block is not present in the
* cache:
* - 0 - current contents of the block are read from the device;
* - not 0 - read operation is skipped and the cached contents are just zeroed -
* this is useful when the whole block is going to be overwritten anyway;
*
* \return cache index on success, negative error code (`ufat_error_t`)
* otherwise
*/

int ufat_cache_open(struct ufat *uf, ufat_block_t blk_index, int skip_read);

/**
* \brief Evicts (flushes) cached blocks which overlap with given range.
*
* \pre `uf` is a valid pointer.
* \pre The filesystem pointed by `uf` is opened.
*
* \param [in] uf is a pointer to the filesystem
* \param [in] start is the index of starting block of the range
* \param [in] count is the number of blocks in the range
*
* \return 0 on success, negative error code (`ufat_error_t`) otherwise
*/

int ufat_cache_evict(struct ufat *uf, ufat_block_t start, ufat_block_t count);

/**
* \brief Invalidates (drops) cached blocks which overlap with given range.
*
* \pre `uf` is a valid pointer.
* \pre The filesystem pointed by `uf` is opened.
*
* \param [in] uf is a pointer to the filesystem
* \param [in] start is the index of starting block of the range
* \param [in] count is the number of blocks in the range
*/

void ufat_cache_invalidate(struct ufat *uf, ufat_block_t start,
ufat_block_t count);

static inline void ufat_cache_write(struct ufat *uf, unsigned int cache_index)
{
uf->stat.cache_write++;
Expand Down

0 comments on commit e55cfb3

Please sign in to comment.