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