added function for getting coffee's fd_set address and size
This commit is contained in:
parent
b258a99e22
commit
7e5047012b
2 changed files with 49 additions and 40 deletions
|
@ -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 *) ©_buf + lp->offset, lp->buf, lp->size);
|
memcpy((char *) ©_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;
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue