LCOV - code coverage report
Current view: top level - fs - char_dev.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 149 282 52.8 %
Date: 2021-04-22 12:43:58 Functions: 13 26 50.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  *  linux/fs/char_dev.c
       4             :  *
       5             :  *  Copyright (C) 1991, 1992  Linus Torvalds
       6             :  */
       7             : 
       8             : #include <linux/init.h>
       9             : #include <linux/fs.h>
      10             : #include <linux/kdev_t.h>
      11             : #include <linux/slab.h>
      12             : #include <linux/string.h>
      13             : 
      14             : #include <linux/major.h>
      15             : #include <linux/errno.h>
      16             : #include <linux/module.h>
      17             : #include <linux/seq_file.h>
      18             : 
      19             : #include <linux/kobject.h>
      20             : #include <linux/kobj_map.h>
      21             : #include <linux/cdev.h>
      22             : #include <linux/mutex.h>
      23             : #include <linux/backing-dev.h>
      24             : #include <linux/tty.h>
      25             : 
      26             : #include "internal.h"
      27             : 
      28             : static struct kobj_map *cdev_map;
      29             : 
      30             : static DEFINE_MUTEX(chrdevs_lock);
      31             : 
      32             : #define CHRDEV_MAJOR_HASH_SIZE 255
      33             : 
      34             : static struct char_device_struct {
      35             :         struct char_device_struct *next;
      36             :         unsigned int major;
      37             :         unsigned int baseminor;
      38             :         int minorct;
      39             :         char name[64];
      40             :         struct cdev *cdev;              /* will die */
      41             : } *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
      42             : 
      43             : /* index in the above */
      44          13 : static inline int major_to_index(unsigned major)
      45             : {
      46          13 :         return major % CHRDEV_MAJOR_HASH_SIZE;
      47             : }
      48             : 
      49             : #ifdef CONFIG_PROC_FS
      50             : 
      51           0 : void chrdev_show(struct seq_file *f, off_t offset)
      52             : {
      53           0 :         struct char_device_struct *cd;
      54             : 
      55           0 :         mutex_lock(&chrdevs_lock);
      56           0 :         for (cd = chrdevs[major_to_index(offset)]; cd; cd = cd->next) {
      57           0 :                 if (cd->major == offset)
      58           0 :                         seq_printf(f, "%3d %s\n", cd->major, cd->name);
      59             :         }
      60           0 :         mutex_unlock(&chrdevs_lock);
      61           0 : }
      62             : 
      63             : #endif /* CONFIG_PROC_FS */
      64             : 
      65           1 : static int find_dynamic_major(void)
      66             : {
      67           1 :         int i;
      68           1 :         struct char_device_struct *cd;
      69             : 
      70           1 :         for (i = ARRAY_SIZE(chrdevs)-1; i >= CHRDEV_MAJOR_DYN_END; i--) {
      71           1 :                 if (chrdevs[i] == NULL)
      72           1 :                         return i;
      73             :         }
      74             : 
      75           0 :         for (i = CHRDEV_MAJOR_DYN_EXT_START;
      76           0 :              i >= CHRDEV_MAJOR_DYN_EXT_END; i--) {
      77           0 :                 for (cd = chrdevs[major_to_index(i)]; cd; cd = cd->next)
      78           0 :                         if (cd->major == i)
      79             :                                 break;
      80             : 
      81           0 :                 if (cd == NULL)
      82           0 :                         return i;
      83             :         }
      84             : 
      85             :         return -EBUSY;
      86             : }
      87             : 
      88             : /*
      89             :  * Register a single major with a specified minor range.
      90             :  *
      91             :  * If major == 0 this function will dynamically allocate an unused major.
      92             :  * If major > 0 this function will attempt to reserve the range of minors
      93             :  * with given major.
      94             :  *
      95             :  */
      96             : static struct char_device_struct *
      97          13 : __register_chrdev_region(unsigned int major, unsigned int baseminor,
      98             :                            int minorct, const char *name)
      99             : {
     100          13 :         struct char_device_struct *cd, *curr, *prev = NULL;
     101          13 :         int ret;
     102          13 :         int i;
     103             : 
     104          13 :         if (major >= CHRDEV_MAJOR_MAX) {
     105           0 :                 pr_err("CHRDEV \"%s\" major requested (%u) is greater than the maximum (%u)\n",
     106             :                        name, major, CHRDEV_MAJOR_MAX-1);
     107           0 :                 return ERR_PTR(-EINVAL);
     108             :         }
     109             : 
     110          13 :         if (minorct > MINORMASK + 1 - baseminor) {
     111           0 :                 pr_err("CHRDEV \"%s\" minor range requested (%u-%u) is out of range of maximum range (%u-%u) for a single major\n",
     112             :                         name, baseminor, baseminor + minorct - 1, 0, MINORMASK);
     113           0 :                 return ERR_PTR(-EINVAL);
     114             :         }
     115             : 
     116          13 :         cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL);
     117          13 :         if (cd == NULL)
     118          13 :                 return ERR_PTR(-ENOMEM);
     119             : 
     120          13 :         mutex_lock(&chrdevs_lock);
     121             : 
     122          13 :         if (major == 0) {
     123           1 :                 ret = find_dynamic_major();
     124           1 :                 if (ret < 0) {
     125           0 :                         pr_err("CHRDEV \"%s\" dynamic allocation region is full\n",
     126             :                                name);
     127           0 :                         goto out;
     128             :                 }
     129           1 :                 major = ret;
     130             :         }
     131             : 
     132          13 :         ret = -EBUSY;
     133          13 :         i = major_to_index(major);
     134          19 :         for (curr = chrdevs[i]; curr; prev = curr, curr = curr->next) {
     135           6 :                 if (curr->major < major)
     136           0 :                         continue;
     137             : 
     138           6 :                 if (curr->major > major)
     139             :                         break;
     140             : 
     141           6 :                 if (curr->baseminor + curr->minorct <= baseminor)
     142           6 :                         continue;
     143             : 
     144           0 :                 if (curr->baseminor >= baseminor + minorct)
     145             :                         break;
     146             : 
     147           0 :                 goto out;
     148             :         }
     149             : 
     150          13 :         cd->major = major;
     151          13 :         cd->baseminor = baseminor;
     152          13 :         cd->minorct = minorct;
     153          13 :         strlcpy(cd->name, name, sizeof(cd->name));
     154             : 
     155          13 :         if (!prev) {
     156           9 :                 cd->next = curr;
     157           9 :                 chrdevs[i] = cd;
     158             :         } else {
     159           4 :                 cd->next = prev->next;
     160           4 :                 prev->next = cd;
     161             :         }
     162             : 
     163          13 :         mutex_unlock(&chrdevs_lock);
     164          13 :         return cd;
     165           0 : out:
     166           0 :         mutex_unlock(&chrdevs_lock);
     167           0 :         kfree(cd);
     168           0 :         return ERR_PTR(ret);
     169             : }
     170             : 
     171             : static struct char_device_struct *
     172           0 : __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
     173             : {
     174           0 :         struct char_device_struct *cd = NULL, **cp;
     175           0 :         int i = major_to_index(major);
     176             : 
     177           0 :         mutex_lock(&chrdevs_lock);
     178           0 :         for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
     179           0 :                 if ((*cp)->major == major &&
     180           0 :                     (*cp)->baseminor == baseminor &&
     181           0 :                     (*cp)->minorct == minorct)
     182             :                         break;
     183           0 :         if (*cp) {
     184           0 :                 cd = *cp;
     185           0 :                 *cp = cd->next;
     186             :         }
     187           0 :         mutex_unlock(&chrdevs_lock);
     188           0 :         return cd;
     189             : }
     190             : 
     191             : /**
     192             :  * register_chrdev_region() - register a range of device numbers
     193             :  * @from: the first in the desired range of device numbers; must include
     194             :  *        the major number.
     195             :  * @count: the number of consecutive device numbers required
     196             :  * @name: the name of the device or driver.
     197             :  *
     198             :  * Return value is zero on success, a negative error code on failure.
     199             :  */
     200           9 : int register_chrdev_region(dev_t from, unsigned count, const char *name)
     201             : {
     202           9 :         struct char_device_struct *cd;
     203           9 :         dev_t to = from + count;
     204           9 :         dev_t n, next;
     205             : 
     206          18 :         for (n = from; n < to; n = next) {
     207           9 :                 next = MKDEV(MAJOR(n)+1, 0);
     208           9 :                 if (next > to)
     209             :                         next = to;
     210          18 :                 cd = __register_chrdev_region(MAJOR(n), MINOR(n),
     211           9 :                                next - n, name);
     212           9 :                 if (IS_ERR(cd))
     213           0 :                         goto fail;
     214             :         }
     215             :         return 0;
     216           0 : fail:
     217           0 :         to = n;
     218           0 :         for (n = from; n < to; n = next) {
     219           0 :                 next = MKDEV(MAJOR(n)+1, 0);
     220           0 :                 kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
     221             :         }
     222           0 :         return PTR_ERR(cd);
     223             : }
     224             : 
     225             : /**
     226             :  * alloc_chrdev_region() - register a range of char device numbers
     227             :  * @dev: output parameter for first assigned number
     228             :  * @baseminor: first of the requested range of minor numbers
     229             :  * @count: the number of minor numbers required
     230             :  * @name: the name of the associated device or driver
     231             :  *
     232             :  * Allocates a range of char device numbers.  The major number will be
     233             :  * chosen dynamically, and returned (along with the first minor number)
     234             :  * in @dev.  Returns zero or a negative error code.
     235             :  */
     236           1 : int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
     237             :                         const char *name)
     238             : {
     239           1 :         struct char_device_struct *cd;
     240           1 :         cd = __register_chrdev_region(0, baseminor, count, name);
     241           1 :         if (IS_ERR(cd))
     242           0 :                 return PTR_ERR(cd);
     243           1 :         *dev = MKDEV(cd->major, cd->baseminor);
     244           1 :         return 0;
     245             : }
     246             : 
     247             : /**
     248             :  * __register_chrdev() - create and register a cdev occupying a range of minors
     249             :  * @major: major device number or 0 for dynamic allocation
     250             :  * @baseminor: first of the requested range of minor numbers
     251             :  * @count: the number of minor numbers required
     252             :  * @name: name of this range of devices
     253             :  * @fops: file operations associated with this devices
     254             :  *
     255             :  * If @major == 0 this functions will dynamically allocate a major and return
     256             :  * its number.
     257             :  *
     258             :  * If @major > 0 this function will attempt to reserve a device with the given
     259             :  * major number and will return zero on success.
     260             :  *
     261             :  * Returns a -ve errno on failure.
     262             :  *
     263             :  * The name of this device has nothing to do with the name of the device in
     264             :  * /dev. It only helps to keep track of the different owners of devices. If
     265             :  * your module name has only one type of devices it's ok to use e.g. the name
     266             :  * of the module here.
     267             :  */
     268           3 : int __register_chrdev(unsigned int major, unsigned int baseminor,
     269             :                       unsigned int count, const char *name,
     270             :                       const struct file_operations *fops)
     271             : {
     272           3 :         struct char_device_struct *cd;
     273           3 :         struct cdev *cdev;
     274           3 :         int err = -ENOMEM;
     275             : 
     276           3 :         cd = __register_chrdev_region(major, baseminor, count, name);
     277           3 :         if (IS_ERR(cd))
     278           0 :                 return PTR_ERR(cd);
     279             : 
     280           3 :         cdev = cdev_alloc();
     281           3 :         if (!cdev)
     282           0 :                 goto out2;
     283             : 
     284           3 :         cdev->owner = fops->owner;
     285           3 :         cdev->ops = fops;
     286           3 :         kobject_set_name(&cdev->kobj, "%s", name);
     287             : 
     288           3 :         err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);
     289           3 :         if (err)
     290           0 :                 goto out;
     291             : 
     292           3 :         cd->cdev = cdev;
     293             : 
     294           3 :         return major ? 0 : cd->major;
     295           0 : out:
     296           0 :         kobject_put(&cdev->kobj);
     297           0 : out2:
     298           0 :         kfree(__unregister_chrdev_region(cd->major, baseminor, count));
     299           0 :         return err;
     300             : }
     301             : 
     302             : /**
     303             :  * unregister_chrdev_region() - unregister a range of device numbers
     304             :  * @from: the first in the range of numbers to unregister
     305             :  * @count: the number of device numbers to unregister
     306             :  *
     307             :  * This function will unregister a range of @count device numbers,
     308             :  * starting with @from.  The caller should normally be the one who
     309             :  * allocated those numbers in the first place...
     310             :  */
     311           0 : void unregister_chrdev_region(dev_t from, unsigned count)
     312             : {
     313           0 :         dev_t to = from + count;
     314           0 :         dev_t n, next;
     315             : 
     316           0 :         for (n = from; n < to; n = next) {
     317           0 :                 next = MKDEV(MAJOR(n)+1, 0);
     318           0 :                 if (next > to)
     319             :                         next = to;
     320           0 :                 kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
     321             :         }
     322           0 : }
     323             : 
     324             : /**
     325             :  * __unregister_chrdev - unregister and destroy a cdev
     326             :  * @major: major device number
     327             :  * @baseminor: first of the range of minor numbers
     328             :  * @count: the number of minor numbers this cdev is occupying
     329             :  * @name: name of this range of devices
     330             :  *
     331             :  * Unregister and destroy the cdev occupying the region described by
     332             :  * @major, @baseminor and @count.  This function undoes what
     333             :  * __register_chrdev() did.
     334             :  */
     335           0 : void __unregister_chrdev(unsigned int major, unsigned int baseminor,
     336             :                          unsigned int count, const char *name)
     337             : {
     338           0 :         struct char_device_struct *cd;
     339             : 
     340           0 :         cd = __unregister_chrdev_region(major, baseminor, count);
     341           0 :         if (cd && cd->cdev)
     342           0 :                 cdev_del(cd->cdev);
     343           0 :         kfree(cd);
     344           0 : }
     345             : 
     346             : static DEFINE_SPINLOCK(cdev_lock);
     347             : 
     348         410 : static struct kobject *cdev_get(struct cdev *p)
     349             : {
     350         410 :         struct module *owner = p->owner;
     351         410 :         struct kobject *kobj;
     352             : 
     353         410 :         if (owner && !try_module_get(owner))
     354             :                 return NULL;
     355         820 :         kobj = kobject_get_unless_zero(&p->kobj);
     356         410 :         if (!kobj)
     357         410 :                 module_put(owner);
     358         410 :         return kobj;
     359             : }
     360             : 
     361         793 : void cdev_put(struct cdev *p)
     362             : {
     363         365 :         if (p) {
     364         383 :                 struct module *owner = p->owner;
     365         383 :                 kobject_put(&p->kobj);
     366         383 :                 module_put(owner);
     367             :         }
     368         365 : }
     369             : 
     370             : /*
     371             :  * Called every time a character special file is opened
     372             :  */
     373         410 : static int chrdev_open(struct inode *inode, struct file *filp)
     374             : {
     375         410 :         const struct file_operations *fops;
     376         410 :         struct cdev *p;
     377         410 :         struct cdev *new = NULL;
     378         410 :         int ret = 0;
     379             : 
     380         410 :         spin_lock(&cdev_lock);
     381         410 :         p = inode->i_cdev;
     382         410 :         if (!p) {
     383          14 :                 struct kobject *kobj;
     384          14 :                 int idx;
     385          14 :                 spin_unlock(&cdev_lock);
     386          14 :                 kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
     387          14 :                 if (!kobj)
     388           0 :                         return -ENXIO;
     389          14 :                 new = container_of(kobj, struct cdev, kobj);
     390          14 :                 spin_lock(&cdev_lock);
     391             :                 /* Check i_cdev again in case somebody beat us to it while
     392             :                    we dropped the lock. */
     393          14 :                 p = inode->i_cdev;
     394          14 :                 if (!p) {
     395          14 :                         inode->i_cdev = p = new;
     396          14 :                         list_add(&inode->i_devices, &p->list);
     397          14 :                         new = NULL;
     398           0 :                 } else if (!cdev_get(p))
     399           0 :                         ret = -ENXIO;
     400         396 :         } else if (!cdev_get(p))
     401           0 :                 ret = -ENXIO;
     402         410 :         spin_unlock(&cdev_lock);
     403         410 :         cdev_put(new);
     404         410 :         if (ret)
     405             :                 return ret;
     406             : 
     407         410 :         ret = -ENXIO;
     408         410 :         fops = fops_get(p->ops);
     409         410 :         if (!fops)
     410           0 :                 goto out_cdev_put;
     411             : 
     412         410 :         replace_fops(filp, fops);
     413         410 :         if (filp->f_op->open) {
     414         410 :                 ret = filp->f_op->open(inode, filp);
     415         410 :                 if (ret)
     416          18 :                         goto out_cdev_put;
     417             :         }
     418             : 
     419             :         return 0;
     420             : 
     421          18 :  out_cdev_put:
     422          18 :         cdev_put(p);
     423             :         return ret;
     424             : }
     425             : 
     426           0 : void cd_forget(struct inode *inode)
     427             : {
     428           0 :         spin_lock(&cdev_lock);
     429           0 :         list_del_init(&inode->i_devices);
     430           0 :         inode->i_cdev = NULL;
     431           0 :         inode->i_mapping = &inode->i_data;
     432           0 :         spin_unlock(&cdev_lock);
     433           0 : }
     434             : 
     435           0 : static void cdev_purge(struct cdev *cdev)
     436             : {
     437           0 :         spin_lock(&cdev_lock);
     438           0 :         while (!list_empty(&cdev->list)) {
     439           0 :                 struct inode *inode;
     440           0 :                 inode = container_of(cdev->list.next, struct inode, i_devices);
     441           0 :                 list_del_init(&inode->i_devices);
     442           0 :                 inode->i_cdev = NULL;
     443             :         }
     444           0 :         spin_unlock(&cdev_lock);
     445           0 : }
     446             : 
     447             : /*
     448             :  * Dummy default file-operations: the only thing this does
     449             :  * is contain the open that then fills in the correct operations
     450             :  * depending on the special file...
     451             :  */
     452             : const struct file_operations def_chr_fops = {
     453             :         .open = chrdev_open,
     454             :         .llseek = noop_llseek,
     455             : };
     456             : 
     457          14 : static struct kobject *exact_match(dev_t dev, int *part, void *data)
     458             : {
     459          14 :         struct cdev *p = data;
     460          14 :         return &p->kobj;
     461             : }
     462             : 
     463          14 : static int exact_lock(dev_t dev, void *data)
     464             : {
     465          14 :         struct cdev *p = data;
     466          14 :         return cdev_get(p) ? 0 : -1;
     467             : }
     468             : 
     469             : /**
     470             :  * cdev_add() - add a char device to the system
     471             :  * @p: the cdev structure for the device
     472             :  * @dev: the first device number for which this device is responsible
     473             :  * @count: the number of consecutive minor numbers corresponding to this
     474             :  *         device
     475             :  *
     476             :  * cdev_add() adds the device represented by @p to the system, making it
     477             :  * live immediately.  A negative error code is returned on failure.
     478             :  */
     479          76 : int cdev_add(struct cdev *p, dev_t dev, unsigned count)
     480             : {
     481          76 :         int error;
     482             : 
     483          76 :         p->dev = dev;
     484          76 :         p->count = count;
     485             : 
     486          76 :         if (WARN_ON(dev == WHITEOUT_DEV))
     487             :                 return -EBUSY;
     488             : 
     489          76 :         error = kobj_map(cdev_map, dev, count, NULL,
     490             :                          exact_match, exact_lock, p);
     491          76 :         if (error)
     492             :                 return error;
     493             : 
     494          76 :         kobject_get(p->kobj.parent);
     495             : 
     496          76 :         return 0;
     497             : }
     498             : 
     499             : /**
     500             :  * cdev_set_parent() - set the parent kobject for a char device
     501             :  * @p: the cdev structure
     502             :  * @kobj: the kobject to take a reference to
     503             :  *
     504             :  * cdev_set_parent() sets a parent kobject which will be referenced
     505             :  * appropriately so the parent is not freed before the cdev. This
     506             :  * should be called before cdev_add.
     507             :  */
     508           0 : void cdev_set_parent(struct cdev *p, struct kobject *kobj)
     509             : {
     510           0 :         WARN_ON(!kobj->state_initialized);
     511           0 :         p->kobj.parent = kobj;
     512           0 : }
     513             : 
     514             : /**
     515             :  * cdev_device_add() - add a char device and it's corresponding
     516             :  *      struct device, linkink
     517             :  * @dev: the device structure
     518             :  * @cdev: the cdev structure
     519             :  *
     520             :  * cdev_device_add() adds the char device represented by @cdev to the system,
     521             :  * just as cdev_add does. It then adds @dev to the system using device_add
     522             :  * The dev_t for the char device will be taken from the struct device which
     523             :  * needs to be initialized first. This helper function correctly takes a
     524             :  * reference to the parent device so the parent will not get released until
     525             :  * all references to the cdev are released.
     526             :  *
     527             :  * This helper uses dev->devt for the device number. If it is not set
     528             :  * it will not add the cdev and it will be equivalent to device_add.
     529             :  *
     530             :  * This function should be used whenever the struct cdev and the
     531             :  * struct device are members of the same structure whose lifetime is
     532             :  * managed by the struct device.
     533             :  *
     534             :  * NOTE: Callers must assume that userspace was able to open the cdev and
     535             :  * can call cdev fops callbacks at any time, even if this function fails.
     536             :  */
     537           0 : int cdev_device_add(struct cdev *cdev, struct device *dev)
     538             : {
     539           0 :         int rc = 0;
     540             : 
     541           0 :         if (dev->devt) {
     542           0 :                 cdev_set_parent(cdev, &dev->kobj);
     543             : 
     544           0 :                 rc = cdev_add(cdev, dev->devt, 1);
     545           0 :                 if (rc)
     546             :                         return rc;
     547             :         }
     548             : 
     549           0 :         rc = device_add(dev);
     550           0 :         if (rc)
     551           0 :                 cdev_del(cdev);
     552             : 
     553             :         return rc;
     554             : }
     555             : 
     556             : /**
     557             :  * cdev_device_del() - inverse of cdev_device_add
     558             :  * @dev: the device structure
     559             :  * @cdev: the cdev structure
     560             :  *
     561             :  * cdev_device_del() is a helper function to call cdev_del and device_del.
     562             :  * It should be used whenever cdev_device_add is used.
     563             :  *
     564             :  * If dev->devt is not set it will not remove the cdev and will be equivalent
     565             :  * to device_del.
     566             :  *
     567             :  * NOTE: This guarantees that associated sysfs callbacks are not running
     568             :  * or runnable, however any cdevs already open will remain and their fops
     569             :  * will still be callable even after this function returns.
     570             :  */
     571           0 : void cdev_device_del(struct cdev *cdev, struct device *dev)
     572             : {
     573           0 :         device_del(dev);
     574           0 :         if (dev->devt)
     575           0 :                 cdev_del(cdev);
     576           0 : }
     577             : 
     578           0 : static void cdev_unmap(dev_t dev, unsigned count)
     579             : {
     580           0 :         kobj_unmap(cdev_map, dev, count);
     581             : }
     582             : 
     583             : /**
     584             :  * cdev_del() - remove a cdev from the system
     585             :  * @p: the cdev structure to be removed
     586             :  *
     587             :  * cdev_del() removes @p from the system, possibly freeing the structure
     588             :  * itself.
     589             :  *
     590             :  * NOTE: This guarantees that cdev device will no longer be able to be
     591             :  * opened, however any cdevs already open will remain and their fops will
     592             :  * still be callable even after cdev_del returns.
     593             :  */
     594           0 : void cdev_del(struct cdev *p)
     595             : {
     596           0 :         cdev_unmap(p->dev, p->count);
     597           0 :         kobject_put(&p->kobj);
     598           0 : }
     599             : 
     600             : 
     601           0 : static void cdev_default_release(struct kobject *kobj)
     602             : {
     603           0 :         struct cdev *p = container_of(kobj, struct cdev, kobj);
     604           0 :         struct kobject *parent = kobj->parent;
     605             : 
     606           0 :         cdev_purge(p);
     607           0 :         kobject_put(parent);
     608           0 : }
     609             : 
     610           0 : static void cdev_dynamic_release(struct kobject *kobj)
     611             : {
     612           0 :         struct cdev *p = container_of(kobj, struct cdev, kobj);
     613           0 :         struct kobject *parent = kobj->parent;
     614             : 
     615           0 :         cdev_purge(p);
     616           0 :         kfree(p);
     617           0 :         kobject_put(parent);
     618           0 : }
     619             : 
     620             : static struct kobj_type ktype_cdev_default = {
     621             :         .release        = cdev_default_release,
     622             : };
     623             : 
     624             : static struct kobj_type ktype_cdev_dynamic = {
     625             :         .release        = cdev_dynamic_release,
     626             : };
     627             : 
     628             : /**
     629             :  * cdev_alloc() - allocate a cdev structure
     630             :  *
     631             :  * Allocates and returns a cdev structure, or NULL on failure.
     632             :  */
     633          72 : struct cdev *cdev_alloc(void)
     634             : {
     635          72 :         struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
     636          72 :         if (p) {
     637          72 :                 INIT_LIST_HEAD(&p->list);
     638          72 :                 kobject_init(&p->kobj, &ktype_cdev_dynamic);
     639             :         }
     640          72 :         return p;
     641             : }
     642             : 
     643             : /**
     644             :  * cdev_init() - initialize a cdev structure
     645             :  * @cdev: the structure to initialize
     646             :  * @fops: the file_operations for this device
     647             :  *
     648             :  * Initializes @cdev, remembering @fops, making it ready to add to the
     649             :  * system with cdev_add().
     650             :  */
     651           4 : void cdev_init(struct cdev *cdev, const struct file_operations *fops)
     652             : {
     653           4 :         memset(cdev, 0, sizeof *cdev);
     654           4 :         INIT_LIST_HEAD(&cdev->list);
     655           4 :         kobject_init(&cdev->kobj, &ktype_cdev_default);
     656           4 :         cdev->ops = fops;
     657           4 : }
     658             : 
     659           0 : static struct kobject *base_probe(dev_t dev, int *part, void *data)
     660             : {
     661           0 :         if (request_module("char-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0)
     662             :                 /* Make old-style 2.4 aliases work */
     663           0 :                 request_module("char-major-%d", MAJOR(dev));
     664           0 :         return NULL;
     665             : }
     666             : 
     667           1 : void __init chrdev_init(void)
     668             : {
     669           1 :         cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
     670           1 : }
     671             : 
     672             : 
     673             : /* Let modules do char dev stuff */
     674             : EXPORT_SYMBOL(register_chrdev_region);
     675             : EXPORT_SYMBOL(unregister_chrdev_region);
     676             : EXPORT_SYMBOL(alloc_chrdev_region);
     677             : EXPORT_SYMBOL(cdev_init);
     678             : EXPORT_SYMBOL(cdev_alloc);
     679             : EXPORT_SYMBOL(cdev_del);
     680             : EXPORT_SYMBOL(cdev_add);
     681             : EXPORT_SYMBOL(cdev_set_parent);
     682             : EXPORT_SYMBOL(cdev_device_add);
     683             : EXPORT_SYMBOL(cdev_device_del);
     684             : EXPORT_SYMBOL(__register_chrdev);
     685             : EXPORT_SYMBOL(__unregister_chrdev);

Generated by: LCOV version 1.14