Exemple #1
0
int
main(int argc, char *argv[])
{
	int fd;
	char *dest;
	char *src;
	struct stat stbuf;

	START(argc, argv, "pmem_memcpy");

	if (argc != 5)
		FATAL("usage: %s file srcoff destoff length", argv[0]);

	fd = OPEN(argv[1], O_RDWR);
	int dest_off = atoi(argv[2]);
	int src_off = atoi(argv[3]);
	size_t bytes = strtoul(argv[4], NULL, 0);

	FSTAT(fd, &stbuf);

	/* src > dst */
	dest = pmem_map(fd);
	if (dest == NULL)
		FATAL("!could not map file: %s", argv[1]);

	src = MMAP(dest + stbuf.st_size, stbuf.st_size, PROT_READ|PROT_WRITE,
		MAP_SHARED|MAP_ANONYMOUS, -1, 0);
	/*
	 * Its very unlikely that src would not be > dest. pmem_map
	 * chooses the first unused address >= 1TB, large
	 * enough to hold the give range, and 1GB aligned. If the
	 * addresses did not get swapped to allow src > dst, log error
	 * and allow test to continue.
	 */
	if (src <= dest) {
		swap_mappings(&dest, &src, stbuf.st_size, fd);
		if (src <= dest)
			ERR("cannot map files in memory order");
	}

	memset(dest, 0, (2 * bytes));
	memset(src, 0, (2 * bytes));

	do_memcpy(fd, dest, dest_off, src, src_off, bytes, argv[1]);

	/* dest > src */
	swap_mappings(&dest, &src, stbuf.st_size, fd);

	if (dest <= src) {
		ERR("cannot map files in memory order");
	}

	do_memcpy(fd, dest, dest_off, src, src_off, bytes, argv[1]);
	MUNMAP(dest, stbuf.st_size);
	MUNMAP(src, stbuf.st_size);

	CLOSE(fd);

	DONE(NULL);
}
Exemple #2
0
int
main(int argc, char *argv[])
{
	int srcfd;
	int dstfd;
	struct stat stbuf;
	char *pmemaddr;

	if (argc != 3) {
		fprintf(stderr, "usage: %s src-file dst-file\n", argv[0]);
		exit(1);
	}

	/* open src-file */
	if ((srcfd = open(argv[1], O_RDONLY)) < 0) {
		perror(argv[1]);
		exit(1);
	}

	/* create a pmem file */
	if ((dstfd = open(argv[2], O_CREAT|O_EXCL|O_RDWR, 0666)) < 0) {
		perror(argv[2]);
		exit(1);
	}

	/* find the size of the src-file */
	if (fstat(srcfd, &stbuf) < 0) {
		perror("fstat");
		exit(1);
	}

	/* allocate the pmem */
	if ((errno = posix_fallocate(dstfd, 0, stbuf.st_size)) != 0) {
		perror("posix_fallocate");
		exit(1);
	}

	/* memory map it */
	if ((pmemaddr = pmem_map(dstfd)) == NULL) {
		perror("pmem_map");
		exit(1);
	}
	close(dstfd);

	/* determine if range is true pmem, call appropriate copy routine */
	if (pmem_is_pmem(pmemaddr, stbuf.st_size))
		do_copy_to_pmem(pmemaddr, srcfd, stbuf.st_size);
	else
		do_copy_to_non_pmem(pmemaddr, srcfd, stbuf.st_size);

	close(srcfd);

	exit(0);
}
int
main(int argc, char *argv[])
{
	int fd;
	struct stat stbuf;
	char *dest;

	START(argc, argv, "pmem_valgr_simple");

	if (argc != 4)
		FATAL("usage: %s file offset length", argv[0]);

	fd = OPEN(argv[1], O_RDWR);
	int dest_off = atoi(argv[2]);
	size_t bytes = strtoul(argv[3], NULL, 0);

	FSTAT(fd, &stbuf);

	dest = pmem_map(fd);
	if (dest == NULL)
		FATAL("!Could not mmap %s\n", argv[1]);

	/* these will not be made persistent */
	*(int *)dest = 4;

	/* this will be made persistent */
	uint64_t *tmp64dst = (void *)((uintptr_t)dest + 4096);
	*tmp64dst = 50;

	if (pmem_is_pmem(dest, sizeof (*tmp64dst))) {
		pmem_persist(tmp64dst, sizeof (*tmp64dst));
	} else {
		pmem_msync(tmp64dst, sizeof (*tmp64dst));
	}

	uint16_t *tmp16dst = (void *)((uintptr_t)dest + 1024);
	*tmp16dst = 21;
	/* will appear as flushed in valgrind log */
	pmem_flush(tmp16dst, sizeof (*tmp16dst));

	/* shows strange behavior of memset in some cases */
	memset(dest + dest_off, 0, bytes);

	pmem_unmap(dest, stbuf.st_size);

	CLOSE(fd);

	DONE(NULL);
}
Exemple #4
0
PMEMobjpool *
pmemobj_open_mock(const char *fname)
{
	int fd = open(fname, O_RDWR);
	if (fd == -1) {
		OUT("!%s: open", fname);

		return NULL;
	}

	struct stat stbuf;
	if (fstat(fd, &stbuf) < 0) {
		OUT("!fstat");

		return NULL;
	}

	ASSERT(stbuf.st_size > PMEMOBJ_POOL_HDR_SIZE);

	void *addr = pmem_map(fd);
	if (!addr) {
		OUT("!%s: pmem_map", fname);

		return NULL;
	}

	close(fd);

	PMEMobjpool *pop = (PMEMobjpool *)addr;
	VALGRIND_REMOVE_PMEM_MAPPING(addr + sizeof (pop->hdr), 4096);
	pop->addr = addr;
	pop->size = stbuf.st_size;
	pop->is_pmem = pmem_is_pmem(addr, stbuf.st_size);
	pop->rdonly = 0;

	if (pop->is_pmem) {
		pop->persist = pmem_persist;
		pop->flush = pmem_flush;
		pop->drain = pmem_drain;
	} else {
		pop->persist = (persist_fn)pmem_msync;
		pop->flush = (persist_fn)pmem_msync;
		pop->drain = pmem_drain_nop;
	}

	return pop;
}
Exemple #5
0
/*
 * pmem_memcpy_init -- benchmark initialization
 *
 * Parses command line arguments, allocates persistent memory, and maps it.
 */
