Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 May 2011 20:10:12 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r222268 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201105242010.p4OKACI1083993@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: pjd
Date: Tue May 24 20:10:12 2011
New Revision: 222268
URL: http://svn.freebsd.org/changeset/base/222268

Log:
  Don't pass pointer to name buffer which is on the stack to another thread,
  because the stack might be paged out once the other thread tries to use the
  data. Instead, just allocate memory.
  
  MFC after:	2 weeks

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c	Tue May 24 20:07:15 2011	(r222267)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c	Tue May 24 20:10:12 2011	(r222268)
@@ -239,15 +239,20 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, zn
 			return (ENOENT);
 		}
 		if (dl == NULL)	{
+			size_t namesize;
+
 			/*
 			 * Allocate a new dirlock and add it to the list.
 			 */
-			dl = kmem_alloc(sizeof (zfs_dirlock_t), KM_SLEEP);
+			namesize = strlen(name) + 1;
+			dl = kmem_alloc(sizeof (zfs_dirlock_t) + namesize,
+			    KM_SLEEP);
 			cv_init(&dl->dl_cv, NULL, CV_DEFAULT, NULL);
-			dl->dl_name = name;
+			dl->dl_name = (char *)(dl + 1);
+			bcopy(name, dl->dl_name, namesize);
 			dl->dl_sharecnt = 0;
 			dl->dl_namelock = 0;
-			dl->dl_namesize = 0;
+			dl->dl_namesize = namesize;
 			dl->dl_dzp = dzp;
 			dl->dl_next = dzp->z_dirlocks;
 			dzp->z_dirlocks = dl;
@@ -264,20 +269,8 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, zn
 	if (flag & ZHAVELOCK)
 		dl->dl_namelock = 1;
 
-	if ((flag & ZSHARED) && ++dl->dl_sharecnt > 1 && dl->dl_namesize == 0) {
-		/*
-		 * We're the second shared reference to dl.  Make a copy of
-		 * dl_name in case the first thread goes away before we do.
-		 * Note that we initialize the new name before storing its
-		 * pointer into dl_name, because the first thread may load
-		 * dl->dl_name at any time.  He'll either see the old value,
-		 * which is his, or the new shared copy; either is OK.
-		 */
-		dl->dl_namesize = strlen(dl->dl_name) + 1;
-		name = kmem_alloc(dl->dl_namesize, KM_SLEEP);
-		bcopy(dl->dl_name, name, dl->dl_namesize);
-		dl->dl_name = name;
-	}
+	if (flag & ZSHARED)
+		dl->dl_sharecnt++;
 
 	mutex_exit(&dzp->z_lock);
 
@@ -361,10 +354,8 @@ zfs_dirent_unlock(zfs_dirlock_t *dl)
 	cv_broadcast(&dl->dl_cv);
 	mutex_exit(&dzp->z_lock);
 
-	if (dl->dl_namesize != 0)
-		kmem_free(dl->dl_name, dl->dl_namesize);
 	cv_destroy(&dl->dl_cv);
-	kmem_free(dl, sizeof (*dl));
+	kmem_free(dl, sizeof (*dl) + dl->dl_namesize);
 }
 
 /*



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