WIP fat extend file, write zeros to new clusters

This commit is contained in:
Travis Geiselbrecht
2022-09-05 22:37:47 -07:00
parent db19c46914
commit a2572e586f
5 changed files with 63 additions and 6 deletions

View File

@@ -148,6 +148,9 @@ static struct bcache_block *alloc_block(struct bcache *cache) {
LTRACEF("looking at %p, num %u\n", block, block->blocknum);
if (block->ref_count == 0) {
if (block->is_dirty) {
/* if the oldest block in the list that's available is dirty, write
* it back first.
*/
err = flush_block(cache, block);
if (err)
return NULL;

View File

@@ -175,8 +175,10 @@ static status_t fat_mark_entry(fat_fs *fat, uint32_t cluster, uint32_t val) {
// start_cluster is an existing cluster that it should link to (or 0 if its the first in the chain)
// count is number of clusters to allocate
// first and last cluster are the first and lastly allocated in the new part of the list (may be the same)
status_t fat_allocate_cluster_chain(fat_fs *fat, uint32_t start_cluster, uint32_t count, uint32_t *first_cluster, uint32_t *last_cluster) {
LTRACEF("fat %p, starting %u, count %u\n", fat, start_cluster, count);
status_t fat_allocate_cluster_chain(fat_fs *fat, uint32_t start_cluster, uint32_t count,
uint32_t *first_cluster, uint32_t *last_cluster,
bool zero_new_blocks) {
LTRACEF("fat %p, starting %u, count %u, zero %u\n", fat, start_cluster, count, zero_new_blocks);
DEBUG_ASSERT(fat->lock.is_held());
@@ -224,6 +226,11 @@ status_t fat_allocate_cluster_chain(fat_fs *fat, uint32_t start_cluster, uint32_
// its a free entry, allocate it and move on
LTRACEF("found free cluster %u, sector %u, offset %u\n", search_cluster, sector, fat_offset_in_sector);
// zero the cluster first
if (zero_new_blocks) {
fat_zero_cluster(fat, search_cluster);
}
// add it to the chain
if (prev_cluster > 0) {
// link the last cluster we had found before to this one.
@@ -319,6 +326,38 @@ ssize_t fat_read_cluster(fat_fs *fat, void *buf, uint32_t cluster) {
LTRACEF("buf %p, cluster %u\n", buf, cluster);
auto sector = fat_sector_for_cluster(fat, cluster);
return bio_read_block(fat->dev(), buf, sector, fat->info().sectors_per_cluster);
uint8_t *buf8 = (uint8_t *)buf;
for (size_t i = 0; i < fat->info().sectors_per_cluster; i++) {
status_t err = bcache_read_block(fat->bcache(), buf8, sector);
if (err < 0) {
return err;
}
buf8 += fat->info().bytes_per_sector;
sector++;
}
return NO_ERROR;
}
// zero a cluster, using the bcache
ssize_t fat_zero_cluster(fat_fs *fat, uint32_t cluster) {
DEBUG_ASSERT(fat->lock.is_held());
LTRACEF("cluster %u\n", cluster);
auto sector = fat_sector_for_cluster(fat, cluster);
for (size_t i = 0; i < fat->info().sectors_per_cluster; i++) {
status_t err = bcache_zero_block(fat->bcache(), sector);
if (err < 0) {
return err;
}
sector++;
}
return NO_ERROR;
}

View File

@@ -24,11 +24,14 @@ typedef void *fsfilecookie;
/* file allocation table parsing */
uint32_t fat_next_cluster_in_chain(fat_fs *fat, uint32_t cluster);
uint32_t fat_find_last_cluster_in_chain(fat_fs *fat, uint32_t starting_cluster);
status_t fat_allocate_cluster_chain(fat_fs *fat, uint32_t start_cluster, uint32_t count, uint32_t *first_cluster, uint32_t *last_cluster);
status_t fat_allocate_cluster_chain(fat_fs *fat, uint32_t start_cluster, uint32_t count,
uint32_t *first_cluster, uint32_t *last_cluster,
bool zero_new_blocks);
/* general io routines */
uint32_t fat_sector_for_cluster(fat_fs *fat, uint32_t cluster);
ssize_t fat_read_cluster(fat_fs *fat, void *buf, uint32_t cluster);
ssize_t fat_zero_cluster(fat_fs *fat, uint32_t cluster);
// general directory apis outside of an object
struct dir_entry {

View File

@@ -335,13 +335,15 @@ status_t fat_file::truncate_file_priv(uint64_t _len) {
// TODO: compartmentalize this cluster extension/shrinking so DIR code can reuse it
// TODO: write zeros to any partial blocks we're extending
// walk to the end of the existing cluster chain
const uint32_t existing_chain_end = fat_find_last_cluster_in_chain(fs_, start_cluster_);
uint32_t first_cluster;
uint32_t last_cluster;
status_t err = fat_allocate_cluster_chain(fs_, existing_chain_end, new_cluster_count - current_cluster_count,
&first_cluster, &last_cluster);
&first_cluster, &last_cluster, true);
LTRACEF("fat_allocate_cluster_chain returns %d, first_cluster %u, last_cluster %u\n", err, first_cluster, last_cluster);
if (err != NO_ERROR) {

View File

@@ -16,6 +16,7 @@
#include <malloc.h>
#include <string.h>
#include <endian.h>
#include <stdlib.h>
#include "fat_priv.h"
#include "fat_fs.h"
@@ -218,7 +219,12 @@ status_t fat_fs::mount(bdev_t *dev, fscookie **cookie) {
}
info->bytes_per_cluster = info->sectors_per_cluster * info->bytes_per_sector;
fat->bcache_ = bcache_create(fat->dev(), info->bytes_per_sector, 16);
int bcache_size = MIN(16, 64 * info->sectors_per_cluster);
dprintf(INFO, "FAT: creating bcache of %d entries of %u bytes\n", bcache_size, info->bytes_per_sector);
fat->bcache_ = bcache_create(fat->dev(), info->bytes_per_sector, bcache_size);
// we're okay, cancel our cleanup of the fat structure
ac2.cancel();
@@ -243,6 +249,10 @@ status_t fat_fs::unmount(fscookie *cookie) {
// TODO: handle unmounting when files/dirs are active
DEBUG_ASSERT(list_is_empty(&fat->file_list_));
if (LK_DEBUGLEVEL > INFO) {
bcache_dump(fat->bcache(), "FAT bcache ");
}
bcache_flush(fat->bcache());
bcache_destroy(fat->bcache());
}