Skip to content
This repository was archived by the owner on May 21, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion LINUX_PMEM_API.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,17 @@ SYNOPSIS
/* make changes persistent */
msync(addr, nbytes, MS_SYNC);

/* optional, instead of mmap line above: */
/* optional, instead of msync line above: */
pmem_persist(addr, nbytes, 0);

/* optional, instead of msync line above: */
int pmem_persist_iov(const struct iovec *addrs, size_t count,
int flags);

/* optional, instead of msync line above: */
int pmem_persist_iov_verify(const struct iovec *addrs,
size_t count, int flags);

/* other interfaces described in this document... */
pmem_flush_cache(addr, len, flags);
pmem_fence();
Expand Down Expand Up @@ -187,6 +195,51 @@ DESCRIPTION
persistent -- they can become persistent at any time
before pmem_persist() is called.

void pmem_persist_iov(const struct iovec *addrs, size_t count,
int flags);

Force any changes in an array of (discontinuous) ranges
[addr, addr+len) to be stored durably in Persistent Memory.
This is an alternative to msync(2) and pmem_persist described
above. This might be even more optimal than pmem_persist above
as it will alleviate the overhead of enforcing memory barriers
after each flush if possible.

No flags have been defined for this call yet.

WARNING: Like msync(2) described above, there is nothing
atomic or transactional about this call. Any
unwritten stores in the given range(s) will be written,
but some stores may have already been written by
virtue of normal cache eviction/replacement policies.
Correctly written code must not depend on stores
waiting until pmem_persist_iov() is called to become
persistent -- they can become persistent at any time
before pmem_persist() is called.

void pmem_persist_iov_verify(const struct iovec *addrs, size_t count,
int flags);

Force any changes in an array of (discontinuous) ranges
[addr, addr+len) to be stored durably in Persistent Memory
with Posix synchronized I/O data integrity completion, i.e.
O_SYNC-like behavior. This is an alternative to msync(2),
pmem_persist and pmem_persist_iov described above. This
ensures data integrity of writes unlike pmem_persist and
pmem_persist_iov.

No flags have been defined for this call yet.

WARNING: Like msync(2) described above, there is nothing
atomic or transactional about this call. Any
unwritten stores in the given range(s) will be written,
but some stores may have already been written by
virtue of normal cache eviction/replacement policies.
Correctly written code must not depend on stores
waiting until pmem_persist_iov() is called to become
persistent -- they can become persistent at any time
before pmem_persist() is called.

void pmem_flush_cache(void *addr, size_t len, int flags);
void pmem_fence(void);
void pmem_drain_pm_stores(void);
Expand Down
78 changes: 73 additions & 5 deletions basic/basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,41 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
* Copyright (c) 2013, NetApp, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the NetApp, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE..
*/

/*
* basic.c -- illustrate basic load/store operations on PM
*
* usage: basic [-FMd] [-i icount] path [strings...]
* usage: basic [-FMRVd] [-i icount] path [strings...]
*
* Where <path> is a file on a Persistent Memory aware file system
* like PMFS. If path doesn't exist, this program will create it
Expand All @@ -51,6 +82,14 @@
* Use this when you don't have a PM-aware file system and you're
* running on traditional memory-mapped files instead.
*
* The -R flag enables the multi-range version of pmem_persist.
* Use this when you want to persist multiple dirty regions
* together.
*
* The -V flag enables the multi-range version of pmem_persist with verify.
* Use this when you want to persist multiple dirty regions
* together with Posix synchronized I/O data integrity completion.
*
* The -d flag turns on debugging prints.
*
* The -i flag, if given, turns on instruction counting for the
Expand All @@ -76,13 +115,13 @@
#include "icount/icount.h"
#include "libpmem/pmem.h"

char Usage[] = "[-FMd] [-i icount] path [strings...]"; /* for USAGE() */
char Usage[] = "[-FMRVd] [-i icount] path [strings...]"; /* for USAGE() */

