diff options
Diffstat (limited to 'fs/fuse/cuse.c')
-rw-r--r-- | fs/fuse/cuse.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index ee8d55042298..e397b675b029 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <linux/miscdevice.h> | 45 | #include <linux/miscdevice.h> |
46 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
47 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
48 | #include <linux/spinlock.h> | ||
49 | #include <linux/stat.h> | 48 | #include <linux/stat.h> |
50 | #include <linux/module.h> | 49 | #include <linux/module.h> |
51 | 50 | ||
@@ -63,7 +62,7 @@ struct cuse_conn { | |||
63 | bool unrestricted_ioctl; | 62 | bool unrestricted_ioctl; |
64 | }; | 63 | }; |
65 | 64 | ||
66 | static DEFINE_SPINLOCK(cuse_lock); /* protects cuse_conntbl */ | 65 | static DEFINE_MUTEX(cuse_lock); /* protects registration */ |
67 | static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN]; | 66 | static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN]; |
68 | static struct class *cuse_class; | 67 | static struct class *cuse_class; |
69 | 68 | ||
@@ -114,14 +113,14 @@ static int cuse_open(struct inode *inode, struct file *file) | |||
114 | int rc; | 113 | int rc; |
115 | 114 | ||
116 | /* look up and get the connection */ | 115 | /* look up and get the connection */ |
117 | spin_lock(&cuse_lock); | 116 | mutex_lock(&cuse_lock); |
118 | list_for_each_entry(pos, cuse_conntbl_head(devt), list) | 117 | list_for_each_entry(pos, cuse_conntbl_head(devt), list) |
119 | if (pos->dev->devt == devt) { | 118 | if (pos->dev->devt == devt) { |
120 | fuse_conn_get(&pos->fc); | 119 | fuse_conn_get(&pos->fc); |
121 | cc = pos; | 120 | cc = pos; |
122 | break; | 121 | break; |
123 | } | 122 | } |
124 | spin_unlock(&cuse_lock); | 123 | mutex_unlock(&cuse_lock); |
125 | 124 | ||
126 | /* dead? */ | 125 | /* dead? */ |
127 | if (!cc) | 126 | if (!cc) |
@@ -267,7 +266,7 @@ static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp) | |||
267 | static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo) | 266 | static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo) |
268 | { | 267 | { |
269 | char *end = p + len; | 268 | char *end = p + len; |
270 | char *key, *val; | 269 | char *uninitialized_var(key), *uninitialized_var(val); |
271 | int rc; | 270 | int rc; |
272 | 271 | ||
273 | while (true) { | 272 | while (true) { |
@@ -305,14 +304,14 @@ static void cuse_gendev_release(struct device *dev) | |||
305 | */ | 304 | */ |
306 | static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | 305 | static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) |
307 | { | 306 | { |
308 | struct cuse_conn *cc = fc_to_cc(fc); | 307 | struct cuse_conn *cc = fc_to_cc(fc), *pos; |
309 | struct cuse_init_out *arg = req->out.args[0].value; | 308 | struct cuse_init_out *arg = req->out.args[0].value; |
310 | struct page *page = req->pages[0]; | 309 | struct page *page = req->pages[0]; |
311 | struct cuse_devinfo devinfo = { }; | 310 | struct cuse_devinfo devinfo = { }; |
312 | struct device *dev; | 311 | struct device *dev; |
313 | struct cdev *cdev; | 312 | struct cdev *cdev; |
314 | dev_t devt; | 313 | dev_t devt; |
315 | int rc; | 314 | int rc, i; |
316 | 315 | ||
317 | if (req->out.h.error || | 316 | if (req->out.h.error || |
318 | arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) { | 317 | arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) { |
@@ -356,15 +355,24 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
356 | dev_set_drvdata(dev, cc); | 355 | dev_set_drvdata(dev, cc); |
357 | dev_set_name(dev, "%s", devinfo.name); | 356 | dev_set_name(dev, "%s", devinfo.name); |
358 | 357 | ||
358 | mutex_lock(&cuse_lock); | ||
359 | |||
360 | /* make sure the device-name is unique */ | ||
361 | for (i = 0; i < CUSE_CONNTBL_LEN; ++i) { | ||
362 | list_for_each_entry(pos, &cuse_conntbl[i], list) | ||
363 | if (!strcmp(dev_name(pos->dev), dev_name(dev))) | ||
364 | goto err_unlock; | ||
365 | } | ||
366 | |||
359 | rc = device_add(dev); | 367 | rc = device_add(dev); |
360 | if (rc) | 368 | if (rc) |
361 | goto err_device; | 369 | goto err_unlock; |
362 | 370 | ||
363 | /* register cdev */ | 371 | /* register cdev */ |
364 | rc = -ENOMEM; | 372 | rc = -ENOMEM; |
365 | cdev = cdev_alloc(); | 373 | cdev = cdev_alloc(); |
366 | if (!cdev) | 374 | if (!cdev) |
367 | goto err_device; | 375 | goto err_unlock; |
368 | 376 | ||
369 | cdev->owner = THIS_MODULE; | 377 | cdev->owner = THIS_MODULE; |
370 | cdev->ops = &cuse_frontend_fops; | 378 | cdev->ops = &cuse_frontend_fops; |
@@ -377,9 +385,8 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
377 | cc->cdev = cdev; | 385 | cc->cdev = cdev; |
378 | 386 | ||
379 | /* make the device available */ | 387 | /* make the device available */ |
380 | spin_lock(&cuse_lock); | ||
381 | list_add(&cc->list, cuse_conntbl_head(devt)); | 388 | list_add(&cc->list, cuse_conntbl_head(devt)); |
382 | spin_unlock(&cuse_lock); | 389 | mutex_unlock(&cuse_lock); |
383 | 390 | ||
384 | /* announce device availability */ | 391 | /* announce device availability */ |
385 | dev_set_uevent_suppress(dev, 0); | 392 | dev_set_uevent_suppress(dev, 0); |
@@ -391,7 +398,8 @@ out: | |||
391 | 398 | ||
392 | err_cdev: | 399 | err_cdev: |
393 | cdev_del(cdev); | 400 | cdev_del(cdev); |
394 | err_device: | 401 | err_unlock: |
402 | mutex_unlock(&cuse_lock); | ||
395 | put_device(dev); | 403 | put_device(dev); |
396 | err_region: | 404 | err_region: |
397 | unregister_chrdev_region(devt, 1); | 405 | unregister_chrdev_region(devt, 1); |
@@ -520,9 +528,9 @@ static int cuse_channel_release(struct inode *inode, struct file *file) | |||
520 | int rc; | 528 | int rc; |
521 | 529 | ||
522 | /* remove from the conntbl, no more access from this point on */ | 530 | /* remove from the conntbl, no more access from this point on */ |
523 | spin_lock(&cuse_lock); | 531 | mutex_lock(&cuse_lock); |
524 | list_del_init(&cc->list); | 532 | list_del_init(&cc->list); |
525 | spin_unlock(&cuse_lock); | 533 | mutex_unlock(&cuse_lock); |
526 | 534 | ||
527 | /* remove device */ | 535 | /* remove device */ |
528 | if (cc->dev) | 536 | if (cc->dev) |