Example #1
0
u32_t fs_bufs_heuristic(int minbufs, u32_t btotal, u32_t bfree, 
         int blocksize, dev_t majordev)
{
  struct vm_stats_info vsi;
  int bufs;
  u32_t kbytes_used_fs, kbytes_total_fs, kbcache, kb_fsmax;
  u32_t kbytes_remain_mem, bused;

  bused = btotal-bfree;

  /* but we simply need minbufs no matter what, and we don't
   * want more than that if we're a memory device
   */
  if(majordev == MEMORY_MAJOR) {
	return minbufs;
  }

  /* set a reasonable cache size; cache at most a certain
   * portion of the used FS, and at most a certain %age of remaining
   * memory
   */
  if((vm_info_stats(&vsi) != OK)) {
	bufs = 1024;
	printf("fslib: heuristic info fail: default to %d bufs\n", bufs);
	return bufs;
  }

  kbytes_remain_mem = div64u(mul64u(vsi.vsi_free, vsi.vsi_pagesize), 1024);

  /* check fs usage. */
  kbytes_used_fs = div64u(mul64u(bused, blocksize), 1024);
  kbytes_total_fs = div64u(mul64u(btotal, blocksize), 1024);

  /* heuristic for a desired cache size based on FS usage;
   * but never bigger than half of the total filesystem
   */
  kb_fsmax = sqrt_approx(kbytes_used_fs)*40;
  kb_fsmax = MIN(kb_fsmax, kbytes_total_fs/2);

  /* heuristic for a maximum usage - 10% of remaining memory */
  kbcache = MIN(kbytes_remain_mem/10, kb_fsmax);
  bufs = kbcache * 1024 / blocksize;

  /* but we simply need MINBUFS no matter what */
  if(bufs < minbufs)
	bufs = minbufs;

  return bufs;
}
Example #2
0
File: cache.c Project: wieck/minix
u32_t fs_bufs_heuristic(int minbufs, u32_t btotal, u32_t bfree, 
         int blocksize, dev_t majordev)
{
  struct vm_stats_info vsi;
  int bufs;
  u32_t kbytes_used_fs, kbytes_total_fs, kbcache, kb_fsmax;
  u32_t kbytes_remain_mem, bused;

  bused = btotal-bfree;

  /* set a reasonable cache size; cache at most a certain
   * portion of the used FS, and at most a certain %age of remaining
   * memory
   */
  if(vm_info_stats(&vsi) != OK) {
	bufs = 1024;
	if(!quiet)
	  printf("fslib: heuristic info fail: default to %d bufs\n", bufs);
	return bufs;
  }

  /* remaining free memory is unused memory plus memory in used for cache,
   * as the cache can be evicted
   */
  kbytes_remain_mem = (u64_t)(vsi.vsi_free + vsi.vsi_cached) *
	vsi.vsi_pagesize / 1024;

  /* check fs usage. */
  kbytes_used_fs = div64u(mul64u(bused, blocksize), 1024);
  kbytes_total_fs = div64u(mul64u(btotal, blocksize), 1024);

  /* heuristic for a desired cache size based on FS usage;
   * but never bigger than half of the total filesystem
   */
  kb_fsmax = sqrt_approx(kbytes_used_fs)*40;
  kb_fsmax = MIN(kb_fsmax, kbytes_total_fs/2);

  /* heuristic for a maximum usage - 10% of remaining memory */
  kbcache = MIN(kbytes_remain_mem/10, kb_fsmax);
  bufs = kbcache * 1024 / blocksize;

  /* but we simply need MINBUFS no matter what */
  if(bufs < minbufs)
	bufs = minbufs;

  return bufs;
}
Example #3
0
/* Write a block. */
void
put_block(block_t n, void *buf)
{

  (void) read_and_set(n);

  mkfs_seek(mul64u(n, block_size), SEEK_SET);
  mkfs_write(buf, block_size);
}
Example #4
0
u32_t
micros_to_ticks(u32_t micros)
{
        u32_t ticks;

        ticks = div64u(mul64u(micros, sys_hz()), 1000000);
        if(ticks < 1) ticks = 1;

        return ticks;
}
Example #5
0
File: mkfs.c Project: kl07/minix
/* Write a block. */
void
put_block(block_t n, void *buf)
{

  (void) read_and_set(n);

  if (lseek64(fd, mul64u(n, block_size), SEEK_SET, NULL) == (off_t) -1)
	pexit("put_block couldn't seek");
  if (write(fd, buf, block_size)!= block_size)
	pexit("put_block couldn't write block #%u", (unsigned)n);
}
Example #6
0
File: mkfs.c Project: 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;
}
Example #7
0
/* Read a block. */
void
get_block(block_t n, void *buf)
{
  ssize_t k;

  /* First access returns a zero block */
  if (read_and_set(n) == 0) {
	memcpy(buf, zero, block_size);
	return;
  }
  mkfs_seek(mul64u(n, block_size), SEEK_SET);
  k = read(fd, buf, block_size);
  if (k != block_size)
	pexit("get_block couldn't read block #%u", (unsigned)n);
}
Example #8
0
File: mkfs.c Project: kl07/minix
/* Read a block. */
void
get_block(block_t n, void *buf)
{
  ssize_t k;

  /* First access returns a zero block */
  if (read_and_set(n) == 0) {
	memcpy(buf, zero, block_size);
	return;
  }
  if (lseek64(fd, mul64u(n, block_size), SEEK_SET, NULL) == (off_t)(-1))
	pexit("get_block couldn't seek");
  k = read(fd, buf, block_size);
  if (k != block_size)
	pexit("get_block couldn't read block #%u", (unsigned)n);
}
Example #9
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;
	}
}
Example #10
0
/*===========================================================================*
 *				rw_block				     *
 *===========================================================================*/
