svn commit: r250236 - in head: contrib/smbfs/lib/smb contrib/smbfs/mount_smbfs sys/fs/smbfs sys/netsmb

Davide Italiano davide at FreeBSD.org
Sat May 4 14:03:20 UTC 2013


Author: davide
Date: Sat May  4 14:03:18 2013
New Revision: 250236
URL: http://svnweb.freebsd.org/changeset/base/250236

Log:
  Completely rewrite the interface to smbdev switching from dev_clone
  to cdevpriv(9). This commit changes the semantic of mount_smbfs
  in userland as well, which now passes file descriptor in order to
  to mount a specific filesystem istance.
  
  Reviewed by:	attilio, ed
  Tested by:	martymac

Modified:
  head/contrib/smbfs/lib/smb/ctx.c
  head/contrib/smbfs/mount_smbfs/mount_smbfs.c
  head/sys/fs/smbfs/smbfs.h
  head/sys/fs/smbfs/smbfs_vfsops.c
  head/sys/netsmb/smb_dev.c
  head/sys/netsmb/smb_dev.h

Modified: head/contrib/smbfs/lib/smb/ctx.c
==============================================================================
--- head/contrib/smbfs/lib/smb/ctx.c	Sat May  4 14:00:16 2013	(r250235)
+++ head/contrib/smbfs/lib/smb/ctx.c	Sat May  4 14:03:18 2013	(r250236)
@@ -602,40 +602,12 @@ smb_ctx_gethandle(struct smb_ctx *ctx)
 	int fd, i;
 	char buf[20];
 
-	/*
-	 * First, try to open as cloned device
-	 */
 	fd = open("/dev/"NSMB_NAME, O_RDWR);
 	if (fd >= 0) {
 		ctx->ct_fd = fd;
 		return 0;
 	}
-	/*
-	 * well, no clone capabilities available - we have to scan
-	 * all devices in order to get free one
-	 */
-	 for (i = 0; i < 1024; i++) {
-	         snprintf(buf, sizeof(buf), "/dev/%s%d", NSMB_NAME, i);
-		 fd = open(buf, O_RDWR);
-		 if (fd >= 0) {
-			ctx->ct_fd = fd;
-			return 0;
-		 }
-	 }
-	 /*
-	  * This is a compatibility with old /dev/net/nsmb device
-	  */
-	 for (i = 0; i < 1024; i++) {
-	         snprintf(buf, sizeof(buf), "/dev/net/%s%d", NSMB_NAME, i);
-		 fd = open(buf, O_RDWR);
-		 if (fd >= 0) {
-			ctx->ct_fd = fd;
-			return 0;
-		 }
-		 if (errno == ENOENT)
-		         return ENOENT;
-	 }
-	 return ENOENT;
+	return ENOENT;
 }
 
 int

Modified: head/contrib/smbfs/mount_smbfs/mount_smbfs.c
==============================================================================
--- head/contrib/smbfs/mount_smbfs/mount_smbfs.c	Sat May  4 14:00:16 2013	(r250235)
+++ head/contrib/smbfs/mount_smbfs/mount_smbfs.c	Sat May  4 14:03:18 2013	(r250236)
@@ -82,7 +82,7 @@ main(int argc, char *argv[])
 	struct xvfsconf vfc;
 #endif
 	char *next;
-	int opt, error, mntflags, caseopt, dev;
+	int opt, error, mntflags, caseopt, fd;
 	uid_t uid;
 	gid_t gid;
 	mode_t dir_mode, file_mode;
@@ -90,7 +90,7 @@ main(int argc, char *argv[])
 
 	iov = NULL;
 	iovlen = 0;
-	dev = 0;
+	fd = 0;
 	uid = (uid_t)-1;
 	gid = (gid_t)-1;
 	caseopt = 0;
@@ -266,11 +266,11 @@ main(int argc, char *argv[])
 		exit(1);
 	}
 
