コード例 #1
0
ファイル: cfs-coffee.c プロジェクト: dreimers/contiki-inga
/*---------------------------------------------------------------------------*/
static void
write_header(struct file_header *hdr, coffee_page_t page)
{
  hdr->flags |= HDR_FLAG_VALID;
  COFFEE_WRITE(hdr, sizeof(*hdr), page * COFFEE_PAGE_SIZE);
	PRINTF("hdr.flags = %x\n", hdr->flags);
}
コード例 #2
0
ファイル: cfs-coffee.c プロジェクト: zzuzpb/contiki-2.7-xc8
static int
write_log_page(struct file *file, struct log_param *lp)
{
  struct file_header hdr;
  uint16_t region;
  coffee_page_t log_page;
  int16_t log_record;
  uint16_t log_record_size;
  uint16_t log_records;
  cfs_offset_t offset;
  struct log_param lp_out;

  read_header(&hdr, file->page);

  adjust_log_config(&hdr, &log_record_size, &log_records);
  region = modify_log_buffer(log_record_size, &lp->offset, &lp->size);

  log_page = 0;
  if(HDR_MODIFIED(hdr)) {
    /* A log structure has already been created. */
    log_page = hdr.log_page;
    log_record = find_next_record(file, log_page, log_records);
    if(log_record >= log_records) {
      /* The log is full; merge the log. */
      PRINTF(("Coffee: Merging the file %s with its log\n", hdr.name));
      return merge_log(file->page, 0);
    }
  } else {
    /* Create a log structure. */
    log_page = create_log(file, &hdr);
    if(log_page == INVALID_PAGE) {
      return -1;
    }
    PRINTF(("Coffee: Created a log structure for file %s at page %u\n",
    	hdr.name, (unsigned)log_page));
    hdr.log_page = log_page;
    log_record = 0;
  }

  {
    char copy_buf[log_record_size];

    lp_out.offset = offset = region * log_record_size;
    lp_out.buf = copy_buf;
    lp_out.size = log_record_size;

    if((lp->offset > 0 || lp->size != log_record_size) &&
	read_log_page(&hdr, log_record, &lp_out) < 0) {
      COFFEE_READ(copy_buf, sizeof(copy_buf),
	  absolute_offset(file->page, offset));
    }

    memcpy(&copy_buf[lp->offset], lp->buf, lp->size);

    /*
     * Write the region number in the region index table.
     * The region number is incremented to avoid values of zero.
     */
    offset = absolute_offset(log_page, 0);
    ++region;
    COFFEE_WRITE(&region, sizeof(region),
		 offset + log_record * sizeof(region));

    offset += log_records * sizeof(region);
    COFFEE_WRITE(copy_buf, sizeof(copy_buf),
		 offset + log_record * log_record_size);
    file->record_count = log_record + 1;
  }

  return lp->size;
}
コード例 #3
0
ファイル: cfs-coffee.c プロジェクト: zzuzpb/contiki-2.7-xc8
/*---------------------------------------------------------------------------*/
static int
merge_log(coffee_page_t file_page, int extend)
{
  struct file_header hdr, hdr2;
  int fd, n;
  cfs_offset_t offset;
  coffee_page_t max_pages;
  struct file *new_file;
  int i;

  read_header(&hdr, file_page);

  fd = cfs_open(hdr.name, CFS_READ);
  if(fd < 0) {
    return -1;
  }

  /*
   * The reservation function adds extra space for the header, which has
   * already been accounted for in the previous reservation.
   */
  max_pages = hdr.max_pages << extend;
  new_file = reserve(hdr.name, max_pages, 1, 0);
  if(new_file == NULL) {
    cfs_close(fd);
    return -1;
  }

  offset = 0;
  do {
    char buf[hdr.log_record_size == 0 ? COFFEE_PAGE_SIZE : hdr.log_record_size];
    n = cfs_read(fd, buf, sizeof(buf));
    if(n < 0) {
      remove_by_page(new_file->page, !REMOVE_LOG, !CLOSE_FDS, ALLOW_GC);
      cfs_close(fd);
      return -1;
    } else if(n > 0) {
      COFFEE_WRITE(buf, n, absolute_offset(new_file->page, offset));
      offset += n;
    }
  } while(n != 0);

  for(i = 0; i < COFFEE_FD_SET_SIZE; i++) {
    if(coffee_fd_set[i].flags != COFFEE_FD_FREE && 
       coffee_fd_set[i].file->page == file_page) {
      coffee_fd_set[i].file = new_file;
      new_file->references++;
    }
  }

  if(remove_by_page(file_page, REMOVE_LOG, !CLOSE_FDS, !ALLOW_GC) < 0) {
    remove_by_page(new_file->page, !REMOVE_LOG, !CLOSE_FDS, !ALLOW_GC);
    cfs_close(fd);
    return -1;
  }

  /* Copy the log configuration and the EOF hint. */
  read_header(&hdr2, new_file->page);
  hdr2.log_record_size = hdr.log_record_size;
  hdr2.log_records = hdr.log_records;
  write_header(&hdr2, new_file->page);

  new_file->flags &= ~COFFEE_FILE_MODIFIED;
  new_file->end = offset;

  cfs_close(fd);

  return 0;
}
コード例 #4
0
ファイル: cfs-coffee.c プロジェクト: zzuzpb/contiki-2.7-xc8
/*---------------------------------------------------------------------------*/
int
cfs_write(int fd, const void *buf, unsigned size)
{
  struct file_desc *fdp;
  struct file *file;
#if COFFEE_MICRO_LOGS
  int i;
  struct log_param lp;
  cfs_offset_t bytes_left;
  const char dummy[1] = { 0xff };
#endif

  if(!(FD_VALID(fd) && FD_WRITABLE(fd))) {
    return -1;
  }

  fdp = &coffee_fd_set[fd];
  file = fdp->file;

  /* Attempt to extend the file if we try to write past the end. */
#if COFFEE_IO_SEMANTICS
  if(!(fdp->io_flags & CFS_COFFEE_IO_FIRM_SIZE)) {
#endif
  while(size + fdp->offset + sizeof(struct file_header) >
     (file->max_pages * COFFEE_PAGE_SIZE)) {
    if(merge_log(file->page, 1) < 0) {
      return -1;
    }
    file = fdp->file;
    PRINTF(("Extended the file at page %u\n", (unsigned)file->page));
  }
#if COFFEE_IO_SEMANTICS
  }
#endif

#if COFFEE_MICRO_LOGS
#if COFFEE_IO_SEMANTICS
  if(!(fdp->io_flags & CFS_COFFEE_IO_FLASH_AWARE) &&
     (FILE_MODIFIED(file) || fdp->offset < file->end)) {
#else
  if(FILE_MODIFIED(file) || fdp->offset < file->end) {
#endif
    for(bytes_left = size; bytes_left > 0;) {
      lp.offset = fdp->offset;
      lp.buf = buf;
      lp.size = bytes_left;
      i = write_log_page(file, &lp);
      if(i < 0) {
	/* Return -1 if we wrote nothing because the log write failed. */
	if(size == bytes_left) {
	  return -1;
	}
	break;
      } else if(i == 0) {
        /* The file was merged with the log. */
	file = fdp->file;
      } else {
	/* A log record was written. */
	bytes_left -= i;
	fdp->offset += i;
	buf = (char *)buf + i;

        /* Update the file end for a potential log merge that might
           occur while writing log records. */
        if(fdp->offset > file->end) {
          file->end = fdp->offset;
        }
      }
    }

    if(fdp->offset > file->end) {
      /* Update the original file's end with a dummy write. */
      COFFEE_WRITE(dummy, 1, absolute_offset(file->page, fdp->offset));
    }
  } else {
#endif /* COFFEE_MICRO_LOGS */
#if COFFEE_APPEND_ONLY
    if(fdp->offset < file->end) {
      return -1;
    }
#endif /* COFFEE_APPEND_ONLY */

    COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset));
    fdp->offset += size;
#if COFFEE_MICRO_LOGS
  }
