Beispiel #1
0
/*
 * pmemlog_persist -- (internal) persist data, then metadata
 *
 * On entry, the write lock should be held.
 */
static void
pmemlog_persist(PMEMlogpool *plp, uint64_t new_write_offset)
{
    uint64_t old_write_offset = le64toh(plp->write_offset);
    size_t length = new_write_offset - old_write_offset;

    /* unprotect the log space range (debug version only) */
    RANGE_RW(plp->addr + old_write_offset, length);

    /* persist the data */
    if (plp->is_pmem)
        pmem_drain(); /* data already flushed */
    else
        pmem_msync(plp->addr + old_write_offset, length);

    /* protect the log space range (debug version only) */
    RANGE_RO(plp->addr + old_write_offset, length);

    /* unprotect the pool descriptor (debug version only) */
    RANGE_RW(plp->addr + sizeof (struct pool_hdr), LOG_FORMAT_DATA_ALIGN);

    /* write the metadata */
    plp->write_offset = htole64(new_write_offset);

    /* persist the metadata */
    if (plp->is_pmem)
        pmem_persist(&plp->write_offset, sizeof (plp->write_offset));
    else
        pmem_msync(&plp->write_offset, sizeof (plp->write_offset));

    /* set the write-protection again (debug version only) */
    RANGE_RO(plp->addr + sizeof (struct pool_hdr), LOG_FORMAT_DATA_ALIGN);
}
Beispiel #2
0
/*
 * pmem_persist -- make any cached changes to a range of pmem persistent
 */
void
pmem_persist(void *addr, size_t len)
{
	LOG(15, "addr %p len %zu", addr, len);

	pmem_flush(addr, len);
	pmem_drain();
}
Beispiel #3
0
/*
 * pmem_memset_persist -- memset to pmem
 */
void *
pmem_memset_persist(void *pmemdest, int c, size_t len)
{
	LOG(15, "pmemdest %p c %d len %zu", pmemdest, c, len);

	PMEM_API_START();

	Funcs.memset_nodrain(pmemdest, c, len, 0);
	pmem_drain();

	PMEM_API_END();
	return pmemdest;
}
Beispiel #4
0
/*
 * pmem_memcpy_persist -- memcpy to pmem
 */
void *
pmem_memcpy_persist(void *pmemdest, const void *src, size_t len)
{
	LOG(15, "pmemdest %p src %p len %zu", pmemdest, src, len);

	PMEM_API_START();

	Funcs.memmove_nodrain(pmemdest, src, len, 0);
	pmem_drain();

	PMEM_API_END();
	return pmemdest;
}
Beispiel #5
0
/*
 * nswrite -- (internal) write data to the namespace encapsulating the BTT
 *
 * This routine is provided to btt_init() to allow the btt module to
 * do I/O on the memory pool containing the BTT layout.
 */
static int
nswrite(void *ns, int lane, const void *buf, size_t count, off_t off)
{
	struct pmemblk *pbp = (struct pmemblk *)ns;

	LOG(13, "pbp %p lane %d count %zu off %lld",
			pbp, lane, count, (long long)off);

	if (off + count > pbp->datasize) {
		ERR("offset + count (%lld) past end of data area (%zu)",
				(long long)off + count, pbp->datasize);
		errno = EINVAL;
		return -1;
	}

	void *dest = pbp->data + off;

#ifdef DEBUG
	/* grab debug write lock */
	if ((errno = pthread_mutex_lock(&pbp->write_lock))) {
		ERR("!pthread_mutex_lock");
		return -1;
	}
#endif

	/* unprotect the memory (debug version only) */
	RANGE_RW(dest, count);

	if (pbp->is_pmem)
		pmem_memcpy_nodrain(dest, buf, count);
	else
		memcpy(dest, buf, count);

	/* protect the memory again (debug version only) */
	RANGE_RO(dest, count);

#ifdef DEBUG
	/* release debug write lock */
	if ((errno = pthread_mutex_unlock(&pbp->write_lock)))
		ERR("!pthread_mutex_unlock");
#endif

	if (pbp->is_pmem)
		pmem_drain();
	else
		pmem_msync(dest, count);

	return 0;
}
Beispiel #6
0
Datei: blk.c Projekt: xguo/nvml
/*
 * nswrite -- (internal) write data to the namespace encapsulating the BTT
 *
 * This routine is provided to btt_init() to allow the btt module to
 * do I/O on the memory pool containing the BTT layout.
 */
