static struct ssd_info *_alloc_ssd(char *path) { struct ssd_info *ssd; struct block_device *const bdev = lookup_bdev(path); dev_t dev_t = 0; if (IS_ERR(bdev)) return NULL; DBG("bdev %p found for path %s.\n", bdev, path); dev_t = bdev->bd_dev; bdput(bdev); ssd = _search_ssd(dev_t); if (NULL != ssd) return NULL; /* EEXIST */ ssd = kzalloc(sizeof(*ssd), GFP_NOWAIT); if (unlikely(NULL == ssd)) return NULL; /* ENOMEM */ strcpy(ssd->path, path); ssd->dev_t = dev_t; atomic_set(&ssd->nr_ref, 0); INIT_LIST_HEAD(&ssd->list); DBG("Created ssd struct ptr=%p.\n", ssd); return ssd; }
/** * 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; }
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; }
/* * look up a superblock on which quota ops will be performed * - use the name of a block device to find the superblock thereon */ static struct super_block *quotactl_block(const char __user *special, int cmd) { #ifdef CONFIG_BLOCK struct block_device *bdev; struct super_block *sb; char *tmp = getname(special); if (IS_ERR(tmp)) return ERR_CAST(tmp); bdev = lookup_bdev(tmp); putname(tmp); if (IS_ERR(bdev)) return ERR_CAST(bdev); if (quotactl_cmd_write(cmd)) sb = get_super_thawed(bdev); else sb = get_super(bdev); bdput(bdev); if (!sb) return ERR_PTR(-ENODEV); return sb; #else return ERR_PTR(-ENODEV); #endif }
/* * 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; }
/* 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 void unlock_fs(struct mapped_device *md) { thaw_bdev(md->frozen_bdev, md->frozen_sb); bdput(md->frozen_bdev); md->frozen_sb = NULL; md->frozen_bdev = NULL; }
/* * Convert a device path to a dev_t. */ static int lookup_device(const char *path, dev_t *dev) { struct block_device *bdev = lookup_bdev(path); if (IS_ERR(bdev)) return PTR_ERR(bdev); *dev = bdev->bd_dev; bdput(bdev); return 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); if (!bdev) return -ENOMEM; /* Do not reset an active device! */ if (bdev->bd_holders) { ret = -EBUSY; goto out; } ret = kstrtou16(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; }
/* * Find the swap type that corresponds to given device (if any). * * @offset - number of the PAGE_SIZE-sized block of the device, starting * from 0, in which the swap header is expected to be located. * * This is needed for the suspend to disk (aka swsusp). */ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) { struct block_device *bdev = NULL; int i; if (device) bdev = bdget(device); spin_lock(&swap_lock); for (i = 0; i < nr_swapfiles; i++) { struct swap_info_struct *sis = swap_info + i; if (!(sis->flags & SWP_WRITEOK)) continue; if (!bdev) { if (bdev_p) *bdev_p = sis->bdev; spin_unlock(&swap_lock); return i; } if (bdev == sis->bdev) { struct swap_extent *se; se = list_entry(sis->extent_list.next, struct swap_extent, list); if (se->start_block == offset) { if (bdev_p) *bdev_p = sis->bdev; spin_unlock(&swap_lock); bdput(bdev); return i; } } } spin_unlock(&swap_lock); if (bdev) bdput(bdev); return -ENODEV; }
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; }
void bufsync(void) { bufptr bp; /* FIXME: this can generate a lot of d_flush calls when you have plenty of buffers */ for (bp = bufpool; bp < bufpool_end; ++bp) { if ((bp->bf_dev != NO_DEVICE) && bp->bf_dirty) bdput(bp); } }
void bdrop(uint16_t dev) { bufptr bp; for (bp = bufpool; bp < bufpool_end; ++bp) { if (bp->bf_dev == dev) { bdput(bp); bp->bf_dev = NO_DEVICE; } } }
static void tbio_exit(void) { if(Device.bdev) { invalidate_bdev(Device.bdev,1); bdput(Device.bdev); } del_gendisk(Device.gd); put_disk(Device.gd); unregister_blkdev(TBIO_MAJOR , "tbio"); vfree(Device.data); }
void ssd_unregister(char *path) { struct block_device *const bdev = lookup_bdev(path); dev_t dev_t = 0; DBG("bdev %p found for path %s.\n", bdev, path); if (IS_ERR(bdev)) return; dev_t = bdev->bd_dev; bdput(bdev); mutex_lock(&gctx.ctl_mtx); _ssd_remove(_search_ssd(dev_t)); mutex_unlock(&gctx.ctl_mtx); }
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); } }
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); }
/* * 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; }
/* * 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 struct block_device *stackbd_bdev_open(char dev_path[]) { /* Open underlying device */ struct block_device *bdev_raw = lookup_bdev(dev_path); printk("Opened %s\n", dev_path); if (IS_ERR(bdev_raw)) { printk("stackbd: error opening raw device <%lu>\n", PTR_ERR(bdev_raw)); return NULL; } if (!bdget(bdev_raw->bd_dev)) { printk("stackbd: error bdget()\n"); return NULL; } /* FIXME:VER */ /* if (blkdev_get(bdev_raw, STACKBD_BDEV_MODE, &stackbd))*/ if (blkdev_get(bdev_raw, STACKBD_BDEV_MODE)) { printk("stackbd: error blkdev_get()\n"); bdput(bdev_raw); return NULL; } if (bd_claim(bdev_raw, &stackbd)) { printk("stackbd: error bd_claim()\n"); bdput(bdev_raw); return NULL; } return bdev_raw; }
static void free_dev(struct mapped_device *md) { unsigned int minor = md->disk->first_minor; if (md->suspended_bdev) { thaw_bdev(md->suspended_bdev, NULL); bdput(md->suspended_bdev); } mempool_destroy(md->tio_pool); mempool_destroy(md->io_pool); del_gendisk(md->disk); free_minor(minor); put_disk(md->disk); blk_put_queue(md->queue); kfree(md); }
static void __exit stackbd_exit(void) { printk("stackbd: exit\n"); if (stackbd.is_active) { kthread_stop(stackbd.thread); blkdev_put(stackbd.bdev_raw, STACKBD_BDEV_MODE); bdput(stackbd. bdev_raw); } del_gendisk(stackbd.gd); put_disk(stackbd.gd); unregister_blkdev(major_num, STACKBD_NAME); blk_cleanup_queue(stackbd.queue); }
int dm_resume(struct mapped_device *md) { int r = -EINVAL; struct bio *def; struct dm_table *map = NULL; down(&md->suspend_lock); if (!dm_suspended(md)) goto out; map = dm_get_table(md); if (!map || !dm_table_get_size(map)) goto out; r = dm_table_resume_targets(map); if (r) goto out; down_write(&md->io_lock); 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); if (md->suspended_bdev) { bdput(md->suspended_bdev); md->suspended_bdev = NULL; } clear_bit(DMF_SUSPENDED, &md->flags); dm_table_unplug_all(map); kobject_uevent(&md->disk->kobj, KOBJ_CHANGE); r = 0; out: dm_table_put(map); up(&md->suspend_lock); return r; }
/* * Given a path, return TRUE if path is a ZVOL. */ boolean_t zvol_is_zvol(const char *device) { struct block_device *bdev; unsigned int major; bdev = vdev_lookup_bdev(device); if (IS_ERR(bdev)) return (B_FALSE); major = MAJOR(bdev->bd_dev); bdput(bdev); if (major == zvol_major) return (B_TRUE); return (B_FALSE); }
/* * 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); }
static void free_dev(struct mapped_device *md) { int minor = md->disk->first_minor; if (md->suspended_bdev) { thaw_bdev(md->suspended_bdev, NULL); bdput(md->suspended_bdev); } mempool_destroy(md->tio_pool); mempool_destroy(md->io_pool); del_gendisk(md->disk); free_minor(minor); spin_lock(&_minor_lock); md->disk->private_data = NULL; spin_unlock(&_minor_lock); put_disk(md->disk); blk_cleanup_queue(md->queue); module_put(THIS_MODULE); kfree(md); }
int _lkl_disk_del_disk(__kernel_dev_t devt) { struct block_device *bdev; struct gendisk *gd; int ret = 0, partno; bdev = bdget(devt); if (!bdev) return -EINVAL; gd = get_gendisk(new_decode_dev(devt), &partno); if (!gd || gd->major != major) { ret = -EINVAL; goto out; } del_gendisk(gd); out: bdput(bdev); return ret; }
int set_blocksize(kdev_t dev, int size) { int oldsize; struct block_device *bdev; /* Size must be a power of two, and between 512 and PAGE_SIZE */ if (size > PAGE_SIZE || size < 512 || (size & (size-1))) return -EINVAL; /* Size cannot be smaller than the size supported by the device */ if (size < get_hardsect_size(dev)) return -EINVAL; /* No blocksize array? Implies hardcoded BLOCK_SIZE */ if (!blksize_size[MAJOR(dev)]) { if (size == BLOCK_SIZE) return 0; return -EINVAL; } oldsize = blksize_size[MAJOR(dev)][MINOR(dev)]; if (oldsize == size) return 0; if (!oldsize && size == BLOCK_SIZE) { blksize_size[MAJOR(dev)][MINOR(dev)] = size; return 0; } /* Ok, we're actually changing the blocksize.. */ bdev = bdget(dev); sync_buffers(dev, 2); blksize_size[MAJOR(dev)][MINOR(dev)] = size; bdev->bd_inode->i_blkbits = blksize_bits(size); kill_bdev(bdev); bdput(bdev); return 0; }
static int stackbd_start(char dev_path[]) { unsigned max_sectors; if (!(stackbd.bdev_raw = stackbd_bdev_open(dev_path))) return -EFAULT; /* Set up our internal device */ stackbd.capacity = get_capacity(stackbd.bdev_raw->bd_disk); printk("stackbd: Device real capacity: %llu\n", (unsigned long long) stackbd.capacity); set_capacity(stackbd.gd, stackbd.capacity); max_sectors = queue_max_hw_sectors(bdev_get_queue(stackbd.bdev_raw)); blk_queue_max_hw_sectors(stackbd.queue, max_sectors); printk("stackbd: Max sectors: %u\n", max_sectors); stackbd.thread = kthread_create(stackbd_threadfn, NULL, stackbd.gd->disk_name); if (IS_ERR(stackbd.thread)) { printk("stackbd: error kthread_create <%lu>\n", PTR_ERR(stackbd.thread)); goto error_after_bdev; } printk("stackbd: done initializing successfully\n"); stackbd.is_active = 1; wake_up_process(stackbd.thread); return 0; error_after_bdev: blkdev_put(stackbd.bdev_raw, STACKBD_BDEV_MODE); bdput(stackbd.bdev_raw); return -EFAULT; }