diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_sysfs.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_sysfs.c | 246 |
1 files changed, 139 insertions, 107 deletions
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index d31000886ca8..f5f60698dc4c 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c | |||
@@ -3,12 +3,13 @@ | |||
3 | * | 3 | * |
4 | * sysfs attributes. | 4 | * sysfs attributes. |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2008 | 6 | * Copyright IBM Corporation 2008, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
11 | 11 | ||
12 | #include <linux/slab.h> | ||
12 | #include "zfcp_ext.h" | 13 | #include "zfcp_ext.h" |
13 | 14 | ||
14 | #define ZFCP_DEV_ATTR(_feat, _name, _mode, _show, _store) \ | 15 | #define ZFCP_DEV_ATTR(_feat, _name, _mode, _show, _store) \ |
@@ -19,30 +20,43 @@ static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev, \ | |||
19 | struct device_attribute *at,\ | 20 | struct device_attribute *at,\ |
20 | char *buf) \ | 21 | char *buf) \ |
21 | { \ | 22 | { \ |
22 | struct _feat_def *_feat = dev_get_drvdata(dev); \ | 23 | struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \ |
23 | \ | 24 | \ |
24 | return sprintf(buf, _format, _value); \ | 25 | return sprintf(buf, _format, _value); \ |
25 | } \ | 26 | } \ |
26 | static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \ | 27 | static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \ |
27 | zfcp_sysfs_##_feat##_##_name##_show, NULL); | 28 | zfcp_sysfs_##_feat##_##_name##_show, NULL); |
28 | 29 | ||
29 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n", | 30 | #define ZFCP_DEFINE_A_ATTR(_name, _format, _value) \ |
30 | atomic_read(&adapter->status)); | 31 | static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \ |
31 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwnn, "0x%016llx\n", | 32 | struct device_attribute *at,\ |
32 | (unsigned long long) adapter->peer_wwnn); | 33 | char *buf) \ |
33 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwpn, "0x%016llx\n", | 34 | { \ |
34 | (unsigned long long) adapter->peer_wwpn); | 35 | struct ccw_device *cdev = to_ccwdev(dev); \ |
35 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_d_id, "0x%06x\n", | 36 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); \ |
36 | adapter->peer_d_id); | 37 | int i; \ |
37 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n", | 38 | \ |
38 | adapter->hydra_version); | 39 | if (!adapter) \ |
39 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, lic_version, "0x%08x\n", | 40 | return -ENODEV; \ |
40 | adapter->fsf_lic_version); | 41 | \ |
41 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, hardware_version, "0x%08x\n", | 42 | i = sprintf(buf, _format, _value); \ |
42 | adapter->hardware_version); | 43 | zfcp_ccw_adapter_put(adapter); \ |
43 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, in_recovery, "%d\n", | 44 | return i; \ |
44 | (atomic_read(&adapter->status) & | 45 | } \ |
45 | ZFCP_STATUS_COMMON_ERP_INUSE) != 0); | 46 | static ZFCP_DEV_ATTR(adapter, _name, S_IRUGO, \ |
47 | zfcp_sysfs_adapter_##_name##_show, NULL); | ||
48 | |||
49 | ZFCP_DEFINE_A_ATTR(status, "0x%08x\n", atomic_read(&adapter->status)); | ||
50 | ZFCP_DEFINE_A_ATTR(peer_wwnn, "0x%016llx\n", | ||
51 | (unsigned long long) adapter->peer_wwnn); | ||
52 | ZFCP_DEFINE_A_ATTR(peer_wwpn, "0x%016llx\n", | ||
53 | (unsigned long long) adapter->peer_wwpn); | ||
54 | ZFCP_DEFINE_A_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id); | ||
55 | ZFCP_DEFINE_A_ATTR(card_version, "0x%04x\n", adapter->hydra_version); | ||
56 | ZFCP_DEFINE_A_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); | ||
57 | ZFCP_DEFINE_A_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version); | ||
58 | ZFCP_DEFINE_A_ATTR(in_recovery, "%d\n", (atomic_read(&adapter->status) & | ||
59 | ZFCP_STATUS_COMMON_ERP_INUSE) != 0); | ||
46 | 60 | ||
47 | ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n", | 61 | ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n", |
48 | atomic_read(&port->status)); | 62 | atomic_read(&port->status)); |
@@ -73,7 +87,7 @@ static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev, \ | |||
73 | struct device_attribute *attr, \ | 87 | struct device_attribute *attr, \ |
74 | char *buf) \ | 88 | char *buf) \ |
75 | { \ | 89 | { \ |
76 | struct _feat_def *_feat = dev_get_drvdata(dev); \ | 90 | struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \ |
77 | \ | 91 | \ |
78 | if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \ | 92 | if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \ |
79 | return sprintf(buf, "1\n"); \ | 93 | return sprintf(buf, "1\n"); \ |
@@ -84,15 +98,12 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \ | |||
84 | struct device_attribute *attr,\ | 98 | struct device_attribute *attr,\ |
85 | const char *buf, size_t count)\ | 99 | const char *buf, size_t count)\ |
86 | { \ | 100 | { \ |
87 | struct _feat_def *_feat = dev_get_drvdata(dev); \ | 101 | struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \ |
88 | unsigned long val; \ | 102 | unsigned long val; \ |
89 | int retval = 0; \ | 103 | int retval = 0; \ |
90 | \ | 104 | \ |
91 | mutex_lock(&zfcp_data.config_mutex); \ | 105 | if (!(_feat && get_device(&_feat->dev))) \ |
92 | if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) { \ | 106 | return -EBUSY; \ |
93 | retval = -EBUSY; \ | ||
94 | goto out; \ | ||
95 | } \ | ||
96 | \ | 107 | \ |
97 | if (strict_strtoul(buf, 0, &val) || val != 0) { \ | 108 | if (strict_strtoul(buf, 0, &val) || val != 0) { \ |
98 | retval = -EINVAL; \ | 109 | retval = -EINVAL; \ |
@@ -105,29 +116,82 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \ | |||
105 | _reopen_id, NULL); \ | 116 | _reopen_id, NULL); \ |
106 | zfcp_erp_wait(_adapter); \ | 117 | zfcp_erp_wait(_adapter); \ |
107 | out: \ | 118 | out: \ |
108 | mutex_unlock(&zfcp_data.config_mutex); \ | 119 | put_device(&_feat->dev); \ |
109 | return retval ? retval : (ssize_t) count; \ | 120 | return retval ? retval : (ssize_t) count; \ |
110 | } \ | 121 | } \ |
111 | static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \ | 122 | static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \ |
112 | zfcp_sysfs_##_feat##_failed_show, \ | 123 | zfcp_sysfs_##_feat##_failed_show, \ |
113 | zfcp_sysfs_##_feat##_failed_store); | 124 | zfcp_sysfs_##_feat##_failed_store); |
114 | 125 | ||
115 | ZFCP_SYSFS_FAILED(zfcp_adapter, adapter, adapter, "syafai1", "syafai2"); | ||
116 | ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2"); | 126 | ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2"); |
117 | ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2"); | 127 | ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2"); |
118 | 128 | ||
129 | static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev, | ||
130 | struct device_attribute *attr, | ||
131 | char *buf) | ||
132 | { | ||
133 | struct ccw_device *cdev = to_ccwdev(dev); | ||
134 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); | ||
135 | int i; | ||
136 | |||
137 | if (!adapter) | ||
138 | return -ENODEV; | ||
139 | |||
140 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
141 | i = sprintf(buf, "1\n"); | ||
142 | else | ||
143 | i = sprintf(buf, "0\n"); | ||
144 | |||
145 | zfcp_ccw_adapter_put(adapter); | ||
146 | return i; | ||
147 | } | ||
148 | |||
149 | static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev, | ||
150 | struct device_attribute *attr, | ||
151 | const char *buf, size_t count) | ||
152 | { | ||
153 | struct ccw_device *cdev = to_ccwdev(dev); | ||
154 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); | ||
155 | unsigned long val; | ||
156 | int retval = 0; | ||
157 | |||
158 | if (!adapter) | ||
159 | return -ENODEV; | ||
160 | |||
161 | if (strict_strtoul(buf, 0, &val) || val != 0) { | ||
162 | retval = -EINVAL; | ||
163 | goto out; | ||
164 | } | ||
165 | |||
166 | zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL, | ||
167 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); | ||
168 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | ||
169 | "syafai2", NULL); | ||
170 | zfcp_erp_wait(adapter); | ||
171 | out: | ||
172 | zfcp_ccw_adapter_put(adapter); | ||
173 | return retval ? retval : (ssize_t) count; | ||
174 | } | ||
175 | static ZFCP_DEV_ATTR(adapter, failed, S_IWUSR | S_IRUGO, | ||
176 | zfcp_sysfs_adapter_failed_show, | ||
177 | zfcp_sysfs_adapter_failed_store); | ||
178 | |||
119 | static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, | 179 | static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, |
120 | struct device_attribute *attr, | 180 | struct device_attribute *attr, |
121 | const char *buf, size_t count) | 181 | const char *buf, size_t count) |
122 | { | 182 | { |
123 | struct zfcp_adapter *adapter = dev_get_drvdata(dev); | 183 | struct ccw_device *cdev = to_ccwdev(dev); |
124 | int ret; | 184 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
125 | 185 | ||
126 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) | 186 | if (!adapter) |
127 | return -EBUSY; | 187 | return -ENODEV; |
128 | 188 | ||
129 | ret = zfcp_fc_scan_ports(adapter); | 189 | /* sync the user-space- with the kernel-invocation of scan_work */ |
130 | return ret ? ret : (ssize_t) count; | 190 | queue_work(adapter->work_queue, &adapter->scan_work); |
191 | flush_work(&adapter->scan_work); | ||
192 | zfcp_ccw_adapter_put(adapter); | ||
193 | |||
194 | return (ssize_t) count; | ||
131 | } | 195 | } |
132 | static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, | 196 | static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, |
133 | zfcp_sysfs_port_rescan_store); | 197 | zfcp_sysfs_port_rescan_store); |
@@ -136,44 +200,34 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, | |||
136 | struct device_attribute *attr, | 200 | struct device_attribute *attr, |
137 | const char *buf, size_t count) | 201 | const char *buf, size_t count) |
138 | { | 202 | { |
139 | struct zfcp_adapter *adapter = dev_get_drvdata(dev); | 203 | struct ccw_device *cdev = to_ccwdev(dev); |
204 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); | ||
140 | struct zfcp_port *port; | 205 | struct zfcp_port *port; |
141 | u64 wwpn; | 206 | u64 wwpn; |
142 | int retval = 0; | 207 | int retval = -EINVAL; |
143 | LIST_HEAD(port_remove_lh); | ||
144 | 208 | ||
145 | mutex_lock(&zfcp_data.config_mutex); | 209 | if (!adapter) |
146 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) { | 210 | return -ENODEV; |
147 | retval = -EBUSY; | ||
148 | goto out; | ||
149 | } | ||
150 | 211 | ||
151 | if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) { | 212 | if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) |
152 | retval = -EINVAL; | ||
153 | goto out; | 213 | goto out; |
154 | } | ||
155 | 214 | ||
156 | write_lock_irq(&zfcp_data.config_lock); | ||
157 | port = zfcp_get_port_by_wwpn(adapter, wwpn); | 215 | port = zfcp_get_port_by_wwpn(adapter, wwpn); |
158 | if (port && (atomic_read(&port->refcount) == 0)) { | 216 | if (!port) |
159 | zfcp_port_get(port); | ||
160 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); | ||
161 | list_move(&port->list, &port_remove_lh); | ||
162 | } else | ||
163 | port = NULL; | ||
164 | write_unlock_irq(&zfcp_data.config_lock); | ||
165 | |||
166 | if (!port) { | ||
167 | retval = -ENXIO; | ||
168 | goto out; | 217 | goto out; |
169 | } | 218 | else |
219 | retval = 0; | ||
220 | |||
221 | write_lock_irq(&adapter->port_list_lock); | ||
222 | list_del(&port->list); | ||
223 | write_unlock_irq(&adapter->port_list_lock); | ||
224 | |||
225 | put_device(&port->dev); | ||
170 | 226 | ||
171 | zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); | 227 | zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); |
172 | zfcp_erp_wait(adapter); | 228 | zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); |
173 | zfcp_port_put(port); | ||
174 | zfcp_port_dequeue(port); | ||
175 | out: | 229 | out: |
176 | mutex_unlock(&zfcp_data.config_mutex); | 230 | zfcp_ccw_adapter_put(adapter); |
177 | return retval ? retval : (ssize_t) count; | 231 | return retval ? retval : (ssize_t) count; |
178 | } | 232 | } |
179 | static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL, | 233 | static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL, |
@@ -202,16 +256,13 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, | |||
202 | struct device_attribute *attr, | 256 | struct device_attribute *attr, |
203 | const char *buf, size_t count) | 257 | const char *buf, size_t count) |
204 | { | 258 | { |
205 | struct zfcp_port *port = dev_get_drvdata(dev); | 259 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); |
206 | struct zfcp_unit *unit; | 260 | struct zfcp_unit *unit; |
207 | u64 fcp_lun; | 261 | u64 fcp_lun; |
208 | int retval = -EINVAL; | 262 | int retval = -EINVAL; |
209 | 263 | ||
210 | mutex_lock(&zfcp_data.config_mutex); | 264 | if (!(port && get_device(&port->dev))) |
211 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { | 265 | return -EBUSY; |
212 | retval = -EBUSY; | ||
213 | goto out; | ||
214 | } | ||
215 | 266 | ||
216 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) | 267 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) |
217 | goto out; | 268 | goto out; |
@@ -219,15 +270,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, | |||
219 | unit = zfcp_unit_enqueue(port, fcp_lun); | 270 | unit = zfcp_unit_enqueue(port, fcp_lun); |
220 | if (IS_ERR(unit)) | 271 | if (IS_ERR(unit)) |
221 | goto out; | 272 | goto out; |
222 | 273 | else | |
223 | retval = 0; | 274 | retval = 0; |
224 | 275 | ||
225 | zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL); | 276 | zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL); |
226 | zfcp_erp_wait(unit->port->adapter); | 277 | zfcp_erp_wait(unit->port->adapter); |
227 | flush_work(&unit->scsi_work); | 278 | flush_work(&unit->scsi_work); |
228 | zfcp_unit_put(unit); | ||
229 | out: | 279 | out: |
230 | mutex_unlock(&zfcp_data.config_mutex); | 280 | put_device(&port->dev); |
231 | return retval ? retval : (ssize_t) count; | 281 | return retval ? retval : (ssize_t) count; |
232 | } | 282 | } |
233 | static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); | 283 | static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); |
@@ -236,54 +286,36 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, | |||
236 | struct device_attribute *attr, | 286 | struct device_attribute *attr, |
237 | const char *buf, size_t count) | 287 | const char *buf, size_t count) |
238 | { | 288 | { |
239 | struct zfcp_port *port = dev_get_drvdata(dev); | 289 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); |
240 | struct zfcp_unit *unit; | 290 | struct zfcp_unit *unit; |
241 | u64 fcp_lun; | 291 | u64 fcp_lun; |
242 | int retval = 0; | 292 | int retval = -EINVAL; |
243 | LIST_HEAD(unit_remove_lh); | ||
244 | 293 | ||
245 | mutex_lock(&zfcp_data.config_mutex); | 294 | if (!(port && get_device(&port->dev))) |
246 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { | 295 | return -EBUSY; |
247 | retval = -EBUSY; | ||
248 | goto out; | ||
249 | } | ||
250 | 296 | ||
251 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) { | 297 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) |
252 | retval = -EINVAL; | ||
253 | goto out; | 298 | goto out; |
254 | } | ||
255 | 299 | ||
256 | write_lock_irq(&zfcp_data.config_lock); | ||
257 | unit = zfcp_get_unit_by_lun(port, fcp_lun); | 300 | unit = zfcp_get_unit_by_lun(port, fcp_lun); |
258 | if (unit) { | 301 | if (!unit) |
259 | write_unlock_irq(&zfcp_data.config_lock); | 302 | goto out; |
260 | /* wait for possible timeout during SCSI probe */ | 303 | else |
261 | flush_work(&unit->scsi_work); | 304 | retval = 0; |
262 | write_lock_irq(&zfcp_data.config_lock); | ||
263 | |||
264 | if (atomic_read(&unit->refcount) == 0) { | ||
265 | zfcp_unit_get(unit); | ||
266 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, | ||
267 | &unit->status); | ||
268 | list_move(&unit->list, &unit_remove_lh); | ||
269 | } else { | ||
270 | unit = NULL; | ||
271 | } | ||
272 | } | ||
273 | 305 | ||
274 | write_unlock_irq(&zfcp_data.config_lock); | 306 | /* wait for possible timeout during SCSI probe */ |
307 | flush_work(&unit->scsi_work); | ||
275 | 308 | ||
276 | if (!unit) { | 309 | write_lock_irq(&port->unit_list_lock); |
277 | retval = -ENXIO; | 310 | list_del(&unit->list); |
278 | goto out; | 311 | write_unlock_irq(&port->unit_list_lock); |
279 | } | 312 | |
313 | put_device(&unit->dev); | ||
280 | 314 | ||
281 | zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); | 315 | zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); |
282 | zfcp_erp_wait(unit->port->adapter); | 316 | zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs); |
283 | zfcp_unit_put(unit); | ||
284 | zfcp_unit_dequeue(unit); | ||
285 | out: | 317 | out: |
286 | mutex_unlock(&zfcp_data.config_mutex); | 318 | put_device(&port->dev); |
287 | return retval ? retval : (ssize_t) count; | 319 | return retval ? retval : (ssize_t) count; |
288 | } | 320 | } |
289 | static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); | 321 | static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); |