LCOV - code coverage report
Current view: top level - drivers/base - map.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 61 88 69.3 %
Date: 2022-03-28 15:32:58 Functions: 3 4 75.0 %
Branches: 21 40 52.5 %

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

Generated by: LCOV version 1.14