map.c 3.3 KB

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