Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6e9624b8 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Jens Axboe
Browse files

block: push down BKL into .open and .release



The open and release block_device_operations are currently
called with the BKL held. In order to change that, we must
first make sure that all drivers that currently rely
on this have no regressions.

This blindly pushes the BKL into all .open and .release
operations for all block drivers to prepare for the
next step. The drivers can subsequently replace the BKL
with their own locks or remove it completely when it can
be shown that it is not needed.

The functions blkdev_get and blkdev_put are the only
remaining users of the big kernel lock in the block
layer, besides a few uses in the ioctl code, none
of which need to serialize with blkdev_{get,put}.

Most of these two functions is also under the protection
of bdev->bd_mutex, including the actual calls to
->open and ->release, and the common code does not
access any global data structures that need the BKL.

Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Acked-by: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarJens Axboe <jaxboe@fusionio.com>
parent 8a6cfeb6
Loading
Loading
Loading
Loading
+6 −1
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@
#include "linux/mm.h"
#include "linux/mm.h"
#include "linux/slab.h"
#include "linux/slab.h"
#include "linux/vmalloc.h"
#include "linux/vmalloc.h"
#include "linux/smp_lock.h"
#include "linux/blkpg.h"
#include "linux/blkpg.h"
#include "linux/genhd.h"
#include "linux/genhd.h"
#include "linux/spinlock.h"
#include "linux/spinlock.h"
@@ -1098,6 +1099,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode)
	struct ubd *ubd_dev = disk->private_data;
	struct ubd *ubd_dev = disk->private_data;
	int err = 0;
	int err = 0;


	lock_kernel();
	if(ubd_dev->count == 0){
	if(ubd_dev->count == 0){
		err = ubd_open_dev(ubd_dev);
		err = ubd_open_dev(ubd_dev);
		if(err){
		if(err){
@@ -1116,6 +1118,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode)
	        err = -EROFS;
	        err = -EROFS;
	}*/
	}*/
out:
out:
	unlock_kernel();
	return err;
	return err;
}
}


@@ -1123,8 +1126,10 @@ static int ubd_release(struct gendisk *disk, fmode_t mode)
{
{
	struct ubd *ubd_dev = disk->private_data;
	struct ubd *ubd_dev = disk->private_data;


	lock_kernel();
	if(--ubd_dev->count == 0)
	if(--ubd_dev->count == 0)
		ubd_close_dev(ubd_dev);
		ubd_close_dev(ubd_dev);
	unlock_kernel();
	return 0;
	return 0;
}
}


+9 −4
Original line number Original line Diff line number Diff line
@@ -79,23 +79,28 @@ static int DAC960_open(struct block_device *bdev, fmode_t mode)
	struct gendisk *disk = bdev->bd_disk;
	struct gendisk *disk = bdev->bd_disk;
	DAC960_Controller_T *p = disk->queue->queuedata;
	DAC960_Controller_T *p = disk->queue->queuedata;
	int drive_nr = (long)disk->private_data;
	int drive_nr = (long)disk->private_data;
	int ret = -ENXIO;


	lock_kernel();
	if (p->FirmwareType == DAC960_V1_Controller) {
	if (p->FirmwareType == DAC960_V1_Controller) {
		if (p->V1.LogicalDriveInformation[drive_nr].
		if (p->V1.LogicalDriveInformation[drive_nr].
		    LogicalDriveState == DAC960_V1_LogicalDrive_Offline)
		    LogicalDriveState == DAC960_V1_LogicalDrive_Offline)
			return -ENXIO;
			goto out;
	} else {
	} else {
		DAC960_V2_LogicalDeviceInfo_T *i =
		DAC960_V2_LogicalDeviceInfo_T *i =
			p->V2.LogicalDeviceInformation[drive_nr];
			p->V2.LogicalDeviceInformation[drive_nr];
		if (!i || i->LogicalDeviceState == DAC960_V2_LogicalDevice_Offline)
		if (!i || i->LogicalDeviceState == DAC960_V2_LogicalDevice_Offline)
			return -ENXIO;
			goto out;
	}
	}


	check_disk_change(bdev);
	check_disk_change(bdev);


	if (!get_capacity(p->disks[drive_nr]))
	if (!get_capacity(p->disks[drive_nr]))
		return -ENXIO;
		goto out;
	return 0;
	ret = 0;
out:
	unlock_kernel();
	return ret;
}
}


