Ejemplo n.º 1
0
/*
 * Reproducer for something like this
 *
 * [data][prealloc][data]
 *
 * and then in the [prealloc] section we have
 *
 * [ pre ][pre][     pre     ]
 * [d][pp][dd][ppp][d][ppp][d]
 *
 * where each letter represents on block of either data or prealloc.
 *
 * This explains all the weirdly specific numbers.
 */
static int test_six()
{
	int character = (random() % 126) + 33;
	int i;

	memset(buf, character, 4096);

	/* Write on either side of the file, leaving a hole in the middle */
	for (i = 0; i < 10; i++) {
		if (pwrite(test_fd, buf, 4096, i * 4096) < 4096) {
			fprintf(stderr, "Short write %d\n", errno);
			return 1;
		}
	}

	if (fsync(test_fd)) {
		fprintf(stderr, "Fsync failed %d\n", errno);
		return 1;
	}

	/*
	 * The test fs I had the prealloc extent was 13 4k blocks long so I'm
	 * just using that to give myself the best chances of reproducing.
	 */
	for (i = 23; i < 33; i++) {
		if (pwrite(test_fd, buf, 4096, i * 4096) < 4096) {
			fprintf(stderr, "Short write %d\n", errno);
			return 1;
		}
	}

	if (fsync(test_fd)) {
		fprintf(stderr, "Fsync failed %d\n", errno);
		return 1;
	}

	if (fallocate(test_fd, 0, 10 * 4096, 4 * 4096)) {
		fprintf(stderr, "Error fallocating %d\n", errno);
		return 1;
	}

	if (fallocate(test_fd, 0, 14 * 4096, 5 * 4096)) {
		fprintf(stderr, "Error fallocating %d\n", errno);
		return 1;
	}

	if (fallocate(test_fd, 0, 19 * 4096, 4 * 4096)) {
		fprintf(stderr, "Error fallocating %d\n", errno);
		return 1;
	}

	if (pwrite(test_fd, buf, 4096, 10 * 4096) < 4096) {
		fprintf(stderr, "Short write %d\n", errno);
		return 1;
	}

	if (fsync(test_fd)) {
		fprintf(stderr, "Fsync failed %d\n", errno);
		return 1;
	}

	for (i = 13; i < 15; i++) {
		if (pwrite(test_fd, buf, 4096, i * 4096) < 4096) {
			fprintf(stderr, "Short write %d\n", errno);
			return 1;
		}
	}

	if (fsync(test_fd)) {
		fprintf(stderr, "Fsync failed %d\n", errno);
		return 1;
	}

	if (pwrite(test_fd, buf, 4096, 18 * 4096) < 4096) {
		fprintf(stderr, "Short write %d\n", errno);
		return 1;
	}

	if (fsync(test_fd)) {
		fprintf(stderr, "Fsync failed %d\n", errno);
		return 1;
	}

	if (pwrite(test_fd, buf, 4096, 22 * 4096) < 4096) {
		fprintf(stderr, "Short write %d\n", errno);
		return 1;
	}

	if (fsync(test_fd)) {
		fprintf(stderr, "Fsync failed %d\n", errno);
		return 1;
	}

	return 0;
}
Ejemplo n.º 2
0
/*
 * Randomly write inside of a file, either creating a sparse file or prealloc
 * the file and randomly write within it, depending on the prealloc flag
 */
static int test_three(int *max_blocks, int prealloc, int rand_fsync,
		      int do_sync, int drop_caches)
{
	int size = (random() % 2048) + 4;
	int blocks = size / 2;
	int sync_block = blocks / 2;
	int rand_sync_interval = (random() % blocks) + 1;
	int character = (random() % 126) + 33;

	if (prealloc && fallocate(test_fd, 0, 0, size * 4096)) {
		fprintf(stderr, "Error fallocating %d (%s)\n", errno,
			strerror(errno));
		return 1;
	}

	if (prealloc)
		*max_blocks = size;

	memset(buf, character, 4096);
	while (blocks--) {
		int block = (random() % size);

		if ((block + 1) > *max_blocks)
			*max_blocks = block + 1;

		if (rand_fsync && !(blocks % rand_sync_interval)) {
			if (fsync(test_fd)) {
				fprintf(stderr, "Fsync failed, test results "
					"will be invalid: %d\n", errno);
				return 1;
			}
		}

		/* Force a transaction commit in between just for fun */
		if (blocks == sync_block && (do_sync || drop_caches)) {
			if (do_sync)
				sync();
			else
				sync_file_range(test_fd, 0, 0,
						SYNC_FILE_RANGE_WRITE|
						SYNC_FILE_RANGE_WAIT_AFTER);

			if (drop_caches) {
				close(test_fd);
				drop_all_caches();
				test_fd = open(fname, O_RDWR);
				if (test_fd < 0) {
					test_fd = 0;
					fprintf(stderr, "Error re-opening file: %d\n",
						errno);
					return 1;
				}
			}
		}

		if (pwrite(test_fd, buf, 4096, block * 4096) < 4096) {
			fprintf(stderr, "Short write %d\n", errno);
			return 1;
		}
	}

	return 0;
}
Ejemplo n.º 3
0
/*
 * Leaves f->fd open on success, caller must close
 */
