[vbox-dev] [PATCH] performance improvements for Solaris guest shared folders

Life is hard, and then you die ronald at innovation.ch
Sun Jan 16 10:50:06 GMT 2011


Attached are some patches to improve the performance of shared-folders
in Solaris guests. Together they speed up things between 2 to 4 times:
operations like untarring and deleting whole directory tree are
typically 2 to 2.5 times faster, and when running builds that include
things like building Solaris packages I see a speedup of 3 to almost 4.
The bulk of the speedup comes from the second (file open) patch.

These patches assume my previously sent patches have been applied.

Licensed under MIT/public-domain.


  Cheers,

  Ronald

-------------- next part --------------

Consolidated separate volinfo calls into one, thereby both simplifying the
code and making the statvfs call several times faster.

diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
index d76ba0f..e58c85d 100644
--- a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
+++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
@@ -183,7 +183,7 @@ sfprov_unmount(sfp_mount_t *mnt)
  * query information about a mounted file system
  */
 int
-sfprov_get_blksize(sfp_mount_t *mnt, uint64_t *blksize)
+sfprov_get_fsinfo(sfp_mount_t *mnt, sffs_fsinfo_t *fsinfo)
 {
 	int rc;
 	SHFLVOLINFO info;
@@ -193,69 +193,15 @@ sfprov_get_blksize(sfp_mount_t *mnt, uint64_t *blksize)
 	    (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (SHFLDIRINFO *)&info);
 	if (RT_FAILURE(rc))
 		return (EINVAL);
-	*blksize = info.ulBytesPerAllocationUnit;
-	return (0);
-}
 
