map.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * linux/drivers/base/map.c
  4. *
  5. * (C) Copyright Al Viro 2002,2003
  6. * Released under GPL v2.
  7. *
  8. * NOTE: data structure needs to be changed. It works, but for large dev_t
  9. * it will be too slow. It is isolated, though, so these changes will be
  10. * local to that file.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/slab.h>
  14. #include <linux/mutex.h>
  15. #include <linux/kdev_t.h>
  16. #include <linux/kobject.h>
  17. #include <linux/kobj_map.h>
  18. struct kobj_map {
  19. struct probe {
  20. struct probe *next;
  21. dev_t dev;
  22. unsigned long range;
  23. struct module *owner;
  24. kobj_probe_t *get;
  25. int (*lock)(dev_t, void *);
  26. void *data;
  27. } *probes[255];
  28. struct mutex *lock;
  29. };
  30. int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
  31. struct module *module, kobj_probe_t *probe,
  32. int (*lock)(dev_t, void *), void *data)
  33. {
  34. unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
  35. unsigned index = MAJOR(dev);
  36. unsigned i;
  37. struct probe *p;
  38. if (n > 255)
  39. n = 255;
  40. p = kmalloc_array(n, sizeof(struct probe), GFP_KERNEL);
  41. if (p == NULL)
  42. return -ENOMEM;
  43. for (i = 0; i < n; i++, p++) {
  44. p->owner = module;
  45. p->get = probe;
  46. p->lock = lock;
  47. p->dev = dev;
  48. p->range = range;
  49. p->data = data;
  50. }
  51. mutex_lock(domain->lock);
  52. for (i = 0, p -= n; i < n; i++, p++, index++) {
  53. struct probe **s = &domain->probes[index % 255];
  54. while (*s && (*s)->range < range)
  55. s = &(*s)->next;
  56. p->next = *s;
  57. *s = p;
  58. }
  59. mutex_unlock(domain->lock);
  60. return 0;
  61. }
  62. void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
  63. {
  64. unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
  65. unsigned index = MAJOR(dev);
  66. unsigned i;
  67. struct probe *found = NULL;
  68. if (n > 255)
  69. n = 255;
  70. mutex_lock(domain->lock);
  71. for (i = 0; i < n; i++, index++) {
  72. struct probe **s;
  73. for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
  74. struct probe *p = *s;
  75. if (p->dev == dev && p->range == range) {
  76. *s = p->next;
  77. if (!found)
  78. found = p;
  79. break;
  80. }
  81. }
  82. }
  83. mutex_unlock(domain->lock);
  84. kfree(found);
  85. }
  86. struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
  87. {
  88. struct kobject *kobj;
  89. struct probe *p;
  90. unsigned long best = ~0UL;
  91. retry:
  92. mutex_lock(domain->lock);
  93. for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
  94. struct kobject *(*probe)(dev_t, int *, void *);
  95. struct module *owner;
  96. void *data;
  97. if (p->dev > dev || p->dev + p->range - 1 < dev)
  98. continue;
  99. if (p->range - 1 >= best)
  100. break;
  101. if (!try_module_get(p->owner))
  102. continue;
  103. owner = p->owner;
  104. data = p->data;
  105. probe = p->get;
  106. best = p->range - 1;
  107. *index = dev - p->dev;
  108. if (p->lock && p->lock(dev, data) < 0) {
  109. module_put(owner);
  110. continue;
  111. }
  112. mutex_unlock(domain->lock);
  113. kobj = probe(dev, index, data);
  114. /* Currently ->owner protects _only_ ->probe() itself. */
  115. module_put(owner);
  116. if (kobj)
  117. return kobj;
  118. goto retry;
  119. }
  120. mutex_unlock(domain->lock);
  121. return NULL;
  122. }
  123. struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock)
  124. {
  125. struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
  126. struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);
  127. int i;
  128. if ((p == NULL) || (base == NULL)) {
  129. kfree(p);
  130. kfree(base);
  131. return NULL;
  132. }
  133. base->dev = 1;
  134. base->range = ~0;
  135. base->get = base_probe;
  136. for (i = 0; i < 255; i++)
  137. p->probes[i] = base;
  138. p->lock = lock;
  139. return p;
  140. }