Merge pull request #964 from nvt/coffee-code-style
Fix some code style issues in Coffee.
This commit is contained in:
commit
f504b4dd17
1 changed files with 153 additions and 154 deletions
|
@ -35,12 +35,12 @@
|
||||||
* Coffee: A file system for a variety of storage types in
|
* Coffee: A file system for a variety of storage types in
|
||||||
* memory-constrained devices.
|
* memory-constrained devices.
|
||||||
*
|
*
|
||||||
* For further information, see "Enabling Large-Scale Storage in
|
* For further information, see "Enabling Large-Scale Storage in
|
||||||
* Sensor Networks with the Coffee File System" in the proceedings
|
* Sensor Networks with the Coffee File System" in the proceedings
|
||||||
* of ACM/IEEE IPSN 2009.
|
* of ACM/IEEE IPSN 2009.
|
||||||
*
|
*
|
||||||
* \author
|
* \author
|
||||||
* Nicolas Tsiftes <nvt@sics.se>
|
* Nicolas Tsiftes <nvt@sics.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -62,23 +62,23 @@
|
||||||
/* Micro logs enable modifications on storage types that do not support
|
/* Micro logs enable modifications on storage types that do not support
|
||||||
in-place updates. This applies primarily to flash memories. */
|
in-place updates. This applies primarily to flash memories. */
|
||||||
#ifndef COFFEE_MICRO_LOGS
|
#ifndef COFFEE_MICRO_LOGS
|
||||||
#define COFFEE_MICRO_LOGS 1
|
#define COFFEE_MICRO_LOGS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the files are expected to be appended to only, this parameter
|
/* If the files are expected to be appended to only, this parameter
|
||||||
can be set to save some code space. */
|
can be set to save some code space. */
|
||||||
#ifndef COFFEE_APPEND_ONLY
|
#ifndef COFFEE_APPEND_ONLY
|
||||||
#define COFFEE_APPEND_ONLY 0
|
#define COFFEE_APPEND_ONLY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if COFFEE_MICRO_LOGS && COFFEE_APPEND_ONLY
|
#if COFFEE_MICRO_LOGS && COFFEE_APPEND_ONLY
|
||||||
#error "Cannot have COFFEE_APPEND_ONLY set when COFFEE_MICRO_LOGS is set."
|
#error "Cannot have COFFEE_APPEND_ONLY set when COFFEE_MICRO_LOGS is set."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* I/O semantics can be set on file descriptors in order to optimize
|
/* I/O semantics can be set on file descriptors in order to optimize
|
||||||
file access on certain storage types. */
|
file access on certain storage types. */
|
||||||
#ifndef COFFEE_IO_SEMANTICS
|
#ifndef COFFEE_IO_SEMANTICS
|
||||||
#define COFFEE_IO_SEMANTICS 0
|
#define COFFEE_IO_SEMANTICS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -87,72 +87,72 @@
|
||||||
* to longer garbage collection procedures.
|
* to longer garbage collection procedures.
|
||||||
*/
|
*/
|
||||||
#ifndef COFFEE_EXTENDED_WEAR_LEVELLING
|
#ifndef COFFEE_EXTENDED_WEAR_LEVELLING
|
||||||
#define COFFEE_EXTENDED_WEAR_LEVELLING 1
|
#define COFFEE_EXTENDED_WEAR_LEVELLING 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if COFFEE_START & (COFFEE_SECTOR_SIZE - 1)
|
#if COFFEE_START & (COFFEE_SECTOR_SIZE - 1)
|
||||||
#error COFFEE_START must point to the first byte in a sector.
|
#error COFFEE_START must point to the first byte in a sector.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define COFFEE_FD_FREE 0x0
|
#define COFFEE_FD_FREE 0x0
|
||||||
#define COFFEE_FD_READ 0x1
|
#define COFFEE_FD_READ 0x1
|
||||||
#define COFFEE_FD_WRITE 0x2
|
#define COFFEE_FD_WRITE 0x2
|
||||||
#define COFFEE_FD_APPEND 0x4
|
#define COFFEE_FD_APPEND 0x4
|
||||||
|
|
||||||
#define COFFEE_FILE_MODIFIED 0x1
|
#define COFFEE_FILE_MODIFIED 0x1
|
||||||
|
|
||||||
#define INVALID_PAGE ((coffee_page_t)-1)
|
#define INVALID_PAGE ((coffee_page_t)-1)
|
||||||
#define UNKNOWN_OFFSET ((cfs_offset_t)-1)
|
#define UNKNOWN_OFFSET ((cfs_offset_t)-1)
|
||||||
|
|
||||||
#define REMOVE_LOG 1
|
#define REMOVE_LOG 1
|
||||||
#define CLOSE_FDS 1
|
#define CLOSE_FDS 1
|
||||||
#define ALLOW_GC 1
|
#define ALLOW_GC 1
|
||||||
|
|
||||||
/* "Greedy" garbage collection erases as many sectors as possible. */
|
/* "Greedy" garbage collection erases as many sectors as possible. */
|
||||||
#define GC_GREEDY 0
|
#define GC_GREEDY 0
|
||||||
/* "Reluctant" garbage collection stops after erasing one sector. */
|
/* "Reluctant" garbage collection stops after erasing one sector. */
|
||||||
#define GC_RELUCTANT 1
|
#define GC_RELUCTANT 1
|
||||||
|
|
||||||
/* File descriptor macros. */
|
/* File descriptor macros. */
|
||||||
#define FD_VALID(fd) \
|
#define FD_VALID(fd) \
|
||||||
((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \
|
((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \
|
||||||
coffee_fd_set[(fd)].flags != COFFEE_FD_FREE)
|
coffee_fd_set[(fd)].flags != COFFEE_FD_FREE)
|
||||||
#define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ)
|
#define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ)
|
||||||
#define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE)
|
#define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE)
|
||||||
#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND)
|
#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND)
|
||||||
|
|
||||||
/* File object macros. */
|
/* File object macros. */
|
||||||
#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED)
|
#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED)
|
||||||
#define FILE_FREE(file) ((file)->max_pages == 0)
|
#define FILE_FREE(file) ((file)->max_pages == 0)
|
||||||
#define FILE_UNREFERENCED(file) ((file)->references == 0)
|
#define FILE_UNREFERENCED(file) ((file)->references == 0)
|
||||||
|
|
||||||
/* File header flags. */
|
/* File header flags. */
|
||||||
#define HDR_FLAG_VALID 0x1 /* Completely written header. */
|
#define HDR_FLAG_VALID 0x1 /* Completely written header. */
|
||||||
#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */
|
#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */
|
||||||
#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */
|
#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */
|
||||||
#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */
|
#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */
|
||||||
#define HDR_FLAG_LOG 0x10 /* Log file. */
|
#define HDR_FLAG_LOG 0x10 /* Log file. */
|
||||||
#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */
|
#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */
|
||||||
|
|
||||||
/* File header macros. */
|
/* File header macros. */
|
||||||
#define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag))
|
#define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag))
|
||||||
#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID)
|
#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID)
|
||||||
#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED)
|
#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED)
|
||||||
#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr)
|
#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr)
|
||||||
#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG)
|
#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG)
|
||||||
#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED)
|
#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED)
|
||||||
#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED)
|
#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED)
|
||||||
#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE)
|
#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE)
|
||||||
#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \
|
#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \
|
||||||
!HDR_OBSOLETE(hdr) && \
|
!HDR_OBSOLETE(hdr) && \
|
||||||
!HDR_ISOLATED(hdr))
|
!HDR_ISOLATED(hdr))
|
||||||
|
|
||||||
/* Shortcuts derived from the hardware-dependent configuration of Coffee. */
|
/* Shortcuts derived from the hardware-dependent configuration of Coffee. */
|
||||||
#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE)
|
#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE)
|
||||||
#define COFFEE_PAGE_COUNT \
|
#define COFFEE_PAGE_COUNT \
|
||||||
((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE))
|
((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE))
|
||||||
#define COFFEE_PAGES_PER_SECTOR \
|
#define COFFEE_PAGES_PER_SECTOR \
|
||||||
((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE))
|
((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE))
|
||||||
|
|
||||||
/* This structure is used for garbage collection statistics. */
|
/* This structure is used for garbage collection statistics. */
|
||||||
struct sector_status {
|
struct sector_status {
|
||||||
|
@ -181,7 +181,7 @@ struct file_desc {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The file header structure mimics the representation of file headers
|
/* The file header structure mimics the representation of file headers
|
||||||
in the physical storage medium. */
|
in the physical storage medium. */
|
||||||
struct file_header {
|
struct file_header {
|
||||||
coffee_page_t log_page;
|
coffee_page_t log_page;
|
||||||
|
@ -201,9 +201,9 @@ struct log_param {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The protected memory consists of structures that should not be
|
* The protected memory consists of structures that should not be
|
||||||
* overwritten during system checkpointing because they may be used by
|
* overwritten during system checkpointing because they may be used by
|
||||||
* the checkpointing implementation. These structures need not be
|
* the checkpointing implementation. These structures need not be
|
||||||
* protected if checkpointing is not used.
|
* protected if checkpointing is not used.
|
||||||
*/
|
*/
|
||||||
static struct protected_mem_t {
|
static struct protected_mem_t {
|
||||||
|
@ -212,10 +212,10 @@ static struct protected_mem_t {
|
||||||
coffee_page_t next_free;
|
coffee_page_t next_free;
|
||||||
char gc_wait;
|
char gc_wait;
|
||||||
} protected_mem;
|
} protected_mem;
|
||||||
static struct file * const coffee_files = protected_mem.coffee_files;
|
static struct file *const coffee_files = protected_mem.coffee_files;
|
||||||
static struct file_desc * const coffee_fd_set = protected_mem.coffee_fd_set;
|
static struct file_desc *const coffee_fd_set = protected_mem.coffee_fd_set;
|
||||||
static coffee_page_t * const next_free = &protected_mem.next_free;
|
static coffee_page_t *const next_free = &protected_mem.next_free;
|
||||||
static char * const gc_wait = &protected_mem.gc_wait;
|
static char *const gc_wait = &protected_mem.gc_wait;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
@ -256,8 +256,8 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
||||||
active = obsolete = free = 0;
|
active = obsolete = free = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_sector_status() is an iterative function using local static
|
* get_sector_status() is an iterative function using local static
|
||||||
* state. It therefore requires that the caller starts iterating from
|
* state. It therefore requires that the caller starts iterating from
|
||||||
* sector 0 in order to reset the internal state.
|
* sector 0 in order to reset the internal state.
|
||||||
*/
|
*/
|
||||||
if(sector == 0) {
|
if(sector == 0) {
|
||||||
|
@ -269,8 +269,8 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
||||||
sector_end = sector_start + COFFEE_PAGES_PER_SECTOR;
|
sector_end = sector_start + COFFEE_PAGES_PER_SECTOR;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Account for pages belonging to a file starting in a previous
|
* Account for pages belonging to a file starting in a previous
|
||||||
* segment that extends into this segment. If the whole segment is
|
* segment that extends into this segment. If the whole segment is
|
||||||
* covered, we do not need to continue counting pages in this iteration.
|
* covered, we do not need to continue counting pages in this iteration.
|
||||||
*/
|
*/
|
||||||
if(last_pages_are_active) {
|
if(last_pages_are_active) {
|
||||||
|
@ -289,7 +289,7 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
||||||
obsolete = skip_pages;
|
obsolete = skip_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine the amount of pages of each type that have not been
|
/* Determine the amount of pages of each type that have not been
|
||||||
accounted for yet in the current sector. */
|
accounted for yet in the current sector. */
|
||||||
for(page = sector_start + skip_pages; page < sector_end;) {
|
for(page = sector_start + skip_pages; page < sector_end;) {
|
||||||
read_header(&hdr, page);
|
read_header(&hdr, page);
|
||||||
|
@ -312,10 +312,10 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine the amount of pages in the following sectors that
|
* Determine the amount of pages in the following sectors that
|
||||||
* should be remembered for the next iteration. This is necessary
|
* should be remembered for the next iteration. This is necessary
|
||||||
* because no page except the first of a file contains information
|
* because no page except the first of a file contains information
|
||||||
* about what type of page it is. A side effect of remembering this
|
* about what type of page it is. A side effect of remembering this
|
||||||
* amount is that there is no need to read in the headers of each
|
* amount is that there is no need to read in the headers of each
|
||||||
* of these pages from the storage.
|
* of these pages from the storage.
|
||||||
*/
|
*/
|
||||||
skip_pages = active + obsolete + free - COFFEE_PAGES_PER_SECTOR;
|
skip_pages = active + obsolete + free - COFFEE_PAGES_PER_SECTOR;
|
||||||
|
@ -332,14 +332,14 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
||||||
stats->free = free;
|
stats->free = free;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To avoid unnecessary page isolation, we notify the caller that
|
* To avoid unnecessary page isolation, we notify the caller that
|
||||||
* "skip_pages" pages should be isolated only if the current file extent
|
* "skip_pages" pages should be isolated only if the current file extent
|
||||||
* ends in the next sector. If the file extent ends in a more distant
|
* ends in the next sector. If the file extent ends in a more distant
|
||||||
* sector, however, the garbage collection can free the next sector
|
* sector, however, the garbage collection can free the next sector
|
||||||
* immediately without requiring page isolation.
|
* immediately without requiring page isolation.
|
||||||
*/
|
*/
|
||||||
return (last_pages_are_active || (skip_pages >= COFFEE_PAGES_PER_SECTOR)) ?
|
return (last_pages_are_active || (skip_pages >= COFFEE_PAGES_PER_SECTOR)) ?
|
||||||
0 : skip_pages;
|
0 : skip_pages;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
@ -359,7 +359,6 @@ isolate_pages(coffee_page_t start, coffee_page_t skip_pages)
|
||||||
}
|
}
|
||||||
PRINTF("Coffee: Isolated %u pages starting in sector %d\n",
|
PRINTF("Coffee: Isolated %u pages starting in sector %d\n",
|
||||||
(unsigned)skip_pages, (int)start / COFFEE_PAGES_PER_SECTOR);
|
(unsigned)skip_pages, (int)start / COFFEE_PAGES_PER_SECTOR);
|
||||||
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
@ -370,7 +369,7 @@ collect_garbage(int mode)
|
||||||
coffee_page_t first_page, isolation_count;
|
coffee_page_t first_page, isolation_count;
|
||||||
|
|
||||||
PRINTF("Coffee: Running the file system garbage collector in %s mode\n",
|
PRINTF("Coffee: Running the file system garbage collector in %s mode\n",
|
||||||
mode == GC_RELUCTANT ? "reluctant" : "greedy");
|
mode == GC_RELUCTANT ? "reluctant" : "greedy");
|
||||||
/*
|
/*
|
||||||
* 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.
|
||||||
|
@ -378,8 +377,8 @@ collect_garbage(int mode)
|
||||||
for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) {
|
for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) {
|
||||||
isolation_count = get_sector_status(sector, &stats);
|
isolation_count = get_sector_status(sector, &stats);
|
||||||
PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n",
|
PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n",
|
||||||
sector, (unsigned)stats.active,
|
sector, (unsigned)stats.active,
|
||||||
(unsigned)stats.obsolete, (unsigned)stats.free);
|
(unsigned)stats.obsolete, (unsigned)stats.free);
|
||||||
|
|
||||||
if(stats.active > 0) {
|
if(stats.active > 0) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -410,13 +409,13 @@ static coffee_page_t
|
||||||
next_file(coffee_page_t page, struct file_header *hdr)
|
next_file(coffee_page_t page, struct file_header *hdr)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The quick-skip algorithm for finding file extents is the most
|
* The quick-skip algorithm for finding file extents is the most
|
||||||
* essential part of Coffee. The file allocation rules enables this
|
* essential part of Coffee. The file allocation rules enables this
|
||||||
* algorithm to quickly jump over free areas and allocated extents
|
* algorithm to quickly jump over free areas and allocated extents
|
||||||
* after reading single headers and determining their status.
|
* after reading single headers and determining their status.
|
||||||
*
|
*
|
||||||
* The worst-case performance occurs when we encounter multiple long
|
* The worst-case performance occurs when we encounter multiple long
|
||||||
* sequences of isolated pages, but such sequences are uncommon and
|
* sequences of isolated pages, but such sequences are uncommon and
|
||||||
* always shorter than a sector.
|
* always shorter than a sector.
|
||||||
*/
|
*/
|
||||||
if(HDR_FREE(*hdr)) {
|
if(HDR_FREE(*hdr)) {
|
||||||
|
@ -424,7 +423,7 @@ next_file(coffee_page_t page, struct file_header *hdr)
|
||||||
} else if(HDR_ISOLATED(*hdr)) {
|
} else if(HDR_ISOLATED(*hdr)) {
|
||||||
return page + 1;
|
return page + 1;
|
||||||
}
|
}
|
||||||
return page + hdr->max_pages;
|
return page + hdr->max_pages;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static struct file *
|
static struct file *
|
||||||
|
@ -475,7 +474,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(FILE_FREE(&coffee_files[i])) {
|
if(FILE_FREE(&coffee_files[i])) {
|
||||||
|
@ -487,7 +486,7 @@ find_file(const char *name)
|
||||||
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);
|
||||||
|
@ -521,10 +520,10 @@ file_end(coffee_page_t start)
|
||||||
COFFEE_READ(buf, sizeof(buf), (start + page) * COFFEE_PAGE_SIZE);
|
COFFEE_READ(buf, sizeof(buf), (start + page) * COFFEE_PAGE_SIZE);
|
||||||
for(i = COFFEE_PAGE_SIZE - 1; i >= 0; i--) {
|
for(i = COFFEE_PAGE_SIZE - 1; i >= 0; i--) {
|
||||||
if(buf[i] != 0) {
|
if(buf[i] != 0) {
|
||||||
if(page == 0 && i < sizeof(hdr)) {
|
if(page == 0 && i < sizeof(hdr)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1 + i + (page * COFFEE_PAGE_SIZE) - sizeof(hdr);
|
return 1 + i + (page * COFFEE_PAGE_SIZE) - sizeof(hdr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -544,7 +543,7 @@ find_contiguous_pages(coffee_page_t amount)
|
||||||
read_header(&hdr, page);
|
read_header(&hdr, page);
|
||||||
if(HDR_FREE(hdr)) {
|
if(HDR_FREE(hdr)) {
|
||||||
if(start == INVALID_PAGE) {
|
if(start == INVALID_PAGE) {
|
||||||
start = page;
|
start = page;
|
||||||
if(start + amount >= COFFEE_PAGE_COUNT) {
|
if(start + amount >= COFFEE_PAGE_COUNT) {
|
||||||
/* We can stop immediately if the remaining pages are not enough. */
|
/* We can stop immediately if the remaining pages are not enough. */
|
||||||
break;
|
break;
|
||||||
|
@ -557,9 +556,9 @@ find_contiguous_pages(coffee_page_t amount)
|
||||||
|
|
||||||
if(start + amount <= page) {
|
if(start + amount <= page) {
|
||||||
if(start == *next_free) {
|
if(start == *next_free) {
|
||||||
*next_free = start + amount;
|
*next_free = start + amount;
|
||||||
}
|
}
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
start = INVALID_PAGE;
|
start = INVALID_PAGE;
|
||||||
|
@ -596,7 +595,7 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds,
|
||||||
if(close_fds) {
|
if(close_fds) {
|
||||||
for(i = 0; i < COFFEE_FD_SET_SIZE; i++) {
|
for(i = 0; i < COFFEE_FD_SET_SIZE; i++) {
|
||||||
if(coffee_fd_set[i].file != NULL && coffee_fd_set[i].file->page == page) {
|
if(coffee_fd_set[i].file != NULL && coffee_fd_set[i].file->page == page) {
|
||||||
coffee_fd_set[i].flags = COFFEE_FD_FREE;
|
coffee_fd_set[i].flags = COFFEE_FD_FREE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -622,12 +621,12 @@ static coffee_page_t
|
||||||
page_count(cfs_offset_t size)
|
page_count(cfs_offset_t size)
|
||||||
{
|
{
|
||||||
return (size + sizeof(struct file_header) + COFFEE_PAGE_SIZE - 1) /
|
return (size + sizeof(struct file_header) + COFFEE_PAGE_SIZE - 1) /
|
||||||
COFFEE_PAGE_SIZE;
|
COFFEE_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static struct file *
|
static struct file *
|
||||||
reserve(const char *name, coffee_page_t pages,
|
reserve(const char *name, coffee_page_t pages,
|
||||||
int allow_duplicates, unsigned flags)
|
int allow_duplicates, unsigned flags)
|
||||||
{
|
{
|
||||||
struct file_header hdr;
|
struct file_header hdr;
|
||||||
coffee_page_t page;
|
coffee_page_t page;
|
||||||
|
@ -657,7 +656,7 @@ reserve(const char *name, coffee_page_t pages,
|
||||||
write_header(&hdr, page);
|
write_header(&hdr, page);
|
||||||
|
|
||||||
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(page, &hdr);
|
file = load_file(page, &hdr);
|
||||||
if(file != NULL) {
|
if(file != NULL) {
|
||||||
|
@ -670,19 +669,19 @@ reserve(const char *name, coffee_page_t pages,
|
||||||
#if COFFEE_MICRO_LOGS
|
#if COFFEE_MICRO_LOGS
|
||||||
static void
|
static void
|
||||||
adjust_log_config(struct file_header *hdr,
|
adjust_log_config(struct file_header *hdr,
|
||||||
uint16_t *log_record_size, uint16_t *log_records)
|
uint16_t *log_record_size, uint16_t *log_records)
|
||||||
{
|
{
|
||||||
*log_record_size = hdr->log_record_size == 0 ?
|
*log_record_size = hdr->log_record_size == 0 ?
|
||||||
COFFEE_PAGE_SIZE : hdr->log_record_size;
|
COFFEE_PAGE_SIZE : hdr->log_record_size;
|
||||||
*log_records = hdr->log_records == 0 ?
|
*log_records = hdr->log_records == 0 ?
|
||||||
COFFEE_LOG_SIZE / *log_record_size : hdr->log_records;
|
COFFEE_LOG_SIZE / *log_record_size : hdr->log_records;
|
||||||
}
|
}
|
||||||
#endif /* COFFEE_MICRO_LOGS */
|
#endif /* COFFEE_MICRO_LOGS */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#if COFFEE_MICRO_LOGS
|
#if COFFEE_MICRO_LOGS
|
||||||
static uint16_t
|
static uint16_t
|
||||||
modify_log_buffer(uint16_t log_record_size,
|
modify_log_buffer(uint16_t log_record_size,
|
||||||
cfs_offset_t *offset, uint16_t *size)
|
cfs_offset_t *offset, uint16_t *size)
|
||||||
{
|
{
|
||||||
uint16_t region;
|
uint16_t region;
|
||||||
|
|
||||||
|
@ -700,7 +699,7 @@ modify_log_buffer(uint16_t log_record_size,
|
||||||
#if COFFEE_MICRO_LOGS
|
#if COFFEE_MICRO_LOGS
|
||||||
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)
|
||||||
{
|
{
|
||||||
cfs_offset_t base;
|
cfs_offset_t base;
|
||||||
uint16_t processed;
|
uint16_t processed;
|
||||||
|
@ -709,30 +708,30 @@ 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);
|
||||||
batch_size = 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[batch_size];
|
uint16_t indices[batch_size];
|
||||||
|
|
||||||
while(processed < search_records && match_index < 0) {
|
while(processed < search_records && match_index < 0) {
|
||||||
if(batch_size + processed > search_records) {
|
if(batch_size + processed > search_records) {
|
||||||
batch_size = search_records - processed;
|
batch_size = search_records - processed;
|
||||||
}
|
|
||||||
|
|
||||||
base -= batch_size * sizeof(indices[0]);
|
|
||||||
COFFEE_READ(&indices, sizeof(indices[0]) * batch_size, base);
|
|
||||||
|
|
||||||
for(i = batch_size - 1; i >= 0; i--) {
|
|
||||||
if(indices[i] - 1 == region) {
|
|
||||||
match_index = search_records - processed - (batch_size - i);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
processed += batch_size;
|
base -= batch_size * sizeof(indices[0]);
|
||||||
}
|
COFFEE_READ(&indices, sizeof(indices[0]) * batch_size, base);
|
||||||
|
|
||||||
|
for(i = batch_size - 1; i >= 0; i--) {
|
||||||
|
if(indices[i] - 1 == region) {
|
||||||
|
match_index = search_records - processed - (batch_size - i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processed += batch_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return match_index;
|
return match_index;
|
||||||
|
@ -839,7 +838,7 @@ merge_log(coffee_page_t file_page, int extend)
|
||||||
} while(n != 0);
|
} while(n != 0);
|
||||||
|
|
||||||
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 &&
|
||||||
coffee_fd_set[i].file->page == file_page) {
|
coffee_fd_set[i].file->page == file_page) {
|
||||||
coffee_fd_set[i].file = new_file;
|
coffee_fd_set[i].file = new_file;
|
||||||
new_file->references++;
|
new_file->references++;
|
||||||
|
@ -869,7 +868,7 @@ merge_log(coffee_page_t file_page, int extend)
|
||||||
#if COFFEE_MICRO_LOGS
|
#if COFFEE_MICRO_LOGS
|
||||||
static int
|
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, preferred_batch_size;
|
int log_record, preferred_batch_size;
|
||||||
|
|
||||||
|
@ -878,7 +877,7 @@ find_next_record(struct file *file, coffee_page_t log_page,
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
{
|
{
|
||||||
/* The next log record is unknown at this point; search for it. */
|
/* The next log record is unknown at this point; search for it. */
|
||||||
uint16_t indices[preferred_batch_size];
|
uint16_t indices[preferred_batch_size];
|
||||||
|
@ -888,15 +887,15 @@ find_next_record(struct file *file, coffee_page_t log_page,
|
||||||
log_record = log_records;
|
log_record = log_records;
|
||||||
for(processed = 0; processed < log_records; processed += batch_size) {
|
for(processed = 0; processed < log_records; processed += batch_size) {
|
||||||
batch_size = log_records - processed >= preferred_batch_size ?
|
batch_size = log_records - processed >= preferred_batch_size ?
|
||||||
preferred_batch_size : log_records - processed;
|
preferred_batch_size : log_records - processed;
|
||||||
|
|
||||||
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(log_record = 0; log_record < batch_size; log_record++) {
|
for(log_record = 0; log_record < batch_size; log_record++) {
|
||||||
if(indices[log_record] == 0) {
|
if(indices[log_record] == 0) {
|
||||||
log_record += processed;
|
log_record += processed;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -940,7 +939,7 @@ write_log_page(struct file *file, struct log_param *lp)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
PRINTF("Coffee: Created a log structure for file %s at page %u\n",
|
PRINTF("Coffee: Created a log structure for file %s at page %u\n",
|
||||||
hdr.name, (unsigned)log_page);
|
hdr.name, (unsigned)log_page);
|
||||||
hdr.log_page = log_page;
|
hdr.log_page = log_page;
|
||||||
log_record = 0;
|
log_record = 0;
|
||||||
}
|
}
|
||||||
|
@ -953,9 +952,9 @@ 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, log_record, &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, offset));
|
absolute_offset(file->page, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(©_buf[lp->offset], lp->buf, lp->size);
|
memcpy(©_buf[lp->offset], lp->buf, lp->size);
|
||||||
|
@ -967,11 +966,11 @@ write_log_page(struct file *file, struct log_param *lp)
|
||||||
offset = absolute_offset(log_page, 0);
|
offset = absolute_offset(log_page, 0);
|
||||||
++region;
|
++region;
|
||||||
COFFEE_WRITE(®ion, sizeof(region),
|
COFFEE_WRITE(®ion, sizeof(region),
|
||||||
offset + log_record * sizeof(region));
|
offset + log_record * sizeof(region));
|
||||||
|
|
||||||
offset += log_records * sizeof(region);
|
offset += log_records * sizeof(region);
|
||||||
COFFEE_WRITE(copy_buf, sizeof(copy_buf),
|
COFFEE_WRITE(copy_buf, sizeof(copy_buf),
|
||||||
offset + log_record * log_record_size);
|
offset + log_record * log_record_size);
|
||||||
file->record_count = log_record + 1;
|
file->record_count = log_record + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1171,7 +1170,7 @@ cfs_write(int fd, const void *buf, unsigned size)
|
||||||
if(!(fdp->io_flags & CFS_COFFEE_IO_FIRM_SIZE)) {
|
if(!(fdp->io_flags & CFS_COFFEE_IO_FIRM_SIZE)) {
|
||||||
#endif
|
#endif
|
||||||
while(size + fdp->offset + sizeof(struct file_header) >
|
while(size + fdp->offset + sizeof(struct file_header) >
|
||||||
(file->max_pages * COFFEE_PAGE_SIZE)) {
|
(file->max_pages * COFFEE_PAGE_SIZE)) {
|
||||||
if(merge_log(file->page, 1) < 0) {
|
if(merge_log(file->page, 1) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1179,7 +1178,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 COFFEE_IO_SEMANTICS
|
#if COFFEE_IO_SEMANTICS
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if COFFEE_MICRO_LOGS
|
#if COFFEE_MICRO_LOGS
|
||||||
|
@ -1196,19 +1195,19 @@ cfs_write(int fd, const void *buf, unsigned size)
|
||||||
lp.size = bytes_left;
|
lp.size = bytes_left;
|
||||||
i = write_log_page(file, &lp);
|
i = write_log_page(file, &lp);
|
||||||
if(i < 0) {
|
if(i < 0) {
|
||||||
/* Return -1 if we wrote nothing because the log write failed. */
|
/* Return -1 if we wrote nothing because the log write failed. */
|
||||||
if(size == bytes_left) {
|
if(size == bytes_left) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if(i == 0) {
|
} else if(i == 0) {
|
||||||
/* The file was merged with the log. */
|
/* The file was merged with the log. */
|
||||||
file = fdp->file;
|
file = fdp->file;
|
||||||
} else {
|
} else {
|
||||||
/* A log record was written. */
|
/* A log record was written. */
|
||||||
bytes_left -= i;
|
bytes_left -= i;
|
||||||
fdp->offset += i;
|
fdp->offset += i;
|
||||||
buf = (char *)buf + i;
|
buf = (char *)buf + i;
|
||||||
|
|
||||||
/* Update the file end for a potential log merge that might
|
/* Update the file end for a potential log merge that might
|
||||||
occur while writing log records. */
|
occur while writing log records. */
|
||||||
|
@ -1231,15 +1230,15 @@ cfs_write(int fd, const void *buf, unsigned size)
|
||||||
} else {
|
} else {
|
||||||
#endif /* COFFEE_MICRO_LOGS */
|
#endif /* COFFEE_MICRO_LOGS */
|
||||||
#if COFFEE_APPEND_ONLY
|
#if COFFEE_APPEND_ONLY
|
||||||
if(fdp->offset < file->end) {
|
if(fdp->offset < file->end) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif /* COFFEE_APPEND_ONLY */
|
#endif /* COFFEE_APPEND_ONLY */
|
||||||
|
|
||||||
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;
|
||||||
#if COFFEE_MICRO_LOGS
|
#if COFFEE_MICRO_LOGS
|
||||||
}
|
}
|
||||||
#endif /* COFFEE_MICRO_LOGS */
|
#endif /* COFFEE_MICRO_LOGS */
|
||||||
|
|
||||||
if(fdp->offset > file->end) {
|
if(fdp->offset > file->end) {
|
||||||
|
@ -1253,7 +1252,7 @@ int
|
||||||
cfs_opendir(struct cfs_dir *dir, const char *name)
|
cfs_opendir(struct cfs_dir *dir, const char *name)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Coffee is only guaranteed to support "/" and ".", but it does not
|
* Coffee is only guaranteed to support "/" and ".", but it does not
|
||||||
* currently enforce this.
|
* currently enforce this.
|
||||||
*/
|
*/
|
||||||
memset(dir->dummy_space, 0, sizeof(coffee_page_t));
|
memset(dir->dummy_space, 0, sizeof(coffee_page_t));
|
||||||
|
@ -1300,7 +1299,7 @@ cfs_coffee_reserve(const char *name, cfs_offset_t size)
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
int
|
int
|
||||||
cfs_coffee_configure_log(const char *filename, unsigned log_size,
|
cfs_coffee_configure_log(const char *filename, unsigned log_size,
|
||||||
unsigned log_record_size)
|
unsigned log_record_size)
|
||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
struct file_header hdr;
|
struct file_header hdr;
|
||||||
|
|
Loading…
Reference in a new issue