免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3945 | 回复: 2

[内核入门] device_del后还要put_device吗? [复制链接]

论坛徽章:
0
发表于 2012-05-10 17:52 |显示全部楼层
lk 3.0.8
看到有些driver在调用device_del后有加put_device,有些driver又没有加,
原本觉得device_add里应该是get_device了一次,所以device_del后需要put_device
实际上看device_add在进入函数时有get_device,正常退出走done时又put_device了,error退出反而没有
再看某些driver里device_add失败后有调用put_device,有些driver又没有。

论坛徽章:
0
发表于 2012-05-10 18:05 |显示全部楼层
哪些调了哪些没调,举些例子吧。可能有些是动态分配,有些是静态分配。

论坛徽章:
0
发表于 2012-05-11 13:42 |显示全部楼层
回复 2# tempname8
genhd.c
  1. void register_disk(struct gendisk *disk)
  2. {
  3.         struct device *ddev = disk_to_dev(disk);
  4.         struct block_device *bdev;
  5.         struct disk_part_iter piter;
  6.         struct hd_struct *part;
  7.         int err;

  8.         ddev->parent = disk->driverfs_dev;

  9.         dev_set_name(ddev, disk->disk_name);

  10.         /* delay uevents, until we scanned partition table */
  11.         dev_set_uevent_suppress(ddev, 1);

  12.         if (device_add(ddev))
  13.                 return;
  14.         if (!sysfs_deprecated) {
  15.                 err = sysfs_create_link(block_depr, &ddev->kobj,
  16.                                         kobject_name(&ddev->kobj));
  17.                 if (err) {
  18.                         device_del(ddev);
  19.                         return;
  20.                 }
  21.         }
  22.     disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
  23.     disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);

  24.     /* No minors to use for partitions */
  25.     if (!disk_partitionable(disk))
  26.         goto exit;

  27.     /* No such device (e.g., media were just removed) */
  28.     if (!get_capacity(disk))
  29.         goto exit;

  30.     bdev = bdget_disk(disk, 0);
  31.     if (!bdev)
  32.         goto exit;

  33.     bdev->bd_invalidated = 1;
  34.     err = blkdev_get(bdev, FMODE_READ, NULL);
  35.     if (err < 0)
  36.         goto exit;
  37.     blkdev_put(bdev, FMODE_READ);

  38. exit:
  39.     /* announce disk after possible partitions are created */
  40.     dev_set_uevent_suppress(ddev, 0);
  41.     kobject_uevent(&ddev->kobj, KOBJ_ADD);

  42.     /* announce possible partitions */
  43.     disk_part_iter_init(&piter, disk, 0);
  44.     while ((part = disk_part_iter_next(&piter)))
  45.         kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD);
  46.     disk_part_iter_exit(&piter);
  47. }
复制代码
这里的device_add失败直接返回,device_del后没有put_device

check.c
  1. struct hd_struct *add_partition(struct gendisk *disk, int partno,
  2.                                 sector_t start, sector_t len, int flags,
  3.                                 struct partition_meta_info *info)
  4. {
  5.         struct hd_struct *p;
  6.         dev_t devt = MKDEV(0, 0);
  7.         struct device *ddev = disk_to_dev(disk);
  8.         struct device *pdev;
  9.         struct disk_part_tbl *ptbl;
  10.         const char *dname;
  11.         int err;

  12.         err = disk_expand_part_tbl(disk, partno);
  13.         if (err)
  14.                 return ERR_PTR(err);
  15.         ptbl = disk->part_tbl;

  16.         if (ptbl->part[partno])
  17.                 return ERR_PTR(-EBUSY);

  18.         p = kzalloc(sizeof(*p), GFP_KERNEL);
  19.         if (!p)
  20.                 return ERR_PTR(-EBUSY);

  21.         if (!init_part_stats(p)) {
  22.                 err = -ENOMEM;
  23.                 goto out_free;
  24.         }
  25.         pdev = part_to_dev(p);

  26.         p->start_sect = start;
  27.         p->alignment_offset =
  28.                 queue_limit_alignment_offset(&disk->queue->limits, start);
  29.         p->discard_alignment =
  30.                 queue_limit_discard_alignment(&disk->queue->limits, start);
  31.         p->nr_sects = len;
  32.         p->partno = partno;
  33.         p->policy = get_disk_ro(disk);

  34.         if (info) {
  35.                 struct partition_meta_info *pinfo = alloc_part_info(disk);
  36.                 if (!pinfo)
  37.                         goto out_free_stats;
  38.                 memcpy(pinfo, info, sizeof(*info));
  39.                 p->info = pinfo;
  40.         }

  41.         dname = dev_name(ddev);
  42.         if (isdigit(dname[strlen(dname) - 1]))
  43.                 dev_set_name(pdev, "%sp%d", dname, partno);
  44.         else
  45.                 dev_set_name(pdev, "%s%d", dname, partno);

  46.         device_initialize(pdev);
  47.         pdev->class = &block_class;
  48.         pdev->type = &part_type;
  49.         pdev->parent = ddev;

  50.         err = blk_alloc_devt(p, &devt);
  51.         if (err)
  52.                 goto out_free_info;
  53.         pdev->devt = devt;

  54.         /* delay uevent until 'holders' subdir is created */
  55.         dev_set_uevent_suppress(pdev, 1);
  56.         err = device_add(pdev);
  57.         if (err)
  58.                 goto out_put;

  59.         err = -ENOMEM;
  60.         p->holder_dir = kobject_create_and_add("holders", &pdev->kobj);
  61.         if (!p->holder_dir)
  62.                 goto out_del;

  63.         dev_set_uevent_suppress(pdev, 0);
  64.         if (flags & ADDPART_FLAG_WHOLEDISK) {
  65.                 err = device_create_file(pdev, &dev_attr_whole_disk);
  66.                 if (err)
  67.                         goto out_del;
  68.         }

  69.         /* everything is up and running, commence */
  70.         rcu_assign_pointer(ptbl->part[partno], p);

  71.         /* suppress uevent if the disk suppresses it */
  72.         if (!dev_get_uevent_suppress(ddev))
  73.                 kobject_uevent(&pdev->kobj, KOBJ_ADD);

  74.         hd_ref_init(p);
  75.         return p;

  76. out_free_info:
  77.         free_part_info(p);
  78. out_free_stats:
  79.         free_part_stats(p);
  80. out_free:
  81.         kfree(p);
  82.         return ERR_PTR(err);
  83. out_del:
  84.         kobject_put(p->holder_dir);
  85.         device_del(pdev);
  86. out_put:
  87.         put_device(pdev);
  88.         blk_free_devt(devt);
  89.         return ERR_PTR(err);
  90. }
复制代码
这里的device_add失败后到out_put put_device,device_del后也走put_device

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP