Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 3 Nov 2008 14:23:16 +0000 (UTC)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r184592 - head/sys/netsmb
Message-ID:  <200811031423.mA3ENGoY068456@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rwatson
Date: Mon Nov  3 14:23:15 2008
New Revision: 184592
URL: http://svn.freebsd.org/changeset/base/184592

Log:
  Implement device cloning for /dev/nsmb, the netsmb control pseudo-device.
  The smb library in userspace already knows how to deal with this type of
  cloning.
  
  This also corrects a leak in which the netsmb kernel module could not be
  unloaded if device nodes had been stat'd but not open'd.
  
  Discussed with:	kib

Modified:
  head/sys/netsmb/smb_dev.c

Modified: head/sys/netsmb/smb_dev.c
==============================================================================
--- head/sys/netsmb/smb_dev.c	Mon Nov  3 14:11:06 2008	(r184591)
+++ head/sys/netsmb/smb_dev.c	Mon Nov  3 14:23:15 2008	(r184592)
@@ -89,28 +89,38 @@ int smb_dev_queue(struct smb_dev *ndp, s
 
 static struct cdevsw nsmb_cdevsw = {
 	.d_version =	D_VERSION,
-	.d_flags =	D_NEEDGIANT,
+	.d_flags =	D_NEEDGIANT | D_NEEDMINOR,
 	.d_open =	nsmb_dev_open,
 	.d_close =	nsmb_dev_close,
 	.d_ioctl =	nsmb_dev_ioctl,
 	.d_name =	NSMB_NAME
 };
 
-static eventhandler_tag nsmb_dev_tag;
+static eventhandler_tag	 nsmb_dev_tag;
+static struct clonedevs	*nsmb_clones;
 
 static void
 nsmb_dev_clone(void *arg, struct ucred *cred, char *name, int namelen,
     struct cdev **dev)
 {
-	int u;
+	int i, u;
 
 	if (*dev != NULL)
 		return;
-	if (dev_stdclone(name, NULL, NSMB_NAME, &u) != 1)
+
+	if (strcmp(name, NSMB_NAME) == 0)
+		u = -1;
+	else if (dev_stdclone(name, NULL, NSMB_NAME, &u) != 1)
 		return;
-	*dev = make_dev(&nsmb_cdevsw, u, 0, 0, 0600,
-	    NSMB_NAME"%d", u);
-	dev_ref(*dev);
+	i = clone_create(&nsmb_clones, &nsmb_cdevsw, &u, dev, 0);
+	if (i) {
+		*dev = make_dev(&nsmb_cdevsw, u, UID_ROOT, GID_WHEEL, 0600,
+		    "%s%d", NSMB_NAME, u);
+		if (*dev != NULL) {
+			dev_ref(*dev);
+			(*dev)->si_flags |= SI_CHEAPCLONE;
+		}
+	}
 }
 
 static int
@@ -340,6 +350,7 @@ nsmb_dev_load(module_t mod, int cmd, voi
 			smb_sm_done();
 			break;
 		}
+		clone_setup(&nsmb_clones);
 		nsmb_dev_tag = EVENTHANDLER_REGISTER(dev_clone, nsmb_dev_clone, 0, 1000);
 		printf("netsmb_dev: loaded\n");
 		break;
@@ -350,6 +361,7 @@ nsmb_dev_load(module_t mod, int cmd, voi
 			break;
 		EVENTHANDLER_DEREGISTER(dev_clone, nsmb_dev_tag);
 		drain_dev_clone_events();
+		clone_cleanup(&nsmb_clones);
 		destroy_dev_drain(&nsmb_cdevsw);
 		printf("netsmb_dev: unloaded\n");
 		break;



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