-	dev = ctx->ct_fd;
+	fd = ctx->ct_fd;
 
 	build_iovec(&iov, &iovlen, "fstype", strdup("smbfs"), -1);
 	build_iovec(&iov, &iovlen, "fspath", mount_point, -1);
-	build_iovec_argf(&iov, &iovlen, "dev", "%d", dev);
+	build_iovec_argf(&iov, &iovlen, "fd", "%d", fd);
 	build_iovec(&iov, &iovlen, "mountpoint", mount_point, -1);
 	build_iovec_argf(&iov, &iovlen, "uid", "%d", uid);
 	build_iovec_argf(&iov, &iovlen, "gid", "%d", gid);

Modified: head/sys/fs/smbfs/smbfs.h
==============================================================================
--- head/sys/fs/smbfs/smbfs.h	Sat May  4 14:00:16 2013	(r250235)
+++ head/sys/fs/smbfs/smbfs.h	Sat May  4 14:03:18 2013	(r250236)
@@ -75,6 +75,7 @@ struct smbmount {
 	mode_t 			sm_dir_mode;
 	struct mount * 		sm_mp;
 	struct smbnode *	sm_root;
+	struct smb_dev *	sm_dev;
 	struct ucred *		sm_owner;
 	uint64_t		sm_flags;
 	long			sm_nextino;

Modified: head/sys/fs/smbfs/smbfs_vfsops.c
==============================================================================
--- head/sys/fs/smbfs/smbfs_vfsops.c	Sat May  4 14:00:16 2013	(r250235)
+++ head/sys/fs/smbfs/smbfs_vfsops.c	Sat May  4 14:03:18 2013	(r250236)
@@ -122,7 +122,7 @@ smbfs_cmount(struct mntarg *ma, void * d
 }
 
 static const char *smbfs_opts[] = {
-	"dev", "soft", "intr", "strong", "have_nls", "long",
+	"fd", "soft", "intr", "strong", "have_nls", "long",
 	"mountpoint", "rootpath", "uid", "gid", "file_mode", "dir_mode",
 	"caseopt", "errmsg", NULL
 };
@@ -135,10 +135,12 @@ smbfs_mount(struct mount *mp)
 	struct smb_share *ssp = NULL;
 	struct vnode *vp;
 	struct thread *td;
+	struct smb_dev *dev;
 	struct smb_cred *scred;
 	int error, v;
 	char *pc, *pe;
 
+	dev = NULL;
 	td = curthread;
 	if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS))
 		return EOPNOTSUPP;
@@ -150,26 +152,29 @@ smbfs_mount(struct mount *mp)
 
 	scred = smbfs_malloc_scred();
 	smb_makescred(scred, td, td->td_ucred);
