X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Ffs%2Fbattfs.c;h=a817d0beba5eea0154c53e134b06d61b9ad25d91;hb=c36d4b6e73fd7e760f1a99fd2d87d7083fd87933;hp=6253af88b8f37a875dca6bd11a5c4ecfb55e044a;hpb=82697da95a4f826ecd42451e0ccb8902e2fbb96f;p=bertos.git diff --git a/bertos/fs/battfs.c b/bertos/fs/battfs.c index 6253af88..a817d0be 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 @@ -156,8 +156,8 @@ static bool battfs_writeHeader(struct BattFsSuper *disk, pgcnt_t page, struct Ba * Header is actually a footer, and so * resides at page end. */ - if (disk->write(disk, page, disk->page_size - BATTFS_HEADER_LEN, buf, BATTFS_HEADER_LEN) - != BATTFS_HEADER_LEN) + if (!(disk->bufferWrite(disk, disk->page_size - BATTFS_HEADER_LEN, buf, BATTFS_HEADER_LEN) + == BATTFS_HEADER_LEN && disk->save(disk, page))) { LOG_ERR("Error: page[%d]\n", page); return false; @@ -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. @@ -363,7 +401,9 @@ bool battfs_init(struct BattFsSuper *disk) /* Disk open must set all of these */ ASSERT(disk->read); - ASSERT(disk->write); + ASSERT(disk->load); + ASSERT(disk->bufferWrite); + ASSERT(disk->save); ASSERT(disk->erase); ASSERT(disk->close); ASSERT(disk->page_size); @@ -395,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); @@ -407,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; } /** @@ -425,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. @@ -447,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) { @@ -505,19 +621,19 @@ bool battfs_fileExists(BattFsSuper *disk, inode_t inode) * in disk->page_array. Size is written in \a size. * \return true if all s ok, false on disk read errors. */ -static bool countFileSize(BattFsSuper *disk, pgcnt_t *start, inode_t inode, file_size_t *size) +static file_size_t countFileSize(BattFsSuper *disk, pgcnt_t *start, inode_t inode) { - *size = 0; + file_size_t size = 0; BattFsPageHeader hdr; for (;;) { if (!battfs_readHeader(disk, *start++, &hdr)) - return false; + return EOF; if (hdr.fcs == computeFcs(&hdr) && hdr.inode == inode) - *size += hdr.fill; + size += hdr.fill; else - return true; + return size; } } @@ -550,7 +666,7 @@ bool battfs_fileopen(BattFsSuper *disk, BattFs *fd, inode_t inode, filemode_t mo } /* Fill file size */ - if (!countFileSize(disk, fd->start, inode, &fd->fd.size)) + if ((fd->fd.size = countFileSize(disk, fd->start, inode)) == EOF) return false; /* Reset seek position */ @@ -575,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 @@ -612,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;