author: Amos Waterland <apw@us.ibm.com> 2006-09-29 02:00:08 -0700
committer: Linus Torvalds <torvalds@g5.osdl.org> 2006-09-29 09:18:12 -0700
commit: 01d553d0fe9f90a132c5ff494872be8d4126be1e
parent: f400e198b2ed26ce55b22a1412ded0896e7516ac
Commit Summary:
Diffstat:
1 file changed, 20 insertions, 5 deletions
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 0009346d827f..33b95af89da4 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -128,13 +128,31 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
if ((*cp)->major > major ||
- ((*cp)->major == major && (*cp)->baseminor >= baseminor))
+ ((*cp)->major == major &&
+ (((*cp)->baseminor >= baseminor) ||
+ ((*cp)->baseminor + (*cp)->minorct > baseminor))))
break;
- if (*cp && (*cp)->major == major &&
- (*cp)->baseminor < baseminor + minorct) {
- ret = -EBUSY;
- goto out;
+
+ /* 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;
+
+ /* New driver overlaps from the left. */
+ if (new_max >= old_min && new_max <= old_max) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* New driver overlaps from the right. */
+ if (new_min <= old_max && new_min >= old_min) {
+ ret = -EBUSY;
+ goto out;
+ }
}
+
cd->next = *cp;
*cp = cd;
mutex_unlock(&chrdevs_lock);