-	if (1 != vfs_scanopt(mp->mnt_optnew, "dev", "%d", &v)) {
-		vfs_mount_error(mp, "No dev option");
+	
+	/* Ask userspace of `fd`, the file descriptor of this session */
+	if (1 != vfs_scanopt(mp->mnt_optnew, "fd", "%d", &v)) {
+		vfs_mount_error(mp, "No fd option");
 		smbfs_free_scred(scred);
 		return (EINVAL);
 	}
-	error = smb_dev2share(v, SMBM_EXEC, scred, &ssp);
+	error = smb_dev2share(v, SMBM_EXEC, scred, &ssp, &dev);
+	smp = malloc(sizeof(*smp), M_SMBFSDATA, M_WAITOK | M_ZERO);
 	if (error) {
 		printf("invalid device handle %d (%d)\n", v, error);
-		vfs_mount_error(mp, "invalid device handle %d (%d)\n", v, error);
+		vfs_mount_error(mp, "invalid device handle %d %d\n", v, error);
 		smbfs_free_scred(scred);
+		free(smp, M_SMBFSDATA);
 		return error;
 	}
 	vcp = SSTOVC(ssp);
 	smb_share_unlock(ssp, 0);
 	mp->mnt_stat.f_iosize = SSTOVC(ssp)->vc_txmax;
-
-	smp = malloc(sizeof(*smp), M_SMBFSDATA, M_WAITOK | M_ZERO);
-        mp->mnt_data = smp;
+	mp->mnt_data = smp;
 	smp->sm_share = ssp;
 	smp->sm_root = NULL;
+	smp->sm_dev = dev;
 	if (1 != vfs_scanopt(mp->mnt_optnew,
 	    "caseopt", "%d", &smp->sm_caseopt)) {
 		vfs_mount_error(mp, "Invalid caseopt");
@@ -238,8 +243,15 @@ smbfs_mount(struct mount *mp)
 bad:
 	if (ssp)
 		smb_share_put(ssp, scred);
-	smbfs_free_scred(scred);
-        return error;
+	smbfs_free_scred(scred);	
+	SMB_LOCK();
+	if (error && smp->sm_dev == dev) {
+		smp->sm_dev = NULL;
+		sdp_trydestroy(dev);
+	}
+	SMB_UNLOCK();
+	free(smp, M_SMBFSDATA);
+	return error;
 }
 
 /* Unmount the filesystem described by mp. */
@@ -249,6 +261,7 @@ smbfs_unmount(struct mount *mp, int mntf
 	struct thread *td;
 	struct smbmount *smp = VFSTOSMBFS(mp);
 	struct smb_cred *scred;
+	struct smb_dev *dev;
 	int error, flags;
 
 	SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
@@ -277,7 +290,13 @@ smbfs_unmount(struct mount *mp, int mntf
 	if (error)
 		goto out;
 	smb_share_put(smp->sm_share, scred);
+	SMB_LOCK();
+	dev = smp->sm_dev;
+	if (!dev)
+		panic("No private data for mount point");
+	sdp_trydestroy(dev);
 	mp->mnt_data = NULL;
+	SMB_UNLOCK();
 	free(smp, M_SMBFSDATA);
 	MNT_ILOCK(mp);
 	mp->mnt_flag &= ~MNT_LOCAL;

Modified: head/sys/netsmb/smb_dev.c
==============================================================================
--- head/sys/netsmb/smb_dev.c	Sat May  4 14:00:16 2013	(r250235)
+++ head/sys/netsmb/smb_dev.c	Sat May  4 14:03:18 2013	(r250236)
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/capability.h>
 #include <sys/module.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
@@ -55,20 +56,16 @@ __FBSDID("$FreeBSD$");
 #include <netsmb/smb_subr.h>
 #include <netsmb/smb_dev.h>
 
-#define SMB_GETDEV(dev)		((struct smb_dev*)(dev)->si_drv1)
-#define	SMB_CHECKMINOR(dev)	do { \
-				    sdp = SMB_GETDEV(dev); \
-				    if (sdp == NULL) return ENXIO; \
-				} while(0)
+static struct cdev *nsmb_dev;
 
 static d_open_t	 nsmb_dev_open;
-static d_close_t nsmb_dev_close;
 static d_ioctl_t nsmb_dev_ioctl;
 
 MODULE_DEPEND(netsmb, libiconv, 1, 1, 2);
 MODULE_VERSION(netsmb, NSMB_VERSION);
 
 static int smb_version = NSMB_VERSION;
+struct sx smb_lock;
 
 
 SYSCTL_DECL(_net_smb);
@@ -76,110 +73,97 @@ SYSCTL_INT(_net_smb, OID_AUTO, version, 
 
 static MALLOC_DEFINE(M_NSMBDEV, "NETSMBDEV", "NET/SMB device");
 
-
-/*
-int smb_dev_queue(struct smb_dev *ndp, struct smb_rq *rqp, int prio);
-*/
-
 static struct cdevsw nsmb_cdevsw = {
 	.d_version =	D_VERSION,
-	.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 struct clonedevs	*nsmb_clones;
-
-static void
-nsmb_dev_clone(void *arg, struct ucred *cred, char *name, int namelen,
-    struct cdev **dev)
+static int
+nsmb_dev_init(void)
 {
-	int i, u;
 
-	if (*dev != NULL)
-		return;
+	nsmb_dev = make_dev(&nsmb_cdevsw, 0, UID_ROOT, GID_OPERATOR,
+	    0600, "nsmb");
+	if (nsmb_dev == NULL)
+		return (ENOMEM);  
+	return (0);
+}
 
-	if (strcmp(name, NSMB_NAME) == 0)
-		u = -1;
-	else if (dev_stdclone(name, NULL, NSMB_NAME, &u) != 1)
-		return;
-	i = clone_create(&nsmb_clones, &nsmb_cdevsw, &u, dev, 0);
-	if (i)
-		*dev = make_dev_credf(MAKEDEV_REF, &nsmb_cdevsw, u, cred,
-		    UID_ROOT, GID_WHEEL, 0600, "%s%d", NSMB_NAME, u);
+static void 
+nsmb_dev_destroy(void)
+{
+
+	MPASS(nsmb_dev != NULL);
+	destroy_dev(nsmb_dev);
+	nsmb_dev = NULL;
 }
 
-static int
-nsmb_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+static struct smb_dev *
+smbdev_alloc(struct cdev *dev)
 {
 	struct smb_dev *sdp;
-	struct ucred *cred = td->td_ucred;
-	int s;
 
-	sdp = SMB_GETDEV(dev);
-	if (sdp && (sdp->sd_flags & NSMBFL_OPEN))
-		return EBUSY;
-	if (sdp == NULL) {
-		sdp = malloc(sizeof(*sdp), M_NSMBDEV, M_WAITOK);
-		dev->si_drv1 = (void*)sdp;
-	}
-	/*
-	 * XXX: this is just crazy - make a device for an already passed device...
-	 * someone should take care of it.
-	 */
-	if ((dev->si_flags & SI_NAMED) == 0)
-		make_dev(&nsmb_cdevsw, dev2unit(dev), cred->cr_uid,
-		    cred->cr_gid, 0700, NSMB_NAME"%d", dev2unit(dev));
-	bzero(sdp, sizeof(*sdp));
-/*
-	STAILQ_INIT(&sdp->sd_rqlist);
-	STAILQ_INIT(&sdp->sd_rplist);
-	bzero(&sdp->sd_pollinfo, sizeof(struct selinfo));
-*/
-	s = splimp();
+	sdp = malloc(sizeof(struct smb_dev), M_NSMBDEV, M_WAITOK | M_ZERO);
+	sdp->dev = dev;	
 	sdp->sd_level = -1;
 	sdp->sd_flags |= NSMBFL_OPEN;
-	splx(s);
-	return 0;
+	sdp->refcount = 1;
+	return (sdp);	
+} 
+
+void
+sdp_dtor(void *arg)
+{
+	struct smb_dev *dev;
+
+	dev = (struct smb_dev *)arg;	
+	SMB_LOCK();
+	sdp_trydestroy(dev);
+	SMB_UNLOCK();
 }
 
 static int
-nsmb_dev_close(struct cdev *dev, int flag, int fmt, struct thread *td)
+nsmb_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
 {
 	struct smb_dev *sdp;
+	int error;
+
+	sdp = smbdev_alloc(dev);
+	error = devfs_set_cdevpriv(sdp, sdp_dtor);
+	if (error) {
+		free(sdp, M_NSMBDEV);	
+		return (error);
+	}
+	return (0);
+}
+
+void
+sdp_trydestroy(struct smb_dev *sdp)
+{
 	struct smb_vc *vcp;
 	struct smb_share *ssp;
 	struct smb_cred *scred;
-	int s;
 
+	SMB_LOCKASSERT();
+	if (!sdp)
+		panic("No smb_dev upon device close");
+	MPASS(sdp->refcount > 0);
+	sdp->refcount--;
+	if (sdp->refcount) 
+		return;
 	scred = malloc(sizeof(struct smb_cred), M_NSMBDEV, M_WAITOK);
-	SMB_CHECKMINOR(dev);
-	s = splimp();
-	if ((sdp->sd_flags & NSMBFL_OPEN) == 0) {
-		splx(s);
-		free(scred, M_NSMBDEV);
-		return EBADF;
-	}
-	smb_makescred(scred, td, NULL);
+	smb_makescred(scred, curthread, NULL);
 	ssp = sdp->sd_share;
 	if (ssp != NULL)
 		smb_share_rele(ssp, scred);
 	vcp = sdp->sd_vc;
 	if (vcp != NULL)
 		smb_vc_rele(vcp, scred);
-/*
-	smb_flushq(&sdp->sd_rqlist);
-	smb_flushq(&sdp->sd_rplist);
-*/
-	dev->si_drv1 = NULL;
-	free(sdp, M_NSMBDEV);
-	destroy_dev_sched(dev);
-	splx(s);
 	free(scred, M_NSMBDEV);
-	return 0;
+	free(sdp, M_NSMBDEV);
+	return;
 }
 
 
@@ -192,11 +176,11 @@ nsmb_dev_ioctl(struct cdev *dev, u_long 
 	struct smb_cred *scred;
 	int error = 0;
 
-	SMB_CHECKMINOR(dev);
-	if ((sdp->sd_flags & NSMBFL_OPEN) == 0)
-		return EBADF;
-
+	error = devfs_get_cdevpriv((void **)&sdp);
+	if (error)
+		return (error);
 	scred = malloc(sizeof(struct smb_cred), M_NSMBDEV, M_WAITOK);
+	SMB_LOCK();
 	smb_makescred(scred, td, NULL);
 	switch (cmd) {
 	    case SMBIOC_OPENSESSION:
@@ -345,6 +329,7 @@ nsmb_dev_ioctl(struct cdev *dev, u_long 
 	}
 out:
 	free(scred, M_NSMBDEV);
+	SMB_UNLOCK();
 	return error;
 }
 
@@ -363,18 +348,18 @@ 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);
+		error = nsmb_dev_init();
+		if (error)
+			break;
+		sx_init(&smb_lock, "samba device lock");
 		break;
 	    case MOD_UNLOAD:
 		smb_iod_done();
 		error = smb_sm_done();
 		if (error)
 			break;
-		EVENTHANDLER_DEREGISTER(dev_clone, nsmb_dev_tag);
-		drain_dev_clone_events();
-		clone_cleanup(&nsmb_clones);
-		destroy_dev_drain(&nsmb_cdevsw);
+		nsmb_dev_destroy();
+		sx_destroy(&smb_lock);
 		break;
 	    default:
 		error = EINVAL;
@@ -385,58 +370,40 @@ nsmb_dev_load(module_t mod, int cmd, voi
 
 DEV_MODULE (dev_netsmb, nsmb_dev_load, 0);
 
-/*
- * Convert a file descriptor to appropriate smb_share pointer
- */
-static struct file*
-nsmb_getfp(struct filedesc* fdp, int fd, int flag)
-{
-	struct file* fp;
-
-	FILEDESC_SLOCK(fdp);
-	if ((fp = fget_locked(fdp, fd)) == NULL || (fp->f_flag & flag) == 0) {
-		FILEDESC_SUNLOCK(fdp);
-		return (NULL);
-	}
-	fhold(fp);
-	FILEDESC_SUNLOCK(fdp);
-	return (fp);
-}
-
 int
 smb_dev2share(int fd, int mode, struct smb_cred *scred,
-	struct smb_share **sspp)
+	struct smb_share **sspp, struct smb_dev **ssdp)
 {
-	struct file *fp;
-	struct vnode *vp;
+	struct file *fp, *fptmp;
 	struct smb_dev *sdp;
 	struct smb_share *ssp;
-	struct cdev *dev;
+	struct thread *td;
 	int error;
 
-	fp = nsmb_getfp(scred->scr_td->td_proc->p_fd, fd, FREAD | FWRITE);
-	if (fp == NULL)
-		return EBADF;
-	vp = fp->f_vnode;
-	if (vp == NULL) {
-		fdrop(fp, curthread);
-		return EBADF;
-	}
-	if (vp->v_type != VCHR) {
-		fdrop(fp, curthread);
-		return EBADF;
-	}
-	dev = vp->v_rdev;
-	SMB_CHECKMINOR(dev);
+	td = curthread;
+	error = fget(td, fd, CAP_READ, &fp);
+	if (error)
+		return (error);
+	fptmp = td->td_fpop;
+	td->td_fpop = fp;
+	error = devfs_get_cdevpriv((void **)&sdp);
+	td->td_fpop = fptmp;
+	fdrop(fp, td);
+	if (error || sdp == NULL)
+		return (error);
+	SMB_LOCK();
+	*ssdp = sdp;
 	ssp = sdp->sd_share;
 	if (ssp == NULL) {
-		fdrop(fp, curthread);
-		return ENOTCONN;
+		SMB_UNLOCK();
+		return (ENOTCONN);
 	}
 	error = smb_share_get(ssp, LK_EXCLUSIVE, scred);
-	if (error == 0) 
+	if (error == 0) {
+		sdp->refcount++;
 		*sspp = ssp;
-	fdrop(fp, curthread);
+	}
+	SMB_UNLOCK();
 	return error;
 }
 

Modified: head/sys/netsmb/smb_dev.h
==============================================================================
--- head/sys/netsmb/smb_dev.h	Sat May  4 14:00:16 2013	(r250235)
+++ head/sys/netsmb/smb_dev.h	Sat May  4 14:03:18 2013	(r250236)
@@ -155,22 +155,28 @@ struct smbioc_rw {
 STAILQ_HEAD(smbrqh, smb_rq);
 
 struct smb_dev {
+	struct cdev *	dev;
 	int		sd_opened;
 	int		sd_level;
 	struct smb_vc * sd_vc;		/* reference to VC */
 	struct smb_share *sd_share;	/* reference to share if any */
 	int		sd_poll;
 	int		sd_seq;
-/*	struct ifqueue	sd_rdqueue;
-	struct ifqueue	sd_wrqueue;
-	struct selinfo	sd_pollinfo;
-	struct smbrqh	sd_rqlist;
-	struct smbrqh	sd_rplist;
-	struct ucred 	*sd_owner;*/
 	int		sd_flags;
+	int		refcount;
+	int		usecount;
 };
 
+extern struct sx smb_lock;
+#define	SMB_LOCK()		sx_xlock(&smb_lock)
+#define	SMB_UNLOCK() 		sx_unlock(&smb_lock)
+#define	SMB_LOCKASSERT()	sx_assert(&smb_lock, SA_XLOCKED)
+
 struct smb_cred;
+
+void sdp_dtor(void *arg);
+void sdp_trydestroy(struct smb_dev *dev);
+
 /*
  * Compound user interface
  */
@@ -185,7 +191,7 @@ int  smb_usr_simplerequest(struct smb_sh
 int  smb_usr_t2request(struct smb_share *ssp, struct smbioc_t2rq *data,
 	struct smb_cred *scred);
 int  smb_dev2share(int fd, int mode, struct smb_cred *scred,
-	struct smb_share **sspp);
+	struct smb_share **sspp, struct smb_dev **ssdp);
 
 
 #endif /* _KERNEL */


More information about the svn-src-all mailing list