Beispiel #1
0
/*---------------------------------------------------------------------------*/
cfs_offset_t
cfs_seek(int fd, cfs_offset_t offset, int whence)
{
  struct file_desc *fdp;
  cfs_offset_t new_offset;

  if(!FD_VALID(fd)) {
    return -1;
  }
  fdp = &coffee_fd_set[fd];

  if(whence == CFS_SEEK_SET) {
    new_offset = offset;
  } else if(whence == CFS_SEEK_END) {
    new_offset = fdp->file->end + offset;
  } else if(whence == CFS_SEEK_CUR) {
    new_offset = fdp->offset + offset;
  } else {
    return (cfs_offset_t)-1;
  }

  if(new_offset < 0 || new_offset > fdp->file->max_pages * COFFEE_PAGE_SIZE) {
    return -1;
  }

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

  return fdp->offset = new_offset;
}
Beispiel #2
0
/*---------------------------------------------------------------------------*/
void
cfs_close(int fd)
{
  if(FD_VALID(fd)) {
    coffee_fd_set[fd].flags = COFFEE_FD_FREE;
    coffee_fd_set[fd].file->references--;
    coffee_fd_set[fd].file = NULL;
  }
}
Beispiel #3
0
void *get_data_by_fd(int fd, int dir)
{
	if ( !FD_VALID(fd) ) {
		log_message(LOG_INFO, "get_data_by_fd: fd %d out of range.", fd);
		return NULL;
	}

	return epfd_set[fd].data[dir];
}
Beispiel #4
0
/*---------------------------------------------------------------------------*/
int
cfs_read(int fd, void *buf, unsigned size)
{
  struct file_desc *fdp;
  struct file *file;
#if COFFEE_MICRO_LOGS
  struct file_header hdr;
  struct log_param lp;
  unsigned bytes_left;
  int r;
#endif

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

  fdp = &coffee_fd_set[fd];
  file = fdp->file;
  if(fdp->offset + size > file->end) {
    size = file->end - fdp->offset;
  }

  /* If the file is allocated, read directly in the file. */
  if(!FILE_MODIFIED(file)) {
    COFFEE_READ(buf, size, absolute_offset(file->page, fdp->offset));
    fdp->offset += size;
    return size;
  }

#if COFFEE_MICRO_LOGS
  read_header(&hdr, file->page);

  /*
   * Fill the buffer by copying from the log in first hand, or the
   * ordinary file if the page has no log record.
   */
  for(bytes_left = size; bytes_left > 0; bytes_left -= r) {
    r = -1;

    lp.offset = fdp->offset;
    lp.buf = buf;
    lp.size = bytes_left;
    r = read_log_page(&hdr, file->record_count, &lp);

    /* Read from the original file if we cannot find the data in the log. */
    if(r < 0) {
      COFFEE_READ(buf, lp.size, absolute_offset(file->page, fdp->offset));
      r = lp.size;
    }
    fdp->offset += r;
    buf = (char *)buf + r;
  }
#endif /* COFFEE_MICRO_LOGS */

  return size;
}
Beispiel #5
0
/*---------------------------------------------------------------------------*/
int
cfs_read(int fd, void *buf, unsigned size)
{
  struct file_desc *fdp;
  struct file *file;
#if COFFEE_MICRO_LOGS
  struct file_header hdr;
  struct log_param lp;
  unsigned bytes_left;
  int r;
#endif

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

  fdp = &coffee_fd_set[fd];
  file = fdp->file;
  if(fdp->offset + size > file->end) {
    size = file->end - fdp->offset;
  }

  /* If the file is not modified, read directly from the file extent. */
  if(!FILE_MODIFIED(file)) {
    COFFEE_READ(buf, size, absolute_offset(file->page, fdp->offset));
    fdp->offset += size;
    return size;
  }

#if COFFEE_MICRO_LOGS
  read_header(&hdr, file->page);

  /*
   * Copy the contents of the most recent log record. If there is
   * no log record for the file area to read from, we simply read
   * from the original file extent.
   */
  for(bytes_left = size; bytes_left > 0; bytes_left -= r) {
    lp.offset = fdp->offset;
    lp.buf = buf;
    lp.size = bytes_left;
    r = read_log_page(&hdr, file->record_count, &lp);

    /* Read from the original file if we cannot find the data in the log. */
    if(r < 0) {
      COFFEE_READ(buf, lp.size, absolute_offset(file->page, fdp->offset));
      r = lp.size;
    }
    fdp->offset += r;
    buf = (char *)buf + r;
  }
#endif /* COFFEE_MICRO_LOGS */

  return size;
}
Beispiel #6
0
int
cfs_coffee_set_io_semantics(int fd, unsigned flags)
{
  if(!FD_VALID(fd)) {
    return -1;
  }

  coffee_fd_set[fd].io_flags |= flags;

  return 0;
}
/*---------------------------------------------------------------------------*/
int
cfs_read(int fd, void *buf, unsigned size)
{
    struct file_header hdr;
    struct file_desc *fdp;
    struct file *file;
    unsigned bytes_left;
    int r;
#if COFFEE_MICRO_LOGS
    struct log_param lp;
#endif

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

    fdp = &coffee_fd_set[fd];
    file = fdp->file;
    if(fdp->offset + size > file->end) {
        size = file->end - fdp->offset;
    }

    bytes_left = size;
    if(FILE_MODIFIED(file)) {
        read_header(&hdr, file->page);
    }

    /*
     * Fill the buffer by copying from the log in first hand, or the
     * ordinary file if the page has no log record.
     */
    while(bytes_left) {
        watchdog_periodic();
        r = -1;
#if COFFEE_MICRO_LOGS
        if(FILE_MODIFIED(file)) {
            lp.offset = fdp->offset;
            lp.buf = buf;
            lp.size = bytes_left;
            r = read_log_page(&hdr, file->record_count, &lp);
        }
#endif /* COFFEE_MICRO_LOGS */
        /* Read from the original file if we cannot find the data in the log. */
        if(r < 0) {
            r = bytes_left;
            COFFEE_READ(buf, r, absolute_offset(file->page, fdp->offset));
        }
        bytes_left -= r;
        fdp->offset += r;
        buf += r;
    }
    return size;
}
Beispiel #8
0
/* if fd is in epoll fdset, return 1, else return 0 */
int epoll_fdisset(int fd, int dir)
{
	if ( !FD_VALID(fd) ) {
		log_message(LOG_INFO, "epoll_fdisset: fd %d out of range.", fd);
		return 0;
	}

	if (((dir == DIR_RD) && ((epfd_set[fd].events & EPOLLIN) == EPOLLIN)) ||
			((dir == DIR_WR) && ((epfd_set[fd].events & EPOLLOUT) == EPOLLOUT)))
		return 1;

	return 0;
}
Beispiel #9
0
/**
 * Doesn't support timeout other than 0 or infinite (negative) timeout
 */
