map.c 3.2 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/kdev_t.h>
  14. #include <linux/kobject.h>
  15. #include <linux/kobj_map.h>
  16. struct kobj_map {
  17. struct probe {
  18. struct probe *next;
  19. dev_t dev;
  20. unsigned long range;
  21. struct module *owner;
  22. kobj_probe_t *get;
  23. int (*lock)(dev_t, void *);
  24. void *data;
  25. } *probes[255];
  26. struct semaphore *sem;
  27. };
  28. int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
  29. struct module *module, kobj_probe_t *probe,
  30. int (*lock)(dev_t, void *), void *data)
  31. {
  32. unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
  33. unsigned index = MAJOR(dev);
  34. unsigned i;
  35. struct probe *p;
  36. if (n > 255)
  37. n = 255;
  38. p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);
  39. if (p == NULL)
  40. return -ENOMEM;
  41. for (i = 0; i < n; i++, p++) {
  42. p->owner = module;
  43. p->get = probe;
  44. p->lock = lock;
  45. p->dev = dev;
  46. p->range = range;
  47. p->data = data;
  48. }
  49. down(domain->sem);
  50. for (i = 0, p -= n; i < n; i++, p++, index++) {
  51. struct probe **s = &domain->probes[index % 255];
  52. while (*s && (*s)->range < range)
  53. s = &(*s)->next;
  54. p->next = *s;
  55. *s = p;
  56. }
  57. up(domain->sem);
  58. return 0;
  59. }
  60. void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
  61. {
  62. unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
  63. unsigned index = MAJOR(dev);
  64. unsigned i;
  65. struct probe *found = NULL;
  66. if (n > 255)
  67. n = 255;
  68. down(domain->sem);
  69. for (i = 0; i < n; i++, index++) {
  70. struct probe **s;
  71. for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
  72. struct probe *p = *s;
  73. if (p->dev == dev && p->range == range) {
  74. *s = p->next;
  75. if (!found)
  76. found = p;
  77. break;
  78. }
  79. }
  80. }
  81. up(domain->sem);
  82. kfree(found);
  83. }
  84. struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
  85. {
  86. struct kobject *kobj;
  87. struct probe *p;
  88. unsigned long best = ~0UL;
  89. retry:
  90. down(domain->sem);
  91. for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
  92. struct kobject *(*probe)(dev_t, int *, void *);
  93. struct module *owner;
  94. void *data;
  95. if (p->dev > dev || p->dev + p->range - 1 < dev)
  96. continue;
  97. if (p->range - 1 >= best)
  98. break;
  99. if (!try_module_get(p->owner))
  100. continue;
  101. owner = p->owner;
  102. data = p->data;
  103. probe = p->get;
  104. best = p->range - 1;
  105. *index = dev - p->dev;
  106. if (p->lock && p->lock(dev, data) < 0) {
  107. module_put(owner);
  108. continue;
  109. }
  110. up(domain->sem);
  111. kobj = probe(dev, index, data);
  112. /* Currently ->owner protects _only_ ->probe() itself. */
  113. module_put(owner);
  114. if (kobj)
  115. return kobj;
  116. goto retry;
  117. }
  118. up(domain->sem);
  119. return NULL;
  120. }
  121. struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
  122. {
  123. struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
  124. struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);
  125. int i;
  126. if ((p == NULL) || (base == NULL)) {
  127. kfree(p);
  128. kfree(base);
  129. return NULL;
  130. }
  131. base->dev = 1;
  132. base->range = ~0;
  133. base->get = base_probe;
  134. for (i = 0; i < 255; i++)
  135. p->probes[i] = base;
  136. p->sem = sem;
  137. return p;
  138. }