panic: dev ... is on clonelist

From: Andrew Gallatin <gallatin_at_cs.duke.edu>
Date: Thu, 3 Mar 2005 18:01:17 -0500 (EST)
Hi,

I've got a character driver which I'd like to make behave as much like
a linux cloning driver as possible because I'm maintaining linux
binary compat.  I'm using the cloning interface in 5.x and 6.0.

My driver *seems* to work fine in 5.4, even with INVARIANTS.  But in
6.0, I'm dying with: "dev 0xc2f89c00 (mx_fake.1) is on clonelist".
>From the si_drv{1,2} fields, it looks like the cdev was closed.
Did something change between 5.x and 6.0?  Or am I doing something
that's bogus in 5.x and I'm just getting lucky?

What I want is to have a unique cdev generated for each open
of the device.  Then I would like to use the si_drv1 and
si_drv2 fields of the cdev to hang per-open information from.

So, if the user opens /dev/mx0, then I'd like a unique cdev generated.
And if somebody else opens /dev/mx0, then I'd like a second unique cdev
generated.

What I've been doing (and what seemed to work in 5.x) was this:

- Don't make any /dev/mx devices at all, use clone handler for all
  device creation.

- Use dev_stdclone() in to get the "real" unit number (0 from /dev/mx0,
  1 from /dev/mx1, etc, where the unit corresponds to a physical
  device).

- Prepare a "fake" device for the user, so that every open
  has a unique cdev.   To do this,  I have been calling
  clone_create() with a "fake" unit number (starting at 0,
  and increasing) until I find either a free "fake" cdev, or
  a "fake" cdev which does not exist.  By free, I make
  a cdev whose si_drv1 indicates he's free.  By "fake",
  I mean I don't care what the unit number is.

- if the "fake" cdev does not exist, create a /dev/mx_fake.%d,
  using the "fake" unit number via make_dev()

- using the cdev obtained from either clone_create(), or make_dev(),
  set (*cdev)->si_drv1 to the "real" unit number so my open
  routine knows what to do.


Any idea what I'm doing wrong?

Thanks for the help,

Drew



static void
mx_clone(void *arg, char *name, int namelen, struct cdev **cdev)
{
  int u, i, privileged, mode, fake_unit, free_cdev;

  if (*cdev != NULL) {
    /*    printf("mx_clone called with non-null struct cdev *??\n");*/
    return;
  }
  if (dev_stdclone(name, NULL, "mxp", &u)) {
    privileged = 1;
    mode = 0600;
  } else if (dev_stdclone(name, NULL, "mx", &u)) {
    privileged = 0;
    mode = 0666;    
  } else {/* Don't recognize the name */
    return;
  }
  if (u >= mx_num_instances)
    return; /* unit too large */

  if (privileged && suser(curthread))
    return; /* EPERM */


  /* Now we iterate over our clone list.  We start at index 0, and
     keep going until we find a free clone.  We know the clone is free
     because either the cdev is null (in which case it was never
     allocated, and no /dev/mx_fake.%d entry exists) or the cdev is
     non-null, and its si_drv1 field is null (which means that it has
     been closed by another process, and a /dev/mx_fake.%d exists).

     Its important to find priviliged devices, so we always search
     only odd units when we want a priviliged device.
  */
     
  fake_unit = 0 + privileged;

  do {
    i = clone_create(&mx_clones, &mx_cdevsw, &fake_unit, cdev, 0);
    free_cdev = i || ((*cdev)->si_drv1 == NULL);
#if 1
    printf("dev: %d. i: %d", fake_unit, i);
    if (i == 0)
      printf(" drv1: %p", (*cdev)->si_drv1);
    else
      printf(" drv1: NULL");
    printf(" Free = %d\n", free_cdev);
#endif
    if (!free_cdev)
      fake_unit+=2;
  } while (!free_cdev);

  if (i) {
    /* need to allocate a new /dev/mx_fake.%d device node */
    *cdev = make_dev(&mx_cdevsw, unit2minor(fake_unit), 
	      UID_ROOT, GID_WHEEL, 
			    mode, "mx_fake.%d", fake_unit);
  }
  if (*cdev != NULL) {
    /* Treat si_drv1 like a bitfield.  Low bit is "in use" flag,
       second bit is privileged bit, remainder is the real unit that 
       the opener requested */
    mx_always_assert((*cdev)->si_drv1 == NULL);
    (*cdev)->si_drv1 = (void *)(uintptr_t)(1 | (privileged << 1) | (u << 2));
    (*cdev)->si_drv2 = NULL;
  }
}
Received on Thu Mar 03 2005 - 22:01:23 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:29 UTC