Caleb Land wrote:
>
> Hello,
> Recently I installed Red Hat 7.1 from the SGI XFS disc (very
> nice work BTW) and when I first used the system, I had problems with
> ide-cd not loading (as others have), but after running `depmod -a
> ` everything seemed to be solved,
Hm, we still need to look into that...
> but then as I used the computer past
> 10 minutes, I noticed that if I didn't have any CDROM drives in
> use/mounted during that time, I would lose my /dev/hd[ac] entries, and
> the cdrom entries (those are my cdrom devices). I found that cron was
> unloading unused modules every 10 minutes.
Yep...
> Now, if I put something like:
>
> alias /dev/ide* /dev/ide (/dev/ide is a probeall module in
> modules.devfsd)
>
> alias /dev/cdroms* /dev/ide
>
> and
>
> alias /dev/hd* /dev/ide
>
> in my modules.conf, the ide-cd module is loaded whenever these devices
> are accessed, but for some reason, the entries in /dev/cdroms keep
> incrementing the cdromX number (IE the second time the module is
> loaded, I have cdrom2 and cdrom3)
Yep, this is a buglet. Attached is a patch from Jens to fix this
incrementing behavior. We will probably include it in the final kernel
RPMS.
This patch should fix the incrementing problem, and I think the
devfsd.conf will work as it was originally installed, but let me know if
you find holes in it, or if you think your lines above still need to be
adde.
Thanks,
-Eric
--
Eric Sandeen XFS for Linux http://oss.sgi.com/projects/xfs
sandeen@xxxxxxx SGI, Inc. diff -ur --exclude-from /home/axboe/exclude
/opt/kernel/linux-2.4.4-pre4/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- /opt/kernel/linux-2.4.4-pre4/drivers/cdrom/cdrom.c Thu Mar 29 21:56:07 2001
+++ linux/drivers/cdrom/cdrom.c Wed Apr 18 13:27:36 2001
@@ -279,6 +279,9 @@
static int lockdoor = 1;
/* will we ever get to use this... sigh. */
static int check_media_type;
+static unsigned long *cdrom_numbers;
+static DECLARE_MUTEX(cdrom_sem);
+
MODULE_PARM(debug, "i");
MODULE_PARM(autoclose, "i");
MODULE_PARM(autoeject, "i");
@@ -340,6 +343,38 @@
check_media_change: cdrom_media_changed,
};
+/*
+ * get or clear a new cdrom number, run under cdrom_sem
+ */
+static int cdrom_get_entry(void)
+{
+ int i, nr, foo;
+
+ nr = 0;
+ foo = -1;
+ for (i = 0; i < CDROM_MAX_CDROMS / (sizeof(unsigned long) * 8); i++) {
+ if (cdrom_numbers[i] == ~0UL) {
+ nr += sizeof(unsigned long) * 8;
+ continue;
+ }
+ foo = ffz(cdrom_numbers[i]);
+ set_bit(foo, &cdrom_numbers[i]);
+ nr += foo;
+ break;
+ }
+
+ return foo == -1 ? foo : nr;
+}
+
+static void cdrom_clear_entry(struct cdrom_device_info *cdi)
+{
+ int bit_nr = cdi->nr & ~(sizeof(unsigned long) * 8);
+ int cd_index = cdi->nr / (sizeof(unsigned long) * 8);
+
+ clear_bit(bit_nr, &cdrom_numbers[cd_index]);
+}
+
+
/* This macro makes sure we don't have to check on cdrom_device_ops
* existence in the run-time routines below. Change_capability is a
* hack to have the capability flags defined const, while we can still
@@ -354,7 +389,6 @@
struct cdrom_device_ops *cdo = cdi->ops;
int *change_capability = (int *)&cdo->capability; /* hack */
char vname[16];
- static unsigned int cdrom_counter;
cdinfo(CD_OPEN, "entering register_cdrom\n");
@@ -395,7 +429,17 @@
if (!devfs_handle)
devfs_handle = devfs_mk_dir (NULL, "cdroms", NULL);
- sprintf (vname, "cdrom%u", cdrom_counter++);
+
+ /*
+ * get new cdrom number
+ */
+ down(&cdrom_sem);
+ cdi->nr = cdrom_get_entry();
+ up(&cdrom_sem);
+ if (cdi->nr == -1)
+ return -ENOMEM;
+
+ sprintf(vname, "cdrom%u", cdi->nr);
if (cdi->de) {
int pos;
devfs_handle_t slave;
@@ -418,9 +462,13 @@
S_IFBLK | S_IRUGO | S_IWUGO,
&cdrom_fops, NULL);
}
- cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
+
+ down(&cdrom_sem);
cdi->next = topCdromPtr;
topCdromPtr = cdi;
+ up(&cdrom_sem);
+
+ cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
return 0;
}
#undef ENSURE
@@ -429,12 +477,14 @@
{
struct cdrom_device_info *cdi, *prev;
int major = MAJOR(unreg->dev);
+ int bit_nr, cd_index;
cdinfo(CD_OPEN, "entering unregister_cdrom\n");
if (major < 0 || major >= MAX_BLKDEV)
return -1;
+ down(&cdrom_sem);
prev = NULL;
cdi = topCdromPtr;
while (cdi != NULL && cdi->dev != unreg->dev) {
@@ -442,14 +492,20 @@
cdi = cdi->next;
}
- if (cdi == NULL)
+ if (cdi == NULL) {
+ up(&cdrom_sem);
return -2;
+ }
+
+ cdrom_clear_entry(cdi);
+
if (prev)
prev->next = cdi->next;
else
topCdromPtr = cdi->next;
+ up(&cdrom_sem);
cdi->ops->n_minors--;
- devfs_unregister (cdi->de);
+ devfs_unregister(cdi->de);
cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
return 0;
}
@@ -458,10 +514,14 @@
{
struct cdrom_device_info *cdi;
+ down(&cdrom_sem);
+
cdi = topCdromPtr;
while (cdi != NULL && cdi->dev != dev)
cdi = cdi->next;
+ up(&cdrom_sem);
+
return cdi;
}
@@ -2418,6 +2478,8 @@
}
pos = sprintf(info, "CD-ROM information, " VERSION "\n");
+
+ down(&cdrom_sem);
pos += sprintf(info+pos, "\ndrive name:\t");
for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
@@ -2487,6 +2549,8 @@
for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
+ up(&cdrom_sem);
+
strcpy(info+pos,"\n\n");
return proc_dostring(ctl, write, filp, buffer, lenp);
@@ -2633,6 +2697,10 @@
static int __init cdrom_init(void)
{
+ int n_entries = CDROM_MAX_CDROMS / (sizeof(unsigned long) * 8);
+
+ cdrom_numbers = kmalloc(n_entries * sizeof(unsigned long), GFP_KERNEL);
+
#ifdef CONFIG_SYSCTL
cdrom_sysctl_register();
#endif
@@ -2643,6 +2711,7 @@
static void __exit cdrom_exit(void)
{
printk(KERN_INFO "Uniform CD-ROM driver unloaded\n");
+ kfree(cdrom_numbers);
#ifdef CONFIG_SYSCTL
cdrom_sysctl_unregister();
#endif
diff -ur --exclude-from /home/axboe/exclude
/opt/kernel/linux-2.4.4-pre4/include/linux/cdrom.h linux/include/linux/cdrom.h
--- /opt/kernel/linux-2.4.4-pre4/include/linux/cdrom.h Wed Apr 18 14:37:43 2001
+++ linux/include/linux/cdrom.h Wed Apr 18 13:02:10 2001
@@ -577,6 +577,8 @@
struct dvd_manufact manufact;
} dvd_struct;
+#define CDROM_MAX_CDROMS 256
+
/*
* DVD authentication ioctl
*/
@@ -732,6 +734,7 @@
devfs_handle_t de; /* real driver creates this */
/* specifications */
kdev_t dev; /* device number */
+ int nr; /* cdrom entry */
int mask; /* mask of capability: disables them */
int speed; /* maximum speed for reading data */
int capacity; /* number of discs in jukebox */
|