/*
 * Trigger a partition detection.
 */
int dasd_scan_partitions(struct dasd_block *block)
{
	struct block_device *bdev;

	bdev = bdget_disk(block->gdp, 0);
	if (!bdev || blkdev_get(bdev, FMODE_READ) < 0)
		return -ENODEV;
	/*
	 * See fs/partition/check.c:register_disk,rescan_partitions
	 * Can't call rescan_partitions directly. Use ioctl.
	 */
	ioctl_by_bdev(bdev, BLKRRPART, 0);
	/*
	 * Since the matching blkdev_put call to the blkdev_get in
	 * this function is not called before dasd_destroy_partitions
	 * the offline open_count limit needs to be increased from
	 * 0 to 1. This is done by setting device->bdev (see
	 * dasd_generic_set_offline). As long as the partition
	 * detection is running no offline should be allowed. That
	 * is why the assignment to device->bdev is done AFTER
	 * the BLKRRPART ioctl.
	 */
	block->bdev = bdev;
	return 0;
}
示例#2
0
/**
 * Resize disk.
 *
 * @gd disk.
 * @new_size new size [logical block].
 *
 * RETURN:
 *   true in success, or false.
 */
bool resize_disk(struct gendisk *gd, u64 new_size)
{
	struct block_device *bdev;
	u64 old_size;

	ASSERT(gd);

	old_size = get_capacity(gd);
	if (old_size == new_size) {
		return true;
	}
	set_capacity(gd, new_size);

	bdev = bdget_disk(gd, 0);
	if (!bdev) {
		LOGe("bdget_disk failed.\n");
		return false;
	}
	mutex_lock(&bdev->bd_mutex);
	if (old_size > new_size) {
		LOGn("Shrink disk should discard block cache.\n");
		check_disk_size_change(gd, bdev);
		/* This should be implemented in check_disk_size_change(). */
		bdev->bd_invalidated = 0;
	} else {
		i_size_write(bdev->bd_inode,
			(loff_t)new_size * LOGICAL_BLOCK_SIZE);
	}
	mutex_unlock(&bdev->bd_mutex);
	bdput(bdev);
	return true;
}
示例#3
0
static ssize_t reset_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t len)
{
	int ret;
	unsigned short do_reset;
	struct zram *zram;
	struct block_device *bdev;

	zram = dev_to_zram(dev);
	bdev = bdget_disk(zram->disk, 0);

	/* Do not reset an active device! */
	if (bdev->bd_holders)
		return -EBUSY;

	ret = kstrtou16(buf, 10, &do_reset);
	if (ret)
		return ret;

	if (!do_reset)
		return -EINVAL;

	/* Make sure all pending I/O is finished */
	if (bdev)
		fsync_bdev(bdev);

	down_write(&zram->init_lock);
	if (zram->init_done)
		__zram_reset_device(zram);
	up_write(&zram->init_lock);

	return len;
}
示例#4
0
/* this function performs work that has been deferred until sleeping is OK
 */
void
aoecmd_sleepwork(struct work_struct *work)
{
	struct aoedev *d = container_of(work, struct aoedev, work);

	if (d->flags & DEVFL_GDALLOC)
		aoeblk_gdalloc(d);

	if (d->flags & DEVFL_NEWSIZE) {
		struct block_device *bd;
		unsigned long flags;
		u64 ssize;

		ssize = d->gd->capacity;
		bd = bdget_disk(d->gd, 0);

		if (bd) {
			mutex_lock(&bd->bd_inode->i_mutex);
			i_size_write(bd->bd_inode, (loff_t)ssize<<9);
			mutex_unlock(&bd->bd_inode->i_mutex);
			bdput(bd);
		}
		spin_lock_irqsave(&d->lock, flags);
		d->flags |= DEVFL_UP;
		d->flags &= ~DEVFL_NEWSIZE;
		spin_unlock_irqrestore(&d->lock, flags);
	}
}
static struct block_device *get_emmc_bdev(void)
{
	struct block_device *bdev;
	struct device *emmc_disk;

	emmc_disk = class_find_device(&block_class, NULL, NULL,
					mmcblk0boot0_match);
	if (emmc_disk == 0) {
		pr_err("emmc not found!\n");
		return NULL;
	}

