diff --git a/doc/Makefile b/doc/Makefile index bd6ef6688d528d22ae2ded9f19488957ba5efae9..257bc0bf9631882b2bd52ffe56f1f08dd4ef038b 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -92,7 +92,7 @@ MANPAGES_3_DUMMY_EXP = MANPAGES_1_DUMMY_EXP = # libpmem2 -MANPAGES_7_MD_PMEM2 = libpmem2/libpmem2.7.md +MANPAGES_7_MD_PMEM2 = libpmem2/libpmem2.7.md libpmem2/libpmem2_unsafe_shutdown.7.md MANPAGES_5_MD_PMEM2 = MANPAGES_3_MD_PMEM2 = libpmem2/pmem2_errormsg.3.md libpmem2/pmem2_config_new.3.md libpmem2/pmem2_map.3.md \ libpmem2/pmem2_unmap.3.md libpmem2/pmem2_map_get_address.3.md libpmem2/pmem2_map_get_size.3.md \ @@ -106,7 +106,8 @@ MANPAGES_3_MD_PMEM2 = libpmem2/pmem2_errormsg.3.md libpmem2/pmem2_config_new.3.m libpmem2/pmem2_config_set_vm_reservation.3.md libpmem2/pmem2_vm_reservation_new.3.md \ libpmem2/pmem2_badblock_context_new.3.md libpmem2/pmem2_badblock_next.3.md \ libpmem2/pmem2_badblock_clear.3.md libpmem2/pmem2_config_set_protection.3.md \ - libpmem2/pmem2_deep_flush.3.md libpmem2/pmem2_source_from_anon.3.md + libpmem2/pmem2_deep_flush.3.md libpmem2/pmem2_source_from_anon.3.md \ + libpmem2/pmem2_source_device_id.3.md libpmem2/pmem2_source_device_usc.3.md MANPAGES_1_MD_PMEM2 = ifeq ($(PMEM2_INSTALL),y) MANPAGES_3_DUMMY += libpmem2/pmem2_config_delete.3 libpmem2/pmem2_source_from_handle.3 libpmem2/pmem2_source_delete.3 \ diff --git a/doc/libpmem2/.gitignore b/doc/libpmem2/.gitignore index 710e48a6d6be83dc1a185d2dc402bffe1cb36593..1474ccdf6567edd1f69005e6a71088c1f8970f05 100644 --- a/doc/libpmem2/.gitignore +++ b/doc/libpmem2/.gitignore @@ -1,4 +1,5 @@ libpmem2.7 +libpmem2_unsafe_shutdown.7 pmem2_badblock_context_new.3 pmem2_badblock_next.3 pmem2_badblock_clear.3 @@ -25,6 +26,8 @@ pmem2_source_alignment.3 pmem2_source_from_fd.3 pmem2_source_from_anon.3 pmem2_source_size.3 +pmem2_source_device_id.3 +pmem2_source_device_usc.3 pmem2_unmap.3 pmem2_perror.3 pmem2_vm_reservation_new.3 diff --git a/doc/libpmem2/libpmem2_unsafe_shutdown.7.md b/doc/libpmem2/libpmem2_unsafe_shutdown.7.md new file mode 100644 index 0000000000000000000000000000000000000000..83c8940c6e72a0c3ea62ac58bfb3711037a2205e --- /dev/null +++ b/doc/libpmem2/libpmem2_unsafe_shutdown.7.md @@ -0,0 +1,84 @@ +--- +layout: manual +Content-Style: 'text/css' +title: _MP(LIBPMEM2_UNSAFE_SHUTDOWN, 7) +collection: libpmem2 +header: PMDK +date: pmem2 API version 1.0 +... + +[comment]: <> (SPDX-License-Identifier: BSD-3-Clause +[comment]: <> (Copyright 2020, Intel Corporation) + +[comment]: <> (libpmem2_unsafe_shutdown.7 -- man page for libpmem2 unsafe shutdown) + +[NAME](#name)<br /> +[DESCRIPTION](#description)<br /> +[UNSAFE SHUTDOWN DETECTION](#unsafe-shutdown-detection)<br /> +[SEE ALSO](#see-also) + +# NAME # + +**libpmem2_unsafe_shutdown** - libpmem2 unsafe shutdown + +# DESCRIPTION # + +In systems with the persistent memory support, *a power-fail protected domain* +covers a set of resources from which the platform will flush data to the +*a persistent medium* in case of *a power-failure*. Data stored on +*the persistent medium* is preserved across power cycles. + +The hardware guarantees the feature to flush all data stored in +*the power-fail protected domain* to *the persistent medium*. However, nothing +is infallible, and Persistent Memory hardware can expose a monotonically +increasing *unsafe shutdown counter* (**USC**) that is incremented every time +a failure of the mechanism above is detected. This allows software to discover +situations where a running application was interrupted by a power failure that +led to an unsafe shutdown. Undiscovered unsafe shutdowns might cause silent data +corruption. + +>Note: *The unsafe shutdown* may corrupt data stored on a device, in a file, +in a set of files, and a mapping spanning only a part of a file. +For the sake of simplicity, all of the above cases will be called *file* below. + +# UNSAFE SHUTDOWN DETECTION # + +Software can detect an unsafe shutdown by watching for the change between +unsafe shutdown count value across application startups. Any changes can be +indicative of unsafe shutdown occurrence. + +Applications can implement a detection mechanism by storing the **USC** retrieved +from **pmem2_source_device_usc**(3) in Persistent Memory. Then, on subsequent +startups, the stored value must be compared with a newly retrieved one. + +However, this detection method can result in false-positives. Moving the file to +different Persistent Memory devices with possibly different **USC** values would +lead to false unsafe shutdown detection. + +Additionally, relying on **USC** value alone could result in the detection of +unsafe shutdown events that occur when such a shutdown has no chance of impacting +the data used by the application, e.g., when nothing is actively using the file. + +Applications can avoid false-positives associated with moving the file by storing +device identification, obtained through **pmem2_source_device_id**(3), alongside +the **USC**. This enables the software to check if the underlying device has +changed, and reinitialize the stored **USC** in such cases. + +The second behavior, detection of possibly irrelevant unsafe shutdown events, +if undesirable, can be prevented by storing a flag indicating whether the file +is in use, alongside all the rest of the relevant information. + +The application should use **pmem2_deep_flush**(3) when storing any data related +to unsafe shutdown detection for higher reliability. This helps ensure that the +detection mechanism is not reliant on the correct functioning of the same hardware +features it is designed to safeguard. + +General-purpose software should not assume the presence of **USC** in the platform, +and should instead appropriately handle any *PMEM2_E_NOSUPP* it encounters. +Doing otherwise might cause the software to be unnecessarily restrictive about +the hardware it supports and would prevent, e.g., testing on emulated PMEM. + +# SEE ALSO # + +**pmem2_deep_flush**(3), **pmem2_persist_fn**(3), **pmem2_source_device_id**(3), +**pmem2_source_device_usc**(3) and **<https://pmem.io>** diff --git a/doc/libpmem2/pmem2_source_device_id.3.md b/doc/libpmem2/pmem2_source_device_id.3.md new file mode 100644 index 0000000000000000000000000000000000000000..eeff69b7c32ebf1bf742848c1f22810138f7ac92 --- /dev/null +++ b/doc/libpmem2/pmem2_source_device_id.3.md @@ -0,0 +1,90 @@ +--- +layout: manual +Content-Style: 'text/css' +title: _MP(PMEM2_SOURCE_DEVICE_ID, 3) +collection: libpmem2 +header: PMDK +date: pmem2 API version 1.0 +... + +[comment]: <> (SPDX-License-Identifier: BSD-3-Clause) +[comment]: <> (Copyright 2020, Intel Corporation) + +[comment]: <> (pmem2_source_device_id.3 -- man page for pmem2_source_device_id) + +[NAME](#name)<br /> +[SYNOPSIS](#synopsis)<br /> +[DESCRIPTION](#description)<br /> +[RETURN VALUE](#return-value)<br /> +[SEE ALSO](#see-also)<br /> + +# NAME # + +**pmem2_source_device_id**() - returns the unique identifier of a device + +# SYNOPSIS # + +```c +#include <libpmem2.h> + +struct pmem2_source; +int pmem2_source_device_id(const struct pmem2_source *source, char *id, size_t *len); +``` + +# DESCRIPTION # + +The **pmem2_source_device_id**() function retrieves a unique identifier +of all NVDIMMs backing the data source. This function has two operating modes: + +* if *\*id* is NULL the function calculates a buffer length required for +storing the identifier of the *\*source* device and puts this length in *\*len* +The more hardware devices back the data source, the longer the length is. + +* if *\*id* is not NULL it must point to a buffer of length *\*len* provided by +the previous call to this function. +On success, **pmem2_source_device_id**() will store a unique identifier +of all hardware devices backing the data source. + +For details on how to use the unique identifier for detecting *the unsafe shutdown* +please refer to **libpmem2_unsafe_shutdown**(7) manual page. + +# RETURN VALUE # + +The **pmem2_source_device_id**() function returns 0 on success. +If the function fails, the *\*id* and *\*len* variables contents are left unmodified, +and one of the following errors is returned: + +On all systems: + +* **PMEM2_E_BUFFER_TOO_SMALL** - the provided buffer of length *\*len* is too +small to store the full identifier of the backing devices. +* **PMEM2_E_NOSUPP** - the underlying platform does not expose hardware +identification. + +On Windows: + +* -**errno** equivalent of return code set by failing +**GetFinalPathNameByHandleW**(), while trying to resolve the volume path from the +file handle. + +* -**errno** set by failing **malloc**(3), while trying to allocate a buffer +for storing volume path. + +* -**errno** equivalent of return code set by failing +**CreateFileW**(), while trying to obtain a handle to the volume. + +* -**errno** equivalent of return code set by failing +**DeviceIoControl **(), while trying to obtain volume **USC** value. + +On Linux: + +* -**errno** set by failing **fstat**(2), while trying to validate the file +descriptor. + +* -**errno** set by failing **ndctl_new**(), while trying to initiate a new +NDCTL library context. + +# SEE ALSO # + +**fstat**(2), **errno**(3), **malloc**(3), **libpmem2_unsafe_shutdown**(7), + and **<http://pmem.io>** diff --git a/doc/libpmem2/pmem2_source_device_usc.3.md b/doc/libpmem2/pmem2_source_device_usc.3.md new file mode 100644 index 0000000000000000000000000000000000000000..20cf67a9d3922703885f9ad832bec281cf01e9cc --- /dev/null +++ b/doc/libpmem2/pmem2_source_device_usc.3.md @@ -0,0 +1,84 @@ +--- +layout: manual +Content-Style: 'text/css' +title: _MP(PMEM2_SOURCE_DEVICE_USC, 3) +collection: libpmem2 +header: PMDK +date: pmem2 API version 1.0 +... + +[comment]: <> (SPDX-License-Identifier: BSD-3-Clause) +[comment]: <> (Copyright 2020, Intel Corporation) + +[comment]: <> (pmem2_source_device_usc.3 -- man page for pmem2_source_device_usc) + +[NAME](#name)<br /> +[SYNOPSIS](#synopsis)<br /> +[DESCRIPTION](#description)<br /> +[RETURN VALUE](#return-value)<br /> +[SEE ALSO](#see-also)<br /> + +# NAME # + +**pmem2_source_device_usc**() - returns the *unsafe shutdown counter* value of a +device + +# SYNOPSIS # + +```c +#include <libpmem2.h> + +struct pmem2_source; +int pmem2_source_device_usc(const struct pmem2_source *source, uint64_t *usc); +``` + +# DESCRIPTION # + +The **pmem2_source_device_usc**() function retrieves the sum of the +*unsafe shutdown count*(**USC**) values of all hardware devices backing +the data source and stores it in *\*usc*. + +Please refer to **libpmem2_unsafe_shutdown**(7) for detailed description on how +to properly consume this information. + +# RETURN VALUE # + +The **pmem2_source_device_usc**() function returns 0 on success. +If the function fails, the *\*usc* variable content is left unmodified, and one of +the following errors is returned: + +On all systems: + +* **PMEM2_E_NOSUPP** - the underlying platform does not expose unsafe shutdown +count information. + +On Windows: + +* -**errno** equivalent of return code set by failing +**GetFinalPathNameByHandleW**(), while trying to resolve volume path from the +file handle. + +* -**errno** set by failing **malloc**(3), while trying to allocate a buffer +for storing volume path. + +* -**errno** equivalent of return code set by failing +**CreateFileW**(), while trying to obtain a handle to the volume. + +* -**errno** equivalent of return code set by failing +**DeviceIoControl**(), while trying to obtain volume **USC** value. + +On Linux: + +* -**errno** set by failing **fstat**(2), while trying to validate the file +descriptor. + +* -**errno** set by failing **ndctl_new**(), while trying to initiate a new +NDCTL library context. + +* -**errno** set by failing **ndctl_dimm_get_dirty_shutdown**(), +while trying to obtain DIMM **USC** value. + +# SEE ALSO # + +**fstat**(2), **errno**(3), **malloc**(3), **libpmem2_unsafe_shutdown**(7), + and **<http://pmem.io>**