Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * raid_class.c - implementation of a simple raid visualisation class
0004  *
0005  * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com>
0006  *
0007  * This class is designed to allow raid attributes to be visualised and
0008  * manipulated in a form independent of the underlying raid.  Ultimately this
0009  * should work for both hardware and software raids.
0010  */
0011 #include <linux/init.h>
0012 #include <linux/module.h>
0013 #include <linux/list.h>
0014 #include <linux/slab.h>
0015 #include <linux/string.h>
0016 #include <linux/raid_class.h>
0017 #include <scsi/scsi_device.h>
0018 #include <scsi/scsi_host.h>
0019 
0020 #define RAID_NUM_ATTRS  3
0021 
0022 struct raid_internal {
0023     struct raid_template r;
0024     struct raid_function_template *f;
0025     /* The actual attributes */
0026     struct device_attribute private_attrs[RAID_NUM_ATTRS];
0027     /* The array of null terminated pointers to attributes 
0028      * needed by scsi_sysfs.c */
0029     struct device_attribute *attrs[RAID_NUM_ATTRS + 1];
0030 };
0031 
0032 struct raid_component {
0033     struct list_head node;
0034     struct device dev;
0035     int num;
0036 };
0037 
0038 #define to_raid_internal(tmpl)  container_of(tmpl, struct raid_internal, r)
0039 
0040 #define tc_to_raid_internal(tcont) ({                   \
0041     struct raid_template *r =                   \
0042         container_of(tcont, struct raid_template, raid_attrs);  \
0043     to_raid_internal(r);                        \
0044 })
0045 
0046 #define ac_to_raid_internal(acont) ({                   \
0047     struct transport_container *tc =                \
0048         container_of(acont, struct transport_container, ac);    \
0049     tc_to_raid_internal(tc);                    \
0050 })
0051 
0052 #define device_to_raid_internal(dev) ({             \
0053     struct attribute_container *ac =                \
0054         attribute_container_classdev_to_container(dev); \
0055     ac_to_raid_internal(ac);                    \
0056 })
0057     
0058 
0059 static int raid_match(struct attribute_container *cont, struct device *dev)
0060 {
0061     /* We have to look for every subsystem that could house
0062      * emulated RAID devices, so start with SCSI */
0063     struct raid_internal *i = ac_to_raid_internal(cont);
0064 
0065     if (IS_ENABLED(CONFIG_SCSI) && scsi_is_sdev_device(dev)) {
0066         struct scsi_device *sdev = to_scsi_device(dev);
0067 
0068         if (i->f->cookie != sdev->host->hostt)
0069             return 0;
0070 
0071         return i->f->is_raid(dev);
0072     }
0073     /* FIXME: look at other subsystems too */
0074     return 0;
0075 }
0076 
0077 static int raid_setup(struct transport_container *tc, struct device *dev,
0078                struct device *cdev)
0079 {
0080     struct raid_data *rd;
0081 
0082     BUG_ON(dev_get_drvdata(cdev));
0083 
0084     rd = kzalloc(sizeof(*rd), GFP_KERNEL);
0085     if (!rd)
0086         return -ENOMEM;
0087 
0088     INIT_LIST_HEAD(&rd->component_list);
0089     dev_set_drvdata(cdev, rd);
0090         
0091     return 0;
0092 }
0093 
0094 static int raid_remove(struct transport_container *tc, struct device *dev,
0095                struct device *cdev)
0096 {
0097     struct raid_data *rd = dev_get_drvdata(cdev);
0098     struct raid_component *rc, *next;
0099     dev_printk(KERN_ERR, dev, "RAID REMOVE\n");
0100     dev_set_drvdata(cdev, NULL);
0101     list_for_each_entry_safe(rc, next, &rd->component_list, node) {
0102         list_del(&rc->node);
0103         dev_printk(KERN_ERR, rc->dev.parent, "RAID COMPONENT REMOVE\n");
0104         device_unregister(&rc->dev);
0105     }
0106     dev_printk(KERN_ERR, dev, "RAID REMOVE DONE\n");
0107     kfree(rd);
0108     return 0;
0109 }
0110 
0111 static DECLARE_TRANSPORT_CLASS(raid_class,
0112                    "raid_devices",
0113                    raid_setup,
0114                    raid_remove,
0115                    NULL);
0116 
0117 static const struct {
0118     enum raid_state value;
0119     char        *name;
0120 } raid_states[] = {
0121     { RAID_STATE_UNKNOWN, "unknown" },
0122     { RAID_STATE_ACTIVE, "active" },
0123     { RAID_STATE_DEGRADED, "degraded" },
0124     { RAID_STATE_RESYNCING, "resyncing" },
0125     { RAID_STATE_OFFLINE, "offline" },
0126 };
0127 
0128 static const char *raid_state_name(enum raid_state state)
0129 {
0130     int i;
0131     char *name = NULL;
0132 
0133     for (i = 0; i < ARRAY_SIZE(raid_states); i++) {
0134         if (raid_states[i].value == state) {
0135             name = raid_states[i].name;
0136             break;
0137         }
0138     }
0139     return name;
0140 }
0141 
0142 static struct {
0143     enum raid_level value;
0144     char *name;
0145 } raid_levels[] = {
0146     { RAID_LEVEL_UNKNOWN, "unknown" },
0147     { RAID_LEVEL_LINEAR, "linear" },
0148     { RAID_LEVEL_0, "raid0" },
0149     { RAID_LEVEL_1, "raid1" },
0150     { RAID_LEVEL_10, "raid10" },
0151     { RAID_LEVEL_1E, "raid1e" },
0152     { RAID_LEVEL_3, "raid3" },
0153     { RAID_LEVEL_4, "raid4" },
0154     { RAID_LEVEL_5, "raid5" },
0155     { RAID_LEVEL_50, "raid50" },
0156     { RAID_LEVEL_6, "raid6" },
0157     { RAID_LEVEL_JBOD, "jbod" },
0158 };
0159 
0160 static const char *raid_level_name(enum raid_level level)
0161 {
0162     int i;
0163     char *name = NULL;
0164 
0165     for (i = 0; i < ARRAY_SIZE(raid_levels); i++) {
0166         if (raid_levels[i].value == level) {
0167             name = raid_levels[i].name;
0168             break;
0169         }
0170     }
0171     return name;
0172 }
0173 
0174 #define raid_attr_show_internal(attr, fmt, var, code)           \
0175 static ssize_t raid_show_##attr(struct device *dev,             \
0176                 struct device_attribute *attr,      \
0177                 char *buf)              \
0178 {                                   \
0179     struct raid_data *rd = dev_get_drvdata(dev);            \
0180     code                                \
0181     return snprintf(buf, 20, #fmt "\n", var);           \
0182 }
0183 
0184 #define raid_attr_ro_states(attr, states, code)             \
0185 raid_attr_show_internal(attr, %s, name,                 \
0186     const char *name;                       \
0187     code                                \
0188     name = raid_##states##_name(rd->attr);              \
0189 )                                   \
0190 static DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
0191 
0192 
0193 #define raid_attr_ro_internal(attr, code)               \
0194 raid_attr_show_internal(attr, %d, rd->attr, code)           \
0195 static DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
0196 
0197 #define ATTR_CODE(attr)                         \
0198     struct raid_internal *i = device_to_raid_internal(dev);     \
0199     if (i->f->get_##attr)                       \
0200         i->f->get_##attr(dev->parent);
0201 
0202 #define raid_attr_ro(attr)  raid_attr_ro_internal(attr, )
0203 #define raid_attr_ro_fn(attr)   raid_attr_ro_internal(attr, ATTR_CODE(attr))
0204 #define raid_attr_ro_state(attr)    raid_attr_ro_states(attr, attr, )
0205 #define raid_attr_ro_state_fn(attr) raid_attr_ro_states(attr, attr, ATTR_CODE(attr))
0206 
0207 
0208 raid_attr_ro_state(level);
0209 raid_attr_ro_fn(resync);
0210 raid_attr_ro_state_fn(state);
0211 
0212 static void raid_component_release(struct device *dev)
0213 {
0214     struct raid_component *rc =
0215         container_of(dev, struct raid_component, dev);
0216     dev_printk(KERN_ERR, rc->dev.parent, "COMPONENT RELEASE\n");
0217     put_device(rc->dev.parent);
0218     kfree(rc);
0219 }
0220 
0221 int raid_component_add(struct raid_template *r,struct device *raid_dev,
0222                struct device *component_dev)
0223 {
0224     struct device *cdev =
0225         attribute_container_find_class_device(&r->raid_attrs.ac,
0226                               raid_dev);
0227     struct raid_component *rc;
0228     struct raid_data *rd = dev_get_drvdata(cdev);
0229     int err;
0230 
0231     rc = kzalloc(sizeof(*rc), GFP_KERNEL);
0232     if (!rc)
0233         return -ENOMEM;
0234 
0235     INIT_LIST_HEAD(&rc->node);
0236     device_initialize(&rc->dev);
0237     rc->dev.release = raid_component_release;
0238     rc->dev.parent = get_device(component_dev);
0239     rc->num = rd->component_count++;
0240 
0241     dev_set_name(&rc->dev, "component-%d", rc->num);
0242     list_add_tail(&rc->node, &rd->component_list);
0243     rc->dev.class = &raid_class.class;
0244     err = device_add(&rc->dev);
0245     if (err)
0246         goto err_out;
0247 
0248     return 0;
0249 
0250 err_out:
0251     list_del(&rc->node);
0252     rd->component_count--;
0253     put_device(component_dev);
0254     kfree(rc);
0255     return err;
0256 }
0257 EXPORT_SYMBOL(raid_component_add);
0258 
0259 struct raid_template *
0260 raid_class_attach(struct raid_function_template *ft)
0261 {
0262     struct raid_internal *i = kzalloc(sizeof(struct raid_internal),
0263                       GFP_KERNEL);
0264     int count = 0;
0265 
0266     if (unlikely(!i))
0267         return NULL;
0268 
0269     i->f = ft;
0270 
0271     i->r.raid_attrs.ac.class = &raid_class.class;
0272     i->r.raid_attrs.ac.match = raid_match;
0273     i->r.raid_attrs.ac.attrs = &i->attrs[0];
0274 
0275     attribute_container_register(&i->r.raid_attrs.ac);
0276 
0277     i->attrs[count++] = &dev_attr_level;
0278     i->attrs[count++] = &dev_attr_resync;
0279     i->attrs[count++] = &dev_attr_state;
0280 
0281     i->attrs[count] = NULL;
0282     BUG_ON(count > RAID_NUM_ATTRS);
0283 
0284     return &i->r;
0285 }
0286 EXPORT_SYMBOL(raid_class_attach);
0287 
0288 void
0289 raid_class_release(struct raid_template *r)
0290 {
0291     struct raid_internal *i = to_raid_internal(r);
0292 
0293     BUG_ON(attribute_container_unregister(&i->r.raid_attrs.ac));
0294 
0295     kfree(i);
0296 }
0297 EXPORT_SYMBOL(raid_class_release);
0298 
0299 static __init int raid_init(void)
0300 {
0301     return transport_class_register(&raid_class);
0302 }
0303 
0304 static __exit void raid_exit(void)
0305 {
0306     transport_class_unregister(&raid_class);
0307 }
0308 
0309 MODULE_AUTHOR("James Bottomley");
0310 MODULE_DESCRIPTION("RAID device class");
0311 MODULE_LICENSE("GPL");
0312 
0313 module_init(raid_init);
0314 module_exit(raid_exit);
0315