2 * This file adds support for a character device /dev/bcache that is used to
3 * atomically register a list of devices, remove a device from a cache_set
4 * and add a device to a cache set.
6 * Copyright (c) 2014 Datera, Inc.
14 #include <linux/module.h>
16 #include <linux/major.h>
17 #include <linux/cdev.h>
18 #include <linux/device.h>
19 #include <linux/ioctl.h>
20 #include <linux/uaccess.h>
21 #include <linux/slab.h>
22 #include <linux/bcache-ioctl.h>
24 static long bch_ioctl_assemble(struct bch_ioctl_assemble __user *user_arg)
26 struct bch_ioctl_assemble arg;
28 u64 *user_devs = NULL;
33 if (copy_from_user(&arg, user_arg, sizeof(arg)))
36 user_devs = kmalloc_array(arg.nr_devs, sizeof(u64), GFP_KERNEL);
40 devs = kcalloc(arg.nr_devs, sizeof(char *), GFP_KERNEL);
42 if (copy_from_user(user_devs, user_arg->devs,
43 sizeof(u64) * arg.nr_devs))
46 for (i = 0; i < arg.nr_devs; i++) {
47 devs[i] = strndup_user((const char __user *)(unsigned long)
56 err = bch_fs_open(devs, arg.nr_devs, bch_opts_empty(), NULL);
58 pr_err("Could not register cache set: %s", err);
66 for (i = 0; i < arg.nr_devs; i++)
72 static long bch_ioctl_incremental(struct bch_ioctl_incremental __user *user_arg)
74 struct bch_ioctl_incremental arg;
78 if (copy_from_user(&arg, user_arg, sizeof(arg)))
81 path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX);
85 err = bch_fs_open_incremental(path);
89 pr_err("Could not register bcache devices: %s", err);
96 static long bch_global_ioctl(unsigned cmd, void __user *arg)
99 case BCH_IOCTL_ASSEMBLE:
100 return bch_ioctl_assemble(arg);
101 case BCH_IOCTL_INCREMENTAL:
102 return bch_ioctl_incremental(arg);
108 static long bch_ioctl_stop(struct cache_set *c)
114 static long bch_ioctl_disk_add(struct cache_set *c,
115 struct bch_ioctl_disk_add __user *user_arg)
117 struct bch_ioctl_disk_add arg;
121 if (copy_from_user(&arg, user_arg, sizeof(arg)))
124 path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX);
128 ret = bch_dev_add(c, path);
134 /* returns with ref on ca->ref */
135 static struct cache *bch_device_lookup(struct cache_set *c,
136 const char __user *dev)
138 struct block_device *bdev;
143 path = strndup_user(dev, PATH_MAX);
145 return ERR_PTR(-ENOMEM);
147 bdev = lookup_bdev(strim(path));
150 return ERR_CAST(bdev);
152 for_each_cache(ca, c, i)
153 if (ca->disk_sb.bdev == bdev)
162 static long bch_ioctl_disk_remove(struct cache_set *c,
163 struct bch_ioctl_disk_remove __user *user_arg)
165 struct bch_ioctl_disk_remove arg;
169 if (copy_from_user(&arg, user_arg, sizeof(arg)))
172 ca = bch_device_lookup(c, (const char __user *)(unsigned long) arg.dev);
176 ret = bch_dev_remove(ca, arg.flags & BCH_FORCE_IF_DATA_MISSING)
179 percpu_ref_put(&ca->ref);
183 static long bch_ioctl_disk_fail(struct cache_set *c,
184 struct bch_ioctl_disk_fail __user *user_arg)
186 struct bch_ioctl_disk_fail arg;
190 if (copy_from_user(&arg, user_arg, sizeof(arg)))
193 ca = bch_device_lookup(c, (const char __user *)(unsigned long) arg.dev);
197 /* XXX: failed not actually implemented yet */
198 ret = bch_dev_remove(ca, true);
200 percpu_ref_put(&ca->ref);
204 static struct bch_member *bch_uuid_lookup(struct cache_set *c, uuid_le uuid)
206 struct bch_sb_field_members *mi = bch_sb_get_members(c->disk_sb);
209 lockdep_assert_held(&c->sb_lock);
211 for (i = 0; i < c->disk_sb->nr_devices; i++)
212 if (!memcmp(&mi->members[i].uuid, &uuid, sizeof(uuid)))
213 return &mi->members[i];
218 static long bch_ioctl_disk_remove_by_uuid(struct cache_set *c,
219 struct bch_ioctl_disk_remove_by_uuid __user *user_arg)
221 struct bch_ioctl_disk_fail_by_uuid arg;
222 struct bch_member *m;
225 if (copy_from_user(&arg, user_arg, sizeof(arg)))
228 mutex_lock(&c->sb_lock);
229 if ((m = bch_uuid_lookup(c, arg.dev))) {
231 SET_BCH_MEMBER_STATE(m, BCH_MEMBER_STATE_FAILED);
235 mutex_unlock(&c->sb_lock);
240 static long bch_ioctl_disk_fail_by_uuid(struct cache_set *c,
241 struct bch_ioctl_disk_fail_by_uuid __user *user_arg)
243 struct bch_ioctl_disk_fail_by_uuid arg;
244 struct bch_member *m;
247 if (copy_from_user(&arg, user_arg, sizeof(arg)))
250 mutex_lock(&c->sb_lock);
251 if ((m = bch_uuid_lookup(c, arg.dev))) {
252 SET_BCH_MEMBER_STATE(m, BCH_MEMBER_STATE_FAILED);
256 mutex_unlock(&c->sb_lock);
261 static long bch_ioctl_query_uuid(struct cache_set *c,
262 struct bch_ioctl_query_uuid __user *user_arg)
264 return copy_to_user(&user_arg->uuid,
266 sizeof(c->sb.user_uuid));
269 long bch_fs_ioctl(struct cache_set *c, unsigned cmd, void __user *arg)
271 /* ioctls that don't require admin cap: */
273 case BCH_IOCTL_QUERY_UUID:
274 return bch_ioctl_query_uuid(c, arg);
277 if (!capable(CAP_SYS_ADMIN))
280 /* ioctls that do require admin cap: */
285 return bch_ioctl_stop(c);
287 case BCH_IOCTL_DISK_ADD:
288 return bch_ioctl_disk_add(c, arg);
289 case BCH_IOCTL_DISK_REMOVE:
290 return bch_ioctl_disk_remove(c, arg);
291 case BCH_IOCTL_DISK_FAIL:
292 return bch_ioctl_disk_fail(c, arg);
294 case BCH_IOCTL_DISK_REMOVE_BY_UUID:
295 return bch_ioctl_disk_remove_by_uuid(c, arg);
296 case BCH_IOCTL_DISK_FAIL_BY_UUID:
297 return bch_ioctl_disk_fail_by_uuid(c, arg);
304 static long bch_chardev_ioctl(struct file *filp, unsigned cmd, unsigned long v)
306 struct cache_set *c = filp->private_data;
307 void __user *arg = (void __user *) v;
310 ? bch_fs_ioctl(c, cmd, arg)
311 : bch_global_ioctl(cmd, arg);
314 static const struct file_operations bch_chardev_fops = {
315 .owner = THIS_MODULE,
316 .unlocked_ioctl = bch_chardev_ioctl,
317 .open = nonseekable_open,
320 static int bch_chardev_major;
321 static struct class *bch_chardev_class;
322 static struct device *bch_chardev;
323 static DEFINE_IDR(bch_chardev_minor);
325 void bch_fs_chardev_exit(struct cache_set *c)
327 if (!IS_ERR_OR_NULL(c->chardev))
328 device_unregister(c->chardev);
330 idr_remove(&bch_chardev_minor, c->minor);
333 int bch_fs_chardev_init(struct cache_set *c)
335 c->minor = idr_alloc(&bch_chardev_minor, c, 0, 0, GFP_KERNEL);
339 c->chardev = device_create(bch_chardev_class, NULL,
340 MKDEV(bch_chardev_major, c->minor), NULL,
341 "bcache%u-ctl", c->minor);
342 if (IS_ERR(c->chardev))
343 return PTR_ERR(c->chardev);
348 void bch_chardev_exit(void)
350 if (!IS_ERR_OR_NULL(bch_chardev_class))
351 device_destroy(bch_chardev_class,
352 MKDEV(bch_chardev_major, 0));
353 if (!IS_ERR_OR_NULL(bch_chardev_class))
354 class_destroy(bch_chardev_class);
355 if (bch_chardev_major > 0)
356 unregister_chrdev(bch_chardev_major, "bcache");
360 int __init bch_chardev_init(void)
362 bch_chardev_major = register_chrdev(0, "bcache-ctl", &bch_chardev_fops);
363 if (bch_chardev_major < 0)
364 return bch_chardev_major;
366 bch_chardev_class = class_create(THIS_MODULE, "bcache");
367 if (IS_ERR(bch_chardev_class))
368 return PTR_ERR(bch_chardev_class);
370 bch_chardev = device_create(bch_chardev_class, NULL,
371 MKDEV(bch_chardev_major, 255),
373 if (IS_ERR(bch_chardev))
374 return PTR_ERR(bch_chardev);