18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (C) 2008 Red Hat, Inc. All rights reserved. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This file is released under the GPL. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/sysfs.h> 88c2ecf20Sopenharmony_ci#include <linux/dm-ioctl.h> 98c2ecf20Sopenharmony_ci#include "dm-core.h" 108c2ecf20Sopenharmony_ci#include "dm-rq.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistruct dm_sysfs_attr { 138c2ecf20Sopenharmony_ci struct attribute attr; 148c2ecf20Sopenharmony_ci ssize_t (*show)(struct mapped_device *, char *); 158c2ecf20Sopenharmony_ci ssize_t (*store)(struct mapped_device *, const char *, size_t count); 168c2ecf20Sopenharmony_ci}; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define DM_ATTR_RO(_name) \ 198c2ecf20Sopenharmony_cistruct dm_sysfs_attr dm_attr_##_name = \ 208c2ecf20Sopenharmony_ci __ATTR(_name, S_IRUGO, dm_attr_##_name##_show, NULL) 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic ssize_t dm_attr_show(struct kobject *kobj, struct attribute *attr, 238c2ecf20Sopenharmony_ci char *page) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci struct dm_sysfs_attr *dm_attr; 268c2ecf20Sopenharmony_ci struct mapped_device *md; 278c2ecf20Sopenharmony_ci ssize_t ret; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci dm_attr = container_of(attr, struct dm_sysfs_attr, attr); 308c2ecf20Sopenharmony_ci if (!dm_attr->show) 318c2ecf20Sopenharmony_ci return -EIO; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci md = dm_get_from_kobject(kobj); 348c2ecf20Sopenharmony_ci if (!md) 358c2ecf20Sopenharmony_ci return -EINVAL; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci ret = dm_attr->show(md, page); 388c2ecf20Sopenharmony_ci dm_put(md); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci return ret; 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define DM_ATTR_RW(_name) \ 448c2ecf20Sopenharmony_cistruct dm_sysfs_attr dm_attr_##_name = \ 458c2ecf20Sopenharmony_ci __ATTR(_name, S_IRUGO | S_IWUSR, dm_attr_##_name##_show, dm_attr_##_name##_store) 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic ssize_t dm_attr_store(struct kobject *kobj, struct attribute *attr, 488c2ecf20Sopenharmony_ci const char *page, size_t count) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci struct dm_sysfs_attr *dm_attr; 518c2ecf20Sopenharmony_ci struct mapped_device *md; 528c2ecf20Sopenharmony_ci ssize_t ret; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci dm_attr = container_of(attr, struct dm_sysfs_attr, attr); 558c2ecf20Sopenharmony_ci if (!dm_attr->store) 568c2ecf20Sopenharmony_ci return -EIO; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci md = dm_get_from_kobject(kobj); 598c2ecf20Sopenharmony_ci if (!md) 608c2ecf20Sopenharmony_ci return -EINVAL; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci ret = dm_attr->store(md, page, count); 638c2ecf20Sopenharmony_ci dm_put(md); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return ret; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic ssize_t dm_attr_name_show(struct mapped_device *md, char *buf) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci if (dm_copy_name_and_uuid(md, buf, NULL)) 718c2ecf20Sopenharmony_ci return -EIO; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci strcat(buf, "\n"); 748c2ecf20Sopenharmony_ci return strlen(buf); 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic ssize_t dm_attr_uuid_show(struct mapped_device *md, char *buf) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci if (dm_copy_name_and_uuid(md, NULL, buf)) 808c2ecf20Sopenharmony_ci return -EIO; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci strcat(buf, "\n"); 838c2ecf20Sopenharmony_ci return strlen(buf); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic ssize_t dm_attr_suspended_show(struct mapped_device *md, char *buf) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci sprintf(buf, "%d\n", dm_suspended_md(md)); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci return strlen(buf); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic ssize_t dm_attr_use_blk_mq_show(struct mapped_device *md, char *buf) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci /* Purely for userspace compatibility */ 968c2ecf20Sopenharmony_ci sprintf(buf, "%d\n", true); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci return strlen(buf); 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic DM_ATTR_RO(name); 1028c2ecf20Sopenharmony_cistatic DM_ATTR_RO(uuid); 1038c2ecf20Sopenharmony_cistatic DM_ATTR_RO(suspended); 1048c2ecf20Sopenharmony_cistatic DM_ATTR_RO(use_blk_mq); 1058c2ecf20Sopenharmony_cistatic DM_ATTR_RW(rq_based_seq_io_merge_deadline); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic struct attribute *dm_attrs[] = { 1088c2ecf20Sopenharmony_ci &dm_attr_name.attr, 1098c2ecf20Sopenharmony_ci &dm_attr_uuid.attr, 1108c2ecf20Sopenharmony_ci &dm_attr_suspended.attr, 1118c2ecf20Sopenharmony_ci &dm_attr_use_blk_mq.attr, 1128c2ecf20Sopenharmony_ci &dm_attr_rq_based_seq_io_merge_deadline.attr, 1138c2ecf20Sopenharmony_ci NULL, 1148c2ecf20Sopenharmony_ci}; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic const struct sysfs_ops dm_sysfs_ops = { 1178c2ecf20Sopenharmony_ci .show = dm_attr_show, 1188c2ecf20Sopenharmony_ci .store = dm_attr_store, 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic struct kobj_type dm_ktype = { 1228c2ecf20Sopenharmony_ci .sysfs_ops = &dm_sysfs_ops, 1238c2ecf20Sopenharmony_ci .default_attrs = dm_attrs, 1248c2ecf20Sopenharmony_ci .release = dm_kobject_release, 1258c2ecf20Sopenharmony_ci}; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci/* 1288c2ecf20Sopenharmony_ci * Initialize kobj 1298c2ecf20Sopenharmony_ci * because nobody using md yet, no need to call explicit dm_get/put 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_ciint dm_sysfs_init(struct mapped_device *md) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci return kobject_init_and_add(dm_kobject(md), &dm_ktype, 1348c2ecf20Sopenharmony_ci &disk_to_dev(dm_disk(md))->kobj, 1358c2ecf20Sopenharmony_ci "%s", "dm"); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/* 1398c2ecf20Sopenharmony_ci * Remove kobj, called after all references removed 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_civoid dm_sysfs_exit(struct mapped_device *md) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci struct kobject *kobj = dm_kobject(md); 1448c2ecf20Sopenharmony_ci kobject_put(kobj); 1458c2ecf20Sopenharmony_ci wait_for_completion(dm_get_completion_from_kobject(kobj)); 1468c2ecf20Sopenharmony_ci} 147