static void rw_block(
  register struct buf *bp,	/* buffer pointer */
  int rw_flag 			/* READING or WRITING */
)
{
/* Read or write a disk block. This is the only routine in which actual disk
 * I/O is invoked. If an error occurs, a message is printed here, but the error
 * is not reported to the caller.  If the error occurred while purging a block
 * from the cache, it is not clear what the caller could do about it anyway.
 */
  int r, op_failed = 0;
  u64_t pos;
  dev_t dev;

  if ( (dev = bp->b_dev) != NO_DEV) {
	pos = mul64u(bp->b_blocknr, fs_block_size);
	if (rw_flag == READING)
		r = bdev_read(dev, pos, bp->b_data, fs_block_size,
			BDEV_NOFLAGS);
	else
		r = bdev_write(dev, pos, bp->b_data, fs_block_size,
			BDEV_NOFLAGS);
	if (r < 0) {
		printf("Ext2(%d) I/O error on device %d/%d, block %u\n",
			SELF_E, major(dev), minor(dev), bp->b_blocknr);
		op_failed = 1;
	} else if (r != (ssize_t) fs_block_size) {
		r = END_OF_FILE;
		op_failed = 1;
	}

	if (op_failed) {
		bp->b_dev = NO_DEV;     /* invalidate block */

		/* Report read errors to interested parties. */
		if (rw_flag == READING) rdwt_err = r;

	}
  }

  bp->b_dirt = CLEAN;
}
Example #11
0
/*===========================================================================*
 *				action_pre_misdir			     *
 *===========================================================================*/
