^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * raid_class.c - implementation of a simple raid visualisation class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This class is designed to allow raid attributes to be visualised and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * manipulated in a form independent of the underlying raid. Ultimately this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * should work for both hardware and software raids.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/raid_class.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <scsi/scsi_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define RAID_NUM_ATTRS 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct raid_internal {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct raid_template r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct raid_function_template *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* The actual attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct device_attribute private_attrs[RAID_NUM_ATTRS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* The array of null terminated pointers to attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * needed by scsi_sysfs.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct device_attribute *attrs[RAID_NUM_ATTRS + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct raid_component {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct device dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define to_raid_internal(tmpl) container_of(tmpl, struct raid_internal, r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define tc_to_raid_internal(tcont) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct raid_template *r = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) container_of(tcont, struct raid_template, raid_attrs); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) to_raid_internal(r); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define ac_to_raid_internal(acont) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct transport_container *tc = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) container_of(acont, struct transport_container, ac); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) tc_to_raid_internal(tc); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define device_to_raid_internal(dev) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct attribute_container *ac = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) attribute_container_classdev_to_container(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) ac_to_raid_internal(ac); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static int raid_match(struct attribute_container *cont, struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* We have to look for every subsystem that could house
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * emulated RAID devices, so start with SCSI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct raid_internal *i = ac_to_raid_internal(cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (IS_ENABLED(CONFIG_SCSI) && scsi_is_sdev_device(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct scsi_device *sdev = to_scsi_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (i->f->cookie != sdev->host->hostt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return i->f->is_raid(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* FIXME: look at other subsystems too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static int raid_setup(struct transport_container *tc, struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct raid_data *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) BUG_ON(dev_get_drvdata(cdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) rd = kzalloc(sizeof(*rd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) INIT_LIST_HEAD(&rd->component_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) dev_set_drvdata(cdev, rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int raid_remove(struct transport_container *tc, struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct raid_data *rd = dev_get_drvdata(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct raid_component *rc, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dev_printk(KERN_ERR, dev, "RAID REMOVE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) dev_set_drvdata(cdev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) list_for_each_entry_safe(rc, next, &rd->component_list, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) list_del(&rc->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dev_printk(KERN_ERR, rc->dev.parent, "RAID COMPONENT REMOVE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) device_unregister(&rc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) dev_printk(KERN_ERR, dev, "RAID REMOVE DONE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) kfree(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static DECLARE_TRANSPORT_CLASS(raid_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) "raid_devices",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) raid_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) raid_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) enum raid_state value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) } raid_states[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) { RAID_STATE_UNKNOWN, "unknown" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) { RAID_STATE_ACTIVE, "active" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) { RAID_STATE_DEGRADED, "degraded" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) { RAID_STATE_RESYNCING, "resyncing" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { RAID_STATE_OFFLINE, "offline" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static const char *raid_state_name(enum raid_state state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) char *name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) for (i = 0; i < ARRAY_SIZE(raid_states); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (raid_states[i].value == state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) name = raid_states[i].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) enum raid_level value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) } raid_levels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) { RAID_LEVEL_UNKNOWN, "unknown" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) { RAID_LEVEL_LINEAR, "linear" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) { RAID_LEVEL_0, "raid0" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) { RAID_LEVEL_1, "raid1" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { RAID_LEVEL_10, "raid10" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) { RAID_LEVEL_1E, "raid1e" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) { RAID_LEVEL_3, "raid3" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { RAID_LEVEL_4, "raid4" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) { RAID_LEVEL_5, "raid5" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) { RAID_LEVEL_50, "raid50" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) { RAID_LEVEL_6, "raid6" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) { RAID_LEVEL_JBOD, "jbod" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static const char *raid_level_name(enum raid_level level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) char *name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) for (i = 0; i < ARRAY_SIZE(raid_levels); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (raid_levels[i].value == level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) name = raid_levels[i].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define raid_attr_show_internal(attr, fmt, var, code) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static ssize_t raid_show_##attr(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct raid_data *rd = dev_get_drvdata(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) code \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return snprintf(buf, 20, #fmt "\n", var); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define raid_attr_ro_states(attr, states, code) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) raid_attr_show_internal(attr, %s, name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) const char *name; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) code \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) name = raid_##states##_name(rd->attr); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #define raid_attr_ro_internal(attr, code) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) raid_attr_show_internal(attr, %d, rd->attr, code) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define ATTR_CODE(attr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct raid_internal *i = device_to_raid_internal(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (i->f->get_##attr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) i->f->get_##attr(dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #define raid_attr_ro(attr) raid_attr_ro_internal(attr, )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #define raid_attr_ro_fn(attr) raid_attr_ro_internal(attr, ATTR_CODE(attr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #define raid_attr_ro_state(attr) raid_attr_ro_states(attr, attr, )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) #define raid_attr_ro_state_fn(attr) raid_attr_ro_states(attr, attr, ATTR_CODE(attr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) raid_attr_ro_state(level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) raid_attr_ro_fn(resync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) raid_attr_ro_state_fn(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static void raid_component_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct raid_component *rc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) container_of(dev, struct raid_component, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) dev_printk(KERN_ERR, rc->dev.parent, "COMPONENT RELEASE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) put_device(rc->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) kfree(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int raid_component_add(struct raid_template *r,struct device *raid_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct device *component_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct device *cdev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) attribute_container_find_class_device(&r->raid_attrs.ac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) raid_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct raid_component *rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct raid_data *rd = dev_get_drvdata(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) rc = kzalloc(sizeof(*rc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) INIT_LIST_HEAD(&rc->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) device_initialize(&rc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) rc->dev.release = raid_component_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) rc->dev.parent = get_device(component_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) rc->num = rd->component_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) dev_set_name(&rc->dev, "component-%d", rc->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) list_add_tail(&rc->node, &rd->component_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) rc->dev.class = &raid_class.class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) err = device_add(&rc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) list_del(&rc->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) rd->component_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) put_device(component_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) kfree(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) EXPORT_SYMBOL(raid_component_add);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct raid_template *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) raid_class_attach(struct raid_function_template *ft)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct raid_internal *i = kzalloc(sizeof(struct raid_internal),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (unlikely(!i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) i->f = ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) i->r.raid_attrs.ac.class = &raid_class.class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) i->r.raid_attrs.ac.match = raid_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) i->r.raid_attrs.ac.attrs = &i->attrs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) attribute_container_register(&i->r.raid_attrs.ac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) i->attrs[count++] = &dev_attr_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) i->attrs[count++] = &dev_attr_resync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) i->attrs[count++] = &dev_attr_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) i->attrs[count] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) BUG_ON(count > RAID_NUM_ATTRS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return &i->r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) EXPORT_SYMBOL(raid_class_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) raid_class_release(struct raid_template *r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct raid_internal *i = to_raid_internal(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) BUG_ON(attribute_container_unregister(&i->r.raid_attrs.ac));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) kfree(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) EXPORT_SYMBOL(raid_class_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static __init int raid_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return transport_class_register(&raid_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static __exit void raid_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) transport_class_unregister(&raid_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) MODULE_AUTHOR("James Bottomley");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) MODULE_DESCRIPTION("RAID device class");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) module_init(raid_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) module_exit(raid_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)