Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
/*===========================================================================*
 *				do_llseek				     *
 *===========================================================================*/
int do_llseek()
{
/* Perform the llseek(ls_fd, offset, whence) system call. */
  register struct filp *rfilp;
  u64_t pos, newpos;
  int r = OK, seekfd, seekwhence;
  long off_hi, off_lo;

  seekfd = job_m_in.ls_fd;
  seekwhence = job_m_in.whence;
  off_hi = job_m_in.offset_high;
  off_lo = 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);
  }

  newpos = add64(pos, make64(off_lo, off_hi));

  /* Check for overflow. */
  if ((off_hi > 0) && cmp64(newpos, pos) < 0)
      r = EINVAL;
  else if ((off_hi < 0) && cmp64(newpos, pos) > 0)
      r = EINVAL;
  else {
	/* 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) {
		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);
}
Ejemplo n.º 3
0
/*===========================================================================*
 *				actual_llseek				     *
 *===========================================================================*/
int actual_llseek(struct fproc *rfp, message *m_out, int seekfd, int seekwhence,
	u64_t offset)
{
/* Perform the llseek(ls_fd, offset, whence) system call. */
  register struct filp *rfilp;
  u64_t pos, newpos;
  int r = OK;
  long off_hi = ex64hi(offset);

  /* Check to see if the file descriptor is valid. */
  if ( (rfilp = get_filp2(rfp, 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 = ((u64_t)(0));	break;
    case SEEK_CUR: pos = rfilp->filp_pos;	break;
    case SEEK_END: pos = ((u64_t)(rfilp->filp_vno->v_size));	break;
    default: unlock_filp(rfilp); return(EINVAL);
  }

  newpos = pos + offset;

  /* Check for overflow. */
  if ((off_hi > 0) && cmp64(newpos, pos) < 0)
      r = EINVAL;
  else if ((off_hi < 0) && cmp64(newpos, pos) > 0)
      r = EINVAL;
  else {
	/* 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) {
		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);
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
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;
	}
}
Ejemplo n.º 7
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;

  /* Check to see if the file descriptor is valid. */
  if ( (rfilp = get_filp(m_in.ls_fd)) == NULL) 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);
  }

  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) 
      return(EINVAL);
  if (((long)m_in.offset_high < 0) && cmp64(newpos, pos) > 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 != OK) return(r);
  }

  rfilp->filp_pos = newpos;
  m_out.reply_l1 = ex64lo(newpos);
  m_out.reply_l2 = ex64hi(newpos);
  return(OK);
}
Ejemplo n.º 8
0
int actual_lseek(message *m_out, int seekfd, int seekwhence, off_t offset)
{
/* Perform the lseek(ls_fd, offset, whence) system call. */
  register struct filp *rfilp;
  int r = OK;
  u64_t pos, newpos;

  /* 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);
}
Ejemplo n.º 9
0
/*===========================================================================*
 *				do_lseek				     *
 *===========================================================================*/
PUBLIC int do_lseek()
{
/* Perform the lseek(ls_fd, offset, whence) system call. */
  register struct filp *rfilp;
  int r = OK;
  long offset;
  u64_t pos, newpos;

  /* 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);
  }

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

  /* Check for overflow. */
  if (ex64hi(newpos) != 0)
	r = EINVAL;
  else {
	rfilp->filp_pos = newpos;

	/* insert the new position into the output message */
	m_out.reply_l1 = ex64lo(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);
}
Ejemplo n.º 10
0
Archivo: mkfs.c Proyecto: kl07/minix
/*================================================================
 *                    sizeup  -  determine device size
 *===============================================================*/
block_t
sizeup(char * device)
{
  block_t d;
#if defined(__minix)
  u64_t bytes, resize;
  u32_t rem;
#else
  off_t size;
#endif


  if ((fd = open(device, O_RDONLY)) == -1) {
	if (errno != ENOENT)
		perror("sizeup open");
	return 0;
  }

#if defined(__minix)
  if(minix_sizeup(device, &bytes) < 0) {
       perror("sizeup");
       return 0;
  }

  d = div64u(bytes, block_size);
  rem = rem64u(bytes, block_size);

  resize = add64u(mul64u(d, block_size), rem);
  if(cmp64(resize, bytes) != 0) {
	/* Assume block_t is unsigned */
	d = (block_t)(-1ul);
	fprintf(stderr, "%s: truncating FS at %lu blocks\n",
		progname, (unsigned long)d);
  }
#else
  size = lseek(fd, 0, SEEK_END);
  if (size == (off_t) -1)
	  err(1, "cannot get device size fd=%d: %s", fd, device);
  /* Assume block_t is unsigned */
  if (size / block_size > (block_t)(-1ul)) {
	d = (block_t)(-1ul);
	fprintf(stderr, "%s: truncating FS at %lu blocks\n",
		progname, (unsigned long)d);
  } else
	d = size / block_size;
#endif

  return d;
}
Ejemplo n.º 11
0
double getidle(void)
{
  u64_t stop, idle2;
  u64_t idelta, tdelta;
  double ifp, tfp, rfp;
  int r;

  if (!running) {
	if ((r = sys_getidletsc(&idle)) != OK)
		return -1.0;

	running = 1;

	read_tsc_64(&start);

	return 0.0;
  }
  else {
	read_tsc_64(&stop);

	running = 0;

	if ((r = sys_getidletsc(&idle2)) != OK)
		return -1.0;

	idelta = sub64(idle2, idle);
	tdelta = sub64(stop, start);

	if (cmp64(idelta, tdelta) >= 0)
		return 100.0;

	ifp = make_double(idelta);
	tfp = make_double(tdelta);

	rfp = ifp / tfp * 100.0;

	if (rfp < 0.0) rfp = 0.0;
	else if (rfp > 100.0) rfp = 100.0;

	return rfp;
  }

  running = !running;
}
Ejemplo n.º 12
0
int cmp_ticks(const void *v1, const void *v2)
{
	int c;
	struct tp *p1 = (struct tp *) v1, *p2 = (struct tp *) v2;
	int p1blocked, p2blocked;

	p1blocked = !!p1->p->p_rts_flags;
	p2blocked = !!p2->p->p_rts_flags;

	/* Primarily order by used number of cpu cycles.
	 * 
	 * Exception: if in blockedverbose mode, a blocked
	 * process is always printed after an unblocked
	 * process, and used cpu cycles don't matter.
	 *
	 * In both cases, process slot number is a tie breaker.
	 */

	if(blockedverbose && (p1blocked || p2blocked)) {
		if(!p1blocked &&  p2blocked)
			return -1;
		if( p2blocked && !p1blocked)
			return 1;
	} else if((c=cmp64(p1->ticks, p2->ticks)) != 0)
		return -c;

	/* Process slot number is a tie breaker. */

	if(p1->p->p_nr < p2->p->p_nr)
		return -1;
	if(p1->p->p_nr > p2->p->p_nr)
		return 1;

	fprintf(stderr, "unreachable.\n");
	abort();
}
Ejemplo n.º 13
0
/*===========================================================================*
 *				get_block				     *
 *===========================================================================*/
struct buf *get_block(
  register dev_t dev,		/* on which device is the block? */
  register block_t block,	/* which block is wanted? */
  int only_search		/* if NO_READ, don't read, else act normal */
)
{
/* Check to see if the requested block is in the block cache.  If so, return
 * a pointer to it.  If not, evict some other block and fetch it (unless
 * 'only_search' is 1).  All the blocks in the cache that are not in use
 * are linked together in a chain, with 'front' pointing to the least recently
 * used block and 'rear' to the most recently used block.  If 'only_search' is
 * 1, the block being requested will be overwritten in its entirety, so it is
 * only necessary to see if it is in the cache; if it is not, any free buffer
 * will do.  It is not necessary to actually read the block in from disk.
 * If 'only_search' is PREFETCH, the block need not be read from the disk,
 * and the device is not to be marked on the block, so callers can tell if
 * the block returned is valid.
 * In addition to the LRU chain, there is also a hash chain to link together
 * blocks whose block numbers end with the same bit strings, for fast lookup.
 */

  int b;
  static struct buf *bp, *prev_ptr;
  u64_t yieldid = VM_BLOCKID_NONE, getid = make64(dev, block);

  assert(buf_hash);
  assert(buf);
  assert(nr_bufs > 0);

  ASSERT(fs_block_size > 0);

  /* Search the hash chain for (dev, block). Do_read() can use 
   * get_block(NO_DEV ...) to get an unnamed block to fill with zeros when
   * someone wants to read from a hole in a file, in which case this search
   * is skipped
   */
  if (dev != NO_DEV) {
	b = BUFHASH(block);
	bp = buf_hash[b];
	while (bp != NULL) {
		if (bp->b_blocknr == block && bp->b_dev == dev) {
			/* Block needed has been found. */
			if (bp->b_count == 0) rm_lru(bp);
			bp->b_count++;	/* record that block is in use */
			ASSERT(bp->b_bytes == fs_block_size);
			ASSERT(bp->b_dev == dev);
			ASSERT(bp->b_dev != NO_DEV);
			ASSERT(bp->bp);
			return(bp);
		} else {
			/* This block is not the one sought. */
			bp = bp->b_hash; /* move to next block on hash chain */
		}
	}
  }

  /* Desired block is not on available chain.  Take oldest block ('front'). */
  if ((bp = front) == NULL) panic("all buffers in use: %d", nr_bufs);

  if(bp->b_bytes < fs_block_size) {
	ASSERT(!bp->bp);
	ASSERT(bp->b_bytes == 0);
	if(!(bp->bp = alloc_contig( (size_t) fs_block_size, 0, NULL))) {
		printf("MFS: couldn't allocate a new block.\n");
		for(bp = front;
			bp && bp->b_bytes < fs_block_size; bp = bp->b_next)
			;
		if(!bp) {
			panic("no buffer available");
		}
	} else {
  		bp->b_bytes = fs_block_size;
	}
  }

  ASSERT(bp);
  ASSERT(bp->bp);
  ASSERT(bp->b_bytes == fs_block_size);
  ASSERT(bp->b_count == 0);

  rm_lru(bp);

  /* Remove the block that was just taken from its hash chain. */
  b = BUFHASH(bp->b_blocknr);
  prev_ptr = buf_hash[b];
  if (prev_ptr == bp) {
	buf_hash[b] = bp->b_hash;
  } else {
	/* The block just taken is not on the front of its hash chain. */
	while (prev_ptr->b_hash != NULL)
		if (prev_ptr->b_hash == bp) {
			prev_ptr->b_hash = bp->b_hash;	/* found it */
			break;
		} else {
			prev_ptr = prev_ptr->b_hash;	/* keep looking */
		}
  }

  /* If the block taken is dirty, make it clean by writing it to the disk.
   * Avoid hysteresis by flushing all other dirty blocks for the same device.
   */
  if (bp->b_dev != NO_DEV) {
	if (ISDIRTY(bp)) flushall(bp->b_dev);

	/* Are we throwing out a block that contained something?
	 * Give it to VM for the second-layer cache.
	 */
	yieldid = make64(bp->b_dev, bp->b_blocknr);
	assert(bp->b_bytes == fs_block_size);
	BP_CLEARDEV(bp);
  }

  /* Fill in block's parameters and add it to the hash chain where it goes. */
  if(dev == NO_DEV) BP_CLEARDEV(bp);
  else BP_SETDEV(bp, dev);
  bp->b_blocknr = block;	/* fill in block number */
  bp->b_count++;		/* record that block is being used */
  b = BUFHASH(bp->b_blocknr);
  bp->b_hash = buf_hash[b];

  buf_hash[b] = bp;		/* add to hash list */

  if(dev == NO_DEV) {
	if(vmcache && cmp64(yieldid, VM_BLOCKID_NONE) != 0) {
		vm_yield_block_get_block(yieldid, VM_BLOCKID_NONE,
			bp->bp, fs_block_size);
	}
	return(bp);	/* If the caller wanted a NO_DEV block, work is done. */
  }

  /* Go get the requested block unless searching or prefetching. */
  if(only_search == PREFETCH || only_search == NORMAL) {
	/* Block is not found in our cache, but we do want it
	 * if it's in the vm cache.
	 */
	if(vmcache) {
		/* If we can satisfy the PREFETCH or NORMAL request 
		 * from the vm cache, work is done.
		 */
		if(vm_yield_block_get_block(yieldid, getid,
			bp->bp, fs_block_size) == OK) {
			return bp;
		}
	}
  }

  if(only_search == PREFETCH) {
	/* PREFETCH: don't do i/o. */
	BP_CLEARDEV(bp);
  } else if (only_search == NORMAL) {
	read_block(bp);
  } else if(only_search == NO_READ) {
	/* we want this block, but its contents
	 * will be overwritten. VM has to forget
	 * about it.
	 */
	if(vmcache) {
		vm_forgetblock(getid);
	}
  } else
	panic("unexpected only_search value: %d", only_search);

  assert(bp->bp);

  return(bp);			/* return the newly acquired block */
}
Ejemplo n.º 14
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;
}
Ejemplo n.º 15
0
/*===========================================================================*
 *				driver_open				     *
 *===========================================================================*/
static int driver_open(int which)
{
    /* Perform an open or close operation on the driver. This is
     * unfinished code: we should never be doing a blocking sendrec() to
     * the driver.
     */
    message msg;
    cp_grant_id_t gid;
    struct partition part;
    sector_t sectors;
    int r;

    memset(&msg, 0, sizeof(msg));
    msg.m_type = BDEV_OPEN;
    msg.BDEV_MINOR = driver[which].minor;
    msg.BDEV_ACCESS = R_BIT | W_BIT;
    msg.BDEV_ID = 0;
    r = sendrec(driver[which].endpt, &msg);

    if (r != OK) {
        /* Should we restart the driver now? */
        printf("Filter: driver_open: sendrec returned %d\n", r);

        return RET_REDO;
    }

    if(msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
        printf("Filter: driver_open: sendrec returned %d, %d\n",
               msg.m_type, msg.BDEV_STATUS);

        return RET_REDO;
    }

    /* Take the opportunity to retrieve the hard disk size. */
    gid = cpf_grant_direct(driver[which].endpt,
                           (vir_bytes) &part, sizeof(part), CPF_WRITE);
    if(!GRANT_VALID(gid))
        panic("invalid grant: %d", gid);

    memset(&msg, 0, sizeof(msg));
    msg.m_type = BDEV_IOCTL;
    msg.BDEV_MINOR = driver[which].minor;
    msg.BDEV_REQUEST = DIOCGETP;
    msg.BDEV_GRANT = gid;
    msg.BDEV_ID = 0;

    r = sendrec(driver[which].endpt, &msg);

    cpf_revoke(gid);

    if (r != OK || msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
        /* Not sure what to do here, either. */
        printf("Filter: ioctl(DIOCGETP) returned (%d, %d)\n",
               r, msg.m_type);

        return RET_REDO;
    }

    if(!size_known) {
        disk_size = part.size;
        size_known = 1;
        sectors = div64u(disk_size, SECTOR_SIZE);
        if(cmp64(mul64u(sectors, SECTOR_SIZE), disk_size)) {
            printf("Filter: partition too large\n");

            return RET_REDO;
        }
#if DEBUG
        printf("Filter: partition size: 0x%s / %lu sectors\n",
               print64(disk_size), sectors);
#endif
    } else {
        if(cmp64(disk_size, part.size)) {
            printf("Filter: partition size mismatch (%s != %s)\n",
                   print64(part.size), print64(disk_size));

            return RET_REDO;
        }
    }

    return OK;
}
Ejemplo n.º 16
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);
}