int
rte_netmap_poll(struct pollfd *fds, nfds_t nfds, int timeout)
{
    int32_t count_it, ret;
    uint32_t i, idx, port;
    uint32_t want_rx, want_tx;

    if (timeout > 0)
        return -1;

    ret = 0;
    do {
        for (i = 0; i < nfds; i++) {

            count_it = 0;

            if (!FD_VALID(fds[i].fd) || fds[i].events == 0) {
                fds[i].revents = 0;
                continue;
            }

            idx = FD_TO_IDX(fds[i].fd);
            if ((port = fd_port[idx].port) >= RTE_DIM(ports) ||
                    ports[port].fd != idx) {

                fds[i].revents |= POLLERR;
                ret++;
                continue;
            }

            want_rx = fds[i].events & (POLLIN  | POLLRDNORM);
            want_tx = fds[i].events & (POLLOUT | POLLWRNORM);

            if (want_rx && rx_sync_if(port) > 0) {
                fds[i].revents = (uint16_t)
                                 (fds[i].revents | want_rx);
                count_it = 1;
            }
            if (want_tx && tx_sync_if(port) > 0) {
                fds[i].revents = (uint16_t)
                                 (fds[i].revents | want_tx);
                count_it = 1;
            }

            ret += count_it;
        }
    }
    while ((ret == 0 && timeout < 0) || timeout);

    return ret;
}
Beispiel #10
0
void *
rte_netmap_mmap(void *addr, size_t length,
	int prot, int flags, int fd, off_t offset)
{
	static const int cprot = PROT_WRITE | PROT_READ;

	if (!FD_VALID(fd) || length + offset > netmap.mem_sz ||
			(prot & cprot) != cprot ||
			((flags & MAP_FIXED) != 0 && addr != NULL)) {

		errno = EINVAL;
		return (MAP_FAILED);
	}

	return ((void *)((uintptr_t)netmap.mem + offset));
}
Beispiel #11
0
static int32_t
fd_release(int32_t fd)
{
	uint32_t idx, port;

	idx = FD_TO_IDX(fd);

	if (!FD_VALID(fd) || (port = fd_port[idx].port) == FD_PORT_FREE)
		return (-EINVAL);

	/* if we still have a valid port attached, release the port */
	if (port < RTE_DIM(ports) && ports[port].fd == idx) {
		netmap_unregif(idx, port);
	}

	fd_port[idx].port = FD_PORT_FREE;
	return (0);
}
Beispiel #12
0
int rte_netmap_ioctl(int fd, int op, void *param)
{
	int ret;

	if (!FD_VALID(fd)) {
	    errno = EBADF;
	    return (-1);
	}

	switch (op) {

	    case NIOCGINFO:
	        ret = ioctl_niocginfo(fd, param);
	        break;

	    case NIOCREGIF:
	        ret = ioctl_niocregif(fd, param);
	        break;

	    case NIOCUNREGIF:
	        ret = ioctl_niocunregif(fd);
	        break;

	    case NIOCRXSYNC:
	        ret = ioctl_niocrxsync(fd);
	        break;

	    case NIOCTXSYNC:
	        ret = ioctl_nioctxsync(fd);
	        break;

	    default:
	        ret = -ENOTTY;
	}

	if (ret < 0) {
		errno = -ret;
		ret = -1;
	} else {
		ret = 0;
	}

	return (ret);
}
Beispiel #13
0
/* epoll clear fd */
int epoll_clear_fd(int epfd, int dir, int fd)
{
	int opcode;
	struct epoll_event ev;

	if ( !FD_VALID(fd) ) {
		log_message(LOG_INFO, "epoll_clear_fd: fd %d out of range.", fd);
		return -1;
	}

	if (epfd_set[fd].events == 0) {
		log_message(LOG_INFO, "epoll_clear_fd: fd %d is not in fdset.", fd);
		return -1;
	}

	if (dir == DIR_RD)
		epfd_set[fd].events &= ~EPOLLIN;
	else if (dir == DIR_WR)
		epfd_set[fd].events &= ~EPOLLOUT;

	/* clear default ERR/HUP events */
//	epfd_set[fd].events &= ~(EPOLLERR | EPOLLHUP);

	if (epfd_set[fd].events == 0) {
		opcode = EPOLL_CTL_DEL;
		epfd_set[fd].data[dir] = NULL;
	} else {
		opcode = EPOLL_CTL_MOD;
	}

	ev.events = epfd_set[fd].events;
	ev.data.fd = fd;

	if (epoll_ctl(epfd, opcode, fd, &ev) != 0) {
		log_message(LOG_INFO, "epoll_clear_fd: %s fd %d failure.",
					(opcode == EPOLL_CTL_DEL) ? "DEL":"MOD", fd);
		return -1;
	}

	return 0;
}
Beispiel #14
0
/* epoll set fd */
int epoll_set_fd(int epfd, int dir, int fd, void *data)
{
	int opcode;
	struct epoll_event ev;

	if ( !FD_VALID(fd) ) {
		log_message(LOG_INFO, "epoll_set_fd: fd %d out of range.", fd);
		return -1;
	}

	memset(&ev, 0, sizeof(struct epoll_event));
	ev.data.fd = fd;
	if (dir == DIR_RD)
		ev.events |= EPOLLIN;
	else if (dir == DIR_WR)
		ev.events |= EPOLLOUT;

	if (epfd_set[fd].events == 0) {
		opcode = EPOLL_CTL_ADD;
	} else if( epfd_set[fd].events != ev.events) {
		opcode = EPOLL_CTL_MOD;
	} else {
		/* already exists */
		epfd_set[fd].data[dir] = data;
		return 0;
	}

	if (epoll_ctl(epfd, opcode, fd, &ev) != 0) {
		log_message(LOG_INFO, "epoll_set_fd: %s fd %d failure.",
					(opcode == EPOLL_CTL_ADD) ? "ADD":"MOD", fd);
		return -1;
	}

	epfd_set[fd].events = ev.events;
	epfd_set[fd].data[dir] = data;

	return 0;
}
Beispiel #15
0
/*---------------------------------------------------------------------------*/
cfs_offset_t
cfs_seek(int fd, cfs_offset_t offset, int whence)
{
  struct file_desc *fdp;
  cfs_offset_t new_offset;

  if(!FD_VALID(fd)) {
    return -1;
  }
  fdp = &coffee_fd_set[fd];

  if(whence == CFS_SEEK_SET) {
    new_offset = offset;
  } else if(whence == CFS_SEEK_END) {
    new_offset = fdp->file->end + offset;
  } else if(whence == CFS_SEEK_CUR) {
    new_offset = fdp->offset + offset;
  } else {
    return (cfs_offset_t)-1;
  }

  if(new_offset < 0 || new_offset > fdp->file->max_pages * COFFEE_PAGE_SIZE) {
    return -1;
  }

  if(fdp->file->end < new_offset) {
    if(FD_WRITABLE(fd)) {
      fdp->file->end = new_offset;
    } else {
      /* Disallow seeking past the end of the file for read only FDs */
      return (cfs_offset_t)-1;
    }
  }

  return fdp->offset = new_offset;
}
Beispiel #16
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. */
#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;
}
/*---------------------------------------------------------------------------*/
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;
}