added function for getting coffee's fd_set address and size

This commit is contained in:
fros4943 2009-01-23 16:27:49 +00:00
parent b258a99e22
commit 7e5047012b
2 changed files with 49 additions and 40 deletions

View file

@ -32,7 +32,7 @@
/** /**
* \file * \file
* Coffee: A flash file system for memory-contrained sensor systems. * Coffee: A flash file system for memory-constrained sensor systems.
* \author * \author
* Nicolas Tsiftes <nvt@sics.se> * Nicolas Tsiftes <nvt@sics.se>
*/ */
@ -46,7 +46,7 @@
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#define DEBUG 0 #define DEBUG 1
#if DEBUG #if DEBUG
#include <stdio.h> #include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__) #define PRINTF(...) printf(__VA_ARGS__)
@ -162,7 +162,7 @@ get_sector_status(uint16_t sector, coffee_page_t *active,
struct file_header hdr; struct file_header hdr;
coffee_page_t jump; coffee_page_t jump;
int i; int i;
*active = *free = *obsolete = 0; *active = *free = *obsolete = 0;
if(sector == 0) { if(sector == 0) {
skip_pages = 0; skip_pages = 0;
@ -184,7 +184,7 @@ get_sector_status(uint16_t sector, coffee_page_t *active,
} else { } else {
*obsolete = skip_pages; *obsolete = skip_pages;
/* Split an obsolete file starting in the previous sector and mark /* Split an obsolete file starting in the previous sector and mark
the following pages as isolated. */ the following pages as isolated. */
offset = sector_start; offset = sector_start;
for(i = 0; i < skip_pages; i++) { for(i = 0; i < skip_pages; i++) {
@ -200,7 +200,7 @@ get_sector_status(uint16_t sector, coffee_page_t *active,
offset = sector_start + (skip_pages * COFFEE_PAGE_SIZE); offset = sector_start + (skip_pages * COFFEE_PAGE_SIZE);
end = (sector + 1) * COFFEE_SECTOR_SIZE; end = (sector + 1) * COFFEE_SECTOR_SIZE;
jump = 0; jump = 0;
while(offset < end) { while(offset < end) {
COFFEE_READ(&hdr, sizeof(hdr), offset); COFFEE_READ(&hdr, sizeof(hdr), offset);
last_pages_are_active = 0; last_pages_are_active = 0;
@ -220,7 +220,7 @@ get_sector_status(uint16_t sector, coffee_page_t *active,
} }
offset += jump * COFFEE_PAGE_SIZE; offset += jump * COFFEE_PAGE_SIZE;
} }
skip_pages = *active + *obsolete - COFFEE_PAGES_PER_SECTOR; skip_pages = *active + *obsolete - COFFEE_PAGES_PER_SECTOR;
if(skip_pages > 0) { if(skip_pages > 0) {
if(last_pages_are_active) { if(last_pages_are_active) {
@ -235,7 +235,7 @@ static void
dir_cache_add(char c, coffee_offset_t page) dir_cache_add(char c, coffee_offset_t page)
{ {
int i; int i;
for(i = 0; i < COFFEE_DIR_CACHE_ENTRIES; i++) { for(i = 0; i < COFFEE_DIR_CACHE_ENTRIES; i++) {
if(dir_cache[i].filename_start == '\0') { if(dir_cache[i].filename_start == '\0') {
dir_cache[i].filename_start = c; dir_cache[i].filename_start = c;
@ -249,11 +249,11 @@ static void
dir_cache_del(coffee_offset_t page) dir_cache_del(coffee_offset_t page)
{ {
int i; int i;
for(i = 0; i < COFFEE_DIR_CACHE_ENTRIES; i++) { for(i = 0; i < COFFEE_DIR_CACHE_ENTRIES; i++) {
if(dir_cache[i].page == page) { if(dir_cache[i].page == page) {
dir_cache[i].filename_start = '\0'; dir_cache[i].filename_start = '\0';
} }
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -304,7 +304,7 @@ find_file(const char *name)
} else if(COFFEE_FILE_OBSOLETE(hdr)) { } else if(COFFEE_FILE_OBSOLETE(hdr)) {
page += hdr.max_pages; page += hdr.max_pages;
} else { } else {
/* It follows from the properties of the page allocation algorithm /* It follows from the properties of the page allocation algorithm
that if a free page is encountered, then the rest of the sector that if a free page is encountered, then the rest of the sector
is also free. */ is also free. */
page = (page + COFFEE_PAGES_PER_SECTOR) & ~(COFFEE_PAGES_PER_SECTOR - 1); page = (page + COFFEE_PAGES_PER_SECTOR) & ~(COFFEE_PAGES_PER_SECTOR - 1);
@ -373,7 +373,7 @@ find_offset_in_file(int first_page)
* An important implication of this is that if the last written bytes * An important implication of this is that if the last written bytes
* are zeroes, then these are skipped from the calculation. * are zeroes, then these are skipped from the calculation.
*/ */
for(page = first_page + range_end; page >= first_page; page--) { for(page = first_page + range_end; page >= first_page; page--) {
watchdog_periodic(); watchdog_periodic();
COFFEE_READ(buf, sizeof(buf), page * COFFEE_PAGE_SIZE); COFFEE_READ(buf, sizeof(buf), page * COFFEE_PAGE_SIZE);
@ -396,7 +396,7 @@ find_contiguous_pages(coffee_page_t wanted)
{ {
coffee_page_t page, start; coffee_page_t page, start;
struct file_header hdr; struct file_header hdr;
start = -1; start = -1;
for(page = 0; page < COFFEE_PAGE_COUNT;) { for(page = 0; page < COFFEE_PAGE_COUNT;) {
read_header(&hdr, page); read_header(&hdr, page);
@ -427,9 +427,9 @@ cfs_garbage_collect(void)
coffee_page_t active_pages, free_pages, obsolete_pages; coffee_page_t active_pages, free_pages, obsolete_pages;
watchdog_stop(); watchdog_stop();
PRINTF("Coffee: Running the file system garbage collector...\n"); PRINTF("Coffee: Running the file system garbage collector...\n");
/* /*
* The garbage collector erases as many sectors as possible. A sector is * The garbage collector erases as many sectors as possible. A sector is
* erasable if there are only free or obsolete pages in it. * erasable if there are only free or obsolete pages in it.
*/ */
@ -456,13 +456,13 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds)
if(!COFFEE_FILE_ACTIVE(hdr)) { if(!COFFEE_FILE_ACTIVE(hdr)) {
return -1; return -1;
} }
if(remove_log && COFFEE_FILE_MODIFIED(hdr)) { if(remove_log && COFFEE_FILE_MODIFIED(hdr)) {
if (remove_by_page(hdr.log_page, 0, 0) < 0) { if (remove_by_page(hdr.log_page, 0, 0) < 0) {
return -1; return -1;
} }
} }
dir_cache_del(page); dir_cache_del(page);
hdr.flags |= COFFEE_FLAG_OBSOLETE; hdr.flags |= COFFEE_FLAG_OBSOLETE;
write_header(&hdr, page); write_header(&hdr, page);
@ -549,7 +549,7 @@ modify_log_buffer(uint16_t log_record_size,
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int static int
get_record_index(coffee_page_t log_page, uint16_t search_records, get_record_index(coffee_page_t log_page, uint16_t search_records,
uint16_t region) uint16_t region)
{ {
coffee_offset_t base; coffee_offset_t base;
@ -560,7 +560,7 @@ get_record_index(coffee_page_t log_page, uint16_t search_records,
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 ? record_count = 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;
@ -610,7 +610,7 @@ read_log_page(struct file_header *hdr, int16_t last_record, struct log_param *lp
return -1; return -1;
} }
base = hdr->log_page * COFFEE_PAGE_SIZE; base = hdr->log_page * COFFEE_PAGE_SIZE;
base += sizeof(struct file_header) + log_records * sizeof(region); base += sizeof(struct file_header) + log_records * sizeof(region);
base += (coffee_offset_t)match_index * log_record_size; base += (coffee_offset_t)match_index * log_record_size;
base += lp->offset; base += lp->offset;
@ -631,7 +631,7 @@ create_log_name(unsigned char *new, int max_size, unsigned char *old)
} }
memcpy(new, old, len); memcpy(new, old, len);
memcpy(&new[len], suffix, sizeof(suffix)); memcpy(&new[len], suffix, sizeof(suffix));
return new; return new;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -644,7 +644,7 @@ create_log(coffee_page_t file_page, struct file_header *hdr)
coffee_offset_t size; coffee_offset_t size;
int i; int i;
adjust_log_config(hdr, &log_record_size, &log_records); adjust_log_config(hdr, &log_record_size, &log_records);
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. */
@ -692,7 +692,7 @@ merge_log(coffee_page_t file_page, int extend)
* already been calculated with in the previous reservation. * already been calculated with in the previous reservation.
*/ */
max_pages = hdr.max_pages * (1 << extend); max_pages = hdr.max_pages * (1 << extend);
new_file_page = reserve(hdr.name, max_pages, 1); new_file_page = reserve(hdr.name, max_pages, 1);
if(new_file_page == INVALID_PAGE) { if(new_file_page == INVALID_PAGE) {
cfs_close(fd); cfs_close(fd);
return -1; return -1;
@ -714,7 +714,7 @@ merge_log(coffee_page_t file_page, int extend)
} }
} while(n != 0); } while(n != 0);
if(remove_by_page(file_page, 1, 0) < 0) { if(remove_by_page(file_page, 1, 0) < 0) {
remove_by_page(new_file_page, 0, 0); remove_by_page(new_file_page, 0, 0);
cfs_close(fd); cfs_close(fd);
return -1; return -1;
@ -774,7 +774,7 @@ find_next_record(struct file_desc *fdp, coffee_page_t log_page,
log_record += processed; log_record += processed;
break; break;
} }
} }
} else { } else {
log_record = fdp->next_log_record; log_record = fdp->next_log_record;
} }
@ -834,9 +834,9 @@ write_log_page(struct file_desc *fdp, struct log_param *lp)
COFFEE_READ(copy_buf, sizeof(copy_buf), COFFEE_READ(copy_buf, sizeof(copy_buf),
absolute_offset(fdp->file_page, region * log_record_size)); absolute_offset(fdp->file_page, region * log_record_size));
} }
memcpy((char *) &copy_buf + lp->offset, lp->buf, lp->size); memcpy((char *) &copy_buf + lp->offset, lp->buf, lp->size);
base = (coffee_offset_t)log_page * COFFEE_PAGE_SIZE; base = (coffee_offset_t)log_page * COFFEE_PAGE_SIZE;
base += sizeof(hdr); base += sizeof(hdr);
base += log_records * sizeof(region); base += log_records * sizeof(region);
@ -848,7 +848,7 @@ write_log_page(struct file_desc *fdp, struct log_param *lp)
absolute_offset(log_page, log_record * sizeof(region))); absolute_offset(log_page, log_record * sizeof(region)));
fdp->next_log_record = log_record + 1; fdp->next_log_record = log_record + 1;
} }
return lp->size; return lp->size;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -856,7 +856,7 @@ static int
get_available_fd(void) get_available_fd(void)
{ {
int i; int i;
for(i = 0; i < COFFEE_FD_SET_SIZE; i++) { for(i = 0; i < COFFEE_FD_SET_SIZE; i++) {
if(coffee_fd_set[i].flags == COFFEE_FD_FREE) { if(coffee_fd_set[i].flags == COFFEE_FD_FREE) {
return i; return i;
@ -879,7 +879,7 @@ cfs_open(const char *name, int flags)
return -1; return -1;
} }
fdp = &coffee_fd_set[fd]; fdp = &coffee_fd_set[fd];
page = find_file(name); page = find_file(name);
if(page == INVALID_PAGE) { if(page == INVALID_PAGE) {
if((flags & (CFS_READ | CFS_WRITE)) == CFS_READ) { if((flags & (CFS_READ | CFS_WRITE)) == CFS_READ) {
@ -936,7 +936,7 @@ cfs_seek(int fd, unsigned offset)
if(fdp->end < offset) { if(fdp->end < offset) {
fdp->end = offset; fdp->end = offset;
} }
return fdp->offset = offset; return fdp->offset = offset;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -969,7 +969,7 @@ cfs_read(int fd, void *buf, unsigned size)
int r; int r;
coffee_offset_t base, offset; coffee_offset_t base, offset;
struct log_param lp; struct log_param lp;
if(!(FD_VALID(fd) && FD_READABLE(fd))) { if(!(FD_VALID(fd) && FD_READABLE(fd))) {
return -1; return -1;
} }
@ -991,7 +991,7 @@ cfs_read(int fd, void *buf, unsigned size)
base = fdp->offset; base = fdp->offset;
offset = 0; offset = 0;
/* /*
* Fill the buffer by copying from the log in first hand, or the * Fill the buffer by copying from the log in first hand, or the
* ordinary file if the page has no log record. * ordinary file if the page has no log record.
*/ */
while(remains) { while(remains) {
@ -1027,7 +1027,7 @@ cfs_write(int fd, const void *buf, unsigned size)
if(!(FD_VALID(fd) && FD_WRITABLE(fd))) { if(!(FD_VALID(fd) && FD_WRITABLE(fd))) {
return -1; return -1;
} }
fdp = &coffee_fd_set[fd]; fdp = &coffee_fd_set[fd];
/* Attempt to extend the file if we try to write past the end. */ /* Attempt to extend the file if we try to write past the end. */
while(size + fdp->offset + sizeof(struct file_header) > while(size + fdp->offset + sizeof(struct file_header) >
@ -1037,7 +1037,7 @@ cfs_write(int fd, const void *buf, unsigned size)
return -1; return -1;
} }
} }
if(fdp->offset < fdp->end) { if(fdp->offset < fdp->end) {
remains = size; remains = size;
while(remains) { while(remains) {
@ -1079,7 +1079,7 @@ cfs_write(int fd, const void *buf, unsigned size)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
cfs_opendir(struct cfs_dir *dir, const char *name) cfs_opendir(struct cfs_dir *dir, const char *name)
{ {
/* We have only a root directory. */ /* We have only a root directory. */
if(name[0] != '/' || name[1] != '\0') { if(name[0] != '/' || name[1] != '\0') {
return -1; return -1;
@ -1189,3 +1189,10 @@ cfs_coffee_format(void)
return 0; return 0;
} }
/*---------------------------------------------------------------------------*/
void*
cfs_coffee_get_fd_set(unsigned *size)
{
*size = sizeof(coffee_fd_set);
return &coffee_fd_set;
}

View file

@ -38,6 +38,8 @@
#ifndef CFS_COFFEE_H #ifndef CFS_COFFEE_H
#define CFS_COFFEE_H #define CFS_COFFEE_H
void *cfs_coffee_get_fd_set(unsigned *size);
/** /**
* \file * \file
* Header for the Coffee file system. * Header for the Coffee file system.
@ -54,9 +56,9 @@
* \param size The size of the file. * \param size The size of the file.
* \return 0 on success, -1 on failure. * \return 0 on success, -1 on failure.
* *
* Coffee uses sequential page structures for append-only files. The * Coffee uses sequential page structures for append-only files. The
* sequential structure can be reserved with a certain. If no reservation * sequential structure can be reserved with a certain. If no reservation
* has been done, files will be set to a default size once opened for * has been done, files will be set to a default size once opened for
* the first time. * the first time.
*/ */
int cfs_coffee_reserve(const char *name, uint32_t size); int cfs_coffee_reserve(const char *name, uint32_t size);
@ -68,8 +70,8 @@ int cfs_coffee_reserve(const char *name, uint32_t size);
* \param log_entry_size * \param log_entry_size
* \return 0 on success, -1 on failure. * \return 0 on success, -1 on failure.
* *
* When file data is first modified, Coffee creates a micro log for the * When file data is first modified, Coffee creates a micro log for the
* file. The micro log stores a table of modifications where each record * file. The micro log stores a table of modifications where each record
* is of log_entry_size. * is of log_entry_size.
*/ */
int cfs_coffee_configure_log(const char *file, unsigned log_size, int cfs_coffee_configure_log(const char *file, unsigned log_size,