From 7f5f654ff252cfc899c52c848f3e08c55f778f51 Mon Sep 17 00:00:00 2001
From: Shaoxiong Li <dahefanteng@gmail.com>
Date: Wed, 12 Sep 2018 14:48:31 +0800
Subject: [PATCH 06/16] bcache-tools: Allow user to set label for device
Git-commit: 7f5f654ff252cfc899c52c848f3e08c55f778f51
Patch-mainline: bcache-tools-1.1
References: bsc#1139948

Add option '--label' for  'bcache make' to add label to bcache
device
Add subcommand 'set-label' which is used to set label for
active backend device
Only users with root privilege are allowd to run the 'bcache' command

Signed-off-by: Shaoxiong Li <dahefanteng@gmail.com>
Signed-off-by: Coly Li <colyli@suse.de>
---
 bcache-main.c | 42 +++++++++++++++++++++++++++++++++++++-----
 lib.c         | 45 +++++++++++++++++++++++++++++++++++++--------
 lib.h         |  1 +
 make.c        | 30 +++++++++++++++++++++++-------
 4 files changed, 98 insertions(+), 20 deletions(-)

diff --git a/bcache-main.c b/bcache-main.c
index 53da0bb..e424535 100644
--- a/bcache-main.c
+++ b/bcache-main.c
@@ -52,7 +52,7 @@ bool bad_uuid(char *uuid)
 	regmatch_t regmatche;
 
 	if (regcomp(&reg, pattern, REG_EXTENDED) != 0)
-		fprintf(stderr, "Error happen when check uuid format:%m");
+		fprintf(stderr, "Error happen when check uuid format:%m\n");
 	status = regexec(&reg, uuid, 1, &regmatche, 0);
 	regfree(&reg);
 	if (status == REG_NOMATCH)
@@ -70,7 +70,7 @@ bool bad_dev(char *devname)
 
 	if (regcomp(&reg, pattern, REG_EXTENDED) != 0) {
 		fprintf(stderr,
-			"Error happen when check device name format:%m");
+			"Error happen when check device name format:%m\n");
 	}
 	status = regexec(&reg, devname, 1, &regmatche, 0);
 	regfree(&reg);
@@ -92,7 +92,8 @@ int main_usage(void)
 		"	unregister	unregister device from kernel\n"
 		"	attach		attach backend device(data device) to cache device\n"
 		"	detach		detach backend device(data device) from cache device\n"
-		"	set-cachemode	set cachemode for backend device\n");
+		"	set-cachemode	set cachemode for backend device\n"
+		"	set-label	set label for backend device\n");
 	return EXIT_FAILURE;
 }
 
@@ -146,6 +147,12 @@ int setcachemode_usage(void)
 	return EXIT_FAILURE;
 }
 
+int setlabel_usage(void)
+{
+	fprintf(stderr,
+		"Usage:set-label devicename label\n(only for backend device)\n");
+	return EXIT_FAILURE;
+}
 
 void free_dev(struct list_head *head)
 {
@@ -462,7 +469,7 @@ int attach_both(char *cdev, char *backdev)
 		ret = detail_dev(cdev, &bd, &cd, &type);
 		if (type != BCACHE_SB_VERSION_CDEV
 		    && type != BCACHE_SB_VERSION_CDEV_WITH_UUID) {
-			fprintf(stderr, "%s is not an cache device", cdev);
+			fprintf(stderr, "%s is not an cache device\n", cdev);
 			return 1;
 		}
 		strcpy(buf, cd.base.cset);
@@ -472,10 +479,24 @@ int attach_both(char *cdev, char *backdev)
 	return attach_backdev(buf, backdev);
 }
 
+bool has_permission(void)
+{
+	uid_t euid = geteuid();
+
+	if (euid != 0)
+		return false;
+	return true;
+}
+
 int main(int argc, char **argv)
 {
 	char *subcmd;
 
+	if (!has_permission()) {
+		fprintf(stderr,
+		"Only root or users who has root priviledges can run this command\n");
+		return 1;
+	}
 	if (argc < 2) {
 		main_usage();
 		return 1;
@@ -592,7 +613,18 @@ int main(int argc, char **argv)
 			fprintf(stderr, "Error:Wrong device name found\n");
 			return 1;
 		}
-		return set_backdev_cachemode(argv[1], argv[2]);
+	} else if (strcmp(subcmd, "set-label") == 0) {
+		if (argc != 3)
+			return setlabel_usage();
+		if (bad_dev(argv[1])) {
+			fprintf(stderr, "Error:Wrong device name found\n");
+			return 1;
+		}
+		if (strlen(argv[2]) >= SB_LABEL_SIZE) {
+			fprintf(stderr, "Label is too long\n");
+			return 1;
+		}
+		return set_label(argv[1], argv[2]);
 	}
 	main_usage();
 	return 0;
