blkdev_open

#define UTS_RELEASE "2.6.35.7-perf"

/kernel/fs/block_dev.c

const struct file_operations def_blk_fops = {

    .open        = blkdev_open,

...

};


static int blkdev_open(struct inode * inode, struct file * filp)

{

......

1487    bdev = bd_acquire(inode);------------------------------------->acquire the block device.

1488    if (bdev == NULL)
1489        return -ENOMEM;
......
1499    filp->f_mapping = bdev->bd_inode->i_mapping;------->address_space mapping

1501    res = blkdev_get(bdev, filp->f_mode);---------------------->the core function for open operation
......

}

blkdev_get------->__blkdev_get()

static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
{
......
 restart:

    ret = -ENXIO;
    disk = get_gendisk(bdev->bd_dev, &partno);------------------->get partitioning information for a given device
    if (!disk)
        goto out_unlock_kernel;

    mutex_lock_nested(&bdev->bd_mutex, for_part);
    if (!bdev->bd_openers) {---------------------------------------------->block device is opened before?
        bdev->bd_disk = disk;
        bdev->bd_contains = bdev;
        if (!partno) {------------------------------------------------------------>is partition?
            struct backing_dev_info *bdi;

            ret = -ENXIO;
            bdev->bd_part = disk_get_part(disk, partno);------------>get the hd_struct
            if (!bdev->bd_part)
                goto out_clear;

            if (disk->fops->open) {------------------------------------------->is open is defined in fops?
                ret = disk->fops->open(bdev, mode);-------------------->do the open operation of fops
                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);
                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)-------------------------------------------->partition information is validate?
                rescan_partitions(disk, bdev);-------------------------------------------->partition information is validate?
        } else {----------------------------------------------------------------------->is partition, then insert the block_device in to data struct.
            struct block_device *whole;
            whole = bdget_disk(disk, 0);
            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;
            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 {----------------------------------------------------------------------------------->opened before
        module_put(disk->fops->owner);
        put_disk(disk);
        disk = NULL;
        if (bdev->bd_contains == bdev) {--------------------------------------------->is main device
            if (bdev->bd_disk->fops->open) {----------------------------------------->do open operation
                ret = bdev->bd_disk->fops->open(bdev, mode);
                if (ret)
                    goto out_unlock_bdev;
            }
            if (bdev->bd_invalidated)------------------------------------------------------>partition information is validate?
                rescan_partitions(bdev->bd_disk, bdev);----------------------------->partition information is validate?
        }
    }
    bdev->bd_openers++;
    if (for_part)
        bdev->bd_part_count++;
    mutex_unlock(&bdev->bd_mutex);
    unlock_kernel();
    return 0;
......
}


你可能感兴趣的:(blkdev_open)