linux 刷新block设备,Linux I/O Block--块设备的表示

blkdev_get()函数负责从gendisk中获取信息,并建立相关数据结构之间的联系

int blkdev_get(struct block_device *bdev, fmode_t mode)

{

return __blkdev_get(bdev, mode, 0);

}

注意_blkdev_get()传递的最后一个参数为0,也就是说默认打开的是主设备

获取到gendisk之后会分四种情况进行处理,也就是针对设备是不是第一次打开以及打开的设备是主设备还是分区来进行不同的处理,具体见代码注释

static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)

{

struct gendisk *disk;

int ret;

int partno;

int perm = 0;

if (mode & FMODE_READ)

perm |= MAY_READ;

if (mode & FMODE_WRITE)

perm |= MAY_WRITE;

/*

* hooks: /n/, see "layering violations".

*/

if (!for_part) {

ret = devcgroup_inode_permission(bdev->bd_inode, perm);

if (ret != 0) {

bdput(bdev);

return ret;

}

}

lock_kernel();

restart:

ret = -ENXIO;

//获取该设备的gendisk实例,如果bd_dev对应的是一个分区设备的话,partno将会被修改

disk = get_gendisk(bdev->bd_dev, &partno);

if (!disk)

goto out_unlock_kernel;

mutex_lock_nested(&bdev->bd_mutex, for_part);

if (!bdev->bd_openers) {//如果是第一次打开设备

bdev->bd_disk = disk;//建立block device和gendisk之间的联系

bdev->bd_contains = bdev;

if (!partno) {//partno为0,也就是说打开的是主设备而不是分区

struct backing_dev_info *bdi;

ret = -ENXIO;

bdev->bd_part = disk_get_part(disk, partno);//获取gendisk中的分区数组

if (!bdev->bd_part)

goto out_clear;

if (disk->fops->open) {//gendisk中定义了open方式

ret = disk->fops->open(bdev, mode);//调用open针对具体的设备进行打开操作

if (ret == -ERESTARTSYS) {

/* Lost a race with 'disk' being

* deleted, try again.

* See md.c

*/

disk_put_part(bdev->bd_part);

bdev->bd_part = NULL;

module_put(disk->fops->owner);

put_disk(disk);

bdev->bd_disk = NULL;

mutex_unlock(&bdev->bd_mutex);

goto restart;

}

if (ret)

goto out_clear;

}

if (!bdev->bd_openers) {

bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);//从gendisk中提取容量信息设置到block device

bdi = blk_get_backing_dev_info(bdev);

if (bdi == NULL)

bdi = &default_backing_dev_info;

bdev->bd_inode->i_data.backing_dev_info = bdi;

}

//块设备上的分区改变导致分区在内核中的信息无效,则要重新扫描分区

if (bdev->bd_invalidated)

rescan_partitions(disk, bdev);

} else {//如果打开的是分区

struct block_device *whole;

whole = bdget_disk(disk, 0);//获取主设备的block device实例

ret = -ENOMEM;

if (!whole)

goto out_clear;

BUG_ON(for_part);

ret = __blkdev_get(whole, mode, 1);

if (ret)

goto out_clear;

bdev->bd_contains = whole;//设置分区的block device实例的bd_contains域到主设备

bdev->bd_inode->i_data.backing_dev_info =

whole->bd_inode->i_data.backing_dev_info;

bdev->bd_part = disk_get_part(disk, partno);

if (!(disk->flags & GENHD_FL_UP) ||

!bdev->bd_part || !bdev->bd_part->nr_sects) {

ret = -ENXIO;

goto out_clear;

}

bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);

}

}  else {//如果不是第一次打开

module_put(disk->fops->owner);

put_disk(disk);

disk = NULL;

if (bdev->bd_contains == bdev) {//打开的是主设备

if (bdev->bd_disk->fops->open) {

ret = bdev->bd_disk->fops->open(bdev, mode);//调用定义的open

if (ret)

goto out_unlock_bdev;

}

if (bdev->bd_invalidated)

rescan_partitions(bdev->bd_disk, bdev);

}

}

bdev->bd_openers++;//计数值加1

if (for_part)//如果是分区则分区计数值也加1

bdev->bd_part_count++;

mutex_unlock(&bdev->bd_mutex);

unlock_kernel();

return 0;

out_clear:

disk_put_part(bdev->bd_part);

bdev->bd_disk = NULL;

bdev->bd_part = NULL;

bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;

if (bdev != bdev->bd_contains)

__blkdev_put(bdev->bd_contains, mode, 1);

bdev->bd_contains = NULL;

out_unlock_bdev:

mutex_unlock(&bdev->bd_mutex);

out_unlock_kernel:

unlock_kernel();

if (disk)

module_put(disk->fops->owner);

put_disk(disk);

bdput(bdev);

return ret;

}0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值