static void action_pre_misdir(struct fbd_rule *rule, iovec_t *UNUSED(iov),
	unsigned *UNUSED(count), size_t *UNUSED(size), u64_t *pos)
{
	/* Randomize the request position to fall within the range (and have
	 * the alignment) given by the rule.
	 */
	u32_t range, choice;

	/* Unfortunately, we cannot interpret 0 as end as "up to end of disk"
	 * here, because we have no idea about the actual disk size, and the
	 * resulting address must of course be valid..
	 */
	range = div64u(add64u(sub64(rule->params.misdir.end,
		rule->params.misdir.start), 1), rule->params.misdir.align);

	if (range > 0)
		choice = get_rand(range - 1);
	else
		choice = 0;

	*pos = add64(rule->params.misdir.start,
		mul64u(choice, rule->params.misdir.align));
}
Example #12
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;
}
Example #13
0
PUBLIC u64_t ms_2_cpu_time(unsigned ms)
{
	return mul64u(tsc_per_ms[cpuid], ms);
}
Example #14
0
/*===========================================================================*
 *				rw_scattered				     *
 *===========================================================================*/
PUBLIC void rw_scattered(
  dev_t dev,			/* major-minor device number */
  struct buf **bufq,		/* pointer to array of buffers */
  int bufqsize,		/* number of buffers */
  int rw_flag 			/* READING or WRITING */
)
{
/* Read or write scattered data from a device. */

  register struct buf *bp;
  int gap;
  register int i;
  register iovec_t *iop;
  static iovec_t *iovec = NULL;
  int j, r;

  STATICINIT(iovec, NR_IOREQS);

  /* (Shell) sort buffers on b_blocknr. */
  gap = 1;
  do
	gap = 3 * gap + 1;
  while (gap <= bufqsize);
  while (gap != 1) {
	gap /= 3;
	for (j = gap; j < bufqsize; j++) {
		for (i = j - gap;
		     i >= 0 && bufq[i]->b_blocknr > bufq[i + gap]->b_blocknr;
		     i -= gap) {
			bp = bufq[i];
			bufq[i] = bufq[i + gap];
			bufq[i + gap] = bp;
		}
	}
  }

  /* Set up I/O vector and do I/O.  The result of dev_io is OK if everything
   * went fine, otherwise the error code for the first failed transfer.
   */
  while (bufqsize > 0) {
	for (j = 0, iop = iovec; j < NR_IOREQS && j < bufqsize; j++, iop++) {
		bp = bufq[j];
		if (bp->b_blocknr != (block_t) bufq[0]->b_blocknr + j) break;
		iop->iov_addr = (vir_bytes) bp->b_data;
		iop->iov_size = (vir_bytes) fs_block_size;
	}
	r = block_dev_io(rw_flag == WRITING ? MFS_DEV_SCATTER : MFS_DEV_GATHER,
		dev, SELF_E, iovec,
		mul64u(bufq[0]->b_blocknr, fs_block_size), j);

	/* Harvest the results.  Dev_io reports the first error it may have
	 * encountered, but we only care if it's the first block that failed.
	 */
	for (i = 0, iop = iovec; i < j; i++, iop++) {
		bp = bufq[i];
		if (iop->iov_size != 0) {
			/* Transfer failed. An error? Do we care? */
			if (r != OK && i == 0) {
				printf(
				"fs: I/O error on device %d/%d, block %lu\n",
					major(dev), minor(dev), bp->b_blocknr);
				bp->b_dev = NO_DEV;	/* invalidate block */
				vm_forgetblocks();
			}
			break;
		}
		if (rw_flag == READING) {
			bp->b_dev = dev;	/* validate block */
			put_block(bp, PARTIAL_DATA_BLOCK);
		} else {
			bp->b_dirt = CLEAN;
		}
	}
	bufq += i;
	bufqsize -= i;
	if (rw_flag == READING) {
		/* Don't bother reading more than the device is willing to
		 * give at this time.  Don't forget to release those extras.
		 */
		while (bufqsize > 0) {
			put_block(*bufq++, PARTIAL_DATA_BLOCK);
			bufqsize--;
		}
	}
	if (rw_flag == WRITING && i == 0) {
		/* We're not making progress, this means we might keep
		 * looping. Buffers remain dirty if un-written. Buffers are
		 * lost if invalidate()d or LRU-removed while dirty. This
		 * is better than keeping unwritable blocks around forever..
		 */
		break;
	}
  }
}
Example #15
0
/*================================================================
 *                    mkfs  -  make filesystem
 *===============================================================*/
