Пример #1
0
/*===========================================================================*
 *				fs_breadwrite				     *
 *===========================================================================*/
PUBLIC int fs_breadwrite(void)
{
  int r, rw_flag, completed;
  cp_grant_id_t gid;
  u64_t position;
  unsigned int off, cum_io, chunk, block_size;
  size_t nrbytes;

  /* Pseudo inode for rw_chunk */
  struct inode rip;
  
  r = OK;
  
  /* Get the values from the request message */ 
  rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
  gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
  position = make64((unsigned long) fs_m_in.REQ_SEEK_POS_LO,
  		    (unsigned long) fs_m_in.REQ_SEEK_POS_HI);
  nrbytes = (size_t) fs_m_in.REQ_NBYTES;
  
  block_size = get_block_size( (dev_t) fs_m_in.REQ_DEV2);

  rip.i_zone[0] = (zone_t) fs_m_in.REQ_DEV2;
  rip.i_mode = I_BLOCK_SPECIAL;
  rip.i_size = 0;

  rdwt_err = OK;		/* set to EIO if disk error occurs */
  
  cum_io = 0;
  /* Split the transfer into chunks that don't span two blocks. */
  while (nrbytes > 0) {
	  off = rem64u(position, block_size);	/* offset in blk*/
	  chunk = min(nrbytes, block_size - off);

	  /* Read or write 'chunk' bytes. */
	  r = rw_chunk(&rip, position, off, chunk, nrbytes, rw_flag, gid,
	  	       cum_io, block_size, &completed);

	  if (r != OK) break;	/* EOF reached */
	  if (rdwt_err < 0) break;

	  /* Update counters and pointers. */
	  nrbytes -= chunk;	        /* bytes yet to be read */
	  cum_io += chunk;	        /* bytes read so far */
	  position = add64ul(position, chunk);	/* position within the file */
  }
  
  fs_m_out.RES_SEEK_POS_LO = ex64lo(position); 
  fs_m_out.RES_SEEK_POS_HI = ex64hi(position); 
  
  if (rdwt_err != OK) r = rdwt_err;	/* check for disk error */
  if (rdwt_err == END_OF_FILE) r = OK;

  fs_m_out.RES_NBYTES = cum_io;
  
  return(r);
}
Пример #2
0
static __inline u32_t makehash(u32_t p1, u64_t p2)
{
	u32_t offlo = ex64lo(p2), offhi = ex64hi(p2),
		v = 0x12345678;
	hash_mix(p1, offlo, offhi);
	hash_final(offlo, offhi, v);

	return v % HASHSIZE;
}
Пример #3
0
/*===========================================================================*
 *				do_read					     *
 *===========================================================================*/
int do_read()
{
/* Read data from a file.
 */
  struct inode *ino;
  u64_t pos;
  size_t count, size;
  vir_bytes off;
  char *ptr;
  int r, chunk;

  if ((ino = find_inode(m_in.REQ_INODE_NR)) == NULL)
	return EINVAL;

  if (IS_DIR(ino)) return EISDIR;

  if ((r = get_handle(ino)) != OK)
	return r;

  pos = make64(m_in.REQ_SEEK_POS_LO, m_in.REQ_SEEK_POS_HI);
  count = m_in.REQ_NBYTES;

  assert(count > 0);

  /* Use the buffer from below to eliminate extra copying. */
  size = sffs_table->t_readbuf(&ptr);
  off = 0;

  while (count > 0) {
	chunk = MIN(count, size);

	if ((r = sffs_table->t_read(ino->i_file, ptr, chunk, pos)) <= 0)
		break;

	chunk = r;

	r = sys_safecopyto(m_in.m_source, m_in.REQ_GRANT, off,
		(vir_bytes) ptr, chunk, D);

	if (r != OK)
		break;

	count -= chunk;
	off += chunk;
	pos = add64u(pos, chunk);
  }

  if (r < 0)
	return r;

  m_out.RES_SEEK_POS_HI = ex64hi(pos);
  m_out.RES_SEEK_POS_LO = ex64lo(pos);
  m_out.RES_NBYTES = off;

  return OK;
}
Пример #4
0
static void testdiv(void)
{
	u64_t q, r;
#if TIMED
	struct timeval tvstart, tvend;

	printf("i=0x%.8x%.8x; j=0x%.8x%.8x\n", 
		ex64hi(i), ex64lo(i), 
		ex64hi(j), ex64lo(j));
	fflush(stdout);
	if (gettimeofday(&tvstart, NULL) < 0) ERR;
#endif

	/* division by zero has a separate test */
	if (cmp64u(j, 0) == 0) {
		testdiv0();
		return;
	}

	/* perform division, store q in k to make ERR more informative */
	q = div64(i, j);
	r = rem64(i, j);
	k = q;

#if TIMED
	if (gettimeofday(&tvend, NULL) < 0) ERR;
	tvend.tv_sec -= tvstart.tv_sec;
	tvend.tv_usec -= tvstart.tv_usec;
	if (tvend.tv_usec < 0) {
		tvend.tv_sec -= 1;
		tvend.tv_usec += 1000000;
	}
	printf("q=0x%.8x%.8x; r=0x%.8x%.8x; time=%d.%.6d\n", 
		ex64hi(q), ex64lo(q), 
		ex64hi(r), ex64lo(r), 
		tvend.tv_sec, tvend.tv_usec);
	fflush(stdout);
#endif

	/* compare to 64/32-bit division if possible */
	if (!ex64hi(j)) {
		if (cmp64(q, div64u64(i, ex64lo(j))) != 0) ERR;
		if (!ex64hi(q)) {
			if (cmp64u(q, div64u(i, ex64lo(j))) != 0) ERR;
		}
		if (cmp64u(r, rem64u(i, ex64lo(j))) != 0) ERR;

		/* compare to 32-bit division if possible */
		if (!ex64hi(i)) {
			if (cmp64u(q, ex64lo(i) / ex64lo(j)) != 0) ERR;
			if (cmp64u(r, ex64lo(i) % ex64lo(j)) != 0) ERR;
		}
	}

	/* check results using i = q j + r and r < j */
	if (cmp64(i, add64(mul64(q, j), r)) != 0) ERR;
	if (cmp64(r, j) >= 0) ERR;
}
Пример #5
0
/*===========================================================================*
 *				do_lseek				     *
 *===========================================================================*/
int do_lseek()
{
/* Perform the lseek(ls_fd, offset, whence) system call. */
  register struct filp *rfilp;
  int r = OK, seekfd, seekwhence;
  off_t offset;
  u64_t pos, newpos;

  seekfd = job_m_in.ls_fd;
  seekwhence = job_m_in.whence;
  offset = (off_t) job_m_in.offset_lo;

  /* Check to see if the file descriptor is valid. */
  if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code);

  /* No lseek on pipes. */
  if (S_ISFIFO(rfilp->filp_vno->v_mode)) {
	unlock_filp(rfilp);
	return(ESPIPE);
  }

  /* The value of 'whence' determines the start position to use. */
  switch(seekwhence) {
    case SEEK_SET: pos = cvu64(0);	break;
    case SEEK_CUR: pos = rfilp->filp_pos;	break;
    case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size);	break;
    default: unlock_filp(rfilp); return(EINVAL);
  }

  if (offset >= 0)
	newpos = add64ul(pos, offset);
  else
	newpos = sub64ul(pos, -offset);

  /* Check for overflow. */
  if (ex64hi(newpos) != 0) {
	r = EOVERFLOW;
  } else if ((off_t) ex64lo(newpos) < 0) { /* no negative file size */
	r = EOVERFLOW;
  } else {
	/* insert the new position into the output message */
	m_out.reply_l1 = ex64lo(newpos);

	if (cmp64(newpos, rfilp->filp_pos) != 0) {
		rfilp->filp_pos = newpos;

		/* Inhibit read ahead request */
		r = req_inhibread(rfilp->filp_vno->v_fs_e,
				  rfilp->filp_vno->v_inode_nr);
	}
  }

  unlock_filp(rfilp);
  return(r);
}
Пример #6
0
/*===========================================================================*
 *				do_readsuper				     *
 *===========================================================================*/