int
main(int argc, char *argv[])
{
int opt;
int iflag = 0;
int iflag = 0, iov_flag = 0, iov_verify_flag = 0;
unsigned long icount;
const char *path;
struct stat stbuf;
Expand All @@ -91,7 +130,7 @@ main(int argc, char *argv[])
char *pmaddr;

Myname = argv[0];
while ((opt = getopt(argc, argv, "FMdi:")) != -1) {
while ((opt = getopt(argc, argv, "FMRVdi:")) != -1) {
switch (opt) {
case 'F':
pmem_fit_mode();
Expand All @@ -101,6 +140,14 @@ main(int argc, char *argv[])
pmem_msync_mode();
break;

case 'R':
iov_flag++;
break;

case 'V':
iov_verify_flag++;
break;

case 'd':
Debug++;
break;
Expand Down Expand Up @@ -149,10 +196,19 @@ main(int argc, char *argv[])
if (optind < argc) { /* strings supplied as arguments? */
int i;
char *ptr = pmaddr;
struct iovec *dirty_addrs;
size_t dirty_count = 0;
int dirty_rc = 0;

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


if (iov_flag || iov_verify_flag) {
dirty_addrs = (struct iovec *) malloc ((argc - optind)
* sizeof (struct iovec));
}

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

Expand All @@ -163,12 +219,24 @@ main(int argc, char *argv[])
strcpy(ptr, argv[i]);

/* make that change durable */
pmem_persist(ptr, len, 0);
if (iov_flag || iov_verify_flag) {
pmem_add_dirty_range(dirty_addrs, &dirty_count,
ptr, len);
} else
pmem_persist(ptr, len, 0);

ptr += len;
size -= len;
}

if (iov_flag) {
dirty_rc = pmem_persist_iov(dirty_addrs,
dirty_count, 0);
} else if (iov_verify_flag) {
dirty_rc = pmem_persist_iov_verify(dirty_addrs,
dirty_count, 0);
}

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

Expand Down
79 changes: 79 additions & 0 deletions libpmem/pmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,37 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
* Copyright (c) 2013, NetApp, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the NetApp, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE..
*/

/*
* pmem.c -- entry points for libpmem
*/
Expand All @@ -41,14 +72,23 @@
/* dispatch tables for the various versions of libpmem */
void *pmem_map_cl(int fd, size_t len);
void pmem_persist_cl(void *addr, size_t len, int flags);
int pmem_persist_iov_cl(const struct iovec *addrs, size_t count, int flags);
int pmem_persist_iov_verify_cl(const struct iovec *addrs, size_t count,
int flags);
void pmem_flush_cache_cl(void *addr, size_t len, int flags);
void pmem_drain_pm_stores_cl(void);
void *pmem_map_msync(int fd, size_t len);
void pmem_persist_msync(void *addr, size_t len, int flags);
int pmem_persist_iov_msync(const struct iovec *addrs, size_t count, int flags);
int pmem_persist_iov_verify_msync(const struct iovec *addrs, size_t count,
int flags);
void pmem_flush_cache_msync(void *addr, size_t len, int flags);
void pmem_drain_pm_stores_msync(void);
void *pmem_map_fit(int fd, size_t len);
void pmem_persist_fit(void *addr, size_t len, int flags);
int pmem_persist_iov_fit(const struct iovec *addrs, size_t count, int flags);
int pmem_persist_iov_verify_fit(const struct iovec *addrs, size_t count,
int flags);
void pmem_flush_cache_fit(void *addr, size_t len, int flags);
void pmem_drain_pm_stores_fit(void);
#define PMEM_CL_INDEX 0
Expand All @@ -58,6 +98,13 @@ static void *(*Map[])(int fd, size_t len) =
{ pmem_map_cl, pmem_map_msync, pmem_map_fit };
static void (*Persist[])(void *addr, size_t len, int flags) =
{ pmem_persist_cl, pmem_persist_msync, pmem_persist_fit };
static int (*PersistIOV[])(const struct iovec *addrs, size_t count, int flags) =
{ pmem_persist_iov_cl, pmem_persist_iov_msync,
pmem_persist_iov_fit };
static int (*PersistIOVVerify[])(const struct iovec *addrs, size_t count,
int flags) = { pmem_persist_iov_verify_cl,
pmem_persist_iov_verify_msync,
pmem_persist_iov_verify_fit };
static void (*Flush[])(void *addr, size_t len, int flags) =
{ pmem_flush_cache_cl, pmem_flush_cache_msync,
pmem_flush_cache_fit };
Expand Down Expand Up @@ -106,6 +153,38 @@ pmem_persist(void *addr, size_t len, int flags)
(*Persist[Mode])(addr, len, flags);
}

/*
* pmem_persist_iov -- make any cached changes to an array of (discontinuous)
* ranges of PM persistent
*/
int
pmem_persist_iov(const struct iovec *addrs, size_t count, int flags)
{
(*PersistIOV[Mode])(addrs, count, flags);
}

/*
* pmem_persist_iov_verify -- make any cached changes to an array of
* (discontinuous) ranges of PM persistent with Posix synchronized I/O data
* integrity completion, i.e. O_SYNC-like behavior
*/
int
pmem_persist_iov_verify(const struct iovec *addrs, size_t count, int flags)
{
(*PersistIOVVerify[Mode])(addrs, count, flags);
}

/*
* pmem_add_dirty_range -- Helper function to track dirty addres ranges
*/
void pmem_add_dirty_range(struct iovec *addrs, size_t* count, void *addr,
size_t len)
{
addrs[*count].iov_base = addr;
addrs[*count].iov_len = len;
*count = (*count) + 1;
}

/*
* pmem_flush_cache -- flush processor cache for the given range
*/
Expand Down
36 changes: 36 additions & 0 deletions libpmem/pmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,52 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
* Copyright (c) 2013, NetApp, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the NetApp, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE..
*/

/*
* pmem.h -- definitions of libpmem entry points
*/
#include <sys/uio.h>

void pmem_msync_mode(void); /* for testing on non-PM memory-mapped files */
void pmem_fit_mode(void); /* for fault injection testing */

/* commonly-used functions for Persistent Memory */
void *pmem_map(int fd, size_t len);
void pmem_persist(void *addr, size_t len, int flags);
int pmem_persist_iov(const struct iovec *addrs, size_t count, int flags);
int pmem_persist_iov_verify(const struct iovec *addrs, size_t count, int flags);
void pmem_add_dirty_range(struct iovec *addrs, size_t* count,
void *addr, size_t len);

/* for advanced users -- functions that do portions of pmem_persist() */
void pmem_flush_cache(void *addr, size_t len, int flags);
Expand Down
Loading