Пример #1
0
static int
fsdirstat(char *path, int dev, Dir *d)
{
	int fd;
	struct stat st;
	
	if(stat(path, &st) < 0 && lstat(path, &st) < 0)
		return -1;

	d->name = lastelem(path);
	d->uid = uidtoname(st.st_uid);
	d->gid = gidtoname(st.st_gid);
	d->muid = "";
	d->qid = fsqid(&st);
	d->mode = (d->qid.type<<24) | (st.st_mode&0777);
	d->atime = st.st_atime;
	d->mtime = st.st_mtime;
	d->length = st.st_size;
	if(S_ISBLK(st.st_mode) && (fd = open(path, O_RDONLY)) >= 0){
		d->length = disksize(fd, &st);
		close(fd);
	}
	
	// devmnt leaves 1-9 unused so that we can steal them.
	// it is easier for all involved if #Z shows M as the file type instead of Z.
	// dev is c->dev, either 1 (#Z) or 2 (#Zplan9).
	d->type = 'M';
	d->dev = dev;
	return 0;
}
Пример #2
0
int
seek(char *disk, int oflag)
{
	char	*buf;
	int	fd;
	off64_t	size;
	off64_t	begin, end;
	int	usecs;
	int	error;
	int	tot_msec = 0, tot_io = 0;
	int	stride;

	if ((fd = open(disk, oflag)) == -1) {
		perror(disk);
		return (-1);
	}
#ifdef	linux
	flushdisk(fd);
#endif
	size = disksize(disk);
	buf = valloc(IOSIZE);
	bzero(buf, IOSIZE);

	/*
	 * We flip back and forth, in strides of 1MB (typically).
	 * If we have a 100MB fd, that means we do
	 * 1, 99, 2, 98, etc.
	 *
	 * We want around SEEK POINTS data points 
	 * but the stride has to be at least 512 and a 512 multiple.
	 */
	stride = size / SEEKPOINTS;
	if (stride < 512) stride = 512;
	stride += 511;
	stride >>= 9;
	stride <<= 9;

	debug((stdout, "stride=%d size=%dM points=%d\n",
	    stride, (int)(size >> 20), (int)(size/stride)));

	end = size;
	begin = 0;
	seekto(fd, begin);
	IO(fd, buf, IOSIZE);
	while (end >= begin + stride*2) {
		end -= stride;
		start(0);
		seekto(fd, end);
		IO(fd, buf, IOSIZE);
		usecs = stop(0, 0);
		if (usecs > TOOSMALL && usecs < TOOBIG) {
			tot_io++; tot_msec += usecs/1000;
			fprintf(stderr, "%.01f %.02f\n",
			    (end - begin - stride) / 1000000., usecs/1000.);
		}

		begin += stride;
		start(0);
		seekto(fd, begin);
		IO(fd, buf, IOSIZE);
		usecs = stop(0, 0);
		if (usecs > TOOSMALL && usecs < TOOBIG) {
			tot_io++; tot_msec += usecs/1000;
			fprintf(stderr, "%.01f %.02f\n",
			    (end + stride - begin) / 1000000., usecs/1000.);
		}
	}
	/*
	 * This is wrong, it should take the 1/3 stroke seek average.
	avg_msec = (double)tot_msec/tot_io;
	fprintf(stderr, "Average time == %.04f\n", avg_msec);
	 */
	return (0);
}
Пример #3
0
int
zone(char *disk, int oflag, int bsize)
{
	char	*buf;
	int	usecs;
	int	error;
	int	n;
	int	fd;
	uint64	off;
	int	stride;

	if ((fd = open(disk, oflag)) == -1) {
		perror(disk);
		exit(1);
	}
	buf = valloc(bsize);
	if (!buf) {
		perror("valloc");
		exit(1);
	}
	bzero(buf, bsize);
#ifdef	linux
	flushdisk(fd);
#endif

	/*
	 * We want ZONEPOINTS data points 
	 * but the stride has to be at least 512 and a 512 multiple.
	 * Weird code below for precision.
	 */
	off = disksize(disk);
	off /= ZONEPOINTS;
	stride = off;
	if (stride < 512) stride = 512;
	stride += 511;
	stride >>= 9;
	stride <<= 9;

	/*
	 * Very small disks such as ZIP drives get a 256K blocksize.
	 * As measured on my SCSI ZIP, there seems to be no
	 * difference between 256K and 1MB for sequential reads.
	 * XXX - there is a rotational delay difference but that's tough.
	 */
	if (bsize > stride) bsize = 256<<10;
	if (bsize > stride) stride = bsize;

	off *= ZONEPOINTS;
	debug((stdout, "stride=%d bs=%d size=%dM points=%d\n",
	    stride, bsize, (int)(off >> 20), (int)(off/stride)));

	/*
	 * Read buf's worth of data every stride and time it.
	 * Don't include the rotational delay.
	 * This first I/O outside the loop is to catch read/write permissions.
	 */

#define	IO(a,b,c)	(oflag == 0 ? (n = read(a,b,c)) : (n = write(a,b,c)))

	error = IO(fd, buf, 512);
	if (error == -1) {
		perror(disk);
		exit(1);
	}
	off = 512;
	for ( ;; ) {
		if (IO(fd, buf, 1024) != 1024) {
			exit(0);
		}
		off += 1024;
		start(0);
		if (IO(fd, buf, bsize) != bsize) {
			exit(0);
		}
		usecs = stop(0, 0);
		off += bsize;
		fprintf(stderr, "%.01f %.2f\n",
		    off/1000000.0, (double)bsize/usecs);
		off += stride;
		if (seekto(fd, off)) {
			exit(0);
		}
	}
	exit(0);
}
Пример #4
0
int main(int argc, char* argv[])
{
	char* filename = argv[1];
	off_t disk_size_in_bytes = disksize(filename);
	int i;
	double start_time, end_time;
	unsigned long sector_size = sectorsize(filename);
	long disk_size_in_sectors = disk_size_in_bytes / sector_size;
	int transfer_size_in_sectors = 1;	// Probably doesn't make any sense to be anything other than 1.  Except maybe 64 or 128.
	long transfer_size_in_bytes = transfer_size_in_sectors * sector_size;
	// TODO: initial random I/O test to determine number of repetitions based on random I/O rate. Or just stop after a certain elapsed time!
	int repetitions = 1000;

	struct timeval seed;

	// Scaling factor for the random numbers, to ensure that the sector chosen actually lies within the range of sectors on the disk.
	double block_scaling_factor = (double)MAX_RAND_INT / (double)disk_size_in_sectors;
	//fprintf(stderr, "block scaling factor = %f\n", block_scaling_factor);

	// Seed the RNG from the current time to avoid repetitive I/O patterns (and possible cache effects) across multiple runs:
	gettimeofday(&seed, NULL);
	srandom(seed.tv_usec);

//	char* buf = malloc(transfer_size_in_bytes);
	void* buf;
	int memalign_status = posix_memalign(&buf, 512, transfer_size_in_bytes);
	if (memalign_status != 0) {
		perror("Error allocating aligned buffer memory.");
		exit(EXIT_FAILURE);
	}


	int fd = diskbench_open(filename);

	off_t sector = 0;
	double elapsed_time_in_seconds = 0;
	
	fprintf(stderr, "\nAbout to perform random access test on %s\n\n", filename);
	fprintf(stderr, "Disk size: %lli GiB\n", disk_size_in_bytes / 1024 / 1024 / 1024);
	fprintf(stderr, "           %lli MiB\n", disk_size_in_bytes / 1024 / 1024);
	fprintf(stderr, "           %lli kiB\n", disk_size_in_bytes / 1024);
	fprintf(stderr, "           %jd bytes\n", (intmax_t)disk_size_in_bytes);
	fprintf(stderr, "           %li %lu-byte sectors\n\n", disk_size_in_sectors, sector_size);

	// Heading for output:
	fprintf(stderr, "sector\tbyte\tfraction\ttime(ms)\trate(MiB/s)\n");
	
	for (i = 0; i < repetitions; i++)
	{
		sector = random() / block_scaling_factor;
		
		// Sector being sought:
		printf("%lli", sector);

		// Byte being sought:
		printf("\t%lli", sector * (long long int)sector_size);

		// Location as a fraction of the entire drive space:
		printf("\t%f", (double)sector / (double)disk_size_in_sectors);

		
		// Check the system time before doing the operation:
		start_time = seconds_since_epoch();
		
		// Note: fseek() location is in bytes.
		lseek(fd, sector * (long)sector_size, SEEK_SET);
		
		// Does it make any difference if we only read one byte, rather than the whole block?
		read(fd, buf, transfer_size_in_bytes);

		// Record the time after finishing to determine elapsed time.
		end_time = seconds_since_epoch();
	
		elapsed_time_in_seconds = end_time - start_time;
		
//		printf("; elapsed = %i s", time1.tv_sec - time0.tv_sec);
		printf("\t");
		// Print elapsed time in milliseconds:
		printf("%f", elapsed_time_in_seconds * 1000.0);
	//	printf("%f", 1000 * ((double)(time1.tv_sec - time0.tv_sec) + (double)(time1.tv_nsec - time0.tv_nsec) / 1000000000));

		// Print throughput in MiB/s:
		printf("\t");
		printf("%f", (double)transfer_size_in_bytes / elapsed_time_in_seconds / 1024.0 / 1024.0);
		printf("\n");
		//printf("; time=%i, %i\n", (time1->tv_sec) - (time0->tv_sec), (time1->tv_nsec) - (time0->tv_nsec));
	}
	
	free(buf);
	close(fd);
	return 0;
}