From owner-freebsd-current@FreeBSD.ORG Fri Mar 4 07:41:44 2005 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 26BEA16A4CF for ; Fri, 4 Mar 2005 07:41:44 +0000 (GMT) Received: from critter.freebsd.dk (f170.freebsd.dk [212.242.86.170]) by mx1.FreeBSD.org (Postfix) with ESMTP id 667FD43D31 for ; Fri, 4 Mar 2005 07:41:43 +0000 (GMT) (envelope-from phk@critter.freebsd.dk) Received: from critter.freebsd.dk (localhost [127.0.0.1]) by critter.freebsd.dk (8.13.1/8.13.1) with ESMTP id j247fXbD014920; Fri, 4 Mar 2005 08:41:33 +0100 (CET) (envelope-from phk@critter.freebsd.dk) To: Andrew Gallatin From: "Poul-Henning Kamp" In-Reply-To: Your message of "Thu, 03 Mar 2005 18:01:17 EST." <16935.38717.96802.616769@grasshopper.cs.duke.edu> Date: Fri, 04 Mar 2005 08:41:33 +0100 Message-ID: <14919.1109922093@critter.freebsd.dk> Sender: phk@critter.freebsd.dk cc: freebsd-current@freebsd.org Subject: Re: panic: dev ... is on clonelist X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 Mar 2005 07:41:44 -0000 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.