Commit a72c5e5e authored by Nao Nishijima's avatar Nao Nishijima Committed by James Bottomley

[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: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
Suggested-by: default avatarJon Masters <jcm@redhat.com>
Signed-off-by: default avatarNao Nishijima <nao.nishijima.xt@hitachi.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 76e4e12f
...@@ -206,3 +206,16 @@ Description: ...@@ -206,3 +206,16 @@ Description:
when a discarded area is read the discard_zeroes_data when a discarded area is read the discard_zeroes_data
parameter will be set to one. Otherwise it will be 0 and parameter will be set to one. Otherwise it will be 0 and
the result of reading a discarded area is undefined. the result of reading a discarded area is undefined.
What: /sys/block/<disk>/alias
Date: Aug 2011
Contact: Nao Nishijima <nao.nishijima.xt@hitachi.com>
Description:
A raw device name of a disk does not always point a same disk
each boot-up time. Therefore, users have to use persistent
device names, which udev creates when the kernel finds a disk,
instead of raw device name. However, kernel doesn't show those
persistent names on its messages (e.g. dmesg).
This file can store an alias of the disk and it would be
appeared in kernel messages if it is set. A disk can have an
alias which length is up to 255bytes. Users can use alphabets,
numbers, "-" and "_" in alias name. This file is writeonce.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/ctype.h>
#include "blk.h" #include "blk.h"
...@@ -909,6 +910,74 @@ static int __init genhd_device_init(void) ...@@ -909,6 +910,74 @@ static int __init genhd_device_init(void)
subsys_initcall(genhd_device_init); subsys_initcall(genhd_device_init);
static ssize_t alias_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct gendisk *disk = dev_to_disk(dev);
ssize_t ret = 0;
if (disk->alias)
ret = snprintf(buf, ALIAS_LEN, "%s\n", disk->alias);
return ret;
}
static ssize_t alias_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct gendisk *disk = dev_to_disk(dev);
char *alias;
char *envp[] = { NULL, NULL };
unsigned char c;
int i;
ssize_t ret = count;
if (!count)
return -EINVAL;
if (count >= ALIAS_LEN) {
printk(KERN_ERR "alias: alias is too long\n");
return -EINVAL;
}
/* Validation check */
for (i = 0; i < count; i++) {
c = buf[i];
if (i == count - 1 && c == '\n')
break;
if (!isalnum(c) && c != '_' && c != '-') {
printk(KERN_ERR "alias: invalid alias\n");
return -EINVAL;
}
}
if (disk->alias) {
printk(KERN_INFO "alias: %s is already assigned (%s)\n",
disk->disk_name, disk->alias);
return -EINVAL;
}
alias = kasprintf(GFP_KERNEL, "%s", buf);
if (!alias)
return -ENOMEM;
if (alias[count - 1] == '\n')
alias[count - 1] = '\0';
envp[0] = kasprintf(GFP_KERNEL, "ALIAS=%s", alias);
if (!envp[0]) {
kfree(alias);
return -ENOMEM;
}
disk->alias = alias;
printk(KERN_INFO "alias: assigned %s to %s\n", alias, disk->disk_name);
kobject_uevent_env(&dev->kobj, KOBJ_ADD, envp);
kfree(envp[0]);
return ret;
}
static ssize_t disk_range_show(struct device *dev, static ssize_t disk_range_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -968,6 +1037,7 @@ static ssize_t disk_discard_alignment_show(struct device *dev, ...@@ -968,6 +1037,7 @@ static ssize_t disk_discard_alignment_show(struct device *dev,
return sprintf(buf, "%d\n", queue_discard_alignment(disk->queue)); return sprintf(buf, "%d\n", queue_discard_alignment(disk->queue));
} }
static DEVICE_ATTR(alias, S_IRUGO|S_IWUSR, alias_show, alias_store);
static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL);
static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL);
static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL);
...@@ -990,6 +1060,7 @@ static struct device_attribute dev_attr_fail_timeout = ...@@ -990,6 +1060,7 @@ static struct device_attribute dev_attr_fail_timeout =
#endif #endif
static struct attribute *disk_attrs[] = { static struct attribute *disk_attrs[] = {
&dev_attr_alias.attr,
&dev_attr_range.attr, &dev_attr_range.attr,
&dev_attr_ext_range.attr, &dev_attr_ext_range.attr,
&dev_attr_removable.attr, &dev_attr_removable.attr,
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#define dev_to_part(device) container_of((device), struct hd_struct, __dev) #define dev_to_part(device) container_of((device), struct hd_struct, __dev)
#define disk_to_dev(disk) (&(disk)->part0.__dev) #define disk_to_dev(disk) (&(disk)->part0.__dev)
#define part_to_dev(part) (&((part)->__dev)) #define part_to_dev(part) (&((part)->__dev))
#define alias_name(disk) ((disk)->alias ? (disk)->alias : \
(disk)->disk_name)
extern struct device_type part_type; extern struct device_type part_type;
extern struct kobject *block_depr; extern struct kobject *block_depr;
...@@ -58,6 +60,7 @@ enum { ...@@ -58,6 +60,7 @@ enum {
#define DISK_MAX_PARTS 256 #define DISK_MAX_PARTS 256
#define DISK_NAME_LEN 32 #define DISK_NAME_LEN 32
#define ALIAS_LEN 256
#include <linux/major.h> #include <linux/major.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -162,6 +165,7 @@ struct gendisk { ...@@ -162,6 +165,7 @@ struct gendisk {
* disks that can't be partitioned. */ * disks that can't be partitioned. */
char disk_name[DISK_NAME_LEN]; /* name of major driver */ char disk_name[DISK_NAME_LEN]; /* name of major driver */
char *alias; /* alias name of disk */
char *(*devnode)(struct gendisk *gd, mode_t *mode); char *(*devnode)(struct gendisk *gd, mode_t *mode);
unsigned int events; /* supported events */ unsigned int events; /* supported events */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment