Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : /* 3 : : * linux/drivers/base/map.c 4 : : * 5 : : * (C) Copyright Al Viro 2002,2003 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 : : 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 : : 19 : : struct kobj_map { 20 : : struct probe { 21 : : struct probe *next; 22 : : dev_t dev; 23 : : unsigned long range; 24 : : struct module *owner; 25 : : kobj_probe_t *get; 26 : : int (*lock)(dev_t, void *); 27 : : void *data; 28 : : } *probes[255]; 29 : : struct mutex *lock; 30 : : }; 31 : : 32 : 2655 : int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, 33 : : struct module *module, kobj_probe_t *probe, 34 : : int (*lock)(dev_t, void *), void *data) 35 : : { 36 : 2655 : unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; 37 : 2655 : unsigned index = MAJOR(dev); 38 : 2655 : unsigned i; 39 : 2655 : struct probe *p; 40 : : 41 : 2655 : if (n > 255) 42 : : n = 255; 43 : : 44 : 2655 : p = kmalloc_array(n, sizeof(struct probe), GFP_KERNEL); 45 [ + - ]: 2655 : if (p == NULL) 46 : : return -ENOMEM; 47 : : 48 [ + + ]: 5310 : for (i = 0; i < n; i++, p++) { 49 : 2655 : p->owner = module; 50 : 2655 : p->get = probe; 51 : 2655 : p->lock = lock; 52 : 2655 : p->dev = dev; 53 : 2655 : p->range = range; 54 : 2655 : p->data = data; 55 : : } 56 : 2655 : mutex_lock(domain->lock); 57 [ + + ]: 5310 : for (i = 0, p -= n; i < n; i++, p++, index++) { 58 : 2655 : struct probe **s = &domain->probes[index % 255]; 59 [ + - - + ]: 2655 : while (*s && (*s)->range < range) 60 : 0 : s = &(*s)->next; 61 : 2655 : p->next = *s; 62 : 2655 : *s = p; 63 : : } 64 : 2655 : mutex_unlock(domain->lock); 65 : 2655 : return 0; 66 : : } 67 : : 68 : 0 : void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) 69 : : { 70 : 0 : unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; 71 : 0 : unsigned index = MAJOR(dev); 72 : 0 : unsigned i; 73 : 0 : struct probe *found = NULL; 74 : : 75 : 0 : if (n > 255) 76 : : n = 255; 77 : : 78 : 0 : mutex_lock(domain->lock); 79 [ # # ]: 0 : for (i = 0; i < n; i++, index++) { 80 : 0 : struct probe **s; 81 [ # # ]: 0 : for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) { 82 : 0 : struct probe *p = *s; 83 [ # # # # ]: 0 : if (p->dev == dev && p->range == range) { 84 : 0 : *s = p->next; 85 [ # # ]: 0 : if (!found) 86 : 0 : found = p; 87 : : break; 88 : : } 89 : : } 90 : : } 91 : 0 : mutex_unlock(domain->lock); 92 : 0 : kfree(found); 93 : 0 : } 94 : : 95 : 1092 : struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index) 96 : : { 97 : 1092 : struct kobject *kobj; 98 : 1092 : struct probe *p; 99 : 1092 : unsigned long best = ~0UL; 100 : : 101 : 1113 : retry: 102 : 1113 : mutex_lock(domain->lock); 103 [ + - ]: 4095 : for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) { 104 : 4095 : struct kobject *(*probe)(dev_t, int *, void *); 105 : 4095 : struct module *owner; 106 : 4095 : void *data; 107 : : 108 [ + + - + ]: 4095 : if (p->dev > dev || p->dev + p->range - 1 < dev) 109 : 2982 : continue; 110 [ + - ]: 1113 : if (p->range - 1 >= best) 111 : : break; 112 [ - + ]: 1113 : if (!try_module_get(p->owner)) 113 : 0 : continue; 114 : 1113 : owner = p->owner; 115 : 1113 : data = p->data; 116 : 1113 : probe = p->get; 117 : 1113 : best = p->range - 1; 118 : 1113 : *index = dev - p->dev; 119 [ + + - + ]: 1113 : if (p->lock && p->lock(dev, data) < 0) { 120 : 0 : module_put(owner); 121 : 0 : continue; 122 : : } 123 : 1113 : mutex_unlock(domain->lock); 124 : 1113 : kobj = probe(dev, index, data); 125 : : /* Currently ->owner protects _only_ ->probe() itself. */ 126 : 1113 : module_put(owner); 127 [ + + ]: 1113 : if (kobj) 128 : 1092 : return kobj; 129 : 21 : goto retry; 130 : : } 131 : 0 : mutex_unlock(domain->lock); 132 : 0 : return NULL; 133 : : } 134 : : 135 : 42 : struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock) 136 : : { 137 : 42 : struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL); 138 : 42 : struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL); 139 : 42 : int i; 140 : : 141 [ - + ]: 42 : if ((p == NULL) || (base == NULL)) { 142 : 0 : kfree(p); 143 : 0 : kfree(base); 144 : 0 : return NULL; 145 : : } 146 : : 147 : 42 : base->dev = 1; 148 : 42 : base->range = ~0; 149 : 42 : base->get = base_probe; 150 [ + + ]: 10752 : for (i = 0; i < 255; i++) 151 : 10710 : p->probes[i] = base; 152 : 42 : p->lock = lock; 153 : 42 : return p; 154 : : }