static int extend_file(struct thread_data *td, struct fio_file *f)
{
	int r, new_layout = 0, unlink_file = 0, flags;
	unsigned long long left;
	unsigned int bs;
	char *b;

	if (read_only) {
		log_err("fio: refusing extend of file due to read-only\n");
		return 0;
	}

	/*
	 * check if we need to lay the file out complete again. fio
	 * does that for operations involving reads, or for writes
	 * where overwrite is set
	 */
	if (td_read(td) || (td_write(td) && td->o.overwrite) ||
	    (td_write(td) && td->io_ops->flags & FIO_NOEXTEND))
		new_layout = 1;
	if (td_write(td) && !td->o.overwrite)
		unlink_file = 1;

	if (unlink_file || new_layout) {
		dprint(FD_FILE, "layout unlink %s\n", f->file_name);
		if ((unlink(f->file_name) < 0) && (errno != ENOENT)) {
			td_verror(td, errno, "unlink");
			return 1;
		}
	}

	flags = O_WRONLY | O_CREAT;
	if (new_layout)
		flags |= O_TRUNC;

	dprint(FD_FILE, "open file %s, flags %x\n", f->file_name, flags);
	f->fd = open(f->file_name, flags, 0644);
	if (f->fd < 0) {
		td_verror(td, errno, "open");
		return 1;
	}

#ifdef CONFIG_POSIX_FALLOCATE
	if (!td->o.fill_device) {
		switch (td->o.fallocate_mode) {
		case FIO_FALLOCATE_NONE:
			break;
		case FIO_FALLOCATE_POSIX:
			dprint(FD_FILE, "posix_fallocate file %s size %llu\n",
				 f->file_name,
				 (unsigned long long) f->real_file_size);

			r = posix_fallocate(f->fd, 0, f->real_file_size);
			if (r > 0) {
				log_err("fio: posix_fallocate fails: %s\n",
						strerror(r));
			}
			break;
#ifdef CONFIG_LINUX_FALLOCATE
		case FIO_FALLOCATE_KEEP_SIZE:
			dprint(FD_FILE,
				"fallocate(FALLOC_FL_KEEP_SIZE) "
				"file %s size %llu\n", f->file_name,
				(unsigned long long) f->real_file_size);

			r = fallocate(f->fd, FALLOC_FL_KEEP_SIZE, 0,
					f->real_file_size);
			if (r != 0)
				td_verror(td, errno, "fallocate");

			break;
#endif /* CONFIG_LINUX_FALLOCATE */
		default:
			log_err("fio: unknown fallocate mode: %d\n",
				td->o.fallocate_mode);
			assert(0);
		}
	}
#endif /* CONFIG_POSIX_FALLOCATE */

	if (!new_layout)
		goto done;

	/*
	 * The size will be -1ULL when fill_device is used, so don't truncate
	 * or fallocate this file, just write it
	 */
	if (!td->o.fill_device) {
		dprint(FD_FILE, "truncate file %s, size %llu\n", f->file_name,
					(unsigned long long) f->real_file_size);
		if (ftruncate(f->fd, f->real_file_size) == -1) {
			td_verror(td, errno, "ftruncate");
			goto err;
		}
	}

	b = malloc(td->o.max_bs[DDIR_WRITE]);

	left = f->real_file_size;
	while (left && !td->terminate) {
		bs = td->o.max_bs[DDIR_WRITE];
		if (bs > left)
			bs = left;

		fill_io_buffer(td, b, bs, bs);

		r = write(f->fd, b, bs);

		if (r > 0) {
			left -= r;
			continue;
		} else {
			if (r < 0) {
				int __e = errno;

				if (__e == ENOSPC) {
					if (td->o.fill_device)
						break;
					log_info("fio: ENOSPC on laying out "
						 "file, stopping\n");
					break;
				}
				td_verror(td, errno, "write");
			} else
				td_verror(td, EIO, "write");

			break;
		}
	}

	if (td->terminate) {
		dprint(FD_FILE, "terminate unlink %s\n", f->file_name);
		unlink(f->file_name);
	} else if (td->o.create_fsync) {
		if (fsync(f->fd) < 0) {
			td_verror(td, errno, "fsync");
			goto err;
		}
	}
	if (td->o.fill_device && !td_write(td)) {
		fio_file_clear_size_known(f);
		if (td_io_get_file_size(td, f))
			goto err;
		if (f->io_size > f->real_file_size)
			f->io_size = f->real_file_size;
	}

	free(b);
done:
	return 0;
err:
	close(f->fd);
	f->fd = -1;
	return 1;
}
Ejemplo n.º 4
0
int common_open_file(int *fd, int flags, char *filename, loff_t fallosize)
{
  struct stat statinfo;
  int err = 0;

  err = stat(filename, &statinfo);
  if (err < 0)
    {
      if (errno == ENOENT)
        {
          //We're reading the file
          /* Goddang what's the big idea setting O_RDONLY to 00 */
          if (!(flags & (O_WRONLY | O_RDWR)))
            {
              perror("File open");
              E("File %s not found, eventhought we wan't to read", filename);
              return EACCES;
            }
          else
            {
              D("COMMON_WRT: File doesn't exist. Creating it");
              flags |= O_CREAT;
              err = 0;
            }
        }
      /* Directory doesn't exist */
      else if (errno == ENOTDIR)
        {
          E("The directory doesn't exist");
          return ENOTDIR;
        }
      else
        {
          fprintf(stderr, "Error: %s on %s\n", strerror(errno), filename);
          return err;
        }
    }

  //This will overwrite existing file.TODO: Check what is the desired default behaviour 
  D("COMMON_WRT: Opening file %s", filename);
  *fd = open(filename, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
  if (*fd < 0)
    {
      if (flags & O_WRONLY)
        {
          /* Silent version since, acquire stumbles here and it     */
          /* Works as planned. Could do string processing           */
          /* to check the dir etc. but meh                          */
          D("File opening failed with write on for %s. Acquire should create dir", filename);
          return *fd;
        }
      fprintf(stderr, "Error: %s on %s\n", strerror(errno), filename);
      return *fd;
    }
  D(" File opened as fd %d", *fd);
  if (fallosize > 0)
    {
      err = fallocate(*fd, 0, 0, fallosize);
      if (err < 0)
        {
          perror("fallocate");
          if (errno == EOPNOTSUPP)
            {
              fprintf(stdout,
                      "COMMON_WRT: Not fallocating, since not supported\n");
              err = 0;
            }
          else
            {
              fprintf(stderr, "COMMON_WRT: Fallocate failed on %s\n",
                      filename);
              return err;
            }
        }
      D("File preallocated");
    }
  else
    D("Not fallocating");
  return err;
}
Ejemplo n.º 5
0
/*
    size_t blen, size_t niter, size_t blen_incr, size_t nincr)
*/
static int
run_odsync (const char* fname, const struct test_spec* sp)
{
    int fd = -1, err = 0, rc = 0;
    size_t len = 0, ni = 0, nfalloc = 0, j = 0;
    double sec = 0.0;
    int oflags = O_CREAT | O_RDWR;
    char *buf = NULL;
    struct timeval tstart, tend;
    ssize_t n = -1;
    pthread_t sync_thr = (pthread_t)0;
    wfunc_t write_data = NULL;

    assert (fname && sp);
    srand (time(NULL));

    write_data = (sp->num_chunks > 0) ? writev_nbuf : write_nbuf;

    oflags |= sp->open_flags;
    fd = open (fname, oflags, S_IRUSR|S_IWUSR);
    if (fd < 0) {
        err = errno;
        fprintf (stderr, "open [%s]: %s\n", fname, strerror(err));
        return err;
    }
    (void) printf ("BEGIN test: buf[%ld], niter=%ld, incr=%ld, nincr=%ld, "
            "num_chunks=[%ld] mode=0x%x\n",
            (long)sp->len, (long)sp->niter, (long)sp->incr, (long)sp->nincr,
            (long)sp->num_chunks, sp->mode_flags);
    (void) printf ("opened %s with flags=0x%04x\n", fname, oflags);

    if (sp->mode_flags & FALLOC) {
        nfalloc = (sp->len * sp->niter) + (sp->incr * (sp->nincr-1));
#ifdef __linux__
        rc = fallocate (fd, sp->mode_flags & FALLOC_SZ ? FALLOC_FL_KEEP_SIZE : 0, 0, nfalloc);
#elif !defined (NO_FALLOCATE)
        rc = posix_fallocate (fd, 0, nfalloc);
#endif
        if (rc) {
            err = errno;
            (void) fprintf (stderr, "fallocate [%ld bytes] for %s failed: %s\n",
                (long)nfalloc, fname, strerror (err));
        }
        else {
            (void) printf ("fallocate [%ld] for [%s]\n", (long)nfalloc, fname);
        }
    }

    if ((sp->mode_flags & SYNC_THREAD) && (sp->mode_flags & SYNC_TYPE)) {
        rc = start_sync_thread (&sync_thr);
    }

    for (len = sp->len, ni = 0; !rc && (len < MAX_BUFSZ) && (ni < sp->nincr);
            len += sp->incr, ++ni) {
        if (NULL == (buf = malloc (len))) {
            rc = ENOMEM;
            break;
        }
        for (j = 0; j < len; buf[j++] = rand () & 0xFF);

        (void) printf (" => buf[%ld bytes]: ", (long)len);
        gettimeofday (&tstart, 0);
            n = write_data (fd, buf, len, sp);
            if (n <= 0) {
                rc = (int)n;
                break;
            }
        gettimeofday (&tend, 0);
        sec = get_seconds (&tstart, &tend);
        (void) printf ("%ld/%ld bytes/writes in %.6f sec, %.6f w/sec, %.6f Kb/sec\n", (long)n,
                    (long)sp->niter, sec, (double)sp->niter/sec, ((double)n/sec)/1024);

        free (buf); buf = NULL;
    }

    if (buf) free (buf);
    (void) close (fd);

    if (sync_thr) {
        stop_sync_thread (&sync_thr);
    }

    (void) printf ("\nEND test, rc = %d\n", rc);
    return rc;
}
Ejemplo n.º 6
0
int main(int argc, char *argv[])
{
	struct stat	s;
	struct statfs	sf;
	off_t		offset;
	int		fd;
	blksize_t	blksz;
	off_t		sz;
	int		mode;
	int		error;
	int		c;
	int		size = 1;	/* punch $SIZE blocks ... */
	int		interval = 2;	/* every $INTERVAL blocks */

	while ((c = getopt(argc, argv, "i:s:")) != EOF) {
		switch (c) {
		case 'i':
			interval = atoi(optarg);
			break;
		case 's':
			size = atoi(optarg);
			break;
		default:
			usage(argv[0]);
		}
	}

	if (interval <= 0) {
		printf("interval must be > 0\n");
		usage(argv[0]);
	}

	if (size <= 0) {
		printf("size must be > 0\n");
		usage(argv[0]);
	}

	if (optind != argc - 1)
		usage(argv[0]);

	fd = open(argv[optind], O_WRONLY);
	if (fd < 0)
		goto err;

	error = fstat(fd, &s);
	if (error)
		goto err;

	error = fstatfs(fd, &sf);
	if (error)
		goto err;

	sz = s.st_size;
	blksz = sf.f_bsize;

	mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
	for (offset = 0; offset < sz; offset += blksz * interval) {
		error = fallocate(fd, mode, offset, blksz * size);
		if (error)
			goto err;
	}

	error = fsync(fd);
	if (error)
		goto err;

	error = close(fd);
	if (error)
		goto err;
	return 0;
err:
	perror(argv[optind]);
	return 2;
}
Ejemplo n.º 7
0
static void mfd_assert_write(int fd)
{
	ssize_t l;
	void *p;
	int r;

	/* verify write() succeeds */
	l = write(fd, "\0\0\0\0", 4);
	if (l != 4) {
		printf("write() failed: %m\n");
		abort();
	}

	/* verify PROT_READ | PROT_WRITE is allowed */
	p = mmap(NULL,
		 MFD_DEF_SIZE,
		 PROT_READ | PROT_WRITE,
		 MAP_SHARED,
		 fd,
		 0);
	if (p == MAP_FAILED) {
		printf("mmap() failed: %m\n");
		abort();
	}
	*(char *)p = 0;
	munmap(p, MFD_DEF_SIZE);

	/* verify PROT_WRITE is allowed */
	p = mmap(NULL,
		 MFD_DEF_SIZE,
		 PROT_WRITE,
		 MAP_SHARED,
		 fd,
		 0);
	if (p == MAP_FAILED) {
		printf("mmap() failed: %m\n");
		abort();
	}
	*(char *)p = 0;
	munmap(p, MFD_DEF_SIZE);

	/* verify PROT_READ with MAP_SHARED is allowed and a following
	 * mprotect(PROT_WRITE) allows writing */
	p = mmap(NULL,
		 MFD_DEF_SIZE,
		 PROT_READ,
		 MAP_SHARED,
		 fd,
		 0);
	if (p == MAP_FAILED) {
		printf("mmap() failed: %m\n");
		abort();
	}

	r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
	if (r < 0) {
		printf("mprotect() failed: %m\n");
		abort();
	}

	*(char *)p = 0;
	munmap(p, MFD_DEF_SIZE);

	/* verify PUNCH_HOLE works */
	r = fallocate(fd,
		      FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
		      0,
		      MFD_DEF_SIZE);
	if (r < 0) {
		printf("fallocate(PUNCH_HOLE) failed: %m\n");
		abort();
	}
}
Ejemplo n.º 8
0
int main(int argc, char **argv)
{
	char	*fname;
	int	c;
	int	error;
	int	fd;
	int	mode = 0;
	loff_t	length = -2LL;
	loff_t	offset = 0;

	struct option longopts[] = {
	    { "help",      0, 0, 'h' },
	    { "keep-size", 0, 0, 'n' },
	    { "offset",    1, 0, 'o' },
	    { "length",    1, 0, 'l' },
	    { NULL,        0, 0, 0 }
	};

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	while ((c = getopt_long(argc, argv, "hnl:o:", longopts, NULL)) != -1) {
		switch(c) {
		case 'h':
			usage(stdout);
			break;
		case 'n':
			mode |= FALLOC_FL_KEEP_SIZE;
			break;
		case 'l':
			length = cvtnum(optarg);
			break;
		case 'o':
			offset = cvtnum(optarg);
			break;
		default:
			usage(stderr);
			break;
		}
	}

	if (length == -2LL)
		errx(EXIT_FAILURE, _("no length argument specified"));
	if (length <= 0)
		errx(EXIT_FAILURE, _("invalid length value specified"));
	if (offset < 0)
		errx(EXIT_FAILURE, _("invalid offset value specified"));
	if (optind == argc)
		errx(EXIT_FAILURE, _("no filename specified."));

	fname = argv[optind++];

	if (optind != argc) {
		warnx(_("unexpected number of arguments"));
		usage(stderr);
	}

	fd = open(fname, O_WRONLY|O_CREAT, 0644);
	if (fd < 0)
		err(EXIT_FAILURE, _("%s: open failed"), fname);

#ifdef HAVE_FALLOCATE
	error = fallocate(fd, mode, offset, length);
#else
	error = syscall(SYS_fallocate, fd, mode, offset, length);
#endif
	/*
	 * EOPNOTSUPP: The FALLOC_FL_KEEP_SIZE is unsupported
	 * ENOSYS: The filesystem does not support sys_fallocate
	 */
	if (error < 0) {
		if ((mode & FALLOC_FL_KEEP_SIZE) && errno == EOPNOTSUPP)
			errx(EXIT_FAILURE,
				_("keep size mode (-n option) unsupported"));
		err(EXIT_FAILURE, _("%s: fallocate failed"), fname);
	}

	close(fd);
	return EXIT_SUCCESS;
}
Ejemplo n.º 9
0
int
falloc(int fd, int len)
{
    return fallocate(fd, 0, 0, len);
}
Ejemplo n.º 10
0
int copy_file(const char *srcpath, const char *destpath)
{
	const unsigned PAGESIZE = sysconf(_SC_PAGESIZE) * BUFSIZE;
	int srcfd = open(srcpath, O_RDONLY);
	if(srcfd == ERROR)
	{
		strexit(srcpath);
	}

	struct stat* st = (struct stat*) malloc(sizeof(struct stat));
	if(fstat(srcfd, st) == ERROR) 
	{ 
		strexit("FSTAT");
	}

	int destfd = ERROR;
	if(S_ISDIR(st->st_mode))
	{
		if(mkdir(destpath, st->st_mode) == ERROR)
		{
			strexit(destpath);
		}
		return 0;
	}
	else
	{
		if((destfd = open(destpath, O_WRONLY | O_CREAT | O_APPEND, st->st_mode)) == ERROR)
		{
			strexit(destpath);
		}
	}

	if(samefile(srcfd, destfd))
	{
		return true;
	}

	if(ftruncate(destfd, 0) == ERROR)
	{
		strexit("TRUNCATE");
	}

	if(st->st_size > 0 && fallocate(destfd, FALLOC_FL_KEEP_SIZE, 0, st->st_size) == ERROR)
	{
		strexit("FALLOCATE");
	}

	// AIO Read / Write Information
	struct fileaio* arg = (struct fileaio*) malloc(sizeof(struct fileaio));
	if(!arg)
	{
		strexit("FILEAIO MALLOC");
	}
	arg->srcfd = srcfd;
	arg->destfd = destfd;
	arg->filesize = st->st_size;
	arg->offset = PAGESIZE;

	arg->aio = (struct aiocb*) calloc(1, sizeof(struct aiocb));
	if(!arg->aio)
	{
		strexit("AIOCB CALLOC");
	}

	arg->aio->aio_fildes = srcfd;
	arg->aio->aio_buf = malloc(PAGESIZE);
	if(!arg->aio->aio_buf)
	{
		strexit("AIOCB BUFFER");
	}
	arg->aio->aio_nbytes = PAGESIZE;
	arg->aio->aio_offset = 0;

	// Setup sigevent handler for when AIO finishes
	arg->aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
	arg->aio->aio_sigevent.sigev_notify_function = aio_handler;
	arg->aio->aio_sigevent.sigev_notify_attributes = NULL;
	arg->aio->aio_sigevent.sigev_value.sival_ptr = arg;

	if(aio_read(arg->aio) == ERROR)
	{
		strexit("READ LIO_LISTIO");
	}
	++outstanding_aio;

	return 0;
}
Ejemplo n.º 11
0
int posix_fallocate(int fd, off64_t offset, off64_t len) {
  return fallocate(fd,0,offset,len);
}
  virtual int run(int checkpoint) override {
    int local_checkpoint = 0;

    //Open file foo
    const int fd_foo = open(foo_path.c_str(), O_RDWR);
    if (fd_foo < 0) {
      return -1;
    }

    // system("stat /mnt/snapshot/foo");


    /*-------------------Variant 1 ---------------------------*/
    //unaligned offset and size less than  a page
    //Fallocate from off 17000 of length 3000
    if(fallocate(fd_foo, FALLOC_FL_KEEP_SIZE ,17000, 3000) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    int res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }

    // Make a user checkpoint here. Checkpoint must be 1 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 0;
    }

    //Expected output if checkpoint = 1 : Size = 16K, blocks == 40  (32 + 8)
    // system("stat /mnt/snapshot/foo");



    /*-------------------Variant 2 ---------------------------*/
    //aligned offset and size less than  a page
    //Fallocate from off 24K of length 3000
    if(fallocate(fd_foo, FALLOC_FL_KEEP_SIZE ,24576, 3000) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }

    // Make a user checkpoint here. Checkpoint must be 2 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 0;
    }
    //Expected output if checkpoint = 2: size = 16K, blocks == 48 (40 + 8)
    // system("stat /mnt/snapshot/foo");


    /*-------------------Variant 3 ---------------------------*/
    //Aligned offset and size > a page
    //Fallocate from off 32K of length 8192
    if(fallocate(fd_foo, FALLOC_FL_KEEP_SIZE , 32768, 8192) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }
    // Make a user checkpoint here. Checkpoint must be 3 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 0;
    }
    //Expected output if checkpoint = 3: size = 16K, blocks == 64 (48 + 16)
    // system("stat /mnt/snapshot/foo");


    /*-------------------Variant 4 ---------------------------*/
    //unaligned offset and size less than  a page
    //Fzero from off 42000 of length 3000
    if(fallocate(fd_foo, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE ,42000, 3000) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }

    // Make a user checkpoint here. Checkpoint must be 4 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 0;
    }
    //Expected output if checkpoint = 4 : Size = 16K, blocks == 72  (64 + 8)
    // system("stat /mnt/snapshot/foo");



    /*-------------------Variant 5 ---------------------------*/
    //aligned offset and size less than  a page
    //Fzero from off 48K of length 3000
    if(fallocate(fd_foo, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE ,49152, 3000) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }

    // Make a user checkpoint here. Checkpoint must be 5 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 0;
    }
    //Expected output if checkpoint = 5: size = 16K, blocks == 80 (72 + 8)
    // system("stat /mnt/snapshot/foo");


    /*-------------------Variant 6 ---------------------------*/
    //Aligned offset and size > a page
    //Fzero from off 52K of length 8192
    if(fallocate(fd_foo, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE , 53248, 8192) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }

    // Make a user checkpoint here. Checkpoint must be 6 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 1;
    }
    //Expected output if checkpoint = 6: size = 16K, blocks == 96 (80 + 16)
    // system("stat /mnt/snapshot/foo");






    //Close open files  
    close(fd_foo);

    return 0;
  }