static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo)
static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+10 −2
Original line number Original line Diff line number Diff line
@@ -1555,10 +1555,13 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
	int old_dev;
	int old_dev;
	unsigned long flags;
	unsigned long flags;


	lock_kernel();
	old_dev = fd_device[drive];
	old_dev = fd_device[drive];


	if (fd_ref[drive] && old_dev != system)
	if (fd_ref[drive] && old_dev != system) {
		unlock_kernel();
		return -EBUSY;
		return -EBUSY;
	}


	if (mode & (FMODE_READ|FMODE_WRITE)) {
	if (mode & (FMODE_READ|FMODE_WRITE)) {
		check_disk_change(bdev);
		check_disk_change(bdev);
@@ -1571,10 +1574,12 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
			fd_deselect (drive);
			fd_deselect (drive);
			rel_fdc();
			rel_fdc();


			if (wrprot)
			if (wrprot) {
				unlock_kernel();
				return -EROFS;
				return -EROFS;
			}
			}
		}
		}
	}


	local_irq_save(flags);
	local_irq_save(flags);
	fd_ref[drive]++;
	fd_ref[drive]++;
@@ -1589,6 +1594,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
	printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
	printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
	       unit[drive].type->name, data_types[system].name);
	       unit[drive].type->name, data_types[system].name);


	unlock_kernel();
	return 0;
	return 0;
}
}


@@ -1597,6 +1603,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
	struct amiga_floppy_struct *p = disk->private_data;
	struct amiga_floppy_struct *p = disk->private_data;
	int drive = p - unit;
	int drive = p - unit;


	lock_kernel();
	if (unit[drive].dirty == 1) {
	if (unit[drive].dirty == 1) {
		del_timer (flush_track_timer + drive);
		del_timer (flush_track_timer + drive);
		non_int_flush_track (drive);
		non_int_flush_track (drive);
@@ -1610,6 +1617,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
/* the mod_use counter is handled this way */
/* the mod_use counter is handled this way */
	floppy_off (drive | 0x40000000);
	floppy_off (drive | 0x40000000);
#endif
#endif
	unlock_kernel();
	return 0;
	return 0;
}
}


+4 −0
Original line number Original line Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/genhd.h>
#include <linux/genhd.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/smp_lock.h>
#include "aoe.h"
#include "aoe.h"


static struct kmem_cache *buf_pool_cache;
static struct kmem_cache *buf_pool_cache;
@@ -124,13 +125,16 @@ aoeblk_open(struct block_device *bdev, fmode_t mode)
	struct aoedev *d = bdev->bd_disk->private_data;
	struct aoedev *d = bdev->bd_disk->private_data;
	ulong flags;
	ulong flags;


	lock_kernel();
	spin_lock_irqsave(&d->lock, flags);
	spin_lock_irqsave(&d->lock, flags);
	if (d->flags & DEVFL_UP) {
	if (d->flags & DEVFL_UP) {
		d->nopen++;
		d->nopen++;
		spin_unlock_irqrestore(&d->lock, flags);
		spin_unlock_irqrestore(&d->lock, flags);
		unlock_kernel();
		return 0;
		return 0;
	}
	}
	spin_unlock_irqrestore(&d->lock, flags);
	spin_unlock_irqrestore(&d->lock, flags);
	unlock_kernel();
	return -ENODEV;
	return -ENODEV;
}
}


+13 −1
Original line number Original line Diff line number Diff line
@@ -1850,22 +1850,34 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
	return 0;
	return 0;
}
}


static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
{
	int ret;

	lock_kernel();
	ret = floppy_open(bdev, mode);
	unlock_kernel();

	return ret;
}


static int floppy_release(struct gendisk *disk, fmode_t mode)
static int floppy_release(struct gendisk *disk, fmode_t mode)
{
{
	struct atari_floppy_struct *p = disk->private_data;
	struct atari_floppy_struct *p = disk->private_data;
	lock_kernel();
	if (p->ref < 0)
	if (p->ref < 0)
		p->ref = 0;
		p->ref = 0;
	else if (!p->ref--) {
	else if (!p->ref--) {
		printk(KERN_ERR "floppy_release with fd_ref == 0");
		printk(KERN_ERR "floppy_release with fd_ref == 0");
		p->ref = 0;
		p->ref = 0;
	}
	}
	unlock_kernel();
	return 0;
	return 0;
}
}


static const struct block_device_operations floppy_fops = {
static const struct block_device_operations floppy_fops = {
	.owner		= THIS_MODULE,
	.owner		= THIS_MODULE,
	.open		= floppy_open,
	.open		= floppy_unlocked_open,
	.release	= floppy_release,
	.release	= floppy_release,
	.ioctl		= fd_ioctl,
	.ioctl		= fd_ioctl,
	.media_changed	= check_floppy_change,
	.media_changed	= check_floppy_change,
Loading