1 #include <linux/types.h>
2 #include <linux/device.h>
3 #include <linux/module.h>
4 #include <linux/sched.h>
5 #include <linux/genhd.h>
6 #include <linux/blkdev.h>
10 int blktap_debug_level = 1;
12 static struct class *class;
15 blktap_sysfs_set_name(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
19 tap = dev_get_drvdata(dev);
23 if (size > BLKTAP2_MAX_MESSAGE_LEN)
26 if (strnlen(buf, size) >= size)
29 strlcpy(tap->name, buf, size);
35 blktap_sysfs_get_name(struct device *dev, struct device_attribute *attr, char *buf)
40 tap = dev_get_drvdata(dev);
45 size = sprintf(buf, "%s\n", tap->name);
47 size = sprintf(buf, "%d\n", tap->minor);
51 static DEVICE_ATTR(name, S_IRUGO|S_IWUSR,
52 blktap_sysfs_get_name, blktap_sysfs_set_name);
55 blktap_sysfs_remove_work(struct work_struct *work)
58 = container_of(work, struct blktap, remove_work);
59 blktap_control_destroy_tap(tap);
63 blktap_sysfs_remove_device(struct device *dev,
64 struct device_attribute *attr,
65 const char *buf, size_t size)
70 tap = dev_get_drvdata(dev);
74 if (test_and_set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
78 struct blkif_sring *sring = tap->ring.ring.sring;
79 sring->private.tapif_user.msg = BLKTAP2_RING_MESSAGE_CLOSE;
80 blktap_ring_kick_user(tap);
82 INIT_WORK(&tap->remove_work, blktap_sysfs_remove_work);
83 schedule_work(&tap->remove_work);
86 err = wait_event_interruptible(tap->remove_wait,
87 !dev_get_drvdata(dev));
93 static DEVICE_ATTR(remove, S_IWUSR, NULL, blktap_sysfs_remove_device);
96 blktap_sysfs_debug_device(struct device *dev, struct device_attribute *attr, char *buf)
99 char *s = buf, *end = buf + PAGE_SIZE;
101 tap = dev_get_drvdata(dev);
105 s += blktap_control_debug(tap, s, end - s);
107 s += blktap_request_debug(tap, s, end - s);
109 s += blktap_device_debug(tap, s, end - s);
111 s += blktap_ring_debug(tap, s, end - s);
115 static DEVICE_ATTR(debug, S_IRUGO, blktap_sysfs_debug_device, NULL);
118 blktap_sysfs_show_task(struct device *dev, struct device_attribute *attr, char *buf)
123 tap = dev_get_drvdata(dev);
128 rv = sprintf(buf, "%d\n", tap->ring.task->pid);
132 static DEVICE_ATTR(task, S_IRUGO, blktap_sysfs_show_task, NULL);
135 blktap_sysfs_show_pool(struct device *dev,
136 struct device_attribute *attr,
139 struct blktap *tap = dev_get_drvdata(dev);
140 return sprintf(buf, "%s", kobject_name(&tap->pool->kobj));
144 blktap_sysfs_store_pool(struct device *dev,
145 struct device_attribute *attr,
146 const char *buf, size_t size)
148 struct blktap *tap = dev_get_drvdata(dev);
149 struct blktap_page_pool *pool, *tmp = tap->pool;
154 pool = blktap_page_pool_get(buf);
156 return PTR_ERR(pool);
159 kobject_put(&tmp->kobj);
163 static DEVICE_ATTR(pool, S_IRUSR|S_IWUSR,
164 blktap_sysfs_show_pool, blktap_sysfs_store_pool);
167 blktap_sysfs_create(struct blktap *tap)
169 struct blktap_ring *ring = &tap->ring;
173 init_waitqueue_head(&tap->remove_wait);
175 dev = device_create(class, NULL, ring->devno,
176 tap, "blktap%d", tap->minor);
180 err = device_create_file(dev, &dev_attr_name);
182 err = device_create_file(dev, &dev_attr_remove);
184 err = device_create_file(dev, &dev_attr_debug);
186 err = device_create_file(dev, &dev_attr_task);
188 err = device_create_file(dev, &dev_attr_pool);
192 device_unregister(dev);
198 blktap_sysfs_destroy(struct blktap *tap)
200 struct blktap_ring *ring = &tap->ring;
208 dev_set_drvdata(dev, NULL);
209 wake_up(&tap->remove_wait);
211 device_unregister(dev);
216 blktap_sysfs_show_verbosity(struct class *class, struct class_attribute *attr,
219 return sprintf(buf, "%d\n", blktap_debug_level);
223 blktap_sysfs_set_verbosity(struct class *class, struct class_attribute *attr,
224 const char *buf, size_t size)
228 if (sscanf(buf, "%d", &level) == 1) {
229 blktap_debug_level = level;
235 static CLASS_ATTR(verbosity, S_IRUGO|S_IWUSR,
236 blktap_sysfs_show_verbosity, blktap_sysfs_set_verbosity);
239 blktap_sysfs_show_devices(struct class *class, struct class_attribute *attr,
245 mutex_lock(&blktap_lock);
248 for (i = 0; i < blktap_max_minor; i++) {
253 if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse))
256 ret += sprintf(buf + ret, "%d %s\n", tap->minor, tap->name);
259 mutex_unlock(&blktap_lock);
263 static CLASS_ATTR(devices, S_IRUGO, blktap_sysfs_show_devices, NULL);
265 static char *blktap_devnode(struct device *dev, umode_t *mode)
267 return kasprintf(GFP_KERNEL, BLKTAP2_DEV_DIR "blktap%u",
272 blktap_sysfs_exit(void)
275 class_destroy(class);
279 blktap_sysfs_init(void)
284 cls = class_create(THIS_MODULE, "blktap2");
288 cls->devnode = blktap_devnode;
290 err = class_create_file(cls, &class_attr_verbosity);
292 err = class_create_file(cls, &class_attr_devices);