From 2b906c8f200a037e15db7717ebc74f12907adf71 Mon Sep 17 00:00:00 2001 From: batt Date: Fri, 19 Sep 2008 16:26:14 +0000 Subject: [PATCH] Add preliminary write support; initialize to 0xff the memory in battfs_writeTestBlock; implement battfs_flush. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@1814 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/fs/battfs.c | 131 ++++++++++++++++++++++++++++++++++++++++++--- bertos/fs/battfs.h | 2 + 2 files changed, 127 insertions(+), 6 deletions(-) diff --git a/bertos/fs/battfs.c b/bertos/fs/battfs.c index 59b03ae4..d8fdfc3f 100644 --- a/bertos/fs/battfs.c +++ b/bertos/fs/battfs.c @@ -44,7 +44,7 @@ #include /* MIN, MAX */ #include /* cpu_to_xx */ -#define LOG_LEVEL LOG_LVL_INFO +#define LOG_LEVEL LOG_LVL_WARNING #define LOG_FORMAT LOG_FMT_VERBOSE #include @@ -342,6 +342,44 @@ static bool fillPageArray(struct BattFsSuper *disk, pgoff_t *filelen_table) return true; } + +/** + * Flush the current \a disk buffer. + * \return true if ok, false on errors. + */ +static bool battfs_flushBuffer(struct BattFsSuper *disk) +{ + if (disk->cache_dirty) + { + TRACE; + if (!disk->save(disk, disk->curr_page)) + return false; + disk->cache_dirty = false; + } + return true; +} + +/** + * Load \a new_page from \a disk in disk page buffer. + * If a previuos page is still dirty in the buffer, will be + * flushed first. + * \return true if ok, false on errors. + */ +static bool battfs_loadPage(struct BattFsSuper *disk, pgcnt_t new_page) +{ + if (disk->curr_page == new_page) + return true; + + if (battfs_flushBuffer(disk)) + return false; + + if (!disk->load(disk, new_page)) + return false; + disk->curr_page = new_page; + return true; +} + + /** * Initialize and mount disk described by * \a disk. @@ -397,6 +435,12 @@ bool battfs_init(struct BattFsSuper *disk) LOG_ERR("error filling page array\n"); return false; } + #warning TODO: shuffle free blocks + + /* Initialize page buffer cache */ + disk->cache_dirty = false; + disk->curr_page = 0; + disk->load(disk, disk->curr_page); /* Init list for opened files. */ LIST_INIT(&disk->file_opened_list); @@ -409,9 +453,12 @@ bool battfs_init(struct BattFsSuper *disk) */ static int battfs_flush(struct KFile *fd) { - (void)fd; - #warning TODO - return 0; + BattFs *fdb = BATTFS_CAST(fd); + + if (battfs_flushBuffer(fdb->disk)) + return 0; + else + return EOF; } /** @@ -427,6 +474,69 @@ static int battfs_fileclose(struct KFile *fd) return 0; } + +/** + * Write to file \a fd \a size bytes from \a buf. + * \return The number of bytes written. + */ +static size_t battfs_write(struct KFile *fd, const void *_buf, size_t size) +{ + BattFs *fdb = BATTFS_CAST(fd); + const uint8_t *buf = (const uint8_t *)_buf; + + size_t total_write = 0; + pgoff_t pg_offset; + pgaddr_t addr_offset; + pgaddr_t wr_len; + + size = MIN((kfile_off_t)size, fd->size - fd->seek_pos); + + while (size) + { + #warning TODO: outside EOF? + + pg_offset = fd->seek_pos / (fdb->disk->page_size - BATTFS_HEADER_LEN); + addr_offset = fd->seek_pos % (fdb->disk->page_size - BATTFS_HEADER_LEN); + wr_len = MIN(size, (size_t)(fdb->disk->page_size - BATTFS_HEADER_LEN - addr_offset)); + + + if (fdb->start[pg_offset] != fdb->disk->curr_page) + { + if (!battfs_loadPage(fdb->disk, fdb->start[pg_offset])) + { + #warning TODO set error? + return total_write; + } + + /* Get a free page */ + fdb->disk->curr_page = fdb->disk->page_array[fdb->disk->free_page_start]; + movePages(fdb->disk, fdb->disk->free_page_start + 1, -1); + + /* Insert previous page in free blocks list */ + fdb->disk->page_array[fdb->disk->page_count - 1] = fdb->start[pg_offset]; + /* Assign new page */ + fdb->start[pg_offset] = fdb->disk->curr_page; + #warning TODO: hdr have to be updated! + } + + + if (fdb->disk->bufferWrite(fdb->disk, addr_offset, buf, wr_len) != wr_len) + { + #warning TODO set error? + } + fdb->disk->cache_dirty = true; + + size -= wr_len; + fd->seek_pos += wr_len; + total_write += wr_len; + buf += wr_len; + #warning TODO: hdr have to be updated! + } + return total_write; + +} + + /** * Read from file \a fd \a size bytes in \a buf. * \return The number of bytes read. @@ -449,6 +559,10 @@ static size_t battfs_read(struct KFile *fd, void *_buf, size_t size) addr_offset = fd->seek_pos % (fdb->disk->page_size - BATTFS_HEADER_LEN); read_len = MIN(size, (size_t)(fdb->disk->page_size - BATTFS_HEADER_LEN - addr_offset)); + /* Flush current page if needed */ + if (fdb->start[pg_offset] == fdb->disk->curr_page) + battfs_flushBuffer(fdb->disk); + /* Read from disk */ if (fdb->disk->read(fdb->disk, fdb->start[pg_offset], addr_offset, buf, read_len) != read_len) { @@ -577,10 +691,10 @@ bool battfs_fileopen(BattFsSuper *disk, BattFs *fd, inode_t inode, filemode_t mo fd->fd.read = battfs_read; fd->fd.reopen = kfile_genericReopen; fd->fd.seek = kfile_genericSeek; + fd->fd.write = battfs_write; -#warning TODO battfs_write, battfs_error, battfs_clearerr +#warning TODO battfs_error, battfs_clearerr #if 0 - fd->fd.write = battfs_write; fd->fd.error = battfs_error; fd->fd.clearerr = battfs_clearerr; #endif @@ -614,6 +728,11 @@ bool battfs_writeTestBlock(struct BattFsSuper *disk, pgcnt_t page, inode_t inode { BattFsPageHeader hdr; + /* Reset page to all 0xff */ + uint8_t buf[disk->page_size]; + memset(buf, 0xFF, disk->page_size); + disk->bufferWrite(disk, 0, buf, disk->page_size); + hdr.inode = inode; hdr.fill = fill; hdr.pgoff = pgoff; diff --git a/bertos/fs/battfs.h b/bertos/fs/battfs.h index d5afb523..e0829917 100644 --- a/bertos/fs/battfs.h +++ b/bertos/fs/battfs.h @@ -194,6 +194,8 @@ typedef struct BattFsSuper * the entire disk in memory. */ pgcnt_t *page_array; + pgcnt_t curr_page; + bool cache_dirty; /** * Lowest address, in page array, for free pages. -- 2.25.1