	/* partition 0 means raw disk */
	bdev = bdget_disk(dev_to_disk(emmc_disk), 0);
	if (bdev == NULL) {
		dev_err(emmc_disk, "unable to get disk\n");
		return NULL;
	}

	/* Note: this bdev ref will be freed after first
	 * bdev_get/bdev_put cycle
	 */

	return bdev;
}
示例#6
0
ssize_t diskdump_sysfs_show_disk(struct gendisk *disk, char *buf)
{
	struct block_device *bdev;
	int part, tmp, len = 0, maxlen = 1024;
	char* p = buf; 
	char name[BDEVNAME_SIZE];

	if (!dump_ops || !dump_ops->find_dump)
		return 0;

	if (!disk->part)
		return 0;

	/* print device */
	down(&dump_ops_mutex);
	for (part = 0; part < disk->minors; part++) {
		bdev = bdget_disk(disk, part);
		if (dump_ops->find_dump(bdev)) {
			tmp = sprintf(p, "%s\n", bdevname(bdev, name));
			len += tmp;
			p += tmp;
		}
		bdput(bdev);
		if(len >= maxlen)
			break;
	}
	up(&dump_ops_mutex);

	return len;
}
示例#7
0
ssize_t diskdump_sysfs_store_disk(struct gendisk *disk, struct device *dev, const char *buf, size_t count)
{
	struct block_device *bdev;
	int part, remove = 0;

	if (!dump_ops || !dump_ops->add_dump || !dump_ops->remove_dump)
		return count;

	/* get partition number */
	if (sscanf (buf, "%d\n", &part) != 1)
		return -EINVAL;

	if (part < 0) {
		part = -part;
		remove = 1;
	}

	if (part >= disk->minors)
		return -EINVAL;

	/* get block device */
	if (!(bdev = bdget_disk(disk, part)))
		return count;

	/* add/remove device */
	down(&dump_ops_mutex);
	if (!remove)
		dump_ops->add_dump(dev, bdev);
	else
		dump_ops->remove_dump(bdev);
	up(&dump_ops_mutex);

	return count;
}
示例#8
0
static ssize_t reset_store(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t len)
{
    int ret;
    unsigned long do_reset;
    struct xzram *xzram;
    struct block_device *bdev;

    xzram = dev_to_xzram(dev);
    bdev = bdget_disk(xzram->disk, 0);

    /* Do not reset an active device! */
    if (bdev->bd_holders)
        return -EBUSY;

    ret = strict_strtoul(buf, 10, &do_reset);
    if (ret)
        return ret;

    if (!do_reset)
        return -EINVAL;

    /* Make sure all pending I/O is finished */
    if (bdev)
        fsync_bdev(bdev);

    if (xzram->init_done)
        xzram_reset_device(xzram);

    return len;
}
示例#9
0
文件: dm.c 项目: waterice/Test-Git
/*
 * Functions to lock and unlock any filesystem running on the
 * device.
 */
