13bd94003SHeinz Mauelshagen // SPDX-License-Identifier: GPL-2.0-only
2784aae73SMilan Broz /*
3784aae73SMilan Broz * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
4784aae73SMilan Broz *
5784aae73SMilan Broz * This file is released under the GPL.
6784aae73SMilan Broz */
7784aae73SMilan Broz
8784aae73SMilan Broz #include <linux/sysfs.h>
9784aae73SMilan Broz #include <linux/dm-ioctl.h>
104cc96131SMike Snitzer #include "dm-core.h"
114cc96131SMike Snitzer #include "dm-rq.h"
12784aae73SMilan Broz
13784aae73SMilan Broz struct dm_sysfs_attr {
14784aae73SMilan Broz struct attribute attr;
1502f10ba1SHeinz Mauelshagen ssize_t (*show)(struct mapped_device *md, char *p);
1602f10ba1SHeinz Mauelshagen ssize_t (*store)(struct mapped_device *md, const char *p, size_t count);
17784aae73SMilan Broz };
18784aae73SMilan Broz
19784aae73SMilan Broz #define DM_ATTR_RO(_name) \
20784aae73SMilan Broz struct dm_sysfs_attr dm_attr_##_name = \
216a808034SHeinz Mauelshagen __ATTR(_name, 0444, dm_attr_##_name##_show, NULL)
22784aae73SMilan Broz
dm_attr_show(struct kobject * kobj,struct attribute * attr,char * page)23784aae73SMilan Broz static ssize_t dm_attr_show(struct kobject *kobj, struct attribute *attr,
24784aae73SMilan Broz char *page)
25784aae73SMilan Broz {
26784aae73SMilan Broz struct dm_sysfs_attr *dm_attr;
27784aae73SMilan Broz struct mapped_device *md;
28784aae73SMilan Broz ssize_t ret;
29784aae73SMilan Broz
30784aae73SMilan Broz dm_attr = container_of(attr, struct dm_sysfs_attr, attr);
31784aae73SMilan Broz if (!dm_attr->show)
32784aae73SMilan Broz return -EIO;
33784aae73SMilan Broz
34784aae73SMilan Broz md = dm_get_from_kobject(kobj);
35784aae73SMilan Broz if (!md)
36784aae73SMilan Broz return -EINVAL;
37784aae73SMilan Broz
38784aae73SMilan Broz ret = dm_attr->show(md, page);
39784aae73SMilan Broz dm_put(md);
40784aae73SMilan Broz
41784aae73SMilan Broz return ret;
42784aae73SMilan Broz }
43784aae73SMilan Broz
44b898320dSMike Snitzer #define DM_ATTR_RW(_name) \
45b898320dSMike Snitzer struct dm_sysfs_attr dm_attr_##_name = \
466a808034SHeinz Mauelshagen __ATTR(_name, 0644, dm_attr_##_name##_show, dm_attr_##_name##_store)
47b898320dSMike Snitzer
dm_attr_store(struct kobject * kobj,struct attribute * attr,const char * page,size_t count)48b898320dSMike Snitzer static ssize_t dm_attr_store(struct kobject *kobj, struct attribute *attr,
49b898320dSMike Snitzer const char *page, size_t count)
50b898320dSMike Snitzer {
51b898320dSMike Snitzer struct dm_sysfs_attr *dm_attr;
52b898320dSMike Snitzer struct mapped_device *md;
53b898320dSMike Snitzer ssize_t ret;
54b898320dSMike Snitzer
55b898320dSMike Snitzer dm_attr = container_of(attr, struct dm_sysfs_attr, attr);
56b898320dSMike Snitzer if (!dm_attr->store)
57b898320dSMike Snitzer return -EIO;
58b898320dSMike Snitzer
59b898320dSMike Snitzer md = dm_get_from_kobject(kobj);
60b898320dSMike Snitzer if (!md)
61b898320dSMike Snitzer return -EINVAL;
62b898320dSMike Snitzer
63b898320dSMike Snitzer ret = dm_attr->store(md, page, count);
64b898320dSMike Snitzer dm_put(md);
65b898320dSMike Snitzer
66b898320dSMike Snitzer return ret;
67b898320dSMike Snitzer }
68b898320dSMike Snitzer
dm_attr_name_show(struct mapped_device * md,char * buf)69784aae73SMilan Broz static ssize_t dm_attr_name_show(struct mapped_device *md, char *buf)
70784aae73SMilan Broz {
71784aae73SMilan Broz if (dm_copy_name_and_uuid(md, buf, NULL))
72784aae73SMilan Broz return -EIO;
73784aae73SMilan Broz
74784aae73SMilan Broz strcat(buf, "\n");
75784aae73SMilan Broz return strlen(buf);
76784aae73SMilan Broz }
77784aae73SMilan Broz
dm_attr_uuid_show(struct mapped_device * md,char * buf)78784aae73SMilan Broz static ssize_t dm_attr_uuid_show(struct mapped_device *md, char *buf)
79784aae73SMilan Broz {
80784aae73SMilan Broz if (dm_copy_name_and_uuid(md, NULL, buf))
81784aae73SMilan Broz return -EIO;
82784aae73SMilan Broz
83784aae73SMilan Broz strcat(buf, "\n");
84784aae73SMilan Broz return strlen(buf);
85784aae73SMilan Broz }
86784aae73SMilan Broz
dm_attr_suspended_show(struct mapped_device * md,char * buf)87486d220fSPeter Rajnoha static ssize_t dm_attr_suspended_show(struct mapped_device *md, char *buf)
88486d220fSPeter Rajnoha {
894f186f8bSKiyoshi Ueda sprintf(buf, "%d\n", dm_suspended_md(md));
90486d220fSPeter Rajnoha
91486d220fSPeter Rajnoha return strlen(buf);
92486d220fSPeter Rajnoha }
93486d220fSPeter Rajnoha
dm_attr_use_blk_mq_show(struct mapped_device * md,char * buf)9417e149b8SMike Snitzer static ssize_t dm_attr_use_blk_mq_show(struct mapped_device *md, char *buf)
9517e149b8SMike Snitzer {
966a23e05cSJens Axboe /* Purely for userspace compatibility */
976a23e05cSJens Axboe sprintf(buf, "%d\n", true);
9817e149b8SMike Snitzer
9917e149b8SMike Snitzer return strlen(buf);
10017e149b8SMike Snitzer }
10117e149b8SMike Snitzer
102784aae73SMilan Broz static DM_ATTR_RO(name);
103784aae73SMilan Broz static DM_ATTR_RO(uuid);
104486d220fSPeter Rajnoha static DM_ATTR_RO(suspended);
10517e149b8SMike Snitzer static DM_ATTR_RO(use_blk_mq);
1060ce65797SMike Snitzer static DM_ATTR_RW(rq_based_seq_io_merge_deadline);
107784aae73SMilan Broz
108784aae73SMilan Broz static struct attribute *dm_attrs[] = {
109784aae73SMilan Broz &dm_attr_name.attr,
110784aae73SMilan Broz &dm_attr_uuid.attr,
111486d220fSPeter Rajnoha &dm_attr_suspended.attr,
11217e149b8SMike Snitzer &dm_attr_use_blk_mq.attr,
1130ce65797SMike Snitzer &dm_attr_rq_based_seq_io_merge_deadline.attr,
114784aae73SMilan Broz NULL,
115784aae73SMilan Broz };
116eaac0b59SGreg Kroah-Hartman ATTRIBUTE_GROUPS(dm);
117784aae73SMilan Broz
11852cf25d0SEmese Revfy static const struct sysfs_ops dm_sysfs_ops = {
119784aae73SMilan Broz .show = dm_attr_show,
120b898320dSMike Snitzer .store = dm_attr_store,
121784aae73SMilan Broz };
122784aae73SMilan Broz
123*b0bbd86aSThomas Weißschuh static const struct kobj_type dm_ktype = {
124784aae73SMilan Broz .sysfs_ops = &dm_sysfs_ops,
125eaac0b59SGreg Kroah-Hartman .default_groups = dm_groups,
126be35f486SMikulas Patocka .release = dm_kobject_release,
127784aae73SMilan Broz };
128784aae73SMilan Broz
129784aae73SMilan Broz /*
130784aae73SMilan Broz * Initialize kobj
131784aae73SMilan Broz * because nobody using md yet, no need to call explicit dm_get/put
132784aae73SMilan Broz */
dm_sysfs_init(struct mapped_device * md)133784aae73SMilan Broz int dm_sysfs_init(struct mapped_device *md)
134784aae73SMilan Broz {
135784aae73SMilan Broz return kobject_init_and_add(dm_kobject(md), &dm_ktype,
136784aae73SMilan Broz &disk_to_dev(dm_disk(md))->kobj,
137784aae73SMilan Broz "%s", "dm");
138784aae73SMilan Broz }
139784aae73SMilan Broz
140784aae73SMilan Broz /*
141784aae73SMilan Broz * Remove kobj, called after all references removed
142784aae73SMilan Broz */
dm_sysfs_exit(struct mapped_device * md)143784aae73SMilan Broz void dm_sysfs_exit(struct mapped_device *md)
144784aae73SMilan Broz {
145be35f486SMikulas Patocka struct kobject *kobj = dm_kobject(md);
1460ef0b471SHeinz Mauelshagen
147be35f486SMikulas Patocka kobject_put(kobj);
148be35f486SMikulas Patocka wait_for_completion(dm_get_completion_from_kobject(kobj));
149784aae73SMilan Broz }
150