Ejemplo n.º 13
0
static void mfd_assert_write(int fd)
{
	ssize_t l;
	void *p;
	int r;

	/*
	 * huegtlbfs does not support write, but we want to
	 * verify everything else here.
	 */
	if (!hugetlbfs_test) {
		/* verify write() succeeds */
		l = write(fd, "\0\0\0\0", 4);
		if (l != 4) {
			printf("write() failed: %m\n");
			abort();
		}
	}

	/* verify PROT_READ | PROT_WRITE is allowed */
	p = mmap(NULL,
		 mfd_def_size,
		 PROT_READ | PROT_WRITE,
		 MAP_SHARED,
		 fd,
		 0);
	if (p == MAP_FAILED) {
		printf("mmap() failed: %m\n");
		abort();
	}
	*(char *)p = 0;
	munmap(p, mfd_def_size);

	/* verify PROT_WRITE is allowed */
	p = mmap(NULL,
		 mfd_def_size,
		 PROT_WRITE,
		 MAP_SHARED,
		 fd,
		 0);
	if (p == MAP_FAILED) {
		printf("mmap() failed: %m\n");
		abort();
	}
	*(char *)p = 0;
	munmap(p, mfd_def_size);

	/* verify PROT_READ with MAP_SHARED is allowed and a following
	 * mprotect(PROT_WRITE) allows writing */
	p = mmap(NULL,
		 mfd_def_size,
		 PROT_READ,
		 MAP_SHARED,
		 fd,
		 0);
	if (p == MAP_FAILED) {
		printf("mmap() failed: %m\n");
		abort();
	}

	r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
	if (r < 0) {
		printf("mprotect() failed: %m\n");
		abort();
	}

	*(char *)p = 0;
	munmap(p, mfd_def_size);

	/* verify PUNCH_HOLE works */
	r = fallocate(fd,
		      FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
		      0,
		      mfd_def_size);
	if (r < 0) {
		printf("fallocate(PUNCH_HOLE) failed: %m\n");
		abort();
	}
}
Ejemplo n.º 14
0
bool __check_request(struct bufferevent* bev, struct evbuffer* in,
                     struct evbuffer* out, struct nbd_client* client)
{
    struct nbd_req_header* peek = NULL;
    struct nbd_req_header req;
    uint32_t err = 0;
    uint64_t handle = 0;
    void* test = NULL;
    char bytestr[32];
    peek = (struct nbd_req_header*)
           evbuffer_pullup(in, sizeof(struct nbd_req_header));