static int lock_fs(struct mapped_device *md)
{
	int r = -ENOMEM;

	md->frozen_bdev = bdget_disk(md->disk, 0);
	if (!md->frozen_bdev) {
		DMWARN("bdget failed in lock_fs");
		goto out;
	}

	WARN_ON(md->frozen_sb);

	md->frozen_sb = freeze_bdev(md->frozen_bdev);
	if (IS_ERR(md->frozen_sb)) {
		r = PTR_ERR(md->frozen_sb);
		goto out_bdput;
	}

	/* don't bdput right now, we don't want the bdev
	 * to go away while it is locked.  We'll bdput
	 * in unlock_fs
	 */
	return 0;

out_bdput:
	bdput(md->frozen_bdev);
	md->frozen_sb = NULL;
	md->frozen_bdev = NULL;
out:
	return r;
}
示例#10
0
文件: dm.c 项目: wxlong/Test
static void __set_size(struct gendisk *disk, sector_t size)
{
	struct block_device *bdev;

	set_capacity(disk, size);
	bdev = bdget_disk(disk, 0);
	if (bdev) {
		down(&bdev->bd_inode->i_sem);
		i_size_write(bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
		up(&bdev->bd_inode->i_sem);
		bdput(bdev);
	}
}
示例#11
0
/*
 * performs formatting of _device_ according to _fdata_
 * Note: The discipline's format_function is assumed to deliver formatting
 * commands to format a single unit of the device. In terms of the ECKD
 * devices this means CCWs are generated to format a single track.
 */
static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
{
    struct dasd_ccw_req *cqr;
    struct dasd_device *base;
    int rc;

    base = block->base;
    if (base->discipline->format_device == NULL)
        return -EPERM;

    if (base->state != DASD_STATE_BASIC) {
        DEV_MESSAGE(KERN_WARNING, base, "%s",
                    "dasd_format: device is not disabled! ");
        return -EBUSY;
    }

    DBF_DEV_EVENT(DBF_NOTICE, base,
                  "formatting units %d to %d (%d B blocks) flags %d",
                  fdata->start_unit,
                  fdata->stop_unit, fdata->blksize, fdata->intensity);

    /* Since dasdfmt keeps the device open after it was disabled,
     * there still exists an inode for this device.
     * We must update i_blkbits, otherwise we might get errors when
     * enabling the device later.
     */
    if (fdata->start_unit == 0) {
        struct block_device *bdev = bdget_disk(block->gdp, 0);
        bdev->bd_inode->i_blkbits = blksize_bits(fdata->blksize);
        bdput(bdev);
    }

    while (fdata->start_unit <= fdata->stop_unit) {
        cqr = base->discipline->format_device(base, fdata);
        if (IS_ERR(cqr))
            return PTR_ERR(cqr);
        rc = dasd_sleep_on_interruptible(cqr);
        dasd_sfree_request(cqr, cqr->memdev);
        if (rc) {
            if (rc != -ERESTARTSYS)
                DEV_MESSAGE(KERN_ERR, base,
                            " Formatting of unit %d failed "
                            "with rc = %d",
                            fdata->start_unit, rc);
            return rc;
        }
        fdata->start_unit++;
    }
    return 0;
}
示例#12
0
文件: zvol.c 项目: alek-p/zfs
static void
zvol_size_changed(zvol_state_t *zv, uint64_t volsize)
{
	struct block_device *bdev;

	bdev = bdget_disk(zv->zv_disk, 0);
	if (bdev == NULL)
		return;
	set_capacity(zv->zv_disk, volsize >> 9);
	zv->zv_volsize = volsize;
	check_disk_size_change(zv->zv_disk, bdev);

	bdput(bdev);
}
示例#13
0
/*
 * Ensure the zap is flushed then inform the VFS of the capacity change.
 */
static int
zvol_update_volsize(zvol_state_t *zv, uint64_t volsize, objset_t *os)
{
	struct block_device *bdev;
	dmu_tx_t *tx;
	int error;

	ASSERT(MUTEX_HELD(&zvol_state_lock));

	tx = dmu_tx_create(os);
	dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
	error = dmu_tx_assign(tx, TXG_WAIT);
	if (error) {
		dmu_tx_abort(tx);
		return (error);
	}

	error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1,
	    &volsize, tx);
	dmu_tx_commit(tx);

	if (error)
		return (error);

	error = dmu_free_long_range(os,
	    ZVOL_OBJ, volsize, DMU_OBJECT_END);
	if (error)
		return (error);

	bdev = bdget_disk(zv->zv_disk, 0);
	if (!bdev)
		return (EIO);
/*
 * 2.6.28 API change
 * Added check_disk_size_change() helper function.
 */
#ifdef HAVE_CHECK_DISK_SIZE_CHANGE
	set_capacity(zv->zv_disk, volsize >> 9);
	zv->zv_volsize = volsize;
	check_disk_size_change(zv->zv_disk, bdev);
#else
	zv->zv_volsize = volsize;
	zv->zv_changed = 1;
	(void) check_disk_change(bdev);
#endif /* HAVE_CHECK_DISK_SIZE_CHANGE */

	bdput(bdev);

	return (0);
}
示例#14
0
/*
 * performs formatting of _device_ according to _fdata_
 * Note: The discipline's format_function is assumed to deliver formatting
 * commands to format a single unit of the device. In terms of the ECKD
 * devices this means CCWs are generated to format a single track.
 */
