aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2012-11-17 06:45:48 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2013-01-17 07:04:57 -0500
commit30783587b0f318b9e2e165f34cf5dfd9425a4904 (patch)
tree4aeaf43d76cda5cad2c968214c1efce047f53f71
parent8ce03fd76d323526a693d05d85296ef07a387a9f (diff)
cuse: do not register multiple devices with identical names
Sysfs doesn't allow two devices with the same name, but we register a sysfs entry for each cuse device without checking for name collisions. This extends the registration to first check whether the name was already registered. To avoid race-conditions between the name-check and linking the device, we need to protect the whole registration with a mutex. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r--fs/fuse/cuse.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index 048e89f25082..2a2797e2abc5 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -304,14 +304,14 @@ static void cuse_gendev_release(struct device *dev)
304 */ 304 */
305static 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)
306{ 306{
307 struct cuse_conn *cc = fc_to_cc(fc); 307 struct cuse_conn *cc = fc_to_cc(fc), *pos;
308 struct cuse_init_out *arg = req->out.args[0].value; 308 struct cuse_init_out *arg = req->out.args[0].value;
309 struct page *page = req->pages[0]; 309 struct page *page = req->pages[0];
310 struct cuse_devinfo devinfo = { }; 310 struct cuse_devinfo devinfo = { };
311 struct device *dev; 311 struct device *dev;
312 struct cdev *cdev; 312 struct cdev *cdev;
313 dev_t devt; 313 dev_t devt;
314 int rc; 314 int rc, i;
315 315
316 if (req->out.h.error || 316 if (req->out.h.error ||
317 arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) { 317 arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) {
@@ -355,15 +355,24 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
355 dev_set_drvdata(dev, cc); 355 dev_set_drvdata(dev, cc);
356 dev_set_name(dev, "%s", devinfo.name); 356 dev_set_name(dev, "%s", devinfo.name);
357 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
358 rc = device_add(dev); 367 rc = device_add(dev);
359 if (rc) 368 if (rc)
360 goto err_device; 369 goto err_unlock;
361 370
362 /* register cdev */ 371 /* register cdev */
363 rc = -ENOMEM; 372 rc = -ENOMEM;
364 cdev = cdev_alloc(); 373 cdev = cdev_alloc();
365 if (!cdev) 374 if (!cdev)
366 goto err_device; 375 goto err_unlock;
367 376
368 cdev->owner = THIS_MODULE; 377 cdev->owner = THIS_MODULE;
369 cdev->ops = &cuse_frontend_fops; 378 cdev->ops = &cuse_frontend_fops;
@@ -376,7 +385,6 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
376 cc->cdev = cdev; 385 cc->cdev = cdev;
377 386
378 /* make the device available */ 387 /* make the device available */
379 mutex_lock(&cuse_lock);
380 list_add(&cc->list, cuse_conntbl_head(devt)); 388 list_add(&cc->list, cuse_conntbl_head(devt));
381 mutex_unlock(&cuse_lock); 389 mutex_unlock(&cuse_lock);
382 390
@@ -390,7 +398,8 @@ out:
390 398
391err_cdev: 399err_cdev:
392 cdev_del(cdev); 400 cdev_del(cdev);
393err_device: 401err_unlock:
402 mutex_unlock(&cuse_lock);
394 put_device(dev); 403 put_device(dev);
395err_region: 404err_region:
396 unregister_chrdev_region(devt, 1); 405 unregister_chrdev_region(devt, 1);