PUBLIC int do_readsuper()
{
/* Mount the file system.
 */
  char path[PATH_MAX];
  struct inode *ino;
  struct hgfs_attr attr;
  int r;

  dprintf(("HGFS: readsuper (dev %x, flags %x)\n",
	(dev_t) m_in.REQ_DEV, m_in.REQ_FLAGS));

  if (m_in.REQ_FLAGS & REQ_ISROOT) {
	printf("HGFS: attempt to mount as root device\n");

	return EINVAL;
  }

  state.read_only = !!(m_in.REQ_FLAGS & REQ_RDONLY);
  state.dev = m_in.REQ_DEV;

  init_dentry();
  ino = init_inode();

  attr.a_mask = HGFS_ATTR_MODE | HGFS_ATTR_SIZE;

  /* We cannot continue if we fail to get the properties of the root inode at
   * all, because we cannot guess the details of the root node to return to
   * VFS. Print a (hopefully) helpful error message, and abort the mount.
   */
  if ((r = verify_inode(ino, path, &attr)) != OK) {
	if (r == EAGAIN)
		printf("HGFS: shared folders disabled\n");
	else if (opt.prefix[0] && (r == ENOENT || r == EACCES))
		printf("HGFS: unable to access the given prefix directory\n");
	else
		printf("HGFS: unable to access shared folders\n");

	return r;
  }

  m_out.RES_INODE_NR = INODE_NR(ino);
  m_out.RES_MODE = get_mode(ino, attr.a_mode);
  m_out.RES_FILE_SIZE_HI = ex64hi(attr.a_size);
  m_out.RES_FILE_SIZE_LO = ex64lo(attr.a_size);
  m_out.RES_UID = opt.uid;
  m_out.RES_GID = opt.gid;
  m_out.RES_DEV = NO_DEV;

  m_out.RES_CONREQS = 1;	/* We can handle only 1 request at a time */

  state.mounted = TRUE;

  return OK;
}
Пример #7
0
/*===========================================================================*
 *				scall_lseek				     *
 *===========================================================================*/
int scall_lseek()
{
	/* Perform the lseek(ls_fd, offset, whence) system call. */
	register struct filp *rfilp;
	int r;
	long offset;
	u64_t pos, newpos;

	/* Check to see if the file descriptor is valid. */
	if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP)
		return(err_code);

	/* No lseek on pipes. */
	if (rfilp->filp_vno->v_pipe == I_PIPE)
		return -ESPIPE;

	/* The value of 'whence' determines the start position to use. */
	switch(m_in.whence) {
	case SEEK_SET:
		pos = cvu64(0);
		break;

	case SEEK_CUR:
		pos = rfilp->filp_pos;
		break;

	case SEEK_END:
		pos = cvul64(rfilp->filp_vno->v_size);
		break;

	default:
		return(-EINVAL);
	}

	offset= m_in.offset_lo;
	if (offset >= 0)
		newpos= add64ul(pos, offset);
	else
		newpos= sub64ul(pos, -offset);

	/* Check for overflow. */
	if (ex64hi(newpos) != 0)
		return -EINVAL;

	if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
		r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr);

		if (r != 0)
			return r;
	}

	rfilp->filp_pos = newpos;

	return ex64lo(newpos);
}
Пример #8
0
static void testmul(void)
{
	int kdone, kidx;
	u32_t ilo = ex64lo(i), jlo = ex64lo(j);
	u64_t prod = mul64(i, j);
	int prodbits;
		
	/* compute maximum index of highest-order bit */
	prodbits = bsr64(i) + bsr64(j) + 1;
	if (cmp64u(i, 0) == 0 || cmp64u(j, 0) == 0) prodbits = -1;
	if (bsr64(prod) > prodbits) ERR;

	/* compare to 32-bit multiplication if possible */	
	if (ex64hi(i) == 0 && ex64hi(j) == 0) {
		if (cmp64(prod, mul64u(ilo, jlo)) != 0) ERR;
		
		/* if there is no overflow we can check against pure 32-bit */
		if (prodbits < 32 && cmp64u(prod, ilo * jlo) != 0) ERR;
	}

	/* in 32-bit arith low-order DWORD matches regardless of overflow */
	if (ex64lo(prod) != ilo * jlo) ERR;

	/* multiplication by zero yields zero */
	if (prodbits < 0 && cmp64u(prod, 0) != 0) ERR;

	/* if there is no overflow, check absence of zero divisors */
	if (prodbits >= 0 && prodbits < 64 && cmp64u(prod, 0) == 0) ERR;

	/* commutativity */
	if (cmp64(prod, mul64(j, i)) != 0) ERR;

	/* loop though all argument value combinations for third argument */
	for (kdone = 0, kidx = 0; k = getargval(kidx, &kdone), !kdone; kidx++) {
		/* associativity */
		if (cmp64(mul64(mul64(i, j), k), mul64(i, mul64(j, k))) != 0) ERR;

		/* left and right distributivity */
		if (cmp64(mul64(add64(i, j), k), add64(mul64(i, k), mul64(j, k))) != 0) ERR;
		if (cmp64(mul64(i, add64(j, k)), add64(mul64(i, j), mul64(i, k))) != 0) ERR;
	}
}
Пример #9
0
/*===========================================================================*
 *				print64					     *
 *===========================================================================*/
char *print64(u64_t p)
{
#define NB 10
	static int n = 0;
	static char buf[NB][100];
	u32_t lo = ex64lo(p), hi = ex64hi(p);
	n = (n+1) % NB;
	if(!hi) sprintf(buf[n], "%lx", lo);
	else sprintf(buf[n], "%lx%08lx", hi, lo);
	return buf[n];
}
Пример #10
0
/*===========================================================================*
 *				fs_bread				     *
 *===========================================================================*/
int fs_bread(void)
{
    int r, rw_flag, chunk, block_size;
    cp_grant_id_t gid;
    int nrbytes;
    u64_t position;
    unsigned int off, cum_io;
    int completed;
    struct dir_record *dir;

    r = OK;

    rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
    gid = fs_m_in.REQ_GRANT;
    position = make64(fs_m_in.REQ_SEEK_POS_LO, fs_m_in.REQ_SEEK_POS_HI);
    nrbytes = (unsigned) fs_m_in.REQ_NBYTES;
    block_size = v_pri.logical_block_size_l;
    dir = v_pri.dir_rec_root;

    if(rw_flag == WRITING) return (EIO);	/* Not supported */
    rdwt_err = OK;		/* set to EIO if disk error occurs */

    cum_io = 0;
    /* Split the transfer into chunks that don't span two blocks. */
    while (nrbytes != 0) {
        off = rem64u(position, block_size);	/* offset in blk*/

        chunk = MIN(nrbytes, block_size - off);
        if (chunk < 0) chunk = block_size - off;

        /* Read 'chunk' bytes. */
        r = read_chunk(dir, position, off, chunk, (unsigned) nrbytes,
                       gid, cum_io, block_size, &completed);

        if (r != OK) break;	/* EOF reached */
        if (rdwt_err < 0) break;

        /* Update counters and pointers. */
        nrbytes -= chunk;	        /* bytes yet to be read */
        cum_io += chunk;	        /* bytes read so far */
        position= add64ul(position, chunk);	/* position within the file */
    }

    fs_m_out.RES_SEEK_POS_LO = ex64lo(position);
    fs_m_out.RES_SEEK_POS_HI = ex64hi(position);

    if (rdwt_err != OK) r = rdwt_err;	/* check for disk error */
    if (rdwt_err == END_OF_FILE) r = OK;

    fs_m_out.RES_NBYTES = cum_io;

    return(r);
}
Пример #11
0
/*===========================================================================*
 *				do_llseek				     *
 *===========================================================================*/
