diff --git a/doc/Makefile b/doc/Makefile index c635dceb266e9cae9c9e0b782306d45078b8c9a8..1ab350594717d2a7c43862d8791fde51415749ec 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -108,7 +108,9 @@ MANPAGES_3_MD_PMEM2 = libpmem2/pmem2_errormsg.3.md libpmem2/pmem2_config_new.3.m 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_source_device_id.3.md libpmem2/pmem2_source_device_usc.3.md \ - libpmem2/pmem2_map_from_existing.3.md + libpmem2/pmem2_map_from_existing.3.md libpmem2/pmem2_source_get_fd.3.md \ + libpmem2/pmem2_source_get_handle.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 8118753d62d16e6ececfaa30885bec97519ff3f2..6c2dd66a535390ca3358f4de8dfd16f91943d2ab 100644 --- a/doc/libpmem2/.gitignore +++ b/doc/libpmem2/.gitignore @@ -25,6 +25,8 @@ pmem2_map_get_store_granularity.3 pmem2_source_alignment.3 pmem2_source_from_fd.3 pmem2_source_from_anon.3 +pmem2_source_get_fd.3 +pmem2_source_get_handle.3 pmem2_source_size.3 pmem2_source_device_id.3 pmem2_source_device_usc.3 diff --git a/doc/libpmem2/pmem2_source_get_fd.3.md b/doc/libpmem2/pmem2_source_get_fd.3.md new file mode 100644 index 0000000000000000000000000000000000000000..982d829e77f36032bf3405c089a4ba298b3505cc --- /dev/null +++ b/doc/libpmem2/pmem2_source_get_fd.3.md @@ -0,0 +1,57 @@ +--- +layout: manual +Content-Style: 'text/css' +title: _MP(PMEM2_SOURCE_GET_FD, 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_get_fd.3 -- man page for pmem2_source_get_fd + +[NAME](#name)<br /> +[SYNOPSIS](#synopsis)<br /> +[DESCRIPTION](#description)<br /> +[RETURN VALUE](#return-value)<br /> +[ERRORS](#errors)<br /> +[SEE ALSO](#see-also)<br /> + +# NAME # + +**pmem2_source_get_fd**() - reads file descriptor of the data source + +# SYNOPSIS # + +```c +#include <libpmem2.h> + +int pmem2_source_get_fd(const struct pmem2_source *src, int *fd); +``` + +# DESCRIPTION # + +The **pmem2_source_get_fd**() function reads the file descriptor of +*struct pmem2_source** object describing the data source and returns it +by *fd* parameter. + +This function is Linux only, on Windows use **pmem2_source_get_handle**(3). + +# RETURN VALUE # + +The **pmem2_source_get_fd**() function returns 0 on success +or a negative error code on failure. + +# ERRORS # + +The **pmem2_source_get_fd**() can fail with the following errors: + +* **PMEM2_E_FILE_DESCRIPTOR_NOT_SET** - in case of an instance of +*struct pmem2_source* that does not come from source type that +support file descriptors, eg. anonymous data source. + +# SEE ALSO # + +**pmem2_source_get_handle**(3), **libpmem2**(7) and **<http://pmem.io>** diff --git a/doc/libpmem2/pmem2_source_get_handle.3.md b/doc/libpmem2/pmem2_source_get_handle.3.md new file mode 100644 index 0000000000000000000000000000000000000000..0156d1e7b5eaaf0a34b48de72432e372b8f6d48e --- /dev/null +++ b/doc/libpmem2/pmem2_source_get_handle.3.md @@ -0,0 +1,62 @@ +--- +layout: manual +Content-Style: 'text/css' +title: _MP(PMEM2_SOURCE_GET_HANDLE, 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_get_handsle.3 -- man page for pmem2_source_get_handle + +[NAME](#name)<br /> +[SYNOPSIS](#synopsis)<br /> +[DESCRIPTION](#description)<br /> +[RETURN VALUE](#return-value)<br /> +[ERRORS](#errors)<br /> +[SEE ALSO](#see-also)<br /> + +# NAME # + +**pmem2_source_get_handle**() - reads file handler of the data source + +# SYNOPSIS # + +```c +#include <libpmem2.h> + +int pmem2_source_get_handle(const struct pmem2_source *src, HANDLE *h); +``` + +# DESCRIPTION # + +The **pmem2_source_get_handle**() function reads the file handler of +*struct pmem2_source** object describing the data source and returns +it by *h* parameter. + +This function is Windows only, on Linux use **pmem2_source_get_fd**(3). +If the source was created using **pmem2_source_from_fd**(3) then +**pmem2_source_get_handle**() is also valid function to read handler, because +file descriptor is converted to file handle during source creation. + +However, there are limitations to what you can do with a handle created from a file descriptor. +For details refer to **DESCRIPTION** section in the **pmem2_source_from_fd**(3) manpage. + +# ERRORS # + +The **pmem2_source_get_handle**() can fail with the following errors: + +* **PMEM2_E_FILE_HANDLE_NOT_SET** - in case of an instance of +*struct pmem2_source* that does not come from source type that +support file handles, eg. anonymous data source. + +# RETURN VALUE # + +The **pmem2_source_get_handle**() returns a file handle of data source. + +# SEE ALSO # + +**pmem2_source_from_fd**(3), **pmem2_source_get_fd**(3), **libpmem2**(7) and **<http://pmem.io>** diff --git a/src/include/libpmem2.h b/src/include/libpmem2.h index 752fb1cca74d02f7a1e83f8f65f2c8c494ccb642..4d2e6027cf4bd0d712757484f9292146f2d5abcc 100644 --- a/src/include/libpmem2.h +++ b/src/include/libpmem2.h @@ -70,6 +70,7 @@ extern "C" { #define PMEM2_E_NO_ACCESS (-100032) #define PMEM2_E_VM_RESERVATION_NOT_EMPTY (-100033) #define PMEM2_E_MAP_EXISTS (-100034) +#define PMEM2_E_FILE_DESCRIPTOR_NOT_SET (-100035) /* source setup */ @@ -79,6 +80,9 @@ int pmem2_source_from_fd(struct pmem2_source **src, int fd); int pmem2_source_from_anon(struct pmem2_source **src, size_t size); #ifdef _WIN32 int pmem2_source_from_handle(struct pmem2_source **src, HANDLE handle); +int pmem2_source_get_handle(const struct pmem2_source *src, HANDLE *h); +#else +int pmem2_source_get_fd(const struct pmem2_source *src, int *fd); #endif int pmem2_source_size(const struct pmem2_source *src, size_t *size); diff --git a/src/libpmem2/libpmem2.def b/src/libpmem2/libpmem2.def index c8bdbc39d9a68857a55200225a398d37fa22ee33..ccda52c7258a514d2d52d2ff0bbbe5d610093745 100644 --- a/src/libpmem2/libpmem2.def +++ b/src/libpmem2/libpmem2.def @@ -45,6 +45,7 @@ EXPORTS pmem2_source_from_anon pmem2_source_from_fd pmem2_source_from_handle + pmem2_source_get_handle pmem2_source_size pmem2_vm_reservation_delete pmem2_vm_reservation_get_address diff --git a/src/libpmem2/libpmem2.link.in b/src/libpmem2/libpmem2.link.in index 0bb0edafed1995fd4c3354882a602dd377466bb5..320b7e7e35a02e00db58cc7f2a5c10b6d1c38f3f 100644 --- a/src/libpmem2/libpmem2.link.in +++ b/src/libpmem2/libpmem2.link.in @@ -40,6 +40,7 @@ LIBPMEM2_1.0 { pmem2_source_from_anon; pmem2_source_from_fd; pmem2_source_from_handle; + pmem2_source_get_fd; pmem2_source_size; pmem2_vm_reservation_delete; pmem2_vm_reservation_get_address; diff --git a/src/libpmem2/source_posix.c b/src/libpmem2/source_posix.c index 422d48d9f568a5d373d53fb59dfec82a59a3c516..92f618609776dc6b7e201c6113eb5f55379b7192 100644 --- a/src/libpmem2/source_posix.c +++ b/src/libpmem2/source_posix.c @@ -174,3 +174,23 @@ pmem2_source_alignment(const struct pmem2_source *src, size_t *alignment) return 0; } + +/* + * pmem2_source_get_fd -- get file descriptor from provided source + */ +int +pmem2_source_get_fd(const struct pmem2_source *src, int *fd) +{ + LOG(3, "src type %d", src->type); + PMEM2_ERR_CLR(); + + if (src->type == PMEM2_SOURCE_FD) { + *fd = src->value.fd; + } else { + ERR( + "File descriptor is not set, source type does not support fd"); + return PMEM2_E_FILE_DESCRIPTOR_NOT_SET; + } + + return 0; +} diff --git a/src/libpmem2/source_windows.c b/src/libpmem2/source_windows.c index ea7d03a9011c40a20c921fb2592ca82dc143b3b3..fb813273e9c454d147024e80c157a81315476f0e 100644 --- a/src/libpmem2/source_windows.c +++ b/src/libpmem2/source_windows.c @@ -161,3 +161,23 @@ pmem2_source_alignment(const struct pmem2_source *src, size_t *alignment) return 0; } + +/* + * pmem2_source_get_handle -- get file handler from provided source + */ +int +pmem2_source_get_handle(const struct pmem2_source *src, HANDLE *h) +{ + LOG(3, "src type %d", src->type); + PMEM2_ERR_CLR(); + + if (src->type == PMEM2_SOURCE_HANDLE) { + *h = src->value.handle; + } else { + ERR( + "File handle is not set, source type does not support file handles"); + return PMEM2_E_FILE_HANDLE_NOT_SET; + } + + return 0; +} diff --git a/src/test/pmem2_source/TESTS.py b/src/test/pmem2_source/TESTS.py index 1d6f972bc6429852a35d9f6312701683789bc178..d4308dd95810ea5cb3ad30d02e24b66c01b8c4d5 100755 --- a/src/test/pmem2_source/TESTS.py +++ b/src/test/pmem2_source/TESTS.py @@ -94,3 +94,27 @@ class TEST11(PMEM2_SOURCE): def run(self, ctx): ctx.exec('pmem2_source', self.test_case, ctx.testdir) + + +@t.windows_only +class TEST12(PMEM2_SOURCE): + """get handle from the source""" + test_case = "test_get_handle" + + +@t.windows_exclude +class TEST13(PMEM2_SOURCE): + """get file descriptor from the source""" + test_case = "test_get_fd" + + +@t.windows_only +class TEST14(PMEM2_SOURCE_NO_DIR): + """get handle from the invalid source type""" + test_case = "test_get_handle_inval_type" + + +@t.windows_exclude +class TEST15(PMEM2_SOURCE_NO_DIR): + """get file descriptor from the invalid source type""" + test_case = "test_get_fd_inval_type" diff --git a/src/test/pmem2_source/pmem2_source.c b/src/test/pmem2_source/pmem2_source.c index 6e1b836f099378b3349a864268d316185439d43c..cfc40b272d00fd0666eeee1cff1560d10af225ad 100644 --- a/src/test/pmem2_source/pmem2_source.c +++ b/src/test/pmem2_source/pmem2_source.c @@ -293,6 +293,54 @@ test_set_mutex_handle(const struct test_case *tc, int argc, char *argv[]) return 0; } + +/* + * test_get_handle - test getting handle value + */ +static int +test_get_handle(const struct test_case *tc, int argc, char *argv[]) +{ + if (argc < 1) + UT_FATAL("usage: test_get_handle <file>"); + + char *file = argv[0]; + HANDLE h = CreateFile(file, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_ALWAYS, 0, NULL); + UT_ASSERTne(h, INVALID_HANDLE_VALUE); + + struct pmem2_source *src; + int ret = pmem2_source_from_handle(&src, h); + UT_PMEM2_EXPECT_RETURN(ret, 0); + + HANDLE handle_from_pmem2; + ret = pmem2_source_get_handle(src, &handle_from_pmem2); + UT_ASSERTeq(handle_from_pmem2, h); + UT_PMEM2_EXPECT_RETURN(ret, 0); + + CloseHandle(h); + pmem2_source_delete(&src); + + return 1; +} + +/* + * test_get_handle_inval_type - test getting handle value from invalid type + */ +static int +test_get_handle_inval_type(const struct test_case *tc, int argc, char *argv[]) +{ + struct pmem2_source *src; + int ret = pmem2_source_from_anon(&src, 0); + UT_PMEM2_EXPECT_RETURN(ret, 0); + + HANDLE handle_from_pmem2; + ret = pmem2_source_get_handle(src, &handle_from_pmem2); + UT_PMEM2_EXPECT_RETURN(ret, PMEM2_E_FILE_HANDLE_NOT_SET); + + pmem2_source_delete(&src); + + return 0; +} #else /* * test_set_directory_handle - test setting directory's fd @@ -315,6 +363,53 @@ test_set_directory_fd(const struct test_case *tc, int argc, char *argv[]) return 1; } + +/* + * test_get_fd - test getting file descriptor value + */ +static int +test_get_fd(const struct test_case *tc, int argc, char *argv[]) +{ + if (argc < 1) + UT_FATAL("usage: test_get_fd <file>"); + + char *file = argv[0]; + int fd = OPEN(file, O_RDONLY); + UT_ASSERTne(fd, -1); + + struct pmem2_source *src; + int ret = pmem2_source_from_fd(&src, fd); + UT_PMEM2_EXPECT_RETURN(ret, 0); + + int fd_from_pmem2; + ret = pmem2_source_get_fd(src, &fd_from_pmem2); + UT_ASSERTeq(fd_from_pmem2, fd); + UT_PMEM2_EXPECT_RETURN(ret, 0); + + CLOSE(fd); + pmem2_source_delete(&src); + + return 1; +} + +/* + * test_get_fd_inval_type - test getting fd value from invalid type + */ +static int +test_get_fd_inval_type(const struct test_case *tc, int argc, char *argv[]) +{ + struct pmem2_source *src; + int ret = pmem2_source_from_anon(&src, 0); + UT_PMEM2_EXPECT_RETURN(ret, 0); + + int fd_from_pmem2; + ret = pmem2_source_get_fd(src, &fd_from_pmem2); + UT_PMEM2_EXPECT_RETURN(ret, PMEM2_E_FILE_DESCRIPTOR_NOT_SET); + + pmem2_source_delete(&src); + + return 0; +} #endif /* @@ -333,8 +428,12 @@ static struct test_case test_cases[] = { TEST_CASE(test_set_invalid_handle), TEST_CASE(test_set_directory_handle), TEST_CASE(test_set_mutex_handle), + TEST_CASE(test_get_handle), + TEST_CASE(test_get_handle_inval_type), #else TEST_CASE(test_set_directory_fd), + TEST_CASE(test_get_fd), + TEST_CASE(test_get_fd_inval_type), #endif }; diff --git a/src/test/scope/out13.log.match b/src/test/scope/out13.log.match index 8a9fdb4b0f48e8b1c9a219e1d41937bf34073001..0bf8d66c22b8a8202b44b3f0ff97eed8a9270ca2 100644 --- a/src/test/scope/out13.log.match +++ b/src/test/scope/out13.log.match @@ -31,6 +31,7 @@ pmem2_source_device_id$(nW) pmem2_source_device_usc$(nW) pmem2_source_from_anon$(nW) pmem2_source_from_fd$(nW) +pmem2_source_get_fd$(nW) pmem2_source_size$(nW) pmem2_vm_reservation_delete$(nW) pmem2_vm_reservation_get_address$(nW) diff --git a/src/test/scope/out14.log.match b/src/test/scope/out14.log.match index eb93f12f1c7f112208e2d82bcfbdeacb34a65e40..3c80cd7997e39d07d5ba482a495e23895eed1658 100644 --- a/src/test/scope/out14.log.match +++ b/src/test/scope/out14.log.match @@ -36,6 +36,7 @@ pmem2_source_device_usc pmem2_source_from_anon pmem2_source_from_fd pmem2_source_from_handle +pmem2_source_get_handle pmem2_source_size pmem2_vm_reservation_delete pmem2_vm_reservation_get_address