-int
-sfprov_get_blksused(sfp_mount_t *mnt, uint64_t *blksused)
-{
-	int rc;
-	SHFLVOLINFO info;
-	uint32_t bytes = sizeof(SHFLVOLINFO);
-
-	rc = vboxCallFSInfo(&vbox_client, &mnt->map, 0,
-	    (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (SHFLDIRINFO *)&info);
-	if (RT_FAILURE(rc))
-		return (EINVAL);
-	*blksused = (info.ullTotalAllocationBytes -
+	fsinfo->blksize = info.ulBytesPerAllocationUnit;
+	fsinfo->blksused = (info.ullTotalAllocationBytes -
 	    info.ullAvailableAllocationBytes) / info.ulBytesPerAllocationUnit;
-	return (0);
-}
-
-int
-sfprov_get_blksavail(sfp_mount_t *mnt, uint64_t *blksavail)
-{
-	int rc;
-	SHFLVOLINFO info;
-	uint32_t bytes = sizeof(SHFLVOLINFO);
-
-	rc = vboxCallFSInfo(&vbox_client, &mnt->map, 0,
-	    (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (SHFLDIRINFO *)&info);
-	if (RT_FAILURE(rc))
-		return (EINVAL);
-	*blksavail =
+	fsinfo->blksavail =
 	    info.ullAvailableAllocationBytes / info.ulBytesPerAllocationUnit;
-	return (0);
-}
+	fsinfo->maxnamesize = info.fsProperties.cbMaxComponent;
+	fsinfo->readonly = info.fsProperties.fReadOnly;
 
-int
-sfprov_get_maxnamesize(sfp_mount_t *mnt, uint32_t *maxnamesize)
-{
-	int rc;
-	SHFLVOLINFO info;
-	uint32_t bytes = sizeof(SHFLVOLINFO);
-
-	rc = vboxCallFSInfo(&vbox_client, &mnt->map, 0,
-	    (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (SHFLDIRINFO *)&info);
-	if (RT_FAILURE(rc))
-		return (EINVAL);
-	*maxnamesize = info.fsProperties.cbMaxComponent;
-	return (0);
-}
-
-int
-sfprov_get_readonly(sfp_mount_t *mnt, uint32_t *readonly)
-{
-	int rc;
-	SHFLVOLINFO info;
-	uint32_t bytes = sizeof(SHFLVOLINFO);
-
-	rc = vboxCallFSInfo(&vbox_client, &mnt->map, 0,
-	    (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (SHFLDIRINFO *)&info);
-	if (RT_FAILURE(rc))
-		return (EINVAL);
-	*readonly = info.fsProperties.fReadOnly;
 	return (0);
 }
 
diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h
index 7b917d8..0092faa 100644
--- a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h
+++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h
@@ -71,11 +71,15 @@ extern int sfprov_unmount(sfp_mount_t *);
 /*
  * query information about a mounted file system
  */
-extern int sfprov_get_blksize(sfp_mount_t *, uint64_t *);
-extern int sfprov_get_blksused(sfp_mount_t *, uint64_t *);
-extern int sfprov_get_blksavail(sfp_mount_t *, uint64_t *);
-extern int sfprov_get_maxnamesize(sfp_mount_t *, uint32_t *);
-extern int sfprov_get_readonly(sfp_mount_t *, uint32_t *);
+typedef struct sffs_fsinfo {
+	uint64_t blksize;
+	uint64_t blksused;
+	uint64_t blksavail;
+	uint32_t maxnamesize;
+	uint32_t readonly;
+} sffs_fsinfo_t;
+
+extern int sfprov_get_fsinfo(sfp_mount_t *, sffs_fsinfo_t *);
 
 /*
  * File operations: open/close/read/write/etc.
diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c
index 198131c..fedaa34 100644
--- a/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c
+++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c
@@ -472,47 +472,36 @@ static int
 sffs_statvfs(vfs_t *vfsp, statvfs64_t *sbp)
 {
 	sffs_data_t *sffs = (sffs_data_t *)vfsp->vfs_data;
-	uint64_t x;
-	uint32_t u;
+	sffs_fsinfo_t fsinfo;
 	dev32_t d32;
 	int error;
 
 	bzero(sbp, sizeof(*sbp));
-	error = sfprov_get_blksize(sffs->sf_handle, &x);
+	error = sfprov_get_fsinfo(sffs->sf_handle, &fsinfo);
 	if (error != 0)
 		return (error);
-	sbp->f_bsize = x;
-	sbp->f_frsize = x;
 
-	error = sfprov_get_blksavail(sffs->sf_handle, &x);
-	if (error != 0)
-		return (error);
-	sbp->f_bfree = x;
-	sbp->f_bavail = x;
-	sbp->f_files = x / 4;	/* some kind of reasonable value */
-	sbp->f_ffree = x / 4;
-	sbp->f_favail = x / 4;
+	sbp->f_bsize = fsinfo.blksize;
+	sbp->f_frsize = fsinfo.blksize;
 
-	error = sfprov_get_blksused(sffs->sf_handle, &x);
-	if (error != 0)
-		return (error);
-	sbp->f_blocks = x + sbp->f_bavail;
+	sbp->f_bfree = fsinfo.blksavail;
+	sbp->f_bavail = fsinfo.blksavail;
+	sbp->f_files = fsinfo.blksavail / 4; /* some kind of reasonable value */
+	sbp->f_ffree = fsinfo.blksavail / 4;
+	sbp->f_favail = fsinfo.blksavail / 4;
+
+	sbp->f_blocks = fsinfo.blksused + sbp->f_bavail;
 
 	(void) cmpldev(&d32, vfsp->vfs_dev);
 	sbp->f_fsid = d32;
 	strcpy(&sbp->f_basetype[0], "sffs");
 	sbp->f_flag |= ST_NOSUID;
 
-	error = sfprov_get_readonly(sffs->sf_handle, &u);
-	if (error != 0)
-		return (error);
-	if (u)
+	if (fsinfo.readonly)
 		sbp->f_flag |= ST_RDONLY;
 
-	error = sfprov_get_maxnamesize(sffs->sf_handle, &u);
-	if (error != 0)
-		return (error);
-	sbp->f_namemax = u;
+	sbp->f_namemax = fsinfo.maxnamesize;
+
 	return (0);
 }
 
-------------- next part --------------

Don't open the underlying file unless really requested.
    
Opening the underlying file is somewhat expensive, and not necessary when
doing things like reading directories or getting attributes. By only opening
it when necessary we can speed up directory operations, including things like
recursive deletes, substantially.

diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c
index e5a33d2..0118db3 100644
--- a/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c
+++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c
@@ -207,7 +207,6 @@ sfnode_get_vnode(sfnode_t *node)
 		vp->v_data = node;
 		node->sf_vnode = vp;
 	}
-	sfnode_open(node);
 	return (node->sf_vnode);
 }
 
@@ -1854,7 +1853,19 @@ sffs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
 static int
 sffs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
 {
-	return (0);
+	sfnode_t *node;
+	int error = 0;
+
+	mutex_enter(&sffs_lock);
+
+	node = VN2SFN(*vpp);
+	sfnode_open(node);
+	if (node->sf_file == NULL)
+		error = EINVAL;
+
+	mutex_exit(&sffs_lock);
+
+	return (error);
 }
 
 /*
@@ -1888,6 +1899,11 @@ sffs_close(
 
 	sfnode_invalidate_stat_cache(node);
 
+	if (node->sf_file != NULL && vp->v_count <= 1) {
+		(void)sfprov_close(node->sf_file);
+		node->sf_file = NULL;
+	}
+
 	mutex_exit(&sffs_lock);
 	return (0);
 }
-------------- next part --------------

Factored out mode-to-fmode conversion and grouped conversion routines at
top of file. No functional changes.

diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
index e58c85d..ba1b21c 100644
--- a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
+++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
@@ -206,6 +206,114 @@ sfprov_get_fsinfo(sfp_mount_t *mnt, sffs_fsinfo_t *fsinfo)
 }
 
 /*
+ * file/directory information conversions.
+ */
+static void
+sfprov_fmode_from_mode(RTFMODE *fMode, mode_t mode)
+{
+	RTFMODE m = 0;
+
+#define mode_set(r) ((mode & (S_##r)) ? RTFS_UNIX_##r : 0)
+	m  = mode_set (ISUID);
+	m |= mode_set (ISGID);
+	m |= (mode & S_ISVTX) ? RTFS_UNIX_ISTXT : 0;
+	m |= mode_set (IRUSR);
+	m |= mode_set (IWUSR);
+	m |= mode_set (IXUSR);
+	m |= mode_set (IRGRP);
+	m |= mode_set (IWGRP);
+	m |= mode_set (IXGRP);
+	m |= mode_set (IROTH);
+	m |= mode_set (IWOTH);
+	m |= mode_set (IXOTH);
+
+	if (S_ISDIR(mode))
+		m |= RTFS_TYPE_DIRECTORY;
+	else if (S_ISREG(mode))
+		m |= RTFS_TYPE_FILE;
+	else if (S_ISFIFO(mode))
+		m |= RTFS_TYPE_FIFO;
+	else if (S_ISCHR(mode))
+		m |= RTFS_TYPE_DEV_CHAR;
+	else if (S_ISBLK(mode))
+		m |= RTFS_TYPE_DEV_BLOCK;
+	else if (S_ISLNK(mode))
+		m |= RTFS_TYPE_SYMLINK;
+	else if (S_ISSOCK(mode))
+		m |= RTFS_TYPE_SOCKET;
+	else
+		m |= RTFS_TYPE_FILE;
+
+	*fMode = m;
+}
+
+static void
+sfprov_mode_from_fmode(mode_t *mode, RTFMODE fMode)
+{
+	mode_t m = 0;
+
+	if (RTFS_IS_DIRECTORY(fMode))
+		m |= S_IFDIR;
+	else if (RTFS_IS_FILE(fMode))
+		m |= S_IFREG;
+	else if (RTFS_IS_FIFO(fMode))
+		m |= S_IFIFO;
+	else if (RTFS_IS_DEV_CHAR(fMode))
+		m |= S_IFCHR;
+	else if (RTFS_IS_DEV_BLOCK(fMode))
+		m |= S_IFBLK;
+	else if (RTFS_IS_SYMLINK(fMode))
+		m |= S_IFLNK;
+	else if (RTFS_IS_SOCKET(fMode))
+		m |= S_IFSOCK;
+
+	if (fMode & RTFS_UNIX_IRUSR)
+		m |= S_IRUSR;
+	if (fMode & RTFS_UNIX_IWUSR)
+		m |= S_IWUSR;
+	if (fMode & RTFS_UNIX_IXUSR)
+		m |= S_IXUSR;
+	if (fMode & RTFS_UNIX_IRGRP)
+		m |= S_IRGRP;
+	if (fMode & RTFS_UNIX_IWGRP)
+		m |= S_IWGRP;
+	if (fMode & RTFS_UNIX_IXGRP)
+		m |= S_IXGRP;
+	if (fMode & RTFS_UNIX_IROTH)
+		m |= S_IROTH;
+	if (fMode & RTFS_UNIX_IWOTH)
+		m |= S_IWOTH;
+	if (fMode & RTFS_UNIX_IXOTH)
+		m |= S_IXOTH;
+	if (fMode & RTFS_UNIX_ISUID)
+		m |= S_ISUID;
+	if (fMode & RTFS_UNIX_ISGID)
+		m |= S_ISGID;
+	if (fMode & RTFS_UNIX_ISTXT)
+		m |= S_ISVTX;
+	*mode = m;
+}
+
+static void
+sfprov_ftime_from_timespec(timestruc_t *time, RTTIMESPEC *ts)
+{
+	uint64_t nanosec = RTTimeSpecGetNano(ts);
+	time->tv_sec = nanosec / UINT64_C(1000000000);
+	time->tv_nsec = nanosec % UINT64_C(1000000000);
+}
+
+static void
+sfprov_stat_from_info(sffs_stat_t *stat, SHFLFSOBJINFO *info)
+{
+	sfprov_mode_from_fmode(&stat->sf_mode, info->Attr.fMode);
+	stat->sf_size = info->cbObject;
+	stat->sf_alloc = info->cbAllocated;
+	sfprov_ftime_from_timespec(&stat->sf_atime, &info->AccessTime);
+	sfprov_ftime_from_timespec(&stat->sf_mtime, &info->ModificationTime);
+	sfprov_ftime_from_timespec(&stat->sf_ctime, &info->ChangeTime);
+}
+
+/*
  * File operations: open/close/read/write/etc.
  *
  * open/create can return any relevant errno, however ENOENT
@@ -398,56 +506,6 @@ sfprov_getinfo(sfp_mount_t *mnt, char *path, PSHFLFSOBJINFO info)
 /*
  * get information about a file (or directory)
  */
-static void
-sfprov_mode_from_fmode(mode_t *mode, RTFMODE fMode)
-{
-	mode_t m = 0;
-
-	if (RTFS_IS_DIRECTORY(fMode))
-		m |= S_IFDIR;
-	else if (RTFS_IS_FILE(fMode))
-		m |= S_IFREG;
-	else if (RTFS_IS_FIFO(fMode))
-		m |= S_IFIFO;
-	else if (RTFS_IS_DEV_CHAR(fMode))
-		m |= S_IFCHR;
-	else if (RTFS_IS_DEV_BLOCK(fMode))
-		m |= S_IFBLK;
-	else if (RTFS_IS_SYMLINK(fMode))
-		m |= S_IFLNK;
-	else if (RTFS_IS_SOCKET(fMode))
-		m |= S_IFSOCK;
-
-	if (fMode & RTFS_UNIX_IRUSR)
-		m |= S_IRUSR;
-	if (fMode & RTFS_UNIX_IWUSR)
-		m |= S_IWUSR;
-	if (fMode & RTFS_UNIX_IXUSR)
-		m |= S_IXUSR;
-	if (fMode & RTFS_UNIX_IRGRP)
-		m |= S_IRGRP;
-	if (fMode & RTFS_UNIX_IWGRP)
-		m |= S_IWGRP;
-	if (fMode & RTFS_UNIX_IXGRP)
-		m |= S_IXGRP;
-	if (fMode & RTFS_UNIX_IROTH)
-		m |= S_IROTH;
-	if (fMode & RTFS_UNIX_IWOTH)
-		m |= S_IWOTH;
-	if (fMode & RTFS_UNIX_IXOTH)
-		m |= S_IXOTH;
-	if (fMode & RTFS_UNIX_ISUID)
-		m |= S_ISUID;
-	if (fMode & RTFS_UNIX_ISGID)
-		m |= S_ISGID;
-	if (fMode & RTFS_UNIX_ISTXT)
-		m |= S_ISVTX;
-	*mode = m;
-}
-
-/*
- * get information about a file (or directory)
- */
 int
 sfprov_get_mode(sfp_mount_t *mnt, char *path, mode_t *mode)
 {
@@ -474,25 +532,6 @@ sfprov_get_size(sfp_mount_t *mnt, char *path, uint64_t *size)
 	return (0);
 }
 
-static void
-sfprov_ftime_from_timespec(timestruc_t *time, RTTIMESPEC *ts)
-{
-	uint64_t nanosec = RTTimeSpecGetNano(ts);
-	time->tv_sec = nanosec / UINT64_C(1000000000);
-	time->tv_nsec = nanosec % UINT64_C(1000000000);
-}
-
-static void
-sfprov_stat_from_info(sffs_stat_t *stat, SHFLFSOBJINFO *info)
-{
-	sfprov_mode_from_fmode(&stat->sf_mode, info->Attr.fMode);
-	stat->sf_size = info->cbObject;
-	stat->sf_alloc = info->cbAllocated;
-	sfprov_ftime_from_timespec(&stat->sf_atime, &info->AccessTime);
-	sfprov_ftime_from_timespec(&stat->sf_mtime, &info->ModificationTime);
-	sfprov_ftime_from_timespec(&stat->sf_ctime, &info->ChangeTime);
-}
-
 int
 sfprov_get_atime(sfp_mount_t *mnt, char *path, timestruc_t *time)
 {
@@ -592,40 +631,8 @@ sfprov_set_attr(
 	}
 
 	RT_ZERO(info);
-	if (mask & AT_MODE) {
-#define mode_set(r) ((mode & (S_##r)) ? RTFS_UNIX_##r : 0)
-
-		info.Attr.fMode  = mode_set (ISUID);
-		info.Attr.fMode |= mode_set (ISGID);
-		info.Attr.fMode |= (mode & S_ISVTX) ? RTFS_UNIX_ISTXT : 0;
-		info.Attr.fMode |= mode_set (IRUSR);
-		info.Attr.fMode |= mode_set (IWUSR);
-		info.Attr.fMode |= mode_set (IXUSR);
-		info.Attr.fMode |= mode_set (IRGRP);
-		info.Attr.fMode |= mode_set (IWGRP);
-		info.Attr.fMode |= mode_set (IXGRP);
-		info.Attr.fMode |= mode_set (IROTH);
-		info.Attr.fMode |= mode_set (IWOTH);
-		info.Attr.fMode |= mode_set (IXOTH);
-
-		if (S_ISDIR(mode))
-			info.Attr.fMode |= RTFS_TYPE_DIRECTORY;
-		else if (S_ISREG(mode))
-			info.Attr.fMode |= RTFS_TYPE_FILE;
-		else if (S_ISFIFO(mode))
-			info.Attr.fMode |= RTFS_TYPE_FIFO;
-		else if (S_ISCHR(mode))
-			info.Attr.fMode |= RTFS_TYPE_DEV_CHAR;
-		else if (S_ISBLK(mode))
-			info.Attr.fMode |= RTFS_TYPE_DEV_BLOCK;
-		else if (S_ISLNK(mode))
-			info.Attr.fMode |= RTFS_TYPE_SYMLINK;
-		else if (S_ISSOCK(mode))
-			info.Attr.fMode |= RTFS_TYPE_SOCKET;
-		else
-			info.Attr.fMode |= RTFS_TYPE_FILE;
-	}
-
+	if (mask & AT_MODE)
+		sfprov_fmode_from_mode(&info.Attr.fMode, mode);
 	if (mask & AT_ATIME)
 		sfprov_timespec_from_ftime(&info.AccessTime, atime);
 	if (mask & AT_MTIME)
-------------- next part --------------

Pass file/dir mode directly to create/mkdir call instead of using a separate
set_attr call, and cache the returned stats.

diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
index ba1b21c..85a7248 100644
--- a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
+++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
@@ -325,7 +325,12 @@ struct sfp_file {
 };
 
 int
-sfprov_create(sfp_mount_t *mnt, char *path, sfp_file_t **fp)
+sfprov_create(
+	sfp_mount_t *mnt,
+	char *path,
+	mode_t mode,
+	sfp_file_t **fp,
+	sffs_stat_t *stat)
 {
 
 	int rc;
@@ -335,8 +340,9 @@ sfprov_create(sfp_mount_t *mnt, char *path, sfp_file_t **fp)
 	sfp_file_t *newfp;
 
 	str = sfprov_string(path, &size);
-	parms.Handle = 0;
+	parms.Handle = SHFL_HANDLE_NIL;
 	parms.Info.cbObject = 0;
+	sfprov_fmode_from_mode(&parms.Info.Attr.fMode, mode);
 	parms.CreateFlags = SHFL_CF_ACT_CREATE_IF_NEW |
 	    SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACCESS_READWRITE;
 	rc = vboxCallCreate(&vbox_client, &mnt->map, str, &parms);
@@ -357,6 +363,7 @@ sfprov_create(sfp_mount_t *mnt, char *path, sfp_file_t **fp)
 	newfp->handle = parms.Handle;
 	newfp->map = mnt->map;
 	*fp = newfp;
+	sfprov_stat_from_info(stat, &parms.Info);
 	return (0);
 }
 
@@ -725,7 +732,12 @@ fail2:
  * Directory operations
  */
 int
-sfprov_mkdir(sfp_mount_t *mnt, char *path, sfp_file_t **fp)
+sfprov_mkdir(
+	sfp_mount_t *mnt,
+	char *path,
+	mode_t mode,
+	sfp_file_t **fp,
+	sffs_stat_t *stat)
 {
 	int rc;
 	SHFLCREATEPARMS parms;
@@ -734,8 +746,9 @@ sfprov_mkdir(sfp_mount_t *mnt, char *path, sfp_file_t **fp)
 	sfp_file_t *newfp;
 
 	str = sfprov_string(path, &size);
-	parms.Handle = 0;
+	parms.Handle = SHFL_HANDLE_NIL;
 	parms.Info.cbObject = 0;
+	sfprov_fmode_from_mode(&parms.Info.Attr.fMode, mode);
 	parms.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_CREATE_IF_NEW |
 	    SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACCESS_READ;
 	rc = vboxCallCreate(&vbox_client, &mnt->map, str, &parms);
@@ -752,6 +765,7 @@ sfprov_mkdir(sfp_mount_t *mnt, char *path, sfp_file_t **fp)
 	newfp->handle = parms.Handle;
 	newfp->map = mnt->map;
 	*fp = newfp;
+	sfprov_stat_from_info(stat, &parms.Info);
 	return (0);
 }
 
diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h
index 0092faa..623cd45 100644
--- a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h
+++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h
@@ -87,9 +87,19 @@ extern int sfprov_get_fsinfo(sfp_mount_t *, sffs_fsinfo_t *);
  * open/create can return any relevant errno, however ENOENT
  * generally means that the host file didn't exist.
  */
+typedef struct sffs_stat {
+	mode_t		sf_mode;
+	off_t		sf_size;
+	off_t		sf_alloc;
+	timestruc_t	sf_atime;
+	timestruc_t	sf_mtime;
+	timestruc_t	sf_ctime;
+} sffs_stat_t;
+
 typedef struct sfp_file sfp_file_t;
 
-extern int sfprov_create(sfp_mount_t *, char *path, sfp_file_t **fp);
+extern int sfprov_create(sfp_mount_t *, char *path, mode_t mode,
+    sfp_file_t **fp, sffs_stat_t *stat);
 extern int sfprov_open(sfp_mount_t *, char *path, sfp_file_t **fp);
 extern int sfprov_close(sfp_file_t *fp);
 extern int sfprov_read(sfp_file_t *, char * buffer, uint64_t offset,
@@ -102,15 +112,6 @@ extern int sfprov_fsync(sfp_file_t *fp);
 /*
  * get/set information about a file (or directory) using pathname
  */
-typedef struct sffs_stat {
-	mode_t		sf_mode;
-	off_t		sf_size;
-	off_t		sf_alloc;
-	timestruc_t	sf_atime;
-	timestruc_t	sf_mtime;
-	timestruc_t	sf_ctime;
-} sffs_stat_t;
-
 extern int sfprov_get_mode(sfp_mount_t *, char *, mode_t *);
 extern int sfprov_get_size(sfp_mount_t *, char *, uint64_t *);
 extern int sfprov_get_atime(sfp_mount_t *, char *, timestruc_t *);
@@ -127,7 +128,8 @@ extern int sfprov_set_size(sfp_mount_t *, char *, uint64_t);
  */
 extern int sfprov_trunc(sfp_mount_t *, char *);
 extern int sfprov_remove(sfp_mount_t *, char *path, uint_t is_link);
-extern int sfprov_mkdir(sfp_mount_t *, char *path, sfp_file_t **fp);
+extern int sfprov_mkdir(sfp_mount_t *, char *path, mode_t mode,
+    sfp_file_t **fp, sffs_stat_t *stat);
 extern int sfprov_rmdir(sfp_mount_t *, char *path);
 extern int sfprov_rename(sfp_mount_t *, char *from, char *to, uint_t is_dir);
 
diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c
index 0118db3..0469a82 100644
--- a/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c
+++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c
@@ -527,6 +527,7 @@ sfnode_lookup(
 	sfnode_t *dir,
 	char *name,
 	vtype_t create,
+	mode_t c_mode,
 	sffs_stat_t *stat,
 	uint64_t stat_time,
 	int *err)
@@ -579,10 +580,16 @@ sfnode_lookup(
 	 */
 	if (create == VREG) {
 		type = VREG;
-		error = sfprov_create(dir->sf_sffs->sf_handle, fullpath, &fp);
+		stat = &tmp_stat;
+		error = sfprov_create(dir->sf_sffs->sf_handle, fullpath, c_mode,
+		    &fp, stat);
+		stat_time = sfnode_cur_time_usec();
 	} else if (create == VDIR) {
 		type = VDIR;
-		error = sfprov_mkdir(dir->sf_sffs->sf_handle, fullpath, &fp);
+		stat = &tmp_stat;
+		error = sfprov_mkdir(dir->sf_sffs->sf_handle, fullpath, c_mode,
+		    &fp, stat);
+		stat_time = sfnode_cur_time_usec();
 	} else {
 		mode_t m;
 		fp = NULL;
@@ -778,7 +785,7 @@ sffs_readdir(
 				node = dir;
 		} else {
 			node = sfnode_lookup(dir, dirent->sf_entry.d_name, VNON,
-			    &dirent->sf_stat, sfnode_cur_time_usec(), NULL);
+			    0, &dirent->sf_stat, sfnode_cur_time_usec(), NULL);
 			if (node == NULL)
 				panic("sffs_readdir() lookup failed");
 		}
@@ -1195,7 +1202,7 @@ sffs_lookup(
 	/*
 	 * Lookup the node.
 	 */
-	node = sfnode_lookup(VN2SFN(dvp), name, VNON, NULL, 0, NULL);
+	node = sfnode_lookup(VN2SFN(dvp), name, VNON, 0, NULL, 0, NULL);
 	if (node != NULL)
 		*vpp = sfnode_get_vnode(node);
 	mutex_exit(&sffs_lock);
@@ -1290,7 +1297,7 @@ sffs_create(
 	 * Create a new node. First check for a race creating it.
 	 */
 	mutex_enter(&sffs_lock);
-	node = sfnode_lookup(VN2SFN(dvp), name, VNON, NULL, 0, NULL);
+	node = sfnode_lookup(VN2SFN(dvp), name, VNON, 0, NULL, 0, NULL);
 	if (node != NULL) {
 		mutex_exit(&sffs_lock);
 		return (EEXIST);
@@ -1301,15 +1308,8 @@ sffs_create(
 	 */
 	sfnode_invalidate_stat_cache(VN2SFN(dvp));
 	int lookuperr;
-	node = sfnode_lookup(VN2SFN(dvp), name, VREG, NULL, 0, &lookuperr);
-	if (node && (vap->va_mask & AT_MODE)) {
-		timestruc_t dummy;
-		error = sfprov_set_attr(node->sf_sffs->sf_handle, node->sf_path,
-		    AT_MODE, vap->va_mode, dummy, dummy, dummy);
-		if (error)
-			cmn_err(CE_WARN, "sffs_create: set_mode(%s, %o) failed"
-			    " rc=%d", node->sf_path, vap->va_mode, error);
-	}
+	node = sfnode_lookup(VN2SFN(dvp), name, VREG,
+	    (vap->va_mask & AT_MODE) ? vap->va_mode : 0, NULL, 0, &lookuperr);
 
 	if (node && node->sf_parent)
 		sfnode_clear_dir_list(node->sf_parent);
@@ -1368,15 +1368,8 @@ sffs_mkdir(
 
 	sfnode_invalidate_stat_cache(VN2SFN(dvp));
 	int lookuperr = EACCES;
-	node = sfnode_lookup(VN2SFN(dvp), nm, VDIR, NULL, 0, &lookuperr);
-	if (node && (va->va_mask & AT_MODE)) {
-		timestruc_t dummy;
-		error = sfprov_set_attr(node->sf_sffs->sf_handle, node->sf_path,
-		    AT_MODE, va->va_mode, dummy, dummy, dummy);
-		if (error)
-			cmn_err(CE_WARN, "sffs_mkdir: set_mode(%s, %o) failed"
-			    " rc=%d", node->sf_path, va->va_mode, error);
-	}
+	node = sfnode_lookup(VN2SFN(dvp), nm, VDIR,
+	    (va->va_mask & AT_MODE) ? va->va_mode : 0, NULL, 0, &lookuperr);
 
 	if (node && node->sf_parent)
 		sfnode_clear_dir_list(node->sf_parent);
@@ -1549,7 +1542,8 @@ sffs_symlink(
 
 	mutex_enter(&sffs_lock);
 
-	if (sfnode_lookup(VN2SFN(dvp), linkname, VNON, NULL, 0, NULL) != NULL) {
+	if (sfnode_lookup(VN2SFN(dvp), linkname, VNON, 0, NULL, 0, NULL) !=
+	    NULL) {
 		error = EEXIST;
 		goto done;
 	}
@@ -1570,8 +1564,8 @@ sffs_symlink(
 	if (error)
 		goto done;
 
-	node = sfnode_lookup(dir, linkname, VLNK, &stat, sfnode_cur_time_usec(),
-	    NULL);
+	node = sfnode_lookup(dir, linkname, VLNK, 0, &stat,
+	    sfnode_cur_time_usec(), NULL);
 
 	sfnode_invalidate_stat_cache(dir);
 	sfnode_clear_dir_list(dir);
@@ -1606,7 +1600,8 @@ sfnode_resolve_link(sfnode_t *node, int *err)
 		}
 
 		ASSERT(node->sf_parent != NULL);
-		node = sfnode_lookup(node->sf_parent, target, VNON, NULL, 0, err);
+		node = sfnode_lookup(node->sf_parent, target, VNON, 0, NULL, 0,
+		    err);
 		if (node == NULL)
 			goto done;
 	}
@@ -1715,7 +1710,7 @@ sffs_rename(
 	if (error)
 		goto done;
 
-	node = sfnode_lookup(VN2SFN(old_dir), old_nm, VNON, NULL, 0, NULL);
+	node = sfnode_lookup(VN2SFN(old_dir), old_nm, VNON, 0, NULL, 0, NULL);
 	if (node == NULL) {
 		error = ENOENT;
 		goto done;


More information about the vbox-dev mailing list