From 39ea9405bb8832e2e112591af8fa39ac5f13eee8 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Wed, 9 Feb 2011 15:03:57 +0100 Subject: [PATCH] Added a function for setting the I/O semantics on a Coffee file descriptor. Changed the configuration parameters slightly and updated the platform definitions to reflect this change. --- core/cfs/cfs-coffee.c | 73 +++++++++++++++++++++++++++---- core/cfs/cfs-coffee.h | 44 +++++++++++++++++-- platform/native/cfs-coffee-arch.h | 1 + platform/sky/cfs-coffee-arch.h | 2 + 4 files changed, 108 insertions(+), 12 deletions(-) diff --git a/core/cfs/cfs-coffee.c b/core/cfs/cfs-coffee.c index 0f5ca4152..ca84f88b0 100644 --- a/core/cfs/cfs-coffee.c +++ b/core/cfs/cfs-coffee.c @@ -32,7 +32,13 @@ /** * \file - * Coffee: A flash file system for memory-constrained sensor systems. + * Coffee: A file system for a variety of storage types in + * memory-constrained devices. + * + * For further information, see "Enabling Large-Scale Storage in + * Sensor Networks with the Coffee File System" in the proceedings + * of ACM/IEEE IPSN 2009. + * * \author * Nicolas Tsiftes */ @@ -53,14 +59,35 @@ #include "cfs-coffee-arch.h" #include "cfs/cfs-coffee.h" -#ifndef COFFEE_CONF_APPEND_ONLY -#define COFFEE_APPEND_ONLY 0 -#else -#define COFFEE_APPEND_ONLY COFFEE_CONF_APPEND_ONLY -#if COFFEE_MICRO_LOGS -#error "Cannot have COFFEE_APPEND_ONLY when COFFEE_MICRO_LOGS is set." +/* Micro logs enable modifications on storage types that do not support + in-place updates. This applies primarily to flash memories. */ +#ifndef COFFEE_MICRO_LOGS +#define COFFEE_MICRO_LOGS 1 #endif -#define COFFEE_MICRO_LOGS 0 + +/* If the files are expected to be appended to only, this parameter + can be set to save some code space. */ +#ifndef COFFEE_APPEND_ONLY +#define COFFEE_APPEND_ONLY 0 +#endif + +#if COFFEE_MICRO_LOGS && COFFEE_APPEND_ONLY +#error "Cannot have COFFEE_APPEND_ONLY set when COFFEE_MICRO_LOGS is set." +#endif + +/* I/O semantics can be set on file descriptors in order to optimize + file access on certain storage types. */ +#ifndef COFFEE_IO_SEMANTICS +#define COFFEE_IO_SEMANTICS 0 +#endif + +/* + * Prevent sectors from being erased directly after file removal. + * This will level the wear across sectors better, but may lead + * to longer garbage collection procedures. + */ +#ifndef COFFEE_EXTENDED_WEAR_LEVELLING +#define COFFEE_EXTENDED_WEAR_LEVELLING 1 #endif #if COFFEE_START & (COFFEE_SECTOR_SIZE - 1) @@ -149,6 +176,9 @@ struct file_desc { cfs_offset_t offset; struct file *file; uint8_t flags; +#ifdef COFFEE_IO_SEMANTICS + uint8_t io_flags; +#endif }; /* The file header structure mimics the representation of file headers @@ -579,7 +609,7 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds, } } -#if !COFFEE_CONF_EXTENDED_WEAR_LEVELLING +#if !COFFEE_EXTENDED_WEAR_LEVELLING if(gc_allowed) { collect_garbage(GC_RELUCTANT); } @@ -1137,6 +1167,9 @@ cfs_write(int fd, const void *buf, unsigned size) file = fdp->file; /* Attempt to extend the file if we try to write past the end. */ +#ifdef COFFEE_IO_SEMANTICS + if(!(fdp->io_flags & CFS_COFFEE_IO_FIRM_SIZE)) { +#endif while(size + fdp->offset + sizeof(struct file_header) > (file->max_pages * COFFEE_PAGE_SIZE)) { if(merge_log(file->page, 1) < 0) { @@ -1145,9 +1178,17 @@ cfs_write(int fd, const void *buf, unsigned size) file = fdp->file; PRINTF("Extended the file at page %u\n", (unsigned)file->page); } +#ifdef COFFEE_IO_SEMANTICS + } +#endif #if COFFEE_MICRO_LOGS +#if COFFEE_IO_SEMANTICS + if(!(fdp->io_flags & CFS_COFFEE_IO_TOGGLE_ONLY) && + (FILE_MODIFIED(file) || fdp->offset < file->end)) { +#else if(FILE_MODIFIED(file) || fdp->offset < file->end) { +#endif for(bytes_left = size; bytes_left > 0;) { lp.offset = fdp->offset; lp.buf = buf; @@ -1280,6 +1321,20 @@ cfs_coffee_configure_log(const char *filename, unsigned log_size, return 0; } /*---------------------------------------------------------------------------*/ +#ifdef COFFEE_IO_SEMANTICS +int +cfs_coffee_set_io_semantics(int fd, unsigned flags) +{ + if(!FD_VALID(fd)) { + return -1; + } + + coffee_fd_set[fd].io_flags |= flags; + + return 0; +} +#endif +/*---------------------------------------------------------------------------*/ int cfs_coffee_format(void) { diff --git a/core/cfs/cfs-coffee.h b/core/cfs/cfs-coffee.h index de9d17e4a..1a999a5f8 100644 --- a/core/cfs/cfs-coffee.h +++ b/core/cfs/cfs-coffee.h @@ -40,6 +40,29 @@ #include "cfs.h" +/** + * Instruct Coffee that the access pattern to this file is adapted to + * flash I/O semantics by design, and Coffee should therefore not + * invoke its own micro logs when file modifications occur. + * + * This semantical I/O setting is useful when implementing flash storage + * algorithms on top of Coffee. + * + * \sa cfs_coffee_set_io_semantics() + */ +#define CFS_COFFEE_IO_TOGGLE_ONLY 0x1 + +/** + * Instruct Coffee not to attempt to extend the file when there is + * an attempt to write past the reserved file size. + * + * A case when this is necessary is when the file has a firm size limit, + * and a safeguard is needed to protect against writes beyond this limit. + * + * \sa cfs_coffee_set_io_semantics() + */ +#define CFS_COFFEE_IO_FIRM_SIZE 0x2 + /** * \file * Header for the Coffee file system. @@ -65,9 +88,9 @@ int cfs_coffee_reserve(const char *name, cfs_offset_t size); /** * \brief Configure the on-demand log file. - * \param file - * \param log_size - * \param log_entry_size + * \param file The filename. + * \param log_size The total log size. + * \param log_entry_size The log entry size. * \return 0 on success, -1 on failure. * * When file data is first modified, Coffee creates a micro log for the @@ -78,6 +101,21 @@ int cfs_coffee_reserve(const char *name, cfs_offset_t size); int cfs_coffee_configure_log(const char *file, unsigned log_size, unsigned log_entry_size); +/** + * \brief Set the I/O semantics for accessing a file. + * + * \param fd The file descriptor through which the file is accessed. + * \param flags A bit vector of flags. + * + * Coffee is used on a wide range of storage types, and the default + * I/O file semantics may not be optimal for the access pattern + * of a certain file. Hence, this functions allows programmers to + * switch the /O semantics on a file that is accessed through a + * particular file descriptor. + * + */ +int cfs_coffee_set_io_semantics(int fd, unsigned flags); + /** * \brief Format the storage area assigned to Coffee. * \return 0 on success, -1 on failure. diff --git a/platform/native/cfs-coffee-arch.h b/platform/native/cfs-coffee-arch.h index 763e1ebae..d7622cd46 100644 --- a/platform/native/cfs-coffee-arch.h +++ b/platform/native/cfs-coffee-arch.h @@ -55,6 +55,7 @@ #define COFFEE_LOG_SIZE 8192 #define COFFEE_LOG_TABLE_LIMIT 256 #define COFFEE_MICRO_LOGS 0 +#define COFFEE_IO_SEMANTICS 1 #define COFFEE_WRITE(buf, size, offset) \ xmem_pwrite((char *)(buf), (size), COFFEE_START + (offset)) diff --git a/platform/sky/cfs-coffee-arch.h b/platform/sky/cfs-coffee-arch.h index 4525da174..6f30068fa 100644 --- a/platform/sky/cfs-coffee-arch.h +++ b/platform/sky/cfs-coffee-arch.h @@ -55,6 +55,8 @@ #define COFFEE_DYN_SIZE 4*1024 #define COFFEE_LOG_SIZE 1024 +#define COFFEE_IO_SEMANTICS 1 +#define COFFEE_APPEND_ONLY 0 #define COFFEE_MICRO_LOGS 1 /* Flash operations. */