diff options
author | Chengguang Xu <cgxu519@gmx.com> | 2019-02-15 13:27:13 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-04-02 17:49:58 +0200 |
commit | 4b0be572603233b4240f6072f0bd35542d311ed8 (patch) | |
tree | cdd02e67764c9dce78f6c3f4ae6412890e1781b4 | |
parent | chardev: add a check for given minor range (diff) | |
download | linux-4b0be572603233b4240f6072f0bd35542d311ed8.tar.xz linux-4b0be572603233b4240f6072f0bd35542d311ed8.zip |
chardev: code cleanup for __register_chrdev_region()
It's just code cleanup, not functional change.
Signed-off-by: Chengguang Xu <cgxu519@gmx.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | fs/char_dev.c | 69 |
1 files changed, 28 insertions, 41 deletions
diff --git a/fs/char_dev.c b/fs/char_dev.c index 6803e98414f1..bd2bf1fd847e 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -100,10 +100,16 @@ static struct char_device_struct * __register_chrdev_region(unsigned int major, unsigned int baseminor, int minorct, const char *name) { - struct char_device_struct *cd, **cp; - int ret = 0; + struct char_device_struct *cd, *curr, *prev = NULL; + int ret = -EBUSY; int i; + if (major >= CHRDEV_MAJOR_MAX) { + pr_err("CHRDEV \"%s\" major requested (%u) is greater than the maximum (%u)\n", + name, major, CHRDEV_MAJOR_MAX-1); + return ERR_PTR(-EINVAL); + } + if (minorct > MINORMASK + 1 - baseminor) { pr_err("CHRDEV \"%s\" minor range requested (%u-%u) is out of range of maximum range (%u-%u) for a single major\n", name, baseminor, baseminor + minorct - 1, 0, MINORMASK); @@ -126,55 +132,36 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, major = ret; } - if (major >= CHRDEV_MAJOR_MAX) { - pr_err("CHRDEV \"%s\" major requested (%u) is greater than the maximum (%u)\n", - name, major, CHRDEV_MAJOR_MAX-1); - ret = -EINVAL; - goto out; - } - - cd->major = major; - cd->baseminor = baseminor; - cd->minorct = minorct; - strlcpy(cd->name, name, sizeof(cd->name)); - i = major_to_index(major); + for (curr = chrdevs[i]; curr; prev = curr, curr = curr->next) { + if (curr->major < major) + continue; - for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) - if ((*cp)->major > major || - ((*cp)->major == major && - (((*cp)->baseminor >= baseminor) || - ((*cp)->baseminor + (*cp)->minorct > baseminor)))) + if (curr->major > major) break; - /* Check for overlapping minor ranges. */ - if (*cp && (*cp)->major == major) { - int old_min = (*cp)->baseminor; - int old_max = (*cp)->baseminor + (*cp)->minorct - 1; - int new_min = baseminor; - int new_max = baseminor + minorct - 1; + if (curr->baseminor + curr->minorct <= baseminor) + continue; - /* New driver overlaps from the left. */ - if (new_max >= old_min && new_max <= old_max) { - ret = -EBUSY; - goto out; - } + if (curr->baseminor >= baseminor + minorct) + break; - /* New driver overlaps from the right. */ - if (new_min <= old_max && new_min >= old_min) { - ret = -EBUSY; - goto out; - } + goto out; + } - if (new_min < old_min && new_max > old_max) { - ret = -EBUSY; - goto out; - } + cd->major = major; + cd->baseminor = baseminor; + cd->minorct = minorct; + strlcpy(cd->name, name, sizeof(cd->name)); + if (!prev) { + cd->next = curr; + chrdevs[i] = cd; + } else { + cd->next = prev->next; + prev->next = cd; } - cd->next = *cp; - *cp = cd; mutex_unlock(&chrdevs_lock); return cd; out: |