static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
{
	struct dasd_ccw_req *cqr;
	struct dasd_device *base;
	int rc;

	base = block->base;
	if (base->discipline->format_device == NULL)
		return -EPERM;

	if (base->state != DASD_STATE_BASIC) {
		pr_warning("%s: The DASD cannot be formatted while it is "
			   "enabled\n",  dev_name(&base->cdev->dev));
		return -EBUSY;
	}

	DBF_DEV_EVENT(DBF_NOTICE, base,
		      "formatting units %u to %u (%u B blocks) flags %u",
		      fdata->start_unit,
		      fdata->stop_unit, fdata->blksize, fdata->intensity);

	/* Since dasdfmt keeps the device open after it was disabled,
	 * there still exists an inode for this device.
	 * We must update i_blkbits, otherwise we might get errors when
	 * enabling the device later.
	 */
	if (fdata->start_unit == 0) {
		struct block_device *bdev = bdget_disk(block->gdp, 0);
		bdev->bd_inode->i_blkbits = blksize_bits(fdata->blksize);
		bdput(bdev);
	}

	while (fdata->start_unit <= fdata->stop_unit) {
		cqr = base->discipline->format_device(base, fdata);
		if (IS_ERR(cqr))
			return PTR_ERR(cqr);
		rc = dasd_sleep_on_interruptible(cqr);
		dasd_sfree_request(cqr, cqr->memdev);
		if (rc) {
			if (rc != -ERESTARTSYS)
				pr_err("%s: Formatting unit %d failed with "
				       "rc=%d\n", dev_name(&base->cdev->dev),
				       fdata->start_unit, rc);
			return rc;
		}
		fdata->start_unit++;
	}
	return 0;
}
示例#15
0
static ssize_t reset_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t len)
{
	int ret;
	unsigned long do_reset;
	struct zram *zram;
	struct block_device *bdev;

	zram = dev_to_zram(dev);
	bdev = bdget_disk(zram->disk, 0);

	if (!bdev)
		return -ENOMEM;

	/* Do not reset an active device! */
	if (bdev->bd_holders) {
		ret = -EBUSY;
		goto out;
	}

	ret = strict_strtoul(buf, 10, &do_reset);
	if (ret)
		goto out;

	if (!do_reset) {
		ret = -EINVAL;
		goto out;
	}

	/* Make sure all pending I/O is finished */
	fsync_bdev(bdev);
	bdput(bdev);

	down_write(&zram->init_lock);
	if (zram->init_done)
		__zram_reset_device(zram);
	up_write(&zram->init_lock);

	return len;

out:
	bdput(bdev);
	return ret;
}
示例#16
0
文件: dm.c 项目: wxlong/Test
static int __unlock_fs(struct mapped_device *md)
{
	struct block_device *bdev;

	if (!test_and_clear_bit(DMF_FS_LOCKED, &md->flags))
		return 0;

	bdev = bdget_disk(md->disk, 0);
	if (!bdev) {
		DMWARN("bdget failed in __unlock_fs");
		return -ENOMEM;
	}

	thaw_bdev(bdev, md->frozen_sb);
	md->frozen_sb = NULL;
	bdput(bdev);
	bdput(bdev);
	return 0;
}
示例#17
0
/*
 * Ensure the zap is flushed then inform the VFS of the capacity change.
 */
static int
zvol_update_volsize(zvol_state_t *zv, uint64_t volsize)
{
	struct block_device *bdev;
	dmu_tx_t *tx;
	int error;

	ASSERT(MUTEX_HELD(&zvol_state_lock));

	tx = dmu_tx_create(zv->zv_objset);
	dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
	error = dmu_tx_assign(tx, TXG_WAIT);
	if (error) {
		dmu_tx_abort(tx);
		return (error);
	}

	error = zap_update(zv->zv_objset, ZVOL_ZAP_OBJ, "size", 8, 1,
	    &volsize, tx);
	dmu_tx_commit(tx);

	if (error)
		return (error);

	error = dmu_free_long_range(zv->zv_objset,
	    ZVOL_OBJ, volsize, DMU_OBJECT_END);
	if (error)
		return (error);

	zv->zv_volsize = volsize;
	zv->zv_changed = 1;

	bdev = bdget_disk(zv->zv_disk, 0);
	if (!bdev)
		return EIO;

	error = check_disk_change(bdev);
	ASSERT3U(error, !=, 0);
	bdput(bdev);

	return (0);
}
示例#18
0
文件: dm.c 项目: wxlong/Test
/*
 * Functions to lock and unlock any filesystem running on the
 * device.
 */
