[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