1 #include <linux/types.h>
2 #include <linux/device.h>
3 #include <linux/module.h>
7 int blktap_debug_level = 1;
9 static struct class *class;
10 static DECLARE_WAIT_QUEUE_HEAD(sysfs_wq);
13 blktap_sysfs_get(struct blktap *tap)
15 atomic_inc(&tap->ring.sysfs_refcnt);
19 blktap_sysfs_put(struct blktap *tap)
21 if (atomic_dec_and_test(&tap->ring.sysfs_refcnt))
26 blktap_sysfs_enter(struct blktap *tap)
28 blktap_sysfs_get(tap); /* pin sysfs device */
29 mutex_lock(&tap->ring.sysfs_mutex); /* serialize sysfs operations */
33 blktap_sysfs_exit(struct blktap *tap)
35 mutex_unlock(&tap->ring.sysfs_mutex);
36 blktap_sysfs_put(tap);
39 static ssize_t blktap_sysfs_pause_device(struct device *,
40 struct device_attribute *,
41 const char *, size_t);
42 static DEVICE_ATTR(pause, S_IWUSR, NULL, blktap_sysfs_pause_device);
43 static ssize_t blktap_sysfs_resume_device(struct device *,
44 struct device_attribute *,
45 const char *, size_t);
46 static DEVICE_ATTR(resume, S_IWUSR, NULL, blktap_sysfs_resume_device);
49 blktap_sysfs_set_name(struct device *dev, struct device_attribute *attr,
50 const char *buf, size_t size)
53 struct blktap *tap = dev_get_drvdata(dev);
55 blktap_sysfs_enter(tap);
58 test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
63 if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
68 if (size > BLKTAP2_MAX_MESSAGE_LEN) {
73 if (strnlen(buf, size) >= size) {
78 strlcpy(tap->params.name, buf, size);
82 blktap_sysfs_exit(tap);
87 blktap_sysfs_get_name(struct device *dev, struct device_attribute *attr,
91 struct blktap *tap = dev_get_drvdata(dev);
93 blktap_sysfs_enter(tap);
97 else if (tap->params.name[0])
98 size = sprintf(buf, "%s\n", tap->params.name);
100 size = sprintf(buf, "%d\n", tap->minor);
102 blktap_sysfs_exit(tap);
106 static DEVICE_ATTR(name, S_IRUSR | S_IWUSR,
107 blktap_sysfs_get_name, blktap_sysfs_set_name);
110 blktap_sysfs_remove_device(struct device *dev, struct device_attribute *attr,
111 const char *buf, size_t size)
114 struct blktap *tap = dev_get_drvdata(dev);
119 if (test_and_set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
122 err = blktap_control_destroy_device(tap);
124 return (err ? : size);
126 static DEVICE_ATTR(remove, S_IWUSR, NULL, blktap_sysfs_remove_device);
129 blktap_sysfs_pause_device(struct device *dev, struct device_attribute *attr,
130 const char *buf, size_t size)
133 struct blktap *tap = dev_get_drvdata(dev);
135 blktap_sysfs_enter(tap);
137 BTDBG("pausing %u:%u: dev_inuse: %lu\n",
138 MAJOR(tap->ring.devno), MINOR(tap->ring.devno), tap->dev_inuse);
140 if (!tap->ring.dev ||
141 test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
146 if (test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse)) {
151 if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
156 err = blktap_device_pause(tap);
158 device_remove_file(dev, &dev_attr_pause);
159 err = device_create_file(dev, &dev_attr_resume);
163 blktap_sysfs_exit(tap);
165 return (err ? err : size);
169 blktap_sysfs_resume_device(struct device *dev, struct device_attribute *attr,
170 const char *buf, size_t size)
173 struct blktap *tap = dev_get_drvdata(dev);
175 blktap_sysfs_enter(tap);
177 if (!tap->ring.dev ||
178 test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
183 if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
188 err = blktap_device_resume(tap);
190 device_remove_file(dev, &dev_attr_resume);
191 err = device_create_file(dev, &dev_attr_pause);
195 blktap_sysfs_exit(tap);
197 BTDBG("returning %zd\n", (err ? err : size));
198 return (err ? err : size);
201 #ifdef ENABLE_PASSTHROUGH
203 blktap_sysfs_enable_passthrough(struct device *dev,
204 struct device_attribute *attr,
205 const char *buf, size_t size)
208 unsigned major, minor;
209 struct blktap *tap = dev_get_drvdata(dev);
211 BTINFO("passthrough request enabled\n");
213 blktap_sysfs_enter(tap);
215 if (!tap->ring.dev ||
216 test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
221 if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
226 if (test_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse)) {
231 err = sscanf(buf, "%x:%x", &major, &minor);
237 err = blktap_device_enable_passthrough(tap, major, minor);
240 blktap_sysfs_exit(tap);
241 BTDBG("returning %d\n", (err ? err : size));
242 return (err ? err : size);
247 blktap_sysfs_debug_device(struct device *dev, struct device_attribute *attr,
252 struct blktap *tap = dev_get_drvdata(dev);
255 blktap_sysfs_get(tap);
257 if (!tap->ring.dev) {
258 ret = sprintf(tmp, "no device\n");
262 tmp += sprintf(tmp, "%s (%u:%u), refcnt: %d, dev_inuse: 0x%08lx\n",
263 tap->params.name, MAJOR(tap->ring.devno),
264 MINOR(tap->ring.devno), atomic_read(&tap->refcnt),
266 tmp += sprintf(tmp, "capacity: 0x%llx, sector size: 0x%lx, "
267 "device users: %d\n", tap->params.capacity,
268 tap->params.sector_size, tap->device.users);
270 down_read(&tap->tap_sem);
272 tmp += sprintf(tmp, "pending requests: %d\n", tap->pending_cnt);
273 for (i = 0; i < MAX_PENDING_REQS; i++) {
274 struct blktap_request *req = tap->pending_requests[i];
278 tmp += sprintf(tmp, "req %d: id: %llu, usr_idx: %d, "
279 "status: 0x%02x, pendcnt: %d, "
280 "nr_pages: %u, op: %d, time: %lu:%lu\n",
281 i, (unsigned long long)req->id, req->usr_idx,
282 req->status, atomic_read(&req->pendcnt),
283 req->nr_pages, req->operation, req->time.tv_sec,
287 up_read(&tap->tap_sem);
288 ret = (tmp - buf) + 1;
291 blktap_sysfs_put(tap);
296 static DEVICE_ATTR(debug, S_IRUSR, blktap_sysfs_debug_device, NULL);
299 blktap_sysfs_create(struct blktap *tap)
301 struct blktap_ring *ring;
310 dev = device_create(class, NULL, ring->devno, tap,
311 "blktap%d", tap->minor);
317 mutex_init(&ring->sysfs_mutex);
318 atomic_set(&ring->sysfs_refcnt, 0);
319 set_bit(BLKTAP_SYSFS, &tap->dev_inuse);
321 err = device_create_file(dev, &dev_attr_name);
324 err = device_create_file(dev, &dev_attr_remove);
328 err = device_create_file(dev, &dev_attr_pause);
332 err = device_create_file(dev, &dev_attr_debug);
335 switch (state * !!err) {
336 case 3: device_remove_file(dev, &dev_attr_pause);
337 case 2: device_remove_file(dev, &dev_attr_remove);
338 case 1: device_remove_file(dev, &dev_attr_name);
345 _blktap_sysfs_destroy(struct device *dev)
347 struct blktap *tap = dev_get_drvdata(dev);
349 device_remove_file(dev, &dev_attr_name);
350 device_remove_file(dev, &dev_attr_remove);
351 device_remove_file(dev, &dev_attr_pause);
352 device_remove_file(dev, &dev_attr_resume);
353 device_remove_file(dev, &dev_attr_debug);
355 device_unregister(dev);
357 clear_bit(BLKTAP_SYSFS, &tap->dev_inuse);
359 blktap_control_finish_destroy(tap);
363 blktap_sysfs_destroy(struct blktap *tap)
365 struct blktap_ring *ring;
374 if (wait_event_interruptible(sysfs_wq,
375 !atomic_read(&tap->ring.sysfs_refcnt)))
378 return device_schedule_callback(dev, _blktap_sysfs_destroy);
382 blktap_sysfs_show_verbosity(struct class *class, struct class_attribute *attr,
385 return sprintf(buf, "%d\n", blktap_debug_level);
389 blktap_sysfs_set_verbosity(struct class *class, struct class_attribute *attr,
390 const char *buf, size_t size)
394 if (sscanf(buf, "%d", &level) == 1) {
395 blktap_debug_level = level;
401 static CLASS_ATTR(verbosity, S_IRUSR | S_IWUSR,
402 blktap_sysfs_show_verbosity, blktap_sysfs_set_verbosity);
405 blktap_sysfs_show_devices(struct class *class, struct class_attribute *attr,
412 for (i = 0; i < CONFIG_XEN_NR_TAP2_DEVICES; i++) {
417 if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse))
420 ret += sprintf(buf + ret, "%d ", tap->minor);
421 ret += snprintf(buf + ret, sizeof(tap->params.name) - 1,
423 ret += sprintf(buf + ret, "\n");
428 static CLASS_ATTR(devices, S_IRUSR, blktap_sysfs_show_devices, NULL);
431 blktap_sysfs_free(void)
436 class_remove_file(class, &class_attr_verbosity);
437 class_remove_file(class, &class_attr_devices);
439 class_destroy(class);
442 static char *blktap_devnode(struct device *dev, umode_t *mode)
444 return kasprintf(GFP_KERNEL, BLKTAP2_DEV_DIR "blktap%u",
449 blktap_sysfs_init(void)
457 cls = class_create(THIS_MODULE, "blktap2");
461 cls->devnode = blktap_devnode;
463 err = class_create_file(cls, &class_attr_verbosity);
465 err = class_create_file(cls, &class_attr_devices);
467 class_remove_file(cls, &class_attr_verbosity);