dm: add name and uuid to sysfs

Implement simple read-only sysfs entry for device-mapper block device.

This patch adds a simple sysfs directory named "dm" under block device
properties and implements
- name attribute (string containing mapped device name)
- uuid attribute (string containing UUID, or empty string if not set)

The kobject is embedded in mapped_device struct, so no additional
memory allocation is needed for initializing sysfs entry.

During the processing of sysfs attribute we need to lock mapped device
which is done by a new function dm_get_from_kobj, which returns the md
associated with kobject and increases the usage count.

Each 'show attribute' function is responsible for its own locking.

Signed-off-by: Milan Broz <mbroz@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

authored by

Milan Broz and committed by
Alasdair G Kergon
784aae73 d5816876

+136 -2
+1 -1
drivers/md/Makefile
··· 3 3 # 4 4 5 5 dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ 6 - dm-ioctl.o dm-io.o dm-kcopyd.o 6 + dm-ioctl.o dm-io.o dm-kcopyd.o dm-sysfs.o 7 7 dm-multipath-objs := dm-path-selector.o dm-mpath.o 8 8 dm-snapshot-objs := dm-snap.o dm-exception-store.o 9 9 dm-mirror-objs := dm-raid1.o
+99
drivers/md/dm-sysfs.c
··· 1 + /* 2 + * Copyright (C) 2008 Red Hat, Inc. All rights reserved. 3 + * 4 + * This file is released under the GPL. 5 + */ 6 + 7 + #include <linux/sysfs.h> 8 + #include <linux/dm-ioctl.h> 9 + #include "dm.h" 10 + 11 + struct dm_sysfs_attr { 12 + struct attribute attr; 13 + ssize_t (*show)(struct mapped_device *, char *); 14 + ssize_t (*store)(struct mapped_device *, char *); 15 + }; 16 + 17 + #define DM_ATTR_RO(_name) \ 18 + struct dm_sysfs_attr dm_attr_##_name = \ 19 + __ATTR(_name, S_IRUGO, dm_attr_##_name##_show, NULL) 20 + 21 + static ssize_t dm_attr_show(struct kobject *kobj, struct attribute *attr, 22 + char *page) 23 + { 24 + struct dm_sysfs_attr *dm_attr; 25 + struct mapped_device *md; 26 + ssize_t ret; 27 + 28 + dm_attr = container_of(attr, struct dm_sysfs_attr, attr); 29 + if (!dm_attr->show) 30 + return -EIO; 31 + 32 + md = dm_get_from_kobject(kobj); 33 + if (!md) 34 + return -EINVAL; 35 + 36 + ret = dm_attr->show(md, page); 37 + dm_put(md); 38 + 39 + return ret; 40 + } 41 + 42 + static ssize_t dm_attr_name_show(struct mapped_device *md, char *buf) 43 + { 44 + if (dm_copy_name_and_uuid(md, buf, NULL)) 45 + return -EIO; 46 + 47 + strcat(buf, "\n"); 48 + return strlen(buf); 49 + } 50 + 51 + static ssize_t dm_attr_uuid_show(struct mapped_device *md, char *buf) 52 + { 53 + if (dm_copy_name_and_uuid(md, NULL, buf)) 54 + return -EIO; 55 + 56 + strcat(buf, "\n"); 57 + return strlen(buf); 58 + } 59 + 60 + static DM_ATTR_RO(name); 61 + static DM_ATTR_RO(uuid); 62 + 63 + static struct attribute *dm_attrs[] = { 64 + &dm_attr_name.attr, 65 + &dm_attr_uuid.attr, 66 + NULL, 67 + }; 68 + 69 + static struct sysfs_ops dm_sysfs_ops = { 70 + .show = dm_attr_show, 71 + }; 72 + 73 + /* 74 + * dm kobject is embedded in mapped_device structure 75 + * no need to define release function here 76 + */ 77 + static struct kobj_type dm_ktype = { 78 + .sysfs_ops = &dm_sysfs_ops, 79 + .default_attrs = dm_attrs, 80 + }; 81 + 82 + /* 83 + * Initialize kobj 84 + * because nobody using md yet, no need to call explicit dm_get/put 85 + */ 86 + int dm_sysfs_init(struct mapped_device *md) 87 + { 88 + return kobject_init_and_add(dm_kobject(md), &dm_ktype, 89 + &disk_to_dev(dm_disk(md))->kobj, 90 + "%s", "dm"); 91 + } 92 + 93 + /* 94 + * Remove kobj, called after all references removed 95 + */ 96 + void dm_sysfs_exit(struct mapped_device *md) 97 + { 98 + kobject_put(dm_kobject(md)); 99 + }
+28 -1
drivers/md/dm.c
··· 1 1 /* 2 2 * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. 3 - * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 3 + * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. 4 4 * 5 5 * This file is released under the GPL. 6 6 */ ··· 167 167 168 168 /* forced geometry settings */ 169 169 struct hd_geometry geometry; 170 + 171 + /* sysfs handle */ 172 + struct kobject kobj; 170 173 }; 171 174 172 175 #define MIN_IOS 256 ··· 1288 1285 if (!md) 1289 1286 return -ENXIO; 1290 1287 1288 + dm_sysfs_init(md); 1289 + 1291 1290 *result = md; 1292 1291 return 0; 1293 1292 } ··· 1365 1360 dm_table_presuspend_targets(map); 1366 1361 dm_table_postsuspend_targets(map); 1367 1362 } 1363 + dm_sysfs_exit(md); 1368 1364 dm_table_put(map); 1369 1365 __unbind(md); 1370 1366 free_dev(md); ··· 1703 1697 struct gendisk *dm_disk(struct mapped_device *md) 1704 1698 { 1705 1699 return md->disk; 1700 + } 1701 + 1702 + struct kobject *dm_kobject(struct mapped_device *md) 1703 + { 1704 + return &md->kobj; 1705 + } 1706 + 1707 + /* 1708 + * struct mapped_device should not be exported outside of dm.c 1709 + * so use this check to verify that kobj is part of md structure 1710 + */ 1711 + struct mapped_device *dm_get_from_kobject(struct kobject *kobj) 1712 + { 1713 + struct mapped_device *md; 1714 + 1715 + md = container_of(kobj, struct mapped_device, kobj); 1716 + if (&md->kobj != kobj) 1717 + return NULL; 1718 + 1719 + dm_get(md); 1720 + return md; 1706 1721 } 1707 1722 1708 1723 int dm_suspended(struct mapped_device *md)
+8
drivers/md/dm.h
··· 74 74 void dm_interface_exit(void); 75 75 76 76 /* 77 + * sysfs interface 78 + */ 79 + int dm_sysfs_init(struct mapped_device *md); 80 + void dm_sysfs_exit(struct mapped_device *md); 81 + struct kobject *dm_kobject(struct mapped_device *md); 82 + struct mapped_device *dm_get_from_kobject(struct kobject *kobj); 83 + 84 + /* 77 85 * Targets for linear and striped mappings 78 86 */ 79 87 int dm_linear_init(void);