int
main(int argc, char *argv[])
{
  int nread, mode, usrid, grpid, ch, extra_space_percent, Tflag = 0;
  block_t blocks, maxblocks, bblocks;
  ino_t inodes, root_inum;
  char *token[MAX_TOKENS], line[LINE_LEN], *sfx;
  struct fs_size fssize;
  int insertmode = 0;

  progname = argv[0];

  /* Process switches. */
  blocks = 0;
  inodes = 0;
  bblocks = 0;
#ifndef MFS_STATIC_BLOCK_SIZE
  block_size = 0;
#endif
  zone_shift = 0;
  extra_space_percent = 0;
  while ((ch = getopt(argc, argv, "B:b:di:ltvx:z:I:T:")) != EOF)
	switch (ch) {
#ifndef MFS_STATIC_BLOCK_SIZE
	    case 'B':
		block_size = strtoul(optarg, &sfx, 0);
		switch(*sfx) {
		case 'b': case 'B': /* bytes; NetBSD-compatible */
		case '\0':	break;
		case 'K':
		case 'k':	block_size*=1024; break;
		case 's': 	block_size*=SECTOR_SIZE; break;
		default:	usage();
		}
		break;
#else
	    case 'B':
		if (block_size != strtoul(optarg, (char **) NULL, 0))
			errx(4, "block size must be exactly %d bytes",
			    MFS_STATIC_BLOCK_SIZE);
		break;
		(void)sfx;	/* shut up warnings about unused variable...*/
#endif
	    case 'I':
		fs_offset_bytes = strtoul(optarg, (char **) NULL, 0);
		insertmode = 1;
		break;
	    case 'b':
		blocks = bblocks = strtoul(optarg, (char **) NULL, 0);
		break;
	    case 'T':
		Tflag = 1;
		current_time = strtoul(optarg, (char **) NULL, 0);
		break;
	    case 'd':
		dflag = 1;
		break;
	    case 'i':
		inodes = strtoul(optarg, (char **) NULL, 0);
		break;
	    case 'l':	print = 1;	break;
	    case 't':	donttest = 1;	break;
	    case 'v':	++verbose;	break;
	    case 'x':	extra_space_percent = atoi(optarg); break;
	    case 'z':	zone_shift = atoi(optarg);	break;
	    default:	usage();
	}

  if (argc == optind) usage();

  /* Get the current time, set it to the mod time of the binary of
   * mkfs itself when the -d flag is used. The 'current' time is put into
   * the i_mtimes of all the files.  This -d feature is useful when
   * producing a set of file systems, and one wants all the times to be
   * identical. First you set the time of the mkfs binary to what you
   * want, then go.
   */
  if(Tflag) {
    if(dflag)
	errx(1, "-T and -d both specify a time and so are mutually exclusive");
  } else if(dflag) {
	struct stat statbuf;
	if (stat(progname, &statbuf)) {
		err(1, "stat of itself");
	}
	current_time = statbuf.st_mtime;
  } else {
	  current_time = time((time_t *) 0);	/* time mkfs is being run */
  }

  /* Percentage of extra size must be nonnegative.
   * It can legitimately be bigger than 100 but has to make some sort of sense.
   */
  if(extra_space_percent < 0 || extra_space_percent > 2000) usage();

#ifdef DEFAULT_BLOCK_SIZE
  if(!block_size) block_size = DEFAULT_BLOCK_SIZE;
#endif
  if (block_size % SECTOR_SIZE)
	errx(4, "block size must be multiple of sector (%d bytes)", SECTOR_SIZE);
#ifdef MIN_BLOCK_SIZE
  if (block_size < MIN_BLOCK_SIZE)
	errx(4, "block size must be at least %d bytes", MIN_BLOCK_SIZE);
#endif
#ifdef MAX_BLOCK_SIZE
  if (block_size > MAX_BLOCK_SIZE)
	errx(4, "block size must be at most %d bytes", MAX_BLOCK_SIZE);
#endif
  if(block_size%INODE_SIZE)
	errx(4, "block size must be a multiple of inode size (%d bytes)", INODE_SIZE);

  if(zone_shift < 0 || zone_shift > 14)
	errx(4, "zone_shift must be a small non-negative integer");
  zone_per_block = 1 << zone_shift;	/* nr of blocks per zone */

  inodes_per_block = INODES_PER_BLOCK(block_size);
  indir_per_block = INDIRECTS(block_size);
  indir_per_zone = INDIRECTS(block_size) << zone_shift;
  /* number of file zones we can address directly and with a single indirect*/
  nr_indirzones = NR_DZONES + indir_per_zone;
  zone_size = block_size << zone_shift;
  /* Checks for an overflow: only with very big block size */
  if (zone_size <= 0)
	errx(4, "Zones are too big for this program; smaller -B or -z, please!");

  /* now that the block size is known, do buffer allocations where
   * possible.
   */
  zero = alloc_block();

  fs_offset_blocks = roundup(fs_offset_bytes, block_size) / block_size;

  /* Determine the size of the device if not specified as -b or proto. */
  maxblocks = sizeup(argv[optind]);
  if (bblocks != 0 && bblocks + fs_offset_blocks > maxblocks && !insertmode) {
	errx(4, "Given size -b %d exeeds device capacity(%d)\n", bblocks, maxblocks);
  }

  if (argc - optind == 1 && bblocks == 0) {
  	blocks = maxblocks;
  	/* blocks == 0 is checked later, but leads to a funny way of
  	 * reporting a 0-sized device (displays usage).
  	 */
  	if(blocks < 1) {
  		errx(1, "zero size device.");
	}
  }

  /* The remaining args must be 'special proto', or just 'special' if the
   * no. of blocks has already been specified.
   */
  if (argc - optind != 2 && (argc - optind != 1 || blocks == 0)) usage();

  if (maxblocks && blocks > maxblocks && !insertmode) {
 	errx(1, "%s: number of blocks too large for device.", argv[optind]);
  }

  /* Check special. */
  check_mtab(argv[optind]);

  /* Check and start processing proto. */
  optarg = argv[++optind];
  if (optind < argc && (proto = fopen(optarg, "r")) != NULL) {
	/* Prototype file is readable. */
	lct = 1;
	get_line(line, token);	/* skip boot block info */

	/* Read the line with the block and inode counts. */
	get_line(line, token);
	if (bblocks == 0){
		blocks = strtol(token[0], (char **) NULL, 10);
	} else {
		if(bblocks < strtol(token[0], (char **) NULL, 10)) {
 			errx(1, "%s: number of blocks given as parameter(%d)"
				" is too small for given proto file(%d).", 
				argv[optind], bblocks, 
				strtol(token[0], (char **) NULL, 10));
		};
	}
	inodes = strtol(token[1], (char **) NULL, 10);

	/* Process mode line for root directory. */
	get_line(line, token);
	mode = mode_con(token[0]);
	usrid = atoi(token[1]);
	grpid = atoi(token[2]);

	if(blocks <= 0 && inodes <= 0){
		detect_fs_size(&fssize);
		blocks = fssize.blockcount;
		inodes = fssize.inocount;
		blocks += blocks*extra_space_percent/100;
		inodes += inodes*extra_space_percent/100;
/* XXX is it OK to write on stdout? Use warn() instead? Also consider using verbose */
		fprintf(stderr, "dynamically sized filesystem: %u blocks, %u inodes\n",
		    (unsigned int) blocks, (unsigned int) inodes);
	}
  } else {
	lct = 0;
	if (optind < argc) {
		/* Maybe the prototype file is just a size.  Check. */
		blocks = strtoul(optarg, (char **) NULL, 0);
		if (blocks == 0) errx(2, "Can't open prototype file");
	}

	/* Make simple file system of the given size, using defaults. */
	mode = 040777;
	usrid = BIN;
	grpid = BINGRP;
	simple = 1;
  }

  if (inodes == 0) {
	long long kb = ((unsigned long long)blocks*block_size) / 1024;

	inodes = kb / 2;
	if (kb >= 100000) inodes = kb / 4;
	if (kb >= 1000000) inodes = kb / 6;
	if (kb >= 10000000) inodes = kb / 8;
	if (kb >= 100000000) inodes = kb / 10;
	if (kb >= 1000000000) inodes = kb / 12;
/* XXX check overflow: with very large number of blocks, this results in insanely large number of inodes */
/* XXX check underflow (if/when ino_t is signed), else the message below will look strange */

	/* round up to fill inode block */
	inodes += inodes_per_block - 1;
	inodes = inodes / inodes_per_block * inodes_per_block;
  }

  if (blocks < 5) errx(1, "Block count too small");
  if (inodes < 1) errx(1, "Inode count too small");

  nrblocks = blocks;
  nrinodes = inodes;

  umap_array_elements = 1 + blocks/8;
  if(!(umap_array = malloc(umap_array_elements)))
	err(1, "can't allocate block bitmap (%u bytes).",
		(unsigned)umap_array_elements);

  /* Open special. */
  special(argv[--optind], insertmode);

  if (!donttest) {
	uint16_t *testb;
	ssize_t w;

	testb = alloc_block();

	/* Try writing the last block of partition or diskette. */
	mkfs_seek(mul64u(blocks - 1, block_size), SEEK_SET);
	testb[0] = 0x3245;
	testb[1] = 0x11FF;
	testb[block_size/2-1] = 0x1F2F;
	w=mkfs_write(testb, block_size);
	sync();			/* flush write, so if error next read fails */
	mkfs_seek(mul64u(blocks - 1, block_size), SEEK_SET);
	testb[0] = 0;
	testb[1] = 0;
	testb[block_size/2-1] = 0;
	nread = read(fd, testb, block_size);
	if (nread != block_size || testb[0] != 0x3245 || testb[1] != 0x11FF ||
	    testb[block_size/2-1] != 0x1F2F) {
		warn("nread = %d\n", nread);
		warnx("testb = 0x%x 0x%x 0x%x\n",
		    testb[0], testb[1], testb[block_size-1]);
		errx(1, "File system is too big for minor device (read)");
	}
	mkfs_seek(mul64u(blocks - 1, block_size), SEEK_SET);
	testb[0] = 0;
	testb[1] = 0;
	testb[block_size/2-1] = 0;
	mkfs_write(testb, block_size);
	mkfs_seek(0L, SEEK_SET);
	free(testb);
  }

  /* Make the file-system */

  put_block(BOOT_BLOCK, zero);		/* Write a null boot block. */
  put_block(BOOT_BLOCK+1, zero);	/* Write another null block. */

  super(nrblocks >> zone_shift, inodes);

  root_inum = alloc_inode(mode, usrid, grpid);
  rootdir(root_inum);
  if (simple == 0) eat_dir(root_inum);

  if (print) print_fs();
  else if (verbose > 1) {
	  if (zone_shift)
		fprintf(stderr, "%d inodes used.     %u zones (%u blocks) used.\n",
		    (int)next_inode-1, next_zone, next_zone*zone_per_block);
	  else
		fprintf(stderr, "%d inodes used.     %u zones used.\n",
		    (int)next_inode-1, next_zone);
  }

  if(insertmode) printf("%ld\n", written_fs_size);

  return(0);

  /* NOTREACHED */
}				/* end main */
Example #16
0
/*
 * Convert a POSIX timespec structure to a VirtualBox timestamp.
 */
