diff options
author | Nao Nishijima <nao.nishijima.xt@hitachi.com> | 2011-08-25 05:04:06 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-08-29 03:16:19 -0400 |
commit | a72c5e5eb738033938ab30d6a634b74d1d060f10 (patch) | |
tree | 72cea6d75a62f7003d55f8a754c2d17149ada85f /block | |
parent | 76e4e12ff2b3ef86773989fd897b194eb38016e6 (diff) |
[SCSI] genhd: add a new attribute "alias" in gendisk
This patch allows the user to set an "alias" of the disk via sysfs interface.
This patch only adds a new attribute "alias" in gendisk structure.
To show the alias instead of the device name in kernel messages,
we need to revise printk messages and use alias_name() in them.
Example:
(current) printk("disk name is %s\n", disk->disk_name);
(new) printk("disk name is %s\n", alias_name(disk));
Users can use alphabets, numbers, '-' and '_' in "alias" attribute. A disk can
have an "alias" which length is up to 255 bytes. This attribute is write-once.
Suggested-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Suggested-by: Jon Masters <jcm@redhat.com>
Signed-off-by: Nao Nishijima <nao.nishijima.xt@hitachi.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/genhd.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/block/genhd.c b/block/genhd.c index e2f67902dd02..94855a9717de 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
20 | #include <linux/idr.h> | 20 | #include <linux/idr.h> |
21 | #include <linux/log2.h> | 21 | #include <linux/log2.h> |
22 | #include <linux/ctype.h> | ||
22 | 23 | ||
23 | #include "blk.h" | 24 | #include "blk.h" |
24 | 25 | ||
@@ -909,6 +910,74 @@ static int __init genhd_device_init(void) | |||
909 | 910 | ||
910 | subsys_initcall(genhd_device_init); | 911 | subsys_initcall(genhd_device_init); |
911 | 912 | ||
913 | static ssize_t alias_show(struct device *dev, | ||
914 | struct device_attribute *attr, char *buf) | ||
915 | { | ||
916 | struct gendisk *disk = dev_to_disk(dev); | ||
917 | ssize_t ret = 0; | ||
918 | |||
919 | if (disk->alias) | ||
920 | ret = snprintf(buf, ALIAS_LEN, "%s\n", disk->alias); | ||
921 | return ret; | ||
922 | } | ||
923 | |||
924 | static ssize_t alias_store(struct device *dev, struct device_attribute *attr, | ||
925 | const char *buf, size_t count) | ||
926 | { | ||
927 | struct gendisk *disk = dev_to_disk(dev); | ||
928 | char *alias; | ||
929 | char *envp[] = { NULL, NULL }; | ||
930 | unsigned char c; | ||
931 | int i; | ||
932 | ssize_t ret = count; | ||
933 | |||
934 | if (!count) | ||
935 | return -EINVAL; | ||
936 | |||
937 | if (count >= ALIAS_LEN) { | ||
938 | printk(KERN_ERR "alias: alias is too long\n"); | ||
939 | return -EINVAL; | ||
940 | } | ||
941 | |||
942 | /* Validation check */ | ||
943 | for (i = 0; i < count; i++) { | ||
944 | c = buf[i]; | ||
945 | if (i == count - 1 && c == '\n') | ||
946 | break; | ||
947 | if (!isalnum(c) && c != '_' && c != '-') { | ||
948 | printk(KERN_ERR "alias: invalid alias\n"); | ||
949 | return -EINVAL; | ||
950 | } | ||
951 | } | ||
952 | |||
953 | if (disk->alias) { | ||
954 | printk(KERN_INFO "alias: %s is already assigned (%s)\n", | ||
955 | disk->disk_name, disk->alias); | ||
956 | return -EINVAL; | ||
957 | } | ||
958 | |||
959 | alias = kasprintf(GFP_KERNEL, "%s", buf); | ||
960 | if (!alias) | ||
961 | return -ENOMEM; | ||
962 | |||
963 | if (alias[count - 1] == '\n') | ||
964 | alias[count - 1] = '\0'; | ||
965 | |||
966 | envp[0] = kasprintf(GFP_KERNEL, "ALIAS=%s", alias); | ||
967 | if (!envp[0]) { | ||
968 | kfree(alias); | ||
969 | return -ENOMEM; | ||
970 | } | ||
971 | |||
972 | disk->alias = alias; | ||
973 | printk(KERN_INFO "alias: assigned %s to %s\n", alias, disk->disk_name); | ||
974 | |||
975 | kobject_uevent_env(&dev->kobj, KOBJ_ADD, envp); | ||
976 | |||
977 | kfree(envp[0]); | ||
978 | return ret; | ||
979 | } | ||
980 | |||
912 | static ssize_t disk_range_show(struct device *dev, | 981 | static ssize_t disk_range_show(struct device *dev, |
913 | struct device_attribute *attr, char *buf) | 982 | struct device_attribute *attr, char *buf) |
914 | { | 983 | { |
@@ -968,6 +1037,7 @@ static ssize_t disk_discard_alignment_show(struct device *dev, | |||
968 | return sprintf(buf, "%d\n", queue_discard_alignment(disk->queue)); | 1037 | return sprintf(buf, "%d\n", queue_discard_alignment(disk->queue)); |
969 | } | 1038 | } |
970 | 1039 | ||
1040 | static DEVICE_ATTR(alias, S_IRUGO|S_IWUSR, alias_show, alias_store); | ||
971 | static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); | 1041 | static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); |
972 | static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); | 1042 | static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); |
973 | static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); | 1043 | static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); |
@@ -990,6 +1060,7 @@ static struct device_attribute dev_attr_fail_timeout = | |||
990 | #endif | 1060 | #endif |
991 | 1061 | ||
992 | static struct attribute *disk_attrs[] = { | 1062 | static struct attribute *disk_attrs[] = { |
1063 | &dev_attr_alias.attr, | ||
993 | &dev_attr_range.attr, | 1064 | &dev_attr_range.attr, |
994 | &dev_attr_ext_range.attr, | 1065 | &dev_attr_ext_range.attr, |
995 | &dev_attr_removable.attr, | 1066 | &dev_attr_removable.attr, |