mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Carsten Otte" <COTTE@de.ibm.com>
To: Richard Gooch <rgooch@ras.ucalgary.ca>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] linux-2.417 devfs 64bit portablility issue
Date: Wed, 20 Mar 2002 13:27:47 +0100	[thread overview]
Message-ID: <OF651FD06B.226CC224-ONC1256B82.0043E511@de.ibm.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 803 bytes --]


Hi Richard,

the previous version of my patch did contain a bug,
caused by incorrect parameter order when calling
__devfs_unregister_major. The symptom was, that
major numbers registered with devfs_register_*dev
but not allocated with devfs_alloc_major were not
freed by calling devfs_unregister_*dev. This is
now fixed. Sorry, the patch is attached (due to Notes
messing up with whitespace).
(See attached file: linux-2.4.17-devfs_fixup.diff)

Richard, I would appreciate it if you could finally
look into this.

mit freundlichem Gruß / with kind regards
Carsten Otte

IBM Deutschland Entwicklung GmbH
Linux for eServer development - device driver team
Phone: +49/07031/16-4076
IBM internal phone: *120-4076
--
We are Linux.
Resistance indicates that you're missing the point!

[-- Attachment #2: linux-2.4.17-devfs_fixup.diff --]
[-- Type: application/octet-stream, Size: 11027 bytes --]

diff -ruN linux-2.4.17-sdmany/fs/devfs/base.c linux-2.4.17-sdmany-devfs_fixup/fs/devfs/base.c
--- linux-2.4.17-sdmany/fs/devfs/base.c	Wed Feb 13 13:25:50 2002
+++ linux-2.4.17-sdmany-devfs_fixup/fs/devfs/base.c	Tue Mar 12 20:15:53 2002
@@ -2186,7 +2186,7 @@
 }   /*  End Function devfs_get_name  */
 
 
-/**y
+/**
  *	devfs_register_chrdev - Optionally register a conventional character driver.
  *	@major: The major number for the driver.
  *	@name: The name of the driver (as seen in /proc/devices).
@@ -2201,12 +2201,21 @@
 			   struct file_operations *fops)
 {
     unsigned int new_major;
-    if (boot_options & OPTION_ONLY) return 0;
-    if (major)
-	new_major = major;
-    else
-	new_major = devfs_alloc_major (DEVFS_SPECIAL_CHR);
-    return register_chrdev (new_major, name, fops);
+    int result;
+    if (boot_options & OPTION_ONLY) 
+	    return 0;
+    new_major = __devfs_register_major (major, DEVFS_SPECIAL_CHR);
+    if (new_major < 0) 
+	    return new_major;
+    result=register_chrdev (new_major, name, fops);
+    if (result < 0) {
+	    __devfs_unregister_major (major, DEVFS_SPECIAL_CHR);
+	    return result;
+    }
+    if (major) 
+	    return 0;
+    else 
+	    return new_major;
 }   /*  End Function devfs_register_chrdev  */
 
 
@@ -2225,12 +2234,21 @@
 			   struct block_device_operations *bdops)
 {
     unsigned int new_major;
-    if (boot_options & OPTION_ONLY) return 0;
-    if (major)
-	new_major = major;
-    else
-	new_major = devfs_alloc_major (DEVFS_SPECIAL_BLK);
-    return register_blkdev (new_major, name, bdops);
+    int result;
+    if (boot_options & OPTION_ONLY) 
+	    return 0;
+    new_major = __devfs_register_major (major, DEVFS_SPECIAL_BLK);
+    if (new_major < 0)
+	    return new_major;
+    result=register_blkdev (new_major, name, bdops);
+    if (result < 0) {
+	    __devfs_unregister_major (major, DEVFS_SPECIAL_BLK);
+	    return result;
+    }
+    if (major) 
+	    return 0;
+    else 
+	    return new_major;
 }   /*  End Function devfs_register_blkdev  */
 
 
@@ -2246,8 +2264,9 @@
 
 int devfs_unregister_chrdev (unsigned int major, const char *name)
 {
-    if (boot_options & OPTION_ONLY) return 0;
-    devfs_dealloc_major (major, DEVFS_SPECIAL_CHR);
+    if (boot_options & OPTION_ONLY) 
+	    return 0;
+    __devfs_unregister_major (major, DEVFS_SPECIAL_CHR);
     return unregister_chrdev (major, name);
 }   /*  End Function devfs_unregister_chrdev  */
 