PUBLIC int do_llseek()
{
/* Perform the llseek(ls_fd, offset, whence) system call. */
  register struct filp *rfilp;
  u64_t pos, newpos;
  int r = OK;

  /* Check to see if the file descriptor is valid. */
  if ( (rfilp = get_filp(m_in.ls_fd, VNODE_READ)) == NULL) return(err_code);

  /* No lseek on pipes. */
  if (rfilp->filp_vno->v_pipe == I_PIPE) {
	unlock_filp(rfilp);
	return(ESPIPE);
  }

  /* The value of 'whence' determines the start position to use. */
  switch(m_in.whence) {
    case SEEK_SET: pos = cvu64(0);	break;
    case SEEK_CUR: pos = rfilp->filp_pos;	break;
    case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size);	break;
    default: unlock_filp(rfilp); return(EINVAL);
  }

  newpos = add64(pos, make64(m_in.offset_lo, m_in.offset_high));

  /* Check for overflow. */
  if (( (long) m_in.offset_high > 0) && cmp64(newpos, pos) < 0)
      r = EINVAL;
  else if (( (long) m_in.offset_high < 0) && cmp64(newpos, pos) > 0)
      r = EINVAL;
  else {
	rfilp->filp_pos = newpos;

	/* insert the new position into the output message */
	m_out.reply_l1 = ex64lo(newpos);
	m_out.reply_l2 = ex64hi(newpos);

	if (cmp64(newpos, rfilp->filp_pos) != 0) {
		/* Inhibit read ahead request */
		r = req_inhibread(rfilp->filp_vno->v_fs_e,
				  rfilp->filp_vno->v_inode_nr);
	}
  }

  unlock_filp(rfilp);
  return(r);
}
Пример #12
0
Файл: fbd.c Проект: tworaz/minix
/*===========================================================================*
 *				fbd_transfer				     *
 *===========================================================================*/
static int fbd_transfer(dev_t UNUSED(minor), int do_write, u64_t position,
                        endpoint_t endpt, iovec_t *iov, unsigned int nr_req, int flags)
{
    /* Transfer data from or to the device. */
    unsigned count;
    size_t size, osize;
    int i, hooks;
    ssize_t r;

    /* Compute the total size of the request. */
    for (size = i = 0; i < nr_req; i++)
        size += iov[i].iov_size;

    osize = size;
    count = nr_req;

    hooks = rule_find(position, size,
                      do_write ? FBD_FLAG_WRITE : FBD_FLAG_READ);

#if DEBUG
    printf("FBD: %s operation for pos %lx:%08lx size %u -> hooks %x\n",
           do_write ? "write" : "read", ex64hi(position),
           ex64lo(position), size, hooks);
#endif

    if (hooks & PRE_HOOK)
        rule_pre_hook(iov, &count, &size, &position);

    if (count > 0) {
        if (hooks & IO_HOOK) {
            r = fbd_transfer_copy(do_write, position, endpt, iov,
                                  count, size, flags);
        } else {
            r = fbd_transfer_direct(do_write, position, endpt, iov,
                                    count, flags);
        }
    }
    else r = 0;

    if (hooks & POST_HOOK)
        rule_post_hook(osize, &r);

#if DEBUG
    printf("FBD: returning %d\n", r);
#endif

    return r;
}
Пример #13
0
static double make_double(u64_t d)
{
/* Convert a 64-bit fixed point value into a double.
 * This whole thing should be replaced by something better eventually.
 */
  double value;
  size_t i;

  value = (double) ex64hi(d);
  for (i = 0; i < sizeof(unsigned long); i += 2)
	value *= 65536.0;

  value += (double) ex64lo(d);

  return value;
}
Пример #14
0
/*===========================================================================*
 *                              vfs_request                                 *
 *===========================================================================*/
int vfs_request(int reqno, int fd, struct vmproc *vmp, u64_t offset, u32_t len,
	vfs_callback_t reply_callback, void *cbarg, void *state, int statelen)
{
/* Perform an asynchronous request to VFS.
 * We send a message of type VFS_VMCALL to VFS. VFS will respond
 * with message type VM_VFS_REPLY. We send the request asynchronously
 * and then handle the reply as it if were a VM_VFS_REPLY request.
 */
 	message *m;
	static int reqid = 0;
	struct vfs_request_node *reqnode;

	reqid++;

	assert(statelen <= STATELEN);

	if(!SLABALLOC(reqnode)) {
		printf("vfs_request: no memory for request node\n");
		return ENOMEM;
	}

	m = &reqnode->reqmsg;
	m->m_type = VFS_VMCALL;
	m->VFS_VMCALL_REQ = reqno;
	m->VFS_VMCALL_FD = fd;
	m->VFS_VMCALL_REQID = reqid;
	m->VFS_VMCALL_ENDPOINT = vmp->vm_endpoint;
	m->VFS_VMCALL_OFFSET_LO = ex64lo(offset);
	m->VFS_VMCALL_OFFSET_HI = ex64hi(offset);
	m->VFS_VMCALL_LENGTH = len;

	reqnode->who = vmp->vm_endpoint;
	reqnode->req_id = reqid;
	reqnode->next = first_queued;
	reqnode->callback = reply_callback;
	reqnode->opaque = cbarg;
	if(state) memcpy(reqnode->reqstate, state, statelen);
	first_queued = reqnode;

	/* Send the request message if none pending. */
	if(!active)
		activate();

	return OK;
}
Пример #15
0
/*===========================================================================*
 *			req_bpeek					     *
 *===========================================================================*/
int req_bpeek(endpoint_t fs_e, dev_t dev, u64_t pos, unsigned int num_of_bytes)
{
  message m;

  memset(&m, 0, sizeof(m));

  /* Fill in request message */
  m.m_type = REQ_BPEEK;
  m.REQ_DEV2 = dev;
  m.REQ_SEEK_POS_LO = ex64lo(pos);
  m.REQ_SEEK_POS_HI = ex64hi(pos);
  m.REQ_NBYTES = num_of_bytes;

  /* Send/rec request */
  return fs_sendrec(fs_e, &m);

  return(OK);
}
Пример #16
0
/*===========================================================================*
 *				get_range				     *
 *===========================================================================*/
static size_t get_range(struct fbd_rule *rule, u64_t pos, size_t *size,
	u64_t *skip)
{
	/* Compute the range within the given request range that is affected
	 * by the given rule, and optionally the number of bytes preceding
	 * the range that are also affected by the rule.
	 */
	u64_t delta;
	size_t off;
	int to_eof;

	to_eof = cmp64(rule->start, rule->end) >= 0;

	if (cmp64(pos, rule->start) > 0) {
		if (skip != NULL) *skip = sub64(pos, rule->start);

		off = 0;
	}
	else {
		if (skip != NULL) *skip = cvu64(0);

		delta = sub64(rule->start, pos);

		assert(ex64hi(delta) == 0);

		off = ex64lo(delta);
	}

	if (!to_eof) {
		assert(cmp64(pos, rule->end) < 0);

		delta = sub64(rule->end, pos);

		if (cmp64u(delta, *size) < 0)
			*size = ex64lo(delta);
	}

	assert(*size > off);

	*size -= off;

	return off;
}
Пример #17
0
Файл: fbd.c Проект: tworaz/minix
/*===========================================================================*
 *				fbd_transfer_direct			     *
 *===========================================================================*/