#endif /* COFFEE_MICRO_LOGS */

  if(fdp->offset > file->end) {
    file->end = fdp->offset;
  }

  return size;
}
/*---------------------------------------------------------------------------*/
int
cfs_opendir(struct cfs_dir *dir, const char *name)
{
  /*
   * Coffee is only guaranteed to support "/" and ".", but it does not 
   * currently enforce this.
   */
  memset(dir->dummy_space, 0, sizeof(coffee_page_t));
  return 0;
}
コード例 #5
0
/*---------------------------------------------------------------------------*/
int
cfs_write(int fd, const void *buf, unsigned size)
{
    struct file_desc *fdp;
    struct file *file;
#if COFFEE_MICRO_LOGS
    int i;
    struct log_param lp;
    cfs_offset_t bytes_left;
    const char dummy[1] = { 0xff };
#endif
    if(!(FD_VALID(fd) && FD_WRITABLE(fd))) {
        return -1;
    }

    fdp = &coffee_fd_set[fd];
    file = fdp->file;

    /* Attempt to extend the file if we try to write past the end. */
    while(size + fdp->offset + sizeof(struct file_header) >
            (file->max_pages * COFFEE_PAGE_SIZE)) {
        if(merge_log(file->page, 1) < 0) {
            return -1;
        }
        file = fdp->file;
        PRINTF("Extended the file at page %u\n", (unsigned)file->page);
    }

#if COFFEE_MICRO_LOGS
    if(FILE_MODIFIED(file) || fdp->offset < file->end) {
        bytes_left = size;
        while(bytes_left) {
            lp.offset = fdp->offset;
            lp.buf = buf;
            lp.size = bytes_left;
            i = write_log_page(file, &lp);
            if(i < 0) {
                /* Return -1 if we wrote nothing because the log write failed. */
                if(size == bytes_left) {
                    return -1;
                }
                break;
            } else if(i == 0) {
                /* The file was merged with the log. */
                file = fdp->file;
            } else {
                /* A log record was written. */
                bytes_left -= i;
                fdp->offset += i;
                buf += i;
            }
        }

        if(fdp->offset > file->end) {
            /* Update the original file's end with a dummy write. */
            COFFEE_WRITE(dummy, 1, absolute_offset(file->page, fdp->offset));
        }
    } else {
#endif /* COFFEE_MICRO_LOGS */
#if COFFEE_APPEND_ONLY
        if(fdp->offset < file->end) {
            return -1;
        }
#endif /* COFFEE_APPEND_ONLY */
        COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset));
        fdp->offset += size;