@@ -2264,8 +2283,9 @@
 
 int devfs_unregister_blkdev (unsigned int major, const char *name)
 {
-    if (boot_options & OPTION_ONLY) return 0;
-    devfs_dealloc_major (major, DEVFS_SPECIAL_BLK);
+    if (boot_options & OPTION_ONLY) 
+	    return 0;
+    __devfs_unregister_major (major, DEVFS_SPECIAL_BLK);
     return unregister_blkdev (major, name);
 }   /*  End Function devfs_unregister_blkdev  */
 
diff -ruN linux-2.4.17-sdmany/fs/devfs/util.c linux-2.4.17-sdmany-devfs_fixup/fs/devfs/util.c
--- linux-2.4.17-sdmany/fs/devfs/util.c	Fri Oct 26 20:00:52 2001
+++ linux-2.4.17-sdmany-devfs_fixup/fs/devfs/util.c	Tue Mar 12 20:48:52 2002
@@ -185,43 +185,62 @@
 
 struct major_list
 {
-    spinlock_t lock;
-    __u32 bits[8];
+	spinlock_t lock;
+	unsigned char state[256];
 };
 
+
+
 /*  Block majors already assigned:
     0-3, 7-9, 11-63, 65-99, 101-113, 120-127, 199, 201, 240-255
     Total free: 122
 */
+
 static struct major_list block_major_list =
