X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Ffs%2Fbattfs.c;h=f40d310d8d3bae3d77f500dbd6640f30b9054700;hb=e8b0472be10fba4ca6baa62d8d483db90e28c06e;hp=dbed578183670bd28721c9d75548dca536d968e0;hpb=706954ecdc8313eb3dd0a23190ae9d12cd4392a3;p=bertos.git diff --git a/bertos/fs/battfs.c b/bertos/fs/battfs.c index dbed5781..f40d310d 100644 --- a/bertos/fs/battfs.c +++ b/bertos/fs/battfs.c @@ -32,7 +32,6 @@ * * \brief BattFS: a filesystem for embedded platforms (implementation). * - * \version $Id$ * * \author Francesco Sacchi * @@ -55,7 +54,7 @@ static void dumpPageArray(struct BattFsSuper *disk) { kprintf("Page array dump, free_page_start %d:", disk->free_page_start); - for (pgcnt_t i = 0; i < disk->page_count; i++) + for (pgcnt_t i = 0; i < disk->dev->blk_cnt; i++) { if (!(i % 16)) kputchar('\n'); @@ -199,13 +198,13 @@ static pgcnt_t countPages(pgoff_t *filelen_table, inode_t inode) static void movePages(struct BattFsSuper *disk, pgcnt_t src, int offset) { pgcnt_t dst = src + offset; - LOG_INFO("src %d, offset %d, size %d\n", src, offset, (unsigned int)((disk->page_count - MAX(dst, src)) * sizeof(pgcnt_t))); - memmove(&disk->page_array[dst], &disk->page_array[src], (disk->page_count - MAX(dst, src)) * sizeof(pgcnt_t)); + LOG_INFO("src %d, offset %d, size %d\n", src, offset, (unsigned int)((disk->dev->blk_cnt - MAX(dst, src)) * sizeof(pgcnt_t))); + memmove(&disk->page_array[dst], &disk->page_array[src], (disk->dev->blk_cnt - MAX(dst, src)) * sizeof(pgcnt_t)); if (offset < 0) { /* Fill empty space in array with sentinel */ - for (pgcnt_t page = disk->page_count + offset; page < disk->page_count; page++) + for (pgcnt_t page = disk->dev->blk_cnt + offset; page < disk->dev->blk_cnt; page++) disk->page_array[page] = PAGE_UNSET_SENTINEL; } } @@ -225,7 +224,7 @@ static bool countDiskFilePages(struct BattFsSuper *disk, pgoff_t *filelen_table) disk->free_page_start = 0; /* Count the number of disk page per file */ - for (pgcnt_t page = 0; page < disk->page_count; page++) + for (pgcnt_t page = 0; page < disk->dev->blk_cnt; page++) { if (!readHdr(disk, page, &hdr)) return false; @@ -270,7 +269,7 @@ static bool fillPageArray(struct BattFsSuper *disk, pgoff_t *filelen_table) BattFsPageHeader hdr; pgcnt_t curr_free_page = disk->free_page_start; /* Fill page allocation array */ - for (pgcnt_t page = 0; page < disk->page_count; page++) + for (pgcnt_t page = 0; page < disk->dev->blk_cnt; page++) { if (!readHdr(disk, page, &hdr)) return false; @@ -367,23 +366,22 @@ bool battfs_mount(struct BattFsSuper *disk, struct KBlock *dev, pgcnt_t *page_ar pgoff_t filelen_table[BATTFS_MAX_FILES]; ASSERT(dev); + ASSERT(kblock_partialWrite(dev)); disk->dev = dev; - disk->page_size = dev->blk_size; - disk->page_count = dev->blk_cnt; - ASSERT(disk->page_size > BATTFS_HEADER_LEN); + ASSERT(disk->dev->blk_size > BATTFS_HEADER_LEN); /* Fill page_size with the usable space */ - disk->data_size = disk->page_size - BATTFS_HEADER_LEN; - ASSERT(disk->page_count); - ASSERT(disk->page_count < PAGE_UNSET_SENTINEL - 1); + disk->data_size = disk->dev->blk_size - BATTFS_HEADER_LEN; + ASSERT(disk->dev->blk_cnt); + ASSERT(disk->dev->blk_cnt < PAGE_UNSET_SENTINEL - 1); ASSERT(page_array); disk->page_array = page_array; - ASSERT(array_size >= disk->page_count * sizeof(pgcnt_t)); + ASSERT(array_size >= disk->dev->blk_cnt * sizeof(pgcnt_t)); memset(filelen_table, 0, BATTFS_MAX_FILES * sizeof(pgoff_t)); disk->free_bytes = 0; - disk->disk_size = (disk_size_t)disk->data_size * disk->page_count; + disk->disk_size = (disk_size_t)disk->data_size * disk->dev->blk_cnt; /* Count pages per file */ if (!countDiskFilePages(disk, filelen_table)) @@ -395,7 +393,7 @@ bool battfs_mount(struct BattFsSuper *disk, struct KBlock *dev, pgcnt_t *page_ar /* Once here, we have filelen_table filled with file lengths */ /* Fill page array with sentinel */ - for (pgcnt_t page = 0; page < disk->page_count; page++) + for (pgcnt_t page = 0; page < disk->dev->blk_cnt; page++) disk->page_array[page] = PAGE_UNSET_SENTINEL; /* Fill page allocation array using filelen_table */ @@ -408,7 +406,7 @@ bool battfs_mount(struct BattFsSuper *disk, struct KBlock *dev, pgcnt_t *page_ar dumpPageArray(disk); #endif #if CONFIG_BATTFS_SHUFFLE_FREE_PAGES - SHUFFLE(&disk->page_array[disk->free_page_start], disk->page_count - disk->free_page_start); + SHUFFLE(&disk->page_array[disk->free_page_start], disk->dev->blk_cnt - disk->free_page_start); LOG_INFO("Page array after shuffle:\n"); #if LOG_LEVEL >= LOG_LVL_INFO @@ -428,8 +426,8 @@ bool battfs_fsck(struct BattFsSuper *disk) { #define FSCHECK(cond) do { if(!(cond)) { LOG_ERR("\"" #cond "\"\n"); return false; } } while (0) - FSCHECK(disk->free_page_start <= disk->page_count); - FSCHECK(disk->data_size < disk->page_size); + FSCHECK(disk->free_page_start <= disk->dev->blk_cnt); + FSCHECK(disk->data_size < disk->dev->blk_size); FSCHECK(disk->free_bytes <= disk->disk_size); disk_size_t free_bytes = 0; @@ -442,7 +440,7 @@ bool battfs_fsck(struct BattFsSuper *disk) /* Uneeded, the first time will be overwritten but useful to silence * the warning for uninitialized value */ FSCHECK(readHdr(disk, 0, &prev_hdr)); - for (pgcnt_t page = 0; page < disk->page_count; page++) + for (pgcnt_t page = 0; page < disk->dev->blk_cnt; page++) { FSCHECK(readHdr(disk, disk->page_array[page], &hdr)); free_bytes += disk->data_size; @@ -547,7 +545,7 @@ static pgcnt_t renewPage(struct BattFsSuper *disk, pgcnt_t old_pos) if (SPACE_OVER(disk)) { LOG_ERR("No disk space available!\n"); - return PAGE_UNSET_SENTINEL; + return NO_SPACE; } /* Get a free page */ @@ -556,7 +554,7 @@ static pgcnt_t renewPage(struct BattFsSuper *disk, pgcnt_t old_pos) /* Insert previous page in free blocks list */ LOG_INFO("Setting page %d as free\n", old_pos); - disk->page_array[disk->page_count - 1] = old_pos; + disk->page_array[disk->dev->blk_cnt - 1] = old_pos; return new_page; } @@ -591,18 +589,31 @@ static size_t battfs_write(struct KFile *fd, const void *_buf, size_t size) return total_write; } - new_page = renewPage(disk, fdb->start[fdb->max_off]); - if (new_page == NO_SPACE) + /* + * Renew page only if is not in cache. + * This avoids rewriting the same page continuously + * if the user code keeps writing in the same portion + * of the file. + */ + if (kblock_buffered(disk->dev) + && ((fdb->start[fdb->max_off] != kblock_cachedBlock(disk->dev)) || !kblock_cacheDirty(disk->dev))) { - fdb->errors |= BATTFS_DISK_SPACEOVER_ERR; - return total_write; - } + new_page = renewPage(disk, fdb->start[fdb->max_off]); + if (new_page == NO_SPACE) + { + fdb->errors |= BATTFS_DISK_SPACEOVER_ERR; + return total_write; + } - kblock_copy(disk->dev, fdb->start[fdb->max_off], new_page); - fdb->start[fdb->max_off] = new_page; + kblock_copy(disk->dev, fdb->start[fdb->max_off], new_page); + fdb->start[fdb->max_off] = new_page; + } + else + new_page = fdb->start[fdb->max_off]; /* Fill unused space of first page with 0s */ uint8_t dummy = 0; + // TODO: write in blocks to speed up things pgaddr_t zero_bytes = MIN(fd->seek_pos - fd->size, (kfile_off_t)(disk->data_size - curr_hdr.fill)); while (zero_bytes--) { @@ -625,46 +636,44 @@ static size_t battfs_write(struct KFile *fd, const void *_buf, size_t size) /* Allocate the missing pages first. */ pgoff_t missing_pages = fd->seek_pos / disk->data_size - fdb->max_off; - if (missing_pages) + LOG_INFO("missing pages: %d\n", missing_pages); + + while (missing_pages--) { - LOG_INFO("missing pages: %d\n", missing_pages); + zero_bytes = MIN((kfile_off_t)disk->data_size, fd->seek_pos - fd->size); - while (missing_pages--) + new_page = allocateNewPage(disk, (fdb->start - disk->page_array) + fdb->max_off + 1, fdb->inode); + if (new_page == NO_SPACE) { - zero_bytes = MIN((kfile_off_t)disk->data_size, fd->seek_pos - fd->size); - - new_page = allocateNewPage(disk, (fdb->start - disk->page_array) + fdb->max_off + 1, fdb->inode); - if (new_page == NO_SPACE) - { - fdb->errors |= BATTFS_DISK_SPACEOVER_ERR; - return total_write; - } - + fdb->errors |= BATTFS_DISK_SPACEOVER_ERR; + return total_write; + } - /* Fill page buffer with 0 to avoid filling unused pages with garbage */ - for (pgaddr_t off = 0; off < disk->data_size; off++) - { - if (kblock_write(disk->dev, new_page, &dummy, off, 1) != 1) - { - fdb->errors |= BATTFS_DISK_WRITE_ERR; - return total_write; - } - } - curr_hdr.inode = fdb->inode; - curr_hdr.pgoff = ++fdb->max_off; - curr_hdr.fill = zero_bytes; - curr_hdr.seq = 0; - if (!writeHdr(disk, new_page, &curr_hdr)) + // TODO: write in blocks to speed up things + /* Fill page buffer with 0 to avoid filling unused pages with garbage */ + for (pgaddr_t off = 0; off < disk->data_size; off++) + { + if (kblock_write(disk->dev, new_page, &dummy, off, 1) != 1) { fdb->errors |= BATTFS_DISK_WRITE_ERR; return total_write; } + } + curr_hdr.inode = fdb->inode; + curr_hdr.pgoff = ++fdb->max_off; + curr_hdr.fill = zero_bytes; + curr_hdr.seq = 0; - /* Update size and free space left */ - fd->size += zero_bytes; - disk->free_bytes -= zero_bytes; + if (!writeHdr(disk, new_page, &curr_hdr)) + { + fdb->errors |= BATTFS_DISK_WRITE_ERR; + return total_write; } + + /* Update size and free space left */ + fd->size += zero_bytes; + disk->free_bytes -= zero_bytes; } } @@ -700,20 +709,31 @@ static size_t battfs_write(struct KFile *fd, const void *_buf, size_t size) return total_write; } - new_page = renewPage(disk, fdb->start[pg_offset]); - if (new_page == NO_SPACE) + /* Renew page only if is not in cache. */ + if (kblock_buffered(disk->dev) + && ((fdb->start[fdb->max_off] != kblock_cachedBlock(disk->dev)) || !kblock_cacheDirty(disk->dev))) { - fdb->errors |= BATTFS_DISK_SPACEOVER_ERR; - return total_write; - } + new_page = renewPage(disk, fdb->start[pg_offset]); + if (new_page == NO_SPACE) + { + fdb->errors |= BATTFS_DISK_SPACEOVER_ERR; + return total_write; + } - LOG_INFO("Re-writing page %d to %d\n", fdb->start[pg_offset], new_page); - if (kblock_copy(disk->dev, fdb->start[pg_offset], new_page) != 0) + LOG_INFO("Re-writing page %d to %d\n", fdb->start[pg_offset], new_page); + if (kblock_copy(disk->dev, fdb->start[pg_offset], new_page) != 0) + { + fdb->errors |= BATTFS_DISK_WRITE_ERR; + return total_write; + } + fdb->start[pg_offset] = new_page; + } + else { - fdb->errors |= BATTFS_DISK_WRITE_ERR; - return total_write; + LOG_INFO("Using cached block %d\n", fdb->start[pg_offset]); + new_page = fdb->start[pg_offset]; } - fdb->start[pg_offset] = new_page; + curr_hdr.seq++; } //LOG_INFO("writing to buffer for page %d, offset %d, size %d\n", disk->curr_page, addr_offset, wr_len);