aboutsummaryrefslogtreecommitdiffstats
path: root/fs/block_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r--fs/block_dev.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 3c9a03e51b62..f55aad4d1611 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -359,25 +359,30 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
359 mutex_lock(&bd_inode->i_mutex); 359 mutex_lock(&bd_inode->i_mutex);
360 size = i_size_read(bd_inode); 360 size = i_size_read(bd_inode);
361 361
362 retval = -EINVAL;
362 switch (origin) { 363 switch (origin) {
363 case 2: 364 case SEEK_END:
364 offset += size; 365 offset += size;
365 break; 366 break;
366 case 1: 367 case SEEK_CUR:
367 offset += file->f_pos; 368 offset += file->f_pos;
369 case SEEK_SET:
370 break;
371 default:
372 goto out;
368 } 373 }
369 retval = -EINVAL;
370 if (offset >= 0 && offset <= size) { 374 if (offset >= 0 && offset <= size) {
371 if (offset != file->f_pos) { 375 if (offset != file->f_pos) {
372 file->f_pos = offset; 376 file->f_pos = offset;
373 } 377 }
374 retval = offset; 378 retval = offset;
375 } 379 }
380out:
376 mutex_unlock(&bd_inode->i_mutex); 381 mutex_unlock(&bd_inode->i_mutex);
377 return retval; 382 return retval;
378} 383}
379 384
380int blkdev_fsync(struct file *filp, int datasync) 385int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
381{ 386{
382 struct inode *bd_inode = filp->f_mapping->host; 387 struct inode *bd_inode = filp->f_mapping->host;
383 struct block_device *bdev = I_BDEV(bd_inode); 388 struct block_device *bdev = I_BDEV(bd_inode);
@@ -388,14 +393,10 @@ int blkdev_fsync(struct file *filp, int datasync)
388 * i_mutex and doing so causes performance issues with concurrent 393 * i_mutex and doing so causes performance issues with concurrent
389 * O_SYNC writers to a block device. 394 * O_SYNC writers to a block device.
390 */ 395 */
391 mutex_unlock(&bd_inode->i_mutex);
392
393 error = blkdev_issue_flush(bdev, GFP_KERNEL, NULL); 396 error = blkdev_issue_flush(bdev, GFP_KERNEL, NULL);
394 if (error == -EOPNOTSUPP) 397 if (error == -EOPNOTSUPP)
395 error = 0; 398 error = 0;
396 399
397 mutex_lock(&bd_inode->i_mutex);
398
399 return error; 400 return error;
400} 401}
401EXPORT_SYMBOL(blkdev_fsync); 402EXPORT_SYMBOL(blkdev_fsync);
@@ -766,7 +767,19 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
766 if (!disk) 767 if (!disk)
767 return ERR_PTR(-ENXIO); 768 return ERR_PTR(-ENXIO);
768 769
769 whole = bdget_disk(disk, 0); 770 /*
771 * Normally, @bdev should equal what's returned from bdget_disk()
772 * if partno is 0; however, some drivers (floppy) use multiple
773 * bdev's for the same physical device and @bdev may be one of the
774 * aliases. Keep @bdev if partno is 0. This means claimer
775 * tracking is broken for those devices but it has always been that
776 * way.
777 */
778 if (partno)
779 whole = bdget_disk(disk, 0);
780 else
781 whole = bdgrab(bdev);
782
770 module_put(disk->fops->owner); 783 module_put(disk->fops->owner);
771 put_disk(disk); 784 put_disk(disk);
772 if (!whole) 785 if (!whole)
@@ -1439,6 +1452,8 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
1439 1452
1440int blkdev_put(struct block_device *bdev, fmode_t mode) 1453int blkdev_put(struct block_device *bdev, fmode_t mode)
1441{ 1454{
1455 mutex_lock(&bdev->bd_mutex);
1456
1442 if (mode & FMODE_EXCL) { 1457 if (mode & FMODE_EXCL) {
1443 bool bdev_free; 1458 bool bdev_free;
1444 1459
@@ -1447,7 +1462,6 @@ int blkdev_put(struct block_device *bdev, fmode_t mode)
1447 * are protected with bdev_lock. bd_mutex is to 1462 * are protected with bdev_lock. bd_mutex is to
1448 * synchronize disk_holder unlinking. 1463 * synchronize disk_holder unlinking.
1449 */ 1464 */
1450 mutex_lock(&bdev->bd_mutex);
1451 spin_lock(&bdev_lock); 1465 spin_lock(&bdev_lock);
1452 1466
1453 WARN_ON_ONCE(--bdev->bd_holders < 0); 1467 WARN_ON_ONCE(--bdev->bd_holders < 0);
@@ -1465,17 +1479,21 @@ int blkdev_put(struct block_device *bdev, fmode_t mode)
1465 * If this was the last claim, remove holder link and 1479 * If this was the last claim, remove holder link and
1466 * unblock evpoll if it was a write holder. 1480 * unblock evpoll if it was a write holder.
1467 */ 1481 */
1468 if (bdev_free) { 1482 if (bdev_free && bdev->bd_write_holder) {
1469 if (bdev->bd_write_holder) { 1483 disk_unblock_events(bdev->bd_disk);
1470 disk_unblock_events(bdev->bd_disk); 1484 bdev->bd_write_holder = false;
1471 disk_check_events(bdev->bd_disk);
1472 bdev->bd_write_holder = false;
1473 }
1474 } 1485 }
1475
1476 mutex_unlock(&bdev->bd_mutex);
1477 } 1486 }
1478 1487
1488 /*
1489 * Trigger event checking and tell drivers to flush MEDIA_CHANGE
1490 * event. This is to ensure detection of media removal commanded
1491 * from userland - e.g. eject(1).
1492 */
1493 disk_flush_events(bdev->bd_disk, DISK_EVENT_MEDIA_CHANGE);
1494
1495 mutex_unlock(&bdev->bd_mutex);
1496
1479 return __blkdev_put(bdev, mode, 0); 1497 return __blkdev_put(bdev, mode, 0);
1480} 1498}
1481EXPORT_SYMBOL(blkdev_put); 1499EXPORT_SYMBOL(blkdev_put);