Commit 784aae735d9b0bba3f8b9faef4c8b30df3bf0128
Committed by
Alasdair G Kergon
1 parent
d58168763f
Exists in
master
and in
7 other branches
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>
Showing 4 changed files with 136 additions and 2 deletions Side-by-side Diff
drivers/md/Makefile
... | ... | @@ -3,7 +3,7 @@ |
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 |
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 | +} |
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,6 +167,9 @@ |
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 |
... | ... | @@ -1285,6 +1288,8 @@ |
1285 | 1288 | if (!md) |
1286 | 1289 | return -ENXIO; |
1287 | 1290 | |
1291 | + dm_sysfs_init(md); | |
1292 | + | |
1288 | 1293 | *result = md; |
1289 | 1294 | return 0; |
1290 | 1295 | } |
... | ... | @@ -1360,6 +1365,7 @@ |
1360 | 1365 | dm_table_presuspend_targets(map); |
1361 | 1366 | dm_table_postsuspend_targets(map); |
1362 | 1367 | } |
1368 | + dm_sysfs_exit(md); | |
1363 | 1369 | dm_table_put(map); |
1364 | 1370 | __unbind(md); |
1365 | 1371 | free_dev(md); |
... | ... | @@ -1697,6 +1703,27 @@ |
1697 | 1703 | struct gendisk *dm_disk(struct mapped_device *md) |
1698 | 1704 | { |
1699 | 1705 | return md->disk; |
1706 | +} | |
1707 | + | |
1708 | +struct kobject *dm_kobject(struct mapped_device *md) | |
1709 | +{ | |
1710 | + return &md->kobj; | |
1711 | +} | |
1712 | + | |
1713 | +/* | |
1714 | + * struct mapped_device should not be exported outside of dm.c | |
1715 | + * so use this check to verify that kobj is part of md structure | |
1716 | + */ | |
1717 | +struct mapped_device *dm_get_from_kobject(struct kobject *kobj) | |
1718 | +{ | |
1719 | + struct mapped_device *md; | |
1720 | + | |
1721 | + md = container_of(kobj, struct mapped_device, kobj); | |
1722 | + if (&md->kobj != kobj) | |
1723 | + return NULL; | |
1724 | + | |
1725 | + dm_get(md); | |
1726 | + return md; | |
1700 | 1727 | } |
1701 | 1728 | |
1702 | 1729 | int dm_suspended(struct mapped_device *md) |
drivers/md/dm.h
... | ... | @@ -74,6 +74,14 @@ |
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); |