/* * 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; }
/** * 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; }
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; }
/* 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; }
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; }
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; }
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; }
/* * 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; }
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); } }
/* * 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; }
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); }
/* * 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); }
/* * 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; }
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; }
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; }
/* * 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); }
/* * 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; }
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); }
/* * 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; }
/* * 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; }