diff --git a/libtcmu.c b/libtcmu.c
index d413020..826f482 100644
--- a/libtcmu.c
+++ b/libtcmu.c
@@ -84,6 +84,20 @@ static struct genl_cmd tcmu_cmds[] = {
 		.c_maxattr	= TCMU_ATTR_MAX,
 		.c_attr_policy	= tcmu_attr_policy,
 	},
+	{
+		.c_id		= TCMU_CMD_GET_PR_INFO,
+		.c_name		= "GET PR_INFO",
+		.c_msg_parser	= handle_netlink,
+		.c_maxattr	= TCMU_ATTR_MAX,
+		.c_attr_policy	= tcmu_attr_policy,
+	},
+	{
+		.c_id		= TCMU_CMD_SET_PR_INFO,
+		.c_name		= "SET PR_INFO",
+		.c_msg_parser	= handle_netlink,
+		.c_maxattr	= TCMU_ATTR_MAX,
+		.c_attr_policy	= tcmu_attr_policy,
+	},
 };
 
 static struct genl_ops tcmu_ops = {
@@ -93,7 +107,7 @@ static struct genl_ops tcmu_ops = {
 };
 
 static int send_netlink_reply(struct tcmulib_context *ctx, int reply_cmd,
-			      uint32_t dev_id, int status)
+			      uint32_t dev_id, int status, char *data)
 {
 	struct nl_sock *sock = ctx->nl_sock;
 	struct nl_msg *msg;
@@ -117,6 +131,12 @@ static int send_netlink_reply(struct tcmulib_context *ctx, int reply_cmd,
 	if (ret < 0)
 		goto free_msg;
 
+	if (reply_cmd == TCMU_CMD_GET_PR_INFO_DONE) {
+		ret = nla_put_string(msg, TCMU_ATTR_PR_INFO, data);
+		if (ret < 0)
+			goto free_msg;
+	}
+
 	/* Ignore ack. There is nothing we can do. */
 	ret = nl_send_auto(sock, msg);
 free_msg:
@@ -197,12 +217,77 @@ static int reconfig_device(struct tcmulib_context *ctx, char *dev_name,
 	return 0;
 }
 
+
+static int set_pr_info(struct tcmulib_context *ctx, char *dev_name,
+		       struct genl_info *info)
+{
+	struct tcmu_device *dev;
+	int i, ret;
+	char *pr_info_str = NULL;
+
+	dev = lookup_dev_by_name(ctx, dev_name, &i);
+	if (!dev) {
+		tcmu_err("Could not set PR info, device %s: not found.\n",
+			 dev_name);
+		return -ENODEV;
+	}
+
+	if (!dev->handler->set_pr_info) {
+		tcmu_dev_err(dev, "Setting PR info is not supported with this device.\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (info->attrs[TCMU_ATTR_PR_INFO]) {
+		pr_info_str = nla_get_string(info->attrs[TCMU_ATTR_PR_INFO]);
+	}
+	else {
+		tcmu_dev_err(dev, "Failed to obtain PR info from netlink.\n");
+		return -ENODATA;
+	}
+
+	ret = dev->handler->set_pr_info(dev, pr_info_str);
+	if (ret < 0) {
+		tcmu_dev_err(dev, "Failed to store PR info with error %d.\n",
+			     ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int get_pr_info(struct tcmulib_context *ctx, char *dev_name, char **buf)
+{
+	struct tcmu_device *dev;
+	int i, ret;
+
+	dev = lookup_dev_by_name(ctx, dev_name, &i);
+	if (!dev) {
+		tcmu_err("Could not get PR info, device %s: not found.\n", dev_name);
+		return -ENODEV;
+	}
+
+	if (!dev->handler->get_pr_info) {
+		tcmu_dev_err(dev, "Getting PR info is not supported with this device.\n");
+		return -EOPNOTSUPP;
+	}
+
+
+	ret = dev->handler->get_pr_info(dev, buf);
+	if (ret < 0) {
+		tcmu_dev_err(dev, "Failed to get PR info with error %d.\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int handle_netlink(struct nl_cache_ops *unused, struct genl_cmd *cmd,
 			  struct genl_info *info, void *arg)
 {
 	struct tcmulib_context *ctx = arg;
 	int ret, reply_cmd, version = info->genlhdr->version;
 	char buf[32];
+	char *data = NULL;
 
 	tcmu_dbg("cmd %d. Got header version %d. Supported %d.\n",
 		 cmd->c_id, info->genlhdr->version, TCMU_NL_VERSION);
@@ -237,6 +322,15 @@ static int handle_netlink(struct nl_cache_ops *unused, struct genl_cmd *cmd,
 		reply_cmd = TCMU_CMD_RECONFIG_DEVICE_DONE;
 		ret = reconfig_device(ctx, buf, info);
 		break;
+	case TCMU_CMD_GET_PR_INFO:
+		reply_cmd = TCMU_CMD_GET_PR_INFO_DONE;
+		ret = get_pr_info(ctx, buf, &data);
+		break;
+	case TCMU_CMD_SET_PR_INFO:
+		reply_cmd = TCMU_CMD_SET_PR_INFO_DONE;
+		ret = set_pr_info(ctx, buf, info);
+		break;
+
 	default:
 		tcmu_err("Unknown netlink command %d. Netlink header received version %d. libtcmu supports %d\n",
 			 cmd->c_id, version, TCMU_NL_VERSION);
@@ -246,7 +340,7 @@ static int handle_netlink(struct nl_cache_ops *unused, struct genl_cmd *cmd,
 	if (version > 1)
 		ret = send_netlink_reply(ctx, reply_cmd,
 				nla_get_u32(info->attrs[TCMU_ATTR_DEVICE_ID]),
-				ret);
+				ret, data);
 
 	return ret;
 }
diff --git a/libtcmu.h b/libtcmu.h
index ee7f63d..a43bbbe 100644
--- a/libtcmu.h
+++ b/libtcmu.h
@@ -76,6 +76,10 @@ struct tcmulib_handler {
 	int (*added)(struct tcmu_device *dev);
 	void (*removed)(struct tcmu_device *dev);
 
+	int (*set_pr_info)(struct tcmu_device *dev, char *pr_info);
+	int (*get_pr_info)(struct tcmu_device *dev, char **buf);
+
+
 	void *hm_private; /* private ptr for handler module */
 	void *connection; /* private, dbus connection for this subtype */
 };
diff --git a/main.c b/main.c
index 2e33741..3b12e21 100644
--- a/main.c
+++ b/main.c
@@ -1084,6 +1084,8 @@ int main(int argc, char **argv)
 		tmp_handler.subtype = (*tmp_r_handler)->subtype;
 		tmp_handler.cfg_desc = (*tmp_r_handler)->cfg_desc;
 		tmp_handler.check_config = (*tmp_r_handler)->check_config;
+		tmp_handler.set_pr_info = (*tmp_r_handler)->set_pr_info;
+		tmp_handler.get_pr_info = (*tmp_r_handler)->get_pr_info;
 		tmp_handler.reconfig = dev_reconfig;
 		tmp_handler.added = dev_added;
 		tmp_handler.removed = dev_removed;
diff --git a/rbd.c b/rbd.c
index 0d1ffe9..bc722e1 100644
--- a/rbd.c
+++ b/rbd.c
@@ -78,6 +78,9 @@
 #define TCMU_RBD_LOCKER_TAG_FMT "tcmu_tag=%hu,rbd_client=%s"
 #define TCMU_RBD_LOCKER_BUF_LEN 256
 
+#define TCMU_RBD_PR_INFO_MAX_SIZE	8192
+#define TCMU_PR_INFO_KEY		"pr_info"
+
 struct tcmu_rbd_state {
 	rados_t cluster;
 	rados_ioctx_t io_ctx;
@@ -801,6 +804,36 @@ static int tcmu_rbd_check_image_size(struct tcmu_device *dev, uint64_t new_size)
 	return 0;
 }
 
+static rbd_image_t tcmu_dev_to_image(struct tcmu_device *dev);
+
+static int tcmu_rbd_pr_set(struct tcmu_device *dev, char *buf)
+{
+	int ret = 0;
+
+	rbd_image_t image = tcmu_dev_to_image(dev);
+	ret = rbd_metadata_set(image, TCMU_PR_INFO_KEY, buf);
+
+	return ret;
+}
+
+static int tcmu_rbd_pr_get(struct tcmu_device *dev, char **buf)
+{
+	int ret = 0;
+	size_t len = TCMU_RBD_PR_INFO_MAX_SIZE;
+	rbd_image_t image = tcmu_dev_to_image(dev);
+	char *pr_info_str = malloc(TCMU_RBD_PR_INFO_MAX_SIZE);
+	memset(pr_info_str, 0x0, TCMU_RBD_PR_INFO_MAX_SIZE);
+	if (!pr_info_str) {
+		tcmu_err("Not enough memory for getting PR info.\n");
+		return -ENOMEM;
+	}
+
+	ret = rbd_metadata_get(image, TCMU_PR_INFO_KEY, pr_info_str, &len);
+	*buf = pr_info_str;
+
+	return ret;
+}
+
 static int tcmu_rbd_open(struct tcmu_device *dev, bool reopen)
 {
 	rbd_image_info_t image_info;
@@ -904,6 +937,7 @@ static int tcmu_rbd_open(struct tcmu_device *dev, bool reopen)
 	tcmu_set_dev_write_cache_enabled(dev, 0);
 
 	free(dev_cfg_dup);
+	tcmu_rbd_pr_set(dev, "");
 	return 0;
 
 stop_image:
@@ -1431,6 +1465,8 @@ struct tcmur_handler tcmu_rbd_handler = {
 	.read	       = tcmu_rbd_read,
 	.write	       = tcmu_rbd_write,
 	.reconfig      = tcmu_rbd_reconfig,
+	.set_pr_info   = tcmu_rbd_pr_set,
+	.get_pr_info   = tcmu_rbd_pr_get,
 #ifdef LIBRBD_SUPPORTS_AIO_FLUSH
 	.flush	       = tcmu_rbd_flush,
 #endif
diff --git a/target_core_user_local.h b/target_core_user_local.h
index 2cdb3e5..aefa688 100644
--- a/target_core_user_local.h
+++ b/target_core_user_local.h
@@ -4,7 +4,7 @@
 /* This header will be used by application too */
 
 #include <linux/types.h>
-#include <linux/uio.h>
+//#include <linux/uio.h>
 
 #define TCMU_VERSION "2.0"
 
@@ -131,9 +131,13 @@ enum tcmu_genl_cmd {
 	TCMU_CMD_ADDED_DEVICE,
 	TCMU_CMD_REMOVED_DEVICE,
 	TCMU_CMD_RECONFIG_DEVICE,
+	TCMU_CMD_GET_PR_INFO,
+	TCMU_CMD_SET_PR_INFO,
 	TCMU_CMD_ADDED_DEVICE_DONE,
 	TCMU_CMD_REMOVED_DEVICE_DONE,
 	TCMU_CMD_RECONFIG_DEVICE_DONE,
+	TCMU_CMD_GET_PR_INFO_DONE,
+	TCMU_CMD_SET_PR_INFO_DONE,
 	TCMU_CMD_SET_FEATURES,
 	__TCMU_CMD_MAX,
 };
@@ -150,6 +154,7 @@ enum tcmu_genl_attr {
 	TCMU_ATTR_CMD_STATUS,
 	TCMU_ATTR_DEVICE_ID,
 	TCMU_ATTR_SUPP_KERN_CMD_REPLY,
+	TCMU_ATTR_PR_INFO,
 	__TCMU_ATTR_MAX,
 };
 #define TCMU_ATTR_MAX (__TCMU_ATTR_MAX - 1)
diff --git a/tcmu-runner.h b/tcmu-runner.h
index b423fc5..792ba7f 100644
--- a/tcmu-runner.h
+++ b/tcmu-runner.h
@@ -133,6 +133,9 @@ struct tcmur_handler {
 	 * indicating success/failure.
 	 */
 	int (*get_lock_tag)(struct tcmu_device *dev, uint16_t *tag);
+	int (*set_pr_info)(struct tcmu_device *dev, char *pr_info);
+	int (*get_pr_info)(struct tcmu_device *dev, char **buf);
+
 
 	/*
 	 * internal field, don't touch this
