diff --git a/core/cfs/cfs-coffee.c b/core/cfs/cfs-coffee.c index ea158dfb9..6391e173c 100644 --- a/core/cfs/cfs-coffee.c +++ b/core/cfs/cfs-coffee.c @@ -114,41 +114,41 @@ #define GC_RELUCTANT 1 /* File descriptor macros. */ -#define FD_VALID(fd) \ - ((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \ - coffee_fd_set[(fd)].flags != COFFEE_FD_FREE) +#define FD_VALID(fd) ((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \ + coffee_fd_set[(fd)].flags != COFFEE_FD_FREE) #define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ) #define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE) #define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND) /* File object macros. */ -#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED) -#define FILE_FREE(file) ((file)->max_pages == 0) +#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED) +#define FILE_FREE(file) ((file)->max_pages == 0) #define FILE_UNREFERENCED(file) ((file)->references == 0) /* File header flags. */ -#define HDR_FLAG_VALID 0x1 /* Completely written header. */ -#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */ -#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */ -#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */ -#define HDR_FLAG_LOG 0x10 /* Log file. */ -#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */ +#define HDR_FLAG_VALID 0x01 /* Completely written header. */ +#define HDR_FLAG_ALLOCATED 0x02 /* Allocated file. */ +#define HDR_FLAG_OBSOLETE 0x04 /* File marked for GC. */ +#define HDR_FLAG_MODIFIED 0x08 /* Modified file, log exists. */ +#define HDR_FLAG_LOG 0x10 /* Log file. */ +#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */ /* File header macros. */ #define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag)) -#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID) -#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED) -#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr) -#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG) -#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED) -#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED) -#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE) -#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \ - !HDR_OBSOLETE(hdr) && \ - !HDR_ISOLATED(hdr)) +#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID) +#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED) +#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr) +#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG) +#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED) +#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED) +#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE) +#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \ + !HDR_OBSOLETE(hdr) && \ + !HDR_ISOLATED(hdr)) /* Shortcuts derived from the hardware-dependent configuration of Coffee. */ -#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE) +#define COFFEE_SECTOR_COUNT \ + (coffee_page_t)(COFFEE_SIZE / COFFEE_SECTOR_SIZE) #define COFFEE_PAGE_COUNT \ ((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE)) #define COFFEE_PAGES_PER_SECTOR \ @@ -235,7 +235,7 @@ absolute_offset(coffee_page_t page, cfs_offset_t offset) } /*---------------------------------------------------------------------------*/ static coffee_page_t -get_sector_status(uint16_t sector, struct sector_status *stats) +get_sector_status(coffee_page_t sector, struct sector_status *stats) { static coffee_page_t skip_pages; static char last_pages_are_active; @@ -305,7 +305,7 @@ get_sector_status(uint16_t sector, struct sector_status *stats) /* * Determine the amount of pages in the following sectors that * should be remembered for the next iteration. This is necessary - * because no page except the first of a file contains information + * because no file page except the first contains information * 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 * of these pages from the storage. @@ -356,11 +356,11 @@ isolate_pages(coffee_page_t start, coffee_page_t skip_pages) static void collect_garbage(int mode) { - uint16_t sector; + coffee_page_t sector; struct sector_status stats; coffee_page_t first_page, isolation_count; - PRINTF("Coffee: Running the file system garbage collector in %s mode\n", + PRINTF("Coffee: Running the garbage collector in %s mode\n", mode == GC_RELUCTANT ? "reluctant" : "greedy"); /* * The garbage collector erases as many sectors as possible. A sector is @@ -369,7 +369,7 @@ collect_garbage(int mode) for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) { isolation_count = get_sector_status(sector, &stats); PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n", - sector, (unsigned)stats.active, + (unsigned)sector, (unsigned)stats.active, (unsigned)stats.obsolete, (unsigned)stats.free); if(stats.active > 0) { @@ -402,7 +402,7 @@ next_file(coffee_page_t page, struct file_header *hdr) { /* * 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 enable this * algorithm to quickly jump over free areas and allocated extents * after reading single headers and determining their status. * @@ -648,7 +648,7 @@ reserve(const char *name, coffee_page_t pages, write_header(&hdr, page); PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n", - pages, page, name); + (unsigned)pages, (unsigned)page, name); file = load_file(page, &hdr); if(file != NULL) { @@ -843,7 +843,7 @@ merge_log(coffee_page_t file_page, int extend) return -1; } - /* Copy the log configuration and the EOF hint. */ + /* Copy the log configuration. */ read_header(&hdr2, new_file->page); hdr2.log_record_size = hdr.log_record_size; hdr2.log_records = hdr.log_records; @@ -1102,7 +1102,7 @@ cfs_read(int fd, void *buf, unsigned size) size = file->end - fdp->offset; } - /* If the file is allocated, read directly in the file. */ + /* If the file is not modified, read directly from the file extent. */ if(!FILE_MODIFIED(file)) { COFFEE_READ(buf, size, absolute_offset(file->page, fdp->offset)); fdp->offset += size; @@ -1113,8 +1113,9 @@ cfs_read(int fd, void *buf, unsigned size) read_header(&hdr, file->page); /* - * Fill the buffer by copying from the log in first hand, or the - * ordinary file if the page has no log record. + * Copy the contents of the most recent log record. If there is + * no log record for the file area to read from, we simply read + * from the original file extent. */ for(bytes_left = size; bytes_left > 0; bytes_left -= r) { lp.offset = fdp->offset; @@ -1242,8 +1243,8 @@ int cfs_opendir(struct cfs_dir *dir, const char *name) { /* - * Coffee is only guaranteed to support "/" and ".", but it does not - * currently enforce this. + * Coffee is only guaranteed to support the directory names "/" and ".", + * but it does not enforce this currently. */ memset(dir->dummy_space, 0, sizeof(coffee_page_t)); return 0; @@ -1254,13 +1255,13 @@ cfs_readdir(struct cfs_dir *dir, struct cfs_dirent *record) { struct file_header hdr; coffee_page_t page; + coffee_page_t next_page; memcpy(&page, dir->dummy_space, sizeof(coffee_page_t)); while(page < COFFEE_PAGE_COUNT) { read_header(&hdr, page); if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr)) { - coffee_page_t next_page; memcpy(record->name, hdr.name, sizeof(record->name)); record->name[sizeof(record->name) - 1] = '\0'; record->size = file_end(page); @@ -1334,9 +1335,9 @@ cfs_coffee_set_io_semantics(int fd, unsigned flags) int cfs_coffee_format(void) { - unsigned i; + coffee_page_t i; - PRINTF("Coffee: Formatting %u sectors", COFFEE_SECTOR_COUNT); + PRINTF("Coffee: Formatting %u sectors", (unsigned)COFFEE_SECTOR_COUNT); for(i = 0; i < COFFEE_SECTOR_COUNT; i++) { COFFEE_ERASE(i); diff --git a/core/cfs/cfs-coffee.h b/core/cfs/cfs-coffee.h index a227792a1..2c62f2512 100644 --- a/core/cfs/cfs-coffee.h +++ b/core/cfs/cfs-coffee.h @@ -46,15 +46,15 @@ * 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. + * algorithms such as database indices on top of Coffee. * * \sa cfs_coffee_set_io_semantics() */ #define CFS_COFFEE_IO_FLASH_AWARE 0x1 /** - * Instruct Coffee not to attempt to extend the file when there is - * an attempt to write past the reserved file size. + * Instruct Coffee not to attempt to extend the file upon a request + * 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. @@ -75,8 +75,8 @@ /** * \brief Reserve space for a file. - * \param name The filename. - * \param size The size of the file. + * \param name The file name. + * \param size The initial size to be reserved for the file. * \return 0 on success, -1 on failure. * * Coffee uses sequential page structures for files. The sequential @@ -88,15 +88,15 @@ int cfs_coffee_reserve(const char *name, cfs_offset_t size); /** * \brief Configure the on-demand log file. - * \param file The filename. - * \param log_size The total log size. + * \param file The file name. + * \param log_size The total log file 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 - * file. The micro log stores a table of modifications whose - * parameters--the log size and the log entry size--can be modified - * through the cfs_coffee_configure_log function. + * file. The micro log stores a table of modifications whose parameters -- + * the log size and the log entry size -- can be modified through the + * cfs_coffee_configure_log function. */ int cfs_coffee_configure_log(const char *file, unsigned log_size, unsigned log_entry_size); @@ -109,8 +109,8 @@ int cfs_coffee_configure_log(const char *file, unsigned log_size, * * 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 + * of a certain file. Hence, this function allows programmers to + * switch the I/O semantics on a file that is accessed through a * particular file descriptor. * */ @@ -123,21 +123,14 @@ int cfs_coffee_set_io_semantics(int fd, unsigned flags); * Coffee formats the underlying storage by setting all bits to zero. * Formatting must be done before using Coffee for the first time in * a mote. + * + * Notice that the erased bits may be set to 1 on the physical storage + * when using flash memory. In this case, Coffee requires that the + * COFFEE_READ and COFFEE_WRITE functions used to access the flash memory + * invert all bits. */ int cfs_coffee_format(void); -/** - * \brief Points out a memory region that may not be altered during - * checkpointing operations that use the file system. - * \param size - * \return A pointer to the protected memory. - * - * This function returns the protected memory pointer and writes its size - * to the given parameter. Mainly used by sensornet checkpointing to protect - * the coffee state during CFS-based checkpointing operations. - */ -void *cfs_coffee_get_protected_mem(unsigned *size); - /** @} */ /** @} */