WIP fat extend file, write zeros to new clusters
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user