-{SPIN_LOCK_UNLOCKED,
-    {0xfffffb8f,  /*  Majors 0   to 31   */
-     0xffffffff,  /*  Majors 32  to 63   */
-     0xfffffffe,  /*  Majors 64  to 95   */
-     0xff03ffef,  /*  Majors 96  to 127  */
-     0x00000000,  /*  Majors 128 to 159  */
-     0x00000000,  /*  Majors 160 to 191  */
-     0x00000280,  /*  Majors 192 to 223  */
-     0xffff0000}  /*  Majors 224 to 255  */
+{SPIN_LOCK_UNLOCKED, 
+ { [  0 ...   3] = DEVFS_MAJOR_STATIC,
+   [  4 ...   6] = DEVFS_MAJOR_FREE,
+   [  7 ...   9] = DEVFS_MAJOR_STATIC,
+   [ 10 ...  10] = DEVFS_MAJOR_FREE,
+   [ 11 ...  63] = DEVFS_MAJOR_STATIC,
+   [ 64 ...  64] = DEVFS_MAJOR_FREE,
+   [ 65 ...  99] = DEVFS_MAJOR_STATIC,
+   [100 ... 100] = DEVFS_MAJOR_FREE,
+   [101 ... 113] = DEVFS_MAJOR_STATIC,
+   [114 ... 119] = DEVFS_MAJOR_FREE,
+   [120 ... 127] = DEVFS_MAJOR_STATIC,
+   [128 ... 198] = DEVFS_MAJOR_FREE,
+   [199 ... 199] = DEVFS_MAJOR_STATIC,
+   [200 ... 200] = DEVFS_MAJOR_FREE,
+   [201 ... 201] = DEVFS_MAJOR_STATIC,
+   [202 ... 239] = DEVFS_MAJOR_FREE,
+   [240 ... 255] = DEVFS_MAJOR_STATIC
+ }
 };
 
 /*  Char majors already assigned:
     0-7, 9-151, 154-158, 160-211, 216-221, 224-230, 240-255
     Total free: 19
 */
+
 static struct major_list char_major_list =
 {SPIN_LOCK_UNLOCKED,
-    {0xfffffeff,  /*  Majors 0   to 31   */
-     0xffffffff,  /*  Majors 32  to 63   */
-     0xffffffff,  /*  Majors 64  to 95   */
-     0xffffffff,  /*  Majors 96  to 127  */
-     0x7cffffff,  /*  Majors 128 to 159  */
-     0xffffffff,  /*  Majors 160 to 191  */
-     0x3f0fffff,  /*  Majors 192 to 223  */
-     0xffff007f}  /*  Majors 224 to 255  */
+ { [  0 ...   7] = DEVFS_MAJOR_STATIC,
+   [  8 ...   8] = DEVFS_MAJOR_FREE,
+   [  9 ... 151] = DEVFS_MAJOR_STATIC,
+   [152 ... 153] = DEVFS_MAJOR_FREE,
+   [154 ... 158] = DEVFS_MAJOR_STATIC,
+   [159 ... 159] = DEVFS_MAJOR_FREE,
+   [160 ... 211] = DEVFS_MAJOR_STATIC,
+   [212 ... 215] = DEVFS_MAJOR_FREE,
+   [216 ... 221] = DEVFS_MAJOR_STATIC,
+   [222 ... 223] = DEVFS_MAJOR_FREE,
+   [224 ... 230] = DEVFS_MAJOR_STATIC,
+   [231 ... 239] = DEVFS_MAJOR_FREE,
+   [240 ... 255] = DEVFS_MAJOR_STATIC
+ }
 };
 
-
 /**
  *	devfs_alloc_major - Allocate a major number.
  *	@type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK)
@@ -237,14 +256,63 @@
 
     list = (type == DEVFS_SPECIAL_CHR) ? &char_major_list : &block_major_list;
     spin_lock (&list->lock);
-    major = find_first_zero_bit (list->bits, 256);
-    if (major < 256) __set_bit (major, list->bits);
-    else major = -1;
+    for (major=0; major<256; major++)
+	    if (list->state[major] == DEVFS_MAJOR_FREE)
+		    break;
+    if (major < 256) 
+	    list->state[major] = DEVFS_MAJOR_ALLOCED;
+    else 
+	    major = -1;
     spin_unlock (&list->lock);
     return major;
 }   /*  End Function devfs_alloc_major  */
 EXPORT_SYMBOL(devfs_alloc_major);
 
+/**
+ *	__devfs_register_major - Internaly called by devfs_register_*dev
+ *	@type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK)
+ *       @major: The major number or 0 for automatic selection
+
+ *	Returns the allocated major, else -1 if none are available.
+ *	This routine is thread safe and does not block.
+ */
+
+int __devfs_register_major (int major, char type)
+{
+    struct major_list *list;
+
+    list = (type == DEVFS_SPECIAL_CHR) ? &char_major_list : &block_major_list;
+    spin_lock (&list->lock);
+    switch (major) {
+    case 0:
+	    for (major=0; (major < 256) && (list->state[major] != DEVFS_MAJOR_FREE); major++);
+	    if (major < 256) 
+		    list->state[major] = DEVFS_MAJOR_REGISTERED;
+	    else 
+		    major = -1;
+	    break;
+    default:
+	    switch (list->state[major]) {
+	    case DEVFS_MAJOR_REGISTERED:
+		    major = -1;
+		    break;
+	    case DEVFS_MAJOR_FREE:
+		    list->state[major] = DEVFS_MAJOR_REGISTERED;
+		    break;
+	    case DEVFS_MAJOR_STATIC:
+	    case DEVFS_MAJOR_ALLOCED:
+		    /* fine with this one */
+		    break;
+	    default:
+		    /* inconsistency in list->state array */
+		    spin_unlock(&list->lock);
+		    BUG();
+	    }
+    }
+    spin_unlock (&list->lock);
+    return major;
+}   /*  End Function __devfs_register_major  */
+
 
 /**
  *	devfs_dealloc_major - Deallocate a major number.
@@ -255,20 +323,55 @@
 
 void devfs_dealloc_major (char type, int major)
 {
-    int was_set;
     struct major_list *list;
 
-    if (major < 0) return;
+    if (major < 0) 
+	    return;
     list = (type == DEVFS_SPECIAL_CHR) ? &char_major_list : &block_major_list;
     spin_lock (&list->lock);
-    was_set = __test_and_clear_bit (major, list->bits);
+    if (list->state[major] != DEVFS_MAJOR_ALLOCED)
+	printk (KERN_ERR __FUNCTION__ "(): major %d was not alloced. State was: %d\n",
+		major, list->state[major]);
+    list->state[major] = DEVFS_MAJOR_FREE;
     spin_unlock (&list->lock);
-    if (!was_set)
-	printk (KERN_ERR __FUNCTION__ "(): major %d was already free\n",
-		major);
 }   /*  End Function devfs_dealloc_major  */
 EXPORT_SYMBOL(devfs_dealloc_major);
 
+/**
+ *	__devfs_unregister_major - Internaly called from devfs_unregister_*dev
+ *	@type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK)
+ *	@major: The major number.
+ *	This routine is thread safe and does not block.
+ */
+
+void __devfs_unregister_major (int major, char type)
+{
+    struct major_list *list;
+
+    if (major < 0) 
+	    return;
+    list = (type == DEVFS_SPECIAL_CHR) ? &char_major_list : &block_major_list;
+    spin_lock (&list->lock);
+    switch (list->state[major]) {
+    case DEVFS_MAJOR_FREE:
+	    printk (KERN_ERR __FUNCTION__ "(): major %d was free\n",
+		    major);
+	    break;
+    case DEVFS_MAJOR_ALLOCED:
+    case DEVFS_MAJOR_STATIC:
+	    /* major is still in use -> do not free */
+	    break;
+    case DEVFS_MAJOR_REGISTERED:
+	    list->state[major] = DEVFS_MAJOR_FREE;
+	    break;
+    default:
+	    /* inconsistency in list->state array */
+	    spin_unlock (&list->lock);
+	    BUG();
+    }
+    spin_unlock (&list->lock);
+}   /*  End Function devfs_unregister_major  */
+
 
 struct minor_list
 {
diff -ruN linux-2.4.17-sdmany/include/linux/devfs_fs_kernel.h linux-2.4.17-sdmany-devfs_fixup/include/linux/devfs_fs_kernel.h
--- linux-2.4.17-sdmany/include/linux/devfs_fs_kernel.h	Thu Dec 27 19:53:07 2001
+++ linux-2.4.17-sdmany-devfs_fixup/include/linux/devfs_fs_kernel.h	Tue Mar 12 20:48:49 2002
@@ -20,7 +20,6 @@
        (devfs_get_maj_min(devfs_get_handle_from_inode((inode)),NULL,&m)==0) \
       ) ? m : MINOR((inode)->r_dev); })
 
