mirror of
https://github.com/oliverschmidt/contiki.git
synced 2025-01-03 11:30:53 +00:00
fixed GC bug with big files and unwanted buffer overwrite bug.
This commit is contained in:
parent
1a2084b597
commit
349e14abd4
@ -40,7 +40,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 1
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define PRINTF(...) printf(__VA_ARGS__)
|
#define PRINTF(...) printf(__VA_ARGS__)
|
||||||
@ -110,7 +110,7 @@
|
|||||||
#define COFFEE_PAGES_PER_SECTOR \
|
#define COFFEE_PAGES_PER_SECTOR \
|
||||||
((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE))
|
((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE))
|
||||||
|
|
||||||
struct sector_stats {
|
struct sector_status {
|
||||||
coffee_page_t active;
|
coffee_page_t active;
|
||||||
coffee_page_t obsolete;
|
coffee_page_t obsolete;
|
||||||
coffee_page_t free;
|
coffee_page_t free;
|
||||||
@ -185,7 +185,7 @@ absolute_offset(coffee_page_t page, cfs_offset_t offset)
|
|||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static coffee_page_t
|
static coffee_page_t
|
||||||
get_sector_status(uint16_t sector, struct sector_stats *stats)
|
get_sector_status(uint16_t sector, struct sector_status *stats)
|
||||||
{
|
{
|
||||||
static coffee_page_t skip_pages;
|
static coffee_page_t skip_pages;
|
||||||
static char last_pages_are_active;
|
static char last_pages_are_active;
|
||||||
@ -194,6 +194,7 @@ get_sector_status(uint16_t sector, struct sector_stats *stats)
|
|||||||
coffee_page_t sector_start, sector_end;
|
coffee_page_t sector_start, sector_end;
|
||||||
coffee_page_t page;
|
coffee_page_t page;
|
||||||
|
|
||||||
|
memset(stats, 0, sizeof(*stats));
|
||||||
active = obsolete = free = 0;
|
active = obsolete = free = 0;
|
||||||
|
|
||||||
if(sector == 0) {
|
if(sector == 0) {
|
||||||
@ -205,9 +206,19 @@ get_sector_status(uint16_t sector, struct sector_stats *stats)
|
|||||||
sector_end = sector_start + COFFEE_PAGES_PER_SECTOR;
|
sector_end = sector_start + COFFEE_PAGES_PER_SECTOR;
|
||||||
|
|
||||||
if(last_pages_are_active) {
|
if(last_pages_are_active) {
|
||||||
active = skip_pages & (COFFEE_PAGES_PER_SECTOR - 1);
|
if(skip_pages >= COFFEE_PAGES_PER_SECTOR) {
|
||||||
|
stats->active = COFFEE_PAGES_PER_SECTOR;
|
||||||
|
skip_pages -= COFFEE_PAGES_PER_SECTOR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
active = skip_pages;
|
||||||
} else {
|
} else {
|
||||||
obsolete = skip_pages & (COFFEE_PAGES_PER_SECTOR - 1);
|
if(skip_pages >= COFFEE_PAGES_PER_SECTOR) {
|
||||||
|
stats->obsolete = COFFEE_PAGES_PER_SECTOR;
|
||||||
|
skip_pages -= COFFEE_PAGES_PER_SECTOR;
|
||||||
|
return skip_pages + COFFEE_PAGES_PER_SECTOR;
|
||||||
|
}
|
||||||
|
obsolete = skip_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(page = sector_start + skip_pages; page < sector_end;) {
|
for(page = sector_start + skip_pages; page < sector_end;) {
|
||||||
@ -269,8 +280,8 @@ static void
|
|||||||
collect_garbage(int mode)
|
collect_garbage(int mode)
|
||||||
{
|
{
|
||||||
uint16_t sector;
|
uint16_t sector;
|
||||||
struct sector_stats stats;
|
struct sector_status stats;
|
||||||
coffee_page_t first_page, skip_pages;
|
coffee_page_t first_page, isolation_count;
|
||||||
|
|
||||||
watchdog_stop();
|
watchdog_stop();
|
||||||
|
|
||||||
@ -281,9 +292,10 @@ collect_garbage(int mode)
|
|||||||
* erasable if there are only free or obsolete pages in it.
|
* erasable if there are only free or obsolete pages in it.
|
||||||
*/
|
*/
|
||||||
for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) {
|
for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) {
|
||||||
skip_pages = get_sector_status(sector, &stats);
|
isolation_count = get_sector_status(sector, &stats);
|
||||||
PRINTF("Coffee: Sector %u has %u active, %u free, and %u obsolete pages.\n",
|
PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n",
|
||||||
sector, (unsigned)stats.active, (unsigned)stats.free, (unsigned)stats.obsolete);
|
sector, (unsigned)stats.active,
|
||||||
|
(unsigned)stats.obsolete, (unsigned)stats.free);
|
||||||
|
|
||||||
if(stats.active > 0) {
|
if(stats.active > 0) {
|
||||||
continue;
|
continue;
|
||||||
@ -296,8 +308,8 @@ collect_garbage(int mode)
|
|||||||
*next_free = first_page;
|
*next_free = first_page;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(skip_pages > 0) {
|
if(isolation_count > 0) {
|
||||||
isolate_pages(first_page + COFFEE_PAGES_PER_SECTOR, skip_pages);
|
isolate_pages(first_page + COFFEE_PAGES_PER_SECTOR, isolation_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
COFFEE_ERASE(sector);
|
COFFEE_ERASE(sector);
|
||||||
@ -659,8 +671,8 @@ create_log(struct file *file, struct file_header *hdr)
|
|||||||
|
|
||||||
adjust_log_config(hdr, &log_record_size, &log_records);
|
adjust_log_config(hdr, &log_record_size, &log_records);
|
||||||
|
|
||||||
size = log_records * sizeof(uint16_t); /* Log index size. */
|
/* Log index size + log data size. */
|
||||||
size += log_records * log_record_size; /* Log data size. */
|
size = log_records * (sizeof(uint16_t) + log_record_size);
|
||||||
|
|
||||||
log_file = reserve(hdr->name, page_count(size), 1, HDR_FLAG_LOG);
|
log_file = reserve(hdr->name, page_count(size), 1, HDR_FLAG_LOG);
|
||||||
if(log_file == NULL) {
|
if(log_file == NULL) {
|
||||||
@ -758,10 +770,13 @@ find_next_record(struct file *file, coffee_page_t log_page,
|
|||||||
{
|
{
|
||||||
int log_record, preferred_batch_size;
|
int log_record, preferred_batch_size;
|
||||||
|
|
||||||
|
if(file->next_log_record >= 0) {
|
||||||
|
return file->next_log_record;
|
||||||
|
}
|
||||||
|
|
||||||
preferred_batch_size = log_records > COFFEE_LOG_TABLE_LIMIT ?
|
preferred_batch_size = log_records > COFFEE_LOG_TABLE_LIMIT ?
|
||||||
COFFEE_LOG_TABLE_LIMIT : log_records;
|
COFFEE_LOG_TABLE_LIMIT : log_records;
|
||||||
|
{
|
||||||
if(file->next_log_record == -1) {
|
|
||||||
/* The next log record is unknown. Search for it. */
|
/* The next log record is unknown. Search for it. */
|
||||||
uint16_t indices[preferred_batch_size];
|
uint16_t indices[preferred_batch_size];
|
||||||
uint16_t processed;
|
uint16_t processed;
|
||||||
@ -781,8 +796,6 @@ find_next_record(struct file *file, coffee_page_t log_page,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log_record = file->next_log_record;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return log_record;
|
return log_record;
|
||||||
@ -840,7 +853,7 @@ write_log_page(struct file *file, struct log_param *lp)
|
|||||||
absolute_offset(file->page, offset));
|
absolute_offset(file->page, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy((char *) ©_buf + lp->offset, lp->buf, lp->size);
|
memcpy((char *)©_buf + lp->offset, lp->buf, lp->size);
|
||||||
|
|
||||||
offset = absolute_offset(log_page, 0);
|
offset = absolute_offset(log_page, 0);
|
||||||
++region;
|
++region;
|
||||||
@ -1024,6 +1037,7 @@ cfs_write(int fd, const void *buf, unsigned size)
|
|||||||
int i;
|
int i;
|
||||||
struct log_param lp;
|
struct log_param lp;
|
||||||
cfs_offset_t bytes_left;
|
cfs_offset_t bytes_left;
|
||||||
|
const char dummy[1] = { 0xff };
|
||||||
|
|
||||||
if(!(FD_VALID(fd) && FD_WRITABLE(fd))) {
|
if(!(FD_VALID(fd) && FD_WRITABLE(fd))) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -1068,8 +1082,7 @@ cfs_write(int fd, const void *buf, unsigned size)
|
|||||||
|
|
||||||
if(fdp->offset > file->end) {
|
if(fdp->offset > file->end) {
|
||||||
/* Update the original file's end with a dummy write. */
|
/* Update the original file's end with a dummy write. */
|
||||||
*(char *)buf = 0xff;
|
COFFEE_WRITE(dummy, 1, absolute_offset(file->page, fdp->offset));
|
||||||
COFFEE_WRITE(buf, 1, absolute_offset(file->page, fdp->offset));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset));
|
COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset));
|
||||||
|
Loading…
Reference in New Issue
Block a user