static int __lock_fs(struct mapped_device *md)
{
	struct block_device *bdev;

	if (test_and_set_bit(DMF_FS_LOCKED, &md->flags))
		return 0;

	bdev = bdget_disk(md->disk, 0);
	if (!bdev) {
		DMWARN("bdget failed in __lock_fs");
		return -ENOMEM;
	}

	WARN_ON(md->frozen_sb);
	md->frozen_sb = freeze_bdev(bdev);
	/* don't bdput right now, we don't want the bdev
	 * to go away while it is locked.  We'll bdput
	 * in __unlock_fs
	 */
	return 0;
}
示例#19
0
文件: zvol.c 项目: Acidburn0zzz/zfs
static void
zvol_size_changed(zvol_state_t *zv, uint64_t volsize)
{
	struct block_device *bdev;

	bdev = bdget_disk(zv->zv_disk, 0);
	if (bdev == NULL)
		return;
/*
 * 2.6.28 API change
 * Added check_disk_size_change() helper function.
 */
#ifdef HAVE_CHECK_DISK_SIZE_CHANGE
	set_capacity(zv->zv_disk, volsize >> 9);
	zv->zv_volsize = volsize;
	check_disk_size_change(zv->zv_disk, bdev);
#else
	zv->zv_volsize = volsize;
	zv->zv_changed = 1;
	(void) check_disk_change(bdev);
#endif /* HAVE_CHECK_DISK_SIZE_CHANGE */

	bdput(bdev);
}
示例#20
0
文件: dm.c 项目: 3sOx/asuswrt-merlin
/*
 * We need to be able to change a mapping table under a mounted
 * filesystem.  For example we might want to move some data in
 * the background.  Before the table can be swapped with
 * dm_bind_table, dm_suspend must be called to flush any in
 * flight bios and ensure that any further io gets deferred.
 */
int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
{
	struct dm_table *map = NULL;
	unsigned long flags;
	DECLARE_WAITQUEUE(wait, current);
	struct bio *def;
	int r = -EINVAL;
	int do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ? 1 : 0;
	int noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ? 1 : 0;

	down(&md->suspend_lock);

	if (dm_suspended(md))
		goto out_unlock;

	map = dm_get_table(md);

	/*
	 * DMF_NOFLUSH_SUSPENDING must be set before presuspend.
	 * This flag is cleared before dm_suspend returns.
	 */
	if (noflush)
		set_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);

	/* This does not get reverted if there's an error later. */
	dm_table_presuspend_targets(map);

	/* bdget() can stall if the pending I/Os are not flushed */
	if (!noflush) {
		md->suspended_bdev = bdget_disk(md->disk, 0);
		if (!md->suspended_bdev) {
			DMWARN("bdget failed in dm_suspend");
			r = -ENOMEM;
			goto flush_and_out;
		}
	}

	/*
	 * Flush I/O to the device.
	 * noflush supersedes do_lockfs, because lock_fs() needs to flush I/Os.
	 */
	if (do_lockfs && !noflush) {
		r = lock_fs(md);
		if (r)
			goto out;
	}

	/*
	 * First we set the BLOCK_IO flag so no more ios will be mapped.
	 */
	down_write(&md->io_lock);
	set_bit(DMF_BLOCK_IO, &md->flags);

	add_wait_queue(&md->wait, &wait);
	up_write(&md->io_lock);

	/* unplug */
	if (map)
		dm_table_unplug_all(map);

	/*
	 * Then we wait for the already mapped ios to
	 * complete.
	 */
	while (1) {
		set_current_state(TASK_INTERRUPTIBLE);

		if (!atomic_read(&md->pending) || signal_pending(current))
			break;

		io_schedule();
	}
	set_current_state(TASK_RUNNING);

	down_write(&md->io_lock);
	remove_wait_queue(&md->wait, &wait);

	if (noflush) {
		spin_lock_irqsave(&md->pushback_lock, flags);
		clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
		bio_list_merge_head(&md->deferred, &md->pushback);
		bio_list_init(&md->pushback);
		spin_unlock_irqrestore(&md->pushback_lock, flags);
	}

	/* were we interrupted ? */
	r = -EINTR;
	if (atomic_read(&md->pending)) {
		clear_bit(DMF_BLOCK_IO, &md->flags);
		def = bio_list_get(&md->deferred);
		__flush_deferred_io(md, def);
		up_write(&md->io_lock);
		unlock_fs(md);
		goto out; /* pushback list is already flushed, so skip flush */
	}
	up_write(&md->io_lock);

	dm_table_postsuspend_targets(map);

	set_bit(DMF_SUSPENDED, &md->flags);

	r = 0;