diff --git a/lib.c b/lib.c
index a15c263..6592110 100644
--- a/lib.c
+++ b/lib.c
@@ -79,7 +79,7 @@ bool part_of_disk(char *devname, char *partname)
 
 	sprintf(pattern, "^%s.*[0-9]$", devname);
 	if (regcomp(&reg, pattern, REG_EXTENDED) != 0)
-		fprintf(stderr, "Error happen when compile reg");
+		fprintf(stderr, "Error happen when compile reg\n");
 	status = regexec(&reg, partname, 1, &regmatche, 0);
 	regfree(&reg);
 	if (status == REG_NOMATCH)
@@ -96,7 +96,7 @@ int find_location(char *location, char *devname)
 
 	blockdir = opendir("/sys/block");
 	if (blockdir == NULL) {
-		fprintf(stderr, "Failed to open dir /sys/block/");
+		fprintf(stderr, "Failed to open dir /sys/block/\n");
 		return 1;
 	}
 	sprintf(path, "/sys/block/%s/bcache", devname);
@@ -426,7 +426,7 @@ int detail_dev(char *devname, struct bdev *bd, struct cdev *cd, int *type)
 
 	expected_csum = csum_set(&sb);
 	if (!(sb.csum == expected_csum)) {
-		fprintf(stderr, "Csum is not match with expected one");
+		fprintf(stderr, "Csum is not match with expected one\n");
 		goto Fail;
 	}
 
@@ -448,7 +448,7 @@ int detail_dev(char *devname, struct bdev *bd, struct cdev *cd, int *type)
 		cd->pos = sb.nr_this_dev;
 		cd->replacement = CACHE_REPLACEMENT(&sb);
 	} else {
-		fprintf(stderr, "Unknown bcache device type found");
+		fprintf(stderr, "Unknown bcache device type found\n");
 		goto Fail;
 	}
 	return 0;
@@ -490,7 +490,7 @@ int unregister_cset(char *cset)
 		return 1;
 	}
 	if (dprintf(fd, "%d\n", 1) < 0) {
-		fprintf(stderr, "Failed to unregist this cache device");
+		fprintf(stderr, "Failed to unregister this cache device\n");
 		close(fd);
 		return 1;
 	}
@@ -537,7 +537,7 @@ int unregister_both(char *cset)
 		return 1;
 	}
 	if (dprintf(fd, "%d\n", 1) < 0) {
-		fprintf(stderr, "Failed to stop cset and its backends %m");
+		fprintf(stderr, "Failed to stop cset and its backends %m\n");
 		close(fd);
 		return 1;
 	}
@@ -592,7 +592,7 @@ int detach_backdev(char *devname)
 	}
 	if (dprintf(fd, "%d\n", 1) < 0) {
 		close(fd);
-		fprintf(stderr, "Error detach device %s:%m", devname);
+		fprintf(stderr, "Error detach device %s:%m\n", devname);
 		return 1;
 	}
 	close(fd);
@@ -619,7 +619,7 @@ int set_backdev_cachemode(char *devname, char *cachemode)
 		return 1;
 	}
 	if (dprintf(fd, "%s\n", cachemode) < 0) {
-		printf("Failed to set cachemode for device %s:%m\n",
+		fprintf(stderr, "Failed to set cachemode for device %s:%m\n",
 		       devname);
 		close(fd);
 		return 1;
@@ -653,3 +653,32 @@ int get_backdev_cachemode(char *devname, char *mode)
 	close(fd);
 	return 0;
 }
+
+int set_label(char *devname, char *label)
+{
+	int fd, ret;
+	char path[150];
+	char location[100] = "";
+	char buf[20];
+
+	trim_prefix(buf, devname, DEV_PREFIX_LEN);
+	ret = find_location(location, buf);
+	if (ret < 0)
+		return ret;
+	sprintf(path, "/sys/block/%s/bcache/label", location);
+	fd = open(path, O_WRONLY);
+	if (fd < 0) {
+		fprintf(stderr,
+			"Can't open %s,Make sure the device name is correct\n",
+			path);
+		return 1;
+	}
+	if (dprintf(fd, "%s\n", label) < 0) {
+		fprintf(stderr, "Failed to set label for device %s:%m\n",
+		       devname);
+		close(fd);
+		return 1;
+	}
+	close(fd);
+	return 0;
+}
diff --git a/lib.h b/lib.h
index becc039..d4537b0 100644
--- a/lib.h
+++ b/lib.h
@@ -48,6 +48,7 @@ int unregister_cset(char *cset);
 int attach_backdev(char *cset, char *devname);
 int detach_backdev(char *devname);
 int set_backdev_cachemode(char *devname, char *cachemode);
+int set_label(char *devname, char *label);
 int cset_to_devname(struct list_head *head, char *cset, char *devname);
 
 
diff --git a/make.c b/make.c
index 98eac78..b50bf80 100644
--- a/make.c
+++ b/make.c
@@ -166,6 +166,7 @@ void usage(void)
 	       "	    --writeback		enable writeback\n"
 	       "	    --discard		enable discards\n"
 	       "	    --force		reformat a bcache device even if it is running\n"
+	       "	-l, --label		set label for device\n"
 	       "	    --cache_replacement_policy=(lru|fifo)\n"
 	       "	-h, --help		display this help and exit\n");
 	exit(EXIT_FAILURE);