static int
pmem_memcpy_init(struct benchmark *bench, struct benchmark_args *args)
{
	assert(bench != NULL);
	assert(args != NULL);
	int ret = 0;

	struct pmem_bench *pmb = malloc(sizeof (struct pmem_bench));
	assert(pmb != NULL);

	pmb->pargs = args->opts;
	assert(pmb->pargs != NULL);

	pmb->pargs->chunk_size = args->dsize;

	enum operation_type op_type;
	/*
	 * Assign file and buffer size depending on the operation type
	 * (READ from PMEM or WRITE to PMEM)
	 */
	if (assign_size(pmb, args, &op_type) != 0) {
		ret = -1;
		goto err_free_pmb;
	}

	if ((errno = posix_memalign(
		(void **) &pmb->buf, FLUSH_ALIGN, pmb->bsize)) != 0) {
		perror("posix_memalign");
		ret = -1;
		goto err_free_pmb;
	}

	pmb->n_rand_offsets = args->n_ops_per_thread * args->n_threads;
	pmb->rand_offsets = malloc(pmb->n_rand_offsets *
			sizeof (*pmb->rand_offsets));

	for (size_t i = 0; i < pmb->n_rand_offsets; ++i)
		pmb->rand_offsets[i] = rand() % args->n_ops_per_thread;


	/* create a pmem file */
	pmb->fd = open(args->fname, O_CREAT|O_EXCL|O_RDWR, args->fmode);
	if (pmb->fd == -1) {
		perror(args->fname);
		ret = -1;
		goto err_free_buf;
	}

	/* allocate the pmem */
	if ((errno = posix_fallocate(pmb->fd, 0, pmb->fsize)) != 0) {
		perror("posix_fallocate");
		ret = -1;
		goto err_close_file;
	}
	/* memory map it */
	if ((pmb->pmem_addr = pmem_map(pmb->fd)) == NULL) {
		perror("pmem_map");
		ret = -1;
		goto err_close_file;
	}


	if (op_type == OP_TYPE_READ) {
		pmb->src_addr = pmb->pmem_addr;
		pmb->dest_addr = pmb->buf;
	} else {
		pmb->src_addr = pmb->buf;
		pmb->dest_addr = pmb->pmem_addr;
	}

	/* set proper func_src() and func_dest() depending on benchmark args */
	if ((pmb->func_src = assign_mode_func(pmb->pargs->src_mode)) == NULL) {
		fprintf(stderr, "wrong src_mode parameter -- '%s'",
						pmb->pargs->src_mode);
		ret = -1;
		goto err_unmap;
	}

	if ((pmb->func_dest = assign_mode_func(pmb->pargs->dest_mode))
								== NULL) {
		fprintf(stderr, "wrong dest_mode parameter -- '%s'",
						pmb->pargs->dest_mode);
		ret = -1;
		goto err_unmap;
	}

	close(pmb->fd);

	if (pmb->pargs->memcpy) {
		pmb->func_op = pmb->pargs->persist ?
					libc_memcpy_persist : libc_memcpy;
	} else {
		pmb->func_op = pmb->pargs->persist ?
			libpmem_memcpy_persist : libpmem_memcpy_nodrain;
	}

	pmembench_set_priv(bench, pmb);

	return 0;
err_unmap:
	munmap(pmb->pmem_addr, pmb->fsize);
err_close_file:
	close(pmb->fd);
err_free_buf:
	free(pmb->buf);
err_free_pmb:
	free(pmb);

	return ret;
}
Exemple #6
0
void set_meminfo_ptr(meminfo_page_t** firstPage)
{
	meminfo_store = (meminfo_page_t*)(((void*)*firstPage));
	memzero((void*)KMEM_PMEM_DIR_LOC, KMEM_PMEM_DIR_SIZE);
	pmem_map();
}
Exemple #7
0
int
main(int argc, char *argv[])
{
	int srcfd;
	int dstfd;
	char buf[BUF_LEN];
	char *pmemaddr;
	int is_pmem;
	int cc;

	if (argc != 3) {
		fprintf(stderr, "usage: %s src-file dst-file\n", argv[0]);
		exit(1);
	}

	/* open src-file */
	if ((srcfd = open(argv[1], O_RDONLY)) < 0) {
		perror(argv[1]);
		exit(1);
	}

	/* create a pmem file */
	if ((dstfd = open(argv[2], O_CREAT|O_EXCL|O_RDWR, 0666)) < 0) {
		perror(argv[2]);
		exit(1);
	}

	/* allocate the pmem */
	if ((errno = posix_fallocate(dstfd, 0, BUF_LEN)) != 0) {
		perror("posix_fallocate");
		exit(1);
	}

	/* memory map it */
	if ((pmemaddr = pmem_map(dstfd)) == NULL) {
		perror("pmem_map");
		exit(1);
	}
	close(dstfd);

	/* determine if range is true pmem */
	is_pmem = pmem_is_pmem(pmemaddr, BUF_LEN);

	/* read up to BUF_LEN from srcfd */
	if ((cc = read(srcfd, buf, BUF_LEN)) < 0) {
		perror("read");
		exit(1);
	}

	/* write it to the pmem */
	if (is_pmem) {
		pmem_memcpy(pmemaddr, buf, cc);
	} else {
		memcpy(pmemaddr, buf, cc);
		pmem_msync(pmemaddr, cc);
	}

	close(srcfd);

	exit(0);
}
Exemple #8
0
int
main(int argc, char *argv[])
{
	char *path;
	size_t data_size, pool_size;
	int iterations;
	int is_pmem;
	int fd;
	uint8_t *pool;
	double exec_time_pmem_persist, exec_time_pmem_msync;

	if (argc < 4) {
		printf("Usage %s <file_name> <data_size> <iterations>\n",
			argv[0]);
		return 0;
	}

	path = argv[1];
	data_size = atoi(argv[2]);
	iterations = atoi(argv[3]);
	pool_size = data_size * iterations;

	if ((fd = open(path, O_RDWR|O_CREAT|O_EXCL, S_IRWXU)) < 0) {
		perror("open");
		return -1;
	}

	if ((errno = posix_fallocate(fd, 0, pool_size)) != 0) {
		perror("posix_fallocate");
		goto err;
	}

	if ((pool = pmem_map(fd)) == NULL) {
		perror("pmem_map");
		goto err;
	}
	close(fd);

	/* check if range is true pmem */
	is_pmem = pmem_is_pmem(pool, pool_size);
	if (is_pmem) {
		/* benchmarking pmem_persist */
		exec_time_pmem_persist = benchmark_func(pmem_persist, pool,
						data_size, iterations);
	} else {
		fprintf(stderr, "Notice: pmem_persist is not benchmarked,"
			" because given file (%s) is not in Persistent Memory"
			" aware file system.\n", path);
		exec_time_pmem_persist = 0.0;
	}

	/* benchmarking pmem_msync */
	exec_time_pmem_msync = benchmark_func((persist_fn)pmem_msync, pool,
						data_size, iterations);

	printf("%zu;%e;%zu;%e;%zu;%e\n",
		data_size, exec_time_pmem_persist,
		data_size, exec_time_pmem_msync,
		data_size, exec_time_pmem_persist / exec_time_pmem_msync);

	return 0;

err:
	close(fd);
	unlink(path);
	return -1;
}
Exemple #9
0
int
main(int argc, char *argv[])
{
	int opt;
	int iflag = 0;
	unsigned long icount;
	const char *path;
	struct stat stbuf;
	size_t size;
	int fd;
	char *pmaddr;

	Myname = argv[0];
	while ((opt = getopt(argc, argv, "FMdi:")) != -1) {
		switch (opt) {
		case 'F':
			pmem_fit_mode();
			break;

		case 'M':
			pmem_msync_mode();
			break;

		case 'd':
			Debug++;
			break;

		case 'i':
			iflag++;
			icount = strtoul(optarg, NULL, 10);
			break;

		default:
			USAGE(NULL);
		}
	}

	if (optind >= argc)
		USAGE("No path given");
	path = argv[optind++];

	if (stat(path, &stbuf) < 0) {
		/*
		 * file didn't exist, create it with DEFAULT_SIZE
		 */
		if ((fd = open(path, O_CREAT|O_RDWR, 0666)) < 0)
			FATALSYS("can't create %s", path);

		if ((errno = posix_fallocate(fd, 0, DEFAULT_SIZE)) != 0)
			FATALSYS("posix_fallocate");

		size = DEFAULT_SIZE;
	} else {
		/*
		 * file exists, just open it
		 */
		if ((fd = open(path, O_RDWR)) < 0)
			FATALSYS("open %s", path);

		size = stbuf.st_size;
	}

	/*
	 * map the file into our address space.
	 */
	if ((pmaddr = pmem_map(fd, size)) == NULL)
		FATALSYS("pmem_map");

	if (optind < argc) {	/* strings supplied as arguments? */
		int i;
		char *ptr = pmaddr;

		if (iflag)
			icount_start(icount);	/* start instruction count */

		for (i = optind; i < argc; i++) {
			size_t len = strlen(argv[i]) + 1; /* includes '\0' */

			if (len > size)
				FATAL("no more room for %d-byte string", len);

			/* store to Persistent Memory */
			strcpy(ptr, argv[i]);

			/* make that change durable */
			pmem_persist(ptr, len, 0);

			ptr += len;
			size -= len;
		}

		if (iflag) {
			icount_stop();		/* end instruction count */

			printf("Total instruction count: %lu\n",
					icount_total());
		}
	} else {
		char *ptr = pmaddr;
		char *sep = "";

		/*
		 * dump out all the strings we find in Persistent Memory
		 */
		while (ptr < &pmaddr[size]) {

			/* load from Persistent Memory */
			if (isprint(*ptr)) {
				putc(*ptr, stdout);
				sep = "\n";
			} else if (*ptr == '\0') {
				fputs(sep, stdout);
				sep = "";
			}

			ptr++;
		}
	}

	exit(0);
}
Exemple #10
0
int
main(int argc, char *argv[])
{
	int fd;
	struct stat stbuf;
	void *dest;
	void *src;
	off_t dest_off = 0;
	off_t src_off = 0;
	uint64_t bytes = 0;
	int who = 0;
	off_t overlap = 0;

	START(argc, argv, "pmem_memmove");

	fd = OPEN(argv[1], O_RDWR);
	FSTAT(fd, &stbuf);

	if (argc < 3)
		USAGE();

	for (int arg = 2; arg < argc; arg++) {
		if (strchr("dsboS",
		    argv[arg][0]) == NULL || argv[arg][1] != ':')
			FATAL("op must be d: or s: or b: or o: or S:");

		off_t val = strtoul(&argv[arg][2], NULL, 0);

		switch (argv[arg][0]) {
		case 'd':
			if (val <= 0)
				FATAL("bad offset (%lu) with d: option", val);
			dest_off = val;
			break;

		case 's':
			if (val <= 0)
				FATAL("bad offset (%lu) with s: option", val);
			src_off = val;
			break;

		case 'b':
			if (val <= 0)
				FATAL("bad length (%lu) with b: option", val);
			bytes = val;
			break;

		case 'o':
			if (val != 1 && val != 2)
				FATAL("bad val (%lu) with o: option", val);
			who = (int)val;
			break;

		case 'S':
			overlap = val;
			break;
		}
	}

	if (who == 0 && overlap != 0)
		USAGE();

	/* for overlap the src and dest must be created differently */
	if (who == 0) {
		/* src > dest */
		dest = pmem_map(fd);
		if (dest == NULL)
			FATAL("!could not mmap dest file %s", argv[1]);

		src = MMAP(dest + stbuf.st_size, stbuf.st_size,
			PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
			-1, 0);
		/*
		 * Its very unlikely that src would not be > dest. pmem_map
		 * chooses the first unused address >= 1TB, large
		 * enough to hold the give range, and 1GB aligned. Log
		 * the error if the mapped addresses cannot be swapped
		 * but allow the test to continue.
		 */
		if (src <= dest) {
			swap_mappings(&dest, &src, stbuf.st_size, fd);
			if (src <= dest)
				ERR("cannot map files in memory order");
		}

		do_memmove(fd, dest, src, argv[1], dest_off, src_off,
			0, bytes);

		/* dest > src */
		swap_mappings(&dest, &src, stbuf.st_size, fd);

		if (dest <= src)
			ERR("cannot map files in memory order");

		do_memmove(fd, dest, src, argv[1], dest_off, src_off, 0,
			bytes);
		MUNMAP(dest, stbuf.st_size);
		MUNMAP(src, stbuf.st_size);
	} else if (who == 1) {
		/* src overlap with dest */
		dest = pmem_map(fd);
		if (dest == NULL)
			FATAL("!Could not mmap %s: \n", argv[1]);

		src = dest + overlap;
		memset(dest, 0, bytes);
		do_memmove(fd, dest, src, argv[1], dest_off, src_off,
			overlap, bytes);
		MUNMAP(dest, stbuf.st_size);
	} else {
		/* dest overlap with src */
		dest = pmem_map(fd);
		if (dest == NULL) {
			FATAL("!Could not mmap %s: \n", argv[1]);
		}
		src = dest;
		dest = src + overlap;
		memset(src, 0, bytes);
		do_memmove(fd, dest, src, argv[1], dest_off, src_off,
			overlap, bytes);
		MUNMAP(src, stbuf.st_size);
	}

	CLOSE(fd);

	DONE(NULL);
}
Exemple #11
0
// pmemalloc_init -- setup a Persistent Memory pool for use
void *pmemalloc_init(const char *path, size_t size) {
  int err;
  int fd = -1;
  struct stat stbuf;

  if (pthread_mutex_init(&pmp_mutex, NULL) != 0)
  {
      printf("\n mutex init failed\n");
      exit(0);
  }

  DEBUG("path=%s size=0x%lx", path, size);
  pmem_orig_size = size;

  if (stat(path, &stbuf) < 0) {
    struct clump cl;
    init_clump(&cl);
    struct pool_header hdr; 
    init_pool_header(&hdr);
    size_t lastclumpoff;

    if (errno != ENOENT)
      goto out;

    /*
     * file didn't exist, we're creating a new memory pool
     */
    if (size < PMEM_MIN_POOL_SIZE) {
      DEBUG("size %lu too small (must be at least %lu)", size,
          PMEM_MIN_POOL_SIZE);
      errno = EINVAL;
      goto out;
    }

    ASSERTeq(sizeof(cl), PMEM_CHUNK_SIZE);ASSERTeq(sizeof(hdr), PMEM_PAGE_SIZE);

    if ((fd = open(path, O_CREAT | O_RDWR, 0666)) < 0)
      goto out;

    if ((errno = posix_fallocate(fd, 0, size)) != 0)
      goto out;

    /*
     * location of last clump is calculated by rounding the file
     * size down to a multiple of 64, and then subtracting off
     * another 64 to hold the struct clump.  the last clump is
     * indicated by a size of zero (so no write is necessary
     * here since the file is initially zeros.
     */
    lastclumpoff = (size & ~(PMEM_CHUNK_SIZE - 1)) - PMEM_CHUNK_SIZE;

    /*
     * create the first clump to cover the entire pool
     */
    cl.size = lastclumpoff - PMEM_CLUMP_OFFSET;
    if (pwrite(fd, &cl, sizeof(cl), PMEM_CLUMP_OFFSET) < 0){
        DEBUG("[0x%lx] created clump, size 0x%lx", PMEM_CLUMP_OFFSET, cl.size);
        goto out;
    }
    /*
     * write the pool header
     */
    strcpy(hdr.signature, PMEM_SIGNATURE);
    hdr.totalsize = size;
    if (pwrite(fd, &hdr, sizeof(hdr), PMEM_HDR_OFFSET) < 0)
      goto out;

    if (fsync(fd) < 0)
      goto out;

  } else {

    if ((fd = open(path, O_RDWR)) < 0)
      goto out;

    size = stbuf.st_size;
  }

  /*
   * map the file
   */
  if ((pmp = pmem_map(fd, size)) == NULL) {
    DEBUG("fd : %d size : %lu \n", fd, size);
    perror("mapping failed ");
    goto out;
  }

  return pmp;

  out: err = errno;
  if (fd != -1)
    close(fd);
  errno = err;
  return NULL;
}
Exemple #12
0
int
main(int argc, char *argv[])
{
    START(argc, argv, "pmem_map");

    if (argc != 2)
        FATAL("usage: %s file", argv[0]);

    int fd;
    void *addr;

    fd = OPEN(argv[1], O_RDWR);

    struct stat stbuf;
    FSTAT(fd, &stbuf);

    char pat[CHECK_BYTES];
    char buf[CHECK_BYTES];

    addr = pmem_map(fd);
    if (addr == NULL) {
        OUT("!pmem_map");
        goto err;
    }

    /* write some pattern to the file */
    memset(pat, 0x5A, CHECK_BYTES);
    WRITE(fd, pat, CHECK_BYTES);


    if (memcmp(pat, addr, CHECK_BYTES))
        OUT("%s: first %d bytes do not match",
            argv[1], CHECK_BYTES);

    /* fill up mapped region with new pattern */
    memset(pat, 0xA5, CHECK_BYTES);
    memcpy(addr, pat, CHECK_BYTES);

    MUNMAP(addr, stbuf.st_size);

    LSEEK(fd, (off_t)0, SEEK_SET);
    if (READ(fd, buf, CHECK_BYTES) == CHECK_BYTES) {
        if (memcmp(pat, buf, CHECK_BYTES))
            OUT("%s: first %d bytes do not match",
                argv[1], CHECK_BYTES);
    }

    CLOSE(fd);

    /* re-open the file with read-only access */
    fd = OPEN(argv[1], O_RDONLY);

    addr = pmem_map(fd);
    if (addr != NULL) {
        MUNMAP(addr, stbuf.st_size);
        OUT("expected pmem_map failure");
    }

err:
    CLOSE(fd);

    DONE(NULL);
}
Exemple #13
0
/*
 * pmemalloc_init -- setup a Persistent Memory pool for use
 *
 * Inputs:
 *	path -- path to the file which will contain the memory pool
 *
 *	        If the file doesn't exist, it is created.  If it exists,
 *	        the state of the memory pool is initialized from the file.
 *
 *	size -- size of the memory pool in bytes
 *
 *		The size is only used when creating the memory pool
 *		the first time (the file created will be extended to
 *		that size).  The smallest size allowed is 1 meg.  The
 *		largest size allowed is whatever the underlaying file
 *		system allows as a max file size.
 *
 * Outputs:
 * 	An opaque memory pool handle is returned on success.  That
 * 	handle must be passed in to most of the other pmem routines.
 *
 * 	On error, NULL is returned and errno is set.
 *
 * This function must be called before any other pmem functions.
 */