static ssize_t fbd_transfer_direct(int do_write, u64_t position,
                                   endpoint_t endpt, iovec_t *iov, unsigned int count, int flags)
{
    /* Forward the entire transfer request, without any intervention. */
    iovec_s_t iovec[NR_IOREQS];
    cp_grant_id_t grant;
    message m;
    int i, r;

    for (i = 0; i < count; i++) {
        iovec[i].iov_size = iov[i].iov_size;
        iovec[i].iov_grant = cpf_grant_indirect(driver_endpt, endpt,
                                                iov[i].iov_addr);
        assert(iovec[i].iov_grant != GRANT_INVALID);
    }

    grant = cpf_grant_direct(driver_endpt, (vir_bytes) iovec,
                             count * sizeof(iovec[0]), CPF_READ);
    assert(grant != GRANT_INVALID);

    m.m_type = do_write ? BDEV_SCATTER : BDEV_GATHER;
    m.BDEV_MINOR = driver_minor;
    m.BDEV_COUNT = count;
    m.BDEV_GRANT = grant;
    m.BDEV_FLAGS = flags;
    m.BDEV_ID = 0;
    m.BDEV_POS_LO = ex64lo(position);
    m.BDEV_POS_HI = ex64hi(position);

    if ((r = sendrec(driver_endpt, &m)) != OK)
        panic("sendrec to driver failed (%d)\n", r);

    if (m.m_type != BDEV_REPLY)
        panic("invalid reply from driver (%d)\n", m.m_type);

    cpf_revoke(grant);

    for (i = 0; i < count; i++)
        cpf_revoke(iovec[i].iov_grant);

    return m.BDEV_STATUS;
}
Пример #18
0
static void dump_entry(btrace_entry *entry)
{
  switch (entry->request) {
  case BTREQ_OPEN: printf("OPEN"); break;
  case BTREQ_CLOSE: printf("CLOSE"); break;
  case BTREQ_READ: printf("READ"); break;
  case BTREQ_WRITE: printf("WRITE"); break;
  case BTREQ_GATHER: printf("GATHER"); break;
  case BTREQ_SCATTER: printf("SCATTER"); break;
  case BTREQ_IOCTL: printf("IOCTL"); break;
  }

  printf(" request\n");

  switch (entry->request) {
  case BTREQ_OPEN:
	printf("- access:\t%x\n", entry->size);
	break;
  case BTREQ_READ:
  case BTREQ_WRITE:
  case BTREQ_GATHER:
  case BTREQ_SCATTER:
	printf("- position:\t%08lx%08lx\n",
		ex64hi(entry->position), ex64lo(entry->position));
	printf("- size:\t\t%u\n", entry->size);
	printf("- flags:\t%x\n", entry->flags);
	break;
  case BTREQ_IOCTL:
	printf("- request:\t%08x\n", entry->size);
	break;
  }

  printf("- start:\t%u us\n", entry->start_time);
  printf("- finish:\t%u us\n", entry->finish_time);
  if (entry->result == BTRES_INPROGRESS)
	printf("- result:\t(in progress)\n");
  else
	printf("- result:\t%d\n", entry->result);
  printf("\n");
}
Пример #19
0
/*===========================================================================*
 *			req_breadwrite					     *
 *===========================================================================*/
PUBLIC int req_breadwrite(
  endpoint_t fs_e,
  endpoint_t user_e,
  dev_t dev,
  u64_t pos,
  unsigned int num_of_bytes,
  char *user_addr,
  int rw_flag,
  u64_t *new_posp,
  unsigned int *cum_iop
)
{
  int r;
  cp_grant_id_t grant_id;
  message m;

  grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes,
			(rw_flag == READING ? CPF_WRITE : CPF_READ));
  if(grant_id == -1)
	  panic("req_breadwrite: cpf_grant_magic failed");

  /* Fill in request message */
  m.m_type = rw_flag == READING ? REQ_BREAD : REQ_BWRITE;
  m.REQ_DEV2 = dev;
  m.REQ_GRANT = grant_id;
  m.REQ_SEEK_POS_LO = ex64lo(pos);
  m.REQ_SEEK_POS_HI = ex64hi(pos);
  m.REQ_NBYTES = num_of_bytes;

  /* Send/rec request */
  r = fs_sendrec(fs_e, &m);
  cpf_revoke(grant_id);
  if (r != OK) return(r);

  /* Fill in response structure */
  *new_posp = make64(m.RES_SEEK_POS_LO, m.RES_SEEK_POS_HI);
  *cum_iop = m.RES_NBYTES;

  return(OK);
}
Пример #20
0
PUBLIC void print_proc(struct proc *pp)
{
	struct proc *depproc = NULL;
	endpoint_t dep;

	printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cpu %2d "
			"cr3 0x%lx rts %s misc %s sched %s ",
		proc_nr(pp), pp->p_name, pp->p_endpoint, 
		pp->p_priority, pp->p_user_time,
		pp->p_sys_time, ex64hi(pp->p_cycles),
		ex64lo(pp->p_cycles), pp->p_cpu,
		pp->p_seg.p_cr3,
		rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags),
		schedulerstr(pp->p_scheduler));

	print_sigmgr(pp);

	dep = P_BLOCKEDON(pp);
	if(dep != NONE) {
		printf(" blocked on: ");
		print_endpoint(dep);
	}
	printf("\n");
}
Пример #21
0
int startsim(void){

message m;
int i,j=0,piReady = -1;
u64_t cpuTimeDiff;
FILE *fp;

fp = fopen("/home/out","w");

for(i=0;i<HISTORY;i++){
	pInfoPtrs[i] = (struct pi *) &pInfo[i][0]; 
}
for(i=0;i<HISTORY;i++){
	pQhPtrs[i] = (struct qh*) &pQh[i][0];
}

/* Copy the pointer arrays so that you can go backward and forward through the history */
struct pi *pInfoPtrsCopy[HISTORY];
struct qh *pQhPtrsCopy[HISTORY];
for(i=0;i<HISTORY;i++){
	pInfoPtrsCopy[i] = pInfoPtrs[i];
	pQhPtrsCopy[i] = pQhPtrs[i];
}
m.m1_p1 = (char *) &pInfoPtrs;
m.m1_p2 = (char *) &piReady;
m.m1_i2 = SELF;
m.m1_i3 = HISTORY;
m.m2_p1 = (char *) &pQhPtrs;
m.m3_p1 = (char *) &cpuFreq;

int error = _syscall(PM_PROC_NR,STARTRECORD,&m);
procs();
for(j;j<HISTORY;j++){
		while(piReady < j){
		}
		if(j==0){
			fprintf(fp,"CPU frequency is: %lu Mhz\n",div64u(cpuFreq, 1000000));
		}
		printf("Simulation is %d%% complete.\n",(j*2)+2);
		fprintf(fp,"Proc Table %d\n\n",j);
		fprintf(fp,"Queue heads: ");
		for(i=0;i<NR_SCHED_QUEUES;i++){
				if(pQhPtrsCopy[j]->p_endpoint!=-1){
					fprintf(fp,"Queue: %d %d ",i,pQhPtrsCopy[j]->p_endpoint);
				}
				pQhPtrsCopy[j]++;
		}
		fprintf(fp,"\n\n");
		pQhPtrsCopy[j] = pQhPtrs[j];
	
	/*Write out the runable queues in order */
	for(i=0; i<NR_SCHED_QUEUES; i++){
			fprintf(fp,"Priority Queue %d: ",i);
			if(pQhPtrsCopy[j]->p_endpoint != -1){
				printQ(pInfoPtrsCopy[j],pQhPtrsCopy[j]->p_endpoint,fp);
			}
			else{
				fprintf(fp,"\n");
			}
			pQhPtrsCopy[j]++;
	}
	pQhPtrsCopy[j] = pQhPtrs[j]; /* Reset the Qh Pointers */

	for (i=0;i<ALL_PROCS;i++){ 
		if (!(pInfoPtrsCopy[j]->p_rts_flags == RTS_SLOT_FREE)){ 
			if(j>0){
				cpuTimeDiff = sub64(pInfoPtrsCopy[j]->p_cycles,pInfoPtrsCopy[j-1]->p_cycles);
				}
		fprintf(fp,"Process: %s, Endpoint: %d, Enter queue: %lu%lu, Time in Queue: %lu%lu, Dequeues: %lu, IPC Sync: %lu, IPC Async: %lu,Preempted: %lu,RTS: %x\n\t\t, Priority: %d, Next: %s Endpoint: %d, User time: %d, Sys Time: %d, CPU Cycles Elaps: %lu%lu\n",
				pInfoPtrsCopy[j]->p_name,pInfoPtrsCopy[j]->p_endpoint,ex64hi(pInfoPtrsCopy[j]->p_times.enter_queue),ex64lo(pInfoPtrsCopy[j]->p_times.enter_queue),
				ex64hi(pInfoPtrsCopy[j]->p_times.time_in_queue),ex64lo(pInfoPtrsCopy[j]->p_times.time_in_queue),
				pInfoPtrsCopy[j]->p_times.dequeues,pInfoPtrsCopy[j]->p_times.ipc_sync,pInfoPtrsCopy[j]->p_times.ipc_async,
				pInfoPtrsCopy[j]->p_times.preempted,pInfoPtrsCopy[j]->p_rts_flags,pInfoPtrsCopy[j]->p_priority, pInfoPtrsCopy[j]->p_nextready,
				pInfoPtrsCopy[j]->p_nextready_endpoint,pInfoPtrsCopy[j]->p_user_time,pInfoPtrsCopy[j]->p_sys_time,ex64hi(cpuTimeDiff),
				ex64lo(cpuTimeDiff));
		}
		pInfoPtrsCopy[j]++;
		if(j>0){
			pInfoPtrsCopy[j-1]++;
		}
	}
	pInfoPtrsCopy[j] = pInfoPtrs[j];	
}

m.m1_i3 = -1;
_syscall(PM_PROC_NR,STARTRECORD,&m);
return(0);
}
Пример #22
0
PUBLIC void context_stop(struct proc * p)
{
	u64_t tsc, tsc_delta;
	u64_t * __tsc_ctr_switch = get_cpulocal_var_ptr(tsc_ctr_switch);
#ifdef CONFIG_SMP
	unsigned cpu = cpuid;

	/*
	 * This function is called only if we switch from kernel to user or idle
	 * or back. Therefore this is a perfect location to place the big kernel
	 * lock which will hopefully disappear soon.
	 *
	 * If we stop accounting for KERNEL we must unlock the BKL. If account
	 * for IDLE we must not hold the lock
	 */
	if (p == proc_addr(KERNEL)) {
		u64_t tmp;

		read_tsc_64(&tsc);
		tmp = sub64(tsc, *__tsc_ctr_switch);
		kernel_ticks[cpu] = add64(kernel_ticks[cpu], tmp);
		p->p_cycles = add64(p->p_cycles, tmp);
		BKL_UNLOCK();
	} else {
		u64_t bkl_tsc;
		atomic_t succ;
		
		read_tsc_64(&bkl_tsc);
		/* this only gives a good estimate */
		succ = big_kernel_lock.val;
		
		BKL_LOCK();
		
		read_tsc_64(&tsc);

		bkl_ticks[cpu] = add64(bkl_ticks[cpu], sub64(tsc, bkl_tsc));
		bkl_tries[cpu]++;
		bkl_succ[cpu] += !(!(succ == 0));

		p->p_cycles = add64(p->p_cycles, sub64(tsc, *__tsc_ctr_switch));

#ifdef CONFIG_SMP
		/*
		 * Since at the time we got a scheduling IPI we might have been
		 * waiting for BKL already, we may miss it due to a similar IPI to
		 * the cpu which is already waiting for us to handle its. This
		 * results in a live-lock of these two cpus.
		 *
		 * Therefore we always check if there is one pending and if so,
		 * we handle it straight away so the other cpu can continue and
		 * we do not deadlock.
		 */
		smp_sched_handler();
#endif
	}
#else
	read_tsc_64(&tsc);
	p->p_cycles = add64(p->p_cycles, sub64(tsc, *__tsc_ctr_switch));
#endif
	
	tsc_delta = sub64(tsc, *__tsc_ctr_switch);

	if(kbill_ipc) {
		kbill_ipc->p_kipc_cycles =
			add64(kbill_ipc->p_kipc_cycles, tsc_delta);
		kbill_ipc = NULL;
	}

	if(kbill_kcall) {
		kbill_kcall->p_kcall_cycles =
			add64(kbill_kcall->p_kcall_cycles, tsc_delta);
		kbill_kcall = NULL;
	}

	/*
	 * deduct the just consumed cpu cycles from the cpu time left for this
	 * process during its current quantum. Skip IDLE and other pseudo kernel
	 * tasks
	 */
	if (p->p_endpoint >= 0) {
#if DEBUG_RACE
		make_zero64(p->p_cpu_time_left);
#else
		/* if (tsc_delta < p->p_cpu_time_left) in 64bit */
		if (ex64hi(tsc_delta) < ex64hi(p->p_cpu_time_left) ||
				(ex64hi(tsc_delta) == ex64hi(p->p_cpu_time_left) &&
				 ex64lo(tsc_delta) < ex64lo(p->p_cpu_time_left)))
			p->p_cpu_time_left = sub64(p->p_cpu_time_left, tsc_delta);
		else {
			make_zero64(p->p_cpu_time_left);
		}
#endif
	}

	*__tsc_ctr_switch = tsc;
}
Пример #23
0
/*===========================================================================*
 *				do_fcntl				     *
 *===========================================================================*/
