panda.jpg 


안녕하세요 판다 이우영입니다.


오늘도 복습부터!!

복습!!



gendisk 등록 방법입니다.



typedef struct

{

void *priv;

struct request_queue  *queue;

spinlock_t lock;

struct gendisk *gd;

} XXX_device;


static XXX_device device[MAX_DEVICE];


-----------------------------------------------------------------------------------------------------------

int XXX_init( void) {

....

for(lp = 0; lp < MAX_DEVICE; lp++)

{

device[lp].data  = vdisk[lp];

device[lp].gd = alloc_disk(1);

....

device[lp].gd->major = XXX;

device[lp].gd->first_minor = lp;

device[lp].gd->fops = &fops;

....

add_disk(device[lp].gd);

}

....

}



중요한 gendisk 필드들입니다.


 int major 

 디바이스 드라이버의 주 번호 

 int first_minor;

 디바이스 드라이버 부 번호

 struct block_device_operations *fops;  

 블록 오퍼레이션 등록 

 struct request_queue *queue;

 블록 디바이스마다 관리하는 요구 큐를 등록 

 char disk_name[DISK_NAME_LEN];

 블록 디바이스의 기본이름을 입력

 int flags;

 블록 디바이스의 특성 (제거가 가능하거나 CD-ROM)  

 void *private_data;

 request() 함수에서 디바이스 정보를 얻기위해 사용


복습은 간단하게 넘어가고 오늘내용 알아보겠습니다.


gendisk 등록 및 삭제



저번시간에 설명했던 gendisk 를 등록하는 방법과 제거하는 방법을 조금더 알아 보겠습니다.


gendisk는 alloc_disk()함수를 이용해서 생성한다고 했습니다.

함수원형은 다음과 같습니다.


struct gendisk *alloc_disk(int minors);


인자값은 파티션의 수가 들어갑니다 만약 파티션의 수가 3개라면 블럭디바이스를 포함하여 4개를 넣어주셔야 합니다.

실제 소스 코드 입니다.


/block/genhd.c

1127struct gendisk *alloc_disk(int minors)
1128{
1129        return alloc_disk_node(minors, -1);
1130}
1131EXPORT_SYMBOL(alloc_disk);
1132
1133struct gendisk *alloc_disk_node(int minors, int node_id)
1134{
1135        struct gendisk *disk;
1136
1137        disk = kmalloc_node(sizeof(struct gendisk),
1138                                GFP_KERNEL | __GFP_ZERO, node_id);
1139        if (disk) {
1140                if (!init_part_stats(&disk->part0)) {
1141                        kfree(disk);
1142                        return NULL;
1143                }
1144                disk->node_id = node_id;
1145                if (disk_expand_part_tbl(disk, 0)) {
1146                        free_part_stats(&disk->part0);
1147                        kfree(disk);
1148                        return NULL;
1149                }
1150                disk->part_tbl->part[0] = &disk->part0;
1151
1152                disk->minors = minors;
1153                rand_initialize_disk(disk);
1154                disk_to_dev(disk)->class = &block_class;
1155                disk_to_dev(disk)->type = &disk_type;
1156                device_initialize(disk_to_dev(disk));
1157                INIT_WORK(&disk->async_notify,
1158                        media_change_notify_thread);
1159        }
1160        return disk;
1161}
1162EXPORT_SYMBOL(alloc_disk_node);


그리고 gendisk를 생성했다면 커널에 등록을 해주어야 겠죠?

void add_disk(struct gendisk *disk);


할당받은 gendisk를 넘겨주면 커널에 등록을 합니다.

/block/genhd.c
 503/**
 504 * add_disk - add partitioning information to kernel list
 505 * @disk: per-device partitioning information
 506 *
 507 * This function registers the partitioning information in @disk
 508 * with the kernel.
 509 *
 510 * FIXME: error handling
 511 */
 512void add_disk(struct gendisk *disk)
 513{
 514        struct backing_dev_info *bdi;
 515        dev_t devt;
 516        int retval;
 517
 518        /* minors == 0 indicates to use ext devt from part0 and should
 519         * be accompanied with EXT_DEVT flag.  Make sure all
 520         * parameters make sense.
 521         */
 522        WARN_ON(disk->minors && !(disk->major || disk->first_minor));
 523        WARN_ON(!disk->minors && !(disk->flags & GENHD_FL_EXT_DEVT));
 524
 525        disk->flags |= GENHD_FL_UP;
 526
 527        retval = blk_alloc_devt(&disk->part0, &devt);
 528        if (retval) {
 529                WARN_ON(1);
 530                return;
 531        }
 532        disk_to_dev(disk)->devt = devt;
 533
 534        /* ->major and ->first_minor aren't supposed to be
 535         * dereferenced from here on, but set them just in case.
 536         */
 537        disk->major = MAJOR(devt);
 538        disk->first_minor = MINOR(devt);
 539
 540        blk_register_region(disk_devt(disk), disk->minors, NULL,
 541                            exact_match, exact_lock, disk);
 542        register_disk(disk);
 543        blk_register_queue(disk);
 544
 545        bdi = &disk->queue->backing_dev_info;
 546        bdi_register_dev(bdi, disk_devt(disk));
 547        retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
 548                                   "bdi");
 549        WARN_ON(retval);
 550}

블록 디바이스 드라이버를 제거할때는 이 gendisk를 해제해야겠죠?
등록한 gendisk를 먼저 커널에서 제거합니다.

/fs/partitions/check.c
 604void del_gendisk(struct gendisk *disk)
 605{
 606        struct disk_part_iter piter;
 607        struct hd_struct *part;
 608
 609        /* invalidate stuff */
 610        disk_part_iter_init(&piter, disk,
 611                             DISK_PITER_INCL_EMPTY | DISK_PITER_REVERSE);
 612        while ((part = disk_part_iter_next(&piter))) {
 613                invalidate_partition(disk, part->partno);
 614                delete_partition(disk, part->partno);
 615        }
 616        disk_part_iter_exit(&piter);
 617
 618        invalidate_partition(disk, 0);
 619        blk_free_devt(disk_to_dev(disk)->devt);
 620        set_capacity(disk, 0);
 621        disk->flags &= ~GENHD_FL_UP;
 622        unlink_gendisk(disk);
 623        part_stat_set_all(&disk->part0, 0);
 624        disk->part0.stamp = 0;
 625
 626        kobject_put(disk->part0.holder_dir);
 627        kobject_put(disk->slave_dir);
 628        disk->driverfs_dev = NULL;
 629#ifndef CONFIG_SYSFS_DEPRECATED
 630        sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
 631#endif
 632        device_del(disk_to_dev(disk));
 633}

마지막으로 gendisk의 할당을 해제하면 됩니다.
해제하는 함수는 다음과 같습니다.

void put_disk(struct gendisk *disk);


여기에는 할당받은 gendisk를 넘겨주면 끝입니다.


/block/genhd.c

1185void put_disk(struct gendisk *disk)
1186{
1187        if (disk)
1188                kobject_put(&disk_to_dev(disk)->kobj);
1189}

/lib/kobject.c

 586void kobject_put(struct kobject *kobj)
 587{
 588        if (kobj) {
 589                if (!kobj->state_initialized)
 590                        WARN(1, KERN_WARNING "kobject: '%s' (%p): is not "
 591                               "initialized, yet kobject_put() is being "
 592                               "called.\n", kobject_name(kobj), kobj);
 593                kref_put(&kobj->kref, kobject_release);
 594        }
 595}



그럼 오늘도 간단하게 끝을내겠습니다.

그럼 다음시간에 만나요~.