aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/cuse.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/cuse.c')
-rw-r--r--fs/fuse/cuse.c36
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
66static DEFINE_SPINLOCK(cuse_lock); /* protects cuse_conntbl */ 65static DEFINE_MUTEX(cuse_lock); /* protects registration */
67static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN]; 66static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN];
68static struct class *cuse_class; 67static 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)
267static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo) 266static 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 */
306static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) 305static 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
392err_cdev: 399err_cdev:
393 cdev_del(cdev); 400 cdev_del(cdev);
394err_device: 401err_unlock:
402 mutex_unlock(&cuse_lock);
395 put_device(dev); 403 put_device(dev);
396err_region: 404err_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)