PUBLIC int do_fcntl()
{
/* Perform the fcntl(fd, request, ...) system call. */

  register struct filp *f;
  int new_fd, r, fl;
  struct filp *dummy;

  /* Is the file descriptor valid? */
  if ((f = get_filp(m_in.fd)) == NULL) return(err_code);
  
  switch (m_in.request) {
     case F_DUPFD:
	/* This replaces the old dup() system call. */
	if (m_in.addr < 0 || m_in.addr >= OPEN_MAX) return(EINVAL);
	if ((r = get_fd(m_in.addr, 0, &new_fd, &dummy)) != OK) return(r);
	f->filp_count++;
	fp->fp_filp[new_fd] = f;
	return(new_fd);

     case F_GETFD:
	/* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
	return( FD_ISSET(m_in.fd, &fp->fp_cloexec_set) ? FD_CLOEXEC : 0);

     case F_SETFD:
	/* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
	if(m_in.addr & FD_CLOEXEC)
		FD_SET(m_in.fd, &fp->fp_cloexec_set);
	else
		FD_CLR(m_in.fd, &fp->fp_cloexec_set);
	return(OK);

     case F_GETFL:
	/* Get file status flags (O_NONBLOCK and O_APPEND). */
	fl = f->filp_flags & (O_NONBLOCK | O_APPEND | O_ACCMODE);
	return(fl);	

     case F_SETFL:
	/* Set file status flags (O_NONBLOCK and O_APPEND). */
	fl = O_NONBLOCK | O_APPEND | O_REOPEN;
	f->filp_flags = (f->filp_flags & ~fl) | (m_in.addr & fl);
	return(OK);

     case F_GETLK:
     case F_SETLK:
     case F_SETLKW:
	/* Set or clear a file lock. */
	r = lock_op(f, m_in.request);
	return(r);

     case F_FREESP:
     {
	/* Free a section of a file. Preparation is done here, actual freeing
	 * in freesp_inode().
	 */
	off_t start, end;
	struct flock flock_arg;
	signed long offset;

	/* Check if it's a regular file. */
	if((f->filp_vno->v_mode & I_TYPE) != I_REGULAR) return(EINVAL);
	if (!(f->filp_mode & W_BIT)) return(EBADF);

	/* Copy flock data from userspace. */
	if((r = sys_datacopy(who_e, (vir_bytes) m_in.name1, SELF, 
	     (vir_bytes) &flock_arg, (phys_bytes) sizeof(flock_arg))) != OK)
		return(r);

	/* Convert starting offset to signed. */
	offset = (signed long) flock_arg.l_start;

	/* Figure out starting position base. */
	switch(flock_arg.l_whence) {
	   case SEEK_SET: start = 0; break;
	   case SEEK_CUR:
	      if (ex64hi(f->filp_pos) != 0) 
			panic("do_fcntl: position in file too high");
	      start = ex64lo(f->filp_pos);
	      break;
	   case SEEK_END: start = f->filp_vno->v_size; break;
	   default: return EINVAL;
	}

	/* Check for overflow or underflow. */
	if(offset > 0 && start + offset < start) return EINVAL;
	if(offset < 0 && start + offset > start) return EINVAL; 
	start += offset;
	if(start < 0) return EINVAL;

	if(flock_arg.l_len != 0) {
		if(start >= f->filp_vno->v_size) return EINVAL;
		end = start + flock_arg.l_len;
		if(end <= start) return EINVAL;
		if(end > f->filp_vno->v_size) end = f->filp_vno->v_size;
	} else {
                end = 0;
	}

	r = req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr, start,
		end);

	if(r == OK && flock_arg.l_len == 0)
		f->filp_vno->v_size = start;

	return(r);
     }

     default:
	return(EINVAL);
  }
}
Пример #24
0
/*===========================================================================*
 *				m_transfer				     *
 *===========================================================================*/
