[Devel] [PATCH VZ9 v3 5/5] block/blk-cbt: add BLKCBTRENAME instead of BLKCBTSET flag

Andrey Zhadchenko andrey.zhadchenko at virtuozzo.com
Tue Jan 28 11:15:09 MSK 2025


Users could rename cbts with CI_FLAG_NEW_NAME flag during
BLKCBTSET ioctl. Set command now uses ci_name to identify
target, so we need a new field to present updated name.
Add new BLKCBTRENAME ioctl instead of adding new fields to
blk_user_cbt_info.

Note that we do not need to extra protect cbt->name: it is only
used by
 - concurrent userspace commands, which are also taking cbt_mutex
 - cbt_page_alloc + CBT_DEAD bit. Fortunately CBT_DEAD bit can
only occur during another user space command, which again is
helding cbt_mutex.

https://virtuozzo.atlassian.net/browse/VSTOR-96269
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
---
v2:
 - call all copy_from_user() before taking mutex_lock

 block/blk-cbt.c         | 45 ++++++++++++++++++++++++++++++++++++-----
 block/ioctl.c           |  1 +
 include/uapi/linux/fs.h |  2 +-
 3 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/block/blk-cbt.c b/block/blk-cbt.c
index 5e5f224cf8f4..fa472aa5d006 100644
--- a/block/blk-cbt.c
+++ b/block/blk-cbt.c
@@ -946,11 +946,6 @@ static int cbt_ioc_set(struct block_device *bdev, struct blk_user_cbt_info __use
 	if (!cbt)
 		goto ioc_set_failed;
 
-	if (ci.ci_flags & CI_FLAG_NEW_NAME)
-		memcpy(cbt->name, &ci.ci_name, sizeof(ci.ci_name));
-	else if (memcmp(cbt->name, &ci.ci_name, sizeof(ci.ci_name)))
-		goto ioc_set_failed;
-
 	ret = -EIO;
 	if (test_bit(CBT_ERROR, &cbt->flags))
 		goto ioc_set_failed;
@@ -1020,6 +1015,44 @@ static int cbt_ioc_list(struct block_device *bdev, void __user *arg)
 	return 0;
 }
 
+static int cbt_ioc_rename(struct block_device *bdev, void __user *arg)
+{
+	struct request_queue *q = bdev_get_queue(bdev);
+	struct blk_user_cbt_list lst;
+	char from[CBT_NAME_LENGTH], to[CBT_NAME_LENGTH];
+	struct cbt_info *cbt;
+
+	if (copy_from_user(&lst, arg, sizeof(lst)))
+		return -EFAULT;
+
+	if (lst.count != 2)
+		return -EINVAL;
+
+	if (copy_from_user(from, (char *)arg + sizeof(lst), CBT_NAME_LENGTH))
+		return -EFAULT;
+
+	if (copy_from_user(to, (char *)arg + sizeof(lst) + CBT_NAME_LENGTH, CBT_NAME_LENGTH))
+		return -EFAULT;
+
+	mutex_lock(&cbt_mutex);
+
+	cbt = blk_cbt_find(q, from);
+	if (!cbt) {
+		mutex_unlock(&cbt_mutex);
+		return -ENOENT;
+	}
+
+	if (blk_cbt_find(q, to)) {
+		mutex_unlock(&cbt_mutex);
+		return -EINVAL;
+	}
+
+	memcpy(cbt->name, to, CBT_NAME_LENGTH);
+	mutex_unlock(&cbt_mutex);
+
+	return 0;
+}
+
 static int cbt_ioc_misc(struct block_device *bdev, void __user *arg)
 {
 	struct request_queue *q = bdev_get_queue(bdev);
@@ -1077,6 +1110,8 @@ int blk_cbt_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
 		return cbt_ioc_misc(bdev, arg);
 	case BLKCBTLIST:
 		return cbt_ioc_list(bdev, arg);
+	case BLKCBTRENAME:
+		return cbt_ioc_rename(bdev, arg);
 	default:
 		BUG();
 	}
diff --git a/block/ioctl.c b/block/ioctl.c
index 6e76d55790ea..05d79953b2c0 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -570,6 +570,7 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
 	case BLKCBTCLR:
 	case BLKCBTMISC:
 	case BLKCBTLIST:
+	case BLKCBTRENAME:
 		return blk_cbt_ioctl(bdev, cmd, (char __user *)arg);
 	default:
 		return -ENOIOCTLCMD;
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 3122e2783eda..4ab115091bab 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -151,7 +151,6 @@ struct blk_user_cbt_info {
 enum CI_FLAGS
 {
 	CI_FLAG_ONCE = 1, /* BLKCBTGET will clear bits */
-	CI_FLAG_NEW_NAME = 2 /* BLKCBTSET update name */
 };
 
 /* Extension of cbt ioctls:  */
@@ -189,6 +188,7 @@ struct blk_user_cbt_list {
 #define BLKCBTCLR _IOR(0x12,204,struct blk_user_cbt_info)
 #define BLKCBTMISC _IOWR(0x12,205,struct blk_user_cbt_misc_info)
 #define BLKCBTLIST _IOWR(0x12, 206, struct blk_user_cbt_list)
+#define BLKCBTRENAME _IOWR(0x12, 207, struct blk_user_cbt_list)
 
 /*
  * Flags for the fsx_xflags field
-- 
2.39.3



More information about the Devel mailing list