#if COFFEE_MICRO_LOGS
    }
#endif /* COFFEE_MICRO_LOGS */

    if(fdp->offset > file->end) {
        file->end = fdp->offset;
    }

    return size;
}
コード例 #6
0
ファイル: cfs-coffee.c プロジェクト: kincki/contiki
/*---------------------------------------------------------------------------*/
static void
get_sector_status(uint16_t sector, uint16_t *active,
		  uint16_t *free, uint16_t *obsolete) {
  uint32_t offset, sector_start;
  uint32_t end;
  struct file_header hdr;
  static int16_t skip_pages;
  static int last_pages_are_active;
  int i;
  
  *active = *free = *obsolete = 0;
  if(sector == 0) {
    skip_pages = 0;
    last_pages_are_active = 0;
  } else if(skip_pages > COFFEE_PAGES_PER_SECTOR) {
    skip_pages -= COFFEE_PAGES_PER_SECTOR;
    if(last_pages_are_active) {
      *active = COFFEE_PAGES_PER_SECTOR;
    } else {
      *obsolete = COFFEE_PAGES_PER_SECTOR;
    }
    return;
  }

  sector_start = sector * COFFEE_SECTOR_SIZE;

  if(last_pages_are_active) {
    *active = skip_pages;
  } else {
    *obsolete = skip_pages;

    /* Split an obsolete file starting in the previous sector and mark 
       the following pages as isolated. */
    offset = sector_start;
    for(i = 0; i < skip_pages; i++) {
      COFFEE_READ(&hdr, sizeof(hdr), offset);
      hdr.flags |= COFFEE_FLAG_ISOLATED;
      COFFEE_WRITE(&hdr, sizeof(hdr), offset);
      offset += COFFEE_PAGE_SIZE;
    }
    PRINTF("Coffee: Isolated %u pages starting in sector %d\n",
	(unsigned)skip_pages, (int)sector);
  }

  offset = sector_start + skip_pages * COFFEE_PAGE_SIZE;
  end = (sector + 1) * COFFEE_SECTOR_SIZE;
 
  while(offset < end) {
    COFFEE_READ(&hdr, sizeof(hdr), offset);
    if(COFFEE_PAGE_ACTIVE(hdr)) {
      last_pages_are_active = 1;
      offset += hdr.max_pages * COFFEE_PAGE_SIZE;
      *active += hdr.max_pages;
    } else if(COFFEE_PAGE_ISOLATED(hdr)) {
      last_pages_are_active = 0;
      offset += COFFEE_PAGE_SIZE;
      *obsolete++;
    } else if(COFFEE_PAGE_OBSOLETE(hdr)) {
      last_pages_are_active = 0;
      offset += hdr.max_pages * COFFEE_PAGE_SIZE;
      *obsolete += hdr.max_pages;
    } else if(COFFEE_PAGE_FREE(hdr)) {
      *free = (end - offset) / COFFEE_PAGE_SIZE;
      break;
    }
  }
  
  skip_pages = *active + *obsolete - COFFEE_PAGES_PER_SECTOR;
  if(skip_pages > 0) {
    if(last_pages_are_active) {
      *active = COFFEE_PAGES_PER_SECTOR - *obsolete;
    } else {
      *obsolete = COFFEE_PAGES_PER_SECTOR - *active;
    }
  }
}