static int m_transfer(
  endpoint_t endpt,		/* endpoint of grant owner */
  int opcode,			/* DEV_GATHER_S or DEV_SCATTER_S */
  u64_t pos64,			/* offset on device to read or write */
  iovec_t *iov,			/* pointer to read or write request vector */
  unsigned int nr_req,		/* length of request vector */
  endpoint_t UNUSED(user_endpt),/* endpoint of user process */
  unsigned int UNUSED(flags)
)
{
/* Read or write one the driver's character devices. */
  unsigned count, left, chunk;
  vir_bytes vir_offset = 0;
  struct device *dv;
  unsigned long dv_size;
  int s, r;
  off_t position;
  cp_grant_id_t grant;
  vir_bytes dev_vaddr;

  /* ZERO_DEV and NULL_DEV are infinite in size. */
  if (m_device != ZERO_DEV && m_device != NULL_DEV && ex64hi(pos64) != 0)
	return OK;	/* Beyond EOF */
  position= cv64ul(pos64);

  /* Get minor device number and check for /dev/null. */
  dv = &m_geom[m_device];
  dv_size = cv64ul(dv->dv_size);
  dev_vaddr = m_vaddrs[m_device];

  while (nr_req > 0) {

	/* How much to transfer and where to / from. */
	count = iov->iov_size;
	grant = (cp_grant_id_t) iov->iov_addr;

	switch (m_device) {

	/* No copying; ignore request. */
	case NULL_DEV:
	    if (opcode == DEV_GATHER_S) return(OK);	/* always at EOF */
	    break;

	/* Virtual copying. For kernel memory. */
	default:
	case KMEM_DEV:
	    if(!dev_vaddr || dev_vaddr == (vir_bytes) MAP_FAILED) {
		printf("MEM: dev %d not initialized\n", m_device);
		return EIO;
	    }
	    if (position >= dv_size) return(OK);	/* check for EOF */
	    if (position + count > dv_size) count = dv_size - position;
	    if (opcode == DEV_GATHER_S) {	/* copy actual data */
	        r=sys_safecopyto(endpt, grant, vir_offset,
		  dev_vaddr + position, count);
	    } else {
	        r=sys_safecopyfrom(endpt, grant, vir_offset,
		  dev_vaddr + position, count);
	    }
	    if(r != OK) {
              panic("I/O copy failed: %d", r);
	    }
	    break;

	/* Physical copying. Only used to access entire memory.
	 * Transfer one 'page window' at a time.
	 */
	case MEM_DEV:
	{
	    u32_t pagestart, page_off;
	    static u32_t pagestart_mapped;
	    static int any_mapped = 0;
	    static char *vaddr;
	    int r;
	    u32_t subcount;
	    phys_bytes mem_phys;

	    if (position >= dv_size)
		return(OK);	/* check for EOF */
	    if (position + count > dv_size)
		count = dv_size - position;
	    mem_phys = position;

	    page_off = mem_phys % PAGE_SIZE;
	    pagestart = mem_phys - page_off; 

	    /* All memory to the map call has to be page-aligned.
	     * Don't have to map same page over and over.
	     */
	    if(!any_mapped || pagestart_mapped != pagestart) {
	     if(any_mapped) {
		if(vm_unmap_phys(SELF, vaddr, PAGE_SIZE) != OK)
			panic("vm_unmap_phys failed");
		any_mapped = 0;
	     }
	     vaddr = vm_map_phys(SELF, (void *) pagestart, PAGE_SIZE);
	     if(vaddr == MAP_FAILED) 
		r = ENOMEM;
	     else
		r = OK;
	     if(r != OK) {
		printf("memory: vm_map_phys failed\n");
		return r;
	     }
	     any_mapped = 1;
	     pagestart_mapped = pagestart;
	   }

	    /* how much to be done within this page. */
	    subcount = PAGE_SIZE-page_off;
	    if(subcount > count)
		subcount = count;

	    if (opcode == DEV_GATHER_S) {			/* copy data */
	           s=sys_safecopyto(endpt, grant,
		       vir_offset, (vir_bytes) vaddr+page_off, subcount);
	    } else {
	           s=sys_safecopyfrom(endpt, grant,
		       vir_offset, (vir_bytes) vaddr+page_off, subcount);
	    }
	    if(s != OK)
		return s;
	    count = subcount;
	    break;
	}

	/* Null byte stream generator. */
	case ZERO_DEV:
	    if (opcode == DEV_GATHER_S) {
		size_t suboffset = 0;
	        left = count;
		while (left > 0) {
		    chunk = (left > ZERO_BUF_SIZE) ? ZERO_BUF_SIZE : left;
	             s=sys_safecopyto(endpt, grant,
		       vir_offset+suboffset, (vir_bytes) dev_zero, chunk);
		    if(s != OK)
		        return s;
		    left -= chunk;
	            suboffset += chunk;
		}
	    }
	    break;

	}

	/* Book the number of bytes transferred. */
	position += count;
	vir_offset += count;
	if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }

  }
  return(OK);
}
Пример #25
0
/*===========================================================================*
 *				do_fcntl				     *
 *===========================================================================*/
