Fixed append->modify->append bug.

Approximately doubled the speed of file reservations.

Reduced the compiled code size by about 100 bytes by removing redundant code.
This commit is contained in:
nvt-se 2009-05-11 16:35:49 +00:00
parent 74e9bc8789
commit 995e788d73
1 changed files with 43 additions and 62 deletions

View File

@ -54,9 +54,8 @@
#include "cfs/cfs-coffee.h" #include "cfs/cfs-coffee.h"
#include "dev/watchdog.h" #include "dev/watchdog.h"
#if COFFEE_PAGES_PER_SECTOR & (COFFEE_PAGES_PER_SECTOR - 1) #if COFFEE_START & (COFFEE_SECTOR_SIZE - 1)
#error COFFEE_PAGES_PER_SECTOR must be a power of two. #error COFFEE_START must point to the first byte in a sector.
#error Change COFFEE_PAGES_PER_SECTOR in cfs-coffee-arch.h.
#endif #endif
#define COFFEE_FD_FREE 0x0 #define COFFEE_FD_FREE 0x0
@ -323,7 +322,7 @@ next_file(coffee_page_t page, struct file_header *hdr)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static struct file * static struct file *
load_file(const char *name, struct file_header *hdr, coffee_page_t start) load_file(coffee_page_t start, struct file_header *hdr)
{ {
int i, unreferenced, free; int i, unreferenced, free;
struct file *file; struct file *file;
@ -342,18 +341,22 @@ load_file(const char *name, struct file_header *hdr, coffee_page_t start)
} }
} }
if(free != -1) { if(free == -1) {
i = free; if(unreferenced != -1) {
} else if(unreferenced != -1) { i = unreferenced;
i = unreferenced; } else {
} else { return NULL;
return NULL; }
} }
file = &coffee_files[i]; file = &coffee_files[i];
file->page = start; file->page = start;
file->end = UNKNOWN_OFFSET; file->end = UNKNOWN_OFFSET;
file->max_pages = hdr->max_pages; file->max_pages = hdr->max_pages;
file->flags = 0;
if(HDR_MODIFIED(*hdr)) {
file->flags |= COFFEE_FILE_MODIFIED;
}
file->next_log_record = -1; file->next_log_record = -1;
return file; return file;
@ -365,7 +368,7 @@ find_file(const char *name)
int i; int i;
struct file_header hdr; struct file_header hdr;
coffee_page_t page; coffee_page_t page;
/* First check if the file metadata is cached. */ /* First check if the file metadata is cached. */
for(i = 0; i < COFFEE_MAX_OPEN_FILES; i++) { for(i = 0; i < COFFEE_MAX_OPEN_FILES; i++) {
if(coffee_files[i].max_pages == 0) { if(coffee_files[i].max_pages == 0) {
@ -373,16 +376,16 @@ find_file(const char *name)
} }
read_header(&hdr, coffee_files[i].page); read_header(&hdr, coffee_files[i].page);
if(HDR_ACTIVE(hdr) && strcmp(name, hdr.name) == 0) { if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr) && strcmp(name, hdr.name) == 0) {
return &coffee_files[i]; return &coffee_files[i];
} }
} }
/* Scan the flash memory sequentially otherwise. */ /* Scan the flash memory sequentially otherwise. */
for(page = 0; page < COFFEE_PAGE_COUNT; page = next_file(page, &hdr)) { for(page = 0; page < COFFEE_PAGE_COUNT; page = next_file(page, &hdr)) {
read_header(&hdr, page); read_header(&hdr, page);
if(HDR_ACTIVE(hdr) && strcmp(name, hdr.name) == 0) { if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr) && strcmp(name, hdr.name) == 0) {
return load_file(name, &hdr, page); return load_file(page, &hdr);
} }
} }
@ -546,7 +549,7 @@ reserve(const char *name, coffee_page_t pages, int allow_duplicates)
PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n", PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n",
pages, page, name); pages, page, name);
file = load_file(name, &hdr, page); file = load_file(page, &hdr);
file->end = 0; file->end = 0;
watchdog_start(); watchdog_start();
@ -585,22 +588,19 @@ get_record_index(coffee_page_t log_page, uint16_t search_records,
uint16_t processed; uint16_t processed;
uint16_t batch_size; uint16_t batch_size;
int16_t match_index, i; int16_t match_index, i;
uint16_t record_count;
base = absolute_offset(log_page, sizeof(uint16_t) * search_records); base = absolute_offset(log_page, sizeof(uint16_t) * search_records);
record_count = search_records > COFFEE_LOG_TABLE_LIMIT ? batch_size = search_records > COFFEE_LOG_TABLE_LIMIT ?
COFFEE_LOG_TABLE_LIMIT : search_records; COFFEE_LOG_TABLE_LIMIT : search_records;
processed = 0; processed = 0;
match_index = -1; match_index = -1;
{ {
uint16_t indices[record_count]; uint16_t indices[batch_size];
while(processed < search_records && match_index < 0) { while(processed < search_records && match_index < 0) {
if(record_count + processed > search_records) { if(batch_size + processed > search_records) {
batch_size = search_records - processed; batch_size = search_records - processed;
} else {
batch_size = record_count;
} }
base -= batch_size * sizeof(indices[0]); base -= batch_size * sizeof(indices[0]);
@ -647,27 +647,10 @@ read_log_page(struct file_header *hdr, int16_t last_record, struct log_param *lp
return lp->size; return lp->size;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static unsigned char *
create_log_name(unsigned char *new, int max_size, unsigned char *old)
{
const unsigned char suffix[] = ".log";
int len;
len = strlen(old);
if(len > max_size - sizeof(suffix)) {
len = max_size - sizeof(suffix);
}
memcpy(new, old, len);
memcpy(&new[len], suffix, sizeof(suffix));
return new;
}
/*---------------------------------------------------------------------------*/
static coffee_page_t static coffee_page_t
create_log(struct file *file, struct file_header *hdr) create_log(struct file *file, struct file_header *hdr)
{ {
coffee_page_t log_page; coffee_page_t log_page;
unsigned char log_name[sizeof(hdr->name)];
uint16_t log_record_size, log_records; uint16_t log_record_size, log_records;
cfs_offset_t size; cfs_offset_t size;
struct file *log_file; struct file *log_file;
@ -677,9 +660,8 @@ create_log(struct file *file, struct file_header *hdr)
size = log_records * sizeof(uint16_t); /* Log index size. */ size = log_records * sizeof(uint16_t); /* Log index size. */
size += log_records * log_record_size; /* Log data size. */ size += log_records * log_record_size; /* Log data size. */
log_file = reserve(create_log_name(log_name, sizeof(log_name), hdr->name), log_file = reserve(hdr->name, page_count(size), 1);
page_count(size), 0); if(log_file == NULL) {
if(file == NULL) {
return INVALID_PAGE; return INVALID_PAGE;
} }
log_page = log_file->page; log_page = log_file->page;
@ -761,6 +743,7 @@ merge_log(coffee_page_t file_page, int extend)
hdr2.log_records = hdr.log_records; hdr2.log_records = hdr.log_records;
write_header(&hdr2, new_file->page); write_header(&hdr2, new_file->page);
new_file->flags &= ~COFFEE_FILE_MODIFIED;
new_file->end = offset; new_file->end = offset;
cfs_close(fd); cfs_close(fd);
@ -772,12 +755,12 @@ static int
find_next_record(struct file *file, coffee_page_t log_page, find_next_record(struct file *file, coffee_page_t log_page,
int log_records) int log_records)
{ {
int log_record, i, preferred_batch_size; int log_record, preferred_batch_size;
preferred_batch_size = log_records > COFFEE_LOG_TABLE_LIMIT ? preferred_batch_size = log_records > COFFEE_LOG_TABLE_LIMIT ?
COFFEE_LOG_TABLE_LIMIT : log_records; COFFEE_LOG_TABLE_LIMIT : log_records;
if(file->next_log_record == 0) { if(file->next_log_record == -1) {
/* The next log record is unknown. Search for it. */ /* The next log record is unknown. Search for it. */
uint16_t indices[preferred_batch_size]; uint16_t indices[preferred_batch_size];
uint16_t processed; uint16_t processed;
@ -790,12 +773,11 @@ find_next_record(struct file *file, coffee_page_t log_page,
COFFEE_READ(&indices, batch_size * sizeof(indices[0]), COFFEE_READ(&indices, batch_size * sizeof(indices[0]),
absolute_offset(log_page, processed * sizeof(indices[0]))); absolute_offset(log_page, processed * sizeof(indices[0])));
for(i = 0; i < batch_size && indices[i] != 0; i++); for(log_record = 0; log_record < batch_size; log_record++) {
log_record = i; if(indices[log_record] == 0) {
log_record += processed;
if(log_record < batch_size) { break;
log_record += processed; }
break;
} }
} }
} else { } else {
@ -852,7 +834,7 @@ write_log_page(struct file *file, struct log_param *lp)
lp_out.size = log_record_size; lp_out.size = log_record_size;
if((lp->offset > 0 || lp->size != log_record_size) && if((lp->offset > 0 || lp->size != log_record_size) &&
read_log_page(&hdr, file->next_log_record - 1, &lp_out) < 0) { read_log_page(&hdr, log_record, &lp_out) < 0) {
COFFEE_READ(copy_buf, sizeof(copy_buf), COFFEE_READ(copy_buf, sizeof(copy_buf),
absolute_offset(file->page, region * log_record_size)); absolute_offset(file->page, region * log_record_size));
} }
@ -1029,7 +1011,7 @@ cfs_read(int fd, void *buf, unsigned size)
lp.offset = base + offset; lp.offset = base + offset;
lp.buf = (char *)buf + offset; lp.buf = (char *)buf + offset;
lp.size = remains; lp.size = remains;
r = read_log_page(&hdr, file->next_log_record - 1, &lp); r = read_log_page(&hdr, file->next_log_record, &lp);
} }
/* Read from the original file if we cannot find the data in the log. */ /* Read from the original file if we cannot find the data in the log. */
if(r < 0) { if(r < 0) {
@ -1070,7 +1052,7 @@ cfs_write(int fd, const void *buf, unsigned size)
PRINTF("Extended the file at page %u\n", (unsigned)file->page); PRINTF("Extended the file at page %u\n", (unsigned)file->page);
} }
if(fdp->offset < file->end) { if(FILE_MODIFIED(file) || fdp->offset < file->end) {
remains = size; remains = size;
while(remains) { while(remains) {
lp.offset = fdp->offset; lp.offset = fdp->offset;
@ -1088,6 +1070,11 @@ cfs_write(int fd, const void *buf, unsigned size)
remains -= i; remains -= i;
fdp->offset += i; fdp->offset += i;
} }
if(fdp->offset > file->end) {
/* Update the original file's end with a dummy write. */
COFFEE_WRITE(buf, 1, absolute_offset(file->page, fdp->offset));
}
} else { } else {
COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset)); COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset));
fdp->offset += size; fdp->offset += size;
@ -1178,20 +1165,14 @@ cfs_coffee_configure_log(const char *filename, unsigned log_size,
int int
cfs_coffee_format(void) cfs_coffee_format(void)
{ {
int nsectors, i; int i;
nsectors = COFFEE_SECTOR_COUNT; PRINTF("Coffee: Formatting %d sectors", COFFEE_SECTOR_COUNT);
/* Reject format requests when the configuration is incorrect. */
if(nsectors < 1 || (COFFEE_START & (COFFEE_SECTOR_SIZE - 1))) {
return -1;
}
PRINTF("Coffee: Formatting %d sectors", nsectors);
*next_free = 0; *next_free = 0;
watchdog_stop(); watchdog_stop();
for(i = 0; i < nsectors; i++) { for(i = 0; i < COFFEE_SECTOR_COUNT; i++) {
COFFEE_ERASE(i); COFFEE_ERASE(i);
PRINTF("."); PRINTF(".");
} }