void *
pmemalloc_init(const char *path, size_t size)
{
	void *pmp;
	int err;
	int fd = -1;
	struct stat stbuf;

	DEBUG("path=%s size=0x%lx", path, size);

	if (stat(path, &stbuf) < 0) {
		struct clump cl = { 0 };
		struct pool_header hdr = { 0 };
		size_t lastclumpoff;

		if (errno != ENOENT)
			goto out;

		/*
		 * file didn't exist, we're creating a new memory pool
		 */
		if (size < PMEM_MIN_POOL_SIZE) {
			DEBUG("size %lu too small (must be at least %lu)",
					size, PMEM_MIN_POOL_SIZE);
			errno = EINVAL;
			goto out;
		}

		ASSERTeq(sizeof(cl), PMEM_CHUNK_SIZE);
		ASSERTeq(sizeof(hdr), PMEM_PAGE_SIZE);

		if ((fd = open(path, O_CREAT|O_RDWR, 0666)) < 0)
			goto out;

		if ((errno = posix_fallocate(fd, 0, size)) != 0)
			goto out;

		/*
		 * location of last clump is calculated by rounding the file
		 * size down to a multiple of 64, and then subtracting off
		 * another 64 to hold the struct clump.  the last clump is
		 * indicated by a size of zero (so no write is necessary
		 * here since the file is initially zeros.
		 */
		lastclumpoff =
			(size & ~(PMEM_CHUNK_SIZE - 1)) - PMEM_CHUNK_SIZE;

		/*
		 * create the first clump to cover the entire pool
		 */
		cl.size = lastclumpoff - PMEM_CLUMP_OFFSET;
		if (pwrite(fd, &cl, sizeof(cl), PMEM_CLUMP_OFFSET) < 0)
			goto out;
		DEBUG("[0x%lx] created clump, size 0x%lx",
				PMEM_CLUMP_OFFSET, cl.size);

		/*
		 * write the pool header
		 */
		strcpy(hdr.signature, PMEM_SIGNATURE);
		hdr.totalsize = size;
        pthread_mutex_init( &hdr.pool_lock, NULL );
        pthread_mutex_init( &hdr.activation_lock, NULL );
		if (pwrite(fd, &hdr, sizeof(hdr), PMEM_HDR_OFFSET) < 0)
			goto out;

		if (fsync(fd) < 0)
			goto out;

	} else {
		if ((fd = open(path, O_RDWR)) < 0)
			goto out;
		size = stbuf.st_size;

		/* XXX handle recovery case 1 described below */
	}

	/*
	 * map the file
	 */
	if ((pmp = pmem_map(fd, size)) == NULL)
		goto out;

	/*
	 * scan pool for recovery work, five kinds:
	 * 	1. pmem pool file sisn't even fully setup
	 * 	2. RESERVED clumps that need to be freed
	 * 	3. ACTIVATING clumps that need to be ACTIVE
	 * 	4. FREEING clumps that need to be freed
	 * 	5. adjacent free clumps that need to be coalesced
	 */
	pmemalloc_recover(pmp);
	pmemalloc_coalesce_free(pmp);

	DEBUG("return pmp 0x%lx", pmp);
	return pmp;

out:
	err = errno;
	if (fd != -1)
		close(fd);
	errno = err;
	return NULL;
}
StorageManager::StorageManager()
: data_file_address(nullptr),
  is_pmem(false),
  data_file_len(0),
  data_file_offset(0) {
  // Check if we need a data pool
  if (IsBasedOnWriteAheadLogging(peloton_logging_mode) == true ||
      peloton_logging_mode == LOGGING_TYPE_INVALID) {
    return;
  }

  int data_fd;
  std::string data_file_name;
  struct stat data_stat;

  // Initialize file size
  if (peloton_data_file_size != 0)
    data_file_len = peloton_data_file_size * 1024 * 1024;  // MB
  else
    data_file_len = DATA_FILE_LEN;

  // Check for relevant file system
  bool found_file_system = false;

  switch (peloton_logging_mode) {
    // Check for NVM FS for data
    case LOGGING_TYPE_NVM_NVM:
    case LOGGING_TYPE_NVM_HDD:
    case LOGGING_TYPE_NVM_SSD: {
      int status = stat(NVM_DIR, &data_stat);
      if (status == 0 && S_ISDIR(data_stat.st_mode)) {
        data_file_name = std::string(NVM_DIR) + std::string(DATA_FILE_NAME);
        found_file_system = true;
      }

    } break;

    // Check for SSD FS
    case LOGGING_TYPE_SSD_NVM:
    case LOGGING_TYPE_SSD_SSD:
    case LOGGING_TYPE_SSD_HDD: {
      int status = stat(SSD_DIR, &data_stat);
      if (status == 0 && S_ISDIR(data_stat.st_mode)) {
        data_file_name = std::string(SSD_DIR) + std::string(DATA_FILE_NAME);
        found_file_system = true;
      }

    } break;

    // Check for HDD FS
    case LOGGING_TYPE_HDD_NVM:
    case LOGGING_TYPE_HDD_SSD:
    case LOGGING_TYPE_HDD_HDD: {
      int status = stat(HDD_DIR, &data_stat);
      if (status == 0 && S_ISDIR(data_stat.st_mode)) {
        data_file_name = std::string(HDD_DIR) + std::string(DATA_FILE_NAME);
        found_file_system = true;
      }

    } break;

    default:
      break;
  }

  // Fallback to tmp directory if needed
  if (found_file_system == false) {
    int status = stat(TMP_DIR, &data_stat);
    if (status == 0 && S_ISDIR(data_stat.st_mode)) {
      data_file_name = std::string(TMP_DIR) + std::string(DATA_FILE_NAME);
    }
    else {
      throw Exception("Could not find temp directory : " + std::string(TMP_DIR));
    }
  }

  LOG_INFO("DATA DIR :: %s ", data_file_name.c_str());

  // TODO:
  std::cout << "Data path :: " << data_file_name << "\n";

  // Create a data file
  if ((data_fd = open(data_file_name.c_str(), O_CREAT | O_RDWR, 0666)) < 0) {
    perror(data_file_name.c_str());
    exit(EXIT_FAILURE);
  }

  // Allocate the data file
  if ((errno = posix_fallocate(data_fd, 0, data_file_len)) != 0) {
    perror("posix_fallocate");
    exit(EXIT_FAILURE);
  }

  // memory map the data file
  if ((data_file_address = reinterpret_cast<char *>(pmem_map(data_fd))) ==
      NULL) {
    perror("pmem_map");
    exit(EXIT_FAILURE);
  }

  // true only if the entire range [addr, addr+len) consists of persistent
  // memory
  is_pmem = pmem_is_pmem(data_file_address, data_file_len);

  // close the pmem file -- it will remain mapped
  close(data_fd);
}
Exemple #15
0
int
main(int argc, char *argv[])
{
	START(argc, argv, "pmem_map");

	if (argc != 2)
		FATAL("usage: %s file", argv[0]);

	/* arrange to catch SEGV */
	struct sigaction v;
	sigemptyset(&v.sa_mask);
	v.sa_flags = 0;
	v.sa_handler = signal_handler;
	SIGACTION(SIGSEGV, &v, NULL);

	int fd;
	void *addr;

	fd = OPEN(argv[1], O_RDWR);

	struct stat stbuf;
	FSTAT(fd, &stbuf);

	char pat[CHECK_BYTES];
	char buf[CHECK_BYTES];

	addr = pmem_map(fd);
	if (addr == NULL) {
		OUT("!pmem_map");
		goto err;
	}

	/* write some pattern to the file */
	memset(pat, 0x5A, CHECK_BYTES);
	WRITE(fd, pat, CHECK_BYTES);


	if (memcmp(pat, addr, CHECK_BYTES))
		OUT("%s: first %d bytes do not match",
			argv[1], CHECK_BYTES);

	/* fill up mapped region with new pattern */
	memset(pat, 0xA5, CHECK_BYTES);
	memcpy(addr, pat, CHECK_BYTES);

	pmem_unmap(addr, stbuf.st_size);

	if (!sigsetjmp(Jmp, 1)) {
		/* same memcpy from above should now fail */
		memcpy(addr, pat, CHECK_BYTES);
	} else {
		OUT("unmap successful");
	}

	LSEEK(fd, (off_t)0, SEEK_SET);
	if (READ(fd, buf, CHECK_BYTES) == CHECK_BYTES) {
		if (memcmp(pat, buf, CHECK_BYTES))
			OUT("%s: first %d bytes do not match",
				argv[1], CHECK_BYTES);
	}

	CLOSE(fd);

	/* re-open the file with read-only access */
	fd = OPEN(argv[1], O_RDONLY);

	addr = pmem_map(fd);
	if (addr != NULL) {
		MUNMAP(addr, stbuf.st_size);
		OUT("expected pmem_map failure");
	}

err:
	CLOSE(fd);

	DONE(NULL);
}