static u64_t
set_time(struct timespec *tsp)
{

	return add64u(mul64u(tsp->tv_sec, 1000000000), tsp->tv_nsec);
}
Example #17
0
/*
 * Convert a POSIX timespec structure to a VirtualBox timestamp.
 */
static u64_t
set_time(struct timespec *tsp)
{

    return mul64u(tsp->tv_sec, 1000000000) + tsp->tv_nsec;
}
Example #18
0
/*===========================================================================*
 *				rw_scattered				     *
 *===========================================================================*/
void rw_scattered(
  dev_t dev,			/* major-minor device number */
  struct buf **bufq,		/* pointer to array of buffers */
  int bufqsize,		/* number of buffers */
  int rw_flag 			/* READING or WRITING */
)
{
/* Read or write scattered data from a device. */

  register struct buf *bp;
  int gap;
  register int i;
  register iovec_t *iop;
  static iovec_t *iovec = NULL;
  u64_t pos;
  int j, r;

  STATICINIT(iovec, NR_IOREQS);
  assert(bufq != NULL);

  /* (Shell) sort buffers on b_blocknr. */
  gap = 1;
  do
	gap = 3 * gap + 1;
  while (gap <= bufqsize);
  while (gap != 1) {
	gap /= 3;
	for (j = gap; j < bufqsize; j++) {
		for (i = j - gap;
		     i >= 0 && bufq[i]->b_blocknr > bufq[i + gap]->b_blocknr;
		     i -= gap) {
			bp = bufq[i];
			bufq[i] = bufq[i + gap];
			bufq[i + gap] = bp;
		}
	}
  }

  /* Set up I/O vector and do I/O.  The result of dev_io is OK if everything
   * went fine, otherwise the error code for the first failed transfer.
   */
  while (bufqsize > 0) {
	for (j = 0, iop = iovec; j < NR_IOREQS && j < bufqsize; j++, iop++) {
		bp = bufq[j];
		if (bp->b_blocknr != (block_t) bufq[0]->b_blocknr + j) break;
		iop->iov_addr = (vir_bytes) bp->b_data;
		iop->iov_size = (vir_bytes) fs_block_size;
	}
	pos = mul64u(bufq[0]->b_blocknr, fs_block_size);
	if (rw_flag == READING)
		r = bdev_gather(dev, pos, iovec, j, BDEV_NOFLAGS);
	else
		r = bdev_scatter(dev, pos, iovec, j, BDEV_NOFLAGS);

	/* Harvest the results.  The driver may have returned an error, or it
	 * may have done less than what we asked for.
	 */
	if (r < 0) {
		printf("ext2: I/O error %d on device %d/%d, block %u\n",
			r, major(dev), minor(dev), bufq[0]->b_blocknr);
	}
	for (i = 0; i < j; i++) {
		bp = bufq[i];
		if (r < (ssize_t) fs_block_size) {
			/* Transfer failed. */
			if (i == 0) {
				bp->b_dev = NO_DEV;	/* invalidate block */
				vm_forgetblocks();
			}
			break;
		}
		if (rw_flag == READING) {
			bp->b_dev = dev;	/* validate block */
			put_block(bp, PARTIAL_DATA_BLOCK);
		} else {
			bp->b_dirt = CLEAN;
		}
		r -= fs_block_size;
	}
	bufq += i;
	bufqsize -= i;
	if (rw_flag == READING) {
		/* Don't bother reading more than the device is willing to
		 * give at this time.  Don't forget to release those extras.
		 */
		while (bufqsize > 0) {
			put_block(*bufq++, PARTIAL_DATA_BLOCK);
			bufqsize--;
		}
	}
	if (rw_flag == WRITING && i == 0) {
		/* We're not making progress, this means we might keep
		 * looping. Buffers remain dirty if un-written. Buffers are
		 * lost if invalidate()d or LRU-removed while dirty. This
		 * is better than keeping unwritable blocks around forever..
		 */
		break;
	}
  }
}