flush_and_out:
	if (r && noflush) {
		/*
		 * Because there may be already I/Os in the pushback list,
		 * flush them before return.
		 */
		down_write(&md->io_lock);

		spin_lock_irqsave(&md->pushback_lock, flags);
		clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
		bio_list_merge_head(&md->deferred, &md->pushback);
		bio_list_init(&md->pushback);
		spin_unlock_irqrestore(&md->pushback_lock, flags);

		def = bio_list_get(&md->deferred);
		__flush_deferred_io(md, def);
		up_write(&md->io_lock);
	}

out:
	if (r && md->suspended_bdev) {
		bdput(md->suspended_bdev);
		md->suspended_bdev = NULL;
	}

	dm_table_put(map);

out_unlock:
	up(&md->suspend_lock);
	return r;
}
示例#21
0
文件: dm.c 项目: ena30/snake-os
/*
 * We need to be able to change a mapping table under a mounted
 * filesystem.  For example we might want to move some data in
 * the background.  Before the table can be swapped with
 * dm_bind_table, dm_suspend must be called to flush any in
 * flight bios and ensure that any further io gets deferred.
 */
int dm_suspend(struct mapped_device *md, int do_lockfs)
{
	struct dm_table *map = NULL;
	DECLARE_WAITQUEUE(wait, current);
	struct bio *def;
	int r = -EINVAL;

	down(&md->suspend_lock);

	if (dm_suspended(md))
		goto out;

	map = dm_get_table(md);

	/* This does not get reverted if there's an error later. */
	dm_table_presuspend_targets(map);

	md->suspended_bdev = bdget_disk(md->disk, 0);
	if (!md->suspended_bdev) {
		DMWARN("bdget failed in dm_suspend");
		r = -ENOMEM;
		goto out;
	}

	/* Flush I/O to the device. */
	if (do_lockfs) {
		r = lock_fs(md);
		if (r)
			goto out;
	}

	/*
	 * First we set the BLOCK_IO flag so no more ios will be mapped.
	 */
	down_write(&md->io_lock);
	set_bit(DMF_BLOCK_IO, &md->flags);

	add_wait_queue(&md->wait, &wait);
	up_write(&md->io_lock);

	/* unplug */
	if (map)
		dm_table_unplug_all(map);

	/*
	 * Then we wait for the already mapped ios to
	 * complete.
	 */
	while (1) {
		set_current_state(TASK_INTERRUPTIBLE);

		if (!atomic_read(&md->pending) || signal_pending(current))
			break;

		io_schedule();
	}
	set_current_state(TASK_RUNNING);

	down_write(&md->io_lock);
	remove_wait_queue(&md->wait, &wait);

	/* were we interrupted ? */
	r = -EINTR;
	if (atomic_read(&md->pending)) {
		clear_bit(DMF_BLOCK_IO, &md->flags);
		def = bio_list_get(&md->deferred);
		__flush_deferred_io(md, def);
		up_write(&md->io_lock);
		unlock_fs(md);
		goto out;
	}
	up_write(&md->io_lock);

	dm_table_postsuspend_targets(map);

	set_bit(DMF_SUSPENDED, &md->flags);

	r = 0;

out:
	if (r && md->suspended_bdev) {
		bdput(md->suspended_bdev);
		md->suspended_bdev = NULL;
	}

	dm_table_put(map);
	up(&md->suspend_lock);
	return r;
}