-
 #define DEVFS_FL_NONE           0x000 /* This helps to make code more readable
 				       */
 #define DEVFS_FL_AUTO_OWNER     0x001 /* When a closed inode is opened the
@@ -46,6 +45,10 @@
 
 typedef struct devfs_entry * devfs_handle_t;
 
+#define DEVFS_MAJOR_FREE       0
+#define DEVFS_MAJOR_STATIC     1
+#define DEVFS_MAJOR_ALLOCED    2
+#define DEVFS_MAJOR_REGISTERED 3
 
 #ifdef CONFIG_BLK_DEV_INITRD
 #  define ROOT_DEVICE_NAME ((real_root_dev ==ROOT_DEV) ? root_device_name:NULL)
@@ -115,8 +118,11 @@
 				   unsigned int flags, unsigned int major,
 				   unsigned int minor_start,
 				   umode_t mode, void *ops, void *info);
+extern void devfs_init_major_lists (void);
 extern int devfs_alloc_major (char type);
 extern void devfs_dealloc_major (char type, int major);
+extern int __devfs_register_major (int major, char type);
+extern void __devfs_unregister_major (int major, char type);
 extern kdev_t devfs_alloc_devnum (char type);
 extern void devfs_dealloc_devnum (char type, kdev_t devnum);
 extern int devfs_alloc_unique_number (struct unique_numspace *space);

             reply	other threads:[~2002-03-20 12:29 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-03-20 12:27 Carsten Otte [this message]
2002-03-25  2:28 ` Richard Gooch
  -- strict thread matches above, loose matches on Subject: below --
2002-02-21 14:48 Carsten Otte
2002-02-18 10:01 Carsten Otte
2002-02-18 17:56 ` Richard Gooch
2002-02-12 11:18 Carsten Otte
2002-02-11 13:00 Carsten Otte
2002-02-11 16:12 ` Russell King
2002-02-11 21:05   ` Anton Blanchard
2002-02-12  0:33 ` David S. Miller
2002-02-18  1:02 ` Richard Gooch

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=OF651FD06B.226CC224-ONC1256B82.0043E511@de.ibm.com \
    --to=cotte@de.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rgooch@ras.ucalgary.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®