int do_fcntl()
{
/* Perform the fcntl(fd, request, ...) system call. */

  register struct filp *f;
  int new_fd, fl, r = OK, fcntl_req, fcntl_argx;
  tll_access_t locktype;

  scratch(fp).file.fd_nr = job_m_in.fd;
  scratch(fp).io.io_buffer = job_m_in.buffer;
  scratch(fp).io.io_nbytes = job_m_in.nbytes;	/* a.k.a. m_in.request */
  fcntl_req = job_m_in.request;
  fcntl_argx = job_m_in.addr;

  /* Is the file descriptor valid? */
  locktype = (fcntl_req == F_FREESP) ? VNODE_WRITE : VNODE_READ;
  if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
	return(err_code);

  switch (fcntl_req) {
    case F_DUPFD:
	/* This replaces the old dup() system call. */
	if (fcntl_argx < 0 || fcntl_argx >= OPEN_MAX) r = EINVAL;
	else if ((r = get_fd(fcntl_argx, 0, &new_fd, NULL)) == OK) {
		f->filp_count++;
		fp->fp_filp[new_fd] = f;
		FD_SET(new_fd, &fp->fp_filp_inuse);
		r = new_fd;
	}
	break;

    case F_GETFD:
	/* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
	r = 0;
	if (FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set))
		r = FD_CLOEXEC;
	break;

    case F_SETFD:
	/* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
	if (fcntl_argx & FD_CLOEXEC)
		FD_SET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
	else
		FD_CLR(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
	break;

    case F_GETFL:
	/* Get file status flags (O_NONBLOCK and O_APPEND). */
	fl = f->filp_flags & (O_NONBLOCK | O_APPEND | O_ACCMODE);
	r = fl;
	break;

    case F_SETFL:
	/* Set file status flags (O_NONBLOCK and O_APPEND). */
	fl = O_NONBLOCK | O_APPEND | O_REOPEN;
	f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl);
	break;

    case F_GETLK:
    case F_SETLK:
    case F_SETLKW:
	/* Set or clear a file lock. */
	r = lock_op(f, fcntl_req);
	break;

    case F_FREESP:
     {
	/* Free a section of a file */
	off_t start, end;
	struct flock flock_arg;
	signed long offset;

	/* Check if it's a regular file. */
	if (!S_ISREG(f->filp_vno->v_mode)) r = EINVAL;
	else if (!(f->filp_mode & W_BIT)) r = EBADF;
	else
		/* Copy flock data from userspace. */
		r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer,
				 SELF, (vir_bytes) &flock_arg,
				 sizeof(flock_arg));

	if (r != OK) break;

	/* Convert starting offset to signed. */
	offset = (signed long) flock_arg.l_start;

	/* Figure out starting position base. */
	switch(flock_arg.l_whence) {
	  case SEEK_SET: start = 0; break;
	  case SEEK_CUR:
		if (ex64hi(f->filp_pos) != 0)
			panic("do_fcntl: position in file too high");
		start = ex64lo(f->filp_pos);
		break;
	  case SEEK_END: start = f->filp_vno->v_size; break;
	  default: r = EINVAL;
	}
	if (r != OK) break;

	/* Check for overflow or underflow. */
	if (offset > 0 && start + offset < start) r = EINVAL;
	else if (offset < 0 && start + offset > start) r = EINVAL;
	else {
		start += offset;
		if (start < 0) r = EINVAL;
	}
	if (r != OK) break;

	if (flock_arg.l_len != 0) {
		if (start >= f->filp_vno->v_size) r = EINVAL;
		else if ((end = start + flock_arg.l_len) <= start) r = EINVAL;
		else if (end > f->filp_vno->v_size) end = f->filp_vno->v_size;
	} else {
                end = 0;
	}
	if (r != OK) break;

	r = req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr,start,end);

	if (r == OK && flock_arg.l_len == 0)
		f->filp_vno->v_size = start;

	break;
     }
    case F_GETNOSIGPIPE:
	/* POSIX: return value other than -1 is flag is set, else -1 */
	r = -1;
	if (f->filp_flags & O_NOSIGPIPE)
		r = 0;
	break;
    case F_SETNOSIGPIPE:
	fl = (O_NOSIGPIPE);
	f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl);
	break;
    default:
	r = EINVAL;
  }

  unlock_filp(f);
  return(r);
}
Пример #26
0
/*===========================================================================*
 *				m_block_transfer			     *
 *===========================================================================*/
static int m_block_transfer(
  dev_t minor,			/* minor device number */
  int do_write,			/* read or write? */
  u64_t pos64,			/* offset on device to read or write */
  endpoint_t endpt,		/* process doing the request */
  iovec_t *iov,			/* pointer to read or write request vector */
  unsigned int nr_req,		/* length of request vector */
  int UNUSED(flags)		/* transfer flags */
)
{
/* Read or write one the driver's block devices. */
  unsigned count;
  vir_bytes vir_offset = 0;
  struct device *dv;
  unsigned long dv_size;
  int r;
  off_t position;
  vir_bytes dev_vaddr;
  cp_grant_id_t grant;
  ssize_t total = 0;

  /* Get minor device information. */
  if ((dv = m_block_part(minor)) == NULL) return(ENXIO);
  dv_size = cv64ul(dv->dv_size);
  dev_vaddr = m_vaddrs[minor];

  if (ex64hi(pos64) != 0)
	return OK;	/* Beyond EOF */
  position= cv64ul(pos64);

  while (nr_req > 0) {

	/* How much to transfer and where to / from. */
	count = iov->iov_size;
	grant = (cp_grant_id_t) iov->iov_addr;

	/* Virtual copying. For RAM disks and internal FS. */
	if(!dev_vaddr || dev_vaddr == (vir_bytes) MAP_FAILED) {
		printf("MEM: dev %d not initialized\n", minor);
		return EIO;
	}
	if (position >= dv_size) return(total);	/* check for EOF */
	if (position + count > dv_size) count = dv_size - position;
	if (!do_write) {	/* copy actual data */
	        r=sys_safecopyto(endpt, grant, vir_offset,
		  dev_vaddr + position, count);
	} else {
	        r=sys_safecopyfrom(endpt, grant, vir_offset,
		  dev_vaddr + position, count);
	}
	if(r != OK) {
		panic("I/O copy failed: %d", r);
	}

	/* Book the number of bytes transferred. */
	position += count;
	vir_offset += count;
	total += count;
	if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }

  }
  return(total);
}
Пример #27
0
/*===========================================================================*
 *				m_block_ioctl				     *
 *===========================================================================*/
static int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
	cp_grant_id_t grant)
{
/* I/O controls for the block devices of the memory driver. Currently there is
 * one I/O control specific to the memory driver:
 * - MIOCRAMSIZE: to set the size of the RAM disk.
 */
  struct device *dv;
  u32_t ramdev_size;
  int s;
  void *mem;

  if (request != MIOCRAMSIZE)
	return EINVAL;

  /* Someone wants to create a new RAM disk with the given size.
   * A ramdisk can be created only once, and only on RAM disk device.
   */
  if ((dv = m_block_part(minor)) == NULL) return ENXIO;
  if((minor < RAM_DEV_FIRST || minor > RAM_DEV_LAST) && minor != RAM_DEV_OLD) {
	printf("MEM: MIOCRAMSIZE: %d not a ramdisk\n", minor);
	return EINVAL;
  }

  /* Get request structure */
  s= sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&ramdev_size,
	sizeof(ramdev_size));
  if (s != OK)
	return s;
  if(m_vaddrs[minor] && !cmp64(dv->dv_size, cvul64(ramdev_size))) {
	return(OK);
  }
  /* openct is 1 for the ioctl(). */
  if(openct[minor] != 1) {
	printf("MEM: MIOCRAMSIZE: %d in use (count %d)\n",
		minor, openct[minor]);
	return(EBUSY);
  }
  if(m_vaddrs[minor]) {
	u32_t size;
	if(ex64hi(dv->dv_size)) {
		panic("huge old ramdisk");
	}
	size = ex64lo(dv->dv_size);
	minix_munmap((void *) m_vaddrs[minor], size);
	m_vaddrs[minor] = (vir_bytes) NULL;
  }

#if DEBUG
  printf("MEM:%d: allocating ramdisk of size 0x%x\n", minor, ramdev_size);
#endif

  /* Try to allocate a piece of memory for the RAM disk. */
  if((mem = minix_mmap(NULL, ramdev_size, PROT_READ|PROT_WRITE,
		MAP_PREALLOC|MAP_ANON, -1, 0)) == MAP_FAILED) {
	printf("MEM: failed to get memory for ramdisk\n");
	return(ENOMEM);
  }

  m_vaddrs[minor] = (vir_bytes) mem;

  dv->dv_size = cvul64(ramdev_size);

  return(OK);
}
Пример #28
0
/*===========================================================================*
 *				fs_breadwrite_o				     *
 *===========================================================================*/