    if (peek)
    {
        memcpy(&req, peek, sizeof(struct nbd_req_header));
        
        if (be32toh(req.magic) == GAMMARAY_NBD_REQ_MAGIC)
        {
            handle = be64toh(req.handle);

            switch(be32toh(req.type))
            {
                case NBD_CMD_READ:
                    err = __handle_read(peek, client);
                    if (err == -1)
                        return true;
                    evbuffer_drain(in, sizeof(struct nbd_req_header));
                    __send_response(bev, err, handle,
                                    client->buf, be32toh(req.length));
                    return false;
                case NBD_CMD_WRITE:
                    fprintf(stderr, "+");
                    err = __handle_write(peek, client, in);
                    if (err == -1)
                        return true;
                    pretty_print_bytes(client->write_bytes, bytestr, 32);
                    fprintf(stderr, "\twrite[%"PRIu64"]: %"PRIu64" cumulative "
                                    "bytes (%s)\n", client->write_count,
                                                    client->write_bytes,
                                                    bytestr);
                    evbuffer_drain(in, be32toh(req.length));
                    __send_response(bev, err, handle, NULL, 0);
                    return false;
                case NBD_CMD_DISC:
                    fprintf(stderr, "got disconnect.\n");
                    client->state = NBD_DISCONNECTED;
                    evbuffer_drain(in, sizeof(struct nbd_req_header));
                    nbd_ev_handler(bev, BEV_EVENT_EOF, client);
                    return false;
                case NBD_CMD_FLUSH:
                    fprintf(stderr, "got flush.\n");
                    evbuffer_drain(in, sizeof(struct nbd_req_header));
                    if (fsync(client->handle->fd))
                        __send_response(bev, errno, handle, NULL, 0);
                    else
                        __send_response(bev, 0, handle, NULL, 0);
                    return false;
                case NBD_CMD_TRIM:
                    fprintf(stderr, "got trim.\n");
                    evbuffer_drain(in, sizeof(struct nbd_req_header));
                    if (fallocate(client->handle->fd,
                                  FALLOC_FL_PUNCH_HOLE |
                                  FALLOC_FL_KEEP_SIZE,
                                  be64toh(req.offset),
                                  be32toh(req.length)))
                        __send_response(bev, errno, handle, NULL, 0);
                    else
                        __send_response(bev, 0, handle, NULL, 0);
                    return false;
                default:
                    test = evbuffer_pullup(in, sizeof(struct nbd_req_header) +
                                               be32toh(req.length));
                    if (test)
                        evbuffer_drain(in, sizeof(struct nbd_req_header) +
                                       be32toh(req.length));
                    fprintf(stderr, "unknown command!\n");
                    fprintf(stderr, "-- Hexdumping --\n");
                    if (test)
                        hexdump(test, be32toh(req.length));
                    fprintf(stderr, "disconnecting, protocol error!\n");
                    client->state = NBD_DISCONNECTED;
                    nbd_ev_handler(bev, BEV_EVENT_EOF, client);
            };
        }
    }