@@ -183,7 +184,7 @@ static void write_sb(char *dev, unsigned int block_size,
 			bool writeback, bool discard, bool wipe_bcache,
 			unsigned int cache_replacement_policy,
 			uint64_t data_offset,
-			uuid_t set_uuid, bool bdev, bool force)
+			uuid_t set_uuid, bool bdev, bool force, char *label)
 {
 	int fd;
 	char uuid_str[40], set_uuid_str[40], zeroes[SB_START] = {0};
@@ -253,7 +254,7 @@ static void write_sb(char *dev, unsigned int block_size,
 			if (pwrite(fd, zeroes, sizeof(sb),
 				SB_START) != sizeof(sb)) {
 				fprintf(stderr,
-					"Failed to erase super block for %s",
+					"Failed to erase super block for %s\n",
 					dev);
 				exit(EXIT_FAILURE);
 			}
@@ -354,8 +355,15 @@ static void write_sb(char *dev, unsigned int block_size,
 		putchar('\n');
 	}
 
-	sb.csum = csum_set(&sb);
+	/* write label */
+	int num, i;
 
+	num = strlen(label);
+	for (i = 0; i < num; i++)
+		sb.label[i] = label[i];
+	sb.label[i] = '\0';
+	/* write csum */
+	sb.csum = csum_set(&sb);
 	/* Zero start of disk */
 	if (pwrite(fd, zeroes, SB_START, 0) != SB_START) {
 		perror("write error\n");
@@ -419,7 +427,7 @@ int make_bcache(int argc, char **argv)
 	unsigned int i, ncache_devices = 0, nbacking_devices = 0;
 	char *cache_devices[argc];
 	char *backing_devices[argc];
-
+	char label[SB_LABEL_SIZE];
 	unsigned int block_size = 0, bucket_size = 1024;
 	int writeback = 0, discard = 0, wipe_bcache = 0, force = 0;
 	unsigned int cache_replacement_policy = 0;
@@ -443,11 +451,12 @@ int make_bcache(int argc, char **argv)
 		{ "cset-uuid",		1, NULL,	'u' },
 		{ "help",		0, NULL,	'h' },
 		{ "force",		0, &force,	 1 },
+		{ "label",		1, NULL,	 'l' },
 		{ NULL,			0, NULL,	0 },
 	};
 
 	while ((c = getopt_long(argc, argv,
-				"-hCBUo:w:b:",
+				"-hCBUo:w:b:l:",
 				opts, NULL)) != -1)
 		switch (c) {
 		case 'C':
@@ -489,6 +498,13 @@ int make_bcache(int argc, char **argv)
 				exit(EXIT_FAILURE);
 			}
 			break;
+		case 'l':
+			if (strlen(optarg) >= SB_LABEL_SIZE) {
+				fprintf(stderr, "Label is too long\n");
+				exit(EXIT_FAILURE);
+			}
+			strcpy(label, optarg);
+			break;
 		case 'h':
 			usage();
 			break;
@@ -530,13 +546,13 @@ int make_bcache(int argc, char **argv)
 		write_sb(cache_devices[i], block_size, bucket_size,
 			 writeback, discard, wipe_bcache,
 			 cache_replacement_policy,
-			 data_offset, set_uuid, false, force);
+			 data_offset, set_uuid, false, force, label);
 
 	for (i = 0; i < nbacking_devices; i++)
 		write_sb(backing_devices[i], block_size, bucket_size,
 			 writeback, discard, wipe_bcache,
 			 cache_replacement_policy,
-			 data_offset, set_uuid, true, force);
+			 data_offset, set_uuid, true, force, label);
 
 	return 0;
 }
-- 
2.25.0