PUBLIC int fs_breadwrite_o(void)
{
  int r, usr, rw_flag, chunk, block_size;
  int nrbytes;
  u64_t position;
  unsigned int off, cum_io;
  mode_t mode_word;
  int completed, r2 = OK;
  char *user_addr;

  /* Pseudo inode for rw_chunk */
  struct inode rip;
  
  r = OK;
  
  /* Get the values from the request message */ 
  rw_flag = (fs_m_in.m_type == REQ_BREAD_O ? READING : WRITING);
  usr = fs_m_in.REQ_XFD_WHO_E;
  position = make64(fs_m_in.REQ_XFD_POS_LO, fs_m_in.REQ_XFD_POS_HI);
  nrbytes = (unsigned) fs_m_in.REQ_XFD_NBYTES;
  user_addr = fs_m_in.REQ_XFD_USER_ADDR;
  
  block_size = get_block_size(fs_m_in.REQ_XFD_BDEV);

  rip.i_zone[0] = fs_m_in.REQ_XFD_BDEV;
  rip.i_mode = I_BLOCK_SPECIAL;
  rip.i_size = 0;

  rdwt_err = OK;		/* set to EIO if disk error occurs */
  
  cum_io = 0;
  /* Split the transfer into chunks that don't span two blocks. */
  while (nrbytes != 0) {
      off = rem64u(position, block_size);	/* offset in blk*/
        
      chunk = MIN(nrbytes, block_size - off);
      if (chunk < 0) chunk = block_size - off;

      /* Read or write 'chunk' bytes. */
      r = rw_chunk(&rip, position, off, chunk, (unsigned) nrbytes,
              rw_flag, user_addr, D, usr, block_size, &completed);

      if (r != OK) break;	/* EOF reached */
      if (rdwt_err < 0) break;

      /* Update counters and pointers. */
      user_addr += chunk;	/* user buffer address */
      nrbytes -= chunk;	        /* bytes yet to be read */
      cum_io += chunk;	        /* bytes read so far */
      position= add64ul(position, chunk);	/* position within the file */
  }
  
  fs_m_out.RES_XFD_POS_LO = ex64lo(position); 
  fs_m_out.RES_XFD_POS_HI = ex64hi(position); 
  
  if (rdwt_err != OK) r = rdwt_err;	/* check for disk error */
  if (rdwt_err == END_OF_FILE) r = OK;

  fs_m_out.RES_XFD_CUM_IO = cum_io;
  
  return(r);
}
Пример #29
0
/*===========================================================================*
 *				read_write				     *
 *===========================================================================*/
int read_write(u64_t pos, char *bufa, char *bufb, size_t *sizep, int request)
{
    iovec_s_t vectors[2][NR_IOREQS];
    message m1, m2;
    cp_grant_id_t gids[2];
    int r, both, count;

    gids[0] = gids[1] = GRANT_INVALID;

    /* Send two requests only if mirroring is enabled and the given request
     * is either FLT_READ2 or FLT_WRITE.
     */
    both = (USE_MIRROR && request != FLT_READ);

    count = paired_grant(bufa, bufb, request, gids, vectors, *sizep, both);

    memset(&m1, 0, sizeof(m1));
    m1.m_type = (request == FLT_WRITE) ? BDEV_SCATTER : BDEV_GATHER;
    m1.BDEV_COUNT = count;
    m1.BDEV_POS_LO = ex64lo(pos);
    m1.BDEV_POS_HI = ex64hi(pos);

    m2 = m1;

    m1.BDEV_GRANT = gids[0];
    m2.BDEV_GRANT = gids[1];

    r = paired_sendrec(&m1, &m2, both);

    paired_revoke(gids, vectors, count, both);

    if(r != OK) {
#if DEBUG
        if (r != RET_REDO)
            printf("Filter: paired_sendrec returned %d\n", r);
#endif
        return r;
    }

    if (m1.m_type != BDEV_REPLY || m1.BDEV_STATUS < 0) {
        printf("Filter: unexpected/invalid reply from main driver: "
               "(%x, %d)\n", m1.m_type, m1.BDEV_STATUS);

        return bad_driver(DRIVER_MAIN, BD_PROTO,
                          (m1.m_type == BDEV_REPLY) ? m1.BDEV_STATUS : EFAULT);
    }

    if (m1.BDEV_STATUS != (ssize_t) *sizep) {
        printf("Filter: truncated reply from main driver\n");

        /* If the driver returned a value *larger* than we requested,
         * OR if we did NOT exceed the disk size, then we should
         * report the driver for acting strangely!
         */
        if (m1.BDEV_STATUS > (ssize_t) *sizep ||
                cmp64(add64u(pos, m1.BDEV_STATUS), disk_size) < 0)
            return bad_driver(DRIVER_MAIN, BD_PROTO, EFAULT);

        /* Return the actual size. */
        *sizep = m1.BDEV_STATUS;
    }

    if (both) {
        if (m2.m_type != BDEV_REPLY || m2.BDEV_STATUS < 0) {
            printf("Filter: unexpected/invalid reply from "
                   "backup driver (%x, %d)\n",
                   m2.m_type, m2.BDEV_STATUS);

            return bad_driver(DRIVER_BACKUP, BD_PROTO,
                              m2.m_type == BDEV_REPLY ? m2.BDEV_STATUS :
                              EFAULT);
        }
        if (m2.BDEV_STATUS != (ssize_t) *sizep) {
            printf("Filter: truncated reply from backup driver\n");

            /* As above */
            if (m2.BDEV_STATUS > (ssize_t) *sizep ||
                    cmp64(add64u(pos, m2.BDEV_STATUS),
                          disk_size) < 0)
                return bad_driver(DRIVER_BACKUP, BD_PROTO,
                                  EFAULT);

            /* Return the actual size. */
            if ((ssize_t) *sizep >= m2.BDEV_STATUS)
                *sizep = m2.BDEV_STATUS;
        }
    }

    return OK;
}
Пример #30
0
/*===========================================================================*
 *				do_create				     *
 *===========================================================================*/
PUBLIC int do_create()
{
/* Create a new file.
 */
  char path[PATH_MAX], name[NAME_MAX+1];
  struct inode *parent, *ino;
  struct hgfs_attr attr;
  hgfs_file_t handle;
  int r;

  /* We cannot create files on a read-only file system. */
  if (state.read_only)
	return EROFS;

  /* Get path, name, parent inode and possibly inode for the given path. */
  if ((r = get_name(m_in.REQ_GRANT, m_in.REQ_PATH_LEN, name)) != OK)
	return r;

  if (!strcmp(name, ".") || !strcmp(name, "..")) return EEXIST;

  if ((parent = find_inode(m_in.REQ_INODE_NR)) == NULL)
	return EINVAL;

  if ((r = verify_dentry(parent, name, path, &ino)) != OK)
	return r;

  /* Are we going to need a new inode upon success?
   * Then make sure there is one available before trying anything.
   */
  if (ino == NULL || ino->i_ref > 1 || HAS_CHILDREN(ino)) {
	if (!have_free_inode()) {
		if (ino != NULL)
			put_inode(ino);

		return ENFILE;
	}
  }

  /* Perform the actual create call. */
  r = hgfs_open(path, O_CREAT | O_EXCL | O_RDWR, m_in.REQ_MODE, &handle);

  if (r != OK) {
	/* Let's not try to be too clever with error codes here. If something
	 * is wrong with the directory, we'll find out later anyway.
	 */

	if (ino != NULL)
		put_inode(ino);

	return r;
  }

  /* Get the created file's attributes. */
  attr.a_mask = HGFS_ATTR_MODE | HGFS_ATTR_SIZE;
  r = hgfs_getattr(path, &attr);

  /* If this fails, or returns a directory, we have a problem. This
   * scenario is in fact possible with race conditions.
   * Simulate a close and return a somewhat appropriate error.
   */
  if (r != OK || S_ISDIR(attr.a_mode)) {
	printf("HGFS: lost file after creation!\n");

	hgfs_close(handle);

	if (ino != NULL) {
		del_dentry(ino);

		put_inode(ino);
	}

	return (r == OK) ? EEXIST : r;
  }

  /* We do assume that the HGFS open(O_CREAT|O_EXCL) did its job.
   * If we previousy found an inode, get rid of it now. It's old.
   */
  if (ino != NULL) {
	del_dentry(ino);

	put_inode(ino);
  }

  /* Associate the open file handle with an inode, and reply with its details.
   */
  ino = get_free_inode();

  assert(ino != NULL); /* we checked before whether we had a free one */

  ino->i_file = handle;
  ino->i_flags = I_HANDLE;

  add_dentry(parent, name, ino);

  m_out.RES_INODE_NR = INODE_NR(ino);
  m_out.RES_MODE = get_mode(ino, attr.a_mode);
  m_out.RES_FILE_SIZE_HI = ex64hi(attr.a_size);
  m_out.RES_FILE_SIZE_LO = ex64lo(attr.a_size);
  m_out.RES_UID = opt.uid;
  m_out.RES_GID = opt.gid;
  m_out.RES_DEV = NO_DEV;

  return OK;
}