    return true;
}
Ejemplo n.º 15
0
static void mfd_fail_write(int fd)
{
	ssize_t l;
	void *p;
	int r;

	/* verify write() fails */
	l = write(fd, "data", 4);
	if (l != -EPERM) {
		printf("expected EPERM on write(), but got %d: %m\n", (int)l);
		abort();
	}

	/* verify PROT_READ | PROT_WRITE is not allowed */
	p = mmap(NULL,
		 MFD_DEF_SIZE,
		 PROT_READ | PROT_WRITE,
		 MAP_SHARED,
		 fd,
		 0);
	if (p != MAP_FAILED) {
		printf("mmap() didn't fail as expected\n");
		abort();
	}

	/* verify PROT_WRITE is not allowed */
	p = mmap(NULL,
		 MFD_DEF_SIZE,
		 PROT_WRITE,
		 MAP_SHARED,
		 fd,
		 0);
	if (p != MAP_FAILED) {
		printf("mmap() didn't fail as expected\n");
		abort();
	}

	/* Verify PROT_READ with MAP_SHARED with a following mprotect is not
	 * allowed. Note that for r/w the kernel already prevents the mmap. */
	p = mmap(NULL,
		 MFD_DEF_SIZE,
		 PROT_READ,
		 MAP_SHARED,
		 fd,
		 0);
	if (p != MAP_FAILED) {
		r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
		if (r >= 0) {
			printf("mmap()+mprotect() didn't fail as expected\n");
			abort();
		}
	}

	/* verify PUNCH_HOLE fails */
	r = fallocate(fd,
		      FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
		      0,
		      MFD_DEF_SIZE);
	if (r >= 0) {
		printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
		abort();
	}
}
Ejemplo n.º 16
0
int main(int argc, char **argv)
{
	int blocksize = 0;	/* filesystem blocksize */
	int fd;			/* file descriptor */
	int opt;
	int rc;
	char *fname;		/* filename to map */
	char *map = NULL;	/* file map to generate */
	int runs = -1;		/* the number of runs to have */
	int blocks = 0;		/* the number of blocks to generate */
	int maxblocks = 0;	/* max # of blocks to create */
	int prealloc = 1;	/* whether or not to do preallocation */
	int seed = 1;

	while ((opt = getopt(argc, argv, "m:r:s:p:")) != -1) {
		switch (opt) {
		case 'm':
			map = strdup(optarg);
			break;
		case 'p':
#ifndef NO_FALLOCATE
			prealloc = atoi(optarg);;
			break;
#else
			printf("Not built with preallocation support\n");
			usage();
#endif
			/* sync file before mapping */
		case 'r':
			runs = atoi(optarg);
			break;
		case 's':
			seed = atoi(optarg);
			break;
		default:
			usage();
		}
	}

	if (runs != -1 && map)
		usage();

	fname = argv[optind++];
	if (!fname)
		usage();

	fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (fd < 0) {
		perror("Can't open file");
		exit(1);
	}

	if (ioctl(fd, FIGETBSZ, &blocksize) < 0) {
		perror("Can't get filesystem block size");
		close(fd);
		exit(1);
	}
#ifndef NO_FALLOCATE
	/* if fallocate passes, then we can do preallocation, else not */
	if (prealloc) {
		prealloc = !((int) fallocate(fd, 0, 0, blocksize));
		if (!prealloc)
			printf("preallocation not supported, disabling\n");
	}
#else
	prealloc = 0;
#endif

	if (ftruncate(fd, 0)) {
		perror("Can't truncate file");
		close(fd);
		exit(1);
	}

	if (map) {
		blocks = strlen(map);
		runs = 0;
	}

	srandom(seed);

	/* max file size 2mb / block size */
	maxblocks = (2 * 1024 * 1024) / blocksize;

	if (runs == -1)
		printf
		    ("Starting infinite run, if you don't see any output "
		     "then its working properly.\n");
	do {
		if (!map) {
			blocks = random() % maxblocks;
			if (blocks == 0) {
				printf("Skipping 0 length file\n");
				continue;
			}

			map = generate_file_mapping(blocks, prealloc);
			if (!map) {
				printf("Could not create map\n");
				exit(1);
			}
		}

		rc = create_file_from_mapping(fd, map, blocks, blocksize);
		if (rc) {
			perror("Could not create file\n");
			free(map);
			close(fd);
			exit(1);
		}

		rc = compare_fiemap_and_map(fd, map, blocks, blocksize);
		if (rc) {
			printf("Problem comparing fiemap and map\n");
			free(map);
			close(fd);
			exit(1);
		}

		free(map);
		map = NULL;

		if (ftruncate(fd, 0)) {
			perror("Could not truncate file\n");
			close(fd);
			exit(1);
		}

		if (lseek(fd, 0, SEEK_SET)) {
			perror("Could not seek set\n");
			close(fd);
			exit(1);
		}

		if (runs)
			runs--;
	} while (runs != 0);

	close(fd);

	return 0;
}
Ejemplo n.º 17
0
void verify(const char *mntpt, size_t pgsize)
{
    char filename[128];
    size_t i;
    int e;

    pagesize = pgsize;
    work_alloc_start = 0;
    fd = -1;
    p = NULL;

    fprintf(stderr, "\nVerifying %s  pagesize: %lu ...\n", mntpt, pagesize);

    snprintf(filename, sizeof(filename), "%s/t", mntpt);
    fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0644);
    if (fd==-1)
        err(errno, "open");

    e = ftruncate(fd, FILEMAX);
    if (e)
        err(errno, "ftruncate");

    p = mmap(NULL, VIRTMAX, PROT_READ | PROT_WRITE,
            MAP_SHARED, fd, 0);
    if (p == MAP_FAILED)
        err(errno, "mmap");

    /* touch WORK */
    fprintf(stderr, "allocating...\n");
    for (i=0; i<WORK; i += pagesize) {
        p[i] = 1;

        //if (i%50 == 0)
        //    usleep(1);
    }
    fprintf(stderr, "\t... done\n");
    //assert(p[0] == 1);    /* first pages may be already freed */
    assert(p[work_alloc_start] == 1);

    /* hole punch touched memory */
    fprintf(stderr, "deallocating...\n");
    for (i=0; i<WORK; i += pagesize) {
        e = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
                i, pagesize);
        if (e)
            err(errno, "fallocate");

        //if (i%50 == 0)
        //    usleep(1);
    }
    fprintf(stderr, "\t... done\n");
    assert(p[0] == 0);  /* changes must be forgotten */
    assert(p[work_alloc_start] == 0);

    e = munmap(p, VIRTMAX);
    if (e)
        err(errno, "munmap");

    e = close(fd);
    if (e)
        err(errno, "close");

    fprintf(stderr, "OK\n");
}
Ejemplo n.º 18
0
int main(int argc, char *argv[])
{
	long hpage_size;
	int fd;
	int err;
	unsigned long free_before, free_after;

	test_init(argc, argv);

	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	free_before = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);

	/*
	 * First preallocate file with with just 1 byte.  Allocation sizes
	 * are rounded up, so we should get an entire huge page.
	 */
	err = fallocate(fd, 0, 0, 1);
	if (err) {
		if (errno == EOPNOTSUPP)
			IRRELEVANT();
		if (err)
			FAIL("fallocate(): %s", strerror(errno));
	}

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_before - free_after != 1)
		FAIL("fallocate 1 byte did not preallocate entire huge page\n");

	/*
	 * Now punch a hole with just 1 byte.  On hole punch, sizes are
	 * rounded down.  So, this operation should not create a hole.
	 */
	err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
			0, 1);
	if (err)
		FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_after == free_before)
		FAIL("fallocate hole punch 1 byte free'ed a huge page\n");

	/*
	 * Now punch a hole with of 2 * hpage_size - 1 byte.  This size
	 * should be rounded down to a single huge page and the hole created.
	 */
	err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
			0, (2 * hpage_size) - 1);
	if (err)
		FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_after != free_before)
		FAIL("fallocate hole punch 2 * hpage_size - 1 byte did not free huge page\n");

	/*
	 * Perform a preallocate operation with offset 1 and size of
	 * hpage_size.  The offset should be rounded down and the
	 * size rounded up to preallocate two huge pages.
	 */
	err = fallocate(fd, 0, 1, hpage_size);
	if (err)
		FAIL("fallocate(): %s", strerror(errno));

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_before - free_after != 2)
		FAIL("fallocate 1 byte offset, huge page size did not preallocate two huge pages\n");

	/*
	 * The hole punch code will only delete 'whole' huge pags that are
	 * in the specified range.  The offset is rounded up, and (offset
	 * + size) is rounded down to determine the huge pages to be deleted.
	 * In this case, after rounding the range is (hpage_size, hpage_size).
	 * So, no pages should be deleted.
	 */
	err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
			1, hpage_size);
	if (err)
		FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_before - free_after != 2)
		FAIL("fallocate hole punch 1 byte offset, huge page size incorrectly deleted a huge page\n");

	/*
	 * To delete both huge pages, the range passed to hole punch must
	 * overlap the allocated pages
	 */
	err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
			0, 2 * hpage_size);
	if (err)
		FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_after != free_before)
		FAIL("fallocate hole punch did not delete two huge pages\n");

	PASS();
}
Ejemplo n.º 19
0
int test_dax_poison(struct ndctl_test *test, int dax_fd, unsigned long align,
		void *dax_addr, off_t offset, bool fsdax)
{
	unsigned char *addr = MAP_FAILED;
	struct sigaction act;
	unsigned x = x;
	void *buf;
	int rc;

	if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 19, 0)))
		return 77;

	/*
	 * MADV_HWPOISON must be page aligned, and this routine assumes
	 * align is >= 8K
	 */
	if (align < SZ_2M)
		return 0;

	if (posix_memalign(&buf, 4096, 4096) != 0)
		return -ENOMEM;

	memset(&act, 0, sizeof(act));
	act.sa_sigaction = sigbus_hdl;
	act.sa_flags = SA_SIGINFO;

	if (sigaction(SIGBUS, &act, 0)) {
		fail();
		rc = -errno;
		goto out;
	}

	/* dirty the block on disk to bypass the default zero page */
	if (fsdax) {
		rc = pwrite(dax_fd, buf, 4096, offset + align / 2);
		if (rc < 4096) {
			fail();
			rc = -ENXIO;
			goto out;
		}
		fsync(dax_fd);
	}

	addr = mmap(dax_addr, 2*align, PROT_READ|PROT_WRITE,
			MAP_SHARED_VALIDATE|MAP_POPULATE|MAP_SYNC, dax_fd, offset);
	if (addr == MAP_FAILED) {
		fail();
		rc = -errno;
		goto out;
	}

	if (sigsetjmp(sj_env, 1)) {
		if (sig_mcerr_ar) {
			fprintf(stderr, "madvise triggered 'action required' sigbus\n");
			goto clear_error;
		} else if (sig_count) {
			fail();
			return -ENXIO;
		}
	}

	rc = madvise(addr + align / 2, 4096, MADV_HWPOISON);
	if (rc) {
		fail();
		rc = -errno;
		goto out;
	}

	/* clear the error */
