Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 04 Mar 2005 08:41:33 +0100
From:      "Poul-Henning Kamp" <phk@phk.freebsd.dk>
To:        Andrew Gallatin <gallatin@cs.duke.edu>
Cc:        freebsd-current@freebsd.org
Subject:   Re: panic: dev ... is on clonelist 
Message-ID:  <14919.1109922093@critter.freebsd.dk>
In-Reply-To: Your message of "Thu, 03 Mar 2005 18:01:17 EST." <16935.38717.96802.616769@grasshopper.cs.duke.edu> 

next in thread | previous in thread | raw e-mail | index | archive | help

A lot have changed from RELENG_5 to -current.

I'm a bit hung up this weekend, but if you mail your driver to me
I will take a look as soon as I can.

Poul-Henning

n message <16935.38717.96802.616769@grasshopper.cs.duke.edu>, Andrew Gallatin writes:
>
>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;
>  }
>}
>
>
>
>_______________________________________________
>freebsd-current@freebsd.org mailing list
>http://lists.freebsd.org/mailman/listinfo/freebsd-current
>To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.org"
>

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe    
Never attribute to malice what can adequately be explained by incompetence.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?14919.1109922093>