root/drivers/base/map.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kobj_map
  2. kobj_unmap
  3. kobj_lookup
  4. kobj_map_init

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

/* [<][>][^][v][top][bottom][index][help] */