clear_error:
	if (!sig_mcerr_ar) {
		fail();
		rc = -ENXIO;
		goto out;
	}

	if (!fsdax) {
		rc = 0;
		goto out;
	}

	rc = fallocate(dax_fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,
			offset + align / 2, 4096);
	if (rc) {
		fail();
		rc = -errno;
		goto out;
	}

	rc = pwrite(dax_fd, buf, 4096, offset + align / 2);
	if (rc < 4096) {
		fail();
		rc = -ENXIO;
		goto out;
	}
	fsync(dax_fd);

	/* check that we can fault in the poison page */
	x = *(volatile unsigned *) addr + align / 2;
	rc = 0;

out:
	if (addr != MAP_FAILED)
		munmap(addr, 2 * align);
	free(buf);
	return rc;
}
Ejemplo n.º 20
0
/*****************************************************************************
 * Calls the system call, with appropriate parameters and writes data
 ******************************************************************************/
void runtest(int mode, int fd, loff_t expected_size)
{
	loff_t offset;
	loff_t len = block_size;
	loff_t write_offset, lseek_offset;
	offset = lseek(fd, 0, SEEK_END);
	struct stat file_stat;
	errno = 0;

	TEST(fallocate(fd, mode, offset, len));
	/* check return code */
	if (TEST_RETURN != 0) {
		if (TEST_ERRNO == EOPNOTSUPP || TEST_ERRNO == ENOSYS) {
			tst_brkm(TCONF, cleanup,
				 "fallocate system call is not implemented");
		}
		TEST_ERROR_LOG(TEST_ERRNO);
		tst_resm(TFAIL | TTERRNO,
			 "fallocate(%d, %d, %" PRId64 ", %" PRId64 ") failed",
			 fd, mode, offset, len);
		return;
	} else {
		if (STD_FUNCTIONAL_TEST) {
			/* No Verification test, yet... */
			tst_resm(TPASS,
				 "fallocate(%d, %d, %" PRId64 ", %" PRId64
				 ") returned %ld", fd, mode, offset, len,
				 TEST_RETURN);
		}
	}

	if (fstat(fd, &file_stat) < 0)
		tst_resm(TFAIL | TERRNO, "fstat failed after fallocate()");

	if (file_stat.st_size != expected_size)
		tst_resm(TFAIL | TTERRNO,
			 "fstat test fails on fallocate (%d, %d, %" PRId64 ", %"
			 PRId64 ") Failed on mode", fd, mode, offset, len);

	write_offset = random() % len;
	lseek_offset = lseek(fd, write_offset, SEEK_CUR);
	if (lseek_offset != offset + write_offset) {
		tst_resm(TFAIL | TTERRNO,
			 "lseek fails in fallocate(%d, %d, %" PRId64 ", %"
			 PRId64 ") failed on mode", fd, mode, offset, len);
		return;
	}
	//Write a character to file at random location
	TEST(write(fd, "A", 1));
	/* check return code */
	if (TEST_RETURN == -1) {
		TEST_ERROR_LOG(TEST_ERRNO);
		tst_resm(TFAIL | TTERRNO,
			 "write fails in fallocate(%d, %d, %" PRId64 ", %"
			 PRId64 ") failed", fd, mode, offset, len);
	} else {
		if (STD_FUNCTIONAL_TEST) {
			/* No Verification test, yet... */
			tst_resm(TPASS,
				 "write operation on fallocated(%d, %d, %"
				 PRId64 ", %" PRId64 ") returned %ld", fd, mode,
				 offset, len, TEST_RETURN);
		}
	}
}
Ejemplo n.º 21
0
int parity_chsize(struct snapraid_parity* parity, data_off_t size, data_off_t* out_size, int skip_fallocate)
{
	int ret;

	if (parity->st.st_size < size) {
		int f_ret;
		int f_errno;
		const char* call;

#if HAVE_FALLOCATE
		call = "fallocate";
		if (!skip_fallocate) {
			/* allocate real space using the specific Linux fallocate() operation. */
			/* If the underline filesystem doesn't support it, this operation fails, */
			/* instead posix_fallocate() fallbacks to write the whole file. */
			ret = fallocate(parity->f, 0, 0, size);

			/* fallocate() returns the error number as positive integer, */
			/* and in this case it doesn't set errno, just like posix_fallocate() */
			/* Checking the glibc code (2.11.1 and 2.14.1) it seems that ENOSYS */
			/* may be returned in errno, so we support both the return way */
			if (ret > 0) { /* if a positive error is returned, convert it to errno */
				/* LCOV_EXCL_START */
				errno = ret;
				ret = -1;
				/* LCOV_EXCL_STOP */
			}
		} else {
			errno = EOPNOTSUPP;
			ret = -1;
		}

		/* we get EOPNOTSUPP if the operation is not supported, like in ext3/ext2 */
		/* or ENOSYS with kernel before 2.6.23 */
		if (errno == EOPNOTSUPP || errno == ENOSYS) {
			/* fallback using ftruncate() */
			call = "ftruncate";
			ret = ftruncate(parity->f, size);
		}
#else
		(void)skip_fallocate; /* avoid the warning */

		/* allocate using a sparse file */
		call = "ftruncate";
		ret = ftruncate(parity->f, size);
#endif
		/* save the state of the grow operation */
		f_ret = ret;
		f_errno = errno;

		/* get the stat info */
		ret = fstat(parity->f, &parity->st);
		if (ret != 0) {
			/* LCOV_EXCL_START */
			fprintf(stderr, "Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno));
			goto bail;
			/* LCOV_EXCL_STOP */
		}

		/* return the new size */
		*out_size = parity->st.st_size;

		/* now check the error */
		if (f_ret != 0) {
			/* LCOV_EXCL_START */
			if (f_errno == ENOSPC) {
				fprintf(stderr, "Failed to grow parity file '%s' to size %"PRIu64" using %s due lack of space.\n", parity->path, size, call);
			} else {
				fprintf(stderr, "Error growing parity file '%s' to size %"PRIu64" using %s. Do you have enough space? %s.\n", parity->path, size, call, strerror(f_errno));
			}
			goto bail;
			/* LCOV_EXCL_STOP */
		}
	} else if (parity->st.st_size > size) {
		int f_ret;
		int f_errno;

		/* truncate the parity file */
		ret = ftruncate(parity->f, size);

		/* save the state of the shrink operation */
		f_ret = ret;
		f_errno = errno;

		/* get the stat info */
		ret = fstat(parity->f, &parity->st);
		if (ret != 0) {
			/* LCOV_EXCL_START */
			fprintf(stderr, "Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno));
			goto bail;
			/* LCOV_EXCL_STOP */
		}

		/* return the new size */
		*out_size = parity->st.st_size;

		/* now check the error */
		if (f_ret != 0) {
			/* LCOV_EXCL_START */
			fprintf(stderr, "Error truncating parity file '%s' to size %"PRIu64". %s.\n", parity->path, size, strerror(f_errno));
			goto bail;
			/* LCOV_EXCL_STOP */
		}

		/* adjust the valid to the new size */
		parity->valid_size = size;
	}

	return 0;

bail:
	/* LCOV_EXCL_START */
	parity->valid_size = 0;
	return -1;
	/* LCOV_EXCL_STOP */
}
Ejemplo n.º 22
0
            virtual int run( int checkpoint ) override {
                
				test_path = mnt_dir_ ;
				A_path =  mnt_dir_ + "/A";
				AC_path =  mnt_dir_ + "/A/C";
				B_path =  mnt_dir_ + "/B";
				foo_path =  mnt_dir_ + "/foo";
				bar_path =  mnt_dir_ + "/bar";
				Afoo_path =  mnt_dir_ + "/A/foo";
				Abar_path =  mnt_dir_ + "/A/bar";
				Bfoo_path =  mnt_dir_ + "/B/foo";
				Bbar_path =  mnt_dir_ + "/B/bar";
				ACfoo_path =  mnt_dir_ + "/A/C/foo";
				ACbar_path =  mnt_dir_ + "/A/C/bar";
				int local_checkpoint = 0 ;

				int fd_foo = cm_->CmOpen(foo_path.c_str() , O_RDWR|O_CREAT , 0777); 
				if ( fd_foo < 0 ) { 
					cm_->CmClose( fd_foo); 
					return errno;
				}


				if ( WriteData ( fd_foo, 0, 32768) < 0){ 
					cm_->CmClose( fd_foo); 
					return errno;
				}


				if ( fallocate( fd_foo , FALLOC_FL_KEEP_SIZE , 32768 , 32768) < 0){ 
					cm_->CmClose( fd_foo);
					 return errno;
				}


				int fd_test = cm_->CmOpen(test_path.c_str() , O_DIRECTORY , 0777); 
				if ( fd_test < 0 ) { 
					cm_->CmClose( fd_test); 
					return errno;
				}


				if ( cm_->CmFsync( fd_test) < 0){ 
					return errno;
				}


				if ( cm_->CmCheckpoint() < 0){ 
					return -1;
				}
				local_checkpoint += 1; 
				if (local_checkpoint == checkpoint) { 
					return 1;
				}


				if ( cm_->CmClose ( fd_foo) < 0){ 
					return errno;
				}


				if ( cm_->CmClose ( fd_test) < 0){ 
					return errno;
				}

                return 0;
            }
void runSuccess() {
    int fd = VALID_FD;
    if (fd >= 0) {
        fallocate(fd, anyint(), anyint(), anyint());
    }
}
Ejemplo n.º 24
0
static int eat(const char *filename)
{

#define fail_if(cond) \
  while (cond) \
  { \
    show_error(filename); \
    if (fd != -1) \
      close(fd); \
    return -1; \
  }

#define check_io(i, j) \
  while ((size_t) (i) != (size_t) (j)) \
  { \
    if ((i) >= 0) \
      errno = EIO; \
    fail_if(1); \
  }

  const int fd = open(filename, O_RDWR);
  fail_if(fd == -1);
  const off_t file_size = lseek(fd, 0, SEEK_END);
  fail_if(file_size == -1);

  int rc;
  off_t offset;
  ssize_t r_bytes, w_bytes;

  offset = lseek(fd, 0, SEEK_SET);
  fail_if(offset == -1);

  if (block_size == 0)
  {
    struct statvfs st;
    rc = fstatvfs(fd, &st);
    fail_if(rc == -1);
    if (st.f_bsize == 0 || st.f_bsize >= block_size_limit)
    {
      errno = ERANGE;
      fail_if(1);
    }
    block_size = st.f_bsize;
  }

  const off_t n_blocks = (file_size + block_size - 1) / block_size;
  const size_t tail_size = (size_t) (1 + (file_size - 1) % block_size);

  switch (n_blocks)
  {
  case 2:
    r_bytes = read(fd, buffer, block_size);
    check_io(r_bytes, block_size);
    w_bytes = write(STDOUT_FILENO, buffer, block_size);
    check_io(w_bytes, block_size);
  case 1:
    r_bytes = read(fd, buffer, tail_size);
    check_io(r_bytes, tail_size);
    w_bytes = write(STDOUT_FILENO, buffer, (size_t) r_bytes);
    check_io(w_bytes, r_bytes);
  case 0:
    goto done;
  default:
    break;
  }

  struct stat stat;
  rc = fstat(fd, &stat);
  fail_if(rc == -1);
  if (stat.st_nlink > 1 && !opt_force)
  {
    errno = EMLINK;
    fail_if(1);
  }

  for (off_t i = 0; i < n_blocks / 2; i++)
  {
    r_bytes = read(fd, buffer, block_size);
    check_io(r_bytes, block_size);
    w_bytes = write(STDOUT_FILENO, buffer, block_size);
    check_io(w_bytes, block_size);
    if (i == 0 && opt_punch)
    {
#if HAVE_FALLOC_FL_PUNCH_HOLE
      rc = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, offset, block_size);
      if (rc == 0)
      {
        offset = 0;
        while (1)
        {
          r_bytes = read(fd, buffer, block_size);
          if (r_bytes == 0)
            break;
          offset += r_bytes;
          fail_if(r_bytes == -1);
          w_bytes = write(STDOUT_FILENO, buffer, (size_t) r_bytes);
          check_io(w_bytes, r_bytes);
          rc = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, 0, offset);
          fail_if(rc != 0);
        }
        goto done;
      }
      else
#else
      errno = ENOTSUP;
#endif
      {
        show_error(filename);
        if (opt_punch > 1)
        {
          fprintf(stderr, "hungrycat: %s: fallocate() failed\n", filename);
          close(fd);
          return 1;
        }
        else
          fprintf(stderr, "hungrycat: %s: fallocate() failed; falling back to ftruncate()\n", filename);
      }
    }
    offset = (n_blocks - i - 1) * block_size;
    r_bytes = pread(fd, buffer, block_size, offset);
    check_io(r_bytes, (i == 0 ? tail_size : block_size));
    w_bytes = pwrite(fd, buffer, (size_t) r_bytes, i * block_size);
    check_io(r_bytes, w_bytes);
    rc = ftruncate(fd, offset);
    fail_if(rc == -1);
  }

  if ((n_blocks & 1) == 1)
  {
    r_bytes = read(fd, buffer, block_size);
    check_io(r_bytes, block_size);
    w_bytes = write(STDOUT_FILENO, buffer, block_size);
    check_io(w_bytes, block_size);
    rc = ftruncate(fd, (n_blocks / 2) * block_size);
    fail_if(rc == -1);
  }

  for (off_t i = (n_blocks / 2) - 1; i > 0; i--)
  {
    r_bytes = pread(fd, buffer, block_size, i * block_size);
    check_io(r_bytes, block_size);
    w_bytes = write(STDOUT_FILENO, buffer, block_size);
    check_io(w_bytes, block_size);
    rc = ftruncate(fd, i * block_size);
    fail_if(rc == -1);
  }

  assert(n_blocks > 0);
  r_bytes = pread(fd, buffer, tail_size, 0);
  check_io(r_bytes, tail_size);
  w_bytes = write(STDOUT_FILENO, buffer, (size_t) r_bytes);
  check_io(w_bytes, r_bytes);

done:
  rc = unlink(filename);
  fail_if(rc == -1);
  rc = close(fd);
  {
    const int fd = -1;
    fail_if(rc == -1);
  }
  return 0;

#undef fail_if

}
Ejemplo n.º 25
0
int main(int argc, char *argv[])
{
    int i;
    FILE *fp;
    int fd;
    char *path = NULL;
    size_t off = 0, len = 0;
    char optchr;
    enum EnumMode mode = EnumModePosix;

    while (-1 != (optchr = getopt(argc, argv, "plLh"))) {
        switch (optchr) {
            case EnumModePosix:
            case EnumModeLinux:
            case EnumModeLinuxWithFlag:
                mode = optchr;
                break;

            case 'h':
            default:
                printUsage();
        }
    }

    for (i = optind; i < argc; ++i) {
        if (NULL == path)
            path = argv[i];
        else if ( ! len)
            len = myAtoi(argv[i]);
        else if ( ! off)
            off = myAtoi(argv[i]);
    }

    if (NULL == path)
        printUsage();

    if (0 == len)
        len = (size_t)100 * 1024 * 1024;

    fp = fopen(path, "w");
    if (NULL == fp)
        myPerror("fopen", 42);
    fd = fileno(fp);

    if (EnumModePosix == mode) {
        const int rc = posix_fallocate(fd, off, len);
        if (RC_OK != rc) {
            char buf[BUFLEN];
            fprintf(stderr, "posix_fallocate: %s", strerror_r(rc, buf, sizeof buf));
            exit(40);
        }
    } else {
        const int flag = (EnumModeLinuxWithFlag == mode ? FALLOC_FL_KEEP_SIZE : 0);
        if (RC_NG == fallocate(fd, flag, off, len))
            myPerror("fallocate", 44);
    }

    fclose(fp);

    return 0;
}