static int
nswrite(void *ns, unsigned lane, const void *buf, size_t count,
		uint64_t off)
{
	struct pmemblk *pbp = (struct pmemblk *)ns;

	LOG(13, "pbp %p lane %u count %zu off %ju", pbp, lane, count, off);

	if (off + count > pbp->datasize) {
		ERR("offset + count (%zu) past end of data area (%zu)",
				off + count, pbp->datasize);
		errno = EINVAL;
		return -1;
	}

	void *dest = (char *)pbp->data + off;

#ifdef DEBUG
	/* grab debug write lock */
	util_mutex_lock(&pbp->write_lock);
#endif

	/* unprotect the memory (debug version only) */
	RANGE_RW(dest, count);

	if (pbp->is_pmem)
		pmem_memcpy_nodrain(dest, buf, count);
	else
		memcpy(dest, buf, count);

	/* protect the memory again (debug version only) */
	RANGE_RO(dest, count);

#ifdef DEBUG
	/* release debug write lock */
	util_mutex_unlock(&pbp->write_lock);
#endif

	if (pbp->is_pmem)
		pmem_drain();
	else
		pmem_msync(dest, count);

	return 0;
}
Beispiel #7
0
/*
 * os_part_deep_common -- common function to handle both
 * deep_persist and deep_drain part flush cases.
 */
int
os_part_deep_common(struct pool_replica *rep, unsigned partidx, void *addr,
			size_t len, int flush)
{
	LOG(3, "part %p part %d addr %p len %lu flush %d",
		rep, partidx, addr, len, flush);

	if (!rep->is_pmem) {
		/*
		 * In case of part on non-pmem call msync on the range
		 * to deep flush the data. Deep drain is empty as all
		 * data is msynced to persistence.
		 */

		if (!flush)
			return 0;

		if (pmem_msync(addr, len)) {
			LOG(1, "pmem_msync(%p, %lu)", addr, len);
			return -1;
		}
		return 0;
	}

	/* Call deep flush if it was requested */
	if (flush) {
		LOG(15, "pmem_deep_flush addr %p, len %lu", addr, len);
		pmem_deep_flush(addr, len);
	}
	/*
	 * Before deep drain call normal drain to ensure that data
	 * is at least in WPQ.
	 */
	pmem_drain();

	/*
	 * For deep_drain on normal pmem it is enough to
	 * call msync on one page.
	 */
	if (pmem_msync(addr, MIN(Pagesize, len))) {
		LOG(1, "pmem_msync(%p, %lu)", addr, len);
		return -1;
	}
	return 0;
}
Beispiel #8
0
Datei: libpmem.c Projekt: arh/fio
static int fio_libpmem_close_file(struct thread_data *td, struct fio_file *f)
{
	struct fio_libpmem_data *fdd = FILE_ENG_DATA(f);

	dprint(FD_IO,"DEBUG fio_libpmem_close_file\n");
	dprint(FD_IO,"td->o.odirect %d \n",td->o.odirect);

	if (!td->o.odirect) {
		dprint(FD_IO,"pmem_drain\n");
		pmem_drain();
	}

	FILE_SET_ENG_DATA(f, NULL);
	free(fdd);
	fio_file_clear_partial_mmap(f);

	return generic_close_file(td, f);
}
Beispiel #9
0
/*
 * pmem_memcpy --  memcpy to pmem
 */
void *
pmem_memcpy(void *pmemdest, const void *src, size_t len, unsigned flags)
{
	LOG(15, "pmemdest %p src %p len %zu flags 0x%x",
			pmemdest, src, len, flags);

#ifdef DEBUG
	if (flags & ~PMEM_F_MEM_VALID_FLAGS)
		ERR("invalid flags 0x%x", flags);
#endif
	PMEM_API_START();
	Funcs.memmove_nodrain(pmemdest, src, len, flags & ~PMEM_F_MEM_NODRAIN);

	if ((flags & (PMEM_F_MEM_NODRAIN | PMEM_F_MEM_NOFLUSH)) == 0)
		pmem_drain();

	PMEM_API_END();
	return pmemdest;
}
Beispiel #10
0
/*
 * do_copy_to_pmem -- copy to pmem, postponing drain step until the end
 */
void
do_copy_to_pmem(char *pmemaddr, int srcfd, off_t len)
{
	char buf[BUF_LEN];
	int cc;

	/* copy the file, saving the last flush step to the end */
	while ((cc = read(srcfd, buf, BUF_LEN)) > 0) {
		pmem_memcpy_nodrain(pmemaddr, buf, cc);
		pmemaddr += cc;
	}

	if (cc < 0) {
		perror("read");
		exit(1);
	}

	/* perform final flush step */
	pmem_drain();
}