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);
next 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®