diff options
Diffstat (limited to 'open-vm-tools/modules')
147 files changed, 2802 insertions, 15219 deletions
diff --git a/open-vm-tools/modules/Makefile.in b/open-vm-tools/modules/Makefile.in new file mode 100644 index 00000000..9c594ec2 --- /dev/null +++ b/open-vm-tools/modules/Makefile.in @@ -0,0 +1,550 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules +DIST_COMMON = $(am__include_HEADERS_DIST) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/vmtools.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +am__include_HEADERS_DIST = $(top_srcdir)/lib/include/vmci_sockets.h +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(includedir)" +includeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(include_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_PLUGIN_INSTALLDIR = @COMMON_PLUGIN_INSTALLDIR@ +COMMON_XLIBS = @COMMON_XLIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CUNIT_CPPFLAGS = @CUNIT_CPPFLAGS@ +CUNIT_LIBS = @CUNIT_LIBS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DNET_CPPFLAGS = @DNET_CPPFLAGS@ +DNET_LIBS = @DNET_LIBS@ +DOT = @DOT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FUSE_CPPFLAGS = @FUSE_CPPFLAGS@ +FUSE_LIBS = @FUSE_LIBS@ +GLIB2_CPPFLAGS = @GLIB2_CPPFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMODULE_CPPFLAGS = @GMODULE_CPPFLAGS@ +GMODULE_LIBS = @GMODULE_LIBS@ +GOBJECT_CPPFLAGS = @GOBJECT_CPPFLAGS@ +GOBJECT_LIBS = @GOBJECT_LIBS@ +GREP = @GREP@ +GTHREAD_CPPFLAGS = @GTHREAD_CPPFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKMM_CPPFLAGS = @GTKMM_CPPFLAGS@ +GTKMM_LIBS = @GTKMM_LIBS@ +GTK_CPPFLAGS = @GTK_CPPFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_DOT = @HAVE_DOT@ +HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@ +HGFS_LIBS = @HGFS_LIBS@ +ICU_CPPFLAGS = @ICU_CPPFLAGS@ +ICU_LIBS = @ICU_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTVMSG = @INSTVMSG@ +KERNEL_RELEASE = @KERNEL_RELEASE@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVMTOOLS_LIBADD = @LIBVMTOOLS_LIBADD@ +LIB_AUTH_CPPFLAGS = @LIB_AUTH_CPPFLAGS@ +LIB_IMPERSONATE_CPPFLAGS = @LIB_IMPERSONATE_CPPFLAGS@ +LIB_USER_CPPFLAGS = @LIB_USER_CPPFLAGS@ +LINUXINCLUDE = @LINUXINCLUDE@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MODULES = @MODULES@ +MODULES_DIR = @MODULES_DIR@ +MODULES_OS = @MODULES_OS@ +MSCGEN = @MSCGEN@ +MSCGEN_DIR = @MSCGEN_DIR@ +MSPACK_CPPFLAGS = @MSPACK_CPPFLAGS@ +MSPACK_LIBS = @MSPACK_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAM_CPPFLAGS = @PAM_CPPFLAGS@ +PAM_LIBS = @PAM_LIBS@ +PAM_PREFIX = @PAM_PREFIX@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PLUGIN_CPPFLAGS = @PLUGIN_CPPFLAGS@ +PLUGIN_LDFLAGS = @PLUGIN_LDFLAGS@ +PROCPS_CPPFLAGS = @PROCPS_CPPFLAGS@ +PROCPS_LIBS = @PROCPS_LIBS@ +RANLIB = @RANLIB@ +RPCGEN = @RPCGEN@ +RPCGENFLAGS = @RPCGENFLAGS@ +RPCGEN_WRAPPER = @RPCGEN_WRAPPER@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CPPFLAGS = @SSL_CPPFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +SYSDIR = @SYSDIR@ +TARGET_OS = @TARGET_OS@ +TEST_PLUGIN_INSTALLDIR = @TEST_PLUGIN_INSTALLDIR@ +TOOLS_VERSION = @TOOLS_VERSION@ +VERSION = @VERSION@ +VGAUTH_LIBADD = @VGAUTH_LIBADD@ +VIX_LIBADD = @VIX_LIBADD@ +VMSVC_PLUGIN_INSTALLDIR = @VMSVC_PLUGIN_INSTALLDIR@ +VMTOOLS_CPPFLAGS = @VMTOOLS_CPPFLAGS@ +VMTOOLS_LIBS = @VMTOOLS_LIBS@ +VMUSR_PLUGIN_INSTALLDIR = @VMUSR_PLUGIN_INSTALLDIR@ +XCOMPOSITE_LIBS = @XCOMPOSITE_LIBS@ +XDR_LIBS = @XDR_LIBS@ +XERCES_CPPFLAGS = @XERCES_CPPFLAGS@ +XERCES_LIBS = @XERCES_LIBS@ +XMKMF = @XMKMF@ +XMLSECURITY_CPPFLAGS = @XMLSECURITY_CPPFLAGS@ +XMLSECURITY_LIBS = @XMLSECURITY_LIBS@ +XSM_LIBS = @XSM_LIBS@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_vmw_lib_cfg = @ac_vmw_lib_cfg@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +have_cxx = @have_cxx@ +have_doxygen = @have_doxygen@ +have_genmarshal = @have_genmarshal@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +modulesrc = $(abs_top_srcdir)/modules +@FREEBSD_CUSTOM_SYSDIR_TRUE@EXTRA_ARGS = "SYSDIR=@SYSDIR@" +# Solaris does not have Kbuild-like system so we need to supply +# compiler and linker and other items discovered by configure +# script. +@SOLARIS_TRUE@EXTRA_ARGS = "CC=$(CC)" "CC_WARNINGS=$(CC_WARNINGS)" \ +@SOLARIS_TRUE@ "GLOBAL_DEFS=$(GLOBAL_DEFS)" "LD=$(LD)" \ +@SOLARIS_TRUE@ "HAVE_GNU_LD=$(HAVE_GNU_LD)" +@LINUX_TRUE@include_HEADERS = $(top_srcdir)/lib/include/vmci_sockets.h +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu modules/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu modules/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ + $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ + rm -f "$(DESTDIR)$(includedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-includeHEADERS + +install-dvi: install-dvi-am + +install-exec-am: + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-includeHEADERS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook + +.MAKE: install-am install-exec-am install-strip uninstall-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-local ctags distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-hook install-html install-html-am \ + install-includeHEADERS install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-hook \ + uninstall-includeHEADERS + +all: modules + +.PHONY: modules $(MODULES) +modules: $(MODULES) + +$(MODULES): + $(MAKE) VM_UNAME=$(KERNEL_RELEASE) MV=mv RM=rm \ + OVT_SOURCE_DIR=$(abs_top_srcdir) \ + MODULEBUILDDIR=$(modulesrc)/$(MODULES_OS) \ + $(EXTRA_ARGS) -C "$(modulesrc)/$(MODULES_OS)/$@" + +@LINUX_TRUE@export LINUXINCLUDE := @LINUXINCLUDE@ +@LINUX_TRUE@export vmblockdir := $(MODULES_DIR)/fs/vmblock +@LINUX_TRUE@export vmcidir := $(MODULES_DIR)/drivers/misc +@LINUX_TRUE@export vmhgfsdir := $(MODULES_DIR)/fs/vmhgfs +@LINUX_TRUE@export vmsyncdir := $(MODULES_DIR)/drivers/misc +@LINUX_TRUE@export vmxnetdir := $(MODULES_DIR)/drivers/net +@LINUX_TRUE@export vsockdir := $(MODULES_DIR)/net/vsock +@LINUX_TRUE@@WITH_ROOT_PRIVILEGES_TRUE@export DEPMOD := depmod -a $(KERNEL_RELEASE) + +@SOLARIS_TRUE@export vmhgfsdir := $(MODULES_DIR) + +clean-local: + for MOD in $(MODULES); do \ + if [ -d "$(modulesrc)/$(MODULES_OS)/$$MOD" ]; then \ + $(MAKE) VM_UNAME=$(KERNEL_RELEASE) MV=mv RM=rm \ + -C "$(modulesrc)/$(MODULES_OS)/$$MOD" clean || exit 1; \ + fi \ + done + rm -f $(modulesrc)/$(MODULES_OS)/*.o $(modulesrc)/$(MODULES_OS)/*.ko + rm -f $(modulesrc)/$(MODULES_OS)/VMwareVMCIModule.symvers + +install-exec-hook: +@SOLARIS_TRUE@ for MOD in $(MODULES); do \ +@SOLARIS_TRUE@ $(MAKE) VM_UNAME=$(KERNEL_RELEASE) MV=mv RM=rm \ +@SOLARIS_TRUE@ -C "$(modulesrc)/$(MODULES_OS)/$$MOD" install || exit 1; \ +@SOLARIS_TRUE@ done +@FREEBSD_TRUE@ for MOD in $(MODULES); do \ +@FREEBSD_TRUE@ $(INSTALL) -d $(DESTDIR)$(MODULES_DIR); \ +@FREEBSD_TRUE@ $(INSTALL) -m644 $(modulesrc)/$(MODULES_OS)/$$MOD.ko \ +@FREEBSD_TRUE@ $(DESTDIR)$(MODULES_DIR); \ +@FREEBSD_TRUE@ done +@LINUX_TRUE@ for MOD in $(MODULES); do \ +@LINUX_TRUE@ $(INSTALL) -d $(DESTDIR)`eval echo '$$'$${MOD}dir`; \ +@LINUX_TRUE@ $(INSTALL) -m644 $(modulesrc)/$(MODULES_OS)/$$MOD/$$MOD.ko \ +@LINUX_TRUE@ $(DESTDIR)`eval echo '$$'$${MOD}dir`; \ +@LINUX_TRUE@ done +@LINUX_TRUE@ eval "$$DEPMOD" + +uninstall-hook: + for MOD in $(MODULES); do \ + rm -f $(DESTDIR)`eval echo '$$'$${MOD}dir`/$$MOD.ko &> /dev/null;\ + done + eval "$$DEPMOD" +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/open-vm-tools/modules/freebsd/shared/compat_freebsd.h b/open-vm-tools/modules/freebsd/shared/compat_freebsd.h index 4bbb5d2e..41f52a5b 100644 --- a/open-vm-tools/modules/freebsd/shared/compat_freebsd.h +++ b/open-vm-tools/modules/freebsd/shared/compat_freebsd.h @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/freebsd/shared/compat_mount.h b/open-vm-tools/modules/freebsd/shared/compat_mount.h index 5a823dab..2a8074c0 100644 --- a/open-vm-tools/modules/freebsd/shared/compat_mount.h +++ b/open-vm-tools/modules/freebsd/shared/compat_mount.h @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/freebsd/shared/compat_priv.h b/open-vm-tools/modules/freebsd/shared/compat_priv.h index 14ebfeb2..69653247 100644 --- a/open-vm-tools/modules/freebsd/shared/compat_priv.h +++ b/open-vm-tools/modules/freebsd/shared/compat_priv.h @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/freebsd/shared/compat_vop.h b/open-vm-tools/modules/freebsd/shared/compat_vop.h index 43ecc69d..f76bba50 100644 --- a/open-vm-tools/modules/freebsd/shared/compat_vop.h +++ b/open-vm-tools/modules/freebsd/shared/compat_vop.h @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/freebsd/vmblock/COPYING b/open-vm-tools/modules/freebsd/vmblock/COPYING index f92946e0..e41a6d36 100644 --- a/open-vm-tools/modules/freebsd/vmblock/COPYING +++ b/open-vm-tools/modules/freebsd/vmblock/COPYING @@ -7,9 +7,6 @@ are met: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of VMware Inc. nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission of VMware Inc. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/freebsd/vmblock/Makefile b/open-vm-tools/modules/freebsd/vmblock/Makefile index ff23c9c1..f67af072 100644 --- a/open-vm-tools/modules/freebsd/vmblock/Makefile +++ b/open-vm-tools/modules/freebsd/vmblock/Makefile @@ -11,9 +11,6 @@ # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. -# 3. Neither the name of VMware Inc. nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission of VMware Inc. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/freebsd/vmblock/os.h b/open-vm-tools/modules/freebsd/vmblock/os.h index 5528f2a5..075fcbaa 100644 --- a/open-vm-tools/modules/freebsd/vmblock/os.h +++ b/open-vm-tools/modules/freebsd/vmblock/os.h @@ -10,9 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/freebsd/vmblock/os_panic.c b/open-vm-tools/modules/freebsd/vmblock/os_panic.c index 94e79aae..cacf41c0 100644 --- a/open-vm-tools/modules/freebsd/vmblock/os_panic.c +++ b/open-vm-tools/modules/freebsd/vmblock/os_panic.c @@ -10,9 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/freebsd/vmblock/subr.c b/open-vm-tools/modules/freebsd/vmblock/subr.c index 17865a04..393110af 100644 --- a/open-vm-tools/modules/freebsd/vmblock/subr.c +++ b/open-vm-tools/modules/freebsd/vmblock/subr.c @@ -24,9 +24,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/freebsd/vmblock/vfsops.c b/open-vm-tools/modules/freebsd/vmblock/vfsops.c index bd53a8c1..fb7a12f7 100644 --- a/open-vm-tools/modules/freebsd/vmblock/vfsops.c +++ b/open-vm-tools/modules/freebsd/vmblock/vfsops.c @@ -23,9 +23,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -231,7 +228,7 @@ VMBlockVFSMount(struct mount *mp, // IN: mount(2) parameters */ MNT_ILOCK(mp); mp->mnt_flag |= lowerrootvp->v_mount->mnt_flag & MNT_LOCAL; -#if __FreeBSD_version >= 600000 +#if __FreeBSD_version >= 600000 && __FreeBSD_version < 1000000 mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag & MNTK_MPSAFE; #endif MNT_IUNLOCK(mp); diff --git a/open-vm-tools/modules/freebsd/vmblock/vmblock_k.h b/open-vm-tools/modules/freebsd/vmblock/vmblock_k.h index ce8f516b..eb038c77 100644 --- a/open-vm-tools/modules/freebsd/vmblock/vmblock_k.h +++ b/open-vm-tools/modules/freebsd/vmblock/vmblock_k.h @@ -17,9 +17,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/freebsd/vmblock/vnops.c b/open-vm-tools/modules/freebsd/vmblock/vnops.c index 129be2eb..4f0ad90c 100644 --- a/open-vm-tools/modules/freebsd/vmblock/vnops.c +++ b/open-vm-tools/modules/freebsd/vmblock/vnops.c @@ -23,9 +23,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -755,14 +752,12 @@ struct vop_open_args { */ { VMBlockMount *mp; - VMBlockNode *mip; struct vnode *vp, *ldvp; struct file *fp; int retval; vp = ap->a_vp; ldvp = VMBVPTOLOWERVP(vp); - mip = VPTOVMB(ap->a_vp); mp = MNTTOVMBLOCKMNT(ap->a_vp->v_mount); if (ap->a_vp == mp->rootVnode) { @@ -1365,7 +1360,9 @@ struct vop_inactive_args { */ { struct vnode *vp = ap->a_vp; +#if __FreeBSD_version < 1000000 struct thread *td = ap->a_td; +#endif vp->v_object = NULL; @@ -1373,8 +1370,11 @@ struct vop_inactive_args { * If this is the last reference, then free up the vnode so as not to * tie up the lower vnode. */ - vrecycle(vp, td); - +#if __FreeBSD_version < 1000000 + vrecycle(vp, td); +#else + vrecycle(vp); +#endif return 0; } @@ -1414,7 +1414,6 @@ struct vop_reclaim_args { struct vnode *vp = ap->a_vp; struct VMBlockNode *xp = VPTOVMB(vp); struct vnode *lowervp = xp->lowerVnode; - struct lock *vnlock; KASSERT(lowervp != NULL, ("reclaiming node with no lower vnode")); @@ -1427,7 +1426,6 @@ struct vop_reclaim_args { VI_LOCK(vp); vp->v_data = NULL; vp->v_object = NULL; - vnlock = vp->v_vnlock; /* * Reassign lock pointer to this vnode's lock. (Originally assigned diff --git a/open-vm-tools/modules/freebsd/vmhgfs/COPYING b/open-vm-tools/modules/freebsd/vmhgfs/COPYING deleted file mode 100644 index d511905c..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/open-vm-tools/modules/freebsd/vmhgfs/Makefile b/open-vm-tools/modules/freebsd/vmhgfs/Makefile deleted file mode 100644 index 9f065f18..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/Makefile +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/make -f -########################################################## -# Copyright (C) 2007 VMware, Inc. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation version 2 and no later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -########################################################## - -HEADERS := vnode_if.h -HEADERS += hgfs_kernel.h -HEADERS += request.h -HEADERS += requestInt.h -HEADERS += debug.h -HEADERS += state.h -HEADERS += kernelStubs.h -HEADERS += fsutil.h -HEADERS += vnopscommon.h -HEADERS += os.h -HEADERS += vfsopscommon.h -HEADERS += transport.h -HEADERS += channel.h - -COMMON_SRCS := cpName.c -COMMON_SRCS += cpNameLinux.c -COMMON_SRCS += cpNameLite.c -COMMON_SRCS += sha1.c -COMMON_SRCS += hgfsEscape.c -COMMON_SRCS += hgfsBd.c -COMMON_SRCS += rpcout.c -COMMON_SRCS += message.c -COMMON_SRCS += backdoor.c -.if $(MACHINE_ARCH) == "amd64" -COMMON_SRCS += backdoorGcc64.c -.else -COMMON_SRCS += backdoorGcc32.c -.endif - -COMMON_HGFS_SRCS := debug.c -COMMON_HGFS_SRCS := bdhandler.c -COMMON_HGFS_SRCS += request.c -COMMON_HGFS_SRCS += worker.c -COMMON_HGFS_SRCS += fsutil.c -COMMON_HGFS_SRCS += vnopscommon.c -COMMON_HGFS_SRCS += state.c -COMMON_HGFS_SRCS += vfsopscommon.c -COMMON_HGFS_SRCS += transport.c - -MODULE_SRCS := vnops.c -MODULE_SRCS += vfsops.c -MODULE_SRCS += os.c -MODULE_SRCS += vmci.c -MODULE_SRCS += hgfsUtil.c -MODULE_SRCS += kernelStubsBSD.c - -# -# The FreeBSD kernel module build tree iterates over the following variable -# for build targets. C files will be compiled, and headers will just be -# tested for presence. -# -SRCS = $(MODULE_SRCS) $(COMMON_SRCS) $(COMMON_HGFS_SRCS) $(HEADERS) - -KMOD = vmhgfs -PROG = ../$(KMOD).ko -NOMAN = t -NO_MAN = t -KLDMOD = t -NOOBJ = 1 -NO_OBJ = 1 - -.ifdef OVT_SOURCE_DIR - CFLAGS += -I$(OVT_SOURCE_DIR)/lib/include - CFLAGS += -I$(OVT_SOURCE_DIR)/lib/backdoor - CFLAGS += -I$(OVT_SOURCE_DIR)/lib/hgfs - CFLAGS += -I$(OVT_SOURCE_DIR)/modules/freebsd/shared - VPATH := $(OVT_SOURCE_DIR)/lib/backdoor - VPATH := $(VPATH):$(OVT_SOURCE_DIR)/lib/hgfs - VPATH := $(VPATH):$(OVT_SOURCE_DIR)/lib/hgfsBd - VPATH := $(VPATH):$(OVT_SOURCE_DIR)/lib/message - VPATH := $(VPATH):$(OVT_SOURCE_DIR)/lib/misc - VPATH := $(VPATH):$(OVT_SOURCE_DIR)/lib/rpcOut -.else - CFLAGS += -Ishared -.endif - -# -# FreeBSD's kernel module build system defines a bunch of additional warning -# flags for the compiler in addition to -Wall -Werror. However, some of these, -# like -Wredundant-decls, are overkill. To get around this, I copied their list -# of warning flags, but explicitly disabled a few. -# -CWARNFLAGS := -Wall -CWARNFLAGS += -Werror -CWARNFLAGS += -Wno-redundant-decls -CWARNFLAGS += -Wnested-externs -CWARNFLAGS += -Wstrict-prototypes -CWARNFLAGS += -Wno-missing-prototypes -CWARNFLAGS += -Wpointer-arith -CWARNFLAGS += -Winline -CWARNFLAGS += -Wcast-qual - -EXPORT_SYMS = NO - -.include <bsd.kmod.mk> diff --git a/open-vm-tools/modules/freebsd/vmhgfs/bdhandler.c b/open-vm-tools/modules/freebsd/vmhgfs/bdhandler.c deleted file mode 100644 index 3c92343c..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/bdhandler.c +++ /dev/null @@ -1,236 +0,0 @@ -/********************************************************* - * Copyright (C) 2010 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * bdhandler.c -- - * - */ - -#include "hgfsBd.h" -#include "rpcout.h" -#include "channel.h" - -static Bool HgfsBdChannelOpen(HgfsTransportChannel *channel); -static void HgfsBdChannelClose(HgfsTransportChannel *channel); -static HgfsKReqObject * HgfsBdChannelAllocate(size_t payloadSize, int flags); -void HgfsBdChannelFree(HgfsKReqObject *req, size_t payloadSize); -static int HgfsBdChannelSend(HgfsTransportChannel *channel, HgfsKReqObject *req); - -static HgfsTransportChannel gBdChannel = { - .name = "backdoor", - .ops.open = HgfsBdChannelOpen, - .ops.close = HgfsBdChannelClose, - .ops.allocate = HgfsBdChannelAllocate, - .ops.free = HgfsBdChannelFree, - .ops.send = HgfsBdChannelSend, - .priv = NULL, - .status = HGFS_CHANNEL_NOTCONNECTED -}; - - -/* - *----------------------------------------------------------------------------- - * - * HgfsBdChannelOpen -- - * - * Open the backdoor in an idempotent way. - * - * Results: - * TRUE on success, FALSE on failure. - * - * Side effects: - * None - * - *----------------------------------------------------------------------------- - */ - -static Bool -HgfsBdChannelOpen(HgfsTransportChannel *channel) // IN: Channel -{ - Bool ret; - - if ((ret = HgfsBd_OpenBackdoor((RpcOut **)&channel->priv))) { - DEBUG(VM_DEBUG_INFO, "VMware hgfs: %s: backdoor opened.\n", __func__); - ASSERT(channel->priv != NULL); - channel->status = HGFS_CHANNEL_CONNECTED; - } - - return ret; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsBdChannelClose -- - * - * Close the backdoor in an idempotent way. - * - * Results: - * None - * - * Side effects: - * None - * - *----------------------------------------------------------------------------- - */ - -static void -HgfsBdChannelClose(HgfsTransportChannel *channel) // IN: Channel -{ - int ret; - - if (channel->priv == NULL) { - return; - } - - ret = HgfsBd_CloseBackdoor((RpcOut **)&channel->priv); - if (!ret) { - DEBUG(VM_DEBUG_FAIL, "VMware hgfs: %s: Failed to close backdoor.\n", __func__); - } else { - DEBUG(VM_DEBUG_INFO, "VMware hgfs: %s: backdoor closed.\n", __func__); - } - channel->status = HGFS_CHANNEL_NOTCONNECTED; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsBdChannelAllocate -- - * - * Allocate request in a way that is suitable for sending through - * backdoor. - * - * Results: - * NULL on failure; otherwise address of the new request. - * - * Side effects: - * None - * - *----------------------------------------------------------------------------- - */ - -static HgfsKReqObject * -HgfsBdChannelAllocate(size_t payloadSize, // IN: Size of allocation - int flags) // IN: -{ - return os_malloc(payloadSize, flags); -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsBdChannelFree -- - * - * Free previously allocated request. - * - * Results: - * None. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -void -HgfsBdChannelFree(HgfsKReqObject *req, // IN: - size_t payloadSize) // IN: -{ - ASSERT(req); - os_free(req, payloadSize); -} - - -/* - *---------------------------------------------------------------------- - * - * HgfsBdChannelSend -- - * - * Send a request via backdoor. - * - * Results: - * 0 on success, negative error on failure. - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -static int -HgfsBdChannelSend(HgfsTransportChannel *channel, // IN: Channel - HgfsKReqObject *req) // IN: request to send -{ - char const *replyPacket = NULL; - int ret; - - ASSERT(req); - - DEBUG(VM_DEBUG_INFO, "VMware hgfs: %s: backdoor sending.\n", __func__); - - bcopy(HGFS_SYNC_REQREP_CLIENT_CMD, req->__rpc_packet._command, - HGFS_SYNC_REQREP_CLIENT_CMD_LEN); - - ret = HgfsBd_Dispatch(channel->priv, req->payload, &req->payloadSize, - &replyPacket); - os_mutex_lock(req->stateLock); - - /* - * We have a response. (Maybe.) Re-lock the request, update its state, - * etc. - */ - if ((ret == 0) && (req->state == HGFS_REQ_SUBMITTED)) { - DEBUG(VM_DEBUG_INFO, "VMware hgfs: %s: Success in backdoor.\n", __func__); - bcopy(replyPacket, req->payload, req->payloadSize); - req->state = HGFS_REQ_COMPLETED; - } else { - DEBUG(VM_DEBUG_INFO, "hgfs: %s: Error in backdoor.\n", __func__); - req->state = HGFS_REQ_ERROR; - } - - os_cv_signal(&req->stateCv); - os_mutex_unlock(req->stateLock); - return ret; -} - - -/* - *---------------------------------------------------------------------- - * - * HgfsGetBdChannel -- - * - * Get backdoor channel. - * - * Results: - * Always return pointer to back door channel. - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -HgfsTransportChannel* -HgfsGetBdChannel(void) -{ - return &gBdChannel; -} - diff --git a/open-vm-tools/modules/freebsd/vmhgfs/channel.h b/open-vm-tools/modules/freebsd/vmhgfs/channel.h deleted file mode 100644 index 0fcae727..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/channel.h +++ /dev/null @@ -1,60 +0,0 @@ -/********************************************************* - * Copyright (C) 2010 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * channel.h -- - */ - -#ifndef _HGFS_CHANNEL_H_ -#define _HGFS_CHANNEL__H_ - -#include "hgfs_kernel.h" -#include "requestInt.h" - -/* - * There are the operations a channel should implement. - */ -struct HgfsTransportChannel; -typedef struct HgfsTransportChannelOps { - Bool (*open)(struct HgfsTransportChannel *); - void (*close)(struct HgfsTransportChannel *); - HgfsKReqObject* (*allocate)(size_t payloadSize, int flags); - int (*send)(struct HgfsTransportChannel *, HgfsKReqObject *); - void (*free)(HgfsKReqObject *, size_t payloadSize); -} HgfsTransportChannelOps; - -typedef enum { - HGFS_CHANNEL_UNINITIALIZED, - HGFS_CHANNEL_NOTCONNECTED, - HGFS_CHANNEL_CONNECTED, - HGFS_CHANNEL_DEAD, /* Error has been detected, need to shut it down. */ -} HgfsChannelStatus; - -typedef struct HgfsTransportChannel { - const char *name; /* Channel name. */ - HgfsTransportChannelOps ops; /* Channel ops. */ - HgfsChannelStatus status; /* Connection status. */ - void *priv; /* Channel private data. */ -} HgfsTransportChannel; - -HgfsTransportChannel *HgfsGetBdChannel(void); -HgfsTransportChannel *HgfsGetVmciChannel(void); -Bool HgfsSetupNewChannel(void); -extern HgfsTransportChannel *gHgfsChannel; - -#endif // _HGFS_CHANNEL_H_ diff --git a/open-vm-tools/modules/freebsd/vmhgfs/debug.c b/open-vm-tools/modules/freebsd/vmhgfs/debug.c deleted file mode 100644 index e39da2d5..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/debug.c +++ /dev/null @@ -1,346 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * debug.c -- - * - * Routine(s) for debugging the FreeBSD / Mac OS Hgfs module. - */ - - -#if defined __APPLE__ -#include <sys/proc.h> // for proc_selfpid/name -#include <string.h> -#include "kernelStubs.h" -#endif // defined __APPLE__ -#include "vm_basic_types.h" -#include "debug.h" - -/* - * Global functions - */ -static const char *gHgfsOperationNames[] = { - "HGFS_OP_OPEN", - "HGFS_OP_READ", - "HGFS_OP_WRITE", - "HGFS_OP_CLOSE", - "HGFS_OP_SEARCH_OPEN", - "HGFS_OP_SEARCH_READ", - "HGFS_OP_SEARCH_CLOSE", - "HGFS_OP_GETATTR", - "HGFS_OP_SETATTR", - "HGFS_OP_CREATE_DIR", - "HGFS_OP_DELETE_FILE", - "HGFS_OP_DELETE_DIR", - "HGFS_OP_RENAME", - "HGFS_OP_QUERY_VOLUME_INFO", - "HGFS_OP_OPEN_V2", - "HGFS_OP_GETATTR_V2", - "HGFS_OP_SETATTR_V2", - "HGFS_OP_SEARCH_READ_V2", - "HGFS_OP_CREATE_SYMLINK", - "HGFS_OP_SERVER_LOCK_CHANGE", - "HGFS_OP_CREATE_DIR_V2", - "HGFS_OP_DELETE_FILE_V2", - "HGFS_OP_DELETE_DIR_V2", - "HGFS_OP_RENAME_V2", - "HGFS_OP_OPEN_V3", - "HGFS_OP_READ_V3", - "HGFS_OP_WRITE_V3", - "HGFS_OP_CLOSE_V3", - "HGFS_OP_SEARCH_OPEN_V3", - "HGFS_OP_SEARCH_READ_V3", - "HGFS_OP_SEARCH_CLOSE_V3", - "HGFS_OP_GETATTR_V3", - "HGFS_OP_SETATTR_V3", - "HGFS_OP_CREATE_DIR_V3", - "HGFS_OP_DELETE_FILE_V3", - "HGFS_OP_DELETE_DIR_V3", - "HGFS_OP_RENAME_V3", - "HGFS_OP_QUERY_VOLUME_INFO_V3", - "HGFS_OP_CREATE_SYMLINK_V3", - "HGFS_OP_SERVER_LOCK_CHANGE_V3", - "HGFS_OP_WRITE_WIN32_STREAM_V3", - "HGFS_OP_CREATE_SESSION_V4", - "HGFS_OP_DESTROY_SESSION_V4", - "HGFS_OP_READ_FAST_V4", - "HGFS_OP_WRITE_FAST_V4", - "HGFS_OP_SET_WATCH_V4", - "HGFS_OP_REMOVE_WATCH_V4", - "HGFS_OP_NOTIFY_V4", - "HGFS_OP_SEARCH_READ_V4", -}; - -#if defined VMX86_DEVEL -uint32_t gHgfsVmDebugLevel = VM_DEBUG_DEFAULT_LEV; - -static uint32 HgfsDebugGetSequenceNumber(void); -static int HgfsDebugGetProcessInfo(char *pidName, size_t pidNameBufsize); -static void *HgfsDebugGetCurrentThread(void); -#endif // defined VMX86_DEVEL - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDebugPrint -- - * - * Prints the operation of an request structure. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsDebugPrint(int type, const char *funcname, unsigned int linenum, const char *fmt, ...) -{ -#if defined VMX86_DEVEL -#if defined __APPLE__ - if (0 != (type & gHgfsVmDebugLevel) || - VM_DEBUG_ALWAYS == type) { - char *fmsg; - size_t fmsgLen; - va_list args; - - va_start(args, fmt); - fmsg = Str_Vasprintf(&fmsgLen, fmt, args); - va_end(args); - - if (NULL != fmsg) { - int pid; - void *thrd; - char pidname[64]; - uint32 seqNo; - - thrd = HgfsDebugGetCurrentThread(); - pid = HgfsDebugGetProcessInfo(pidname, sizeof pidname); - seqNo = HgfsDebugGetSequenceNumber(); - - kprintf("|%08u|%p.%08d.%s| %s:%2.2u: %s", - seqNo, thrd, pid, pidname, funcname, linenum, fmsg); - - free(fmsg); - } - } -#endif // defined __APPLE__ -#endif // defined VMX86_DEVEL -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDebugPrintOperation -- - * - * Prints the operation of an request structure. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsDebugPrintOperation(HgfsKReqHandle req) -{ - HgfsRequest *requestHeader; - - ASSERT(NULL != req); - - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - - if (requestHeader->op < ARRAYSIZE(gHgfsOperationNames)) { - DEBUG(VM_DEBUG_STRUCT, " operation: %s\n", gHgfsOperationNames[requestHeader->op]); - } else { - DEBUG(VM_DEBUG_STRUCT, " operation: INVALID %d\n", requestHeader->op); - } -} - - -#if defined VMX86_DEVEL -/* - *---------------------------------------------------------------------------- - * - * HgfsDebugGetProcessInfo -- - * - * Gets the process name and ID making a request. - * - * Results: - * PID of current process, and name in the buffer. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsDebugGetProcessInfo(char *pidname, // OUT: buffer for name - size_t pidNameBufsize) // IN: size of buffer -{ - int curPid = -1; - *pidname = '\0'; -#if defined __APPLE__ - curPid = proc_selfpid(); - proc_name(curPid, pidname, pidNameBufsize); -#endif // defined __APPLE__ - return curPid; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDebugGetCurrentThreadId -- - * - * Gets the current thread making a request. - * - * Results: - * TID of current thread. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static void * -HgfsDebugGetCurrentThread(void) -{ - void *thread = NULL; -#if defined __APPLE__ - thread = current_thread(); -#endif // defined __APPLE__ - return thread; -} -#endif // defined VMX86_DEVEL - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDebugPrintVattr -- - * - * Prints the contents of an attributes structure. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsDebugPrintVattr(const HgfsVnodeAttr *vap) -{ - DEBUG(VM_DEBUG_STRUCT, " va_type: %d\n", vap->va_type); - DEBUG(VM_DEBUG_STRUCT, " va_mode: %o\n", vap->va_mode); - DEBUG(VM_DEBUG_STRUCT, " va_uid: %u\n", vap->va_uid); - DEBUG(VM_DEBUG_STRUCT, " va_gid: %u\n", vap->va_gid); - DEBUG(VM_DEBUG_STRUCT, " va_fsid: %u\n", vap->va_fsid); - DEBUG(VM_DEBUG_STRUCT, " va_rdev: %u\n", vap->va_rdev); - DEBUG(VM_DEBUG_STRUCT, " va_filerev: %"FMT64"u\n", vap->va_filerev); - DEBUG(VM_DEBUG_STRUCT, " va_vaflags: %x\n", vap->va_vaflags); - -#if defined __FreeBSD__ - /* - * The next group of attributes have the same name but different sizes on - * xnu-1228 and FreeBSD 6.2. - */ - DEBUG(VM_DEBUG_STRUCT, " va_flags: %lx\n", vap->va_flags); - DEBUG(VM_DEBUG_STRUCT, " va_gen: %lu\n", vap->va_gen); - DEBUG(VM_DEBUG_STRUCT, " va_fileid: %ld\n", vap->va_fileid); - DEBUG(VM_DEBUG_STRUCT, " va_nlink: %hd\n", vap->va_nlink); - - /* These attributes names changed have between xnu-1228 and FreeBSD 6.2. */ - DEBUG(VM_DEBUG_STRUCT, " va_size: %ju\n", vap->va_size); - DEBUG(VM_DEBUG_STRUCT, " va_blocksize: %ld\n", vap->va_blocksize); - /* - * XXX time_t is __int32_t on 32-bit architectures and __int64_t on 64-bit - * architectures. Would this be better as add'l formats in vm_basic_types.h? - */ - DEBUG(VM_DEBUG_STRUCT, " va_atime.tv_sec: %jd\n", (intmax_t)vap->va_atime.tv_sec); - DEBUG(VM_DEBUG_STRUCT, " va_atime.tv_nsec: %ld\n", vap->va_atime.tv_nsec); - DEBUG(VM_DEBUG_STRUCT, " va_mtime.tv_sec: %jd\n", (intmax_t)vap->va_mtime.tv_sec); - DEBUG(VM_DEBUG_STRUCT, " va_mtime.tv_nsec: %ld\n", vap->va_mtime.tv_nsec); - DEBUG(VM_DEBUG_STRUCT, " va_ctime.tv_sec: %jd\n", (intmax_t)vap->va_ctime.tv_sec); - DEBUG(VM_DEBUG_STRUCT, " va_ctime.tv_nsec: %ld\n", vap->va_ctime.tv_nsec); - DEBUG(VM_DEBUG_STRUCT, " va_birthtime.tv_sec: %jd\n", - (intmax_t)vap->va_birthtime.tv_sec); - DEBUG(VM_DEBUG_STRUCT, " va_birthtime.tv_nsec: %ld\n", - vap->va_birthtime.tv_nsec); - DEBUG(VM_DEBUG_STRUCT, " va_bytes: %"FMT64"u\n", vap->va_bytes); - -#elif defined __APPLE__ - /* - * The next group of attributes have the same name but different sizes on - * xnu-1228 and FreeBSD 6.2. - */ - DEBUG(VM_DEBUG_STRUCT, " va_flags: %x\n", vap->va_flags); - DEBUG(VM_DEBUG_STRUCT, " va_gen: %u\n", vap->va_gen); - DEBUG(VM_DEBUG_STRUCT, " va_fileid: %"FMT64"u\n", vap->va_fileid); - DEBUG(VM_DEBUG_STRUCT, " va_nlink: %"FMT64"u\n", vap->va_nlink); - - /* These attribute names have changed between xnu-1228 and FreeBSD 6.2. */ - DEBUG(VM_DEBUG_STRUCT, " va_size: %"FMT64"u\n", vap->va_data_size); - DEBUG(VM_DEBUG_STRUCT, " va_iosize: %u\n", vap->va_iosize); - - DEBUG(VM_DEBUG_STRUCT, " va_access_time.tv_sec: %ld\n", vap->va_access_time.tv_sec); - DEBUG(VM_DEBUG_STRUCT, " va_access_time.tv_nsec: %ld\n", vap->va_access_time.tv_nsec); - DEBUG(VM_DEBUG_STRUCT, " va_modify_time.tv_sec: %ld\n", vap->va_modify_time.tv_sec); - DEBUG(VM_DEBUG_STRUCT, " va_modify_time.tv_nsec: %ld\n", vap->va_modify_time.tv_nsec); - DEBUG(VM_DEBUG_STRUCT, " va_create_time.tv_sec: %ld\n", vap->va_create_time.tv_sec); - DEBUG(VM_DEBUG_STRUCT, " va_create_time.tv_nsec: %ld\n", vap->va_create_time.tv_nsec); -#endif -} - - -#if defined VMX86_DEVEL -/* - *---------------------------------------------------------------------------- - * - * HgfsDebugGetSequenceNumber -- - * - * Log a sequence number in case we suspect log messages getting dropped - * - * Results: - * The next sequence number. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static uint32 -HgfsDebugGetSequenceNumber(void) -{ - static uint32 ghgfsDebugLogSeq = 0; - return ++ghgfsDebugLogSeq; -} -#endif // defined VMX86_DEVEL diff --git a/open-vm-tools/modules/freebsd/vmhgfs/debug.h b/open-vm-tools/modules/freebsd/vmhgfs/debug.h deleted file mode 100644 index 68043d51..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/debug.h +++ /dev/null @@ -1,104 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * debug.h -- - * - * Macros and includes for debugging. - */ - -#ifndef _DEBUG_H_ -#define _DEBUG_H_ - -#include <sys/param.h> - -#if defined __FreeBSD__ -# include <sys/types.h> // for log(9) -# include <sys/systm.h> // for log(9) -# include <sys/syslog.h> // for log(9), LOG_* macros -#elif defined __APPLE__ -# include <kern/debug.h> // for panic -# if defined VMX86_DEVEL -# include <pexpert/pexpert.h> // for kprintf -# endif -#endif - -#include <sys/vnode.h> // for struct vattr - -#include "hgfs_kernel.h" - -/* - * Macros - */ - -#define Panic(fmt, ...) panic(fmt, ##__VA_ARGS__) - -#define VM_DEBUG_ALWAYS (1) -#define VM_DEBUG_FAIL VM_DEBUG_ALWAYS -#define VM_DEBUG_NOTSUP VM_DEBUG_ALWAYS -#define VM_DEBUG_ENTRY (1 << 1) -#define VM_DEBUG_EXIT (1 << 2) -#define VM_DEBUG_LOAD (1 << 3) -#define VM_DEBUG_INFO (1 << 4) -#define VM_DEBUG_STRUCT (1 << 5) -#define VM_DEBUG_LIST (1 << 6) -#define VM_DEBUG_CHPOLL (1 << 7) -#define VM_DEBUG_RARE (1 << 8) -#define VM_DEBUG_COMM (1 << 9) -#define VM_DEBUG_REQUEST (1 << 10) -#define VM_DEBUG_LOG (1 << 11) -#define VM_DEBUG_ATTR (1 << 12) -#define VM_DEBUG_DEVENTRY (1 << 13) -#define VM_DEBUG_DEVDONE (1 << 14) -#define VM_DEBUG_SIG (1 << 15) -#define VM_DEBUG_ERROR (1 << 16) -#define VM_DEBUG_HSHTBL (1 << 17) -#define VM_DEBUG_HANDLE (1 << 18) -#define VM_DEBUG_STATE (1 << 19) -#define VM_DEBUG_VNODE (1 << 20) -#define VM_DEBUG_ALL (~0) - -#if defined VMX86_DEVEL -extern uint32_t gHgfsVmDebugLevel; -#define VM_DEBUG_DEFAULT_LEV (VM_DEBUG_ALWAYS | VM_DEBUG_ENTRY | VM_DEBUG_EXIT | VM_DEBUG_FAIL) -#endif - -#ifdef VMX86_DEVEL -# if defined __FreeBSD__ -# define DEBUG(type, fmt, ...) \ - ((type & gHgfsVmDebugLevel) ? \ - (log(LOG_NOTICE, "%s:%u: " fmt, \ - __func__, __LINE__, ##__VA_ARGS__)) \ - : 0) -# elif defined __APPLE__ -# define DEBUG(type, fmt, ...) \ - HgfsDebugPrint(type, __func__, __LINE__, fmt, ##__VA_ARGS__) -# endif -#else -# define DEBUG(type, ...) -#endif - -/* - * Global functions - */ - -void HgfsDebugPrint(int type, const char *funcname, unsigned int linenum, const char *fmt, ...); -void HgfsDebugPrintVattr(const HgfsVnodeAttr *vap); -void HgfsDebugPrintOperation(HgfsKReqHandle req); - -#endif // _DEBUG_H_ diff --git a/open-vm-tools/modules/freebsd/vmhgfs/fsutil.c b/open-vm-tools/modules/freebsd/vmhgfs/fsutil.c deleted file mode 100644 index ce8784d5..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/fsutil.c +++ /dev/null @@ -1,1030 +0,0 @@ -/********************************************************* - * Copyright (C) 2008 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * fsutil.c -- - * - * VFS helper functions that are shared between the FreeBSD and Mac OS - * implementaitons of HGFS. - */ - -#include <sys/types.h> -#include <sys/malloc.h> - -#if defined __APPLE__ -# include <libkern/libkern.h> // for rindex -#endif - -#include "fsutil.h" -#include "cpName.h" -#include "hgfsEscape.h" -#include "cpNameLite.h" -#include "os.h" - -#if defined __APPLE__ -char *rindex(const char *ptr, int chr); -#endif - -/* - * Mac OS sets vnode attributes through the use of a VATTR_RETURN function. - * FreeBSD sets vnode attributes directly in the structure. To enable a shared - * implementation of HgfsAttrToBSD and HgfsSetattrCopy, we define VATTR_RETURN - * for FreeBSD. - */ -#if defined __FreeBSD__ -#define VATTR_RETURN(vn, attr, val) \ - do { (vn)-> attr = (val); } while (0) -#endif - -/* Local Function Prototypes */ - -/* - *---------------------------------------------------------------------------- - * - * HgfsSubmitRequest -- - * - * Places a request on the queue for submission by the worker thread, - * then waits for the response. - * - * Both submitting request and waiting for reply are in this function - * because the signaling of the request list's condition variable and - * waiting on the request's condition variable must be atomic. - * - * Results: - * Returns zero on success, and an appropriate error code on error. - * Note: EINTR is returned if cv_wait_sig() is interrupted. - * - * Side effects: - * The request list's condition variable is signaled. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsSubmitRequest(HgfsSuperInfo *sip, // IN: Superinfo containing request list, - // condition variable, and mutex - HgfsKReqHandle req) // IN: Request to submit -{ - int ret = 0; - - ASSERT(sip); - ASSERT(req); - - /* - * The process of submitting the request involves putting it on the request - * list, waking up the backdoor req thread if it is waiting for a request, - * then atomically waiting for the reply. - */ - - /* - * Fail the request if a forcible unmount is in progress. - */ - if (HGFS_MP_IS_FORCEUNMOUNT(sip->vfsp)) { - HgfsKReq_ReleaseRequest(sip->reqs, req); - return EIO; - } - - /* Submit the request & wait for a result. */ - ret = HgfsKReq_SubmitRequest(req); - - if (ret == 0) { - /* The reply should now be in HgfsKReq_GetPayload(req). */ - DEBUG(VM_DEBUG_SIG, "awoken because reply received.\n"); - } else { - /* HgfsKReq_SubmitRequest was interrupted, so we'll abandon now. */ - HgfsKReq_ReleaseRequest(sip->reqs, req); - } - - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsGetStatus -- - * - * Gets the status of the reply packet. If the size of the reply packet - * does not lie between the minimum expected size and maximum allowed packet - * size, then EPROTO is returned. - * - * Results: - * Returns zero on success, and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsGetStatus(HgfsKReqHandle req, // IN: Request that contains reply data - uint32_t minSize) // IN: Minimum size expected for the reply -{ - HgfsReply *replyHeader; - size_t repSize = 0; - int ret = 0; - - ASSERT(req); - ASSERT(minSize <= HGFS_PACKET_MAX); /* we want to know if this fails */ - - switch (HgfsKReq_GetState(req)) { - - case HGFS_REQ_ERROR: - DEBUG(VM_DEBUG_FAIL, "received reply with error.\n"); - ret = EPROTO; - break; - - case HGFS_REQ_COMPLETED: - repSize = HgfsKReq_GetPayloadSize(req); - /* - * Server sets the packet size equal to size of HgfsReply when it - * encounters an error. In order to return correct error code, - * we should first check the status and then check if packet size - * lies between minimum expected size and maximum allowed packet size. - */ - - if (repSize >= sizeof *replyHeader) { - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - ret = HgfsStatusToBSD(replyHeader->status); - if (ret) { - break; - } - } - - if (repSize < minSize || repSize > HGFS_PACKET_MAX) { - DEBUG(VM_DEBUG_FAIL, "successfully " - "completed reply is too small/big: !(%d < %" FMTSZ "d < %d).\n", - minSize, repSize, HGFS_PACKET_MAX); - ret = EPROTO; - } - break; - - /* - * If we get here then there is a programming error in this module: - * HGFS_REQ_UNUSED should be for requests in the free list - * HGFS_REQ_SUBMITTED should be for requests only that are awaiting - * a response - * HGFS_REQ_ABANDONED should have returned an error to the client - */ - default: - NOT_REACHED(); - ret = EPROTO; /* avoid compiler warning */ - } - - return ret; -} - -/* - * XXX - * These were taken and slightly modified from hgfs/driver/solaris/vnode.c. - * (Which, in turn, took them from hgfs/driver/linux/driver.c.) Should we - * move them into a hgfs/driver/posix/driver.c? - */ - - -/* - *---------------------------------------------------------------------- - * - * HgfsGetOpenMode -- - * - * Based on the flags requested by the process making the open() - * syscall, determine which open mode (access type) to request from - * the server. - * - * Results: - * Returns the correct HgfsOpenMode enumeration to send to the - * server, or -1 on failure. - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -int -HgfsGetOpenMode(uint32 flags) // IN: Open flags -{ - /* - * Preprocessor wrapper kept for when this function is factored out - * into a common file. - */ -#if defined _KERNEL || defined KERNEL - /* - * FreeBSD / Mac OS use different values from those in the linux kernel. These are defined in - * <sys/fcntl.h>. - */ - #undef O_RDONLY - #undef O_WRONLY - #undef O_RDWR - - #define O_RDONLY FREAD - #define O_WRONLY FWRITE - #define O_RDWR (FREAD | FWRITE) -#endif - - uint32 mask = O_RDONLY | O_WRONLY | O_RDWR; - int result = -1; - - DEBUG(VM_DEBUG_LOG, "entered\n"); - - /* - * Mask the flags to only look at the access type. - */ - flags &= mask; - - /* Pick the correct HgfsOpenMode. */ - switch (flags) { - - case O_RDONLY: - DEBUG(VM_DEBUG_COMM, "O_RDONLY\n"); - result = HGFS_OPEN_MODE_READ_ONLY; - break; - - case O_WRONLY: - DEBUG(VM_DEBUG_COMM, "O_WRONLY\n"); - result = HGFS_OPEN_MODE_WRITE_ONLY; - break; - - case O_RDWR: - DEBUG(VM_DEBUG_COMM, "O_RDWR\n"); - result = HGFS_OPEN_MODE_READ_WRITE; - break; - - default: - /* This should never happen. */ - NOT_REACHED(); - DEBUG(VM_DEBUG_LOG, "invalid open flags %o\n", flags); - result = -1; - break; - } - - return result; -} - - -/* - *---------------------------------------------------------------------- - * - * HgfsGetOpenFlags -- - * - * Based on the flags requested by the process making the open() - * syscall, determine which flags to send to the server to open the - * file. - * - * Results: - * Returns the correct HgfsOpenFlags enumeration to send to the - * server, or -1 on failure. - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -int -HgfsGetOpenFlags(uint32 flags) // IN: Open flags -{ - uint32 mask = O_CREAT | O_TRUNC | O_EXCL; - int result = -1; - - DEBUG(VM_DEBUG_INFO, "entered\n"); - - /* - * Mask the flags to only look at O_CREAT, O_EXCL, and O_TRUNC. - */ - - flags &= mask; - - /* O_EXCL has no meaning if O_CREAT is not set. */ - if (!(flags & O_CREAT)) { - flags &= ~O_EXCL; - } - - /* Pick the right HgfsOpenFlags. */ - switch (flags) { - - case 0: - /* Regular open; fails if file nonexistant. */ - DEBUG(VM_DEBUG_COMM, "0\n"); - result = HGFS_OPEN; - break; - - case O_CREAT: - /* Create file; if it exists already just open it. */ - DEBUG(VM_DEBUG_COMM, "O_CREAT\n"); - result = HGFS_OPEN_CREATE; - break; - - case O_TRUNC: - /* Truncate existing file; fails if nonexistant. */ - DEBUG(VM_DEBUG_COMM, "O_TRUNC\n"); - result = HGFS_OPEN_EMPTY; - break; - - case (O_CREAT | O_EXCL): - /* Create file; fail if it exists already. */ - DEBUG(VM_DEBUG_COMM, "O_CREAT | O_EXCL\n"); - result = HGFS_OPEN_CREATE_SAFE; - break; - - case (O_CREAT | O_TRUNC): - /* Create file; if it exists already, truncate it. */ - DEBUG(VM_DEBUG_COMM, "O_CREAT | O_TRUNC\n"); - result = HGFS_OPEN_CREATE_EMPTY; - break; - - default: - /* - * This can only happen if all three flags are set, which - * conceptually makes no sense because O_EXCL and O_TRUNC are - * mutually exclusive if O_CREAT is set. - * - * However, the open(2) man page doesn't say you can't set all - * three flags, and certain apps (*cough* Nautilus *cough*) do - * so. To be friendly to those apps, we just silenty drop the - * O_TRUNC flag on the assumption that it's safer to honor - * O_EXCL. - */ - DEBUG(VM_DEBUG_INFO, "invalid open flags %o. " - "Ignoring the O_TRUNC flag.\n", flags); - result = HGFS_OPEN_CREATE_SAFE; - break; - } - - return result; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsMakeFullName -- - * - * Concatenates the path and filename to construct the full path. This - * handles the special cases of . and .. filenames so the Hgfs server - * doesn't return an error. - * - * Results: - * Returns the length of the full path on success, and a negative value on - * error. The full pathname is placed in outBuf. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsMakeFullName(const char *path, // IN: Path of directory containing file - uint32_t pathLen, // IN: Length of path - const char *file, // IN: Name of file - size_t fileLen, // IN: Length of filename - char *outBuf, // OUT: Location to write full path - ssize_t bufSize) // IN: Size of the out buffer -{ - uint32 pathSeparatorLen; - ASSERT(path); - ASSERT(file); - ASSERT(outBuf); - - - DEBUG(VM_DEBUG_INFO, "HgfsMakeFullName:\n" - " path: \"%.*s\" (%d)\n" - " file: \"%s\" (%zu)\n", - pathLen, path, pathLen, file, fileLen); - - /* - * Here there are three possibilities: - * o file is ".", in which case we just place path in outBuf - * o file is "..", in which case we strip the last component from path and - * put that in outBuf - * o for all other cases, we concatenate path, a path separator, file, and - * a NUL terminator and place it in outBuf - */ - - /* Make sure that the path and a NUL terminator will fit. */ - if (bufSize < pathLen + 1) { - return HGFS_ERR_INVAL; - } - - - /* - * Copy path for this file into the caller's buffer. - * The memset call is important here because it implicitly null terminates - * outBuf so that rindex can be called in the second case below. - */ - memset(outBuf, 0, bufSize); - memcpy(outBuf, path, pathLen); - - /* Handle three cases. */ - if (fileLen == 1 && strncmp(file, ".", 1) == 0) { - /* NUL terminate and return provided length. */ - outBuf[pathLen] = '\0'; - return pathLen; - - } else if (fileLen == 2 && strncmp(file, "..", 2) == 0) { - /* - * Replace the last path separator with a NUL terminator, then return the - * size of the buffer. - */ - char *newEnd = rindex(outBuf, DIRSEPC); - if (!newEnd) { - /* - * We should never get here since we name the root vnode "/" in - * HgfsMount(). - */ - return HGFS_ERR_INVAL; - } - - *newEnd = '\0'; - return ((uintptr_t)newEnd - (uintptr_t)outBuf); - } else { - if (bufSize < pathLen + 1 + fileLen + 1) { - return HGFS_ERR_INVAL; - } - - /* - * If the path consists of just a single path separator, then - * do not add another path separator. This will ensure that - * we have only single path separator at the beginning of the - * filename. - */ - if (pathLen == 1 && *path == DIRSEPC) { - pathSeparatorLen = 0; - } else { - outBuf[pathLen] = DIRSEPC; - pathSeparatorLen = DIRSEPSLEN; - } - /* Now append the filename and NUL terminator. */ - memcpy(outBuf + pathSeparatorLen + pathLen, file, fileLen); - outBuf[pathLen + pathSeparatorLen + fileLen] = '\0'; - - return pathLen + pathSeparatorLen + fileLen; - } -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsSetattrCopy -- - * - * Sets the Hgfs attributes that need to be modified based on the provided - * Solaris attribute structure. - * - * Results: - * Returns TRUE if changes need to be made, FALSE otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -Bool -HgfsSetattrCopy(HgfsVnodeAttr *vap, // IN: Attributes to change to - HgfsAttrV2 *hgfsAttrV2, // OUT: Hgfs attributes to fill in - HgfsAttrHint *hints) // OUT: Hgfs attribute hints -{ - Bool ret = FALSE; - - ASSERT(vap); - ASSERT(hgfsAttrV2); - ASSERT(hints); - - memset(hgfsAttrV2, 0, sizeof *hgfsAttrV2); - memset(hints, 0, sizeof *hints); - - /* - * Hgfs supports changing these attributes: - * o mode bits (permissions) - * o uid/gid - * o size - * o access/write times - */ - - if (HGFS_VATTR_MODE_IS_ACTIVE(vap, HGFS_VA_MODE)){ - DEBUG(VM_DEBUG_COMM, "updating permissions.\n"); - hgfsAttrV2->mask |= HGFS_ATTR_VALID_SPECIAL_PERMS | - HGFS_ATTR_VALID_OWNER_PERMS | - HGFS_ATTR_VALID_GROUP_PERMS | - HGFS_ATTR_VALID_OTHER_PERMS; - hgfsAttrV2->specialPerms = (vap->HGFS_VA_MODE & (S_ISUID | S_ISGID | - S_ISVTX)) >> HGFS_ATTR_SPECIAL_PERM_SHIFT; - hgfsAttrV2->ownerPerms = (vap->HGFS_VA_MODE & S_IRWXU) >> - HGFS_ATTR_OWNER_PERM_SHIFT; - hgfsAttrV2->groupPerms = (vap->HGFS_VA_MODE & S_IRWXG) >> - HGFS_ATTR_GROUP_PERM_SHIFT; - hgfsAttrV2->otherPerms = vap->HGFS_VA_MODE & S_IRWXO; - ret = TRUE; - } - - if (HGFS_VATTR_IS_ACTIVE(vap, HGFS_VA_UID)) { - DEBUG(VM_DEBUG_COMM, "updating user id.\n"); - hgfsAttrV2->mask |= HGFS_ATTR_VALID_USERID; - hgfsAttrV2->userId = vap->HGFS_VA_UID; - ret = TRUE; - } - - if (HGFS_VATTR_IS_ACTIVE(vap, HGFS_VA_GID)) { - DEBUG(VM_DEBUG_COMM, "updating group id.\n"); - hgfsAttrV2->mask |= HGFS_ATTR_VALID_GROUPID; - hgfsAttrV2->groupId = vap->HGFS_VA_GID; - ret = TRUE; - } - - if (HGFS_VATTR_IS_ACTIVE(vap, HGFS_VA_ACCESS_TIME_SEC)) { - DEBUG(VM_DEBUG_COMM, "updating access time.\n"); - *hints |= HGFS_ATTR_HINT_SET_ACCESS_TIME; - hgfsAttrV2->mask |= HGFS_ATTR_VALID_ACCESS_TIME; - hgfsAttrV2->accessTime = HGFS_GET_TIME(vap->HGFS_VA_ACCESS_TIME); - ret = TRUE; - } - - if (HGFS_VATTR_IS_ACTIVE(vap, HGFS_VA_MODIFY_TIME_SEC)) { - DEBUG(VM_DEBUG_COMM, "updating write time.\n"); - *hints |= HGFS_ATTR_HINT_SET_WRITE_TIME; - hgfsAttrV2->mask |= HGFS_ATTR_VALID_WRITE_TIME; - hgfsAttrV2->writeTime = HGFS_GET_TIME(vap->HGFS_VA_MODIFY_TIME); - ret = TRUE; - } - - if (HGFS_VATTR_SIZE_IS_ACTIVE(vap, HGFS_VA_DATA_SIZE)) { - DEBUG(VM_DEBUG_COMM, "updating size.\n"); - hgfsAttrV2->mask |= HGFS_ATTR_VALID_SIZE; - hgfsAttrV2->size = vap->HGFS_VA_DATA_SIZE; - ret = TRUE; - } - - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsAttrToBSD -- - * - * Maps Hgfs attributes to Mac OS/BSD attributes, filling the provided BSD - * attribute structure appropriately. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsAttrToBSD(struct vnode *vp, // IN: The vnode for this file - const HgfsAttrV2 *hgfsAttrV2, // IN: Hgfs attributes to copy - HgfsVnodeAttr *vap) // OUT: BSD attributes to fill -{ - short mode = 0; - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - - ASSERT(vp); - ASSERT(hgfsAttrV2); - ASSERT(vap); - - /* XXX Update this function to support all V2 attributes. */ - - DEBUG(VM_DEBUG_ENTRY, "%p -> %p\n", hgfsAttrV2, vap); - - /* - * Initialize all fields to zero. We don't need to do this for Mac OS - * because the VATTR_RETURN macros take care of it for us. - */ -#if defined __FreeBSD__ - VATTR_NULL(vap); -#endif - - if ((hgfsAttrV2->mask & HGFS_ATTR_VALID_TYPE)) { - /* Set the file type. */ - switch (hgfsAttrV2->type) { - case HGFS_FILE_TYPE_REGULAR: - HGFS_VATTR_TYPE_RETURN(vap, VREG); - DEBUG(VM_DEBUG_ATTR, " Type: VREG\n"); - break; - - case HGFS_FILE_TYPE_DIRECTORY: - HGFS_VATTR_TYPE_RETURN(vap, VDIR); - DEBUG(VM_DEBUG_ATTR, " Type: VDIR\n"); - break; - - case HGFS_FILE_TYPE_SYMLINK: - HGFS_VATTR_TYPE_RETURN(vap, VLNK); - DEBUG(VM_DEBUG_ATTR, " Type: VLNK\n"); - break; - - default: - /* - * There are only the above three filetypes. If there is an error - * elsewhere that provides another value, we set the Solaris type to - * none and ASSERT in devel builds. - */ - HGFS_VATTR_TYPE_RETURN(vap, VNON); - DEBUG(VM_DEBUG_FAIL, "invalid HgfsFileType provided.\n"); - } - } else { - HGFS_VATTR_TYPE_RETURN(vap, VNON); - DEBUG(VM_DEBUG_FAIL, "invalid HgfsFileType provided\n"); - } - - if (hgfsAttrV2->mask & HGFS_ATTR_VALID_SPECIAL_PERMS) { - mode |= hgfsAttrV2->specialPerms << HGFS_ATTR_SPECIAL_PERM_SHIFT; - } - - if (hgfsAttrV2->mask & HGFS_ATTR_VALID_OWNER_PERMS) { - mode |= hgfsAttrV2->ownerPerms << HGFS_ATTR_OWNER_PERM_SHIFT; - } - - if (hgfsAttrV2->mask & HGFS_ATTR_VALID_GROUP_PERMS) { - mode |= hgfsAttrV2->groupPerms << HGFS_ATTR_GROUP_PERM_SHIFT; - } - - if (hgfsAttrV2->mask & HGFS_ATTR_VALID_OWNER_PERMS) { - mode |= hgfsAttrV2->otherPerms; - } - - HGFS_VATTR_MODE_RETURN(vap, mode); - - HGFS_VATTR_NLINK_RETURN(vap, 1); /* fake */ - - if (sip->uidSet || (hgfsAttrV2->mask & HGFS_ATTR_VALID_USERID) == 0) { - HGFS_VATTR_UID_RETURN(vap, sip->uid); - } else { - HGFS_VATTR_UID_RETURN(vap, hgfsAttrV2->userId); - } - - if (sip->gidSet || (hgfsAttrV2->mask & HGFS_ATTR_VALID_GROUPID) == 0) { - HGFS_VATTR_GID_RETURN(vap, sip->gid); - } else { - HGFS_VATTR_GID_RETURN(vap, hgfsAttrV2->groupId); - } - - HGFS_VATTR_FSID_RETURN(vap, HGFS_VP_TO_STATFS(vp)->f_fsid.val[0]); - - /* Get the node id calculated for this file in HgfsVnodeGet() */ - HGFS_VATTR_FILEID_RETURN(vap, HGFS_VP_TO_NODEID(vp)); - - HGFS_VATTR_BLOCKSIZE_RETURN(vap, HGFS_BLOCKSIZE); - - if (hgfsAttrV2->mask & HGFS_ATTR_VALID_SIZE) { - HGFS_VATTR_BYTES_RETURN(vap, hgfsAttrV2->size); - HGFS_VATTR_SIZE_RETURN(vap, hgfsAttrV2->size); - } - - /* - * HGFS_SET_TIME does not mark the attribute as supported (unlike - * VATTR_RETURN on Mac OS) so we have to do it explicitly with calls to - * VATTR_SET_SUPPORTED. For FreeBSD, HGFS_VATTR_*_SET_SUPPORTED is just a NULL - * macro. - */ - - if (hgfsAttrV2->mask & HGFS_ATTR_VALID_ACCESS_TIME) { - HGFS_SET_TIME(vap->HGFS_VA_ACCESS_TIME, hgfsAttrV2->accessTime); - HGFS_VATTR_ACCESS_TIME_SET_SUPPORTED(vap); - } - - if (hgfsAttrV2->mask & HGFS_ATTR_VALID_WRITE_TIME) { - HGFS_SET_TIME(vap->HGFS_VA_MODIFY_TIME, hgfsAttrV2->writeTime); - HGFS_VATTR_MODIFY_TIME_SET_SUPPORTED(vap); - } - - if (hgfsAttrV2->mask & HGFS_ATTR_VALID_CHANGE_TIME) { - HGFS_SET_TIME(vap->HGFS_VA_CHANGE_TIME, hgfsAttrV2->attrChangeTime); - HGFS_VATTR_CHANGE_TIME_SET_SUPPORTED(vap); - } - - if (hgfsAttrV2->mask & HGFS_ATTR_VALID_CREATE_TIME) { - /* Since Windows doesn't keep ctime, we may need to use mtime instead. */ - HGFS_SET_TIME(vap->HGFS_VA_CREATE_TIME, hgfsAttrV2->creationTime); - HGFS_VATTR_CREATE_TIME_SET_SUPPORTED(vap); - } else if (hgfsAttrV2->mask & HGFS_ATTR_VALID_WRITE_TIME) { - DEBUG(VM_DEBUG_ATTR, "Set create time from write time\n"); - vap->HGFS_VA_CREATE_TIME = vap->HGFS_VA_MODIFY_TIME; - HGFS_VATTR_CREATE_TIME_SET_SUPPORTED(vap); - } else { - DEBUG(VM_DEBUG_ATTR, "Do not set create time\n"); - } - - DEBUG(VM_DEBUG_ATTR, "Attrib mask %"FMT64"d\n", hgfsAttrV2->mask); - -#if defined __APPLE__ - DEBUG(VM_DEBUG_ATTR, "Supported %lld, active %lld\n", vap->va_supported, - vap->va_active); -#endif - - HgfsDebugPrintVattr(vap); -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsStatusToBSD -- - * - * Convert a cross-platform HGFS status code to its Linux-kernel specific - * counterpart. - * - * Results: - * Zero if the converted status code represents success, negative error - * otherwise. Unknown status codes are converted to the more generic - * "protocol error" status code to maintain forwards compatibility. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -int -HgfsStatusToBSD(HgfsStatus hgfsStatus) // IN: Hgfs status msg to be converted -{ - switch (hgfsStatus) { - case HGFS_STATUS_SUCCESS: - return 0; - - case HGFS_STATUS_NO_SUCH_FILE_OR_DIR: - case HGFS_STATUS_INVALID_NAME: - return ENOENT; - - case HGFS_STATUS_INVALID_HANDLE: - return EBADF; - - case HGFS_STATUS_OPERATION_NOT_PERMITTED: - return EPERM; - - case HGFS_STATUS_FILE_EXISTS: - return EEXIST; - - case HGFS_STATUS_NOT_DIRECTORY: - return ENOTDIR; - - case HGFS_STATUS_DIR_NOT_EMPTY: - return ENOTEMPTY; - - case HGFS_STATUS_PROTOCOL_ERROR: - return EPROTO; - - case HGFS_STATUS_ACCESS_DENIED: - case HGFS_STATUS_SHARING_VIOLATION: - return EACCES; - - case HGFS_STATUS_NO_SPACE: - return ENOSPC; - - case HGFS_STATUS_OPERATION_NOT_SUPPORTED: - return EOPNOTSUPP; - - case HGFS_STATUS_NAME_TOO_LONG: - return ENAMETOOLONG; - - case HGFS_STATUS_GENERIC_ERROR: - return EIO; - - default: - DEBUG(VM_DEBUG_LOG, "VMware hgfs: %s: unknown " - "error: %u\n", __FUNCTION__, hgfsStatus); - return EIO; - } -} - - -/* - *---------------------------------------------------------------------------- - * - * rindex -- - * - * Search a character string for the last instance of chr. This is only - * implemented for Mac OS because it is not exported by the Mac OS kernel. - * - * Results: - * Pointer to the last instance of chr in the string. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -#if defined __APPLE__ -char * -rindex(const char *ptr, // IN: String to search. - int chr) // IN: Char to look for. -{ - char *result = NULL; - - ASSERT(ptr); - - for (; *ptr != '\0'; ptr++) { - if (*ptr == chr) { - result = (char *)ptr; - } - } - - return result; -} -#endif - - -/* - *---------------------------------------------------------------------------- - * - * HgfsAttemptToCreateShare -- - * - * Checks if an attempt to create a new share is made. - * - * Results: - * Returns FALSE if not such attempt is made, TRUE otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -Bool -HgfsAttemptToCreateShare(const char *path, // IN: Path - int flag) // IN: flag -{ - int ret = FALSE; - ASSERT(path); - - /* - * If the first character is the path seperator and - * and there are no more path seperators present in the - * path, then with the create flag (O_CREAT) set, we believe - * that user has attempted to create new a share. This operation - * is not permitted and hence EPERM error code is returned. - */ - if ((flag & O_CREAT) && path[0] == DIRSEPC && - strchr(path + DIRSEPSLEN, DIRSEPC) == NULL) { - ret = TRUE; - } - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsNameToWireEncoding -- - * 1) Input string is converted into precomposed form. - * 2) Precomposed string is then converted to cross platform string. - * 3) Cross platform string is finally unescaped. - * - * Results: - * Returns the size (excluding the NULL terminator) on success and - * negative error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsNameToWireEncoding(const char *bufIn, // IN: Buffer to be normalized - uint32 bufInSize, // IN: Size of input buffer - char *bufOut, // OUT: Normalized string will be stored here - uint32 bufOutSize) // IN: Size of output buffer -{ - char *precomposedBuf = NULL; // allocated from M_TEMP; free when done. - const char *utf8Buf; - int ret = 0; - - if (os_utf8_conversion_needed()) { - /* Allocating precomposed buffer to be equal to Output buffer. */ - precomposedBuf = os_malloc(bufOutSize, M_WAITOK); - if (!precomposedBuf) { - return -ENOMEM; - } - - ret = os_path_to_utf8_precomposed(bufIn, bufInSize, precomposedBuf, bufOutSize); - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "os_path_to_utf8_precomposed failed."); - ret = -EINVAL; - goto out; - } - utf8Buf = precomposedBuf; - } else { - utf8Buf = bufIn; - } - - ret = CPName_ConvertTo(utf8Buf, bufOutSize, bufOut); - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, - "CPName_ConvertTo: Conversion to cross platform name failed.\n"); - ret = -ENAMETOOLONG; - goto out; - } - -out: - if (precomposedBuf != NULL) { - os_free(precomposedBuf, bufOutSize); - } - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsNameFromWireEncoding -- - * 1) Converts input from CPName form if necessary. - * 2) Result is converted into decomposed form. - * - * Results: - * Returns the size (excluding the NULL terminator) on success and - * negative error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsNameFromWireEncoding(const char *bufIn, // IN: Buffer to be encoded - uint32 inputLength, // IN: Number of characters in the input - char *bufOut, // OUT: Encoded buffer will be stored here - uint32 bufOutSize) // IN: Size of output buffer -{ - size_t escapedLen; - int ret = 0; - - /* Output buffer needs one additional byte for NUL terminator. */ - if (inputLength >= bufOutSize) { - return -ENOMEM; - } - escapedLen = HgfsEscape_GetSize(bufIn, inputLength); - if (escapedLen != 0) { - HgfsEscape_Do(bufIn, inputLength, bufOutSize, bufOut); - } else { - escapedLen = inputLength; - memcpy(bufOut, bufIn, inputLength); - } - CPNameLite_ConvertFrom(bufOut, escapedLen, '/'); - - if (os_utf8_conversion_needed()) { - size_t decomposedLen; - char *decomposedBuf = NULL; - /* - * The decomposed form a string can be a lot bigger than the input - * buffer size. We allocate a buffer equal to the output buffer. - */ - decomposedBuf = os_malloc(bufOutSize, M_WAITOK); - if (!decomposedBuf) { - DEBUG(VM_DEBUG_FAIL, "Not enough memory for decomposed buffer size %d.\n", - bufOutSize); - return -ENOMEM; - } - /* - * Convert the input buffer into decomposed form. Higher layers in - * Mac OS expects the name to be in decomposed form. - */ - ret = os_component_to_utf8_decomposed(bufOut, escapedLen, decomposedBuf, - &decomposedLen, bufOutSize); - /* - * If the decomposed name didn't fit in the buffer or it contained - * illegal utf8 characters, return back to the caller. - * os_component_to_utf8_decomposed returns 0 on success or OS_ERR on failure. - */ - if (ret != 0){ - DEBUG(VM_DEBUG_FAIL, "os_component_to_utf8_decomposed failed.\n"); - ret = -EINVAL; - } else { - if (decomposedLen < bufOutSize) { - ret = decomposedLen; - memcpy(bufOut, decomposedBuf, decomposedLen + 1); - } else { - DEBUG(VM_DEBUG_FAIL, "Output buffer is too small.\n"); - ret = -ENOMEM; - } - } - os_free(decomposedBuf, bufOutSize); - } else { - ret = escapedLen; - } - return ret; -} diff --git a/open-vm-tools/modules/freebsd/vmhgfs/fsutil.h b/open-vm-tools/modules/freebsd/vmhgfs/fsutil.h deleted file mode 100644 index 9d1a7ec7..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/fsutil.h +++ /dev/null @@ -1,196 +0,0 @@ -/********************************************************* - * Copyright (C) 2008 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * fsutil.h -- - * - * VFS helper functions that are shared between the FreeBSD and Mac OS - * implementations of HGFS. - */ - -#ifndef _HGFS_FSUTIL_H_ -#define _HGFS_FSUTIL_H_ - -#include <sys/param.h> // for everything -#include <sys/vnode.h> // for struct vnode -#include <sys/mount.h> // for struct mount -#include <sys/namei.h> // for name lookup goodness -#include <sys/fcntl.h> // for in-kernel file access flags (FREAD, etc) -#include <sys/stat.h> // for file flag bitmasks (S_IRWXU, etc) -#include <sys/uio.h> // for uiomove - -#include "debug.h" -#include "hgfsUtil.h" -#include "hgfs_kernel.h" -#include "request.h" - -/* - * Macros - */ - -/* Sets the values of request headers properly */ -#define HGFS_INIT_REQUEST_HDR(header, req, _op) \ - do { \ - header->id = HgfsKReq_GetId(req); \ - header->op = _op; \ - } while(0) - -/* Determine if this is the root vnode. */ -#define HGFS_IS_ROOT_VNODE(sip, vp) \ - (sip->rootVnode == vp) - -#define DIRSEPC '/' -#define DIRSEPS "/" -#define DIRSEPSLEN 1 - -#define HGFS_VA_MODE va_mode -#define HGFS_VA_UID va_uid -#define HGFS_VA_GID va_gid -#define HGFS_VA_TYPE va_type -#define HGFS_VA_NLINK va_nlink -#define HGFS_VA_FSID va_fsid -#define HGFS_VA_FILEID va_fileid - -#define HGFS_VATTR_TYPE_RETURN(vap, val) \ - VATTR_RETURN(vap, va_type, val) - -#define HGFS_VATTR_MODE_RETURN(vap, val) \ - VATTR_RETURN(vap, va_mode, val) - -#define HGFS_VATTR_NLINK_RETURN(vap, val) \ - VATTR_RETURN(vap, va_nlink, val) - -#define HGFS_VATTR_UID_RETURN(vap, val) \ - VATTR_RETURN(vap, va_uid, val) - -#define HGFS_VATTR_GID_RETURN(vap, val) \ - VATTR_RETURN(vap, va_gid, val) - -#define HGFS_VATTR_FSID_RETURN(vap, val) \ - VATTR_RETURN(vap, va_fsid, val) - -#define HGFS_VATTR_FILEID_RETURN(vap, val) \ - VATTR_RETURN(vap, va_fileid, val) - -#if defined __APPLE__ - #define HGFS_VA_DATA_SIZE va_data_size - #define HGFS_VA_DATA_BYTES va_data_size - #define HGFS_VA_ACCESS_TIME_SEC va_access_time - #define HGFS_VA_ACCESS_TIME va_access_time - #define HGFS_VA_MODIFY_TIME_SEC va_modify_time - #define HGFS_VA_MODIFY_TIME va_modify_time - #define HGFS_VA_CREATE_TIME_SEC va_create_time - #define HGFS_VA_CREATE_TIME va_create_time - #define HGFS_VA_CHANGE_TIME_SEC va_change_time - #define HGFS_VA_CHANGE_TIME va_change_time - #define HGFS_VA_BLOCK_SIZE va_iosize - #define HGFS_VATTR_IS_ACTIVE(vap, attr) \ - VATTR_IS_ACTIVE(vap, attr) - #define HGFS_VATTR_MODE_IS_ACTIVE(vap, mode) \ - VATTR_IS_ACTIVE(vap, mode) - #define HGFS_VATTR_SIZE_IS_ACTIVE(vap, size) \ - VATTR_IS_ACTIVE(vap, size) - #define HGFS_VATTR_BLOCKSIZE_RETURN(vap, val) \ - VATTR_RETURN(vap, va_iosize, val) - #define HGFS_VATTR_BYTES_RETURN(vap, val) - #define HGFS_VATTR_SIZE_RETURN(vap, val) \ - VATTR_RETURN(vap, va_data_size, val) - #define HGFS_VATTR_ACCESS_TIME_SET_SUPPORTED(vap) \ - VATTR_SET_SUPPORTED(vap, va_access_time) - #define HGFS_VATTR_MODIFY_TIME_SET_SUPPORTED(vap) \ - VATTR_SET_SUPPORTED(vap, va_modify_time) - #define HGFS_VATTR_CREATE_TIME_SET_SUPPORTED(vap) \ - VATTR_SET_SUPPORTED(vap, va_create_time) - #define HGFS_VATTR_CHANGE_TIME_SET_SUPPORTED(vap) \ - VATTR_SET_SUPPORTED(vap, va_change_time) - -#elif defined __FreeBSD__ - #define HGFS_VA_DATA_SIZE va_size - #define HGFS_VA_DATA_BYTES va_bytes - #define HGFS_VA_ACCESS_TIME_SEC va_atime.tv_sec - #define HGFS_VA_ACCESS_TIME va_atime - #define HGFS_VA_MODIFY_TIME_SEC va_mtime.tv_sec - #define HGFS_VA_MODIFY_TIME va_mtime - #define HGFS_VA_CHANGE_TIME_SEC va_ctime.tv_sec - #define HGFS_VA_CHANGE_TIME va_ctime - #define HGFS_VA_CREATE_TIME_SEC va_birthtime.tv_sec - #define HGFS_VA_CREATE_TIME va_birthtime - #define HGFS_VA_BLOCK_SIZE va_blocksize - #define HGFS_VATTR_IS_ACTIVE(vap, attr) \ - (vap->attr != VNOVAL) - #define HGFS_VATTR_MODE_IS_ACTIVE(vap, mode) \ - (vap->mode != (mode_t)VNOVAL) - #define HGFS_VATTR_SIZE_IS_ACTIVE(vap, size) \ - (vap->size != (u_quad_t)VNOVAL) - #define VATTR_SET_SUPPORTED(vap, time) - #define HGFS_VATTR_BLOCKSIZE_RETURN(vap, val) \ - VATTR_RETURN(vap, va_blocksize, val) - #define HGFS_VATTR_BYTES_RETURN(vap, val) \ - VATTR_RETURN(vap, va_bytes, val) - #define HGFS_VATTR_SIZE_RETURN(vap, val) \ - VATTR_RETURN(vap, va_size, val) - - /* NULL macros */ - #define HGFS_VATTR_ACCESS_TIME_SET_SUPPORTED(vap) - #define HGFS_VATTR_MODIFY_TIME_SET_SUPPORTED(vap) - #define HGFS_VATTR_CREATE_TIME_SET_SUPPORTED(vap) - #define HGFS_VATTR_CHANGE_TIME_SET_SUPPORTED(vap) -#endif - -/* - * Types - */ - -/* - * Hgfs permissions are similar to Unix permissions in that they both include - * bits for read vs. write vs. execute permissions. Since permissions of - * owner, groups and others are passed as individual components by Hgfs, - * we need simple bit shift operations for translation between Hgfs and Unix - * permissions. - */ - -#define HGFS_ATTR_SPECIAL_PERM_SHIFT 9 -#define HGFS_ATTR_OWNER_PERM_SHIFT 6 -#define HGFS_ATTR_GROUP_PERM_SHIFT 3 - -/* Solaris times support nsecs, so only use these functions directly */ -#define HGFS_SET_TIME(unixtm, nttime) \ - HgfsConvertFromNtTimeNsec(&unixtm, nttime) -#define HGFS_GET_TIME(unixtm) \ - HgfsConvertTimeSpecToNtTime(&unixtm) - -/* Utility functions */ - -int HgfsSubmitRequest(HgfsSuperInfo *sip, HgfsKReqHandle req); -int HgfsGetStatus(HgfsKReqHandle req, uint32_t minSize); -int HgfsEscapeBuffer(char const *bufIn, uint32 sizeIn, - uint32 sizeBufOut, char *bufOut); -int HgfsUnescapeBuffer(char *bufIn, uint32 sizeIn); -int HgfsGetOpenMode(uint32 flags); -int HgfsGetOpenFlags(uint32 flags); -int HgfsMakeFullName(const char *path, uint32_t pathLen, const char *file, - size_t fileLen, char *outBuf, ssize_t bufSize); -void HgfsAttrToBSD(struct vnode *vp, const HgfsAttrV2 *hgfsAttrV2, HgfsVnodeAttr *vap); -Bool HgfsSetattrCopy(HgfsVnodeAttr *vap, HgfsAttrV2 *hgfsAttrV2, HgfsAttrHint *hints); -int HgfsStatusToBSD(HgfsStatus hgfsStatus); -Bool HgfsAttemptToCreateShare(const char *path, int flag); -int HgfsNameFromWireEncoding(const char *bufIn, uint32 bufInSize, char *bufOut, uint32 bufOutSize); -int HgfsNameToWireEncoding(const char *bufIn, uint32 bufInSize, char *bufOut, uint32 bufOutSize); - - -#endif // _HGFS_FSUTIL_H_ diff --git a/open-vm-tools/modules/freebsd/vmhgfs/hgfs_kernel.h b/open-vm-tools/modules/freebsd/vmhgfs/hgfs_kernel.h deleted file mode 100644 index 766bdbce..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/hgfs_kernel.h +++ /dev/null @@ -1,175 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * hgfs_kernel.h -- - * - * Declarations for the FreeBSD Hgfs client kernel module. All - * FreeBSD-specifc source files will include this. - */ - -#ifndef _HGFSKERNEL_H_ -#define _HGFSKERNEL_H_ - -/* - * Intended for the Hgfs client kernel module only. - */ -#define INCLUDE_ALLOW_MODULE -#include "includeCheck.h" - -/* - * System includes - */ - -#include <sys/param.h> // for <everything> -#include <sys/vnode.h> // for struct vnode - -/* - * VMware includes - */ - -#include "dbllnklst.h" - -#include "request.h" -#include "state.h" -#include "hgfs.h" -#include "hgfsProto.h" - -#include "vm_basic_types.h" -#include "vm_assert.h" - - -/* - * Macros - */ - -#define HGFS_PAYLOAD_MAX(size) (HGFS_PACKET_MAX - size) -#define HGFS_FS_NAME "vmhgfs" -#define HGFS_FS_NAME_LONG "VMware Hgfs client" -/* - * NB: Used only to provide a value for struct vattr::va_blocksize, "blocksize - * preferred for i/o". - */ -#define HGFS_BLOCKSIZE 1024 - -/* Internal error code(s) */ -#define HGFS_ERR (-1) -#define HGFS_ERR_NULL_INPUT (-50) -#define HGFS_ERR_NODEV (-51) -#define HGFS_ERR_INVAL (-52) - -#if defined __FreeBSD__ -# define HGFS_MP_TO_MNTFLAGS(mp) \ - ((mp)->mnt_flag) -# define HGFS_MP_SET_SIP(mp, sip) \ - ((mp)->mnt_data = (sip)) -# define HGFS_VP_TO_MP(vp) ((vp)->v_mount) -/* Return a pointer to mnt_stat to preserve the interface between Mac OS and FreeBSD. */ -# define HGFS_MP_TO_STATFS(mp) (&(mp)->mnt_stat) - /* Getting to sip via any vnode */ -# define HGFS_VP_TO_SIP(vp) \ - ((HgfsSuperInfo*)HGFS_VP_TO_MP(vp)->mnt_data) - -# define HGFS_VP_VI_LOCK(vp) \ - (VI_LOCK(vp)) -# define HGFS_VP_VI_UNLOCK(vp) \ - (VI_UNLOCK(vp)) -# define HGFS_VP_ISINUSE(vp, usecount) \ - ((vp)->v_usecount > usecount) -# define HGFS_MP_IS_FORCEUNMOUNT(mp) \ - (mp->mnt_kern_flag & MNTK_UNMOUNTF) -#elif defined __APPLE__ -# define HGFS_MP_TO_MNTFLAGS(mp) \ - (vfs_flags(mp)) -# define HGFS_MP_SET_SIP(mp, sip) \ - (vfs_setfsprivate(mp, sip)) -# define HGFS_VP_TO_MP(vp) (vnode_mount(vp)) -# define HGFS_MP_TO_STATFS(mp) (vfs_statfs(mp)) -# define HGFS_VP_TO_SIP(vp) \ - ((HgfsSuperInfo*)vfs_fsprivate(HGFS_VP_TO_MP(vp))) - -/* - * No concept of vnode locks are exposed to the Mac OS VFS layer, so do nothing here for - * VI_LOCK AND VI_UNLOCK. However, make sure to call the lock functions before using - * HGFS_VP_ISINUSE to preserve compatability with FreeBSD. - */ -# define HGFS_VP_VI_LOCK(vp) -# define HGFS_VP_VI_UNLOCK(vp) -# define HGFS_VP_ISINUSE(vp, usecount) \ - (vnode_isinuse(vp, usecount)) -# define HGFS_MP_IS_FORCEUNMOUNT(mp) \ - (vfs_isforce(mp)) -#endif - -#define HGFS_VP_TO_STATFS(vp) (HGFS_MP_TO_STATFS(HGFS_VP_TO_MP(vp))) - -/* - * Types - */ - - - -/* We call them *Header in the kernel code for clarity. */ -typedef HgfsReply HgfsReplyHeader; -typedef HgfsRequest HgfsRequestHeader; - -/* - * The global state structure for a single filesystem mount. This is allocated - * in HgfsVfsMount() and destroyed in HgfsVfsUnmount(). - */ -typedef struct HgfsSuperInfo { - Bool uidSet; - uid_t uid; - Bool gidSet; - gid_t gid; - /* Request container */ - HgfsKReqContainerHandle reqs; /* See request.h. */ - /* For filesystem */ - struct mount *vfsp; /* Our filesystem structure */ - struct vnode *rootVnode; /* Root vnode of the filesystem */ - HgfsFileHashTable fileHashTable; /* File hash table */ - char volumeName[MAXPATHLEN]; /* Name of the volume or share. */ -} HgfsSuperInfo; - - -/* - * Global variables - */ - -/* - * The vnode attributes between Mac OS and FreeBSD are very similar but not exactly the - * same. Fields have names have changed. However, only HgfsAttrToBSD and - * HgfsSetattrCopy care about the differences so we mash the types together to enable - * single function signatures. - */ -#if defined __FreeBSD__ - typedef struct vattr HgfsVnodeAttr; -#elif defined __APPLE__ - typedef struct vnode_attr HgfsVnodeAttr; -#endif - -#if defined __FreeBSD__ - /* Defined in vnops.c. */ - extern struct vop_vector HgfsVnodeOps; -#elif defined __APPLE__ - /* Export vnops.c file operations. */ - extern errno_t (**HgfsVnodeOps)(void *); - extern struct vnodeopv_desc *HgfsVnodeOperationVectorDescList[1]; -#endif - -#endif // ifndef _HGFSKERNEL_H_ diff --git a/open-vm-tools/modules/freebsd/vmhgfs/kernelStubs.h b/open-vm-tools/modules/freebsd/vmhgfs/kernelStubs.h deleted file mode 100644 index 800a0cf8..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/kernelStubs.h +++ /dev/null @@ -1,149 +0,0 @@ -/********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * kernelStubs.h - * - * KernelStubs implements some userspace library functions in terms - * of kernel functions to allow library userspace code to be used in a - * kernel. - */ - -#ifndef __KERNELSTUBS_H__ -#define __KERNELSTUBS_H__ - -#ifdef linux -# ifndef __KERNEL__ -# error "__KERNEL__ is not defined" -# endif -# include "driver-config.h" // Must be included before any other header files -# include "vm_basic_types.h" -# include <linux/kernel.h> -# include <linux/string.h> -#elif defined(_WIN32) -# include "vm_basic_types.h" -# include <ntddk.h> /* kernel memory APIs */ -# include <stdio.h> /* for _vsnprintf, vsprintf */ -# include <stdarg.h> /* for va_start stuff */ -# include <stdlib.h> /* for min macro. */ -# include "vm_assert.h" /* Our assert macros */ -#elif defined(__FreeBSD__) -# include "vm_basic_types.h" -# ifndef _KERNEL -# error "_KERNEL is not defined" -# endif -# include <sys/types.h> -# include <sys/malloc.h> -# include <sys/param.h> -# include <sys/kernel.h> -# include <machine/stdarg.h> -# include <sys/libkern.h> -#elif defined(__APPLE__) -# include "vm_basic_types.h" -# ifndef KERNEL -# error "KERNEL is not defined" -# endif -# include <stdarg.h> -# include <string.h> -# elif defined(sun) -# include "vm_basic_types.h" -# include <sys/types.h> -# include <sys/varargs.h> -#endif - -/* - * Function Prototypes - */ - -#if defined(linux) || defined(__APPLE__) || defined (sun) - -# ifdef linux /* if (linux) { */ -char *strdup(const char *source); -# endif - -/* Shared between Linux and Apple kernel stubs. */ -void *malloc(size_t size); -void free(void *mem); -void *calloc(size_t num, size_t len); -void *realloc(void *ptr, size_t newSize); - -#elif defined(_WIN32) /* } else if (_WIN32) { */ - -#if (_WIN32_WINNT == 0x0400) -/* The following declarations are missing on NT4. */ -typedef unsigned int UINT_PTR; -typedef unsigned int SIZE_T; - -/* No free with tag availaible on NT4 kernel! */ -#define KRNL_STUBS_FREE(P,T) ExFreePool((P)) - -#else /* _WIN32_WINNT */ -#define KRNL_STUBS_FREE(P,T) ExFreePoolWithTag((P),(T)) -/* Win 2K and later useful kernel function, documented but not declared! */ -NTKERNELAPI VOID ExFreePoolWithTag(IN PVOID P, IN ULONG Tag); -#endif /* _WIN32_WINNT */ - -#elif defined(__FreeBSD__) /* } else if (FreeBSD) { */ - -/* Kernel memory on FreeBSD is tagged for statistics and sanity checking. */ -MALLOC_DECLARE(M_VMWARE_TEMP); - -/* - * On FreeBSD, the general memory allocator for both userland and the kernel is named - * malloc, but the kernel malloc() takes more arguments. The following alias & macros - * work around this, to provide the standard malloc() API for userspace code that is - * being used in the kernel. - */ - -# undef malloc - -static INLINE void * -__compat_malloc(unsigned long size, struct malloc_type *type, int flags) { - return malloc(size, type, flags); -} - -# define malloc(size) __compat_malloc(size, M_VMWARE_TEMP, M_NOWAIT) -# define calloc(count, size) __compat_malloc((count) * (size), \ - M_VMWARE_TEMP, M_NOWAIT|M_ZERO) -# define realloc(buf, size) realloc(buf, size, M_VMWARE_TEMP, M_NOWAIT) -# define free(buf) free(buf, M_VMWARE_TEMP) -# define strchr(s,c) index(s,c) -# define strrchr(s,c) rindex(s,c) - -#endif /* } */ - -/* - * Stub functions we provide. - */ - -void Panic(const char *fmt, ...); - -char *Str_Strcpy(char *buf, const char *src, size_t maxSize); -int Str_Vsnprintf(char *str, size_t size, const char *format, - va_list arguments); -char *Str_Vasprintf(size_t *length, const char *format, - va_list arguments); -char *Str_Asprintf(size_t *length, const char *Format, ...); - -/* - * Functions the driver must implement for the stubs. - */ -EXTERN void Debug(const char *fmt, ...); - - -#endif /* __KERNELSTUBS_H__ */ diff --git a/open-vm-tools/modules/freebsd/vmhgfs/kernelStubsBSD.c b/open-vm-tools/modules/freebsd/vmhgfs/kernelStubsBSD.c deleted file mode 100644 index b6fb72f5..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/kernelStubsBSD.c +++ /dev/null @@ -1,259 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * kernelStubsBSD.c -- - * - * Stub functions for use by miscellaneous VMware code when brought into - * the FreeBSD kernel. - */ - - -#include <sys/types.h> -#include <sys/param.h> -#include <machine/stdarg.h> -#include <sys/systm.h> -#include <sys/kernel.h> - -#include "kernelStubs.h" - -MALLOC_DEFINE(M_VMWARE_TEMP, "VMwareTemp", "VMware: Temporary Allocations"); - -void Log (const char *fmt, ...) __attribute__ ((alias ("Debug"))); - - -/* - *----------------------------------------------------------------------------- - * - * Debug -- - * - * Send a debugging message to the system log and/or console. - * - * Results: - * None. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -void -Debug(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); -} - - -/* - *----------------------------------------------------------------------------- - * - * Panic -- - * - * Print a panic message & induce a kernel panic. - * - * Results: - * Does not return. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -void -Panic(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); - - panic(" "); -} - - -/* - *----------------------------------------------------------------------------- - * - * Str_Strcpy -- - * - * Wrapper around strcpy that panics if the source is too long. - * - * Results: - * Returns a pointer to buf. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -char * -Str_Strcpy(char *buf, // OUT: destination buffer - const char *src, // IN : source buffer - size_t maxSize) // IN : size of buf -{ - size_t srcLen = strlen(src); - if (srcLen >= maxSize) { - panic("%s:%d Buffer too small %p\n", __FILE__, __LINE__, buf); - } - return memcpy(buf, src, srcLen + 1); // Extra byte = terminator -} - - -/* - *---------------------------------------------------------------------- - * - * Str_Vsnprintf -- - * - * Compatibility wrapper for vsnprintf(1). - * - * Results: - * - * int - number of bytes stored in 'str' (not including null - * terminate character), -1 on overflow (insufficient space for - * null terminate is considered overflow) - * - * NB: on overflow the buffer WILL be null terminated - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -int -Str_Vsnprintf(char *str, // OUT: destination buffer - size_t size, // IN : size of str - const char *format, // IN : format for vsnprintf - va_list arguments) // IN : variadic args for vsnprintf -{ - int retval; - - retval = vsnprintf(str, size, format, arguments); - if (retval >= size) { - retval = -1; - } - return retval; -} - - -/* - *----------------------------------------------------------------------------- - * - * Str_Vasprintf -- - * - * Allocate and format a string, using the GNU libc way to specify the - * format (i.e. optionally allow the use of positional parameters) - * - * Results: - * The allocated string on success (if 'length' is not NULL, *length - * is set to the length of the allocated string) - * NULL on failure - * - * Side effects: - * None - * - *----------------------------------------------------------------------------- - */ - -char * -Str_Vasprintf(size_t *length, // OUT - const char *format, // IN - va_list arguments) // IN -{ - /* - * Simple implementation of Str_Vasprintf when userlevel libraries are not - * available (e.g. for use in drivers). We just fallback to vsnprintf, - * doubling if we didn't have enough space. - */ - unsigned int bufSize; - char *buf; - int retval; - - bufSize = strlen(format); - buf = NULL; - - do { - /* - * Initial allocation of strlen(format) * 2. Should this be tunable? - * XXX Yes, this could overflow and spin forever when you get near 2GB - * allocations. I don't care. --rrdharan - */ - - va_list tmpArgs; - - bufSize *= 2; - buf = realloc(buf, bufSize); - - if (!buf) { - return NULL; - } - - va_copy(tmpArgs, arguments); - retval = Str_Vsnprintf(buf, bufSize, format, tmpArgs); - va_end(tmpArgs); - } while (retval == -1); - - if (length) { - *length = retval; - } - - /* - * Try to trim the buffer here to save memory? - */ - return buf; -} - - -/* - *----------------------------------------------------------------------------- - * - * Str_Asprintf -- - * - * Same as Str_Vasprintf(), but parameters are passed inline --hpreg - * - * Results: - * Same as Str_Vasprintf() - * - * Side effects: - * Same as Str_Vasprintf() - * - *----------------------------------------------------------------------------- - */ - -char * -Str_Asprintf(size_t *length, // OUT - const char *format, // IN - ...) // IN -{ - va_list arguments; - char *result; - - va_start(arguments, format); - result = Str_Vasprintf(length, format, arguments); - va_end(arguments); - - return result; -} diff --git a/open-vm-tools/modules/freebsd/vmhgfs/os.c b/open-vm-tools/modules/freebsd/vmhgfs/os.c deleted file mode 100644 index 2bfae4d0..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/os.c +++ /dev/null @@ -1,928 +0,0 @@ -/********************************************************* - * Copyright (C) 2008 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * os.c -- - * - * FreeBSD specific implementations of the hgfs memory allocation - * and thread synchronization routines. - */ - -#if !defined _KERNEL -# error "This os.c file can only be compiled for the FreeBSD kernel." -#endif - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/malloc.h> -#include <sys/lock.h> // for struct mtx -#include <sys/kernel.h> -#include <vm/uma.h> // for uma_zone_t -#include <sys/kthread.h> // for kthread_create() -#include <vm/vm.h> -#include <vm/vm_extern.h> // for vnode_pager_setsize - -#include "vm_basic_types.h" -#include "os.h" -#include "debug.h" -#include "channel.h" -#include "compat_freebsd.h" - -/* - * Malloc tag for statistics, debugging, etc. - */ -MALLOC_DEFINE(M_HGFS, HGFS_FS_NAME, HGFS_FS_NAME_LONG); - -/* - * Since FreeBSD provides a zone allocator, just store a pointer to the FreeBSD - * zone allocator. - */ -typedef struct os_zone_struct { - struct uma_zone *umaZone; -} os_zone_struct; - -/* - *---------------------------------------------------------------------------- - * - * os_init -- - * - * Initialize the global memory allocation variables needed by other - * functions in this file. Must be called before any other functions in this - * file. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -os_init(void) -{ - /* NOP */ - return 0; -} - - -/* - *---------------------------------------------------------------------------- - * - * os_cleanup -- - * - * Cleanup the global variables that were created in os_init. - * Must be called if os_init was called. Other functions in this - * file cannot be called after os_cleanup is called. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_cleanup(void) -{ - /* NOP */ -} - - -/* - *---------------------------------------------------------------------------- - * - * os_zone_create -- - * - * Creates a new zone (OS_ZONE_T) from which memory allocations can - * be made. - * - * Results: - * Either an uma zone or NULL (if no memory was available). - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -OS_ZONE_T * -os_zone_create(char *zoneName, // IN - size_t objectSize, // IN - os_zone_ctor ctor, // IN - os_zone_dtor dtor, // IN - os_zone_init init, // IN - os_zone_finit finit, // IN - int align, // IN - uint32 flags) // IN -{ - OS_ZONE_T *zone; - - zone = os_malloc(sizeof *zone, M_WAITOK); - zone->umaZone = uma_zcreate(zoneName, - objectSize, ctor, dtor, init, finit, align, flags); - return zone; -} - - -/* - *---------------------------------------------------------------------------- - * - * os_zone_destroy -- - * - * _destroys a zone created with os_zone_create. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_zone_destroy(OS_ZONE_T *zone) // IN -{ - ASSERT(zone); - - uma_zdestroy(zone->umaZone); - os_free(zone, sizeof *zone); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_zone_alloc -- - * - * Allocates an object from the specified zone and calls the the zone - * initializer and constructor. - * - * Results: - * Either an allocated and initizalized object or NULL. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void * -os_zone_alloc(OS_ZONE_T *zone, // IN - int flags) // IN -{ - void *mem; - HgfsTransportChannel *channel = gHgfsChannel; - HgfsKReqObject *req; - ASSERT(zone); - ASSERT(zone->umaZone); - - mem = uma_zalloc(zone->umaZone, flags | M_ZERO); - if (mem) { - req = (HgfsKReqObject *)mem; - req->channel = channel; - } - return mem; -} - - -/* - *---------------------------------------------------------------------------- - * - * os_zone_free -- - * - * Calls the zone destructor and final initialization routine on the - * specified object and then frees the object. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_zone_free(OS_ZONE_T *zone, // IN - void *mem) // IN -{ - ASSERT(zone); - ASSERT(zone->umaZone); - - uma_zfree(zone->umaZone, mem); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_malloc -- - * - * Malloc some memory in a FreeBSD / Mac OS kernel independent manner. - * This just calls the internal kernel malloc function. According to the - * FreeBSD commments, if M_WAITOK is passed to the flags, malloc will never - * return NULL. - * - * Results: - * A pointer to allocated memory or NULL. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void * -os_malloc(size_t size, // IN - int flags) // IN -{ - return malloc(size, M_HGFS, flags); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_free -- - * - * Free some memory in a FreeBSD / Mac OS kernel independent manner. - * This just calls the internal kernel free function. - * - * Results: - * None. - * - * Side effects: - * The memory (mem) is freed. - * - *---------------------------------------------------------------------------- - */ - -void -os_free(void *mem, // IN - size_t size) // IN -{ - free(mem, M_HGFS); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_mutex_alloc_init -- - * - * Allocate and initialize a FreeBSD mutex in an OS independent way. - * Mtx_name is not used on Mac OS. - * - * Results: - * A new mtx which has been allocated and is ready for use. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -OS_MUTEX_T * -os_mutex_alloc_init(const char *mtxName) // IN -{ - OS_MUTEX_T *mtx; - mtx = os_malloc(sizeof *mtx, - M_ZERO | M_WAITOK); - mtx_init(mtx, mtxName, NULL, MTX_DEF); - return mtx; -} - - -/* - *---------------------------------------------------------------------------- - * - * os_mutex_free -- - * - * Frees a FreeBSD mutex in an OS independent way. - * - * Results: - * None. - * - * Side effects: - * The mutex (mtx) is destroyed. - * - *---------------------------------------------------------------------------- - */ - -void -os_mutex_free(OS_MUTEX_T *mtx) // IN -{ - mtx_destroy(mtx); - os_free(mtx, sizeof *mtx); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_mutex_lock -- - * - * Lock a FreeBSD mutex in an OS independent way. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_mutex_lock(OS_MUTEX_T *mtx) // IN -{ - mtx_lock(mtx); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_mutex_unlock -- - * - * Unlock a FreeBSD mutex in an OS independent way. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_mutex_unlock(OS_MUTEX_T *mtx) // IN -{ - mtx_unlock(mtx); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_rw_lock_alloc_init -- - * - * Allocate and initialize a FreeBSD rwlock in an OS independent way. - * - * Results: - * A new lock which has been allocated and is ready for use. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -OS_RWLOCK_T * -os_rw_lock_alloc_init(const char *lckName) // IN -{ - OS_RWLOCK_T *lck; - lck = os_malloc(sizeof *lck, - M_ZERO | M_WAITOK); - sx_init(lck, lckName); - return lck; -} - - -/* - *---------------------------------------------------------------------------- - * - * os_rw_lock_free -- - * - * Frees a FreeBSD rwlock in an OS independent way. - * - * Results: - * None. - * - * Side effects: - * The rwlock (lck) is destroyed. - * - *---------------------------------------------------------------------------- - */ - -void -os_rw_lock_free(OS_RWLOCK_T *lck) // IN -{ - sx_destroy(lck); - os_free(lck, sizeof *lck); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_rw_lock_lock_shared -- - * - * Lock a FreeBSD rwlock for reads in an OS independent way. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_rw_lock_lock_shared(OS_RWLOCK_T *lck) // IN -{ - sx_slock(lck); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_rw_lock_lock_exclusive -- - * - * Lock a FreeBSD rwlock for writes in an OS independent way. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_rw_lock_lock_exclusive(OS_RWLOCK_T *lck) // IN -{ - sx_xlock(lck); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_rw_lock_unlock_shared -- - * - * Unlock FreeBSD rwlock in an OS independent way. Results are - * undefined if the function caller has an exculsive lock on lck. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_rw_lock_unlock_shared(OS_RWLOCK_T *lck) // IN -{ - sx_sunlock(lck); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_rw_lock_unlock_exclusive -- - * - * Unlock FreeBSD rwlock in an OS independent way. Results are - * undefined if the function caller has an exculsive lock on lck. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_rw_lock_unlock_exclusive(OS_RWLOCK_T *lck) // IN -{ - sx_xunlock(lck); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_cv_init -- - * - * Initialize a cv under FreeBSD. Under Mac OS, we are actually passed an - * object address we will use in place of a cv in later functions. Here - * we simply do nothing. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_cv_init(OS_CV_T *cv, // IN - const char *name) // IN -{ - cv_init(cv, name); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_cv_destroy -- - * - * Destroy a cv under FreeBSD. Under Mac OS, we are actually passed an - * object address we will use in place of a cv in later functions. Here - * we simply do nothing. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_cv_destroy(OS_CV_T *cv) // IN -{ - cv_destroy(cv); -} - -/* - *---------------------------------------------------------------------------- - * - * os_cv_signal -- - * - * Signal a thread to wakeup in a FreeBSD/Mac OS independent way. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_cv_signal(OS_CV_T *cv) // IN -{ - cv_signal(cv); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_cv_wait -- - * - * Have an XNU or FreeBSD kernel thread wait until the specified condition - * is signaled. This function unlocks the mutex (mtx) before it goes to - * sleep and reacquires it after the thread wakes up. Under FreeBSD it is a - * standard condition variable. os_cv_wait will return immediately if the - * thread was interrupted. It is the callers responsibility to determine - * if a signal was delivered or the dependent condition actually occurred. - * Under FreeBSD, it is illegal to sleep while holding a lock. Callers of - * this function should not hold any locks other than the mutex (mtx) that - * is passed into the function. - * - * Results: - * Zero on success. On FreeBSD errno if interrupted. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -os_cv_wait(OS_CV_T *cv, // IN - OS_MUTEX_T *mtx) // IN -{ - return cv_wait_sig(cv, mtx); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_thread_create -- - * - * Create an Mac OS or FreeBSD kernel thread in an OS independent way. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -os_thread_create(void *function, // IN - void *parameter, // IN - const char *threadName, // IN - OS_THREAD_T *newThread) // OUT -{ - return compat_kthread_create(function, parameter, - newThread, 0, 0, threadName); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_thread_join -- - * - * Wait until the specified kernel thread exits and then return. Mtx must - * be held by the calling code and the thread (thread) is not allowed to - * exit while mtx is held. This prevents (thread) from exiting before - * the caller goes to sleep. - * - * Results: - * Zero on success. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_thread_join(OS_THREAD_T thread, // IN - OS_MUTEX_T *mtx) // IN -{ - ASSERT(mtx); - - msleep(thread, mtx, PDROP, NULL, 0); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_thread_release -- - * - * Release the OS_THREAD_T reference that was acquired in os_thread_create. - * This is a nop on FreeBSD. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_thread_release(OS_THREAD_T thread) // IN -{ - /* NOP */ -} - - -/* - *---------------------------------------------------------------------------- - * - * Hgfsthreadexit -- - * - * Called when a thread is exiting. ErrorCode is returned as the thread exit code - * under FreeBSD and ignored under Mac OS. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -os_thread_exit(int errorCode) // IN -{ - compat_kthread_exit(errorCode); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_add_atomic -- - * - * Atomically increment an integer at a given location (address) by a given - * value (amount). - * - * Results: - * The value before the addition.. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -os_add_atomic(unsigned *address, // IN - int amount) // IN -{ - return atomic_fetchadd_int(address, amount); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_utf8_conversion_needed -- - * - * It returns result depending upon whether a particular operating - * system expects utf8 strings in a format (decomposed utf8) - * different from wire format (precomposed utf8) or not. Since FreeBSD - * does not expect decomposed utf8, we return FALSE. - * - * Results: - * FALSE if conversion is not needed, TRUE if needed. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -Bool -os_utf8_conversion_needed(void) -{ - return FALSE; -} - - -/* - *---------------------------------------------------------------------------- - * - * os_component_to_utf8_decomposed -- - * - * Converts an input component into decomposed form and writes it into - * output buffer. It simply returns OS_ERR for FreeBSD. - * - * Results: - * 0 on success or OS_ERR on failure. Since this function is not - * implemented, it always returns OS_ERR. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -os_component_to_utf8_decomposed(char const *bufIn, // IN - uint32 bufSizeIn, // IN - char *bufOut, // OUT - size_t *sizeOut, // OUT - uint32 bufSizeOut) // IN -{ - NOT_IMPLEMENTED(); - return OS_ERR; -} - - -/* - *---------------------------------------------------------------------------- - * - * os_component_to_utf8_precomposed -- - * - * Converts an input component into precomposed form and writes it into - * output buffer. It simply returns OS_ERR for FreeBSD. - * - * Results: - * 0 on success or OS_ERR on failure. Since this function is not - * implemented, it always returns OS_ERR. - * - * Side effects: - * None. - *---------------------------------------------------------------------------- - */ - -int -os_component_to_utf8_precomposed(char const *bufIn, // IN - uint32 bufSizeIn, // IN - char *bufOut, // OUT - size_t *sizeOut, // OUT - uint32 bufSizeOut) // IN -{ - NOT_IMPLEMENTED(); - return OS_ERR; -} - - -/* - *---------------------------------------------------------------------------- - * - * os_path_to_utf8_precomposed -- - * - * Converts an input path into precomposed form and writes it into output - * buffer. It simply returns OS_ERR for FreeBSD. - * - * Results: - * 0 on success or OS_ERR on failure. Since this function is not - * implemented, it always returns OS_ERR. - * - * Side effects: - * None. - *---------------------------------------------------------------------------- - */ - -int -os_path_to_utf8_precomposed(char const *bufIn, // IN - uint32 bufSizeIn, // IN - char *bufOut, // OUT - uint32 bufSizeOut) // IN -{ - NOT_IMPLEMENTED(); - return OS_ERR; -} - - -/* - *---------------------------------------------------------------------------- - * - * os_SetSize -- - * - * Notifies memory management system that file size has been changed. - * - * Results: - * None. - * - * Side effects: - * None. - *---------------------------------------------------------------------------- - */ - -void -os_SetSize(struct vnode* vp, // IN: vnode which size has changed - off_t newSize) // IN: new file size -{ - vnode_pager_setsize(vp, newSize); -} - - -/* - *---------------------------------------------------------------------------- - * - * os_FlushRange -- - * - * Flushes dirty pages associated with the file. - * - * Results: - * Always retun 0 (success) for now since it is NOOP. - * - * Side effects: - * None. - *---------------------------------------------------------------------------- - */ - -int -os_FlushRange(struct vnode *vp, // IN: vnode which data needs flushing - off_t start, // IN: starting offset in the file to flush - uint32_t length) // IN: length of data to flush -{ - /* - * XXX: NOOP for now. This routine is needed to maintain coherence - * between memory mapped data and data for read/write operations. - * Will need to implement when adding support for memory mapped files to HGFS - * for FreeBsd. - */ - return 0; -} diff --git a/open-vm-tools/modules/freebsd/vmhgfs/os.h b/open-vm-tools/modules/freebsd/vmhgfs/os.h deleted file mode 100644 index 9e10bc6d..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/os.h +++ /dev/null @@ -1,135 +0,0 @@ -/********************************************************* - * Copyright (C) 2008 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - - -/* - * os.h -- - * - * Wrappers for OS specific functions that are different between Mac OS and FreeBsd. - * 1. Implementation Mac OS / FreeBSD independent memory allocation and - * thread synchronization routines. - * 2. Interaction with memory manager/pager. - */ - -#ifndef _OS_H_ -#define _OS_H_ - -#if defined __FreeBSD__ -# include <sys/param.h> // for <everything> -# include <sys/proc.h> -# include <sys/condvar.h> -# include <sys/lock.h> // for struct mtx -# include <sys/mutex.h> // for struct mtx -# include <sys/sx.h> -#elif defined __APPLE__ -# include <kern/thread.h> -# include <kern/locks.h> -#endif - -#include <sys/malloc.h> -#include "vm_basic_types.h" - -#if defined __FreeBSD__ - typedef struct proc *OS_THREAD_T; - typedef struct mtx OS_MUTEX_T; - typedef struct sx OS_RWLOCK_T; - typedef struct cv OS_CV_T; -#elif defined __APPLE__ - typedef thread_t OS_THREAD_T; - typedef lck_mtx_t OS_MUTEX_T; - typedef lck_rw_t OS_RWLOCK_T; - /* - * In Mac OS, a kernel thread waits on a 32-bit integer. To avoid collision, - * Apple recommends that threads wait on the address of an object. - */ - typedef void *OS_CV_T; -#endif - -/* OS_ERR is the error code returned by os_* functions on error. */ -#define OS_ERR (-1) - -int os_init(void); -void os_cleanup(void); - -/* - * There does not seem to be a public zone allocator exposed in Mac OS. We create - * a zone wrapper around the FreeBSD zone allocator so that we can keep the - * FreeBSD zone allocator and support Mac OS at the same time. - */ - -struct os_zone_struct; -typedef struct os_zone_struct OS_ZONE_T; - -/* - * Provide zone allocator function prototypes with the same signature as - * the ones used in the FreeBSD kernel. This way they can be used both with - * the FreeBSD uma allocator and the custom Mac OS allocation functions. - */ -typedef int (*os_zone_ctor)(void *mem, int size, void *arg, int flags); -typedef void (*os_zone_dtor)(void *mem, int size, void *arg); -typedef int (*os_zone_init)(void *mem, int size, int flags); -typedef void (*os_zone_finit)(void *mem, int size); - -OS_ZONE_T *os_zone_create(char *zoneName, size_t objectSize, - os_zone_ctor ctor, os_zone_dtor dtor, - os_zone_init init, os_zone_finit finit, - int align, uint32 flags); -void os_zone_destroy(OS_ZONE_T *zone); -void *os_zone_alloc(OS_ZONE_T *zone, int flags); -void os_zone_free(OS_ZONE_T *zone, void *mem); - -void *os_malloc(size_t size, int flags); -void os_free(void *mem, size_t size); - -extern OS_MUTEX_T *os_mutex_alloc_init(const char *mtxName); -extern void os_mutex_free(OS_MUTEX_T *mtx); -extern void os_mutex_lock(OS_MUTEX_T *mtx); -extern void os_mutex_unlock(OS_MUTEX_T *mtx); - -extern OS_RWLOCK_T *os_rw_lock_alloc_init(const char *lckName); -extern void os_rw_lock_free(OS_RWLOCK_T *lck); -extern void os_rw_lock_lock_shared(OS_RWLOCK_T *lck); -extern void os_rw_lock_lock_exclusive(OS_RWLOCK_T *lck); -extern void os_rw_lock_unlock_shared(OS_RWLOCK_T *lck); -extern void os_rw_lock_unlock_exclusive(OS_RWLOCK_T *lck); - -extern void os_cv_init(OS_CV_T *cv, const char *name); -extern void os_cv_destroy(OS_CV_T *cv); -extern void os_cv_signal(OS_CV_T *cv); -extern int os_cv_wait(OS_CV_T *cv, OS_MUTEX_T *mtx); - -extern int os_thread_create(void *function, void *parameter, - const char *threadName, OS_THREAD_T *newThread); -extern void os_thread_join(OS_THREAD_T thread, OS_MUTEX_T *mtx); -extern void os_thread_release(OS_THREAD_T thread); -extern void os_thread_exit(int errorCode); - -extern int os_add_atomic(unsigned int *address, int amount); -extern int os_component_to_utf8_decomposed(const char *bufIn, uint32 bufInSize, char *bufOut, - size_t *sizeOut, uint32 bufOutSize); -extern int os_component_to_utf8_precomposed(const char *bufIn, uint32 bufInSize, char *bufOut, - size_t *sizeOut, uint32 bufOutSize); -extern int os_path_to_utf8_precomposed(const char *bufIn, uint32 bufInSize, char *bufOut, - uint32 bufOutSize); -extern Bool os_utf8_conversion_needed(void); - -// Memory manager/pager functions -void os_SetSize(struct vnode *vp, off_t newSize); -int os_FlushRange(struct vnode *vp, off_t start, uint32_t length); - -#endif // ifndef _OS_H_ diff --git a/open-vm-tools/modules/freebsd/vmhgfs/request.c b/open-vm-tools/modules/freebsd/vmhgfs/request.c deleted file mode 100644 index b3a0cac6..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/request.c +++ /dev/null @@ -1,868 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - - -/* - * request.c -- - * - * Implementation of routines used to initialize, allocate, and move - * requests between lists. - */ - -/* - * Includes - */ - -#include "hgfs_kernel.h" -#include "requestInt.h" -#include "channel.h" - -/* - * Macros - */ - -/* - * Since the DblLnkLst_Links in the requests container is just an anchor, we want to - * skip it (e.g., get the container for the next element) - */ -#define HGFS_SIP_LIST_HEAD(sip) \ - (DblLnkLst_Container((sip)->reqs->list.next, HgfsKReqObject, fsNode)) -#define HGFS_SIP_LIST_HEAD_NODE(sip) (sip->reqs->list.next) - - -/* - * Local data - */ - -/* - * See requestInt.h for details. - */ - -DblLnkLst_Links hgfsKReqWorkItemList; -OS_MUTEX_T *hgfsKReqWorkItemLock; -OS_ZONE_T *hgfsKReqZone; - -OS_CV_T hgfsKReqWorkItemCv; - -/* - * Local functions (prototypes) - */ - -static int HgfsKReqZCtor(void *mem, int size, void *arg, int flags); -static void HgfsKReqZDtor(void *mem, int size, void *arg); -static int HgfsKReqZInit(void *mem, int size, int flags); -static void HgfsKReqZFini(void *mem, int size); - -/* - * Global functions (definitions) - */ - - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReq_SysInit -- - * - * This function simply initializes the hgfsKReqZone. This is done - * separately from the VFS initialization routine, our caller, in order - * to abstract away the request allocation & support code. - * - * Results: - * Zero on success, HGFS_ERR on error. - * - * Side effects: - * hgfsKReqZone is initialized. This routine may sleep. - * - *----------------------------------------------------------------------------- - */ - -int -HgfsKReq_SysInit(void) -{ - int ret = 0; - - hgfsKReqZone = os_zone_create(HGFS_FS_NAME "_zone", - sizeof (struct HgfsKReqObject), - HgfsKReqZCtor, HgfsKReqZDtor, HgfsKReqZInit, - HgfsKReqZFini, 0, 0); - - if (!hgfsKReqZone) { - return HGFS_ERR; - } - - hgfsKReqWorkItemLock = os_mutex_alloc_init(HGFS_FS_NAME "_workmtx"); - if (!hgfsKReqWorkItemLock) { - os_zone_destroy(hgfsKReqZone); - return HGFS_ERR; - } - - /* - * This is a nop on Mac OS because we don't actually have a condition variable - * to initialize. - */ - os_cv_init(&hgfsKReqWorkItemCv, HGFS_FS_NAME "_workcv"); - DblLnkLst_Init(&hgfsKReqWorkItemList); - - /* Spawn the worker thread. */ - ret = os_thread_create(HgfsKReqWorker, &hgfsKReqWorkerState, - "HgfsKReqWorker", &hgfsKReqWorkerThread); - - if (ret != 0) { - os_cv_destroy(&hgfsKReqWorkItemCv); - os_zone_destroy(hgfsKReqZone); - os_mutex_free(hgfsKReqWorkItemLock); - return HGFS_ERR; - } - - return 0; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReq_SysFini -- - * - * Hgfs request subsystem cleanup routine. This should be called when the - * Hgfs client module is unloaded from the kernel. - * - * Results: - * Zero on success or errno on failure. - * - * Side effects: - * This routine may (will?) sleep. hgfsKReqZone is destroyed. - * - *----------------------------------------------------------------------------- - */ - -int -HgfsKReq_SysFini(void) -{ - /* Signal the worker thread to exit. */ - os_mutex_lock(hgfsKReqWorkItemLock); - hgfsKReqWorkerState.exit = TRUE; - os_cv_signal(&hgfsKReqWorkItemCv); - - /* - * Sleep until the worker thread exits. hgfsKReqWorkItemLock is release by - * by os_thread_join. - */ - os_thread_join(hgfsKReqWorkerThread, hgfsKReqWorkItemLock); - - /* - * Destroy resources allocated during _SysInit(). - */ - os_thread_release(hgfsKReqWorkerThread); - os_zone_destroy(hgfsKReqZone); - os_cv_destroy(&hgfsKReqWorkItemCv); - os_mutex_free(hgfsKReqWorkItemLock); - - return 0; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsKReq_AllocateContainer -- - * - * Allocate a request container for a single file system mount. - * - * Results: - * Pointer to a new allocation container or NULL on failure. - * - * Side effects: - * This routine may sleep. - * - *---------------------------------------------------------------------------- - */ - -HgfsKReqContainerHandle -HgfsKReq_AllocateContainer(void) -{ - HgfsKReqContainer *container; - - container = os_malloc(sizeof (struct HgfsKReqContainer), M_WAITOK | M_ZERO); - if (!container) { - return NULL; - } - - container->listLock = os_mutex_alloc_init("hgfs_reql_mtx"); - if (!container->listLock) { - os_free(container, sizeof *container); - return NULL; - } - - DblLnkLst_Init(&container->list); - - return container; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsKReq_FreeContainer -- - * - * Free a request container. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsKReq_FreeContainer(HgfsKReqContainerHandle container) // IN: file system's - // container handle -{ - ASSERT(container); - ASSERT(DblLnkLst_IsLinked(&container->list) == FALSE); - - os_mutex_free(container->listLock); - os_free(container, sizeof(*container)); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsKReq_CancelRequests -- - * - * Cancels all allocated requests by updating their status (set to - * HGFS_REQ_ERROR) and waking up any waiting clients. Also, if linked, - * removes any items from the work item list. - * - * Results: - * None. - * - * Side effects: - * This file system's entries are removed from the work item list are - * removed. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsKReq_CancelRequests(HgfsKReqContainerHandle container) // IN: request container -{ - DblLnkLst_Links *currNode; - DblLnkLst_Links *nextNode; - - DEBUG(VM_DEBUG_REQUEST, "HgfsCancelAllRequests().\n"); - - ASSERT(container); - - /* - * 1. Lock this file system's request list. - * 2. Lock the global pending request list. - * 3. For each request in the file system's request list: - * a. Remove from the global pending request list. - * b. Lock the request. - * c. Set the request's state to HGFS_REQ_ERROR. - * d. Signal any waiters. - * e. Drop our reference, destroying the object if ours was the last. - * 4. Unlock the global pending request list. - * 5. Unlock the file system's request list. - */ - - os_mutex_lock(container->listLock); - os_mutex_lock(hgfsKReqWorkItemLock); - - DEBUG(VM_DEBUG_REQUEST, "HgfsCancelAllRequests(): traversing pending request list.\n"); - - DblLnkLst_ForEachSafe(currNode, nextNode, &container->list) { - HgfsKReqObject *req; - Bool deref = FALSE; - - /* Get a pointer to the request represented by currNode. */ - req = DblLnkLst_Container(currNode, HgfsKReqObject, fsNode); - - /* - * If linked in the pending request list, remove it. Note that we're - * transferring that list's reference to ourself. (I.e., we'll be - * responsible for decrementing the reference count and freeing if it - * reaches zero.) - */ - if (DblLnkLst_IsLinked(&req->pendingNode)) { - deref = TRUE; - DblLnkLst_Unlink1(&req->pendingNode); - } - - /* Force this over to the error state & wake up any waiters. */ - os_mutex_lock(req->stateLock); - req->state = HGFS_REQ_ERROR; - os_cv_signal(&req->stateCv); - os_mutex_unlock(req->stateLock); - - if (deref) { - if (os_add_atomic(&req->refcnt, -1) == 1) { - os_zone_free(hgfsKReqZone, req); - } - } - } - - os_mutex_unlock(hgfsKReqWorkItemLock); - os_mutex_unlock(container->listLock); - - DEBUG(VM_DEBUG_REQUEST, "HgfsCancelAllRequests() done.\n"); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsKReq_ContainerIsEmpty -- - * - * Indicates whether a file system, represented by its superinfo, has any - * outstanding HgfsKReqObjectuests. - * - * Results: - * Returns zero if list is not empty, a positive integer if it is empty. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -Bool -HgfsKReq_ContainerIsEmpty(HgfsKReqContainerHandle container) // IN: -{ - Bool result; - - ASSERT(container); - - os_mutex_lock(container->listLock); - result = DblLnkLst_IsLinked(&container->list) ? FALSE : TRUE; - os_mutex_unlock(container->listLock); - - DEBUG(VM_DEBUG_REQUEST, "Container empty value: %d\n", result); - - return result; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsKReq_AllocateRequest -- - * - * Allocates and initializes a new request structure from the request pool. - * This function blocks until a request is available or it has been - * interrupted by a signal. - * - * Results: - * Pointer to fresh HgfsKReqHandle or NULL on failure. - * - * Side effects: - * Request inserted into caller's requests container. This routine may - * sleep. - * - *---------------------------------------------------------------------------- - */ - -HgfsKReqHandle -HgfsKReq_AllocateRequest(HgfsKReqContainerHandle container, // IN: - int *errorRet) // OUT: -{ - HgfsKReqObject *req; - - ASSERT(errorRet); - ASSERT(container); - - *errorRet = 0; - - if (!gHgfsChannel) { - *errorRet = EIO; - return NULL; - } - - /* - * In case we don't have any channel currently, set up a new channel. - * Note that we remember the channel from which request was allocated - * and sent, thereby making sure that we free it via correct channel. - */ - if (gHgfsChannel->status != HGFS_CHANNEL_CONNECTED) { - if (!HgfsSetupNewChannel()) { - *errorRet = EIO; - return NULL; - } - } - - req = os_zone_alloc(hgfsKReqZone, M_WAITOK); - if (!req) { - *errorRet = ENOMEM; - return NULL; - } - - os_mutex_lock(container->listLock); - DblLnkLst_LinkLast(&container->list, &req->fsNode); - os_mutex_unlock(container->listLock); - - return req; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsKReq_ReleaseReq -- - * - * Routine for file systems to return a request to the pool. - * - * Results: - * None. - * - * Side effects: - * oldReq->refcnt will be decremented, and oldReq may be freed. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsKReq_ReleaseRequest(HgfsKReqContainerHandle container, // IN: - HgfsKReqHandle oldRequest) // IN: -{ - DEBUG(VM_DEBUG_ENTRY, "%s\n", __func__); - - ASSERT(container); - ASSERT(oldRequest); - - /* Dissociate request from this file system. */ - os_mutex_lock(container->listLock); - DblLnkLst_Unlink1(&oldRequest->fsNode); - os_mutex_unlock(container->listLock); - - /* State machine update */ - os_mutex_lock(oldRequest->stateLock); - - switch (oldRequest->state) { - case HGFS_REQ_ALLOCATED: - case HGFS_REQ_SUBMITTED: - oldRequest->state = HGFS_REQ_ABANDONED; - break; - case HGFS_REQ_ABANDONED: - panic("%s: Request (%p) already abandoned!\n", __func__, oldRequest); - break; - case HGFS_REQ_ERROR: - case HGFS_REQ_COMPLETED: - break; - default: - NOT_REACHED(); - } - - os_mutex_unlock(oldRequest->stateLock); - - /* Dereference file system from request. If refcnt goes to zero, free. */ - if (os_add_atomic(&oldRequest->refcnt, -1) == 1) { - os_zone_free(hgfsKReqZone, oldRequest); - } - - DEBUG(VM_DEBUG_REQUEST, "%s done.\n", __func__); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsKReq_SubmitRequest -- - * - * Queues caller's request for Guest <-> Host processing and waits for - * it to be processed. - * - * Results: - * Zero on success, errno if interrupted. - * - * Side effects: - * Request's state may change. - * - * Synchronization notes: - * Assumes caller holds newReq->stateLock. (Implicit from _GetNewReq.) - * - *---------------------------------------------------------------------------- - */ - -int -HgfsKReq_SubmitRequest(HgfsKReqObject *newreq) // IN: Request to enqueue -{ - int ret = 0; - - ASSERT(newreq); - DEBUG(VM_DEBUG_REQUEST, "HgfsEnqueueRequest().\n"); - - /* - * Insert request on pending request list, then alert of its arrival the - * request processor. Since the list will also reference the request, be - * sure to bump its count before unlocking the list! - */ - - os_mutex_lock(hgfsKReqWorkItemLock); - - /* - * With the work item list locked, lock our object and operate on its state. - * Typically we expect it to be in the ALLOCATED state, but if the file - * system asynchronously cancelled all requests, it may be in ERROR instead. - */ - - os_mutex_lock(newreq->stateLock); - - switch (newreq->state) { - case HGFS_REQ_ALLOCATED: - /* - * Update request's state, bump refcnt, and signal worker thread. - */ - - newreq->state = HGFS_REQ_SUBMITTED; - os_add_atomic(&newreq->refcnt, 1); - DblLnkLst_LinkLast(&hgfsKReqWorkItemList, &newreq->pendingNode); - os_cv_signal(&hgfsKReqWorkItemCv); - os_mutex_unlock(hgfsKReqWorkItemLock); - /* - * NB: We're still holding this request's state lock for use with - * cv_wait_sig. - */ - break; - - case HGFS_REQ_ERROR: - /* - * Bail ASAP. - */ - os_mutex_unlock(newreq->stateLock); - os_mutex_unlock(hgfsKReqWorkItemLock); - return EIO; - break; - - case HGFS_REQ_UNUSED: - case HGFS_REQ_SUBMITTED: - case HGFS_REQ_ABANDONED: - case HGFS_REQ_COMPLETED: - panic("Cannot submit object (%p) in its current state: %u", - newreq, newreq->state); - break; - default: - panic("Request object (%p) in unknown state: %u", newreq, newreq->state); - } - - /* Sleep until request is processed or we're interrupted. */ - while (newreq->state == HGFS_REQ_SUBMITTED && ret == 0) { - ret = os_cv_wait(&newreq->stateCv, newreq->stateLock); - } - - /* Okay, we're finished with the state lock for now. */ - os_mutex_unlock(newreq->stateLock); - - return ret; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReq_GetId -- - * - * Return this object's unique request ID. - * - * Results: - * Object's unique request ID. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -uint32_t -HgfsKReq_GetId(HgfsKReqHandle request) // IN: Request to get the ID for -{ - ASSERT(request); - - return request->id; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReq_GetPayload -- - * - * Return a pointer to the payload area of a request. Callers may write - * Hgfs packet data directly to this area. It's guaranteed to hold at - * most HGFS_PACKET_MAX (6144) bytes. For Hgfs version 3, the caller should - * explicitly write request header (HgfsRequest) into this area. - * - * Results: - * Pointer to the payload area. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -char * -HgfsKReq_GetPayload(HgfsKReqHandle request) // IN: Request to get pointer to payload -{ - ASSERT(request); - - return request->payload; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReq_GetPayloadSize -- - * - * Returns the amount of data current stored in the payload. (Typically - * used when the file system receives an Hgfs reply.) - * - * Results: - * Size of current payload in bytes. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -size_t -HgfsKReq_GetPayloadSize(HgfsKReqHandle request) // IN: Request to get the size of -{ - ASSERT(request); - - return request->payloadSize; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReq_SetPayloadSize -- - * - * Record the amount of data currently stored in the payload. (Typically - * used when the file system finishes composing its request.) - * - * Results: - * None. - * - * Side effects: - * Request object's payload size is modified. - * - *----------------------------------------------------------------------------- - */ - -void -HgfsKReq_SetPayloadSize(HgfsKReqHandle request, // IN: Request object - size_t payloadSize) // IN: New payload size -{ - ASSERT(request); - ASSERT(payloadSize <= HGFS_PACKET_MAX); - request->payloadSize = payloadSize; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsKReq_GetState -- - * - * Retrieves state of provided request. - * - * Results: - * Returns state of request. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -HgfsKReqState -HgfsKReq_GetState(HgfsKReqObject *req) // IN: Request to retrieve state of -{ - HgfsKReqState state; - - ASSERT(req); - - os_mutex_lock(req->stateLock); - state = req->state; - os_mutex_unlock(req->stateLock); - - return state; -} - - -/* - * Local functions (definitions) - */ - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReqZInit -- - * - * "The initializer is called when the memory is cached in the uma zone. - * this should be the same state that the destructor leaves the object in." - * - sys/vm/uma.h - * - * Results: - * Zero on success, errno on failure. - * - * Side effects: - * A request's mutex and condvar are initialized, ID recorded, and status - * set to HGFS_REQ_UNUSED. - * - *----------------------------------------------------------------------------- - */ - -static int -HgfsKReqZInit(void *mem, // IN: Pointer to the allocated object - int size, // IN: Size of item being initialized [ignored] - int flags) // IN: malloc(9) style flags -{ - static unsigned int id = 0; - HgfsKReqObject *req = (HgfsKReqObject *)mem; - ASSERT(size == sizeof *req); - - os_add_atomic(&id, 1); - req->id = id; - req->state = HGFS_REQ_UNUSED; - req->stateLock = os_mutex_alloc_init("hgfs_req_mtx"); - if (!req->stateLock) { - return ENOMEM; - } - - os_cv_init(&req->stateCv, "hgfs_req_cv"); - - /* Reset list pointers. */ - DblLnkLst_Init(&req->fsNode); - DblLnkLst_Init(&req->pendingNode); - DblLnkLst_Init(&req->sentNode); - - /* Clear packet of request before allocating to clients. */ - bzero(&req->__rpc_packet, sizeof req->__rpc_packet); - - return 0; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReqZFini -- - * - * "This routine is called when memory leaves a zone and is returned - * to the system for other uses. It is the counter part to the - * init function." - sys/vm/uma.h - * - * Results: - * None. - * - * Side effects: - * A request's mutex and condvar are destroyed. - * - *----------------------------------------------------------------------------- - */ - -static void -HgfsKReqZFini(void *mem, // IN: Pointer to object leaving the UMA cache - int size) // IN: Size of object [Ignored] -{ - HgfsKReqObject *req = (HgfsKReqObject *)mem; - ASSERT(size == sizeof *req); - ASSERT(req->state == HGFS_REQ_UNUSED); - os_mutex_free(req->stateLock); - os_cv_destroy(&req->stateCv); -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReqZCtor - * - * "The constructor is called just before the memory is returned - * to the user. It may block if necessary." - sys/vm/uma.h - * - * Results: - * Zero on success, errno on failure. - * - * Side effects: - * Request's state is set to HGFS_REQ_ALLOCATED, its listNode is - * initialized, and its packet is zeroed out. - * - *----------------------------------------------------------------------------- - */ - -static int -HgfsKReqZCtor(void *mem, // IN: Pointer to memory allocated to user - int size, // IN: Size of allocated object [ignored] - void *arg, // IN: Optional argument from uma_zalloc_arg [ignored] - int flags) // IN: malloc(9) flags -{ - HgfsKReqObject *req = (HgfsKReqObject *)mem; - - ASSERT(size == sizeof *req); - ASSERT(req->state == HGFS_REQ_UNUSED); - ASSERT(DblLnkLst_IsLinked(&req->fsNode) == FALSE); - ASSERT(DblLnkLst_IsLinked(&req->pendingNode) == FALSE); - - /* Initialize state & reference count. */ - req->state = HGFS_REQ_ALLOCATED; - req->refcnt = 1; - return 0; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReqZDtor - * - * "The destructor may perform operations that differ from those performed - * by the initializer, but it must leave the object in the same state. - * This IS type stable storage. This is called after EVERY zfree call." - * - sys/vm/uma.h - * - * Results: - * None. - * - * Side effects: - * Object's state is set to HGFS_REQ_UNUSED. - * - *----------------------------------------------------------------------------- - */ - -static void -HgfsKReqZDtor(void *mem, // IN: Pointer to allocated object - int size, // IN: Size of allocated object [ignored] - void *arg) // IN: Argument for uma_zfree_arg [ignored] -{ - HgfsKReqObject *req = (HgfsKReqObject *)mem; - - ASSERT(req->refcnt == 0); - ASSERT(DblLnkLst_IsLinked(&req->fsNode) == FALSE); - ASSERT(DblLnkLst_IsLinked(&req->pendingNode) == FALSE); - - req->state = HGFS_REQ_UNUSED; -} - diff --git a/open-vm-tools/modules/freebsd/vmhgfs/request.h b/open-vm-tools/modules/freebsd/vmhgfs/request.h deleted file mode 100644 index d68e9c21..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/request.h +++ /dev/null @@ -1,88 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * request.h -- - * - * Declarations for the HgfsRequest module. This interface abstracts Hgfs - * request processing from the filesystem driver. - */ - -#ifndef _REQUEST_H_ -#define _REQUEST_H_ - -#define INCLUDE_ALLOW_MODULE -#include "includeCheck.h" - -#include "dbllnklst.h" /* Double link list types */ - -/* - * Each request will traverse through this set of states. File systems may - * query the state of their request, but they may not update it. - */ -typedef enum { - HGFS_REQ_UNUSED = 1, - HGFS_REQ_ALLOCATED, - HGFS_REQ_SUBMITTED, - HGFS_REQ_ABANDONED, - HGFS_REQ_ERROR, - HGFS_REQ_COMPLETED -} HgfsKReqState; - -/* - * Opaque request handler used by the file system code. Allocated during - * HgfsKReq_AllocRequest and released at HgfsKReq_ReleaseRequest. - */ -typedef struct HgfsKReqObject * HgfsKReqHandle; - -/* - * Opaque request object container for the file system. File systems snag one - * of these during HgfsKReq_InitSip & relinquish during HgfsKReq_UninitSip. - */ -typedef struct HgfsKReqContainer * HgfsKReqContainerHandle; - - -/* - * Global functions (prototypes) - */ - -extern int HgfsKReq_SysInit(void); -extern int HgfsKReq_SysFini(void); - -extern HgfsKReqContainerHandle HgfsKReq_AllocateContainer(void); -extern void HgfsKReq_FreeContainer(HgfsKReqContainerHandle handle); -extern void HgfsKReq_CancelRequests(HgfsKReqContainerHandle handle); -extern Bool HgfsKReq_ContainerIsEmpty(HgfsKReqContainerHandle handle); - -extern HgfsKReqHandle HgfsKReq_AllocateRequest(HgfsKReqContainerHandle handle, int *ret); -extern void HgfsKReq_ReleaseRequest(HgfsKReqContainerHandle container, - HgfsKReqHandle oldRequest); -extern int HgfsKReq_SubmitRequest(HgfsKReqHandle req); -extern HgfsKReqState HgfsKReq_GetState(HgfsKReqHandle req); - -extern uint32_t HgfsKReq_GetId(HgfsKReqHandle req); -extern char * HgfsKReq_GetPayload(HgfsKReqHandle req); -extern char * HgfsKReq_GetPayload_V3(HgfsKReqHandle req); -extern char * HgfsKRep_GetPayload_V3(HgfsKReqHandle req); -extern size_t HgfsKReq_GetPayloadSize(HgfsKReqHandle req); -extern void HgfsKReq_SetPayloadSize(HgfsKReqHandle req, - size_t newSize); - - -#endif /* _REQUEST_H_ */ - diff --git a/open-vm-tools/modules/freebsd/vmhgfs/requestInt.h b/open-vm-tools/modules/freebsd/vmhgfs/requestInt.h deleted file mode 100644 index 72745935..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/requestInt.h +++ /dev/null @@ -1,188 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * requestInt.h -- - * - * Internal declarations for the HgfsRequest module. Filesystem code - * should not include this file. - */ - -#ifndef _requestInt_H_ -#define _requestInt_H_ - -#define INCLUDE_ALLOW_MODULE -#include "includeCheck.h" - -#if defined __FreeBSD__ -# include <sys/libkern.h> // common string, memcpy, etc userland routines -# include <vm/uma.h> // for the UMA (slab) allocator -#elif defined __APPLE__ -# include <string.h> -#endif - - -#include "vm_assert.h" - -#include "os.h" -#include "request.h" -#include "debug.h" - -#if defined __APPLE__ - #include "hgfsTransport.h" - #define HGFS_REQUEST_PREFIX_LENGTH MAX(HGFS_CLIENT_CMD_LEN, sizeof (HgfsVmciTransportStatus)) -#else - #define HGFS_REQUEST_PREFIX_LENGTH HGFS_CLIENT_CMD_LEN -#endif - - -/* - * Data types - */ -struct HgfsTransportChannel; - - -/* - * In-kernel representation of an Hgfs request. These objects are kept on zero, - * one, or two lists at any time. - * - * (Ideal) Lifecycle of an Hgfs request: - * - File system calls HgfsKReq_AllocateRequest to allocate a request. The - * new request's reference count is initialized to one, and it is placed - * in the filesystem's requests container. - * - File system calls HgfsKReq_SubmitRequest to submit the request for - * processing via the backdoor. At this point, request is inserted on a - * global work item list and its reference count is bumped. - * - Worker thread removes request from the work item list. Reference count is - * unchanged as the reference is simply transferred from the work item list to - * the worker thread itself. - * - When the worker thread receives a reply, it updates the request's state, - * copies in the reply data, and decrements the reference count. - * - * At any point, the file system may abort a request with - * HgfsKReq_ReleaseRequest. Doing so will involve decrementing the object's - * reference count, since the file system is giving up its reference. Whoever - * reduces the reference count to zero is responsible for freeing it. - * - * Special case -- Forced unmount of a file system: - * - * If the user forcibly unmounts the file system, the following work is done. - * - For each request object associated with a file system - * - If the item is on the work item list, it is removed from that list. The - * canceling thread is then responsible for decrementing the object's - * reference count. - * - The request's state is set to HGFS_REQ_ERROR, and a wakeup signal is - * sent to the stateCv. (If the file system had not yet submitted the - * request, it will immediately return as a failure at submission time.) - * - Without anything left to do with this request, the cancellation thread - * drops the reference count, and if it reaches zero, frees the object. - */ -typedef struct HgfsKReqObject { - DblLnkLst_Links fsNode; // Link between object and its parent file system. - DblLnkLst_Links pendingNode; // Link between object and pending request list. - DblLnkLst_Links sentNode; // Link between object and sent request list. - - unsigned int refcnt; // Object reference count - HgfsKReqState state; // Indicates state of request - OS_MUTEX_T *stateLock; // Protects state: ... - OS_CV_T stateCv; // Condition variable to wait for and signal - // presence of reply. Used with the stateLock - // above. - - uint32_t id; // The unique identifier of this request. - // Typically just incremented sequentially - // from zero. - size_t payloadSize; // Total size of payload - void *ioBuf; // Pointer to memory descriptor. - // Used for MacOS over VMCI. - - /* On which channel was the request allocated/sent ?. */ - struct HgfsTransportChannel *channel; - /* - * The file system is concerned only with the payload portion of an Hgfs - * request packet, but the RPC message opens with the command string "f ". - * - * Strangely, the HgfsBd_Dispatch routine takes a pointer to the payload, but indexes - * -backwards- from that pointer to get to the RPC command. (This was actually done - * because we wanted to vary the command - async vs. sync - on the fly without - * performing another allocation. So the buffer is sized for any command plus the - * packet, and the command is varied by the transport layer.) So, anyway, effectively - * all of __rpc_packet will be sent across the backdoor, but the file system will only - * muck with _payload. - * - * VMCI: - * Mac OS X is capable of using VMCI in which case _command will have - * HgfsVmciTransportStatus. - * - */ - struct { - char _command[HGFS_REQUEST_PREFIX_LENGTH]; - char _payload[HGFS_PACKET_MAX]; // Contains both the request and - // its reply. - } __rpc_packet; -} HgfsKReqObject; - -#define command __rpc_packet._command -#define payload __rpc_packet._payload - -/* - * Opaque container for a file system's request objects. File system operates - * only on a typedef'd handle. (See request.h.) - */ -typedef struct HgfsKReqContainer { - OS_MUTEX_T *listLock; - DblLnkLst_Links list; -} HgfsKReqContainer; - -/* - * Current state & instruction for the HgfsKReq worker thread. - */ -typedef struct HgfsKReqWState { - Bool running; // Is worker running? - Bool exit; // Set this to TRUE at module unload time. -} HgfsKReqWState; - - -/* - * Module internal variables - */ - -/* Workitem list anchor */ -extern DblLnkLst_Links hgfsKReqWorkItemList; - -/* Workitem list lock. */ -extern OS_MUTEX_T *hgfsKReqWorkItemLock; - -extern OS_CV_T hgfsKReqWorkItemCv; - -/* UMA zone (slab) for allocating HgfsKReqs. */ -extern OS_ZONE_T *hgfsKReqZone; - -/* Process structure for the worker thread */ -extern OS_THREAD_T hgfsKReqWorkerThread; -extern HgfsKReqWState hgfsKReqWorkerState; - - -/* - * Function prototypes - */ - -extern void HgfsKReqWorker(void *arg); - - -#endif // ifndef _requestInt_H_ diff --git a/open-vm-tools/modules/freebsd/vmhgfs/state.c b/open-vm-tools/modules/freebsd/vmhgfs/state.c deleted file mode 100644 index e2e8e5db..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/state.c +++ /dev/null @@ -1,1780 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * state.c -- - * - * Vnode and HgfsFile state manipulation routines. - */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/fcntl.h> - -#if defined __FreeBSD__ -# include <sys/libkern.h> -# include <sys/malloc.h> -# include "sha1.h" -# include "compat_freebsd.h" -#define vnode_get(vnode) vget(vnode, LK_SHARED, curthread) -#define vnode_rele(vnode) vrele(vnode) -#define vnode_ref(vnode) vref(vnode) -#elif defined __APPLE__ -# include <string.h> -/* - * The Mac OS kernel includes the same exact SHA1 routines as those - * provided by bora/lib/misc. Use the kernel ones under Mac OS. - */ -# include <libkern/crypto/sha1.h> -#endif - -#include "hgfs_kernel.h" -#include "state.h" -#include "debug.h" -#include "os.h" - -/* - * Macros - */ - -#define HGFS_FILE_HT_HEAD(ht, index) (ht->hashTable[index]).next -#define HGFS_FILE_HT_BUCKET(ht, index) (&ht->hashTable[index]) - -#define HGFS_IS_ROOT_FILE(sip, file) (HGFS_VP_TO_FP(sip->rootVnode) == file) -#define LCK_MTX_ASSERT(mutex) - -#if defined __APPLE__ -# define SHA1_HASH_LEN SHA_DIGEST_LENGTH - -#if defined VMX86_DEVEL -#undef LCK_MTX_ASSERT -#define LCK_MTX_ASSERT(mutex) lck_mtx_assert(mutex, LCK_MTX_ASSERT_OWNED) -#endif - -#endif - -/* - * Local functions (prototypes) - */ - -static int HgfsVnodeGetInt(struct vnode **vpp, - struct vnode *dvp, - struct HgfsSuperInfo *sip, - struct mount *vfsp, - const char *fileName, - HgfsFileType fileType, - HgfsFileHashTable *htp, - Bool rootVnode, - Bool createFile, - int permissions, - off_t fileSize); - -/* Allocation/initialization/free of open file state */ -static HgfsFile *HgfsAllocFile(const char *fileName, HgfsFileType fileType, - struct vnode *dvp, HgfsFileHashTable *htp, - int permissions, off_t fileSize); - -/* Acquiring/releasing file state */ -static HgfsFile *HgfsInsertFile(const char *fileName, - HgfsFile *fp, - HgfsFileHashTable *htp); -static void HgfsReleaseFile(HgfsFile *fp, HgfsFileHashTable *htp); -static void HgfsFileVnodeLock(HgfsFile *fp, - HgfsVnodeLockType type); -static void HgfsFileVnodeUnlock(HgfsFile *fp, - HgfsVnodeLockType type); -static int HgfsInitFile(HgfsFile *fp, struct vnode *dvp, const char *fileName, - HgfsFileType fileType, int permissions, off_t fileSize); -static void HgfsFreeFile(HgfsFile *fp); - -/* Adding/finding/removing file state from hash table */ -static void HgfsAddFile(HgfsFile *fp, HgfsFileHashTable *htp); -static HgfsFile *HgfsFindFile(const char *fileName, HgfsFileHashTable *htp); - -/* Other utility functions */ -static unsigned int HgfsFileNameHash(const char *fileName); -static void HgfsNodeIdHash(const char *fileName, uint32_t fileNameLength, - ino_t *outHash); -static Bool HgfsIsModeCompatible(HgfsMode requestedMode, HgfsMode existingMode); -/* - * Global functions - */ - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVnodeLock -- - * - * Locks the HgfsFile associated with the vnode (vp). The type specifies if - * we are locking for reads or writes. We only lock the HgfsFile on Mac OS - * because FreeBSD vnodes are locked when handed to the VFS layer and there - * is a 1:1 mapping between vnodes and HgfsFile objects so no extra locking - * is required. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsVnodeLock(struct vnode *vp, // IN: Vnode to lock - HgfsVnodeLockType type) // IN: Reader or Writer lock? -{ - HgfsFile *fp; - - ASSERT(type == HGFS_READER_LOCK || type == HGFS_WRITER_LOCK); - ASSERT(vp); - - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%p,%d,%p)\n", vp, type, fp); - - HgfsFileVnodeLock(fp, type); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVnodeUnlock -- - * - * Unlocks the HgfsFile associated with the vnode (vp). Results are - * undefined the type of lock specified is different than the one that the - * vnode was locked with originally. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsVnodeUnlock(struct vnode *vp, // IN: Vnode to unlock - HgfsVnodeLockType type) // IN: Reader or Writer lock? -{ - HgfsFile *fp; - - ASSERT(type == HGFS_READER_LOCK || type == HGFS_WRITER_LOCK); - ASSERT(vp); - - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%p,%d,%p)\n", vp, type, fp); - - HgfsFileVnodeUnlock(fp, type); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVnodeGet -- - * - * Creates a vnode for the provided filename. - * - * This will always allocate a vnode and HgfsFile. If a HgfsFile - * already exists for this filename then that is used, if a HgfsFile doesn't - * exist, one is created. - * - * Results: - * Returns 0 on success and a non-zero error code on failure. The new - * vnode is returned locked. - * - * Side effects: - * If the HgfsFile already exists and createFile is TRUE then the EEXIST error - * is returned. Otherwise if the HgfsFile already exists its reference count - * is incremented. - * If HgfsFile with the given name does not exist then HgfsFile is created. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsVnodeGet(struct vnode **vpp, // OUT: Filled with address of created vnode - struct vnode *dvp, // IN: Parent directory vnode - HgfsSuperInfo *sip, // IN: Superinfo - struct mount *vfsp, // IN: Filesystem structure - const char *fileName, // IN: Name of this file - HgfsFileType fileType, // IN: Type of file - HgfsFileHashTable *htp, // IN: File hash table - Bool createFile, // IN: Creating a new file or open existing? - int permissions, // IN: Permissions for the created file - off_t fileSize) // IN: File size if the vnode is VREG -{ - return HgfsVnodeGetInt(vpp, dvp, sip, vfsp, fileName, fileType, htp, FALSE, - createFile, permissions, fileSize); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVnodeGetRoot -- - * - * Creates a root vnode. This should only be called by the VFS mount - * function when the filesystem is first being mounted. - * - * Results: - * Returns 0 on success and a non-zero error code on failure. The new - * vnode is returned locked on FreeBSD. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsVnodeGetRoot(struct vnode **vpp, // OUT: Filled with address of created vnode - HgfsSuperInfo *sip, // IN: Superinfo - struct mount *vfsp, // IN: Filesystem structure - const char *fileName, // IN: Name of this file - HgfsFileType fileType, // IN: Type of file - HgfsFileHashTable *htp) // IN: File hash table -{ - return HgfsVnodeGetInt(vpp, NULL, sip, vfsp, fileName, fileType, htp, TRUE, - FALSE, 0, 0); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsReleaseVnodeContext -- - * - * Releases context for the provided vnode. - * - * This will free the context information associated vnode. - * - * Results: - * Returns 0 on success and a non-zero error code on failure. - * - * Side effects: - * - * - *---------------------------------------------------------------------------- - */ - -int -HgfsReleaseVnodeContext(struct vnode *vp, // IN: Vnode to release - HgfsFileHashTable *htp) // IN: Hash table pointer -{ - HgfsFile *fp; - - ASSERT(vp); - ASSERT(htp); - - DEBUG(VM_DEBUG_ENTRY, "Entering HgfsVnodePut\n"); - - /* Get our private open-file state. */ - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - /* We need to release private HGFS information asosiated with the vnode. */ - HgfsReleaseFile(fp, htp); - - return 0; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsNodeIdGet -- - * - * Gets the node id for the provided file. This will only calculate the - * node id again if a per-file state structure doesn't yet exist for this - * file. (This situation exists on a readdir since dentries are filled in - * rather than creating vnodes.) - * - * The Hgfs protocol does not provide us with unique identifiers for files - * since it must support filesystems that do not have the concept of inode - * numbers. Therefore, we must maintain a mapping from filename to node id/ - * inode numbers. This is done in a stateless manner by calculating the - * SHA-1 hash of the filename. All points in the Hgfs code that need a node - * id/inode number obtain it by either calling this function or directly - * referencing the saved node id value in the vnode, if one is available. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsNodeIdGet(HgfsFileHashTable *htp, // IN: File hash table - const char *fileName, // IN: Filename to get node id for - uint32_t fileNameLength, // IN: Length of filename - ino_t *outNodeId) // OUT: Destination for nodeid -{ - HgfsFile *fp; - - ASSERT(htp); - ASSERT(fileName); - ASSERT(outNodeId); - - os_mutex_lock(htp->mutex); - - fp = HgfsFindFile(fileName, htp); - if (fp) { - *outNodeId = fp->nodeId; - } else { - HgfsNodeIdHash(fileName, fileNameLength, outNodeId); - } - - os_mutex_unlock(htp->mutex); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsInitFileHashTable -- - * - * Initializes the hash table used to track per-file state. - * - * Results: - * Returns 0 on success and a non-zero error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsInitFileHashTable(HgfsFileHashTable *htp) // IN: Hash table to initialize -{ - int i; - - ASSERT(htp); - - htp->mutex = os_mutex_alloc_init("HgfsHashChain"); - if (!htp->mutex) { - return HGFS_ERR; - } - - for (i = 0; i < ARRAYSIZE(htp->hashTable); i++) { - DblLnkLst_Init(&htp->hashTable[i]); - } - - return 0; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDestroyFileHashTable -- - * - * Cleanup the hash table used to track per-file state. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsDestroyFileHashTable(HgfsFileHashTable *htp) -{ - ASSERT(htp); - os_mutex_free(htp->mutex); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsFileHashTableIsEmpty -- - * - * Determines whether the hash table is in an acceptable state to unmount - * the file system. - * - * Note that this is not strictly empty: if the only file in the table is - * the root of the filesystem and its reference count is 1, this is - * considered empty since this is part of the operation of unmounting the - * filesystem. - * - * Results: - * Returns TRUE if the hash table is empty and false otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -Bool -HgfsFileHashTableIsEmpty(HgfsSuperInfo *sip, // IN: Superinfo - HgfsFileHashTable *htp) // IN: File hash table -{ - int i; - - ASSERT(sip); - ASSERT(htp); - - os_mutex_lock(htp->mutex); - - /* Traverse each bucket. */ - for (i = 0; i < ARRAYSIZE(htp->hashTable); i++) { - DblLnkLst_Links *currNode = HGFS_FILE_HT_HEAD(htp, i); - - /* Visit each file in this bucket */ - while (currNode != HGFS_FILE_HT_BUCKET(htp, i)) { - HgfsFile *currFile = DblLnkLst_Container(currNode, HgfsFile, listNode); - - /* - * Here we special case the root of our filesystem. In a correct - * unmount, the root vnode of the filesystem will have an entry in the - * hash table and will have a reference count of 1. We check if the - * current entry is the root file, and if so, make sure its vnode's - * reference count is not > 1. Note that we are not mapping from file - * to vnode here (which is not possible), we are using the root vnode - * stored in the superinfo structure. This is the only vnode that - * should have multiple references associated with it because whenever - * someone calls HgfsRoot(), we return that vnode. - */ - if (HGFS_IS_ROOT_FILE(sip, currFile)) { - HGFS_VP_VI_LOCK(sip->rootVnode); - if (!HGFS_VP_ISINUSE(sip->rootVnode, 1)) { - HGFS_VP_VI_UNLOCK(sip->rootVnode); - - /* This file is okay; skip to the next one. */ - currNode = currNode->next; - continue; - } - - DEBUG(VM_DEBUG_FAIL, "HgfsFileHashTableIsEmpty: %s is in use.\n", - currFile->fileName); - - HGFS_VP_VI_UNLOCK(sip->rootVnode); - /* Fall through to failure case */ - } - - /* Fail if a file is found. */ - os_mutex_unlock(htp->mutex); - DEBUG(VM_DEBUG_FAIL, "HgfsFileHashTableIsEmpty: %s still in use.\n", - currFile->fileName); - return FALSE; - } - } - - os_mutex_unlock(htp->mutex); - - return TRUE; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsCheckAndReferenceHandle -- - * - * Determines whether one of vnode's open file handles is currently set. - * If the handle is set the function increments its reference count. - * The function must be called while holding handleLock from the correspondent - * HgfsFile structure. - * - * Results: - * Returns 0 if the handle is set and had been referenced, - * EACCES if the handle is set but has an incompatible open mode, - * ENOENT if no handle is set for the vnode - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsCheckAndReferenceHandle(struct vnode *vp, // IN: Vnode to check handle of - int requestedOpenMode, // IN: Requested open mode - HgfsOpenType openType) // IN: Requested open type -{ - HgfsFile *fp; - int ret = 0; - - ASSERT(vp); - - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - if (0 == fp->handleRefCount && 0 == fp->intHandleRefCount) { - ret = ENOENT; - DEBUG(VM_DEBUG_LOG, "No handle: mode %d type %d\n", requestedOpenMode, openType); - goto exit; - } - - if (!HgfsIsModeCompatible(requestedOpenMode, fp->mode)) { - ret = EACCES; - DEBUG(VM_DEBUG_LOG, "Incompatible modes: %d %d\n", requestedOpenMode, fp->mode); - goto exit; - } - - DEBUG(VM_DEBUG_LOG, "Compatible handle: type %d mapped %d count %d\n", - openType, fp->mmapped, fp->handleRefCount); - - /* - * Do nothing for subsequent mmap/read reference requests. - * For mmap the OS layer invokes mnomap only once - * for multiple mmap calls. - * For read we only need to reference the first real need to open, i.e. ENOENT - * is returned when there isn't a compatible handle. - */ - if (OPENREQ_MMAP == openType && fp->mmapped) { - DEBUG(VM_DEBUG_LOG, "Mmapped: already referenced %d %d\n", requestedOpenMode, fp->mode); - goto exit; - } - - if (OPENREQ_READ == openType) { - DEBUG(VM_DEBUG_LOG, "Open for Read: already referenced %d %d\n", requestedOpenMode, fp->mode); - goto exit; - } - - /* - * Reference the handle for the open. - * For the regular open and memory map calls we increment the normal - * count, for all others (e.g. create) it is an internal increment. - */ - if (OPENREQ_OPEN != openType && OPENREQ_MMAP != openType) { - fp->intHandleRefCount++; - DEBUG(VM_DEBUG_LOG, "Internal Handle Ref Cnt %d\n", fp->intHandleRefCount); - } else { - fp->handleRefCount++; - DEBUG(VM_DEBUG_LOG, "Handle Ref Cnt %d\n", fp->handleRefCount); - } - - if (!(fp->mmapped) && OPENREQ_MMAP == openType) { - fp->mmapped = TRUE; - } - -exit: - return ret; - } - - -/* - *---------------------------------------------------------------------------- - * - * HgfsSetOpenFileHandle -- - * - * Sets the file handle for the provided vnode if it has reference count - * equal to zero. The reference count of the handle must be increased when - * the handle is set. This is done with HgfsCheckAndReferenceHandle. - * Caller must hold handleLock when invoking the function. - * - * Results: - * None. - * - * Side effects: - * The handle may not be set again until it is cleared. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsSetOpenFileHandle(struct vnode *vp, // IN: Vnode to set handle for - HgfsHandle handle, // IN: Value of handle - HgfsMode openMode, // IN: Mode assosiated with the handle - HgfsOpenType openType) // IN: type of open for VNOP_ call -{ - HgfsFile *fp; - - ASSERT(vp); - - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - fp->handle = handle; - fp->mode = openMode; - fp->handleRefCount = 1; - if (OPENREQ_OPEN == openType) { - fp->handleRefCount = 1; - } else { - fp->intHandleRefCount = 1; - } - DEBUG(VM_DEBUG_STATE, "File %s handle %d ref Cnt %d Int Ref Cnt %d\n", - HGFS_VP_TO_FILENAME(vp), fp->handle, fp->handleRefCount, fp->intHandleRefCount); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsGetOpenFileHandle -- - * - * Gets the file handle for the provided vnode. - * - * Results: - * Returns 0 on success and a non-zero error code on failure. On success, - * the value of the vnode's handle is placed in outHandle. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsGetOpenFileHandle(struct vnode *vp, // IN: Vnode to get handle for - HgfsHandle *outHandle) // OUT: Filled with value of handle -{ - HgfsFile *fp; - int ret = 0; - - ASSERT(vp); - ASSERT(outHandle); - - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - os_rw_lock_lock_shared(fp->handleLock); - - if (fp->handleRefCount == 0) { - ret = HGFS_ERR; - } else { - *outHandle = fp->handle; - } - - os_rw_lock_unlock_shared(fp->handleLock); - - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsReleaseOpenFileHandle -- - * - * Decrements the reference count of one of the handles for the provided - * vnode. If the reference count becomes zero, then the handle is cleared and - * the original handle is retruned to the caller. - * - * Results: - * Returns new handle reference count. - * When the returned value is 0 returns the file handle which need to be closed - * on the host. - * Returns special value -1 if the handle had not been open. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsReleaseOpenFileHandle(struct vnode *vp, // IN: correspondent vnode - HgfsOpenType openType, // IN: open type to release - HgfsHandle *handleToClose) // OUT: Host handle to close -{ - int ret = -1; - HgfsFile *fp; - - ASSERT(vp); - - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - os_rw_lock_lock_exclusive(fp->handleLock); - - /* Make sure the reference count is not going negative! */ - ASSERT(fp->handleRefCount >= 0 || fp->intHandleRefCount > 0); - - if (fp->handleRefCount > 0 || fp->intHandleRefCount > 0) { - if (fp->handleRefCount > 0) { - --fp->handleRefCount; - } - /* - * We don't issue explicit closes for internal opens (read/create), so - * always decrement the internal count here. - */ - if (fp->intHandleRefCount > 0) { - --fp->intHandleRefCount; - } - /* Return the real not internal count. */ - ret = fp->handleRefCount; - /* If unmapping clear our flag. */ - if (OPENREQ_MMAP == openType) { - fp->mmapped = FALSE; - } - - /* If the reference count has gone to zero, clear the handle. */ - if (ret == 0) { - DEBUG(VM_DEBUG_LOG, "Last open closing handle %d\n", fp->handle); - *handleToClose = fp->handle; - fp->handle = 0; - fp->intHandleRefCount = 0; - } else { - DEBUG(VM_DEBUG_LOG, "ReleaseOpenFileHandle: refCount: %d intRefCount %d\n", - fp->handleRefCount, fp->intHandleRefCount); - } - } - os_rw_lock_unlock_exclusive(fp->handleLock); - - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsLookupExistingVnode -- - * - * Locates existing vnode in the hash table that matches given file name. - * If a vnode that corresponds the given name does not exists then the function - * returns ENOENT. - * If the vnode exists the function behavior depends on failIfExist parameter. - * When failIfExist is true then the function return EEXIST, otherwise - * function references the vnode, assigns vnode pointer to vpp and return 0. - * - * Results: - * - * Returns 0 if existing vnode is found and its address is returned in vpp or - * an error code otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsLookupExistingVnode(const char* fileName, - HgfsFileHashTable *htp, - Bool failIfExist, - struct vnode **vpp) -{ - HgfsFile* existingFp; - int err = ENOENT; - os_mutex_lock(htp->mutex); - /* First verify if a vnode for the filename is already allocated. */ - existingFp = HgfsFindFile(fileName, htp); - if (existingFp != NULL) { - DEBUG(VM_DEBUG_LOG, "Found existing vnode for %s\n", fileName); - if (failIfExist) { - err = EEXIST; - } else { - err = vnode_get(existingFp->vnodep); - if (err == 0) { - *vpp = existingFp->vnodep; - } else { - /* vnode exists but unusable, remove HGFS context assosiated with it. */ - DEBUG(VM_DEBUG_FAIL, "Removing HgfsFile assosiated with an unusable vnode\n"); - DblLnkLst_Unlink1(&existingFp->listNode); - err = ENOENT; - } - } - } - os_mutex_unlock(htp->mutex); - return err; -} - -/* - * Local functions (definitions) - */ - -/* Internal versions of public functions to allow bypassing htp locking */ - -/* - *---------------------------------------------------------------------------- - * - * HgfsVnodeGetInt -- - * - * Creates a vnode for the provided filename. - * - * If a HgfsFile already exists for this filename then it is used and the associated - * vnode is referenced and returned. - * if a HgfsFile doesn't exist, a new vnode and HgfsFile structure is created. - * - * Results: - * Returns 0 on success and a non-zero error code on failure. The new - * vnode is returned locked. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -#if defined __FreeBSD__ -static int -HgfsVnodeGetInt(struct vnode **vpp, // OUT: Filled with address of created vnode - struct vnode *dvp, // IN: Parent directory vnode - HgfsSuperInfo *sip, // IN: Superinfo - struct mount *vfsp, // IN: Filesystem structure - const char *fileName, // IN: Name of this file - HgfsFileType fileType, // IN: Tyoe of file - HgfsFileHashTable *htp, // IN: File hash - Bool rootVnode, // IN: Is this a root vnode? - Bool fileCreate, // IN: Is it a new file creation? - int permissions, // IN: Permissions for new files - off_t fileSize) // IN: Size of the file -{ - struct vnode *vp; - int ret; - - HgfsFile *fp; - HgfsFile *existingFp; - - ASSERT(vpp); - ASSERT(sip); - ASSERT(vfsp); - ASSERT(fileName); - ASSERT(htp); - ASSERT(dvp != NULL || rootVnode); - - /* First verify if a vnode for the filename is already allocated. */ - ret = HgfsLookupExistingVnode(fileName, htp, fileCreate, vpp); - if (ret != ENOENT) { - return ret; - } - - /* - * Here we need to construct the vnode for the kernel as well as our - * internal file system state. Our internal state described by - * HgfsFile structure which is kept per-file. There is no state information assosiated - * with file descriptor. The reason is that when OS invokes vnode methods - * it does not provide information about file descriptor that was used to initiate the - * IO. We have a one-to-one mapping between vnodes and HgfsFiles. - */ - if ((ret = getnewvnode(HGFS_FS_NAME, vfsp, &HgfsVnodeOps, &vp)) != 0) { - return ret; - } - - /* - * Return a locked vnode to the caller. - */ - ret = compat_lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL, curthread); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Fatal: could not acquire lock on vnode\n"); - goto destroyVnode; - } - - /* - * Now we'll initialize the vnode. We need to set the file type, vnode - * operations, flags, filesystem pointer, reference count, and device. - * After that we'll create our private structures and hang them from the - * vnode's v_data pointer. - */ - switch (fileType) { - case HGFS_FILE_TYPE_REGULAR: - vp->v_type = VREG; - break; - - case HGFS_FILE_TYPE_DIRECTORY: - vp->v_type = VDIR; - break; - - case HGFS_FILE_TYPE_SYMLINK: - vp->v_type = VLNK; - break; - - default: - /* Hgfs only supports directories and regular files */ - ret = EPERM; - goto destroyOut; - } - - /* We now allocate our private open file structure. */ - fp = (void *)HgfsAllocFile(fileName, fileType, dvp, htp, permissions, fileSize); - if (fp == NULL) { - ret = ENOMEM; - goto destroyOut; - } - - fp->vnodep = vp; - vp->v_data = fp; - /* If this is going to be the root vnode, we have to mark it as such. */ - if (rootVnode) { - vp->v_vflag |= VV_ROOT; - } - - existingFp = HgfsInsertFile(fileName, fp, htp); - - if (existingFp != NULL) { // Race occured, another thread inserted a node ahead of us - if (fileCreate) { - ret = EEXIST; - goto destroyOut; - } - compat_lockmgr(vp->v_vnlock, LK_RELEASE, NULL, curthread); - vput(vp); - vp = existingFp->vnodep; - /* - * Return a locked vnode to the caller. - */ - ret = compat_lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL, curthread); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Fatal: could not acquire lock on vnode\n"); - goto destroyVnode; - } - HgfsFreeFile(fp); - } - - /* Fill in the provided address with the new vnode. */ - *vpp = vp; - - /* Return success */ - return 0; - - /* Cleanup points for errors. */ -destroyOut: - compat_lockmgr(vp->v_vnlock, LK_RELEASE, NULL, curthread); -destroyVnode: - vput(vp); - return ret; -} - -#elif defined __APPLE__ -static int -HgfsVnodeGetInt(struct vnode **vpp, // OUT - struct vnode *dvp, // IN - HgfsSuperInfo *sip, // IN - struct mount *vfsp, // IN - const char *fileName, // IN - HgfsFileType fileType, // IN - HgfsFileHashTable *htp, // IN - Bool rootVnode, // IN - Bool fileCreate, // IN - int permissions, // IN - off_t fileSize) // IN -{ - struct vnode *vp; - struct vnode_fsparam params; - int ret; - HgfsFile *fp = NULL; - HgfsFile *existingFp; - - ASSERT(vpp); - ASSERT(sip); - ASSERT(vfsp); - ASSERT(fileName); - ASSERT(htp); - - /* First verify if a vnode for the filename is already allocated. */ - ret = HgfsLookupExistingVnode(fileName, htp, fileCreate, vpp); - if (ret != ENOENT) { - return ret; - } - - params.vnfs_mp = vfsp; - params.vnfs_str = "hgfs"; - params.vnfs_dvp = dvp; - params.vnfs_fsnode = NULL; - params.vnfs_vops = HgfsVnodeOps; - params.vnfs_marksystem = FALSE; - params.vnfs_rdev = 0; - params.vnfs_filesize = fileSize; - params.vnfs_cnp = NULL; - /* Do not let Mac OS cache vnodes for us. */ - params.vnfs_flags = VNFS_NOCACHE | VNFS_CANTCACHE; - - if (rootVnode) { - params.vnfs_markroot = TRUE; - } else { - params.vnfs_markroot = FALSE; - } - - /* - * Now we'll initialize the vnode. We need to set the file type, vnode - * operations, flags, filesystem pointer, reference count, and device. - * After that we'll create our private structures and hang them from the - * vnode's v_data pointer. - */ - switch (fileType) { - case HGFS_FILE_TYPE_REGULAR: - params.vnfs_vtype = VREG; - break; - - case HGFS_FILE_TYPE_DIRECTORY: - params.vnfs_vtype = VDIR; - break; - - case HGFS_FILE_TYPE_SYMLINK: - params.vnfs_vtype = VLNK; - break; - - default: - /* Hgfs only supports directories and regular files */ - ret = EINVAL; - goto out; - } - - fp = HgfsAllocFile(fileName, fileType, dvp, htp, permissions, fileSize); - - params.vnfs_fsnode = (void *)fp; - if (params.vnfs_fsnode == NULL) { - ret = ENOMEM; - goto out; - } - - ret = vnode_create(VNCREATE_FLAVOR, sizeof(params), ¶ms, &vp); - if (ret != 0) { - DEBUG(VM_DEBUG_FAIL, "Failed to create vnode"); - goto out; - } - - fp->vnodep = vp; - - existingFp = HgfsInsertFile(fileName, fp, htp); - - if (existingFp != NULL) { // Race occured, another thread inserted a node ahead of us - vnode_put(vp); - if (fileCreate) { - ret = EEXIST; - goto out; - } - vp = existingFp->vnodep; - HgfsFreeFile(fp); - } else { - /* Get a soft FS reference to the vnode. This tells the system that the vnode - * has data associated with it. It is considered a weak reference though, in that - * it does not prevent the system from reusing the vnode. - */ - vnode_addfsref(vp); - } - - /* Fill in the provided address with the new vnode. */ - *vpp = vp; - - /* Return success */ - return 0; - -out: - if (fp) { - HgfsFreeFile(fp); - } - return ret; -} -#else - NOT_IMPLEMENTED(); -#endif - -/* Vnode read/write lock of open file state */ - -/* - *---------------------------------------------------------------------------- - * - * HgfsFileVnodeLockInit -- - * - * Allocates and initializes the file node's vnode lock. - * NOTE: only lock the node on Mac OS because FreeBSD vnodes are locked when - * handed to the VFS layer. - * - * Results: - * TRUE if successful or FreeBSD, FALSE otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static Bool -HgfsFileVnodeLockInit(HgfsFile *fp) // IN: file state for vnode lock -{ - Bool result = TRUE; - -#if defined __APPLE__ - fp->rwVnodeLock = os_rw_lock_alloc_init("hgfs_rw_file_lock"); - if (NULL == fp->rwVnodeLock) { - result = FALSE; - } - DEBUG(VM_DEBUG_LOG, "fp = %p, rw vnode lock = %p\n", fp, fp->rwVnodeLock); -#endif - - return result; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsFileVnodeLockFree -- - * - * Destroys and releases the file node's vnode lock. - * NOTE: only lock the node on Mac OS because FreeBSD vnodes are locked when - * handed to the VFS layer. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static void -HgfsFileVnodeLockFree(HgfsFile *fp) // IN: file state for vnode lock -{ -#if defined __APPLE__ - DEBUG(VM_DEBUG_LOG, "Destroying fp = %p, rw vnode lock = %p\n", fp, fp->rwVnodeLock); - if (NULL != fp->rwVnodeLock) { - os_rw_lock_free(fp->rwVnodeLock); - } -#endif -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsFileVnodeLock -- - * - * Locks the file node's vnode lock. The type specifies if - * we are locking for reads or writes. We only lock the HgfsFile on Mac OS - * because FreeBSD vnodes are locked when handed to the VFS layer and there - * is a 1:1 mapping between vnodes and HgfsFile objects so no extra locking - * is required. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static void -HgfsFileVnodeLock(HgfsFile *fp, // IN: file state for vnode lock - HgfsVnodeLockType type) // IN: Reader or Writer lock? -{ -#if defined __APPLE__ - DEBUG(VM_DEBUG_ENTRY, "Enter(%p,%p,%d)\n", - fp, fp->rwVnodeLock, type); - - if (type == HGFS_READER_LOCK) { - os_rw_lock_lock_shared(fp->rwVnodeLock); - } else { - os_rw_lock_lock_exclusive(fp->rwVnodeLock); - } -#endif -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsFileVnodeUnlock -- - * - * Unlocks the file node's vnode lock. Results are - * undefined the type of lock specified is different than the one that the - * vnode was locked with originally. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static void -HgfsFileVnodeUnlock(HgfsFile *fp, // IN: file node to lock - HgfsVnodeLockType type) // IN: Reader or Writer lock? -{ -#if defined __APPLE__ - DEBUG(VM_DEBUG_ENTRY, "Enter(%p,%p,%d)\n", - fp, fp->rwVnodeLock, type); - - if (type == HGFS_READER_LOCK) { - os_rw_lock_unlock_shared(fp->rwVnodeLock); - } else { - os_rw_lock_unlock_exclusive(fp->rwVnodeLock); - } -#endif -} - - -/* Allocation/initialization/free of open file state */ - - -/* - *---------------------------------------------------------------------------- - * - * HgfsAllocFile -- - * - * Allocates and initializes a file structure. - * - * Results: - * Returns a pointer to the open file on success, NULL on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static HgfsFile * -HgfsAllocFile(const char *fileName, // IN: Name of file - HgfsFileType fileType, // IN: Type of file - struct vnode *dvp, // IN: Parent directory vnode - HgfsFileHashTable *htp, // IN: Hash table - int permissions, // IN: permissions for creating new files - off_t fileSize) // IN: file size -{ - HgfsFile *fp; - fp = os_malloc(sizeof *fp, M_ZERO | M_WAITOK); - - if (fp != NULL) { - DEBUG(VM_DEBUG_INFO, "HgfsGetFile: allocated HgfsFile for %s.\n", fileName); - - if (HgfsInitFile(fp, dvp, fileName, fileType, permissions, fileSize) != 0) { - DEBUG(VM_DEBUG_FAIL, "Failed to initialize HgfsFile"); - os_free(fp, sizeof(*fp)); - fp = NULL; - } - } else { - DEBUG(VM_DEBUG_FAIL, "Failed to allocate memory"); - } - return fp; -} - -/* Acquiring/releasing file state */ - -/* - *---------------------------------------------------------------------------- - * - * HgfsInsertFile -- - * - * Inserts a HgfsFile object into the hash table if the table does not - * contain an object with the same name. - * If an object with the same name already exists in the hash table - * then does nothing and just returns pointer to the existing object. - * - * Results: - * Returns a pointer to the file if there is a name collision, NULL otherwise. - * - * Side effects: - * If there is a name collision adds reference to vnode IOrefcount. - * - *---------------------------------------------------------------------------- - */ - -static HgfsFile * -HgfsInsertFile(const char *fileName, // IN: Filename to get file for - HgfsFile *fp, // IN: HgfsFile object to insert - HgfsFileHashTable *htp) // IN: Hash table to look in -{ - HgfsFile *existingFp = NULL; - - ASSERT(fileName); - ASSERT(htp); - - /* - * We try to find the file in the hash table. If it exists we increment its - * reference count and return it. - */ - os_mutex_lock(htp->mutex); - - existingFp = HgfsFindFile(fileName, htp); - if (existingFp) { // HgfsFile with this name already exists - int ret = vnode_get(existingFp->vnodep); - if (ret != 0) { - /* - * It is not clear why vnode_get may fail while there is HgfsFile in - * our hash table. Most likely it will never happen. - * However if this ever occur the safest approach is to remove - * the HgfsFile structure from the hash table but do dont free it. - * It should be freed later on when the vnode is recycled. - */ - DblLnkLst_Unlink1(&existingFp->listNode); - existingFp = NULL; - } - } - if (existingFp == NULL) { - HgfsAddFile(fp, htp); - } - - os_mutex_unlock(htp->mutex); - return existingFp; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsReleaseFile -- - * - * Removes HgfsFile structure from the hash table and releases it. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static void -HgfsReleaseFile(HgfsFile *fp, // IN: File to release - HgfsFileHashTable *htp) // IN: Hash table to look in/remove from -{ - ASSERT(fp); - ASSERT(htp); - - DEBUG(VM_DEBUG_INFO, "HgfsReleaseFile: freeing HgfsFile for %s.\n", - fp->fileName); - /* Take this file off its list */ - os_mutex_lock(htp->mutex); - DblLnkLst_Unlink1(&fp->listNode); - os_mutex_unlock(htp->mutex); - - HgfsFreeFile(fp); -} - - -/* Allocation/initialization/free of file state */ - - -/* - *---------------------------------------------------------------------------- - * - * HgfsInitFile -- - * - * Initializes a file structure. - * - * This sets the filename of the file and initializes other structure - * elements. - * - * Results: - * Returns 0 on success and a non-zero error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsInitFile(HgfsFile *fp, // IN: File to initialize - struct vnode *dvp, // IN: Paretn directory vnode - const char *fileName, // IN: Name of file - HgfsFileType fileType, // IN: Type of file - int permissions, // IN: Permissions for new files - off_t fileSize) // IN: File size -{ - int len; - - ASSERT(fp); - ASSERT(fileName); - - /* Make sure the filename will fit. */ - len = strlen(fileName); - if (len > sizeof fp->fileName - 1) { - return HGFS_ERR; - } - - fp->fileNameLength = len; - memcpy(fp->fileName, fileName, len + 1); - fp->fileName[fp->fileNameLength] = '\0'; - - /* - * We save the file type so we can recreate a vnode for the HgfsFile without - * sending a request to the Hgfs Server. - */ - fp->permissions = permissions; - - /* Initialize the links to place this file in our hash table. */ - DblLnkLst_Init(&fp->listNode); - - /* - * Fill in the node id. This serves as the inode number in directory - * entries and the node id in vnode attributes. - */ - HgfsNodeIdHash(fp->fileName, fp->fileNameLength, &fp->nodeId); - - fp->mode = 0; - fp->modeIsSet = FALSE; - - fp->handleRefCount = 0; - fp->intHandleRefCount = 0; - fp->handle = 0; - fp->mmapped = FALSE; - fp->fileSize = fileSize; - - fp->handleLock = os_rw_lock_alloc_init("hgfs_rw_handle_lock"); - if (!fp->handleLock) { - goto destroyOut; - } - - fp->modeMutex = os_mutex_alloc_init("hgfs_mtx_mode"); - if (!fp->modeMutex) { - goto destroyOut; - } - - if (!HgfsFileVnodeLockInit(fp)) { - goto destroyOut; - } - - fp->parent = dvp; - if (dvp != NULL) { - vnode_ref(dvp); - } - - /* Success */ - return 0; - -destroyOut: - ASSERT(fp); - - if (fp->handleLock) { - os_rw_lock_free(fp->handleLock); - } - - if (fp->modeMutex) { - os_mutex_free(fp->modeMutex); - } - - HgfsFileVnodeLockFree(fp); - - os_free(fp, sizeof *fp); - return HGFS_ERR; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsFreeFile -- - * - * Preforms necessary cleanup and frees the memory allocated for HgfsFile. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsFreeFile(HgfsFile *fp) // IN: HgfsFile structure to free -{ - ASSERT(fp); - os_rw_lock_free(fp->handleLock); - os_mutex_free(fp->modeMutex); - HgfsFileVnodeLockFree(fp); - if (fp->parent != NULL) { - vnode_rele(fp->parent); - } - os_free(fp, sizeof *fp); -} - - -/* Adding/finding/removing file state from hash table */ - - -/* - *---------------------------------------------------------------------------- - * - * HgfsAddFile -- - * - * Adds the file to the hash table. - * - * This function must be called with the hash table lock held. This is done - * so adding the file in the hash table can be made with any other - * operations (such as previously finding out that this file wasn't in the - * hash table). - * - * Results: - * Returns 0 on success and a non-zero error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static void -HgfsAddFile(HgfsFile *fp, // IN: File to add - HgfsFileHashTable *htp) // IN: Hash table to add to -{ - unsigned int index; - - ASSERT(fp); - ASSERT(htp); - - LCK_MTX_ASSERT(htp->mutex); - index = HgfsFileNameHash(fp->fileName); - - /* Add this file to the end of the bucket's list */ - DblLnkLst_LinkLast(HGFS_FILE_HT_HEAD(htp, index), &fp->listNode); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsFindFile -- - * - * Looks for a filename in the hash table. - * - * This function must be called with the hash table lock held. This is done - * so finding the file in the hash table and using it (after this function - * returns) can be atomic. - * - * Results: - * Returns a pointer to the file if found, NULL otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static HgfsFile * -HgfsFindFile(const char *fileName, // IN: Filename to look for - HgfsFileHashTable *htp) // IN: Hash table to look in -{ - HgfsFile *found = NULL; - DblLnkLst_Links *currNode; - unsigned int index; - - ASSERT(fileName); - ASSERT(htp); - LCK_MTX_ASSERT(htp->mutex); - - /* Determine which bucket. */ - index = HgfsFileNameHash(fileName); - - /* Traverse the bucket's list. */ - for (currNode = HGFS_FILE_HT_HEAD(htp, index); - currNode != HGFS_FILE_HT_BUCKET(htp, index); - currNode = currNode->next) { - HgfsFile *curr; - curr = DblLnkLst_Container(currNode, HgfsFile, listNode); - - if (strcmp(curr->fileName, fileName) == 0) { - /* We found the file we want. */ - found = curr; - break; - } - } - - /* Return file if found. */ - return found; -} - - -/* Other utility functions */ - - -/* - *---------------------------------------------------------------------------- - * - * HgfsFileNameHash -- - * - * Hashes the filename to get an index into the hash table. This is known - * as the PJW string hash function and it was taken from "Mastering - * Algorithms in C". - * - * Results: - * Returns an index between 0 and HGFS_HT_NR_BUCKETS. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static unsigned int -HgfsFileNameHash(const char *fileName) // IN: Filename to hash -{ - unsigned int val = 0; - - ASSERT(fileName); - - while (*fileName != '\0') { - unsigned int tmp; - - val = (val << 4) + (*fileName); - if ((tmp = (val & 0xf0000000))) { - val = val ^ (tmp >> 24); - val = val ^ tmp; - } - - fileName++; - } - - return val % HGFS_HT_NR_BUCKETS; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsNodeIdHash -- - * - * Hashes the provided filename to generate a node id. - * - * Results: - * None. The value of the hash is filled into outHash. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static void -HgfsNodeIdHash(const char *fileName, // IN: Filename to hash - uint32_t fileNameLength, // IN: Length of the filename - ino_t *outHash) // OUT: Location to write hash to -{ - SHA1_CTX hashContext; - unsigned char digest[SHA1_HASH_LEN]; - int i; - - ASSERT(fileName); - ASSERT(outHash); - - /* Make sure we start at a consistent state. */ - memset(&hashContext, 0, sizeof hashContext); - memset(digest, 0, sizeof digest); - memset(outHash, 0, sizeof *outHash); - - /* Generate a SHA1 hash of the filename */ - SHA1Init(&hashContext); - SHA1Update(&hashContext, (unsigned const char *)fileName, fileNameLength); - SHA1Final(digest, &hashContext); - - /* - * Fold the digest into the allowable size of our hash. - * - * For each group of bytes the same size as our output hash, xor the - * contents of the digest together. If there are less than that many bytes - * left in the digest, xor each byte that's left. - */ - for(i = 0; i < sizeof digest; i += sizeof *outHash) { - int bytesLeft = sizeof digest - i; - - /* Do a byte-by-byte xor if there aren't enough bytes left in the digest */ - if (bytesLeft < sizeof *outHash) { - int j; - - for (j = 0; j < bytesLeft; j++) { - uint8 *outByte = (uint8 *)outHash + j; - uint8 *inByte = (uint8 *)((uint32_t *)(digest + i)) + j; - *outByte ^= *inByte; - } - break; - } - - /* Block xor */ - *outHash ^= *((uint32_t *)(digest + i)); - } - - /* - * Clear the most significant byte so that user space apps depending on - * a node id/inode number that's only 32 bits won't break. (For example, - * gedit's call to stat(2) returns EOVERFLOW if we don't do this.) - */ -#if 0 -# ifndef HGFS_BREAK_32BIT_USER_APPS - *((uint32_t *)outHash) ^= *((uint32_t *)outHash + 1); - *((uint32_t *)outHash + 1) = 0; -# endif -#endif - - DEBUG(VM_DEBUG_INFO, "Hash of: %s (%d) is %u\n", fileName, fileNameLength, *outHash); - - return; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsIsModeCompatible -- - * - * Verifies if the requested open mode for the file is compatible - * with already assigned open mode. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static Bool -HgfsIsModeCompatible(HgfsMode requestedMode, // IN: Requested open mode - HgfsMode existingMode) // IN: Existing open mode -{ - DEBUG(VM_DEBUG_LOG, "Compare mode %d with %d.\n", requestedMode, existingMode); - return (existingMode == HGFS_OPEN_MODE_READ_WRITE || - requestedMode == existingMode); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsSetFileSize -- - * - * Notifies virtual memory system that file size has changed. - * Required for memory mapped files to work properly. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -void -HgfsSetFileSize(struct vnode *vp, // IN: vnode which file size has changed - off_t newSize) // IN: new value for file size -{ - HgfsFile *fp; - - ASSERT(vp); - fp = HGFS_VP_TO_FP(vp); - if (fp->fileSize != newSize) { - fp->fileSize = newSize; - os_SetSize(vp, newSize); - } -} diff --git a/open-vm-tools/modules/freebsd/vmhgfs/state.h b/open-vm-tools/modules/freebsd/vmhgfs/state.h deleted file mode 100644 index 7b91b53d..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/state.h +++ /dev/null @@ -1,216 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * state.h -- - * - * Public functions, types, and macros for Hgfs state that is attached to - * vnodes. - */ - -#ifndef _STATE_H_ -#define _STATE_H_ - -/* - * Includes - */ - -#include <sys/param.h> /* MAXPATHLEN */ -#include <sys/lock.h> -#include <sys/vnode.h> /* struct vnode */ - -#include "hgfsProto.h" -#include "dbllnklst.h" -#include "os.h" - -/* - * Macros - */ - -/* Number of buckets for the HgfsInode hash table */ -#define HGFS_HT_NR_BUCKETS 5 - -/* Conversion between different state structures */ -#if defined __FreeBSD__ -# define HGFS_VP_TO_FP(vp) \ - ((HgfsFile *)(vp)->v_data) -#elif defined __APPLE__ -# define HGFS_VP_TO_FP(vp) \ - ((HgfsFile *)vnode_fsnode(vp)) -#endif - -#define HGFS_FP_TO_VP(fp) \ - (fp)->vnodep - -#define HGFS_VP_TO_FILENAME(vp) \ - HGFS_VP_TO_FP(vp)->fileName - -#define HGFS_VP_TO_FILENAME_LENGTH(vp) \ - HGFS_VP_TO_FP(vp)->fileNameLength - -#define HGFS_VP_TO_NODEID(vp) \ - HGFS_VP_TO_FP(vp)->nodeId - -#define HGFS_VP_TO_RWLOCK(vp) \ - HGFS_VP_TO_FP(vp)->rwlock - -#define HGFS_VP_TO_RWLOCKP(vp) \ - &(HGFS_VP_TO_RWLOCK(vp)) - -#define HGFS_VP_TO_PERMISSIONS(vp) \ - HGFS_VP_TO_FP(vp)->permissions - -#define HGFS_VP_TO_MMAPPED(vp) \ - HGFS_VP_TO_FP(vp)->mmapped - -#define HGFS_VP_TO_FILESIZE(vp) \ - HGFS_VP_TO_FP(vp)->fileSize - - -/* - * Types - */ - -typedef uint32_t HgfsMode; - -typedef enum HgfsVnodeLockType { - HGFS_WRITER_LOCK = 0, - HGFS_READER_LOCK = 1 -} HgfsVnodeLockType; - -typedef enum HgfsOpenType { - OPENREQ_OPEN, /* A referenced handle in response to a vnode_open. */ - OPENREQ_CREATE, /* A referenced handle in response to a vnode_create. */ - OPENREQ_READ, /* A referenced handle in response to a vnode_read. */ - OPENREQ_MMAP, /* A referenced handle in response to a vnode_mmap. */ -} HgfsOpenType; - -/* - * State kept per shared file from the host. - * - * All fields are read-only after initialization except reference count, which - * is protected by the mutex. - */ -typedef struct HgfsFile { - /* Link to place this state on the file state hash table */ - DblLnkLst_Links listNode; - /* - * Full path of file within the filesystem (that is, taking /mnt/hgfs as /). - * These are built from / in HgfsMount() and appending names as provided to - * HgfsLookup(). Saving the length in HgfsIget() saves having to calculate - * it in each HgfsMakeFullName(). - */ - char fileName[MAXPATHLEN + 1]; - uint32_t fileNameLength; - ino_t nodeId; - - /* - * A pointer back to the vnode this HgfsFile is for. - */ - struct vnode *vnodep; - - /* - * A pointer back to the parent directory vnode. - */ - struct vnode *parent; - - /* - * Mode (permissions) specified for this file to be created with. This is necessary - * because create is called with the mode then open is called without it. - * We save this value in create and access it in open. - * This field is set during initialization of HGFS and is never changed. - */ - int permissions; - - /* Mode that was used to open the handle on the host */ - HgfsMode mode; - Bool modeIsSet; - OS_MUTEX_T *modeMutex; - - /* - * Handle provided by reply to a request. If the reference count is > 0, the - * the handle is valid. - */ - uint32_t handleRefCount; - HgfsHandle handle; - OS_RWLOCK_T *handleLock; - /* - * Locked along with the above, the additional reference which is the - * internal references for opening which occurs alongside the actual open. - */ - uint32_t intHandleRefCount; - - /* - * Indicates that memory mapping has been established for the file. - * Used with the reference counting above. - */ - Bool mmapped; - - /* - * One big difference between the Mac OS and FreeBSD VFS layers is that the - * XNU kernel does not lock a vnode before it calls our VFS functions. As a - * result, we have to provide our RwLock which is locked in macos/vnops.c - * before any common functions are called. - */ -#if defined __APPLE__ - OS_RWLOCK_T *rwVnodeLock; -#endif - /* - * File size. HGFS must tell memory management system when file size is changed. - * It implies that HGFS has to know if a write request writes data beyond EOF thus - * it has to maintain local copy of file size that is kept in sync with the size - * reported to memory manager/pager. - */ - off_t fileSize; -} HgfsFile; - -/* The hash table for file state. */ -typedef struct HgfsFileHashTable { - OS_MUTEX_T *mutex; - DblLnkLst_Links hashTable[HGFS_HT_NR_BUCKETS]; -} HgfsFileHashTable; - -/* Forward declaration to prevent circular dependency between this and hgfsbsd.h. */ -struct HgfsSuperInfo; - -void HgfsVnodeLock(struct vnode *vp, HgfsVnodeLockType type); -void HgfsVnodeUnlock(struct vnode *vp, HgfsVnodeLockType type); - -int HgfsVnodeGet(struct vnode **vpp, struct vnode *dp, struct HgfsSuperInfo *sip, - struct mount *vfsp, const char *fileName, HgfsFileType fileType, - HgfsFileHashTable *htp, Bool createFile, int permissions, - off_t fileSize); -int HgfsVnodeGetRoot(struct vnode **vpp, struct HgfsSuperInfo *sip, struct mount *vfsp, - const char *fileName, HgfsFileType fileType, HgfsFileHashTable *htp); -int HgfsReleaseVnodeContext(struct vnode *vp, HgfsFileHashTable *htp); -void HgfsNodeIdGet(HgfsFileHashTable *ht, const char *fileName, - uint32_t fileNameLength, ino_t *outNodeId); -int HgfsInitFileHashTable(HgfsFileHashTable *htp); -void HgfsDestroyFileHashTable(HgfsFileHashTable *htp); -Bool HgfsFileHashTableIsEmpty(struct HgfsSuperInfo *sip, HgfsFileHashTable *htp); - -/* Handle get/set/clear functions */ -void HgfsSetOpenFileHandle(struct vnode *vp, HgfsHandle handle, - HgfsMode openMode, HgfsOpenType openType); -int HgfsGetOpenFileHandle(struct vnode *vp, HgfsHandle *outHandle); -int HgfsReleaseOpenFileHandle(struct vnode *vp, HgfsOpenType openType, HgfsHandle *handleToClose); -int HgfsCheckAndReferenceHandle(struct vnode *vp, int requestedOpenMode, HgfsOpenType openType); -int HgfsHandleIncrementRefCount(struct vnode *vp); -void HgfsSetFileSize(struct vnode *vp, off_t newSize); - -#endif /* _STATE_H_ */ diff --git a/open-vm-tools/modules/freebsd/vmhgfs/transport.c b/open-vm-tools/modules/freebsd/vmhgfs/transport.c deleted file mode 100644 index 5eb86b4e..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/transport.c +++ /dev/null @@ -1,389 +0,0 @@ -/********************************************************* - * Copyright (C) 2008 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * transport.c -- - * - * Functions that prepare HGFS packages and send them to the host. - * Implementations are shared between both Mac OS and FreeBSD. - */ - -#include <sys/param.h> // for everything -#include <sys/vnode.h> // for struct vnode -#include <sys/dirent.h> // for struct dirent - -#include "fsutil.h" -#include "debug.h" -#include "transport.h" -#include "cpName.h" -#include "os.h" - -#define HGFS_FILE_OPEN_MASK (HGFS_OPEN_VALID_MODE | \ - HGFS_OPEN_VALID_FLAGS | \ - HGFS_OPEN_VALID_SPECIAL_PERMS | \ - HGFS_OPEN_VALID_OWNER_PERMS | \ - HGFS_OPEN_VALID_GROUP_PERMS | \ - HGFS_OPEN_VALID_OTHER_PERMS | \ - HGFS_OPEN_VALID_FILE_NAME) - -/* - *---------------------------------------------------------------------------- - * - * HgfsSendOpenDirRequest -- - * - * Sends a SEARCH_OPEN request to the Hgfs server. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsSendOpenDirRequest(HgfsSuperInfo *sip, // IN: Superinfo pointer - char *fullPath, // IN: Full path for the file - uint32 fullPathLen, // IN: Length of the full path - HgfsHandle *handle) // OUT: HGFS handle for the opened file -{ - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestSearchOpenV3 *request; - HgfsReplySearchOpenV3 *reply; - uint32 reqSize; - uint32 repSize; - uint32 reqBufferSize; - int ret; - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - return ret; - } - - /* Set the correct header values */ - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestSearchOpenV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_SEARCH_OPEN_V3); - - request->dirName.flags = 0; - request->dirName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE; - request->dirName.fid = HGFS_INVALID_HANDLE; - request->reserved = 0; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - reqBufferSize = HGFS_NAME_BUFFER_SIZET(HGFS_PACKET_MAX, reqSize); - - /* - * Convert an input string to utf8 precomposed form, convert it to - * the cross platform name format and finally unescape any illegal - * filesystem characters. - */ - ret = HgfsNameToWireEncoding(fullPath, fullPathLen + 1, - request->dirName.name, - reqBufferSize); - - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "Could not encode to wire format"); - HgfsKReq_ReleaseRequest(sip->reqs, req); - return -ret; - } - - request->dirName.length = ret; - reqSize += ret; - - HgfsKReq_SetPayloadSize(req, reqSize); - - /* Submit the request to the Hgfs server */ - ret = HgfsSubmitRequest(sip, req); - if (ret == 0) { - - /* Our reply is in the request packet */ - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - reply = (HgfsReplySearchOpenV3 *)HGFS_REP_GET_PAYLOAD_V3(replyHeader); - - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - - ret = HgfsGetStatus(req, repSize); - if (ret == 0) { - *handle = reply->search; - } else { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - } - - DEBUG(VM_DEBUG_COMM, "received reply for ID %d\n", replyHeader->id); - DEBUG(VM_DEBUG_COMM, " status: %d (see hgfsProto.h)\n", replyHeader->status); - DEBUG(VM_DEBUG_COMM, " handle: %d\n", reply->search); - - HgfsKReq_ReleaseRequest(sip->reqs, req); - } - return ret; -} - -/* - *---------------------------------------------------------------------------- - * - * HgfsSendOpenRequest -- - * - * Sends an OPEN request to the Hgfs server to open an existing file. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsSendOpenRequest(HgfsSuperInfo *sip, // IN: Superinfo pointer - int openMode, // IN: HGFS mode of open - int openFlags, // IN: HGFS open flags - int permissions, // IN: Permissions of open (only when creating) - char *fullPath, // IN: Full path for the file - uint32 fullPathLen, // IN: Length of the full path - HgfsHandle *handle) // OUT: HGFS handle for the opened file -{ - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestOpenV3 *request; - HgfsReplyOpenV3 *reply; - int ret; - uint32 reqSize; - uint32 repSize; - uint32 reqBufferSize; - - DEBUG(VM_DEBUG_LOG, "Trace enter.\n"); - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - DEBUG(VM_DEBUG_FAIL, "HgfsKReq_AllocateRequest failed.\n"); - return ret; - } - - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestOpenV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_OPEN_V3); - - request->mask = HGFS_FILE_OPEN_MASK; - request->reserved1 = 0; - request->reserved2 = 0; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - reqBufferSize = HGFS_NAME_BUFFER_SIZET(HGFS_PACKET_MAX, reqSize); - request->mode = openMode; - request->flags = openFlags; - DEBUG(VM_DEBUG_COMM, "open flags are %x\n", request->flags); - - request->specialPerms = (permissions & (S_ISUID | S_ISGID | S_ISVTX)) >> - HGFS_ATTR_SPECIAL_PERM_SHIFT; - request->ownerPerms = (permissions & S_IRWXU) >> HGFS_ATTR_OWNER_PERM_SHIFT; - request->groupPerms = (permissions & S_IRWXG) >> HGFS_ATTR_GROUP_PERM_SHIFT; - request->otherPerms = permissions & S_IRWXO; - DEBUG(VM_DEBUG_COMM, "permissions are %o\n", permissions); - - request->fileName.flags = 0; - request->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE; - request->fileName.fid = HGFS_INVALID_HANDLE; - - /* - * Convert an input string to utf8 precomposed form, convert it to - * the cross platform name format and finally unescape any illegal - * filesystem characters. - */ - ret = HgfsNameToWireEncoding(fullPath, fullPathLen + 1, - request->fileName.name, - reqBufferSize); - - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "Could not encode to wire format"); - ret = -ret; - goto out; - } - request->fileName.length = ret; - reqSize += ret; - - /* Packet size includes the request and its payload. */ - HgfsKReq_SetPayloadSize(req, reqSize); - - ret = HgfsSubmitRequest(sip, req); - if (ret) { - /* HgfsSubmitRequest will destroy the request if necessary. */ - DEBUG(VM_DEBUG_FAIL, "could not submit request.\n"); - req = NULL; // Request has been deallocated by SubmitRequest - } else { - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - reply = (HgfsReplyOpenV3 *)HGFS_REP_GET_PAYLOAD_V3(replyHeader); - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - ret = HgfsGetStatus(req, repSize); - if (ret == 0) { - *handle = reply->file; - } - } -out: - if (req != NULL) { - HgfsKReq_ReleaseRequest(sip->reqs, req); - } - return ret; -} - -/* - *---------------------------------------------------------------------------- - * - * HgfsCloseServerDirHandle -- - * - * Prepares close handle request and sends it to the HGFS server - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsCloseServerDirHandle(HgfsSuperInfo *sip, // IN: Superinfo pointer - HgfsHandle handle) // IN: Handle to close -{ - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestSearchCloseV3 *request; - HgfsReplySearchCloseV3 *reply; - uint32 reqSize; - uint32 repSize; - int ret; - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - return ret; - } - - /* - * Prepare the request structure. Of note here is that the request is - * always the same size so we just set the packetSize to that. - */ - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestSearchCloseV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_SEARCH_CLOSE_V3); - - request->search = handle; - request->reserved = 0; - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - - HgfsKReq_SetPayloadSize(req, reqSize); - - /* Submit the request to the Hgfs server */ - ret = HgfsSubmitRequest(sip, req); - if (ret == 0) { - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - DEBUG(VM_DEBUG_COMM, "received reply for ID %d\n", replyHeader->id); - DEBUG(VM_DEBUG_COMM, " status: %d (see hgfsProto.h)\n", replyHeader->status); - - ret = HgfsGetStatus(req, repSize); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - if (ret != EPROTO) { - ret = EFAULT; - } - } - - HgfsKReq_ReleaseRequest(sip->reqs, req); - } - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsCloseServerFileHandle -- - * - * Prepares close handle request and sends it to the HGFS server - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsCloseServerFileHandle(HgfsSuperInfo *sip, // IN: Superinfo pointer - HgfsHandle handle) // IN: Handle to close -{ - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestCloseV3 *request; - HgfsReplyCloseV3 *reply; - uint32 reqSize; - uint32 repSize; - int ret; - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - return ret; - } - - /* - * Prepare the request structure. Of note here is that the request is - * always the same size so we just set the packetSize to that. - */ - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestCloseV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_CLOSE_V3); - - request->file = handle; - request->reserved = 0; - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - - HgfsKReq_SetPayloadSize(req, reqSize); - - /* Submit the request to the Hgfs server */ - ret = HgfsSubmitRequest(sip, req); - if (ret == 0) { - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - DEBUG(VM_DEBUG_COMM, "received reply for ID %d\n", replyHeader->id); - DEBUG(VM_DEBUG_COMM, " status: %d (see hgfsProto.h)\n", replyHeader->status); - - ret = HgfsGetStatus(req, repSize); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - if (ret != EPROTO) { - ret = EFAULT; - } - } - - HgfsKReq_ReleaseRequest(sip->reqs, req); - } - return ret; -} diff --git a/open-vm-tools/modules/freebsd/vmhgfs/transport.h b/open-vm-tools/modules/freebsd/vmhgfs/transport.h deleted file mode 100644 index 31ac7ba8..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/transport.h +++ /dev/null @@ -1,39 +0,0 @@ -/********************************************************* - * Copyright (C) 2008 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * transport.h -- - * - * Communication with HGFS server. - */ - -#ifndef _HGFS_TRANSPORT_COMMON_H_ -#define _HGFS_TRANSPORT_COMMON_H_ - -#include "hgfs_kernel.h" - -/* Internal transport functions used by both FreeBSD and Mac OS */ -int HgfsSendOpenRequest(HgfsSuperInfo *sip, int openMode, int openFlags, - int permissions, char *fullPath, - uint32 fullPathLen, HgfsHandle *handle); -int HgfsSendOpenDirRequest(HgfsSuperInfo *sip, char *fullPath, - uint32 fullPathLen, HgfsHandle *handle); -int HgfsCloseServerDirHandle(HgfsSuperInfo *sip, HgfsHandle handleToClose); -int HgfsCloseServerFileHandle(HgfsSuperInfo *sip, HgfsHandle handleToClose); - -#endif // _HGFS_TRANSPORT_COMMON_H_ diff --git a/open-vm-tools/modules/freebsd/vmhgfs/vfsops.c b/open-vm-tools/modules/freebsd/vmhgfs/vfsops.c deleted file mode 100644 index a0fa8f1d..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/vfsops.c +++ /dev/null @@ -1,477 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * vfsops.c -- - * - * VFS operations for the FreeBSD Hgfs client. - */ - - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/mount.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/systm.h> -#if __FreeBSD_version >= 700000 -#include <sys/priv.h> -#endif - -#include "hgfs_kernel.h" -#include "request.h" -#include "debug.h" -#include "hgfsDevLinux.h" -#include "os.h" -#include "compat_freebsd.h" -#include "vfsopscommon.h" - -/* - * Local functions (prototypes) - */ - -static vfs_mount_t HgfsVfsMount; -static vfs_unmount_t HgfsVfsUnmount; -static vfs_root_t HgfsVfsRoot; -static vfs_statfs_t HgfsVfsStatfs; -static vfs_init_t HgfsVfsInit; -static vfs_uninit_t HgfsVfsUninit; - - -/* - * Global data - */ - -/* - * Hgfs VFS operations vector - */ -static struct vfsops HgfsVfsOps = { - .vfs_mount = HgfsVfsMount, - .vfs_unmount = HgfsVfsUnmount, - .vfs_root = HgfsVfsRoot, - .vfs_quotactl = vfs_stdquotactl, - .vfs_statfs = HgfsVfsStatfs, - .vfs_sync = vfs_stdsync, - .vfs_vget = vfs_stdvget, - .vfs_fhtovp = vfs_stdfhtovp, - .vfs_checkexp = vfs_stdcheckexp, -#if __FreeBSD_version < 700000 - .vfs_vptofh = vfs_stdvptofh, -#endif - .vfs_init = HgfsVfsInit, - .vfs_uninit = HgfsVfsUninit, - .vfs_extattrctl = vfs_stdextattrctl, - .vfs_sysctl = vfs_stdsysctl, -}; - -/* - * Kernel module glue to execute init/uninit at load/unload. - */ -VFS_SET(HgfsVfsOps, vmhgfs, 0); - - -/* - * Local functions (definitions) - */ - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVfsMount - * - * "The VFS_MOUNT() macro mounts a file system into the system's - * namespace or updates the attributes of an already mounted file - * system." (VFS_MOUNT(9).) - * - * Results: - * Zero on success, an appropriate system error on failure. - * - * Side effects: - * Done. - * - *----------------------------------------------------------------------------- - */ - -static int -HgfsVfsMount(struct mount *mp, // IN: structure representing the file system - struct thread *td) // IN: thread which is mounting the file system -{ - HgfsSuperInfo *sip; - struct vnode *vp; - int ret = 0; - char *target; - int error; - int size; - Bool *uidSet = NULL; - int *uid = NULL; - Bool *gidSet = NULL; - int *gid = NULL; - - /* - * - Examine/validate mount flags from userland. - * - Grab mount options from userland, validate. (Paths, etc.) - * - Allocate HgfsSuperInfo, root vnode; bind the two. - * - Update mnt_flag/mnt_kern_flags (ex: MPSAFE?) - * - vfs_getnewfsid - * - vfs_mountedfrom - */ - - /* - * We do not support any of the user's mount options, so fail any mount - * attempt with a non-zero mnt_flag. (It'd be quite a shock to find out - * that a share successfully mounted read-only is really writeable!) - */ - if (mp->mnt_flag != 0) { - return EOPNOTSUPP; - } - - /* - * Since Hgfs requires the caller to be root, only allow mount attempts made - * by the superuser. - */ - if ((ret = suser(td)) != 0) { - return ret; - } - - /* - * Allocate a new HgfsSuperInfo structure. This is the super structure - * maintained for each file system. (With M_WAITOK, this call cannot fail.) - */ - sip = os_malloc(sizeof *sip, M_WAITOK | M_ZERO); - mp->mnt_data = sip; - - error = HgfsInitFileHashTable(&sip->fileHashTable); - if (error) { - goto out; - } - - /* - * Allocate the root vnode, then record it and the file system information - * in our superinfo. - */ - error = HgfsVnodeGetRoot(&vp, sip, mp, "/", - HGFS_FILE_TYPE_DIRECTORY, &sip->fileHashTable); - if (error) { - HgfsDestroyFileHashTable(&sip->fileHashTable); - goto out; - } - - sip->vfsp = mp; - sip->rootVnode = vp; - - /* We're finished with the root vnode, so unlock it. */ - COMPAT_VOP_UNLOCK(vp, 0, td); - - /* - * Initialize this file system's Hgfs requests container. - */ - sip->reqs = HgfsKReq_AllocateContainer(); - - /* - * Since this implementation supports fine-grained locking, inform the kernel - * that we're MPSAFE. (This is in the context of protecting its own data - * structures, not oplocks/leases with the VM's host.) - */ - MNT_ILOCK(mp); - mp->mnt_kern_flag |= MNTK_MPSAFE; - MNT_IUNLOCK(mp); - - /* Get a new unique filesystem ID */ - vfs_getnewfsid(mp); - - error = vfs_getopt(mp->mnt_optnew, "target", (void **)&target, &size); - if (error || target[size - 1] != '\0') { - target = "host:hgfs"; - } - - /* Get uidSet */ - error = vfs_getopt(mp->mnt_optnew, "uidSet", (void**)&uidSet, &size); - - if (!error && size == sizeof(Bool) && uidSet) { - sip->uidSet = *uidSet; - } else { - sip->uidSet = FALSE; - } - - /* Get uid */ - error = vfs_getopt(mp->mnt_optnew, "uid", (void**)&uid, &size); - - if (!error && size == sizeof(int) && uid) { - sip->uid = *uid; - } else { - sip->uidSet = FALSE; - } - - /* Get gidSet */ - error = vfs_getopt(mp->mnt_optnew, "gidSet", (void**)&gidSet, &size); - - if (!error && size == sizeof(Bool) && gidSet) { - sip->gidSet = *gidSet; - } else { - sip->gidSet = FALSE; - } - - /* Get gid */ - error = vfs_getopt(mp->mnt_optnew, "gid", (void**)&gid, &size); - - if (!error && size == sizeof(int) && gid) { - sip->gid = *gid; - } else { - sip->gidSet = FALSE; - } - - vfs_mountedfrom(mp, target); - - /* - * Fill in the statfs structure. Note that even if HgfsStatfsInt - * fails, we shall just log the error and move on, since it is - * not a critical operation. - */ - error = HgfsStatfsInt(vp, &mp->mnt_stat); - if (error) { - DEBUG(VM_DEBUG_FAIL, "HgfsStatfsInt failed with ret = %d\n", ret); - error = 0; - } - - DEBUG(VM_DEBUG_LOAD, "Exit\n"); - -out: - if (error) { - os_free(sip, sizeof *sip); - } - - return error; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVfsUnmount -- - * - * "VFS_UNMOUNT -- unmount a file system", VFS_UNMOUNT(9). - * - * Results: - * Zero if filesystem unmounted, otherwise errno. - * - * Side effects: - * This call may fail if the filesystem is busy & MNT_FORCE not set. - * - *----------------------------------------------------------------------------- - */ - -static int -HgfsVfsUnmount(struct mount *mp, int mntflags, struct thread *td) -{ - HgfsSuperInfo *sip; - int ret = 0; - int flags = 0; - - sip = (HgfsSuperInfo *)mp->mnt_data; - - ASSERT(sip); - - /* - * If there are pending requests & we're not being forced out, tell the user - * that we're still busy. - */ - if (((mntflags & MNT_FORCE) == 0) && - ((HgfsKReq_ContainerIsEmpty(sip->reqs) == FALSE) || - (HgfsFileHashTableIsEmpty(sip, &sip->fileHashTable) == FALSE))) { - return EBUSY; - } - - /* - * If the user wants us out, cancel all pending Hgfs requests and fail all - * existing vnode operations. - */ - if (mntflags & MNT_FORCE) { - HgfsKReq_CancelRequests(sip->reqs); - flags |= FORCECLOSE; - } - - /* - * Vflush will wait until all pending vnode operations are complete. - */ - ret = vflush(mp, 1, flags, td); - if (ret != 0) { - return ret; - } - - HgfsDestroyFileHashTable(&sip->fileHashTable); - - /* - * Now we can throw away our superinfo. Let's reclaim everything allocated - * during HgfsVfsMount. - */ - HgfsKReq_FreeContainer(sip->reqs); - - mp->mnt_data = NULL; - os_free(sip, sizeof *sip); - - DEBUG(VM_DEBUG_LOAD, "Exit\n"); - - return 0; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVfsStatvs -- - * - * "VFS_STATFS(9) - return file system status." - * - * Results: - * Zero on success and non-zero error code on failure. - * - * Side effects: - * Caller's statfs structure is populated. - * - *----------------------------------------------------------------------------- - */ - -static int -HgfsVfsStatfs(struct mount *mp, struct statfs *sbp, struct thread *td) -{ - int ret = 0; - struct vnode *vp; - - /* We always want HGFS_BLOCKSIZE to be a power of two */ - ASSERT_ON_COMPILE(HGFS_IS_POWER_OF_TWO(HGFS_BLOCKSIZE)); - - /* - * This fills in file system ID and the type number that - * we got from a call to vfs_getnewfsid() in HgfsVfsMount() - */ - bcopy(&mp->mnt_stat, sbp, sizeof mp->mnt_stat); - - ret = HgfsVfsRoot(mp, LK_SHARED, &vp, td); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "HgfsVfsRoot failed\n"); - return ret; - } - - ret = HgfsStatfsInt(vp, sbp); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "HgfsStatfsInt failed with ret = %d\n", ret); - goto out; - } - -out: - /* Drop the reference and shared lock that we acquired in HgfsVfsRoot */ - vput(vp); - return ret; -} - -/* - *----------------------------------------------------------------------------- - * - * HgfsVfsRoot -- - * - * Retrieves the root Vnode of the specified filesystem. - * - * Results: - * Zero if successful, non-zero otherwise. - * - * Side effects: - * Sets *vpp. - * - *----------------------------------------------------------------------------- - */ - -static int -HgfsVfsRoot(struct mount *mp, // IN: Filesystem structure - int flags, // IN: Flags to vget - struct vnode **vpp, // OUT: Address of root vnode - struct thread *td) // IN: Thread structure -{ - HgfsSuperInfo *sip = (HgfsSuperInfo *)mp->mnt_data; - int ret = 0; - - *vpp = NULL; - - ret = vget(sip->rootVnode, flags, td); - if (ret == 0) { - *vpp = sip->rootVnode; - } - - return ret; -} - -/* - *----------------------------------------------------------------------------- - * - * HgfsVfsInit -- - * - * Initializes the Hgfs filesystem implementation - * - * Results: - * Zero if successful, an errno-type value otherwise. - * - * Side effects: - * Initializes the hgfs request processing system. - * - *----------------------------------------------------------------------------- - */ - -static int -HgfsVfsInit(struct vfsconf *vfsconf) -{ - int ret = 0; - - /* Initialize the os memory allocation and thread synchronization subsystem. */ - if ((ret = os_init()) != 0) { - return ret; - } - - ret = HgfsKReq_SysInit(); - - DEBUG(VM_DEBUG_LOAD, "Hgfs filesystem loaded"); - - return ret; -} - -/* - *----------------------------------------------------------------------------- - * - * HgfsVfsUninit -- - * - * Tears down the Hgfs filesystem module state - * - * Results: - * Zero if successful, an errno-type value otherwise. - * - * Side effects: - * Can no longer use any hgfs file systems. - * - *----------------------------------------------------------------------------- - */ - -static int -HgfsVfsUninit(struct vfsconf *vfsconf) -{ - int ret = 0; - - ret = HgfsKReq_SysFini(); - os_cleanup(); - - DEBUG(VM_DEBUG_LOAD, "Hgfs filesystem unloaded"); - return ret; -} diff --git a/open-vm-tools/modules/freebsd/vmhgfs/vfsopscommon.c b/open-vm-tools/modules/freebsd/vmhgfs/vfsopscommon.c deleted file mode 100644 index 5ab39057..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/vfsopscommon.c +++ /dev/null @@ -1,148 +0,0 @@ -/********************************************************* - * Copyright (C) 2008 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * vnopscommon.h -- - * - * Common VFS vfsop implementations that are shared between both Mac OS and FreeBSD. - */ - -#include <sys/param.h> // for everything -#include <sys/vnode.h> // for struct vnode - -#include "fsutil.h" -#include "state.h" -#include "debug.h" -#include "request.h" -#include "vnopscommon.h" -#include "vfsopscommon.h" - -/* - *---------------------------------------------------------------------------- - * - * HgfsStatfsInt -- - * - * Hgfs statfs method. Called by HgfsVfsStatfs on FreeBSD and - * HgfsVfsGetattr on Mac OS. - * - * Results: - * Returns 0 on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsStatfsInt(struct vnode *vp, // IN: vnode - HgfsStatfs *stat) // IN: statfs structure to fill in -{ - HgfsSuperInfo *sip; - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestQueryVolumeV3 *request; - HgfsReplyQueryVolumeV3 *reply; - uint32 reqSize; - uint32 reqBufferSize; - uint32 repSize; - char *fullPath = NULL; - uint32 fullPathLen; - int ret = 0; - - /* Get pointer to the superinfo. */ - sip = HGFS_VP_TO_SIP(vp); - if (!sip) { - DEBUG(VM_DEBUG_FAIL, "couldn't acquire superinfo\n"); - return ENOTSUP; - } - - /* Prepare the request */ - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - return ret; - } - - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestQueryVolumeV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - /* Initialize the request header */ - requestHeader->id = HgfsKReq_GetId(req); - requestHeader->op = HGFS_OP_QUERY_VOLUME_INFO_V3; - - request->fileName.flags = 0; - request->fileName.fid = HGFS_INVALID_HANDLE; - request->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE; - request->reserved = 0; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - reqBufferSize = HGFS_NAME_BUFFER_SIZET(HGFS_PACKET_MAX, reqSize); - - fullPath = HGFS_VP_TO_FILENAME(vp); - fullPathLen = HGFS_VP_TO_FILENAME_LENGTH(vp); - - ret = HgfsNameToWireEncoding(fullPath, fullPathLen + 1, - request->fileName.name, - reqBufferSize); - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "Could not encode to wire format"); - ret = -ret; - goto destroyOut; - } - request->fileName.length = ret; - reqSize += ret; - - /* The request size includes header, request and file length */ - HgfsKReq_SetPayloadSize(req, reqSize); - - ret = HgfsSubmitRequest(sip, req); - - if (ret) { - /* HgfsSubmitRequest() destroys the request if necessary */ - - goto out; - } - - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - reply = (HgfsReplyQueryVolumeV3 *)HGFS_REP_GET_PAYLOAD_V3(replyHeader); - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - - ret = HgfsGetStatus(req, repSize); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "reply was invalid"); - goto destroyOut; - } - - ret = HgfsStatusToBSD(replyHeader->status); - - if (ret) { - goto destroyOut; - } - - stat->f_bsize = HGFS_BLOCKSIZE; - stat->f_iosize = HGFS_BLOCKSIZE; - stat->f_blocks = HGFS_CONVERT_TO_BLOCKS(reply->totalBytes); - stat->f_bfree = HGFS_CONVERT_TO_BLOCKS(reply->freeBytes); - stat->f_bavail = stat->f_bfree; - -destroyOut: - HgfsKReq_ReleaseRequest(sip->reqs, req); -out: - return ret; -} diff --git a/open-vm-tools/modules/freebsd/vmhgfs/vnops.c b/open-vm-tools/modules/freebsd/vmhgfs/vnops.c deleted file mode 100644 index 1b424ec1..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/vnops.c +++ /dev/null @@ -1,864 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * vnops.c -- - * - * Vnode operations for FreeBSD HGFS client. - */ - -#include <sys/param.h> // for everything -#include <sys/vnode.h> // for struct vnode -#include <sys/mount.h> // for struct mount -#include <sys/namei.h> // for name lookup goodness -#include <sys/libkern.h> // for string & other functions -#include <sys/fcntl.h> // for in-kernel file access flags (FREAD, etc) -#include <sys/stat.h> // for file flag bitmasks (S_IRWXU, etc) -#include <sys/uio.h> // for uiomove -#include <sys/dirent.h> // for struct dirent - -#include "cpName.h" - -#include "hgfsUtil.h" - -#include "hgfs_kernel.h" -#include "request.h" -#include "state.h" -#include "debug.h" -#include "fsutil.h" -#include "vnopscommon.h" - - -/* - * Local functions (prototypes) - */ - -static vop_lookup_t HgfsVopLookup; -static vop_create_t HgfsVopCreate; -static vop_open_t HgfsVopOpen; -static vop_close_t HgfsVopClose; -static vop_access_t HgfsVopAccess; -static vop_getattr_t HgfsVopGetattr; -static vop_setattr_t HgfsVopSetattr; -static vop_read_t HgfsVopRead; -static vop_write_t HgfsVopWrite; -static vop_remove_t HgfsVopRemove; -static vop_rename_t HgfsVopRename; -static vop_mkdir_t HgfsVopMkdir; -static vop_rmdir_t HgfsVopRmdir; -static vop_readdir_t HgfsVopReaddir; -static vop_inactive_t HgfsVopInactive; -static vop_reclaim_t HgfsVopReclaim; -static vop_print_t HgfsVopPrint; -static vop_readlink_t HgfsVopReadlink; -static vop_symlink_t HgfsVopSymlink; - -/* - * Global data - */ - -/* - * HGFS vnode operations vector - */ -struct vop_vector HgfsVnodeOps = { - .vop_default = &default_vnodeops, - .vop_lookup = HgfsVopLookup, - .vop_create = HgfsVopCreate, - .vop_open = HgfsVopOpen, - .vop_close = HgfsVopClose, - .vop_access = HgfsVopAccess, - .vop_getattr = HgfsVopGetattr, - .vop_setattr = HgfsVopSetattr, - .vop_read = HgfsVopRead, - .vop_write = HgfsVopWrite, - .vop_remove = HgfsVopRemove, - .vop_rename = HgfsVopRename, - .vop_mkdir = HgfsVopMkdir, - .vop_rmdir = HgfsVopRmdir, - .vop_readdir = HgfsVopReaddir, - .vop_inactive = HgfsVopInactive, - .vop_reclaim = HgfsVopReclaim, - .vop_print = HgfsVopPrint, - .vop_readlink = HgfsVopReadlink, - .vop_symlink = HgfsVopSymlink, -}; - - -/* - * Local functions (definitions) - */ - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopLookup -- - * - * Looks in the provided directory for the specified filename by calling - * HgfsLookupInt. - * - * Results: - * Returns zero on success and ENOENT if the file cannot be found - * If file is found, a vnode representing the file is returned in vpp. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopLookup(struct vop_lookup_args *ap) -/* -struct vop_lookup_args { - struct vnode *dvp; // IN : locked vnode of search directory - struct vnode **vpp; // IN/OUT: addr to store located (locked) vnode - struct componentname *cnp; // IN : pathname component to search for -}; - */ -{ - struct vnode *dvp = ap->a_dvp; - struct vnode **vpp = ap->a_vpp; - struct componentname *cnp = ap->a_cnp; - - return HgfsLookupInt(dvp, vpp, cnp); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopCreate -- - * - * This entry point is invoked when a user calls open(2) with the O_CREAT - * flag specified. We simply call HgfsCreateInt which does the file - * creation work in a FreeBSD / Mac OS independent way. - * - * Results: - * Returns zero on success and an appropriate error code on error. - * - * Side effects: - * If the file doesn't exist, a vnode will be created. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopCreate(struct vop_create_args *ap) -/* -struct vop_create { - struct vnode *dvp; // IN : locked directory vnode - struct vnode **vp; // OUT: location to place resultant locked vnode - struct componentname *cnp; // IN : pathname component created - struct vattr *vap; // IN : attributes to create new object with - */ -{ - struct vnode *dvp = ap->a_dvp; - struct vnode **vpp = ap->a_vpp; - struct componentname *cnp = ap->a_cnp; - struct vattr *vap = ap->a_vap; - - return HgfsCreateInt(dvp, vpp, cnp, vap->va_mode); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopOpen -- - * - * Invoked when open(2) is called on a file in our filesystem. Sends an - * OPEN request to the Hgfs server with the filename of this vnode. - * - * "Opens a file referenced by the supplied vnode. The open() system call - * has already done a vop_lookup() on the path name, which returned a vnode - * pointer and then calls to vop_open(). This function typically does very - * little since most of the real work was performed by vop_lookup()." - * (Solaris Internals, p537) - * - * Results: - * Returns 0 on success and an error code on error. - * - * Side effects: - * The HgfsOpenFile for this file is given a handle that can be used on - * future read and write requests. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopOpen(struct vop_open_args *ap) -/* -struct vop_open_args { - struct vnode *vp; // IN: vnode of file to open - int mode; // IN: access mode requested by calling process - struct ucred *cred; // IN: calling process's user's credentials - struct thread *td; // IN: thread accessing file - int fdidx; // IN: file descriptor number -}; -*/ -{ - struct vnode *vp = ap->a_vp; - int mode = ap->a_mode; - - return HgfsOpenInt(vp, mode, OPENREQ_OPEN); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopClose -- - * - * Invoked when a user calls close(2) on a file in our filesystem. - * - * Calls HgfsCloseInt which handles the close in a FreeBSD / Mac OS - * independent way. - * - * Results: - * Returns 0 on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopClose(struct vop_close_args *ap) -/* -struct vop_close_args { - struct vnode *vp; // IN: vnode of object to close [exclusive lock held] - int fflag; // IN: F* flags (FWRITE, etc) on object - struct ucred *cred; // IN: calling process's user's credentials - struct thread *td; // IN: thread accessing file -}; -*/ -{ - struct vnode *vp = ap->a_vp; - int fflag = ap->a_fflag; - struct vnode *rootVnode; - int ret = 0; - - /* - * According to the FreeBSD manpage, VOP_CLOSE can be called with or - * without a lock held on vp. However, in the FreeBSD 6.2 source code, - * the only place that VOP_CLOSE is called without a lock held is in - * kern/vfs_subr.c::vgone1 and only if the vnode is not already doomed with the - * VI_DOOMED flag. In addition, the VFS layer will not acquire a vnode lock - * on a doomed vnode (kern/vfs_vnops.c::vn_lock). This means that there is no need - * to do any locking here as this function will always be called in a serial manner. - */ - - /* - * A problem exists where vflush (on unmount) calls close on the root vnode without - * first having calling open. - * Here is the problematic sequence of events: - * 1. HgfsVfsUnmount calls vflush with 1 v_usecount ref on the rootVnode (the one from mount). - * 2. vflush calls vgone on the root vnode because rootrefs (in FreeBSD vflush code) - * is > 0. - * 3. vgone calls VOP_CLOSE because the root vnode has a v_usecount == 1. - * The problem is that there was never an open to match the close. This means that when - * HgfsCloseInt tries decrement the handle reference count, it will go negative (in addition - * to sending a bad close to the hgfs server). To handle this situation, look for this - * specific case (which only happens on FreeBSD) and do not call HgfsCloseInt. - */ - - rootVnode = HGFS_VP_TO_SIP(vp)->rootVnode; - if ((rootVnode == vp) && (rootVnode->v_usecount == 1)) { - DEBUG(VM_DEBUG_LOG, "Skipping final close on rootVnode\n"); - goto out; - } - - ret = HgfsCloseInt(vp, fflag); - -out: - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopAccess -- - * - * This function is invoked when the user calls access(2) on a file in our - * filesystem. It checks to ensure the user has the specified type of - * access to the file. - * - * We send a GET_ATTRIBUTE request by calling HgfsGetattr() to get the mode - * (permissions) for the provided vnode. - * - * Results: - * Returns 0 if access is allowed and a non-zero error code otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopAccess(struct vop_access_args *ap) -/* -struct vop_access_args { - struct vnode *vp; // IN: vnode of file to check - int mode; // IN: type of access required (mask of VREAD|VWRITE|VEXEC) - struct ucred *cred; // IN: calling process's user's credentials - struct thread *td; // IN: thread accessing file -}; -*/ -{ - struct vnode *vp = ap->a_vp; - int mode = ap->a_mode; - HgfsAccessMode accessMode = 0; - Bool isDir = vp->v_type == VDIR; - if (mode & VREAD) { - accessMode |= isDir ? HGFS_MODE_LIST_DIRECTORY : HGFS_MODE_READ_DATA; - accessMode |= HGFS_MODE_READ_ATTRIBUTES; - } - if (mode & VWRITE) { - if (isDir) { - accessMode |= HGFS_MODE_ADD_FILE | HGFS_MODE_ADD_SUBDIRECTORY | - HGFS_MODE_DELETE | HGFS_MODE_DELETE_CHILD | - HGFS_MODE_WRITE_ATTRIBUTES; - } else { - accessMode |= HGFS_MODE_WRITE_DATA | HGFS_MODE_ADD_SUBDIRECTORY | - HGFS_MODE_DELETE | HGFS_MODE_WRITE_ATTRIBUTES; - } - } - if (mode & VAPPEND) { - accessMode |= isDir ? HGFS_MODE_ADD_SUBDIRECTORY : HGFS_MODE_APPEND_DATA; - } - if (mode & VEXEC) { - accessMode |= isDir ? HGFS_MODE_TRAVERSE_DIRECTORY : HGFS_MODE_GENERIC_EXECUTE; - } - - return HgfsAccessInt(vp, accessMode); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopGetattr -- - * - * "Gets the attributes for the supplied vnode." (Solaris Internals, p536) - * - * Results: - * Zero if successful, an errno-type value otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopGetattr(struct vop_getattr_args *ap) -/* -struct vop_getattr_args { - struct vnode *vp; // IN : vnode of file - struct vattr *vap; // OUT: attribute container - struct ucred *cred; // IN : calling process's user's credentials - struct thread *td; // IN : thread accessing file -}; -*/ -{ - struct vnode *vp = ap->a_vp; - struct vattr *vap = ap->a_vap; - - return HgfsGetattrInt(vp, vap); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopSetattr -- - * - * Maps the FreeBSD attributes to Hgfs attributes (by calling - * HgfsSetattrCopy()) and sends a set attribute request to the Hgfs server. - * - * "Sets the attributes for the supplied vnode." (Solaris Internals, p537) - * - * Results: - * Returns 0 on success and a non-zero error code on error. - * - * Side effects: - * The file on the host will have new attributes. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopSetattr(struct vop_setattr_args *ap) -/* -struct vop_setattr_args { - struct vnode *vp; // IN: vnode of file - struct vattr *vap; // IN: attribute container - struct ucred *cred; // IN: calling process's user's credentials - struct thread *td; // IN: thread accessing file -}; -*/ -{ - struct vnode *vp = ap->a_vp; - struct vattr *vap = ap->a_vap; - - return HgfsSetattrInt(vp, vap); - -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopRead -- - * - * Invoked when a user calls read(2) on a file in our filesystem. - * - * Results: - * Returns zero on success and an error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopRead(struct vop_read_args *ap) -/* -struct vop_read_args { - struct vnode *vp; // IN : the vnode of the file - struct uio *uio; // INOUT: location of data to be read - int ioflag; // IN : hints & other directives - struct ucread *cred; // IN : caller's credentials -}; -*/ -{ - struct vnode *vp = ap->a_vp; - struct uio *uiop = ap->a_uio; - - return HgfsReadInt(vp, uiop, FALSE); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopWrite -- - * - * This is invoked when a user calls write(2) on a file in our filesystem. - * - * - * Results: - * Returns 0 on success and error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopWrite(struct vop_write_args *ap) -/* -struct vop_write_args { - struct vnode *vp; // IN : - struct uio *uio; // INOUT: - int ioflag; // IN : - struct ucred *cred; // IN : -}; -*/ -{ - struct vnode *vp = ap->a_vp; - struct uio *uiop = ap->a_uio; - int ioflag = ap->a_ioflag; - - return HgfsWriteInt(vp, uiop, ioflag, FALSE); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopRemove -- - * - * Composes the full pathname of this file and sends a DELETE_FILE request - * by calling HgfsDelete(). - * - * "Removes the file for the supplied vnode." (Solaris Internals, p537) - * - * Results: - * Returns 0 on success or a non-zero error code on error. - * - * Side effects: - * If successful, the file specified will be deleted from the host's - * filesystem. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopRemove(struct vop_remove_args *ap) -/* -struct vop_remove_args { - struct vnode *dvp; // IN: parent directory - struct vnode *vp; // IN: vnode to remove - struct componentname *cnp; // IN: file's pathname information -*/ -{ - struct vnode *vp = ap->a_vp; - - return HgfsRemoveInt(vp); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopRename -- - * - * Renames the provided source name in the source directory with the - * destination name in the destination directory. A RENAME request is sent - * to the Hgfs server. - * - * Results: - * Returns 0 on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopRename(struct vop_rename_args *ap) -/* -struct vop_rename_args { - struct vnode *fdvp; // IN: "from" parent directory - struct vnode *fvp; // IN: "from" file - struct componentname *fcnp: // IN: "from" pathname info - struct vnode *tdvp; // IN: "to" parent directory - struct vnode *tvp; // IN: "to" file (if it exists) - struct componentname *tcnp: // IN: "to" pathname info -}; -*/ -{ - struct vnode *fdvp = ap->a_fdvp; - struct vnode *fvp = ap->a_fvp; - struct vnode *tdvp = ap->a_tdvp; - struct vnode *tvp = ap->a_tvp; - struct componentname *tcnp = ap->a_tcnp; - - - int ret; - - /* - * Note that fvp and fdvp are not locked when called by the VFS layer. However, - * this does not matter for the HgfsRenameInt implementaiton which does not use - * the handle or mode from the HgfsOpenFile (the two things that can change in an - * HgfsOpenFile struct). So while a normal VFS implementation would lock at least fvp - * here, this one does not. - */ - ret = HgfsRenameInt(fvp, tdvp, tvp, tcnp); - - vrele(fdvp); - vrele(fvp); - - vput(tdvp); - if (tvp) { - vput(tvp); - } - - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsMkdir -- - * - * Calls HgfsMkdirInt which does all of the directory creation work in a - * FreeBSD / Mac OS independent way. - * - * Results: - * Returns 0 on success and a non-zero error code on failure. - * - * Side effects: - * If successful, a directory is created on the host's filesystem. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopMkdir(struct vop_mkdir_args *ap) -/* -struct vop_mkdir_args { - struct vnode *dvp; // IN : directory vnode - struct vnode **vpp; // OUT: pointer to new directory vnode - struct componentname *cnp; // IN : pathname component created - struct vattr *vap; // IN : attributes to create directory with -}; -*/ -{ - struct vnode *dvp = ap->a_dvp; - struct vnode **vpp = ap->a_vpp; - struct componentname *cnp = ap->a_cnp; - struct vattr *vap = ap->a_vap; - - return HgfsMkdirInt(dvp, vpp, cnp, vap->va_mode); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopRmdir -- - * - * Removes the specified name from the provided vnode by calling - * HgfsRmdirInt. - * - * Results: - * Returns 0 on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopRmdir(struct vop_rmdir_args *ap) -/* -struct vop_rmdir_args { - struct vnode *dvp; // IN: parent directory vnode - struct vnode *vp; // IN: directory to remove - struct componentname *cnp; // IN: pathname information -}; -*/ -{ - struct vnode *dvp = ap->a_dvp; - struct vnode *vp = ap->a_vp; - struct componentname *cnp = ap->a_cnp; - - return HgfsRmdirInt(dvp, vp, cnp); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopReaddir -- - * - * Reads as many entries from the directory as will fit in to the provided - * buffer. Each directory entry is read by calling HgfsGetNextDirEntry(). - * - * The funciton simply calls HgfsReaddirInt to do all of the common - * FreeBSD and Solaris work. - * - * Results: - * Returns 0 on success and a non-zero error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopReaddir(struct vop_readdir_args *ap) -/* -struct vop_readdir_args { - struct vnode *vp; // IN : directory to read from - struct uio *uio; // INOUT: where to read contents - struct ucred *cred; // IN : caller's credentials - int *eofflag; // INOUT: end of file status - int *ncookies; // OUT : used by NFS server only; ignored - u_long **cookies; // INOUT: used by NFS server only; ignored -}; -*/ -{ - struct vnode *vp = ap->a_vp; - struct uio *uiop = ap->a_uio; - int *eofp = ap->a_eofflag; - - return HgfsReaddirInt(vp, uiop, eofp); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopInactive -- - * - * Called when vnode's use count reaches zero. - * - * Results: - * Unconditionally zero. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopInactive(struct vop_inactive_args *ap) -/* -struct vop_inactive_args { - struct vnode *vp; // IN: vnode to inactive - struct thread *td; // IN: caller's thread context -}; -*/ -{ - return 0; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopReclaim -- - * - * Dissociates vnode from the underlying filesystem. - * - * Results: - * Zero on success, or an appropriate system error otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopReclaim(struct vop_reclaim_args *ap) -/* -struct vop_reclaim_args { - struct vnode *vp; // IN: vnode to reclaim - struct thread *td; // IN: caller's thread context -}; -*/ -{ - struct vnode *vp = ap->a_vp; - - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - - HgfsReleaseVnodeContext(vp, &sip->fileHashTable); - vp->v_data = NULL; - - return 0; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopPrint -- - * - * This function is needed to fill in the HgfsVnodeOps structure. - * Right now it does nothing. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopPrint(struct vop_print_args *ap) -{ - return 0; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopReadlink -- - * - * Invoked when a user calls readlink(2) on a file in our filesystem. - * - * Results: - * Returns zero on success and an error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopReadlink(struct vop_readlink_args *ap) -/* -struct vop_readlink_args { - vnode *vp; // IN : vnode of file - struct uio *uio; // OUT: location to copy symlink name. - struct ucred *cred; // IN : caller's credentials -}; -*/ -{ - struct vnode *vp = ap->a_vp; - struct uio *uiop = ap->a_uio; - - return HgfsReadlinkInt(vp, uiop); -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopSymlink -- - * - * Invoked when a user calls symlink(2) to create a symbolic link. - * - * Results: - * Returns zero on success and an error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsVopSymlink(struct vop_symlink_args *ap) -/* -struct vop_symlink_args { - vnode *dvp; // IN : vnode of directory - vnode **vp; // OUT: location to place resultant vnode - struct componentname *cnp; // IN : symlink pathname info - struct vatttr *vap; // IN : attributes to create new object with - char *target; // IN : Target name -}; -*/ -{ - struct vnode **vp = ap->a_vpp; - struct vnode *dvp = ap->a_dvp; - struct componentname *cnp = ap->a_cnp; - char *target = ap->a_target; - - return HgfsSymlinkInt(dvp, vp, cnp, target); -} - diff --git a/open-vm-tools/modules/freebsd/vmhgfs/vnopscommon.c b/open-vm-tools/modules/freebsd/vmhgfs/vnopscommon.c deleted file mode 100644 index 5857ed74..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/vnopscommon.c +++ /dev/null @@ -1,3274 +0,0 @@ -/********************************************************* - * Copyright (C) 2008 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * vnopscommon.c -- - * - * Common VFS vnop implementations that are shared between both Mac OS and FreeBSD. - */ - -#include <sys/param.h> // for everything -#include <sys/vnode.h> // for struct vnode -#include <sys/dirent.h> // for struct dirent - -#include "fsutil.h" -#include "debug.h" -#include "vnopscommon.h" -#include "transport.h" -#include "cpName.h" -#include "os.h" - -/* Local function prototypes */ -int HgfsGetNextDirEntry(HgfsSuperInfo *sip, HgfsHandle handle, - uint32_t offset, char *nameOut, size_t nameSize, - HgfsFileType *type, Bool *done); -int HgfsDirOpen(HgfsSuperInfo *sip, struct vnode *vp, HgfsOpenType openType); -int HgfsFileOpen(HgfsSuperInfo *sip, struct vnode *vp, - int flag, int permissions, HgfsOpenType openType); -int HgfsDirClose(HgfsSuperInfo *sip, struct vnode *vp); -int HgfsFileClose(HgfsSuperInfo *sip, struct vnode *vp, int flag); -int HgfsDoRead(HgfsSuperInfo *sip, HgfsHandle handle, uint64_t offset, - uint32_t size, struct uio *uiop); -int HgfsDoWrite(HgfsSuperInfo *sip, HgfsHandle handle, int ioflag, - uint64_t offset, uint32_t size, struct uio *uiop); -int HgfsDelete(HgfsSuperInfo *sip, const char *filename, HgfsOp op); -static int HgfsDoGetattrInt(const char *path, const HgfsHandle handle, HgfsSuperInfo *sip, - HgfsAttrV2 *hgfsAttrV2); -static int HgfsDoGetattrByName(const char *path, HgfsSuperInfo *sip, HgfsAttrV2 *hgfsAttrV2); -int HgfsReadlinkInt(struct vnode *vp, struct uio *uiop); -static int HgfsQueryAttrInt(const char *path, HgfsHandle handle, HgfsSuperInfo *sip, - HgfsKReqHandle req); -static int HgfsRenewHandle(struct vnode *vp, HgfsSuperInfo *sip, HgfsHandle *handle); -static int HgfsRefreshDirHandle(struct vnode *vp, HgfsSuperInfo *sip, HgfsHandle *handle); -static int HgfsGetNewHandle(struct vnode *vp, HgfsSuperInfo *sip, HgfsFile *fp, - HgfsHandle *handle); - - -#if 0 -static int HgfsDoGetattrByHandle(HgfsHandle handle, HgfsSuperInfo *sip, HgfsAttrV2 *hgfsAttrV2); -#endif - -#define HGFS_CREATE_DIR_MASK (HGFS_CREATE_DIR_VALID_FILE_NAME | \ - HGFS_CREATE_DIR_VALID_SPECIAL_PERMS | \ - HGFS_CREATE_DIR_VALID_OWNER_PERMS | \ - HGFS_CREATE_DIR_VALID_GROUP_PERMS | \ - HGFS_CREATE_DIR_VALID_OTHER_PERMS) - -/* - *---------------------------------------------------------------------------- - * - * HgfsRenameInt -- - * - * Renames the provided source name in the source directory with the - * destination name in the destination directory. A RENAME request is sent - * to the Hgfs server. - * - * Results: - * Returns 0 on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsRenameInt(struct vnode *fvp, // IN: "from" file - struct vnode *tdvp, // IN: "to" parent directory - struct vnode *tvp, // IN: "to" file - struct componentname *tcnp) // IN: "to" pathname info -{ - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(fvp); - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsRequestRenameV3 *request; - HgfsReplyRenameV3 *reply; - HgfsFileNameV3 *newNameP; - char *srcFullPath = NULL; // will point to fvp's filename; don't free - char *dstFullPath = NULL; // allocated from M_TEMP; free when done. - uint32 srcFullPathLen; - uint32 dstFullPathLen; - uint32 reqBufferSize; - uint32 reqSize; - uint32 repSize; - int ret; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s -> %.*s/%.*s).\n", - HGFS_VP_TO_FILENAME_LENGTH(fvp), HGFS_VP_TO_FILENAME(fvp), - HGFS_VP_TO_FILENAME_LENGTH(tdvp), HGFS_VP_TO_FILENAME(tdvp), - (int)tcnp->cn_namelen, tcnp->cn_nameptr); - - /* No cross-device renaming. */ - if (HGFS_VP_TO_MP(fvp) != HGFS_VP_TO_MP(tdvp)) { - ret = EXDEV; - goto out; - } - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - goto out; - } - - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestRenameV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - /* Initialize the request header */ - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_RENAME_V3); - request->hints = 0; - request->reserved = 0; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - reqBufferSize = HGFS_PACKET_MAX - (reqSize - 2); - - /* Make the full path of the source. */ - srcFullPath = HGFS_VP_TO_FILENAME(fvp); - srcFullPathLen = HGFS_VP_TO_FILENAME_LENGTH(fvp); - - /* Make the full path of the destination. */ - dstFullPath = os_malloc(MAXPATHLEN, M_WAITOK); - if (!dstFullPath) { - ret = ENOMEM; - goto destroyOut; - } - - ret = HgfsMakeFullName(HGFS_VP_TO_FILENAME(tdvp), - HGFS_VP_TO_FILENAME_LENGTH(tdvp), - tcnp->cn_nameptr, - tcnp->cn_namelen, - dstFullPath, - MAXPATHLEN); - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "could not construct full path of dest.\n"); - ret = ENAMETOOLONG; - goto destroyOut; - } - dstFullPathLen = ret; - - /* Ensure both names will fit in one request. */ - if ((reqSize + srcFullPathLen + dstFullPathLen) > HGFS_PACKET_MAX) { - DEBUG(VM_DEBUG_FAIL, "names too big for one request.\n"); - ret = EPROTO; - goto destroyOut; - } - - request->oldName.flags = 0; - request->oldName.fid = HGFS_INVALID_HANDLE; - request->oldName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE; - - /* - * Convert an input string to utf8 precomposed form, convert it to - * the cross platform name format and finally unescape any illegal - * filesystem characters. - */ - ret = HgfsNameToWireEncoding(srcFullPath, srcFullPathLen + 1, - request->oldName.name, reqBufferSize); - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "Couldn't encode to wire format\n"); - ret = -ret; - goto destroyOut; - } - request->oldName.length = ret; - reqSize += ret; - reqBufferSize -= ret; - - /* - * The new name is placed directly after the old name in the packet and we - * access it through this pointer. - */ - newNameP = (HgfsFileNameV3 *)((char *)&request->oldName + - sizeof request->oldName + - request->oldName.length); - newNameP->flags = 0; - newNameP->fid = HGFS_INVALID_HANDLE; - newNameP->caseType = HGFS_FILE_NAME_CASE_SENSITIVE; - - ret = HgfsNameToWireEncoding(dstFullPath, dstFullPathLen + 1, - newNameP->name, reqBufferSize); - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "Couldn't encode to wire format.\n"); - ret = -ret; - goto destroyOut; - } - newNameP->length = ret; - reqSize += ret; - - /* The request's size includes the header, request and both filenames. */ - HgfsKReq_SetPayloadSize(req, reqSize); - - ret = HgfsSubmitRequest(sip, req); - if (ret) { - /* HgfsSubmitRequest() destroys the request if necessary. */ - goto out; - } - - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - - ret = HgfsGetStatus(req, repSize); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - goto destroyOut; - } - - /* Successfully renamed file on the server. */ - -destroyOut: - HgfsKReq_ReleaseRequest(sip->reqs, req); - -out: - if (dstFullPath != NULL) { - os_free(dstFullPath, MAXPATHLEN); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%d).\n", ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsReaddirInt -- - * - * Reads as many entries from the directory as will fit in to the provided - * buffer. Each directory entry is read by calling HgfsGetNextDirEntry(). - * - * "The vop_readdir() method reads chunks of the directory into a uio - * structure. Each chunk can contain as many entries as will fit within - * the size supplied by the uio structure. The uio_resid structure member - * shows the size of the getdents request in bytes, which is divided by the - * size of the directory entry made by the vop_readdir() method to - * calculate how many directory entries to return." (Solaris Internals, - * p555) - * - * Results: - * Returns 0 on success and a non-zero error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsReaddirInt(struct vnode *vp, // IN : Directory vnode to get entries from. - struct uio *uiop, // IN/OUT: Buffer to place dirents in. - int *eofp) // IN/OUT: Have all entries been read? -{ - - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - HgfsHandle handle; - uint64_t offset; - Bool done; - char *fullName = NULL; /* Hashed to generate inode number */ - int ret = 0; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - /* uio_offset is a signed quantity. */ - if (HGFS_UIOP_TO_OFFSET(uiop) < 0) { - DEBUG(VM_DEBUG_FAIL, "fed negative offset.\n"); - ret = EINVAL; - goto out; - } - - /* - * In order to fill the user's buffer with directory entries, we must - * iterate on HGFS_OP_SEARCH_READ requests until either the user's buffer is - * full or there are no more entries. Each call to HgfsGetNextDirEntry() - * fills in the name and attribute structure for the next entry. We then - * escape that name and place it in a kernel buffer that's the same size as - * the user's buffer. Once there are no more entries or no more room in the - * buffer, we copy it to user space. - */ - - /* - * We need to get the handle for this open directory to send to the Hgfs - * server in our requests. - */ - ret = HgfsGetOpenFileHandle(vp, &handle); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "could not get handle.\n"); - ret = EINVAL; - goto out; - } - - if (HGFS_UIOP_TO_OFFSET(uiop) == 0) { - ret = HgfsRefreshDirHandle(vp, sip, &handle); - } - - /* - * Allocate 1K (MAXPATHLEN) buffer for inode number generation. - */ - fullName = os_malloc(MAXPATHLEN, M_WAITOK); - if (!fullName) { - ret = ENOMEM; - goto out; - } - - /* - * Loop until one of the following conditions is met: - * o An error occurs while reading a directory entry - * o There are no more directory entries to read - * o The buffer is full and cannot hold the next entry - * - * We request dentries from the Hgfs server based on their index in the - * directory. The offset value is initialized to the value specified in - * the user's io request and is incremented each time through the loop. - * - * dirp is incremented by the record length each time through the loop and - * is used to determine where in the kernel buffer we write to. - */ - for (offset = HGFS_UIOP_TO_OFFSET(uiop), done = 0; /* Nothing */ ; offset++) { - struct dirent dirent, *dirp = &dirent; - char nameBuf[sizeof dirp->d_name]; - HgfsFileType fileType = HGFS_FILE_TYPE_REGULAR; - - DEBUG(VM_DEBUG_COMM, - "HgfsReaddir: getting directory entry at offset %"FMT64"u.\n", offset); - - DEBUG(VM_DEBUG_HANDLE, "** handle=%d, file=%s\n", - handle, HGFS_VP_TO_FILENAME(vp)); - - bzero(dirp, sizeof *dirp); - - ret = HgfsGetNextDirEntry(sip, handle, offset, nameBuf, sizeof nameBuf, - &fileType, &done); - /* If the filename was too long, we skip to the next entry ... */ - if (ret == EOVERFLOW) { - continue; - } else if (ret == EBADF) { - /* - * If we got invalid handle from the server, this was because user - * enabled/disabled the shared folders. We should get a new handle - * from the server, now. - */ - ret = HgfsRenewHandle(vp, sip, &handle); - if (ret == 0) { - /* - * Now we have valid handle, let's try again from the same - * offset. - */ - offset--; - continue; - } else { - ret = EBADF; - goto out; - } - } else if (ret) { - if (ret != EPROTO) { - ret = EINVAL; - } - DEBUG(VM_DEBUG_FAIL, "failure occurred in HgfsGetNextDirEntry\n"); - goto out; - /* - * ... and if there are no more entries, we set the end of file pointer - * and break out of the loop. - */ - } else if (done == TRUE) { - DEBUG(VM_DEBUG_COMM, "Done reading directory entries.\n"); - if (eofp != NULL) { - *eofp = TRUE; - } - break; - } - /* - * Convert an input string to utf8 decomposed form and then escape its - * buffer. - */ - ret = HgfsNameFromWireEncoding(nameBuf, strlen(nameBuf), dirp->d_name, - sizeof dirp->d_name); - /* - * If the name didn't fit in the buffer or illegal utf8 characters - * were encountered, skip to the next entry. - */ - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "HgfsNameFromWireEncoding failed.\n"); - continue; - } - - /* Fill in the directory entry. */ - dirp->d_namlen = ret; - dirp->d_reclen = sizeof(*dirp); // NB: d_namlen must be set first! - dirp->d_type = - (fileType == HGFS_FILE_TYPE_REGULAR) ? DT_REG : - (fileType == HGFS_FILE_TYPE_DIRECTORY) ? DT_DIR : - DT_UNKNOWN; - - /* - * Make sure there is enough room in the buffer for the entire directory - * entry. If not, we just break out of the loop and copy what we have an set - * the return value to be 0. - */ - if (dirp->d_reclen > HGFS_UIOP_TO_RESID(uiop)) { - DEBUG(VM_DEBUG_INFO, "ran out of room in the buffer.\n"); - ret = 0; - break; - } - - - ret = HgfsMakeFullName(HGFS_VP_TO_FILENAME(vp), // Directorie's name - HGFS_VP_TO_FILENAME_LENGTH(vp), // Length - dirp->d_name, // Name of file - dirp->d_namlen, // Length of filename - fullName, // Destination buffer - MAXPATHLEN); // Size of this buffer - - /* Skip this entry if the full path was too long. */ - if (ret < 0) { - continue; - } - - /* - * Place the node id, which serves the purpose of inode number, for this - * filename directory entry. As long as we are using a dirent64, this is - * okay since ino_t is also a u_longlong_t. - */ - HgfsNodeIdGet(&sip->fileHashTable, fullName, (uint32_t)ret, - &dirp->d_fileno); - - /* Copy out this directory entry. */ - ret = uiomove((caddr_t)dirp, dirp->d_reclen, uiop); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "uiomove failed.\n"); - goto out; - } - } - - /* - * uiomove(9) will have incremented the uio offset by the number of bytes - * written. We reset it here to the fs-specific offset in our directory so - * the next time we are called it is correct. (Note, this does not break - * anything and /is/ how this field is intended to be used.) - */ - HGFS_UIOP_SET_OFFSET(uiop, offset); - - DEBUG(VM_DEBUG_EXIT, "done (ret=%d, *eofp=%d).\n", ret, *eofp); -out: - if (fullName != NULL) { - os_free(fullName, MAXPATHLEN); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsGetattrInt -- - * - * "Gets the attributes for the supplied vnode." (Solaris Internals, p536) - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsGetattrInt(struct vnode *vp, // IN : vnode of the file - HgfsVnodeAttr *vap) // OUT: attributes container -{ - - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - HgfsAttrV2 hgfsAttrV2; - int ret = 0; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - /* XXX It would be nice to do a GetattrByHandle when possible here. */ - ret = HgfsDoGetattrByName(HGFS_VP_TO_FILENAME(vp), sip, &hgfsAttrV2); - - if (!ret) { - /* - * HgfsDoGetattr obtained attributes from the hgfs server so - * map the attributes into BSD attributes. - */ - - HgfsAttrToBSD(vp, &hgfsAttrV2, vap); - } - - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - -/* - *---------------------------------------------------------------------------- - * - * HgfsSetattrInt -- - * - * Maps the Mac OS/FreeBsd attributes to Hgfs attributes (by calling - * HgfsSetattrCopy()) and sends a set attribute request to the Hgfs server. - * - * Results: - * Returns 0 on success and a non-zero error code on error. - * - * Side effects: - * The file on the host will have new attributes. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsSetattrInt(struct vnode *vp, // IN : vnode of the file - HgfsVnodeAttr *vap) // IN : attributes container -{ - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsRequestSetattrV3 *request; - HgfsReplySetattrV3 *reply; - uint32 reqSize; - uint32 reqBufferSize; - uint32 repSize; - char *fullPath = NULL; - uint32 fullPathLen; - int ret; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - ASSERT(vp); - ASSERT(vap); - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - goto out; - } - - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestSetattrV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_SETATTR_V3); - - request->reserved = 0; - - /* - * Fill the attributes and hint fields of the request. If no updates are - * needed then we will just return success without sending the request. - */ - if (HgfsSetattrCopy(vap, &request->attr, &request->hints) == FALSE) { - DEBUG(VM_DEBUG_COMM, "don't need to update attributes.\n"); - ret = 0; - goto destroyOut; - } - - fullPath = HGFS_VP_TO_FILENAME(vp); - fullPathLen = HGFS_VP_TO_FILENAME_LENGTH(vp); - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - reqBufferSize = HGFS_NAME_BUFFER_SIZET(HGFS_PACKET_MAX, reqSize); - - /* - * Convert an input string to utf8 precomposed form, convert it to - * the cross platform name format and finally unescape any illegal - * filesystem characters. - */ - ret = HgfsNameToWireEncoding(fullPath, fullPathLen + 1, - request->fileName.name, - reqBufferSize); - - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "Could not encode to wire format"); - ret = -ret; - goto destroyOut; - } - - request->fileName.fid = HGFS_INVALID_HANDLE; - request->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE; - request->fileName.flags = 0; - request->fileName.length = ret; - - reqSize += ret; - - /* The request's size includes the header, request and filename. */ - HgfsKReq_SetPayloadSize(req, reqSize); - - if (!request->attr.mask) { - /* they were trying to set filerev or vaflags, which we ignore */ - ret = 0; - goto destroyOut; - } - - ret = HgfsSubmitRequest(sip, req); - if (ret) { - /* HgfsSubmitRequest() destroys the request if necessary. */ - goto out; - } - - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - - ret = HgfsGetStatus(req, repSize); - if (ret) { - if (ret == EPROTO) { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - } - goto destroyOut; - } else { - if (HGFS_VATTR_SIZE_IS_ACTIVE(vap, HGFS_VA_DATA_SIZE)) { - HgfsSetFileSize(vp, vap->HGFS_VA_DATA_SIZE); - } - } - -destroyOut: - HgfsKReq_ReleaseRequest(sip->reqs, req); -out: - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsVopRmdir -- - * - * Removes the specified name from the provided vnode. Sends a DELETE - * request by calling HgfsDelete() with the filename and correct opcode to - * indicate deletion of a directory. - * - * "Removes the directory pointed to by the supplied vnode." (Solaris - * Internals, p537) - * - * Results: - * Returns 0 on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsRmdirInt(struct vnode *dvp, // IN: parent directory - struct vnode *vp, // IN: directory to remove - struct componentname *cnp) // IN: Only used for debugging -{ - int ret = 0; - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(dvp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s/%.*s)\n", - HGFS_VP_TO_FILENAME_LENGTH(dvp), HGFS_VP_TO_FILENAME(dvp), - HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - ret = HgfsDelete(sip, HGFS_VP_TO_FILENAME(vp), HGFS_OP_DELETE_DIR_V3); - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s/%.*s -> %d)\n", - HGFS_VP_TO_FILENAME_LENGTH(dvp), HGFS_VP_TO_FILENAME(dvp), - HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsRemoveInt -- - * - * Composes the full pathname of this file and sends a DELETE_FILE request - * by calling HgfsDelete(). - * - * Results: - * Returns 0 on success or a non-zero error code on error. - * - * Side effects: - * If successful, the file specified will be deleted from the host's - * filesystem. - * - *---------------------------------------------------------------------------- - */ - -int HgfsRemoveInt(struct vnode *vp) // IN: Vnode to delete -{ - - int ret = 0; - - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - /* Removing directories is a no-no; save that for VNOP_RMDIR. */ - if (HGFS_VP_TO_VTYPE(vp) == VDIR) { - DEBUG(VM_DEBUG_FAIL, "HgfsRemove(). on dir ret EPERM\n"); - ret = EPERM; - goto out; - } - - os_FlushRange(vp, 0, HGFS_VP_TO_FILESIZE(vp)); - os_SetSize(vp, 0); - - /* We can now send the delete request. */ - ret = HgfsDelete(sip, HGFS_VP_TO_FILENAME(vp), HGFS_OP_DELETE_FILE_V3); - -out: - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsCloseInt -- - * - * Called by HgfsVnopClose under Mac OS or HgfsVopClose under FreeBSD to - * close a file. - * - * "Closes the file given by the supplied vnode. When this is the last - * close, some filesystems use vnop_close() to initiate a writeback of - * outstanding dirty pages by checking the reference cound in the vnode." - * (Solaris Internals, p536) - * - * Results: - * Always returns 0 success. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsCloseInt(struct vnode *vp, // IN: Vnode to close. - int mode) // IN: Mode of vnode being closed. -{ - int ret = 0; - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s, %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - mode); - - /* - * If we are closing a directory we need to send a SEARCH_CLOSE request, - * but if we are closing a regular file we need to send a CLOSE request. - * Other file types are not supported by the Hgfs protocol. - */ - - switch (HGFS_VP_TO_VTYPE(vp)) { - case VDIR: - ret = HgfsDirClose(sip, vp); - break; - - case VREG: - ret = HgfsFileClose(sip, vp, mode); - break; - - default: - DEBUG(VM_DEBUG_FAIL, "unsupported filetype %d.\n", - HGFS_VP_TO_VTYPE(vp)); - ret = EINVAL; - break; - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d -> 0)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return 0; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsOpenInt -- - * - * Invoked when open(2) is called on a file in our filesystem. Sends an - * OPEN request to the Hgfs server with the filename of this vnode. - * - * "Opens a file referenced by the supplied vnode. The open() system call - * has already done a vnop_lookup() on the path name, which returned a vnode - * pointer and then calls to vnop_open(). This function typically does very - * little since most of the real work was performed by vnop_lookup()." - * (Solaris Internals, p537) - * - * Results: - * Returns 0 on success and an error code on error. - * - * Side effects: - * If the HgfsFile for this file does not already have a handle, it is - * given one that can be used for future read and write requests. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsOpenInt(struct vnode *vp, // IN: Vnode to open. - int mode, // IN: Mode of vnode being opened. - HgfsOpenType openType) // IN: TRUE if called outside of VNOP_OPEN. -{ - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - int ret = 0; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s, %d, %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - mode, openType); - - switch(HGFS_VP_TO_VTYPE(vp)) { - case VDIR: - DEBUG(VM_DEBUG_LOG, "opening a directory\n"); - ret = HgfsDirOpen(sip, vp, openType); - break; - - case VREG: - /* - * If HgfsCreate() was called prior to this then is would set permissions - * in HgfsFile that we need to pass to HgfsFileOpen. - * If HgfsCreate has not been called then file already exists and permissions - * are ignored by HgfsFileOpen. - */ - DEBUG(VM_DEBUG_LOG, "opening a file with flag %x\n", mode); - ret = HgfsFileOpen(sip, vp, mode, HGFS_VP_TO_PERMISSIONS(vp), openType); - break; - - default: - DEBUG(VM_DEBUG_FAIL, - "HgfsOpen: unrecognized file of type %d.\n", HGFS_VP_TO_VTYPE(vp)); - ret = EINVAL; - break; - } - - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), - HGFS_VP_TO_FILENAME(vp), ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsLookupInt -- - * - * Looks in the provided directory for the specified filename. If we cannot - * determine the vnode locally (i.e, the vnode is not the root vnode of the - * filesystem provided by dvp or in our hashtable), we send a getattr - * request to the server and allocate a vnode and internal filesystem state - * for this file. - * - * Results: - * Returns zero on success and ENOENT if the file cannot be found - * If file is found, a vnode representing the file is returned in vpp. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsLookupInt(struct vnode *dvp, // IN : directory vnode - struct vnode **vpp, // OUT: ptr to vnode if it exists - struct componentname *cnp) // IN : pathname to component -{ - HgfsAttrV2 attrV2; - HgfsSuperInfo *sip; - char *path = NULL; - int ret = 0; - int len = 0; - - ASSERT(dvp); - ASSERT(vpp); - ASSERT(cnp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s, %.*s).\n", - HGFS_VP_TO_FILENAME_LENGTH(dvp), HGFS_VP_TO_FILENAME(dvp), - (int)cnp->cn_namelen, cnp->cn_nameptr); - - if (cnp->cn_flags & ISDOTDOT) { - HgfsFile *fp = HGFS_VP_TO_FP(dvp); - ASSERT(fp); - if (fp->parent == NULL) { - return EIO; // dvp is root directory - } else { -#if defined __FreeBSD__ - vref(fp->parent); -#else - vnode_get(fp->parent); -#endif - *vpp = fp->parent; - return 0; - } - } - if (cnp->cn_namelen == 1 && *cnp->cn_nameptr == '.') { -#if defined __FreeBSD__ - vref(dvp); -#else - vnode_get(dvp); -#endif - *vpp = dvp; - return 0; - } - - /* - * Get pointer to the superinfo. If the device is not attached, - * hgfsInstance will not be valid and we immediately return an error. - */ - sip = HGFS_VP_TO_SIP(dvp); - if (!sip) { - DEBUG(VM_DEBUG_FAIL, "couldn't acquire superinfo.\n"); - return ENOTSUP; - } - - /* Snag a pathname buffer */ - path = os_malloc(MAXPATHLEN, M_WAITOK); - if (!path) { - return ENOMEM; - } - - /* Construct the full path for this lookup. */ - len = HgfsMakeFullName(HGFS_VP_TO_FILENAME(dvp), // Path to this file - HGFS_VP_TO_FILENAME_LENGTH(dvp), // Length of path - cnp->cn_nameptr, // File's name - cnp->cn_namelen, // Filename length - path, // Destination buffer - MAXPATHLEN); // Size of dest buffer - if (len < 0) { - DEBUG(VM_DEBUG_FAIL, "LookupInt length is less than zero\n"); - ret = EINVAL; - goto out; - } - - DEBUG(VM_DEBUG_LOAD, "full path is \"%s\"\n", path); - - /* See if the lookup is really for the root vnode. */ - if (strcmp(path, "/") == 0) { - DEBUG(VM_DEBUG_INFO, "returning the root vnode.\n"); - *vpp = sip->rootVnode; - /* - * If we are returning the root vnode, then we need to get a reference - * to it. Under Mac OS this gets an I/O Count. - */ - HGFS_VPP_GET_IOCOUNT(vpp); - goto out; - }; - - /* Send a Getattr request to the Hgfs server. */ - ret = HgfsDoGetattrByName(path, sip, &attrV2); - - /* - * If this is the final pathname component & the user is attempt a CREATE - * or RENAME, just return without a leaf vnode. (This differs from - * Solaris where ENOENT would be returned in all cases.) - */ - if (ret == ENOENT) { - if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && - cnp->cn_flags & ISLASTCN) { - ret = EJUSTRETURN; - DEBUG(VM_DEBUG_FAIL, "GetattrByName error %d for \"%s\".\n", ret, path); - goto out; - } - } - - /* Got an error from HgfsDoGetattrByName, return it to the caller. */ - if (ret) { - DEBUG(VM_DEBUG_FAIL, "GetattrByName error %d for \"%s\".\n", ret, path); - goto out; - } - - ret = HgfsVnodeGet(vpp, // Location to write vnode's address - dvp, // Parent vnode - sip, // Superinfo - HGFS_VP_TO_MP(dvp), // VFS for our filesystem - path, // Full name of the file - attrV2.type, // Type of file - &sip->fileHashTable, // File hash table - FALSE, // Not a new file creation - 0, // No permissions - not a new file - attrV2.size); // File size - - if (ret) { - DEBUG(VM_DEBUG_FAIL, "couldn't create vnode for \"%s\".\n", path); - goto out; - } - - /* - * Either we will have a cache hit or called HgfsVnodeGet. Both of these - * paths guarantees that *vpp will be set to a vnode. - */ - ASSERT(*vpp); - - DEBUG(VM_DEBUG_LOAD, "assigned vnode %p to %s\n", *vpp, path); - - ret = 0; /* Return success */ - -out: - if (path != NULL) { - os_free(path, MAXPATHLEN); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s, %.*s -> %d)\n", - HGFS_VP_TO_FILENAME_LENGTH(dvp), HGFS_VP_TO_FILENAME(dvp), - (int)cnp->cn_namelen, cnp->cn_nameptr, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsCreateInt -- - * - * Called by either HgfsVnopCreate under Mac OS or HgfsVopCreate under - * FreeBSD when the user is trying to create a file by calling open() with - * the O_CREAT flag specified. - * - * The kernel calls the open entry point which calls (HgfsOpenInt()) after - * calling this function, so here all we do is consruct the vnode and - * save the filename and permission bits for the file to be created within - * our filesystem internal state. - * - * Results: - * Returns zero on success and an appropriate error code on error. - * - * Side effects: - * If the file doesn't exist, a vnode will be created. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsCreateInt(struct vnode *dvp, // IN : Directory vnode - struct vnode **vpp, // OUT: Pointer to new vnode - struct componentname *cnp, // IN : Location to create new vnode - int mode) // IN : Mode of vnode being created. -{ - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(dvp); - char *fullname = NULL; // allocated from M_TEMP; free when done. - int ret = 0; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s/%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(dvp), HGFS_VP_TO_FILENAME(dvp), - (int)cnp->cn_namelen, cnp->cn_nameptr); - - if (*vpp != NULL) { - DEBUG(VM_DEBUG_FAIL, "vpp (%p) not null\n", vpp); - ret = EEXIST; - goto out; - } - - /* If we have gotten to this point then we know that we need to create a - * new vnode. The actual file will be created on the HGFS server in the - * HgfsOpenInt call should happen right after this call. - */ - fullname = os_malloc(MAXPATHLEN, M_WAITOK); - if (!fullname) { - ret = ENOMEM; - goto out; - } - - ret = HgfsMakeFullName(HGFS_VP_TO_FILENAME(dvp), // Name of directory to create in - HGFS_VP_TO_FILENAME_LENGTH(dvp), // Length of name - cnp->cn_nameptr, // Name of file to create - cnp->cn_namelen, // Length of new filename - fullname, // Buffer to write full name - MAXPATHLEN); // Size of this buffer - - if (ret >= 0) { - /* Create the vnode for this file. */ - ret = HgfsVnodeGet(vpp, dvp, sip, HGFS_VP_TO_MP(dvp), fullname, - HGFS_FILE_TYPE_REGULAR, &sip->fileHashTable, TRUE, - mode, 0); - /* HgfsVnodeGet() guarantees this. */ - ASSERT(ret != 0 || *vpp); - /* - * NOTE: This is a temporary workaround. - * This condition may occur because we look up vnodes by file name in the - * vnode cache. - * There is a race condition when file is already deleted but still referenced - - * thus vnode still exist. If a new file with the same name is created I - * can neither use the vnode of the deleted file nor insert a new vnode with - * the same name - thus I fail the request. This behavior is not correct and will - * be fixed after further restructuring if the source code. - */ - if (ret == EEXIST) { - ret = EIO; - } - } else { - DEBUG(VM_DEBUG_FAIL, "couldn't create full path name.\n"); - ret = ENAMETOOLONG; - } - -out: - if (fullname != NULL) { - os_free(fullname, MAXPATHLEN); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s/%.*s -> %d)\n", - HGFS_VP_TO_FILENAME_LENGTH(dvp), HGFS_VP_TO_FILENAME(dvp), - (int)cnp->cn_namelen, cnp->cn_nameptr, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsReadInt -- - * - * Called by HgfsVnopRead under Mac OS or HgfsVopRead under FreeBSD to read - * a file. - * - * We call HgfsDoRead() to fill the user's buffer until the request is met - * or the file has no more data. This is done since we can only transfer - * HGFS_IO_MAX bytes in any one request. - * - * "Reads the range supplied for the given vnode. vop_read() typically - * maps the requested range of a file into kernel memory and then uses - * vop_getpage() to do the real work." (Solaris Internals, p537) - * - * Results: - * Returns zero on success and an error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsReadInt(struct vnode *vp, // IN : Vnode to read from - struct uio *uiop, // IN/OUT: Buffer to write data into. - Bool pagingIo) // IN: True if the read is a result of a page fault -{ - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - HgfsHandle handle; - uint64_t offset; - int ret; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - /* We can't read from directories, that's what readdir() is for. */ - if (HGFS_VP_TO_VTYPE(vp) != VREG) { - DEBUG(VM_DEBUG_FAIL, "Can only read regular files.\n"); - ret = (HGFS_VP_TO_VTYPE(vp) == VDIR) ? EISDIR : EPERM; - DEBUG(VM_DEBUG_FAIL, "Read not a reg file type %d ret %d.\n", HGFS_VP_TO_VTYPE(vp), ret); - return ret; - } - - /* off_t is a signed quantity */ - if (HGFS_UIOP_TO_OFFSET(uiop) < 0) { - DEBUG(VM_DEBUG_FAIL, "given negative offset.\n"); - return EINVAL; - } - - /* This is where the user wants to start reading from in the file. */ - offset = HGFS_UIOP_TO_OFFSET(uiop); - - /* - * We need to get the handle for the requests sent to the Hgfs server. Note - * that this is guaranteed to not change until a close(2) is called on this - * vnode, so it's safe and correct to acquire it outside the loop below. - */ - ret = HgfsGetOpenFileHandle(vp, &handle); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "could not get handle.\n"); - return EINVAL; - } - - /* Flush mmaped data to maintain data coherence between mmap and read. */ - if (!pagingIo) { - ret = os_FlushRange(vp, offset, HGFS_UIOP_TO_RESID(uiop)); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "could not flush data.\n"); - return EINVAL; - } - } - - /* - * Here we loop around HgfsDoRead with requests less than or equal to - * HGFS_IO_MAX until one of the following conditions is met: - * (1) All the requested data has been read - * (2) The file has no more data - * (3) An error occurred - * - * Since HgfsDoRead() calls uiomove(9), we know condition (1) is met when - * the uio structure's uio_resid is decremented to zero. If HgfsDoRead() - * returns 0 we know condition (2) was met, and if it returns less than 0 we - * know condtion (3) was met. - */ - do { - uint32_t size; - - /* Request at most HGFS_IO_MAX bytes */ - size = (HGFS_UIOP_TO_RESID(uiop) > HGFS_IO_MAX) ? HGFS_IO_MAX : - HGFS_UIOP_TO_RESID(uiop); - - DEBUG(VM_DEBUG_INFO, "offset=%"FMT64"d, uio_offset=%"FMT64"d\n", - offset, HGFS_UIOP_TO_OFFSET(uiop)); - DEBUG(VM_DEBUG_HANDLE, "** handle=%d, file=%s to read %u\n", - handle, HGFS_VP_TO_FILENAME(vp), size); - - if (size == 0) { - /* For a zero byte length read we return success. */ - DEBUG(VM_DEBUG_EXIT, "size of 0 ret -> 0.\n"); - return 0; - } - - /* Send one read request. */ - ret = HgfsDoRead(sip, handle, offset, size, uiop); - if (ret == 0) { - /* On end of file we return success */ - DEBUG(VM_DEBUG_EXIT, "end of file reached.\n"); - return 0; - } else if (ret == -EBADF) { // Stale host handle - ret = HgfsRenewHandle(vp, sip, &handle); - if (ret == 0) { - ret = HgfsDoRead(sip, handle, offset, size, uiop); - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "Failed to read from a fresh handle.\n"); - return -ret; - } - } else { - DEBUG(VM_DEBUG_FAIL, "Failed to get a fresh handle.\n"); - return EBADF; - } - } else if (ret < 0) { - /* - * HgfsDoRead() returns the negative of an appropriate error code to - * differentiate between success and error cases. We flip the sign - * and return the appropriate error code. See the HgfsDoRead() - * function header for a fuller explanation. - */ - DEBUG(VM_DEBUG_FAIL, "HgfsDoRead() failed, error %d.\n", ret); - return -ret; - } - - /* Bump the offset past where we have already read. */ - offset += ret; - } while (HGFS_UIOP_TO_RESID(uiop)); - - /* We fulfilled the user's read request, so return success. */ - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> 0)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - return 0; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsWriteInt -- - * - * Called by HgfsVnopWrite under Mac OS or HgfsVopWrite under FreeBSD. - * - * We call HgfsDoWrite() once with requests less than or equal to - * HGFS_IO_MAX bytes until the user's write request has completed. - * - * Results: - * Returns 0 on success and error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsWriteInt(struct vnode *vp, // IN : the vnode of the file - struct uio *uiop, // IN/OUT: location of data to be written - int ioflag, // IN : hints & other directives - Bool pagingIo) // IN: True if the write is originated by memory manager -{ - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - HgfsHandle handle; - uint64_t offset; - int ret = 0; - int error = 0; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - /* Skip write requests for 0 bytes. */ - if (HGFS_UIOP_TO_RESID(uiop) == 0) { - DEBUG(VM_DEBUG_INFO, "write of 0 bytes requested.\n"); - error = 0; - goto out; - } - - DEBUG(VM_DEBUG_INFO, "file is %s\n", HGFS_VP_TO_FILENAME(vp)); - - /* Off_t is a signed type. */ - if (HGFS_UIOP_TO_OFFSET(uiop) < 0) { - DEBUG(VM_DEBUG_FAIL, "given negative offset.\n"); - error = EINVAL; - goto out; - } - - /* This is where the user will begin writing into the file. */ - offset = HGFS_UIOP_TO_OFFSET(uiop); - - /* Get the handle we need to supply the Hgfs server. */ - ret = HgfsGetOpenFileHandle(vp, &handle); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "could not get handle.\n"); - error = EINVAL; - goto out; - } - - /* Flush mmaped data to maintain data coherence between mmap and read. */ - if (!pagingIo && (ioflag & IO_APPEND) == 0) { - ret = os_FlushRange(vp, offset, HGFS_UIOP_TO_RESID(uiop)); - } - - /* - * We loop around calls to HgfsDoWrite() until either (1) we have written all - * of our data or (2) an error has occurred. HGFS_UIOP_TO_RESID(uiop) is decremented - * by uiomove(9F) inside HgfsDoWrite(), so condition (1) is met when it - * reaches zero. Condition (2) occurs when HgfsDoWrite() returns less than - * zero. - */ - do { - uint32_t size; - - DEBUG(VM_DEBUG_INFO, "** offset=%"FMT64"d, uio_offset=%"FMT64"d\n", - offset, HGFS_UIOP_TO_OFFSET(uiop)); - DEBUG(VM_DEBUG_HANDLE, "** handle=%d, file=%s\n", - handle, HGFS_VP_TO_FILENAME(vp)); - - /* Write at most HGFS_IO_MAX bytes. */ - size = (HGFS_UIOP_TO_RESID(uiop) > HGFS_IO_MAX) ? HGFS_IO_MAX : HGFS_UIOP_TO_RESID(uiop); - - /* Send one write request. */ - ret = HgfsDoWrite(sip, handle, ioflag, offset, size, uiop); - if (ret == -EBADF) { // Stale host handle - ret = HgfsRenewHandle(vp, sip, &handle); - if (ret == 0) { - ret = HgfsDoWrite(sip, handle, ioflag, offset, size, uiop); - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "Failed to write to a fresh handle.\n"); - error = -ret; - break; - } - } else { - DEBUG(VM_DEBUG_FAIL, "Failed to get a fresh handle, error %d.\n", ret); - error = EBADF; - break; - } - } else if (ret < 0) { - /* - * As in HgfsRead(), we need to flip the sign. See the comment in the - * function header of HgfsDoWrite() for a more complete explanation. - */ - DEBUG(VM_DEBUG_INFO, "HgfsDoWrite failed, returning %d\n", -ret); - error = -ret; - break; - } - - /* Increment the offest by the amount already written. */ - offset += ret; - - } while (HGFS_UIOP_TO_RESID(uiop)); - - /* Need to notify memory manager if written data extended the file. */ - if (!pagingIo && (offset > HGFS_VP_TO_FILESIZE(vp))) { - if ((ioflag & IO_APPEND) == 0) { - os_SetSize(vp, offset); - } else { - off_t oldSize = HGFS_VP_TO_FILESIZE(vp); - off_t writtenData = offset - HGFS_UIOP_TO_OFFSET(uiop); - os_SetSize(vp, oldSize + writtenData); - } - } - -out: - /* We have completed the user's write request, so return. */ - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", - HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), error); - - return error; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsMkdirInt -- - * - * Makes a directory named dirname in the directory specified by the dvp - * vnode by sending a CREATE_DIR request, then allocates a vnode for this - * new directory and writes its address into vpp. - * - * Results: - * Returns 0 on success and a non-zero error code on failure. - * - * Side effects: - * If successful, a directory is created on the host's filesystem. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsMkdirInt(struct vnode *dvp, // IN : directory vnode - struct vnode **vpp, // OUT: pointer to new directory vnode - struct componentname *cnp, // IN : pathname to component - int mode) // IN : mode to create dir -{ - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(dvp); - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsRequestCreateDirV3 *request; - HgfsReplyCreateDirV3 *reply; - uint32 reqSize; - uint32 repSize; - uint32 reqBufferSize; - char *fullName = NULL; // allocated from M_TEMP; free when done. - uint32 fullNameLen; - int ret; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s/%.*s,%d)\n", - HGFS_VP_TO_FILENAME_LENGTH(dvp), HGFS_VP_TO_FILENAME(dvp), - (int)cnp->cn_namelen, cnp->cn_nameptr, mode); - - /* - * We need to construct the full path of the directory to create then send - * a CREATE_DIR request. If successful we will create a vnode and fill in - * vpp with a pointer to it. - * - * Note that unlike in HgfsCreate(), *vpp is always NULL. - */ - - /* Construct the complete path of the directory to create. */ - fullName = os_malloc(MAXPATHLEN, M_WAITOK); - if (!fullName) { - ret = ENOMEM; - goto out; - } - - ret = HgfsMakeFullName(HGFS_VP_TO_FILENAME(dvp), // Parent directory - HGFS_VP_TO_FILENAME_LENGTH(dvp), // Length of name - cnp->cn_nameptr, // Name of file to create - cnp->cn_namelen, // Length of filename - fullName, // Buffer to write full name - MAXPATHLEN); // Size of this buffer - - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "couldn't create full path name.\n"); - ret = ENAMETOOLONG; - goto out; - } - fullNameLen = ret; - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - goto out; - } - - /* Initialize the request's contents. */ - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestCreateDirV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_CREATE_DIR_V3); - - request->fileAttr = 0; - request->mask = HGFS_CREATE_DIR_MASK; - request->specialPerms = (mode & (S_ISUID | S_ISGID | S_ISVTX)) >> - HGFS_ATTR_SPECIAL_PERM_SHIFT; - request->ownerPerms = (mode & S_IRWXU) >> HGFS_ATTR_OWNER_PERM_SHIFT; - request->groupPerms = (mode & S_IRWXG) >> HGFS_ATTR_GROUP_PERM_SHIFT; - request->otherPerms = mode & S_IRWXO; - request->fileName.flags = 0; - request->fileName.fid = HGFS_INVALID_HANDLE; - request->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - reqBufferSize = HGFS_NAME_BUFFER_SIZET(HGFS_PACKET_MAX, reqSize); - - /* - * Convert an input string to utf8 precomposed form, convert it to - * the cross platform name format and finally unescape any illegal - * filesystem characters. - */ - ret = HgfsNameToWireEncoding(fullName, fullNameLen + 1, - request->fileName.name, - reqBufferSize); - - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL,"Could not encode to wire format"); - ret = -ret; - goto destroyOut; - } - - request->fileName.length = ret; - reqSize += ret; - - /* Set the size of this request. */ - HgfsKReq_SetPayloadSize(req, reqSize); - - /* Send the request to guestd. */ - ret = HgfsSubmitRequest(sip, req); - if (ret) { - /* Request is destroyed in HgfsSubmitRequest() if necessary. */ - goto out; - } - - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - - ret = HgfsGetStatus(req, repSize); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - goto destroyOut; - } - - ret = HgfsVnodeGet(vpp, dvp, sip, HGFS_VP_TO_MP(dvp), fullName, - HGFS_FILE_TYPE_DIRECTORY, &sip->fileHashTable, TRUE, - mode, 0); - if (ret) { - ret = EIO; - DEBUG(VM_DEBUG_FAIL, "Error encountered creating vnode ret = %d\n", ret); - goto destroyOut; - } - - ASSERT(*vpp); - ret = 0; - -destroyOut: - HgfsKReq_ReleaseRequest(sip->reqs, req); -out: - if (fullName != NULL) { - os_free(fullName, MAXPATHLEN); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s/%.*s -> %d)\n", - HGFS_VP_TO_FILENAME_LENGTH(dvp), HGFS_VP_TO_FILENAME(dvp), - (int)cnp->cn_namelen, cnp->cn_nameptr, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDirOpen -- - * - * Invoked when HgfsOpen() is called with a vnode of type VDIR. - * - * Sends a SEARCH_OPEN request to the Hgfs server. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsDirOpen(HgfsSuperInfo *sip, // IN: Superinfo pointer - struct vnode *vp, // IN: Vnode of directory to open - HgfsOpenType openType) // IN: type of VNOP_OPEN. -{ - char *fullPath; - uint32 fullPathLen; - int ret; - HgfsFile *fp; - HgfsHandle handle; - - ASSERT(sip); - ASSERT(vp); - - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s,%d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - openType); - - /* - * If the directory is already opened then we are done. - * There is no different open modes for directories thus the handle is compatible. - */ - os_rw_lock_lock_exclusive(fp->handleLock); - ret = HgfsCheckAndReferenceHandle(vp, 0, openType); - if (ret == ENOENT) { // Handle is not set, need to get one from the host - - if (HGFS_IS_ROOT_VNODE(sip, vp)) { - fullPath = ""; - fullPathLen = 0; - } else { - fullPath = HGFS_VP_TO_FILENAME(vp); - fullPathLen = HGFS_VP_TO_FILENAME_LENGTH(vp); - } - - ret = HgfsSendOpenDirRequest(sip, fullPath, fullPathLen, &handle); - if (ret == 0) { - /* - * We successfully received a reply, so we need to save the handle in - * this file's HgfsOpenFile and return success. - */ - HgfsSetOpenFileHandle(vp, handle, HGFS_OPEN_MODE_READ_ONLY, openType); - } - } - os_rw_lock_unlock_exclusive(fp->handleLock); - - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", - HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsRequestHostFileHandle -- - * - * Sends a open request to the server to get a file handle. - * If client needs a readonly handle the function first asks for - * read-write handle since this handle may be shared between multiple - * file descriptors. If getting read-write handle fails the function - * sends another request for readonly handle. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsRequestHostFileHandle(HgfsSuperInfo *sip, // IN: Superinfo pointer - struct vnode *vp, // IN: Vnode of file to open - int *openMode, // IN OUT: open mode - int openFlags, // IN: flags for the open request - int permissions, // IN: Permissions for new files - HgfsHandle *handle) // OUT: file handle -{ - char *fullPath; - uint32 fullPathLen; - int ret; - - fullPath = HGFS_VP_TO_FILENAME(vp); - fullPathLen = HGFS_VP_TO_FILENAME_LENGTH(vp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s, %d, %d, %o)\n", fullPathLen, fullPath, - *openMode, openFlags, permissions); - - /* First see if we can get the most permissive read/write open mode */ - ret = HgfsSendOpenRequest(sip, HGFS_OPEN_MODE_READ_WRITE, openFlags, - permissions, fullPath, fullPathLen, handle); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Open failed %d, re-submitting original mode = %d.\n", - ret, *openMode); - if (ret == EACCES && HGFS_OPEN_MODE_READ_WRITE != *openMode) { - /* - * Failed to open in read/write open mode because of denied access. - * It means file's permissions do not allow opening for read/write. - * However caller does not need this mode and may be satisfied with - * less permissive mode. - * Try exact open mode now. - */ - DEBUG(VM_DEBUG_FAIL, "RW mode failed, re-submitting original mode = %d.\n", - *openMode); - ret = HgfsSendOpenRequest(sip, *openMode, openFlags, - permissions, fullPath, fullPathLen, handle); - } - } else { - *openMode = HGFS_OPEN_MODE_READ_WRITE; - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", fullPathLen, fullPath, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsFileOpen -- - * - * Invoked when HgfsOpen() is called with a vnode of type VREG. Sends - * a OPEN request to the Hgfs server. - * - * Note that this function doesn't need to handle creations since the - * HgfsCreate() entry point is called by the kernel for that. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsFileOpen(HgfsSuperInfo *sip, // IN: Superinfo pointer - struct vnode *vp, // IN: Vnode of file to open - int flag, // IN: Flags of open - int permissions, // IN: Permissions of open (only when creating) - HgfsOpenType openType) // IN: initiator type for the open -{ - int ret; - int openMode; - int openFlags; - HgfsHandle handle; - HgfsFile *fp; - - ASSERT(sip); - ASSERT(vp); - - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s,%d,%d,%o)\n", - HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - flag, openType, permissions); - - /* - * Check if the user is trying to create a new share. This check was - * mainly implemented to address the issue with Mac OS. When the user - * attempts to create a file in the root folder, the server returns ENOENT - * error code. However, Mac OS specifically checks for this case. If Mac OS asks for - * the creation of a new file and if it gets ENOENT as a return error code, - * then it assumes that the error was because of some race condition and tries it - * again. Thus, returning ENOENT to the Mac OS puts the guest kernel into infinite - * loop. In order to resolve this issue, before passing on the request to the - * server, we validate if user is attempting to create a new share. If yes, - * we return EACCES as the error code. - */ - if (HgfsAttemptToCreateShare(HGFS_VP_TO_FILENAME(vp), flag)) { - DEBUG (VM_DEBUG_LOG, "An attempt to create a new share was made.\n"); - ret = EACCES; - goto out; - } - - /* Convert FreeBSD modes to Hgfs modes */ - openMode = HgfsGetOpenMode((uint32_t)flag); - if (openMode < 0) { - DEBUG(VM_DEBUG_FAIL, "HgfsGetOpenMode failed.\n"); - ret = EINVAL; - goto out; - } - DEBUG(VM_DEBUG_COMM, "open mode is %x\n", openMode); - - /* Convert FreeBSD flags to Hgfs flags */ - openFlags = HgfsGetOpenFlags((uint32_t)flag); - if (openFlags < 0) { - DEBUG(VM_DEBUG_FAIL, "HgfsGetOpenFlags failed.\n"); - ret = EINVAL; - goto out; - } - - os_rw_lock_lock_exclusive(fp->handleLock); - /* - * If the file is already opened, verify that it is opened in a compatible mode. - * If it is true then add reference to vnode and grant the access, otherwise - * deny the access. - */ - ret = HgfsCheckAndReferenceHandle(vp, openMode, openType); - if (ret == ENOENT) { // Handle is not set, need to get one from the host - ret = HgfsRequestHostFileHandle(sip, vp, &openMode, openFlags, - permissions, &handle); - /* - * We successfully received a reply, so we need to save the handle in - * this file's HgfsOpenFile and return success. - */ - if (ret == 0) { - HgfsSetOpenFileHandle(vp, handle, openMode, openType); - } - } - - os_rw_lock_unlock_exclusive(fp->handleLock); - -out: - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsRefreshDirHandle -- - * - * Refresh the directory HgfsHandle for the vnode. - * Needed when original handle become stale because the directory contents - * have changed either in the VM or on the remote server. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsRefreshDirHandle(struct vnode *vp, // IN: Vnode of file to open - HgfsSuperInfo *sip, // IN: Superinfo pointer - HgfsHandle *handle) // IN/OUT: handle to close and reopen -{ - int ret = 0; - HgfsFile *fp; - - ASSERT(vp); - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - os_rw_lock_lock_exclusive(fp->handleLock); - - ASSERT(HGFS_VP_TO_VTYPE(vp) == VDIR); - - if (fp->handle != *handle) { - /* Handle has been refreshed in another thread. */ - *handle = fp->handle; - } else { - /* Close the existing handle and open a new one from the host. */ - HgfsCloseServerDirHandle(sip, *handle); - ret = HgfsGetNewHandle(vp, sip, fp, handle); - } - - os_rw_lock_unlock_exclusive(fp->handleLock); - - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsRenewHandle -- - * - * Renew the HgfsHandle for the vnode. Needed when original handle - * become stale because HGFS has been disabled and re-enabled or VM - * has been suspened and then resumed. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsRenewHandle(struct vnode *vp, // IN: Vnode of file to open - HgfsSuperInfo *sip, // IN: Superinfo pointer - HgfsHandle *handle) // IN/OUT: Pointer to the stale handle -{ - int result = 0; - HgfsFile *fp; - - ASSERT(vp); - fp = HGFS_VP_TO_FP(vp); - ASSERT(fp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - os_rw_lock_lock_exclusive(fp->handleLock); - - if (fp->handle != *handle) { - /* Handle has been refreshed in another thread. */ - *handle = fp->handle; - } else { - result = HgfsGetNewHandle(vp, sip, fp, handle); - } - os_rw_lock_unlock_exclusive(fp->handleLock); - - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - result); - return result; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsGetNewHandle -- - * - * Get a new HgfsHandle for the vnode. Needed when original handle - * become stale because HGFS has been disabled and re-enabled or VM - * has been suspened and then resumed, or folder contents have changed. - * - * NOTE: file lock must be acquired when calling this function. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsGetNewHandle(struct vnode *vp, // IN: Vnode of file to open - HgfsSuperInfo *sip, // IN: Superinfo pointer - HgfsFile *fp, // IN/OUT: file node pointer - HgfsHandle *handle) // IN OUT: Pointer to the stale handle -{ - int ret = 0; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - /* Retrieve a new handle from the host. */ - if (HGFS_VP_TO_VTYPE(vp) == VREG) { - ret = HgfsRequestHostFileHandle(sip, vp, (int *)&fp->mode, - HGFS_OPEN, 0, handle); - } else if (HGFS_VP_TO_VTYPE(vp) == VDIR) { - char *fullPath = HGFS_VP_TO_FILENAME(vp); - uint32 fullPathLen = HGFS_VP_TO_FILENAME_LENGTH(vp); - - ret = HgfsSendOpenDirRequest(sip, fullPath, fullPathLen, handle); - } else { - goto out; - } - - if (ret == 0) { - fp->handle = *handle; - } - -out: - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDirClose -- - * - * Invoked when HgfsClose() is called with a vnode of type VDIR. - * - * Sends an SEARCH_CLOSE request to the Hgfs server. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsDirClose(HgfsSuperInfo *sip, // IN: Superinfo pointer - struct vnode *vp) // IN: Vnode of directory to close -{ - int ret = 0; - HgfsHandle handleToClose; - - ASSERT(sip); - ASSERT(vp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - /* - * Check to see if we should close the file handle on the host ( which happen when - * the reference count of the current handle become 0. - */ - if (HgfsReleaseOpenFileHandle(vp, OPENREQ_OPEN, &handleToClose) == 0) { - ret = HgfsCloseServerDirHandle(sip, handleToClose); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsFileClose -- - * - * Invoked when HgfsClose() is called with a vnode of type VREG. - * - * Sends a CLOSE request to the Hgfs server. - * - * Results: - * Returns zero on success and an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsFileClose(HgfsSuperInfo *sip, // IN: Superinfo pointer - struct vnode *vp, // IN: Vnode of file to close - int flags) // IN: The mode flags for the close -{ - int ret = 0; - HgfsHandle handleToClose; - - ASSERT(sip); - ASSERT(vp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s,%d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - flags); - - /* - * Check to see if we should close the file handle on the host ( which happen when - * the reference count of the current handle become 0. - */ - if (HgfsReleaseOpenFileHandle(vp, OPENREQ_OPEN, &handleToClose) == 0) { - ret = HgfsCloseServerFileHandle(sip, handleToClose); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDoRead -- - * - * Sends a single READ request to the Hgfs server and writes the contents - * into the user's buffer if successful. - * - * This function is called repeatedly by HgfsRead() with requests of size - * less than or equal to HGFS_IO_MAX. - * - * Note that we return the negative of an appropriate error code in this - * function so we can differentiate between success and failure. On success - * we need to return the number of bytes read, but FreeBSD's error codes are - * positive so we negate them before returning. If callers want to return - * these error codes to the Kernel, they will need to flip their sign. - * - * Results: - * Returns number of bytes read on success and a negative value on error. - * - * Side effects: - * On success, size bytes are written into the user's buffer. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsDoRead(HgfsSuperInfo *sip, // IN: Superinfo pointer - HgfsHandle handle, // IN: Server's handle to read from - uint64_t offset, // IN: File offset to read at - uint32_t size, // IN: Number of bytes to read - struct uio *uiop) // IN: Defines user's read request -{ - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestReadV3 *request; - HgfsReplyReadV3 *reply; - uint32 reqSize; - int ret; - - ASSERT(sip); - ASSERT(uiop); - ASSERT(size <= HGFS_IO_MAX); // HgfsRead() should guarantee this - - DEBUG(VM_DEBUG_ENTRY, "Enter(%u,%"FMT64"u,%u)\n", handle, offset, size); - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - ret = -ret; - goto out; - } - - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestReadV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_READ_V3); - - /* Indicate which file, where in the file, and how much to read. */ - request->file = handle; - request->offset = offset; - request->requiredSize = size; - request->reserved = 0; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - - HgfsKReq_SetPayloadSize(req, reqSize); - - ret = HgfsSubmitRequest(sip, req); - if (ret) { - /* - * We need to flip the sign of the return value to indicate error; see - * the comment in the function header. HgfsSubmitRequest() handles - * destroying the request if necessary, so we don't here. - */ - DEBUG(VM_DEBUG_FAIL, " hgfssubmitrequest failed\n"); - ret = -ret; - goto out; - } - - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - reply = (HgfsReplyReadV3 *)HGFS_REP_GET_PAYLOAD_V3(replyHeader); - - ret = HgfsGetStatus(req, sizeof *replyHeader); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - if (ret != EPROTO && ret != EBADF) { - ret = EACCES; - } - ret = -ret; - goto destroyOut; - } - - /* - * Now perform checks on the actualSize. There are three cases: - * o actualSize is less than or equal to size, which indicates success - * o actualSize is zero, which indicates the end of the file (and success) - * o actualSize is greater than size, which indicates a server error - */ - if (reply->actualSize <= size) { - /* If we didn't get any data, we don't need to copy to the user. */ - if (reply->actualSize == 0) { - goto success; - } - - /* Perform the copy to the user */ - ret = uiomove(reply->payload, reply->actualSize, uiop); - if (ret) { - ret = -EIO; - goto destroyOut; - } - - /* We successfully copied the payload to the user's buffer */ - goto success; - - } else { - /* We got too much data: server error. */ - DEBUG(VM_DEBUG_FAIL, "received too much data in payload.\n"); - ret = -EPROTO; - goto destroyOut; - } - -success: - ret = reply->actualSize; -destroyOut: - HgfsKReq_ReleaseRequest(sip->reqs, req); -out: - DEBUG(VM_DEBUG_EXIT, "Exit(%u -> %d)\n", handle, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDoWrite -- - * - * Sends a single WRITE request to the Hgfs server with the contents of - * the user's buffer. - * - * This function is called repeatedly by HgfsWrite() with requests of size - * less than or equal to HGFS_IO_MAX. - * - * Note that we return the negative of an appropriate error code in this - * function so we can differentiate between success and failure. On success - * we need to return the number of bytes written, but FreeBSD's error codes are - * positive so we negate them before returning. If callers want to return - * these error codes to the kernel, they will need to flip their sign. - * - * Results: - * Returns number of bytes written on success and a negative value on error. - * - * Side effects: - * On success, size bytes are written to the file specified by the handle. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsDoWrite(HgfsSuperInfo *sip, // IN: Superinfo pointer - HgfsHandle handle, // IN: Handle representing file to write to - int ioflag, // IN: Flags for write - uint64_t offset, // IN: Where in the file to begin writing - uint32_t size, // IN: How much data to write - struct uio *uiop) // IN: Describes user's write request -{ - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestWriteV3 *request; - HgfsReplyWriteV3 *reply; - uint32 reqSize; - uint32 repSize; - int ret; - - ASSERT(sip); - ASSERT(uiop); - ASSERT(size <= HGFS_IO_MAX); // HgfsWrite() guarantees this - - DEBUG(VM_DEBUG_ENTRY, "Enter(%u,%d,%"FMT64"u,%u)\n", handle, ioflag, offset, size); - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - ret = -ret; - goto out; - } - - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestWriteV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_WRITE_V3); - - request->file = handle; - request->flags = 0; - request->offset = offset; - request->requiredSize = size; - request->reserved = 0; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - - if (ioflag & IO_APPEND) { - DEBUG(VM_DEBUG_COMM, "writing in append mode.\n"); - request->flags |= HGFS_WRITE_APPEND; - } - - DEBUG(VM_DEBUG_COMM, "requesting write of %d bytes.\n", size); - - /* Copy the data the user wants to write into the payload. */ - ret = uiomove(request->payload, request->requiredSize, uiop); - if (ret) { - DEBUG(VM_DEBUG_FAIL, - "HgfsDoWrite: uiomove(9F) failed copying data from user.\n"); - ret = -EIO; - goto destroyOut; - } - - /* We subtract one so request's 'char payload[1]' member isn't double counted. */ - HgfsKReq_SetPayloadSize(req, reqSize + request->requiredSize - 1); - - ret = HgfsSubmitRequest(sip, req); - if (ret) { - /* - * As in HgfsDoRead(), we need to flip the sign of the error code - * returned by HgfsSubmitRequest(). - */ - DEBUG(VM_DEBUG_FAIL, "HgfsSubmitRequest failed.\n"); - ret = -ret; - goto out; - } - - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - - ret = HgfsGetStatus(req, sizeof *replyHeader); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - if (ret != EPROTO && ret != EBADF) { - ret = EACCES; - } - ret = -ret; - goto destroyOut; - } - - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - - if (HgfsKReq_GetPayloadSize(req) != repSize) { - DEBUG(VM_DEBUG_FAIL, - "Error: invalid size of reply on successful reply.\n"); - ret = -EPROTO; - goto destroyOut; - } - - reply = (HgfsReplyWriteV3 *)HGFS_REP_GET_PAYLOAD_V3(replyHeader); - - /* The write was completed successfully, so return the amount written. */ - ret = reply->actualSize; - -destroyOut: - HgfsKReq_ReleaseRequest(sip->reqs, req); -out: - DEBUG(VM_DEBUG_EXIT, "Exit(%u -> %d)\n", handle, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDelete -- - * - * Sends a request to delete a file or directory. - * - * Results: - * Returns 0 on success or an error code on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsDelete(HgfsSuperInfo *sip, // IN: Superinfo - const char *filename, // IN: Full name of file to remove - HgfsOp op) // IN: Hgfs operation this delete is for -{ - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestDeleteV3 *request; - HgfsReplyDeleteV3 *reply; - uint32 reqSize; - uint32 repSize; - uint32 reqBufferSize; - int ret; - - ASSERT(sip); - ASSERT(filename); - ASSERT((op == HGFS_OP_DELETE_FILE_V3) || (op == HGFS_OP_DELETE_DIR_V3)); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%s,%d)\n", filename, op); - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - goto out; - } - - /* Initialize the request's contents. */ - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestDeleteV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, op); - request->hints = 0; - request->fileName.fid = HGFS_INVALID_HANDLE; - request->fileName.flags = 0; - request->fileName.caseType = HGFS_FILE_NAME_DEFAULT_CASE; - request->reserved = 0; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - reqBufferSize = HGFS_NAME_BUFFER_SIZET(HGFS_PACKET_MAX, reqSize); - - /* - * Convert an input string to utf8 precomposed form, convert it to - * the cross platform name format and finally unescape any illegal - * filesystem characters. - */ - ret = HgfsNameToWireEncoding(filename, strlen(filename) + 1, - request->fileName.name, - reqBufferSize); - - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "Could not encode to wire format"); - ret = -ret; - goto destroyOut; - } - - request->fileName.length = ret; - reqSize += ret; - - /* Set the size of our request. */ - HgfsKReq_SetPayloadSize(req, reqSize); - - DEBUG(VM_DEBUG_COMM, "deleting \"%s\"\n", filename); - - /* Submit our request to guestd. */ - ret = HgfsSubmitRequest(sip, req); - if (ret) { - /* HgfsSubmitRequest() handles destroying the request if necessary. */ - goto out; - } - - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - - ret = HgfsGetStatus(req, repSize); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - goto destroyOut; - } - -destroyOut: - HgfsKReq_ReleaseRequest(sip->reqs, req); -out: - DEBUG(VM_DEBUG_EXIT, "Exit(%s -> %d)\n", filename, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsGetNextDirEntry -- - * - * Writes the name of the directory entry matching the handle and offset to - * nameOut. Also records the entry's type (file, directory) in type. This - * requires sending a SEARCH_READ request. - * - * Results: - * Returns zero on success and an error code on error. The done value is - * set if there are no more directory entries. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsGetNextDirEntry(HgfsSuperInfo *sip, // IN: Superinfo pointer - HgfsHandle handle, // IN: Handle for request - uint32_t offset, // IN: Offset - char *nameOut, // OUT: Location to write name - size_t nameSize, // IN : Size of nameOut - HgfsFileType *type, // OUT: Entry's type - Bool *done) // OUT: Whether there are any more -{ - HgfsKReqHandle req; - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestSearchReadV3 *request; - HgfsReplySearchReadV3 *reply; - HgfsDirEntry *dirent; - uint32 reqSize; - uint32 repSize; - int ret; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%u,%u)\n", handle, offset); - - ASSERT(sip); - ASSERT(nameOut); - ASSERT(done); - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - DEBUG(VM_DEBUG_FAIL, "couldn't get req.\n"); - goto out; - } - - /* - * Fill out the search read request that will return a single directory - * entry for the provided handle at the given offset. - */ - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestSearchReadV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_SEARCH_READ_V3); - - request->search = handle; - request->offset = offset; - request->flags = 0; - request->reserved = 0; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - HgfsKReq_SetPayloadSize(req, reqSize); - - ret = HgfsSubmitRequest(sip, req); - if (ret) { - /* HgfsSubmitRequest will destroy the request if necessary. */ - DEBUG(VM_DEBUG_FAIL, "HgfsSubmitRequest failed.\n"); - goto out; - } - - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - - ret = HgfsGetStatus(req, sizeof *replyHeader); - if (ret) { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - goto destroyOut; - } - - DEBUG(VM_DEBUG_COMM, "received reply for ID %d\n", - replyHeader->id); - DEBUG(VM_DEBUG_COMM, " status: %d (see hgfsProto.h)\n", replyHeader->status); - - reply = (HgfsReplySearchReadV3 *)HGFS_REP_GET_PAYLOAD_V3(replyHeader); - reply->count = 1; - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply) + sizeof *dirent; - dirent = (HgfsDirEntry *)reply->payload; - - /* Make sure we got an entire reply (excluding filename) */ - if (HgfsKReq_GetPayloadSize(req) < repSize) { - DEBUG(VM_DEBUG_FAIL, "server didn't provide entire reply.\n"); - ret = EFAULT; - goto destroyOut; - } - - /* See if there are no more filenames to read */ - if (dirent->fileName.length <= 0) { - DEBUG(VM_DEBUG_LOG, "no more directory entries.\n"); - *done = TRUE; - ret = 0; /* return success */ - goto destroyOut; - } - - /* Make sure filename isn't too long */ - if ((dirent->fileName.length >= nameSize) || - (dirent->fileName.length > HGFS_PAYLOAD_MAX(repSize)) ) { - DEBUG(VM_DEBUG_FAIL, "filename is too long.\n"); - ret = EOVERFLOW; - goto destroyOut; - } - - /* - * Everything is all right, copy filename to caller's buffer. Note that even though - * the hgfs SearchRead reply holds lots of information about the file's attributes, - * FreeBSD directory entries do not currently need any of that information except the - * file type. - */ - memcpy(nameOut, dirent->fileName.name, dirent->fileName.length); - nameOut[dirent->fileName.length] = '\0'; - *type = dirent->attr.type; - ret = 0; - -destroyOut: - HgfsKReq_ReleaseRequest(sip->reqs, req); -out: - DEBUG(VM_DEBUG_EXIT, "Exit(%u -> %d)\n", handle, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsReadlinkInt -- - * - * Reads a symbolic link target. - * - * Results: - * Either 0 on success or a BSD error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsReadlinkInt(struct vnode *vp, // IN : File vnode - struct uio *uiop) // OUT: Attributes from hgfs server -{ - HgfsKReqHandle req = NULL; - int ret = 0; - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - HgfsReplyGetattrV3 *reply; - HgfsReply *replyHeader; - uint32 outLength; - char* outBuffer = NULL; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp)); - - /* This operation is valid only for symbolic links. */ - if (HGFS_VP_TO_VTYPE(vp) != VLNK) { - DEBUG(VM_DEBUG_FAIL, "Must be a symbolic link.\n"); - ret = EINVAL; - goto out; - } - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - goto out; - } - - ret = HgfsQueryAttrInt(HGFS_VP_TO_FILENAME(vp), 0, sip, req); - if (ret != 0) { - DEBUG(VM_DEBUG_FAIL, "Error %d reading symlink name.\n", ret); - goto out; - } - - outLength = HGFS_UIOP_TO_RESID(uiop); - outBuffer = os_malloc(outLength, M_WAITOK); - if (outBuffer != NULL) { - DEBUG(VM_DEBUG_FAIL, "No memory for symlink name.\n"); - ret = ENOMEM; - goto out; - } - - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - reply = (HgfsReplyGetattrV3 *)HGFS_REP_GET_PAYLOAD_V3(replyHeader); - if (reply->symlinkTarget.name[reply->symlinkTarget.length - 1] == '\0') { - ret = EINVAL; // Not a well formed name - goto out; - } - - ret = HgfsNameFromWireEncoding(reply->symlinkTarget.name, - reply->symlinkTarget.length, - outBuffer, outLength); - if (ret < 0) { - ret = -ret; // HgfsNameFromWireEncoding returns negative error code - DEBUG(VM_DEBUG_FAIL, "Error converting link wire format length is %d, name is %s\n", - reply->symlinkTarget.length, reply->symlinkTarget.name); - goto out; - } - - ret = uiomove(outBuffer, MIN(ret, outLength), uiop); - if (ret != 0) { - DEBUG(VM_DEBUG_FAIL, "Failed %d copying into user buffer.\n", ret); - } - -out: - if (outBuffer != NULL) { - os_free(outBuffer, outLength); - } - if (req != NULL) { - HgfsKReq_ReleaseRequest(sip->reqs, req); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d\n", HGFS_VP_TO_FILENAME_LENGTH(vp), HGFS_VP_TO_FILENAME(vp), - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsSymlnikInt -- - * - * Creates symbolic link on the host. - * - * Results: - * Either 0 on success or a BSD error code on failure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsSymlinkInt(struct vnode *dvp, // IN : directory vnode - struct vnode **vpp, // OUT: pointer to new symlink vnode - struct componentname *cnp, // IN : pathname to component - char *targetName) // IN : Symbolic link target -{ - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(dvp); - HgfsKReqHandle req = NULL; - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestSymlinkCreateV3 *request; - HgfsReplySymlinkCreateV3 *reply; - uint32 reqSize; - uint32 repSize; - uint32 reqBufferSize; - int ret; - char *fullName = NULL; - uint32 fullNameLen; - HgfsFileNameV3 *fileNameP; - int nameOffset; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s/%.*s,%s)\n", - HGFS_VP_TO_FILENAME_LENGTH(dvp), HGFS_VP_TO_FILENAME(dvp), - (int)cnp->cn_namelen, cnp->cn_nameptr, - targetName); - - fullName = os_malloc(MAXPATHLEN, M_WAITOK); - if (!fullName) { - ret = ENOMEM; - goto out; - } - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - goto out; - } - - ret = HgfsMakeFullName(HGFS_VP_TO_FILENAME(dvp), // Parent directory - HGFS_VP_TO_FILENAME_LENGTH(dvp), // Length of name - cnp->cn_nameptr, // Name of file to create - cnp->cn_namelen, // Length of filename - fullName, // Buffer to write full name - MAXPATHLEN); // Size of this buffer - - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "couldn't create full path name.\n"); - ret = ENAMETOOLONG; - goto out; - } - fullNameLen = ret; - - /* Initialize the request's contents. */ - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestSymlinkCreateV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_CREATE_SYMLINK_V3); - - request->reserved = 0; - - request->symlinkName.flags = 0; - request->symlinkName.fid = HGFS_INVALID_HANDLE; - request->symlinkName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - reqBufferSize = HGFS_NAME_BUFFER_SIZET(HGFS_PACKET_MAX, reqSize); - - /* - * Convert an input string to utf8 precomposed form, convert it to - * the cross platform name format and finally unescape any illegal - * filesystem characters. - */ - ret = HgfsNameToWireEncoding(fullName, fullNameLen + 1, - request->symlinkName.name, - reqBufferSize); - - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL,"Could not encode file name to wire format"); - ret = -ret; - goto out; - } - request->symlinkName.length = ret; - reqSize += ret; - - fileNameP = (HgfsFileNameV3 *)((char*)&request->symlinkName + - sizeof request->symlinkName + - request->symlinkName.length); - fileNameP->flags = 0; - fileNameP->fid = HGFS_INVALID_HANDLE; - fileNameP->caseType = HGFS_FILE_NAME_CASE_SENSITIVE; - - /* - * Currently we have different name formats for file names and for symbolic - * link targets. Flie names are always absolute and on-wire representation does - * not include leading path separator. HgfsNameToWireEncoding removes - * leading path separator from the name. However symbolic link targets may be - * either absolute or relative. To distinguish between them the leading path separator - * must be preserved for absolute symbolic link target. - * In the long term we should fix the protocol and have only one name - * format which is suitable for all names. - * The following code compensates for this problem before there is such - * universal name representation. - */ - if (*targetName == '/') { - fileNameP->length = 1; - reqSize += 1; - *fileNameP->name = '\0'; - targetName++; - } else { - fileNameP->length = 0; - } - /* - * Convert symbolic link target to utf8 precomposed form, convert it to - * the cross platform name format and finally unescape any illegal - * filesystem characters. - */ - nameOffset = fileNameP->name - (char*)requestHeader; - ret = HgfsNameToWireEncoding(targetName, strlen(targetName) + 1, - fileNameP->name + fileNameP->length, - HGFS_PACKET_MAX - nameOffset - - fileNameP->length); - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL,"Could not encode file name to wire format"); - ret = -ret; - goto out; - } - fileNameP->length += ret; - - reqSize += ret; - - /* Set the size of this request. */ - HgfsKReq_SetPayloadSize(req, reqSize); - - ret = HgfsSubmitRequest(sip, req); - if (ret) { - /* Request is destroyed in HgfsSubmitRequest() if necessary. */ - req = NULL; - goto out; - } - - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - reply = (HgfsReplySymlinkCreateV3 *)HGFS_REP_GET_PAYLOAD_V3(replyHeader); - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply); - ret = HgfsGetStatus(req, repSize); - if (ret == 0) { - ret = HgfsVnodeGet(vpp, dvp, sip, HGFS_VP_TO_MP(dvp), fullName, - HGFS_FILE_TYPE_SYMLINK, &sip->fileHashTable, TRUE, 0, 0); - if (ret) { - ret = EIO; - } - } else { - DEBUG(VM_DEBUG_FAIL, "Error encountered with ret = %d\n", ret); - } - - ASSERT(ret != 0 || *vpp != NULL); - -out: - if (req) { - HgfsKReq_ReleaseRequest(sip->reqs, req); - } - if (fullName != NULL) { - os_free(fullName, MAXPATHLEN); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s/%.*s -> %d)\n", - HGFS_VP_TO_FILENAME_LENGTH(dvp), HGFS_VP_TO_FILENAME(dvp), - (int)cnp->cn_namelen, cnp->cn_nameptr, - ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDoGetattrByName -- - * - * Send a name getattr request to the hgfs server and put the result in - * hgfsAttr. - * - * Results: - * Either 0 on success or a BSD error code on failure. The hgfsAttr field - * is only filled out on success. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsDoGetattrByName(const char *path, // IN : Path to get attributes for - HgfsSuperInfo *sip, // IN : SuperInfo block of hgfs mount. - HgfsAttrV2 *hgfsAttrV2) // OUT: Attributes from hgfs server -{ - int ret; - DEBUG(VM_DEBUG_ENTRY, "Enter(%s)\n", path); - ret = HgfsDoGetattrInt(path, 0, sip, hgfsAttrV2); - DEBUG(VM_DEBUG_EXIT, "Exit(%s -> %d)\n", path, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsDoGetattrByName -- - * - * Send a handle getattr request to the hgfs server and put the result in - * hgfsAttr. - * - * Results: - * Either 0 on success or a BSD error code on failure. The hgfsAttr field - * is only filled out on success. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -#if 0 -static int -HgfsDoGetattrByHandle(HgfsHandle handle, // IN : Hgfs handle for attr request - HgfsSuperInfo *sip, // IN : SuperInfo block for hgfs mount - HgfsAttrV2 *hgfsAttrV2) // OUT: Attributes from hgfs server -{ - int ret; - DEBUG(VM_DEBUG_ENTRY, "Enter(%u)\n", handle); - ret = HgfsDoGetattrInt(NULL, handle, sip, hgfsAttrV2); - DEBUG(VM_DEBUG_EXIT, "Exit(%u -> %d)\n", handle, ret); -} -#endif - -/* - *---------------------------------------------------------------------------- - * - * HgfsDoGetattrInt -- - * - * Internal function that actually sends a getattr request to the hgfs - * server and puts the results in hgfsAttrV2. This function should only - * be called by HgfsDoGetattrByName or HgfsDoGetattrByHandle and will do - * a getattr by filename if path is non-NULL. Otherwise it does a getattr by - * handle. - * - * - * Results: - * Either 0 on success or a BSD error code on failure. The hgfsAttr field - * is only filled out on success. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsDoGetattrInt(const char *path, // IN : Path to get attributes for - HgfsHandle handle, // IN : Handle to get attribues for - HgfsSuperInfo *sip, // IN : SuperInfo block for hgfs mount - HgfsAttrV2 *hgfsAttrV2) // OUT: Attributes from hgfs server -{ - HgfsKReqHandle req; - int ret = 0; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%s,%u)\n", (path != NULL ? path : "null"), handle); - ASSERT(hgfsAttrV2); - - req = HgfsKReq_AllocateRequest(sip->reqs, &ret); - if (!req) { - return ret; - } - - ret = HgfsQueryAttrInt(path, handle, sip, req); - if (ret == 0) { - HgfsReplyGetattrV3 *reply; - HgfsReply *replyHeader; - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - reply = (HgfsReplyGetattrV3 *)HGFS_REP_GET_PAYLOAD_V3(replyHeader); - - /* Fill out hgfsAttrV2 with the results from the server. */ - memcpy(hgfsAttrV2, &reply->attr, sizeof *hgfsAttrV2); - HgfsKReq_ReleaseRequest(sip->reqs, req); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%s,%u -> %d)\n", (path != NULL ? path : "null"), handle, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsQueryAttrInt -- - * - * Internal function that actually sends a getattr request to the hgfs - * server and puts the results in hgfsAttrV2. This function does - * a getattr by filename if path is non-NULL. Otherwise it does a getattr by - * handle. - * - * - * Results: - * Either 0 on success or a BSD error code on failure. When function - * succeeds a valid hgfs request is returned and it must be de-allocaed - * by the caller. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsQueryAttrInt(const char *path, // IN : Path to get attributes for - HgfsHandle handle, // IN : Handle to get attribues for - HgfsSuperInfo *sip, // IN : SuperInfo block for hgfs mount - HgfsKReqHandle req) // IN/OUT: preacllocated hgfs request -{ - HgfsRequest *requestHeader; - HgfsReply *replyHeader; - HgfsRequestGetattrV3 *request; - HgfsReplyGetattrV3 *reply; - uint32 reqSize; - uint32 repSize; - uint32 reqBufferSize; - int ret = 0; - - DEBUG(VM_DEBUG_ENTRY, "Enter(%s,%u)\n", (path != NULL ? path : "null"), handle); - requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req); - request = (HgfsRequestGetattrV3 *)HGFS_REQ_GET_PAYLOAD_V3(requestHeader); - - HGFS_INIT_REQUEST_HDR(requestHeader, req, HGFS_OP_GETATTR_V3); - request->reserved = 0; - - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(request); - reqBufferSize = HGFS_NAME_BUFFER_SIZET(HGFS_PACKET_MAX, reqSize); - - /* - * Per the calling conventions of this function, if the path is NULL then - * this is a Getattr by handle. - */ - if (path == NULL) { - request->hints = HGFS_ATTR_HINT_USE_FILE_DESC; - request->fileName.fid = handle; - request->fileName.flags = HGFS_FILE_NAME_USE_FILE_DESC; - request->fileName.caseType = HGFS_FILE_NAME_DEFAULT_CASE; - request->fileName.length = 0; - - } else { - /* Do a Getattr by path. */ - request->hints = 0; - request->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE; - request->fileName.fid = HGFS_INVALID_HANDLE; - request->fileName.flags = 0; - - /* - * Convert an input string to utf8 precomposed form, convert it to - * the cross platform name format and finally unescape any illegal - * filesystem characters. - */ - ret = HgfsNameToWireEncoding(path, strlen(path) + 1, - request->fileName.name, - reqBufferSize); - - if (ret < 0) { - DEBUG(VM_DEBUG_FAIL, "Could not encode to wire format"); - ret = -ret; - goto destroyOut; - } - request->fileName.length = ret; - reqSize += ret; - } - - /* Packet size includes the header, request and its payload. */ - HgfsKReq_SetPayloadSize(req, reqSize); - - DEBUG(VM_DEBUG_COMM, "sending getattr request for ID %d\n", - requestHeader->id); - DEBUG(VM_DEBUG_COMM, " fileName.length: %d\n", request->fileName.length); - DEBUG(VM_DEBUG_COMM, " fileName.name: \"%s\"\n", request->fileName.name); - - /* - * Submit the request and wait for the reply. HgfsSubmitRequest handles - * destroying the request on both error and interrupt cases. - */ - ret = HgfsSubmitRequest(sip, req); - if (ret) { - /* HgfsSubmitRequest destroys the request if necessary */ - goto out; - } - - replyHeader = (HgfsReply *)HgfsKReq_GetPayload(req); - - ret = HgfsGetStatus(req, sizeof *replyHeader); - if (ret) { - if (ret == EPROTO) { - DEBUG(VM_DEBUG_FAIL, "Error encountered for ID = %d\n" - "with status %d.\n", replyHeader->id, replyHeader->status); - } - goto destroyOut; - } - - reply = (HgfsReplyGetattrV3 *)HGFS_REP_GET_PAYLOAD_V3(replyHeader); - - DEBUG(VM_DEBUG_COMM, "received reply for ID %d\n", replyHeader->id); - DEBUG(VM_DEBUG_COMM, " status: %d (see hgfsProto.h)\n", replyHeader->status); - DEBUG(VM_DEBUG_COMM, " file type: %d\n", reply->attr.type); - DEBUG(VM_DEBUG_COMM, " file size: %llu\n", (long long unsigned)reply->attr.size); - DEBUG(VM_DEBUG_COMM, " permissions: %o\n", reply->attr.ownerPerms); - DEBUG(VM_DEBUG_COMM, " permissions: %o\n", reply->attr.groupPerms); - DEBUG(VM_DEBUG_COMM, " permissions: %o\n", reply->attr.otherPerms); - DEBUG(VM_DEBUG_COMM, " hostFileId: %llu\n", (long long unsigned)reply->attr.hostFileId); - - repSize = HGFS_REP_PAYLOAD_SIZE_V3(reply) + reply->symlinkTarget.length; - - /* The GetAttr succeeded, ensure packet contains correct amount of data. */ - if (HgfsKReq_GetPayloadSize(req) != repSize) { - DEBUG(VM_DEBUG_COMM, "HgfsLookup: invalid packet size received for \"%s\".\n", - path); - ret = EFAULT; - goto destroyOut; - } - -destroyOut: - if (ret != 0) { - HgfsKReq_ReleaseRequest(sip->reqs, req); - } - -out: - DEBUG(VM_DEBUG_EXIT, "Exit(%s,%u -> %d)\n", (path != NULL ? path : "null"), handle, ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * IsModeCompatible -- - * - * Checks if the requested mode is compatible with permissions. - * - * Results: - * Returns TRUE if the mode is compatible, FALSE otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static Bool -IsModeCompatible(HgfsAccessMode mode, // IN: Requested open mode - uint32 permissions) // IN: Effective user permissions -{ - if ((permissions & HGFS_PERM_READ) == 0) { - if ((mode & (HGFS_MODE_GENERIC_READ | - HGFS_MODE_READ_DATA | - HGFS_MODE_LIST_DIRECTORY | - HGFS_MODE_READ_ATTRIBUTES | - HGFS_MODE_READ_EXTATTRIBUTES | - HGFS_MODE_READ_SECURITY)) != 0) { - return FALSE; - } - } - - if ((permissions & HGFS_PERM_WRITE) == 0) { - if ((mode & (HGFS_MODE_GENERIC_WRITE | - HGFS_MODE_WRITE_DATA | - HGFS_MODE_APPEND_DATA | - HGFS_MODE_DELETE | - HGFS_MODE_ADD_SUBDIRECTORY | - HGFS_MODE_DELETE_CHILD | - HGFS_MODE_WRITE_ATTRIBUTES | - HGFS_MODE_WRITE_EXTATTRIBUTES | - HGFS_MODE_WRITE_SECURITY | - HGFS_MODE_TAKE_OWNERSHIP | - HGFS_MODE_ADD_FILE)) != 0) { - return FALSE; - } - } - - if ((permissions & HGFS_PERM_EXEC) == 0) { - if ((mode & (HGFS_MODE_GENERIC_EXECUTE | - HGFS_MODE_TRAVERSE_DIRECTORY)) != 0) { - return FALSE; - } - } - return TRUE; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsAccessInt -- - * - * Check to ensure the user has the specified type of access to the file. - * - * Results: - * Returns 0 if access is allowed and a non-zero error code otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsAccessInt(struct vnode *vp, // IN: Vnode to check access for - HgfsAccessMode mode) // IN: Access mode requested. -{ - int ret = 0; - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - HgfsAttrV2 hgfsAttrV2; - - DEBUG(VM_DEBUG_ENTRY, "HgfsAccessInt(%.*s,%d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), - HGFS_VP_TO_FILENAME(vp), mode); - - ret = HgfsDoGetattrByName(HGFS_VP_TO_FILENAME(vp), sip, &hgfsAttrV2); - if (ret == 0) { - uint32 effectivePermissions; - if (hgfsAttrV2.mask & HGFS_ATTR_VALID_EFFECTIVE_PERMS) { - effectivePermissions = hgfsAttrV2.effectivePerms; - } else { - /* - * If the server did not return actual effective permissions then - * need to calculate ourselves. However we should avoid unnecessary denial of - * access so perform optimistic permissions calculation. - * It is safe since host enforces necessary restrictions regardless of - * the client's decisions. - */ - effectivePermissions = - hgfsAttrV2.ownerPerms | hgfsAttrV2.groupPerms | hgfsAttrV2.otherPerms; - } - if (!IsModeCompatible(mode, effectivePermissions)) { - ret = EACCES; - DEBUG(VM_DEBUG_FAIL, "HgfsAccessInt denied access: %s (%d, %d)\n", - HGFS_VP_TO_FILENAME(vp), mode, effectivePermissions); - } - } else { - DEBUG(VM_DEBUG_FAIL, "HgfsAccessInt failed getting attrib: %s (%d)\n", - HGFS_VP_TO_FILENAME(vp), ret); - } - - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), - HGFS_VP_TO_FILENAME(vp), ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsMmapInt -- - * - * HgfsMmapInt is invoked invoked from HgfsVnopMmap to verify parameters - * and mark vnode as mmapped if necessary. - * - * Results: - * Zero on success or non-zero error code otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsMmapInt(struct vnode *vp, - int accessMode) -{ - int ret; - HgfsFile *fp; - - ASSERT(vp); - fp = HGFS_VP_TO_FP(vp); - - ASSERT(fp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s,%d)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), - HGFS_VP_TO_FILENAME(vp), accessMode); - - /* - * If the directory is already opened then we are done. - * There is no different open modes for directories thus the handle is compatible. - */ - os_rw_lock_lock_exclusive(fp->handleLock); - - ret = HgfsCheckAndReferenceHandle(vp, accessMode, OPENREQ_MMAP); - os_rw_lock_unlock_exclusive(fp->handleLock); - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d).\n", HGFS_VP_TO_FILENAME_LENGTH(vp), - HGFS_VP_TO_FILENAME(vp), ret); - return ret; -} - - -/* - *---------------------------------------------------------------------------- - * - * HgfsMnomapInt -- - * - * HgfsMnomapInt is invoked invoked from HgfsVnopNomap to tear down memory - * mapping and dereference file handle. - * - * Results: - * Zero on success or non-zero error code otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -int -HgfsMnomapInt(struct vnode *vp) -{ - int ret = 0; - HgfsHandle handleToClose; - HgfsSuperInfo *sip = HGFS_VP_TO_SIP(vp); - - ASSERT(vp); - - DEBUG(VM_DEBUG_ENTRY, "Enter(%.*s)\n", HGFS_VP_TO_FILENAME_LENGTH(vp), - HGFS_VP_TO_FILENAME(vp)); - - /* - * Check to see if we should close the file handle on the host, which happen when - * the reference count of the current handle become 0. - */ - if (HgfsReleaseOpenFileHandle(vp, OPENREQ_MMAP, &handleToClose) == 0) { - ret = HgfsCloseServerFileHandle(sip, handleToClose); - } - DEBUG(VM_DEBUG_EXIT, "Exit(%.*s -> %d).\n", HGFS_VP_TO_FILENAME_LENGTH(vp), - HGFS_VP_TO_FILENAME(vp), ret); - return ret; -} diff --git a/open-vm-tools/modules/freebsd/vmhgfs/vnopscommon.h b/open-vm-tools/modules/freebsd/vmhgfs/vnopscommon.h deleted file mode 100644 index 43bcdbde..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/vnopscommon.h +++ /dev/null @@ -1,94 +0,0 @@ -/********************************************************* - * Copyright (C) 2008 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * vnopscommon.h -- - * - * Common VFS vnop implementations that are shared between both Mac OS and FreeBSD. - */ - -#ifndef _HGFS_VNOPS_COMMON_H_ -#define _HGFS_VNOPS_COMMON_H_ - -#include "hgfs_kernel.h" - -/* - * Macros - */ - -/* Access uio struct information in a Mac OS / FreeBSD independent manner. */ -#if defined __FreeBSD__ -#define HGFS_UIOP_TO_RESID(uiop) \ - ((uiop)->uio_resid) -#define HGFS_UIOP_TO_OFFSET(uiop) \ - ((uiop)->uio_offset) -#define HGFS_UIOP_SET_OFFSET(uiop, offset) \ - ((uiop)->uio_offset = (offset)) -#elif defined __APPLE__ -#define HGFS_UIOP_TO_RESID(uiop) \ - (uio_resid(uiop)) -#define HGFS_UIOP_TO_OFFSET(uiop) \ - (uio_offset(uiop)) -#define HGFS_UIOP_SET_OFFSET(uiop, offset) \ - (uio_setoffset(uiop, offset)) -#endif - -/* Access vnode struct information in a Mac OS / FreeBSD independent manner. */ -#if defined __FreeBSD__ -#define HGFS_VP_TO_VTYPE(vp) \ - (vp->v_type) -#define HGFS_VPP_GET_IOCOUNT(vpp) \ - (vref(*vpp)) -#elif defined __APPLE__ -#define HGFS_VP_TO_VTYPE(vp) \ - (vnode_vtype(vp)) -#define HGFS_VPP_GET_IOCOUNT(vpp) \ - (vnode_get(*vpp)) -#endif - -/* Internal Vnops functions used by both FreeBSD and Mac OS */ -int HgfsReaddirInt(struct vnode *vp, struct uio *uiop, int *eofp); -int HgfsSetattrInt(struct vnode *vp, HgfsVnodeAttr *vap); -int HgfsGetattrInt(struct vnode *vp, HgfsVnodeAttr *vap); -int HgfsRmdirInt(struct vnode *dvp, struct vnode *vp, - struct componentname *cnp); -int HgfsRemoveInt(struct vnode *vp); -int HgfsCloseInt(struct vnode *vp, int mode); -int HgfsOpenInt(struct vnode *vp, int fflag, HgfsOpenType openType); -int HgfsLookupInt(struct vnode *dvp, struct vnode **vpp, - struct componentname *cnp); -int HgfsCreateInt(struct vnode *dvp, struct vnode **vpp, - struct componentname *cnp, int mode); -int HgfsReadInt(struct vnode *vp, struct uio *uiop, Bool pagingIo); -int HgfsReadlinkInt(struct vnode *vp, struct uio *uiop); -int HgfsWriteInt(struct vnode *vp, struct uio *uiop, - int ioflag, Bool pagingIo); -int HgfsMkdirInt(struct vnode *dvp, struct vnode **vpp, - struct componentname *cnp, int mode); -int HgfsRenameInt(struct vnode *fvp, - struct vnode *tdvp, struct vnode *tvp, - struct componentname *tcnp); -int HgfsAccessInt(struct vnode *vp, HgfsAccessMode mode); -int HgfsSymlinkInt(struct vnode *dvp, - struct vnode **vpp, - struct componentname *cnp, - char *targetName); -int HgfsMmapInt(struct vnode *vp, int accessMode); -int HgfsMnomapInt(struct vnode *vp); - -#endif // _HGFS_VNOPS_COMMON_H_ diff --git a/open-vm-tools/modules/freebsd/vmhgfs/worker.c b/open-vm-tools/modules/freebsd/vmhgfs/worker.c deleted file mode 100644 index 0a9537b7..00000000 --- a/open-vm-tools/modules/freebsd/vmhgfs/worker.c +++ /dev/null @@ -1,280 +0,0 @@ -/********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * worker.c -- - * - * Worker thread to process issue Guest -> Host Hgfs requests. - */ - -#if defined __FreeBSD__ -# include <sys/libkern.h> -#endif - -#include "hgfs_kernel.h" -#include "request.h" -#include "requestInt.h" -#include "os.h" -#include "channel.h" - - -/* - * Local data - */ - -/* - * Process structure filled in when the worker thread is created. - */ -OS_THREAD_T hgfsKReqWorkerThread; - -/* - * See requestInt.h. - */ -HgfsKReqWState hgfsKReqWorkerState; -HgfsTransportChannel *gHgfsChannel = NULL; -OS_MUTEX_T *gHgfsChannelLock = NULL; - - -/* - * Global (module) functions - */ - -/* - *---------------------------------------------------------------------- - * - * HgfsTransportSetupNewChannel -- - * - * Find a new workable channel. - * - * Results: - * TRUE on success, otherwise FALSE. - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -Bool -HgfsSetupNewChannel(void) -{ - Bool ret; - - os_mutex_lock(gHgfsChannelLock); - - if (gHgfsChannel && gHgfsChannel->status == HGFS_CHANNEL_CONNECTED) { - ret = TRUE; - goto exit; - } - - gHgfsChannel = HgfsGetVmciChannel(); - if (gHgfsChannel) { - if ((ret = gHgfsChannel->ops.open(gHgfsChannel))) { - goto exit; - } - } - - /* Every client using this code is expected to have backdoor enabled. */ - gHgfsChannel = HgfsGetBdChannel(); - ret = gHgfsChannel->ops.open(gHgfsChannel); - -exit: - if (ret) { - gHgfsChannel->status = HGFS_CHANNEL_CONNECTED; - DEBUG(VM_DEBUG_ALWAYS, "Channel: %s\n", gHgfsChannel->name); - } else { - gHgfsChannel->status = HGFS_CHANNEL_NOTCONNECTED; - } - - os_mutex_unlock(gHgfsChannelLock); - - return ret; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsKReqWorker -- - * - * Main routine for Hgfs client worker thread. This thread is responsible - * for all Hgfs communication with the host via the backdoor. - * - * Results: - * None. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -void -HgfsKReqWorker(void *arg) -{ - DblLnkLst_Links *currNode, *nextNode; - HgfsKReqWState *ws = (HgfsKReqWState *)arg; - HgfsKReqObject *req; - int ret = 0; - HgfsTransportChannel *channel; - - ws->running = TRUE; - - gHgfsChannelLock = os_mutex_alloc_init(HGFS_FS_NAME "_channellck"); - if (!gHgfsChannelLock) { - goto exit; - } - - ret = HgfsSetupNewChannel(); - if (!ret) { - DEBUG(VM_DEBUG_INFO, "VMware hgfs: %s: ohoh no channel yet.\n", __func__); - } - - for (;;) { - /* - * This loop spends most of its time sleeping until signalled by another - * thread. We expect to be signalled only if either there is work to do - * or if the module is being unloaded. - */ - - os_mutex_lock(hgfsKReqWorkItemLock); - - while (!ws->exit && !DblLnkLst_IsLinked(&hgfsKReqWorkItemList)) { - os_cv_wait(&hgfsKReqWorkItemCv, hgfsKReqWorkItemLock); - } - - if (ws->exit) { - /* Note that the list lock is still held. */ - break; - } - - /* - * We have work to do! Hooray! Start by locking the request and pulling - * it from the work item list. (The list's reference is transferred to - * us, so we'll decrement the request's reference count when we're - * finished with it.) - * - * With the request locked, make a decision based on the request's state. - * Typically a request will be in the SUBMITTED state, but if its owner - * aborted an operation or the file system cancelled it, it may be listed - * as ABANDONED. If either of the latter are true, then we don't bother - * with any further processing. - * - * Because we're not sure how long the backdoor operation will take, we - * yield the request's state lock before calling HgfsBd_Dispatch. Upon - * return, we must test the state again (see above re: cancellation), - * and then we finally update the state & signal any waiters. - */ - - currNode = hgfsKReqWorkItemList.next; - DblLnkLst_Unlink1(currNode); - req = DblLnkLst_Container(currNode, HgfsKReqObject, pendingNode); - - os_mutex_lock(req->stateLock); - - channel = req->channel; - switch (req->state) { - case HGFS_REQ_SUBMITTED: - if (channel->status != HGFS_CHANNEL_CONNECTED) { - req->state = HGFS_REQ_ERROR; - os_cv_signal(&req->stateCv); - os_mutex_unlock(req->stateLock); - os_mutex_unlock(hgfsKReqWorkItemLock); - goto done; - } - break; - case HGFS_REQ_ABANDONED: - case HGFS_REQ_ERROR: - os_mutex_unlock(req->stateLock); - os_mutex_unlock(hgfsKReqWorkItemLock); - goto done; - default: - panic("Request object (%p) in unknown state: %u", req, req->state); - } - os_mutex_unlock(req->stateLock); - - /* - * We're done with the work item list for now. Unlock it and let the file - * system add requests while we're busy. - */ - os_mutex_unlock(hgfsKReqWorkItemLock); - - ret = channel->ops.send(gHgfsChannel, req); - - if (ret != 0) { - /* - * If the channel was previously open, make sure it's dead and gone - * now. We do this because subsequent requests deserve a chance to - * reopen it. - */ - os_mutex_lock(gHgfsChannelLock); - gHgfsChannel->ops.close(gHgfsChannel); - os_mutex_unlock(gHgfsChannelLock); - } - -done: - - /* - * If transport wants to process request async then it should have - * taken reference for itself. If not we free it. - */ - if (os_add_atomic(&req->refcnt, -1) == 1) { - os_zone_free(hgfsKReqZone, req); - } - } - - /* - * NB: The work item lock is still held. - * - * XXX There may be some request on the sentList. what should we do about them ? - */ - - /* - * We're signaled to exit. Remove any items from the pending request list - * before exiting. - */ - DblLnkLst_ForEachSafe(currNode, nextNode, &hgfsKReqWorkItemList) { - req = DblLnkLst_Container(currNode, HgfsKReqObject, pendingNode); - DblLnkLst_Unlink1(currNode); - os_mutex_lock(req->stateLock); - req->state = HGFS_REQ_ERROR; - os_cv_signal(&req->stateCv); - os_mutex_unlock(req->stateLock); - - /* - * If we held the final reference to a request, free it. - */ - if (os_add_atomic(&req->refcnt, -1) == 1) { - os_zone_free(hgfsKReqZone, req); - } - } - - os_mutex_unlock(hgfsKReqWorkItemLock); - - ws->running = FALSE; - - if (gHgfsChannel && gHgfsChannel->status == HGFS_CHANNEL_CONNECTED) { - gHgfsChannel->ops.close(gHgfsChannel); - } - - if (gHgfsChannelLock) { - os_mutex_free(gHgfsChannelLock); - } -exit: - os_thread_exit(0); -} diff --git a/open-vm-tools/modules/freebsd/vmmemctl/os.c b/open-vm-tools/modules/freebsd/vmmemctl/os.c index caee2a66..1342edab 100644 --- a/open-vm-tools/modules/freebsd/vmmemctl/os.c +++ b/open-vm-tools/modules/freebsd/vmmemctl/os.c @@ -295,7 +295,12 @@ OS_ReservedPageGetHandle(PA64 pa) // IN Mapping OS_MapPageHandle(PageHandle handle) // IN { +#if __FreeBSD_version < 1000000 vm_offset_t res = kmem_alloc_nofault(kernel_map, PAGE_SIZE); +#else + vm_offset_t res = kva_alloc(PAGE_SIZE); +#endif + vm_page_t page = (vm_page_t)handle; if (!res) { @@ -352,7 +357,11 @@ void OS_UnmapPage(Mapping mapping) // IN { pmap_qremove((vm_offset_t)mapping, 1); +#if __FreeBSD_version < 1000000 kmem_free(kernel_map, (vm_offset_t)mapping, PAGE_SIZE); +#else + kva_free((vm_offset_t)mapping, PAGE_SIZE); +#endif } @@ -363,20 +372,28 @@ os_pmap_alloc(os_pmap *p) // IN p->size = (cnt.v_page_count + 7) / 8; /* - * expand to nearest word boundary - * XXX: bitmap can be greater than total number of pages in system + * expand to nearest word boundary + * XXX: bitmap can be greater than total number of pages in system */ - p->size = (p->size + sizeof(unsigned long) - 1) & + p->size = (p->size + sizeof(unsigned long) - 1) & ~(sizeof(unsigned long) - 1); +#if __FreeBSD_version < 1000000 p->bitmap = (unsigned long *)kmem_alloc(kernel_map, p->size); +#else + p->bitmap = (unsigned long *)kmem_malloc(kernel_arena, p->size, M_WAITOK | M_ZERO); +#endif } static void os_pmap_free(os_pmap *p) // IN { +#if __FreeBSD_version < 1000000 kmem_free(kernel_map, (vm_offset_t)p->bitmap, p->size); +#else + kmem_free(kernel_arena, (vm_offset_t)p->bitmap, p->size); +#endif p->size = 0; p->bitmap = NULL; } diff --git a/open-vm-tools/modules/freebsd/vmxnet/net_compat.h b/open-vm-tools/modules/freebsd/vmxnet/net_compat.h index 78c38507..c36ca745 100644 --- a/open-vm-tools/modules/freebsd/vmxnet/net_compat.h +++ b/open-vm-tools/modules/freebsd/vmxnet/net_compat.h @@ -170,9 +170,12 @@ #if __FreeBSD_version < 505000 # define VXN_IF_ADDR_LOCK(_ifp) # define VXN_IF_ADDR_UNLOCK(_ifp) -#else +#elif __FreeBSD_version < 1000000 # define VXN_IF_ADDR_LOCK(_ifp) IF_ADDR_LOCK((_ifp)) # define VXN_IF_ADDR_UNLOCK(_ifp) IF_ADDR_UNLOCK((_ifp)) +#else +# define VXN_IF_ADDR_LOCK(_ifp) if_maddr_rlock((_ifp)) +# define VXN_IF_ADDR_UNLOCK(_ifp) if_maddr_runlock((_ifp)) #endif #endif /* _VXN_NET_COMPAT_H_ */ diff --git a/open-vm-tools/modules/linux/dkms.conf b/open-vm-tools/modules/linux/dkms.conf index 908132e6..7d93e317 100644 --- a/open-vm-tools/modules/linux/dkms.conf +++ b/open-vm-tools/modules/linux/dkms.conf @@ -1,5 +1,5 @@ PACKAGE_NAME=open-vm-tools -PACKAGE_VERSION=2013.09.16 +PACKAGE_VERSION=2015.01.29 MAKE_CMD_TMPL="make VM_UNAME=\$kernelver \ MODULEBUILDDIR=$dkms_tree/$PACKAGE_NAME/$PACKAGE_VERSION/build" diff --git a/open-vm-tools/modules/linux/dkms.sh b/open-vm-tools/modules/linux/dkms.sh index 6626c183..c0cb59c8 100644 --- a/open-vm-tools/modules/linux/dkms.sh +++ b/open-vm-tools/modules/linux/dkms.sh @@ -1,6 +1,6 @@ #!/bin/sh ################################################################################ -### Copyright 2009 VMware, Inc. All rights reserved. +### Copyright (C) 2009-2015 VMware, Inc. All rights reserved. ### ### Script for creating a dmks-compliant source tree from an open-vm-tools ### distribution. @@ -28,12 +28,12 @@ then echo " src: root of unpacked open-vm-tools package" echo " dst: where to create the dkms tree" echo - echo "The script will create an 'open-vm-tools' module with version 2013.09.16." + echo "The script will create an 'open-vm-tools' module with version 2015.01.29." exit 1 fi src=$1 -dst=$2/open-vm-tools-2013.09.16 +dst=$2/open-vm-tools-2015.01.29 SHARED_HEADERS="backdoor_def.h" SHARED_HEADERS="$SHARED_HEADERS backdoor_types.h" diff --git a/open-vm-tools/modules/freebsd/vmhgfs/vmci.c b/open-vm-tools/modules/linux/shared/autoconf/dcount.c index b5fd216d..c78968d0 100644 --- a/open-vm-tools/modules/freebsd/vmhgfs/vmci.c +++ b/open-vm-tools/modules/linux/shared/autoconf/dcount.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2010 VMware, Inc. All rights reserved. + * Copyright (C) 2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,33 +16,28 @@ * *********************************************************/ -/* - * vmci.c -- - * - * VMCI transport channel for the HGFS client is not currently implemented. - */ -#include "channel.h" +#include "compat_version.h" +#include "compat_autoconf.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) +#include <linux/dcache.h> /* - *---------------------------------------------------------------------- - * - * HgfsGetVmciChannel -- - * - * Get Vmci channel. + * After 3.11.0, the dentry d_count field was removed. Red Hat + * backported this behavior into a 3.10.0 kernel. * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- + * This test will fail on a kernel with such a patch. */ - -HgfsTransportChannel* -HgfsGetVmciChannel(void) // IN: +void test(void) { - return NULL; -} + struct dentry dentry; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) + dentry.d_count = 1; +#else + atomic_set(&dentry.d_count, 1); +#endif +} +#else +#error "This test intentionally fails on 3.11.0 or newer kernels." +#endif diff --git a/open-vm-tools/modules/freebsd/vmhgfs/vfsopscommon.h b/open-vm-tools/modules/linux/shared/autoconf/file_operations_flush.c index ad3cd052..818aee32 100644 --- a/open-vm-tools/modules/freebsd/vmhgfs/vfsopscommon.h +++ b/open-vm-tools/modules/linux/shared/autoconf/file_operations_flush.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2008 VMware, Inc. All rights reserved. + * Copyright (C) 2013 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,32 +17,30 @@ *********************************************************/ /* - * vfsopscommon.h -- + * Linux v2.6.18 added an owner parameter to flush. + * But SLES10 has backported the change to its 2.6.16.60 kernel, + * so we can't rely solely on kernel version to determine number of + * arguments. * - * Common VFS vfsop implementations that are shared between both Mac OS and FreeBSD. + * This test will fail on a kernel with such a patch. */ -#ifndef _HGFS_VFSOPS_COMMON_H_ -#define _HGFS_VFSOPS_COMMON_H_ +#include "compat_version.h" +#include "compat_autoconf.h" -#include <sys/mount.h> -#include <sys/vnode.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +#error This compile test intentionally fails on 2.6.18 and newer kernels. +#else -/* - * Macros - */ - -#define HGFS_CONVERT_TO_BLOCKS(bytes) (bytes / HGFS_BLOCKSIZE) -#define HGFS_IS_POWER_OF_TWO(val) (val && !(val & (val - 1))) - -#if defined __FreeBSD__ - typedef struct statfs HgfsStatfs; -#elif defined __APPLE__ - typedef struct vfsstatfs HgfsStatfs; -#endif +#include <linux/fs.h> +static int TestFlush(struct file *file); +{ + return 0; +} -int -HgfsStatfsInt(struct vnode *vp, HgfsStatfs *stat); +struct file_operations testFO = { + .flush = TestFlush, +}; -#endif // _HGFS_VFSOPS_COMMON_H_ +#endif diff --git a/open-vm-tools/modules/linux/shared/compat_cred.h b/open-vm-tools/modules/linux/shared/compat_cred.h index 8f02001a..95a7baa7 100644 --- a/open-vm-tools/modules/linux/shared/compat_cred.h +++ b/open-vm-tools/modules/linux/shared/compat_cred.h @@ -40,4 +40,8 @@ #define cap_set_full(_c) do { (_c) = CAP_FULL_SET; } while (0) #endif +#if !defined(GLOBAL_ROOT_UID) +#define GLOBAL_ROOT_UID (0) +#endif + #endif /* __COMPAT_CRED_H__ */ diff --git a/open-vm-tools/modules/linux/shared/compat_dcache.h b/open-vm-tools/modules/linux/shared/compat_dcache.h index 0450aeef..d16fd1d3 100644 --- a/open-vm-tools/modules/linux/shared/compat_dcache.h +++ b/open-vm-tools/modules/linux/shared/compat_dcache.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2013 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -25,7 +25,7 @@ * per-dentry locking was born in 2.5.62. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 62) -#define compat_lock_dentry(dentry) spin_lock(&dentry->d_lock) +#define compat_lock_dentry(dentry) spin_lock(&dentry->d_lock) #define compat_unlock_dentry(dentry) spin_unlock(&dentry->d_lock) #else #define compat_lock_dentry(dentry) do {} while (0) diff --git a/open-vm-tools/modules/linux/shared/compat_skbuff.h b/open-vm-tools/modules/linux/shared/compat_skbuff.h index d1a72a5e..b6468855 100644 --- a/open-vm-tools/modules/linux/shared/compat_skbuff.h +++ b/open-vm-tools/modules/linux/shared/compat_skbuff.h @@ -35,9 +35,15 @@ #define compat_skb_network_header_len(skb) skb_network_header_len(skb) #define compat_skb_tail_pointer(skb) skb_tail_pointer(skb) #define compat_skb_end_pointer(skb) skb_end_pointer(skb) -#define compat_skb_ip_header(skb) ((struct iphdr *)skb_network_header(skb)) -#define compat_skb_ipv6_header(skb) ((struct ipv6hdr *)skb_network_header(skb)) -#define compat_skb_tcp_header(skb) ((struct tcphdr *)skb_transport_header(skb)) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) +# define compat_skb_ip_header(skb) ip_hdr(skb) +# define compat_skb_ipv6_header(skb) ipv6_hdr(skb) +# define compat_skb_tcp_header(skb) tcp_hdr(skb) +#else +# define compat_skb_ip_header(skb) ((struct iphdr *)skb_network_header(skb)) +# define compat_skb_ipv6_header(skb) ((struct ipv6hdr *)skb_network_header(skb)) +# define compat_skb_tcp_header(skb) ((struct tcphdr *)skb_transport_header(skb)) +#endif #define compat_skb_reset_mac_header(skb) skb_reset_mac_header(skb) #define compat_skb_reset_network_header(skb) skb_reset_network_header(skb) #define compat_skb_reset_transport_header(skb) skb_reset_transport_header(skb) diff --git a/open-vm-tools/modules/linux/shared/kernelStubs.h b/open-vm-tools/modules/linux/shared/kernelStubs.h index 800a0cf8..c242fccd 100644 --- a/open-vm-tools/modules/linux/shared/kernelStubs.h +++ b/open-vm-tools/modules/linux/shared/kernelStubs.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -27,6 +27,21 @@ #ifndef __KERNELSTUBS_H__ #define __KERNELSTUBS_H__ +#define KRNL_STUBS_DRIVER_TYPE_POSIX 1 +#define KRNL_STUBS_DRIVER_TYPE_GDI 2 +#define KRNL_STUBS_DRIVER_TYPE_WDM 3 +#define KRNL_STUBS_DRIVER_TYPE_NDIS 4 + +// For now (vsphere-2015), choose a good default. Later we'll modify all the +// build files using KernelStubs to set this. +#ifndef KRNL_STUBS_DRIVER_TYPE +# if defined(_WIN32) +# define KRNL_STUBS_DRIVER_TYPE KRNL_STUBS_DRIVER_TYPE_WDM +# else +# define KRNL_STUBS_DRIVER_TYPE KRNL_STUBS_DRIVER_TYPE_POSIX +# endif +#endif + #ifdef linux # ifndef __KERNEL__ # error "__KERNEL__ is not defined" @@ -36,12 +51,32 @@ # include <linux/kernel.h> # include <linux/string.h> #elif defined(_WIN32) -# include "vm_basic_types.h" -# include <ntddk.h> /* kernel memory APIs */ -# include <stdio.h> /* for _vsnprintf, vsprintf */ -# include <stdarg.h> /* for va_start stuff */ -# include <stdlib.h> /* for min macro. */ -# include "vm_assert.h" /* Our assert macros */ +# define _CRT_ALLOCATION_DEFINED // prevent malloc.h from defining malloc et. all +# if KRNL_STUBS_DRIVER_TYPE == KRNL_STUBS_DRIVER_TYPE_GDI +# include <d3d9.h> +# include <winddi.h> +# include <stdio.h> +# include "vm_basic_types.h" +# include "vm_basic_defs.h" +# include "vm_assert.h" +# elif KRNL_STUBS_DRIVER_TYPE == KRNL_STUBS_DRIVER_TYPE_NDIS +# include "vm_basic_types.h" +# include <ndis.h> +# elif KRNL_STUBS_DRIVER_TYPE == KRNL_STUBS_DRIVER_TYPE_WDM +# include "vm_basic_types.h" +# if defined(NTDDI_WINXP) && (NTDDI_VERSION >= NTDDI_WINXP) +# include <wdm.h> /* kernel memory APIs, DbgPrintEx */ +# else +# include <ntddk.h> /* kernel memory APIs */ +# endif +# include <stdio.h> /* for _vsnprintf, vsprintf */ +# include <stdarg.h> /* for va_start stuff */ +# include <stdlib.h> /* for min macro. */ +# include "vm_basic_defs.h" +# include "vm_assert.h" /* Our assert macros */ +# else +# error Type KRNL_STUBS_DRIVER_TYPE must be defined. +# endif #elif defined(__FreeBSD__) # include "vm_basic_types.h" # ifndef _KERNEL @@ -65,6 +100,7 @@ # include <sys/types.h> # include <sys/varargs.h> #endif +#include "kernelStubsSal.h" /* * Function Prototypes @@ -84,19 +120,41 @@ void *realloc(void *ptr, size_t newSize); #elif defined(_WIN32) /* } else if (_WIN32) { */ -#if (_WIN32_WINNT == 0x0400) -/* The following declarations are missing on NT4. */ -typedef unsigned int UINT_PTR; -typedef unsigned int SIZE_T; +_Ret_allocates_malloc_mem_opt_bytecap_(_Size) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS _CRTRESTRICT +void * __cdecl malloc( + _In_ size_t _Size); -/* No free with tag availaible on NT4 kernel! */ -#define KRNL_STUBS_FREE(P,T) ExFreePool((P)) +_Ret_allocates_malloc_mem_opt_bytecount_(_Count*_Size) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS _CRTRESTRICT +void * __cdecl calloc( + _In_ size_t _Count, + _In_ size_t _Size); -#else /* _WIN32_WINNT */ -#define KRNL_STUBS_FREE(P,T) ExFreePoolWithTag((P),(T)) -/* Win 2K and later useful kernel function, documented but not declared! */ -NTKERNELAPI VOID ExFreePoolWithTag(IN PVOID P, IN ULONG Tag); -#endif /* _WIN32_WINNT */ +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS +void __cdecl free( + _In_frees_malloc_mem_opt_ void * _Memory); + +_Success_(return != 0) +_When_(_Memory != 0, _Ret_reallocates_malloc_mem_opt_newbytecap_oldbytecap_(_NewSize, ((uintptr_t*)_Memory)[-1])) +_When_(_Memory == 0, _Ret_reallocates_malloc_mem_opt_newbytecap_(_NewSize)) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS _CRTRESTRICT +void * __cdecl realloc( + _In_reallocates_malloc_mem_opt_oldptr_ void * _Memory, + _In_ size_t _NewSize); + +_Success_(return != 0) +_Ret_allocates_malloc_mem_opt_z_ +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTIMP +char * __cdecl _strdup_impl( + _In_opt_z_ const char * _Src); + +#define strdup _strdup_impl #elif defined(__FreeBSD__) /* } else if (FreeBSD) { */ @@ -127,23 +185,84 @@ __compat_malloc(unsigned long size, struct malloc_type *type, int flags) { #endif /* } */ +_Ret_writes_z_(maxSize) +char *Str_Strcpy( + _Out_z_cap_(maxSize) char *buf, + _In_z_ const char *src, + _In_ size_t maxSize); + +_Ret_writes_z_(maxSize) +char *Str_Strcat( + _Inout_z_cap_(maxSize) char *buf, + _In_z_ const char *src, + _In_ size_t maxSize); + +_Success_(return >= 0) +int Str_Sprintf( + _Out_z_cap_(maxSize) _Post_z_count_(return+1) char *buf, + _In_ size_t maxSize, + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(3, 4); + +_Success_(return != -1) +int Str_Vsnprintf( + _Out_z_cap_(size) _Post_z_count_(return+1) char *str, + _In_ size_t size, + _In_z_ _Printf_format_string_ const char *format, + _In_ va_list ap) PRINTF_DECL(3, 0); + +_Success_(return != 0) +_When_(length != 0, _Ret_allocates_malloc_mem_opt_z_bytecount_(*length)) +_When_(length == 0, _Ret_allocates_malloc_mem_opt_z_) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +char *Str_Vasprintf( + _Out_opt_ size_t *length, + _In_z_ _Printf_format_string_ const char *format, + _In_ va_list arguments) PRINTF_DECL(2, 0); + +_Success_(return != 0) +_When_(length != 0, _Ret_allocates_malloc_mem_opt_z_bytecount_(*length)) +_When_(length == 0, _Ret_allocates_malloc_mem_opt_z_) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +char *Str_Asprintf( + _Out_opt_ size_t *length, + _In_z_ _Printf_format_string_ const char *format, + ...) PRINTF_DECL(2, 3); + +#ifdef _WIN32 +#pragma warning(push) +#pragma warning(disable: 28301) // Suppress complaint that first declaration lacked annotations +#endif + +// For now (vsphere-2015), we don't implement Panic, Warning, or Debug in the +// GDI case. +#if KRNL_STUBS_DRIVER_TYPE != KRNL_STUBS_DRIVER_TYPE_GDI + /* * Stub functions we provide. */ +#ifdef _WIN32 +NORETURN +#endif +void Panic( + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(1, 2); -void Panic(const char *fmt, ...); - -char *Str_Strcpy(char *buf, const char *src, size_t maxSize); -int Str_Vsnprintf(char *str, size_t size, const char *format, - va_list arguments); -char *Str_Vasprintf(size_t *length, const char *format, - va_list arguments); -char *Str_Asprintf(size_t *length, const char *Format, ...); +void Warning( + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(1, 2); /* * Functions the driver must implement for the stubs. */ -EXTERN void Debug(const char *fmt, ...); +EXTERN void Debug( + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(1, 2); +#endif // KRNL_STUBS_DRIVER_TYPE != KRNL_STUBS_DRIVER_TYPE_GDI + +#ifdef _WIN32 +#pragma warning(pop) +#endif #endif /* __KERNELSTUBS_H__ */ diff --git a/open-vm-tools/modules/linux/shared/kernelStubsLinux.c b/open-vm-tools/modules/linux/shared/kernelStubsLinux.c index 221f88a6..b8579fca 100644 --- a/open-vm-tools/modules/linux/shared/kernelStubsLinux.c +++ b/open-vm-tools/modules/linux/shared/kernelStubsLinux.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -91,13 +91,15 @@ Str_Strcpy(char *buf, // OUT const char *src, // IN size_t maxSize) // IN { - unsigned int *stack = (unsigned int *)&buf; size_t len; len = strlen(src); if (len >= maxSize) { - Panic("%s:%d Buffer too small 0x%x\n", __FILE__,__LINE__, - stack[-1]); +#ifdef GetReturnAddress + Panic("%s:%d Buffer too small 0x%p\n", __FILE__, __LINE__, GetReturnAddress()); +#else + Panic("%s:%d Buffer too small\n", __FILE__, __LINE__); +#endif } return memcpy(buf, src, len + 1); } diff --git a/open-vm-tools/modules/linux/shared/kernelStubsSal.h b/open-vm-tools/modules/linux/shared/kernelStubsSal.h new file mode 100644 index 00000000..6938aed5 --- /dev/null +++ b/open-vm-tools/modules/linux/shared/kernelStubsSal.h @@ -0,0 +1,134 @@ +/********************************************************* + * Copyright (C) 2014 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +/* + * kernelStubsSal.h + * + * Contains definitions source annotation language definitions for kernel drivers. + * This solves two issues: + * 1. Microsoft changed their annotation language from SAL 1.0 (original one + * widely distributed by the Windows team) to their more final SAL 2.0 + * langauge (championed by the VS team). We target multiple versions of + * Driver Kits, so we have to map 2.0 to 1.0. + * 2. We want these annotations to do nothing during non-Win32 compiles. + * + * A longer term goal is to rationalize this into Bora. + */ +#ifndef __KERNELSTUBSSAL_H__ +#define __KERNELSTUBSSAL_H__ + +#if defined(_WIN32) +# include <DriverSpecs.h> +# if !defined(_SAL_VERSION) +# define _SAL_VERSION 10 +# endif +#endif + +#if !defined(_SAL_VERSION) +#define _In_ +#define _In_z_ +#define _In_opt_ +#define _In_opt_z_ +#define _Out_ +#define _Out_opt_ +#define _Out_z_cap_(e) +#define _Inout_ +#define _Inout_z_cap_(e) +#define _Post_z_count_(e) +#define _Ret_writes_z_(e) +#define _Ret_writes_maybenull_z_(e) +#define _Ret_maybenull_z_ +#define _Success_(expr) +#define _Check_return_ +#define _Must_inspect_result_ +#define _Group_(annos) +#define _When_(expr, annos) +#define _Printf_format_string_ +#define _Use_decl_annotations_ +#elif _SAL_VERSION == 10 +// Microsoft didn't create a header mapping SAL 2.0 to 1.0. We do that here. +#define _In_ __in +#define _In_z_ __in_z +#define _In_opt_ __in_opt +#define _In_opt_z_ __in_z_opt +#define _Out_ __out +#define _Out_opt_ __out_opt +#define _Out_z_cap_(expr) __out_ecount_z(expr) +#define _Inout_ __inout +#define _Inout_z_cap_(expr) __inout_ecount_z(expr) +#define _Post_z_count_(expr) +#define _Ret_writes_z_(expr) __out_ecount_z(expr) +#define _Ret_writes_maybenull_z_(expr) __out_ecount_z_opt(expr) +#define _Ret_maybenull_z_ __out_z +#define _Check_return_ __checkReturn +#define _Must_inspect_result_ __checkReturn +#define _Success_(annos) __success(annos) +#define _Printf_format_string_ __format_string +#define _Use_decl_annotations_ + +// DriverSpecs.h was pretty much empty until the DDK that defined +// NTDDK_WIN6SP1 appeared. +#if defined(NTDDI_WIN6SP1) +#define _Group_(annos) __$drv_group(annos) +#define _When_(expr, annos) __drv_when(expr, annos) +#define _IRQL_requires_max_(irql) __drv_maxIRQL(irql) +#else +#define _Group_(annos) +#define _When_(expr, annos) +#define _IRQL_requires_max_(irql) +#define __drv_allocatesMem(kind) +#define __drv_freesMem(kind) +#endif + +#else +// Sal 2.0 path - everything is already defined. +#endif // _SAL_VERSION + +// Now define our own annotations +#if !defined(_SAL_VERSION) +#define _When_windrv_(annos) +#define _Ret_allocates_malloc_mem_opt_bytecap_(_Size) +#define _Ret_allocates_malloc_mem_opt_bytecount_(_Size) +#define _Ret_allocates_malloc_mem_opt_bytecap_post_bytecount_(_Cap,_Count) +#define _Ret_allocates_malloc_mem_opt_z_bytecount_(_Size) +#define _Ret_allocates_malloc_mem_opt_z_ +#define _In_frees_malloc_mem_opt_ +#elif _SAL_VERSION == 10 +#define _When_windrv_(annos) annos +#define _Ret_allocates_malloc_mem_opt_bytecap_(_Cap) __drv_allocatesMem("Memory") __checkReturn __post __byte_writableTo(_Cap) __exceptthat __maybenull +#define _Ret_allocates_malloc_mem_opt_bytecount_(_Count) __drv_allocatesMem("Memory") __checkReturn __post __byte_readableTo(_Count) __exceptthat __maybenull +#define _Ret_allocates_malloc_mem_opt_bytecap_post_bytecount_(_Cap,_Count) __drv_allocatesMem("Memory") __checkReturn __post __byte_writableTo(_Cap) __byte_readableTo(_Count) __exceptthat __maybenull +#define _Ret_allocates_malloc_mem_opt_z_bytecount_(_Count) __drv_allocatesMem("Memory") __checkReturn __post __byte_readableTo(_Count) __valid __nullterminated __exceptthat __maybenull +#define _Ret_allocates_malloc_mem_opt_z_ __drv_allocatesMem("Memory") __checkReturn __post __valid __nullterminated __exceptthat __maybenull +#define _In_frees_malloc_mem_opt_ __drv_freesMem("Memory") __in_opt __post __notvalid +#else +#define _When_windrv_(annos) annos +#define _Ret_allocates_malloc_mem_opt_bytecap_(_Cap) __drv_allocatesMem("Memory") _Must_inspect_result_ _Ret_opt_bytecap_(_Cap) +#define _Ret_allocates_malloc_mem_opt_bytecount_(_Count) __drv_allocatesMem("Memory") _Must_inspect_result_ _Ret_opt_bytecount_(_Count) +#define _Ret_allocates_malloc_mem_opt_bytecap_post_bytecount_(_Cap,_Count) __drv_allocatesMem("Memory") _Must_inspect_result_ _Ret_opt_bytecap_(_Cap) _Ret_opt_bytecount_(_Count) +#define _Ret_allocates_malloc_mem_opt_z_bytecount_(_Count) __drv_allocatesMem("Memory") _Must_inspect_result_ _Ret_opt_z_bytecount_(_Count) +#define _Ret_allocates_malloc_mem_opt_z_ __drv_allocatesMem("Memory") _Must_inspect_result_ _Ret_opt_z_ +#define _In_frees_malloc_mem_opt_ __drv_freesMem("Memory") _Pre_maybenull_ _Post_invalid_ +#endif // _SAL_VERSION + +// Best we can do for reallocate with simple annotations: assume old size was fully initialized. +#define _Ret_reallocates_malloc_mem_opt_newbytecap_oldbytecap_(_NewSize, _OldSize) _Ret_allocates_malloc_mem_opt_bytecap_post_bytecount_(_NewSize, _OldSize <= _NewSize ? _OldSize : _NewSize) +#define _Ret_reallocates_malloc_mem_opt_newbytecap_(_NewSize) _Ret_allocates_malloc_mem_opt_z_bytecount_(_NewSize) +#define _In_reallocates_malloc_mem_opt_oldptr_ _In_frees_malloc_mem_opt_ + +#endif // __KERNELSTUBSSAL_H__ diff --git a/open-vm-tools/modules/linux/shared/vmciKernelAPI1.h b/open-vm-tools/modules/linux/shared/vmciKernelAPI1.h index 10ce7912..dc528180 100644 --- a/open-vm-tools/modules/linux/shared/vmciKernelAPI1.h +++ b/open-vm-tools/modules/linux/shared/vmciKernelAPI1.h @@ -91,7 +91,11 @@ VMCIId vmci_get_context_id(void); #if defined(linux) && !defined(VMKERNEL) /* Returned value is a bool, 0 for false, 1 for true. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) +int vmci_is_context_owner(VMCIId contextID, kuid_t uid); +#else int vmci_is_context_owner(VMCIId contextID, uid_t uid); +#endif #else // !linux || VMKERNEL /* Returned value is a VMCI error code. */ int vmci_is_context_owner(VMCIId contextID, void *hostUser); @@ -140,9 +144,9 @@ ssize_t vmci_qpair_dequeue(VMCIQPair *qpair, void *buf, size_t bufSize, int mode); ssize_t vmci_qpair_peek(VMCIQPair *qpair, void *buf, size_t bufSize, int mode); -#if defined (SOLARIS) || (defined(__APPLE__) && !defined (VMX86_TOOLS)) || \ - (defined(__linux__) && defined(__KERNEL__)) || \ - (defined(_WIN32) && defined(WINNT_DDK)) +#if (defined(__APPLE__) && !defined (VMX86_TOOLS)) || \ + (defined(__linux__) && defined(__KERNEL__)) || \ + (defined(_WIN32) && defined(WINNT_DDK)) /* * Environments that support struct iovec */ diff --git a/open-vm-tools/modules/linux/shared/vmci_defs.h b/open-vm-tools/modules/linux/shared/vmci_defs.h index c0843359..74d314ff 100644 --- a/open-vm-tools/modules/linux/shared/vmci_defs.h +++ b/open-vm-tools/modules/linux/shared/vmci_defs.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2005-2012 VMware, Inc. All rights reserved. + * Copyright (C) 2005-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -30,6 +30,7 @@ #include "includeCheck.h" #include "vm_basic_types.h" +#include "vm_basic_defs.h" #include "vm_atomic.h" #include "vm_assert.h" diff --git a/open-vm-tools/modules/linux/shared/vmci_infrastructure.h b/open-vm-tools/modules/linux/shared/vmci_infrastructure.h index 73e37c3c..099b5268 100644 --- a/open-vm-tools/modules/linux/shared/vmci_infrastructure.h +++ b/open-vm-tools/modules/linux/shared/vmci_infrastructure.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006,2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -65,12 +65,14 @@ typedef struct VMCIDoorbellCptState { } VMCIDoorbellCptState; /* Used to determine what checkpoint state to get and set. */ -#define VMCI_NOTIFICATION_CPT_STATE 0x1 -#define VMCI_WELLKNOWN_CPT_STATE 0x2 -#define VMCI_DG_OUT_STATE 0x3 -#define VMCI_DG_IN_STATE 0x4 -#define VMCI_DG_IN_SIZE_STATE 0x5 -#define VMCI_DOORBELL_CPT_STATE 0x6 +#define VMCI_NOTIFICATION_CPT_STATE 0x1 +#define VMCI_WELLKNOWN_CPT_STATE 0x2 +#define VMCI_DG_OUT_STATE 0x3 +#define VMCI_DG_IN_STATE 0x4 +#define VMCI_DG_IN_SIZE_STATE 0x5 +#define VMCI_DOORBELL_CPT_STATE 0x6 +#define VMCI_DG_HYPERVISOR_SAVE_STATE_SIZE 0x7 +#define VMCI_DG_HYPERVISOR_SAVE_STATE 0x8 /* Used to control the VMCI device in the vmkernel */ #define VMCI_DEV_RESET 0x01 diff --git a/open-vm-tools/modules/linux/shared/vmci_iocontrols.h b/open-vm-tools/modules/linux/shared/vmci_iocontrols.h index e1355ec3..ce99894a 100644 --- a/open-vm-tools/modules/linux/shared/vmci_iocontrols.h +++ b/open-vm-tools/modules/linux/shared/vmci_iocontrols.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. + * Copyright (C) 2007-2013 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -154,7 +154,7 @@ VMCIPtrToVA64(void const *ptr) // IN #define VMCI_SOCKETS_MAKE_VERSION(_p) \ ((((_p)[0] & 0xFF) << 24) | (((_p)[1] & 0xFF) << 16) | ((_p)[2])) -#if defined(__linux__) || defined(SOLARIS) || defined(VMKERNEL) +#if defined(__linux__) || defined(VMKERNEL) /* * Linux defines _IO* macros, but the core kernel code ignore the encoded * ioctl value. It is up to individual drivers to decode the value (for @@ -317,12 +317,12 @@ enum IOCTLCmd_VMCI { * The size of this must match the size of VSockIoctlPrivSyms in * modules/vsock/common/vsockIoctl.h. */ -#include "vmware_pack_begin.h" +#pragma pack(push, 1) struct IOCTLCmd_VMCIMacOS_PrivSyms { char data[344]; -} -#include "vmware_pack_end.h" -; +}; +#pragma pack(pop) + enum IOCTLCmd_VMCIMacOS { IOCTLCMD_I(SOCKETS_SET_SYMBOLS, struct IOCTLCmd_VMCIMacOS_PrivSyms), IOCTLCMD_O(SOCKETS_VERSION, unsigned int), diff --git a/open-vm-tools/modules/linux/shared/vmci_kernel_if.h b/open-vm-tools/modules/linux/shared/vmci_kernel_if.h index 29c609df..ef8a5520 100644 --- a/open-vm-tools/modules/linux/shared/vmci_kernel_if.h +++ b/open-vm-tools/modules/linux/shared/vmci_kernel_if.h @@ -28,7 +28,7 @@ #define _VMCI_KERNEL_IF_H_ #if !defined(linux) && !defined(_WIN32) && !defined(__APPLE__) && \ - !defined(VMKERNEL) && !defined(SOLARIS) + !defined(VMKERNEL) # error "Platform not supported." #endif @@ -55,21 +55,12 @@ #ifdef VMKERNEL # include "splock.h" +# include "splock_customRanks.h" # include "semaphore_ext.h" # include "vmkapi.h" # include "world_dist.h" #endif -#ifdef SOLARIS -# include <sys/ddi.h> -# include <sys/kmem.h> -# include <sys/mutex.h> -# include <sys/poll.h> -# include <sys/semaphore.h> -# include <sys/sunddi.h> -# include <sys/types.h> -#endif - #include "vm_basic_types.h" #include "vmci_defs.h" @@ -110,7 +101,11 @@ typedef wait_queue_head_t VMCIEvent; typedef struct semaphore VMCIMutex; typedef PPN *VMCIPpnList; /* List of PPNs in produce/consume queue. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + typedef kuid_t VMCIHostUser; +#else typedef uid_t VMCIHostUser; +#endif typedef VA64 VMCIQPGuestMem; #elif defined(__APPLE__) typedef IOLock *VMCILock; @@ -132,14 +127,6 @@ typedef PMDL VMCIPpnList; /* MDL to map the produce/consume queue. */ typedef PSID VMCIHostUser; typedef VA64 *VMCIQPGuestMem; -#elif defined(SOLARIS) - typedef kmutex_t VMCILock; - typedef unsigned long VMCILockFlags; - typedef ksema_t VMCIEvent; - typedef kmutex_t VMCIMutex; - typedef PPN *VMCIPpnList; /* List of PPNs in produce/consume queue. */ - typedef uid_t VMCIHostUser; - typedef VA64 VMCIQPGuestMem; #endif // VMKERNEL /* Callback needed for correctly waiting on events. */ @@ -205,11 +192,6 @@ typedef struct VMCIHost { KEVENT *callEvent; /* Ptr to userlevel event used when signalling * new pending guestcalls in kernel. */ -#elif defined(SOLARIS) - struct pollhead pollhead; /* Per datagram handle pollhead structure to - * be treated as a black-box. None of its - * fields should be referenced. - */ #endif } VMCIHost; @@ -223,9 +205,6 @@ typedef struct VMCIHost { #elif defined(_WIN32) typedef PUCHAR VMCIIoPort; typedef int VMCIIoHandle; -#elif defined(SOLARIS) - typedef uint8_t * VMCIIoPort; - typedef ddi_acc_handle_t VMCIIoHandle; #elif defined(__APPLE__) typedef unsigned short int VMCIIoPort; typedef void *VMCIIoHandle; @@ -260,6 +239,8 @@ void VMCIHost_SetInactiveHnd(VMCIHost *hostContext, uintptr_t eventHnd); uint32 VMCIHost_NumHnds(VMCIHost *hostContext); uintptr_t VMCIHost_GetActiveHnd(VMCIHost *hostContext); void VMCIHost_SignalBitmap(VMCIHost *hostContext); +void VMCIHost_SignalBitmapAlways(VMCIHost *hostContext); +void VMCIHost_SignalCallAlways(VMCIHost *hostContext); #endif #if defined(_WIN32) @@ -296,7 +277,7 @@ Bool VMCI_WaitOnEventInterruptible(VMCIEvent *event, #endif #if !defined(VMKERNEL) && (defined(__linux__) || defined(_WIN32) || \ - defined(__APPLE__) || defined(SOLARIS)) + defined(__APPLE__)) int VMCI_CopyFromUser(void *dst, VA64 src, size_t len); #endif @@ -309,16 +290,16 @@ void VMCIMutex_Destroy(VMCIMutex *mutex); void VMCIMutex_Acquire(VMCIMutex *mutex); void VMCIMutex_Release(VMCIMutex *mutex); -#if defined(SOLARIS) || defined(_WIN32) || defined(__APPLE__) +#if defined(_WIN32) || defined(__APPLE__) int VMCIKernelIf_Init(void); void VMCIKernelIf_Exit(void); #if defined(_WIN32) void VMCIKernelIf_DrainDelayedWork(void); #endif // _WIN32 -#endif // SOLARIS || _WIN32 || __APPLE__ +#endif // _WIN32 || __APPLE__ -#if !defined(VMKERNEL) && (defined(__linux__) || defined(_WIN32) || \ - defined(SOLARIS) || defined(__APPLE__)) +#if !defined(VMKERNEL) && \ + (defined(__linux__) || defined(_WIN32) || defined(__APPLE__)) void *VMCI_AllocQueue(uint64 size, uint32 flags); void VMCI_FreeQueue(void *q, uint64 size); typedef struct PPNSet { @@ -393,12 +374,12 @@ typedef uint32 VMCIGuestMemID; void VMCI_LockQueueHeader(struct VMCIQueue *queue); void VMCI_UnlockQueueHeader(struct VMCIQueue *queue); #else -# define VMCI_LockQueueHeader(_q) ASSERT_NOT_IMPLEMENTED(FALSE) -# define VMCI_UnlockQueueHeader(_q) ASSERT_NOT_IMPLEMENTED(FALSE) +# define VMCI_LockQueueHeader(_q) NOT_IMPLEMENTED() +# define VMCI_UnlockQueueHeader(_q) NOT_IMPLEMENTED() #endif #if (!defined(VMKERNEL) && defined(__linux__)) || defined(_WIN32) || \ - defined(__APPLE__) || defined(SOLARIS) + defined(__APPLE__) int VMCIHost_GetUserMemory(VA64 produceUVA, VA64 consumeUVA, struct VMCIQueue *produceQ, struct VMCIQueue *consumeQ); @@ -406,7 +387,7 @@ typedef uint32 VMCIGuestMemID; struct VMCIQueue *consumeQ); #else # define VMCIHost_GetUserMemory(_puva, _cuva, _pq, _cq) VMCI_ERROR_UNAVAILABLE -# define VMCIHost_ReleaseUserMemory(_pq, _cq) ASSERT_NOT_IMPLEMENTED(FALSE) +# define VMCIHost_ReleaseUserMemory(_pq, _cq) NOT_IMPLEMENTED() #endif #if defined(_WIN32) diff --git a/open-vm-tools/modules/linux/vmblock/Makefile b/open-vm-tools/modules/linux/vmblock/Makefile index 36529cd6..21e5dc16 100644 --- a/open-vm-tools/modules/linux/vmblock/Makefile +++ b/open-vm-tools/modules/linux/vmblock/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/make -f ########################################################## -# Copyright (C) 1998 VMware, Inc. All rights reserved. +# Copyright (C) 1998-2015 VMware, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmci/Makefile b/open-vm-tools/modules/linux/vmci/Makefile index 3ff28c4b..05aa915c 100644 --- a/open-vm-tools/modules/linux/vmci/Makefile +++ b/open-vm-tools/modules/linux/vmci/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/make -f ########################################################## -# Copyright (C) 1998 VMware, Inc. All rights reserved. +# Copyright (C) 1998-2015 VMware, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmci/Makefile.kernel b/open-vm-tools/modules/linux/vmci/Makefile.kernel index ba343eea..8e6e7d0b 100644 --- a/open-vm-tools/modules/linux/vmci/Makefile.kernel +++ b/open-vm-tools/modules/linux/vmci/Makefile.kernel @@ -1,6 +1,6 @@ #!/usr/bin/make -f ########################################################## -# Copyright (C) 2007 VMware, Inc. All rights reserved. +# Copyright (C) 2007,2014 VMware, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -55,7 +55,7 @@ endif # # If this build generated a Module.symvers, copy it to a public place where -# the VMCI Sockets build will be able to find it. +# the vSockets build will be able to find it. # postbuild:: ifeq ($(call vm_check_file,$(SRCROOT)/Module.symvers), yes) diff --git a/open-vm-tools/modules/linux/vmci/common/vmciContext.c b/open-vm-tools/modules/linux/vmci/common/vmciContext.c index 513e93d4..5ebd28ab 100644 --- a/open-vm-tools/modules/linux/vmci/common/vmciContext.c +++ b/open-vm-tools/modules/linux/vmci/common/vmciContext.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006-2012 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2012,2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -577,8 +577,9 @@ VMCIContext_PendingDatagrams(VMCIId cid, // IN */ int -VMCIContext_EnqueueDatagram(VMCIId cid, // IN: Target VM - VMCIDatagram *dg) // IN: +VMCIContext_EnqueueDatagram(VMCIId cid, // IN: Target VM + VMCIDatagram *dg, // IN: + Bool notify) // IN: { DatagramQueueEntry *dqEntry; VMCIContext *context; @@ -648,8 +649,12 @@ VMCIContext_EnqueueDatagram(VMCIId cid, // IN: Target VM VMCIList_Insert(&dqEntry->listItem, &context->datagramQueue); context->pendingDatagrams++; context->datagramQueueSize += vmciDgSize; - VMCIContextSignalNotify(context); - VMCIHost_SignalCall(&context->hostContext); + + if (notify) { + VMCIContextSignalNotify(context); + VMCIHost_SignalCall(&context->hostContext); + } + VMCI_ReleaseLock(&context->lock, flags); VMCIContext_Release(context); @@ -809,7 +814,7 @@ VMCIContext_Release(VMCIContext *context) // IN { uint32 refCount; ASSERT(context); - refCount = Atomic_FetchAndDec(&context->refCount); + refCount = Atomic_ReadDec32(&context->refCount); if (refCount == 1) { VMCIContextFreeContext(context); } @@ -1489,6 +1494,143 @@ VMCIContextFireNotification(VMCIId contextID, // IN return VMCI_SUCCESS; } +/* + *---------------------------------------------------------------------- + * + * VMCIContextDgHypervisorSaveStateSize -- + * + * Calculate the size for the hypervisor datagram checkpoint + * save data. + * + * The format is as follows: + * + * uint32 count - number of entries + * uint32 size - size of first entry + * char bytes[] - contents of first entry + * uint32 size - size of second entry + * char bytes[] - contents of second entry + * ... + * + * Results: + * VMCI_SUCCESS on success, error code otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +VMCIContextDgHypervisorSaveStateSize(VMCIContext *context, // IN + uint32 *bufSize, // IN/OUT + char **cptBufPtr) // UNUSED +{ + uint32 total; + VMCIListItem *iter; + + *bufSize = total = 0; + + VMCIList_Scan(iter, &context->datagramQueue) { + DatagramQueueEntry *dqEntry = + VMCIList_Entry(iter, DatagramQueueEntry, listItem); + + if (dqEntry->dg->src.context == VMCI_HYPERVISOR_CONTEXT_ID) { + /* Size of the datagram followed by the contents of the datagram. */ + total += sizeof(uint32) + dqEntry->dgSize; + } + } + + if (total > 0) { + /* Don't forget the datagram count. */ + *bufSize = total + sizeof(uint32); + } + + return VMCI_SUCCESS; +} + + +/* + *---------------------------------------------------------------------- + * + * VMCIContextDgHypervisorSaveState -- + * + * Get the hypervisor datagram checkpoint save data. + * + * Results: + * VMCI_SUCCESS on success, error code otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +VMCIContextDgHypervisorSaveState(VMCIContext *context, // IN + uint32 *bufSize, // IN/OUT + char **cptBufPtr) // OUT +{ + uint8 *p; + uint32 total; + uint32 count; + VMCIListItem *iter; + + /* Need at least the count field and the size of one entry. */ + if (*bufSize < sizeof(uint32) * 2) { + return VMCI_ERROR_INVALID_ARGS; + } + + p = VMCI_AllocKernelMem(*bufSize, VMCI_MEMORY_NORMAL); + if (p == NULL) { + return VMCI_ERROR_NO_MEM; + } + + *cptBufPtr = p; + + /* Leave space for the datagram count at the start. */ + total = sizeof(uint32); + p += sizeof(uint32); + + count = 0; + VMCIList_Scan(iter, &context->datagramQueue) { + DatagramQueueEntry *dqEntry = + VMCIList_Entry(iter, DatagramQueueEntry, listItem); + + if (dqEntry->dg->src.context == VMCI_HYPERVISOR_CONTEXT_ID) { + + /* + * VMX might have capped the amount of space we can use to checkpoint + * hypervisor datagrams. Respect that here. Those that are not written + * to the buffer will get dropped. + */ + + if (total + sizeof(uint32) + dqEntry->dgSize > *bufSize) { + break; + } + + total += sizeof(uint32) + dqEntry->dgSize; + + /* + * Write in the size of the datagram followed by the contents of the + * datagram itself. + */ + + *(uint32 *)p = dqEntry->dgSize; + p += sizeof(uint32); + + memcpy(p, dqEntry->dg, dqEntry->dgSize); + p += dqEntry->dgSize; + + count++; + } + } + + /* Now rollback and write the count at the start of the block. */ + *(uint32 *)(*cptBufPtr) = count; + + return VMCI_SUCCESS; +} + /* *---------------------------------------------------------------------- @@ -1546,6 +1688,12 @@ VMCIContext_GetCheckpointState(VMCIId contextID, // IN: ASSERT(context->doorbellArray); array = context->doorbellArray; getContextID = FALSE; + } else if (cptType == VMCI_DG_HYPERVISOR_SAVE_STATE_SIZE) { + result = VMCIContextDgHypervisorSaveStateSize(context, bufSize, cptBufPtr); + goto release; + } else if (cptType == VMCI_DG_HYPERVISOR_SAVE_STATE) { + result = VMCIContextDgHypervisorSaveState(context, bufSize, cptBufPtr); + goto release; } else { VMCI_DEBUG_LOG(4, (LGPFX"Invalid cpt state (type=%d).\n", cptType)); result = VMCI_ERROR_INVALID_ARGS; @@ -1589,10 +1737,9 @@ VMCIContext_GetCheckpointState(VMCIId contextID, // IN: } result = VMCI_SUCCESS; - release: +release: VMCI_ReleaseLock(&context->lock, flags); VMCIContext_Release(context); - return result; } @@ -2081,7 +2228,7 @@ VMCIContext_SignalPendingDoorbells(VMCIId contextID) VMCI_ReleaseLock(&context->lock, flags); if (pending) { - VMCIHost_SignalBitmap(&context->hostContext); + VMCIHost_SignalBitmapAlways(&context->hostContext); } VMCIContext_Release(context); @@ -2125,7 +2272,7 @@ VMCIContext_SignalPendingDatagrams(VMCIId contextID) VMCI_ReleaseLock(&context->lock, flags); if (pending) { - VMCIHost_SignalCall(&context->hostContext); + VMCIHost_SignalCallAlways(&context->hostContext); } VMCIContext_Release(context); @@ -2207,7 +2354,7 @@ VMCI_EXPORT_SYMBOL(vmci_is_context_owner) #if defined(linux) && !defined(VMKERNEL) int vmci_is_context_owner(VMCIId contextID, // IN - uid_t uid) // IN + VMCIHostUser uid) // IN { int isOwner = 0; @@ -2215,7 +2362,7 @@ vmci_is_context_owner(VMCIId contextID, // IN VMCIContext *context = VMCIContext_Get(contextID); if (context) { if (context->validUser) { - if (VMCIHost_CompareUser((VMCIHostUser *)&uid, + if (VMCIHost_CompareUser(&uid, &context->user) == VMCI_SUCCESS) { isOwner = 1; } diff --git a/open-vm-tools/modules/linux/vmci/common/vmciContext.h b/open-vm-tools/modules/linux/vmci/common/vmciContext.h index de0201ef..07fc3658 100644 --- a/open-vm-tools/modules/linux/vmci/common/vmciContext.h +++ b/open-vm-tools/modules/linux/vmci/common/vmciContext.h @@ -68,7 +68,7 @@ void VMCIContext_SetId(VMCIContext *context, VMCIId cid); #endif Bool VMCIContext_SupportsHostQP(VMCIContext *context); void VMCIContext_ReleaseContext(VMCIContext *context); -int VMCIContext_EnqueueDatagram(VMCIId cid, VMCIDatagram *dg); +int VMCIContext_EnqueueDatagram(VMCIId cid, VMCIDatagram *dg, Bool notify); int VMCIContext_DequeueDatagram(VMCIContext *context, size_t *maxSize, VMCIDatagram **dg); int VMCIContext_PendingDatagrams(VMCIId cid, uint32 *pending); diff --git a/open-vm-tools/modules/linux/vmci/common/vmciDatagram.c b/open-vm-tools/modules/linux/vmci/common/vmciDatagram.c index 2f17a182..7fd7674a 100644 --- a/open-vm-tools/modules/linux/vmci/common/vmciDatagram.c +++ b/open-vm-tools/modules/linux/vmci/common/vmciDatagram.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006-2011 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2011,2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -622,7 +622,7 @@ VMCIDatagramDispatchAsHost(VMCIId contextID, // IN: VMCI_CanScheduleDelayedWork())) { VMCIDelayedDatagramInfo *dgInfo; - if (Atomic_FetchAndAdd(&delayedDGHostQueueSize, 1) == + if (Atomic_ReadInc32(&delayedDGHostQueueSize) == VMCI_MAX_DELAYED_DG_HOST_QUEUE_SIZE) { Atomic_Dec(&delayedDGHostQueueSize); VMCIResource_Release(resource); @@ -692,7 +692,7 @@ VMCIDatagramDispatchAsHost(VMCIId contextID, // IN: return VMCI_ERROR_NO_MEM; } memcpy(newDG, dg, dgSize); - retval = VMCIContext_EnqueueDatagram(dg->dst.context, newDG); + retval = VMCIContext_EnqueueDatagram(dg->dst.context, newDG, TRUE); if (retval < VMCI_SUCCESS) { VMCI_FreeKernelMem(newDG, dgSize); VMCI_DEBUG_LOG(4, (LGPFX"Enqueue failed\n")); @@ -844,6 +844,12 @@ VMCIDatagram_InvokeGuestHandler(VMCIDatagram *dg) // IN ASSERT(dg); + if (dg->payloadSize > VMCI_MAX_DG_PAYLOAD_SIZE) { + VMCI_DEBUG_LOG(4, (LGPFX"Payload (size=%"FMT64"u bytes) too large to " + "deliver.\n", dg->payloadSize)); + return VMCI_ERROR_PAYLOAD_TOO_LARGE; + } + resource = VMCIResource_Get(dg->dst, VMCI_RESOURCE_TYPE_DATAGRAM); if (NULL == resource) { VMCI_DEBUG_LOG(4, (LGPFX"destination (handle=0x%x:0x%x) doesn't exist.\n", diff --git a/open-vm-tools/modules/linux/vmci/common/vmciDoorbell.c b/open-vm-tools/modules/linux/vmci/common/vmciDoorbell.c index 74053e15..5a3fbfd5 100644 --- a/open-vm-tools/modules/linux/vmci/common/vmciDoorbell.c +++ b/open-vm-tools/modules/linux/vmci/common/vmciDoorbell.c @@ -41,7 +41,7 @@ #define LGPFX "VMCIDoorbell: " -#if !defined(SOLARIS) && !defined(__APPLE__) +#if !defined(__APPLE__) #define VMCI_DOORBELL_INDEX_TABLE_SIZE 64 #define VMCI_DOORBELL_HASH(_idx) \ @@ -1160,7 +1160,7 @@ VMCI_ScanNotificationBitmap(uint8 *bitmap) } -#else // SOLARIS) || __APPLE__ +#else // __APPLE__ /* *----------------------------------------------------------------------------- @@ -1238,4 +1238,4 @@ VMCIDoorbell_Exit(void) { } -#endif // SOLARIS) || __APPLE__ +#endif // __APPLE__ diff --git a/open-vm-tools/modules/linux/vmci/common/vmciDriver.c b/open-vm-tools/modules/linux/vmci/common/vmciDriver.c index bd0b4964..4a379585 100644 --- a/open-vm-tools/modules/linux/vmci/common/vmciDriver.c +++ b/open-vm-tools/modules/linux/vmci/common/vmciDriver.c @@ -124,7 +124,7 @@ VMCI_HostCleanup(void) } -#if defined(__APPLE__) || defined(SOLARIS) || defined(VMKERNEL) +#if defined(__APPLE__) || defined(VMKERNEL) /* Windows has its own implementation of this, and Linux doesn't need one. */ /* *---------------------------------------------------------------------- @@ -189,7 +189,7 @@ void vmci_device_release(void *deviceRegistration) // UNUSED { } -#endif // __APPLE__ || SOLARIS || VMKERNEL +#endif // __APPLE__ || VMKERNEL /* diff --git a/open-vm-tools/modules/linux/vmci/common/vmciQPair.c b/open-vm-tools/modules/linux/vmci/common/vmciQPair.c index dbc64922..7a021278 100644 --- a/open-vm-tools/modules/linux/vmci/common/vmciQPair.c +++ b/open-vm-tools/modules/linux/vmci/common/vmciQPair.c @@ -1234,9 +1234,9 @@ vmci_qpair_peek(VMCIQPair *qpair, // IN } -#if defined (SOLARIS) || (defined(__APPLE__) && !defined (VMX86_TOOLS)) || \ - (defined(__linux__) && defined(__KERNEL__)) || \ - (defined(_WIN32) && defined(WINNT_DDK)) +#if (defined(__APPLE__) && !defined (VMX86_TOOLS)) || \ + (defined(__linux__) && defined(__KERNEL__)) || \ + (defined(_WIN32) && defined(WINNT_DDK)) /* *----------------------------------------------------------------------------- diff --git a/open-vm-tools/modules/linux/vmci/common/vmciRoute.c b/open-vm-tools/modules/linux/vmci/common/vmciRoute.c index b73d3867..cc98b93c 100644 --- a/open-vm-tools/modules/linux/vmci/common/vmciRoute.c +++ b/open-vm-tools/modules/linux/vmci/common/vmciRoute.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2011-2012 VMware, Inc. All rights reserved. + * Copyright (C) 2011-2012,2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -114,17 +114,6 @@ VMCI_Route(VMCIHandle *src, // IN/OUT return VMCI_ERROR_INVALID_ARGS; } - /* - * If the client passed the ANON source handle then respect it (both - * context and resource are invalid). However, if they passed only - * an invalid context, then they probably mean ANY, in which case we - * should set the real context here before passing it down. - */ - - if (VMCI_INVALID_ID == src->context && VMCI_INVALID_ID != src->resource) { - src->context = vmci_get_context_id(); - } - /* Send from local client down to the hypervisor. */ *route = VMCI_ROUTE_AS_GUEST; return VMCI_SUCCESS; diff --git a/open-vm-tools/modules/linux/vmci/linux/driver.c b/open-vm-tools/modules/linux/vmci/linux/driver.c index c9519ca2..58e23c2a 100644 --- a/open-vm-tools/modules/linux/vmci/linux/driver.c +++ b/open-vm-tools/modules/linux/vmci/linux/driver.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2011 VMware, Inc. All rights reserved. + * Copyright (C) 2011-2013 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -1801,8 +1801,9 @@ vmci_probe_device(struct pci_dev *pdev, // IN: vmci PCI device */ if (capabilities & VMCI_CAPS_NOTIFICATIONS) { capabilities = VMCI_CAPS_DATAGRAM; - notification_bitmap = pci_alloc_consistent(pdev, PAGE_SIZE, - ¬ification_base); + notification_bitmap = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, + ¬ification_base, + GFP_KERNEL); if (notification_bitmap == NULL) { printk(KERN_ERR "VMCI device unable to allocate notification bitmap.\n"); } else { @@ -1948,8 +1949,8 @@ vmci_probe_device(struct pci_dev *pdev, // IN: vmci PCI device compat_mutex_unlock(&vmci_dev.lock); release: if (notification_bitmap) { - pci_free_consistent(pdev, PAGE_SIZE, notification_bitmap, - notification_base); + dma_free_coherent(&pdev->dev, PAGE_SIZE, notification_bitmap, + notification_base); notification_bitmap = NULL; } release_region(ioaddr, ioaddr_size); diff --git a/open-vm-tools/modules/linux/vmci/linux/vmciKernelIf.c b/open-vm-tools/modules/linux/vmci/linux/vmciKernelIf.c index 4e72c33f..8b1788fa 100644 --- a/open-vm-tools/modules/linux/vmci/linux/vmciKernelIf.c +++ b/open-vm-tools/modules/linux/vmci/linux/vmciKernelIf.c @@ -428,11 +428,13 @@ int VMCIHost_CompareUser(VMCIHostUser *user1, return VMCI_ERROR_INVALID_ARGS; } - if (*user1 == *user2) { - return VMCI_SUCCESS; - } else { - return VMCI_ERROR_GENERIC; - } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) +# define vmw_uid_eq(a, b) uid_eq(a, b) +#else +# define vmw_uid_eq(a, b) ((a) == (b)) +#endif + + return vmw_uid_eq(*user1, *user2) ? VMCI_SUCCESS : VMCI_ERROR_GENERIC; } @@ -930,8 +932,8 @@ VMCI_AllocQueue(uint64 size, // IN: size of queue (not including header) for (i = 0; i < numPages; i++) { queue->kernelIf->u.g.vas[i] = - pci_alloc_consistent(vmci_pdev, PAGE_SIZE, - &queue->kernelIf->u.g.pas[i]); + dma_alloc_coherent(&vmci_pdev->dev, PAGE_SIZE, + &queue->kernelIf->u.g.pas[i], GFP_KERNEL); if (!queue->kernelIf->u.g.vas[i]) { VMCI_FreeQueue(queue, i * PAGE_SIZE); /* Size excl. the header. */ return NULL; @@ -973,9 +975,9 @@ VMCI_FreeQueue(void *q, // IN: /* Given size does not include header, so add in a page here. */ for (i = 0; i < CEILING(size, PAGE_SIZE) + 1; i++) { - pci_free_consistent(vmci_pdev, PAGE_SIZE, - queue->kernelIf->u.g.vas[i], - queue->kernelIf->u.g.pas[i]); + dma_free_coherent(&vmci_pdev->dev, PAGE_SIZE, + queue->kernelIf->u.g.vas[i], + queue->kernelIf->u.g.pas[i]); } vfree(queue); } diff --git a/open-vm-tools/modules/linux/vmci/linux/vmci_version.h b/open-vm-tools/modules/linux/vmci/linux/vmci_version.h index 497a9175..ee56876d 100644 --- a/open-vm-tools/modules/linux/vmci/linux/vmci_version.h +++ b/open-vm-tools/modules/linux/vmci/linux/vmci_version.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2007-2013 VMware, Inc. All rights reserved. + * Copyright (C) 2007-2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -25,8 +25,8 @@ #ifndef _VMCI_VERSION_H_ #define _VMCI_VERSION_H_ -#define VMCI_DRIVER_VERSION 9.6.0.0 -#define VMCI_DRIVER_VERSION_COMMAS 9,6,0,0 -#define VMCI_DRIVER_VERSION_STRING "9.6.0.0" +#define VMCI_DRIVER_VERSION 9.7.1.0 +#define VMCI_DRIVER_VERSION_COMMAS 9,7,1,0 +#define VMCI_DRIVER_VERSION_STRING "9.7.1.0" #endif /* _VMCI_VERSION_H_ */ diff --git a/open-vm-tools/modules/linux/vmci/shared/pgtbl.h b/open-vm-tools/modules/linux/vmci/shared/pgtbl.h index 461ef483..ed1ae8a1 100644 --- a/open-vm-tools/modules/linux/vmci/shared/pgtbl.h +++ b/open-vm-tools/modules/linux/vmci/shared/pgtbl.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2002 VMware, Inc. All rights reserved. + * Copyright (C) 2002,2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -37,8 +37,8 @@ * holding a spinlock --hpreg * * Results: - * INVALID_MPN64 on failure - * mpn on success + * INVALID_MPN on failure + * mpn on success * * Side effects: * None @@ -51,11 +51,11 @@ PgtblPte2MPN(pte_t *pte) // IN { MPN64 mpn; if (pte_present(*pte) == 0) { - return INVALID_MPN64; + return INVALID_MPN; } mpn = pte_pfn(*pte); - if (mpn >= INVALID_MPN64) { - return INVALID_MPN64; + if (mpn >= INVALID_MPN) { + return INVALID_MPN; } return mpn; } @@ -176,8 +176,8 @@ PgtblVa2PTELocked(struct mm_struct *mm, // IN: Mm structure of a process * must be held, so this function is not allowed to schedule() --hpreg * * Results: - * INVALID_MPN64 on failure - * mpn on success + * INVALID_MPN on failure + * mpn on success * * Side effects: * None @@ -197,7 +197,7 @@ PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process pte_unmap(pte); return mpn; } - return INVALID_MPN64; + return INVALID_MPN; } @@ -213,8 +213,8 @@ PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process * must be held, so this function is not allowed to schedule() --hpreg * * Results: - * INVALID_MPN64 on failure - * mpn on success + * INVALID_MPN on failure + * mpn on success * * Side effects: * None @@ -234,7 +234,7 @@ PgtblKVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a caller pte_unmap(pte); return mpn; } - return INVALID_MPN64; + return INVALID_MPN; } #endif diff --git a/open-vm-tools/modules/linux/vmci/shared/vmciQueue.h b/open-vm-tools/modules/linux/vmci/shared/vmciQueue.h index 11225e7c..000784f6 100644 --- a/open-vm-tools/modules/linux/vmci/shared/vmciQueue.h +++ b/open-vm-tools/modules/linux/vmci/shared/vmciQueue.h @@ -33,7 +33,7 @@ #define INCLUDE_ALLOW_VMKERNEL #include "includeCheck.h" -#if defined(SOLARIS) || defined(__APPLE__) +#if defined(__APPLE__) # include <sys/uio.h> #endif @@ -150,10 +150,10 @@ int VMCIMemcpyFromQueueLocal(void *dest, size_t destOffset, const VMCIQueue *que uint64 queueOffset, size_t size, BUF_TYPE bufType, Bool canBlock); -#if defined VMKERNEL || defined (SOLARIS) || \ +#if defined VMKERNEL || \ (defined(__APPLE__) && !defined (VMX86_TOOLS)) || \ (defined(__linux__) && defined(__KERNEL__)) || \ - (defined(_WIN32) && defined(WINNT_DDK)) + (defined(_WIN32) && defined(WINNT_DDK)) int VMCIMemcpyToQueueV(VMCIQueue *queue, uint64 queueOffset, const void *src, size_t srcOffset, size_t size, BUF_TYPE bufType, Bool canBlock); diff --git a/open-vm-tools/modules/linux/vmci/shared/vmci_handle_array.h b/open-vm-tools/modules/linux/vmci/shared/vmci_handle_array.h index b31ab823..13a46f5d 100644 --- a/open-vm-tools/modules/linux/vmci/shared/vmci_handle_array.h +++ b/open-vm-tools/modules/linux/vmci/shared/vmci_handle_array.h @@ -40,13 +40,6 @@ #include "vm_libc.h" #endif // VMKERNEL -#ifdef SOLARIS -#include <sys/ddi.h> -#include <sys/kmem.h> -#include <sys/types.h> -#include <sys/systm.h> -#endif - #define VMCI_HANDLE_ARRAY_DEFAULT_SIZE 4 typedef struct VMCIHandleArray { diff --git a/open-vm-tools/modules/linux/vmci/shared/vmci_page_channel.h b/open-vm-tools/modules/linux/vmci/shared/vmci_page_channel.h deleted file mode 100644 index 22e94069..00000000 --- a/open-vm-tools/modules/linux/vmci/shared/vmci_page_channel.h +++ /dev/null @@ -1,733 +0,0 @@ -/********************************************************* - * Copyright (C) 2011-2012 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * vmci_page_channel.h - * - * vPageChannel structure and functions. - */ - -#ifndef _VMCI_PAGE_CHANNEL_H_ -#define _VMCI_PAGE_CHANNEL_H_ - -#define INCLUDE_ALLOW_MODULE -#define INCLUDE_ALLOW_VMK_MODULE -#define INCLUDE_ALLOW_VMKERNEL -#include "includeCheck.h" - -#include "vmci_defs.h" -#include "vmci_call_defs.h" - -/** \cond PRIVATE */ -#define VPAGECHANNEL_MAX_TX_BUF_SIZE (1 << 14) -#define VPAGECHANNEL_MAX_PAGES_PER_TX_BUFFER \ - (VPAGECHANNEL_MAX_TX_BUF_SIZE / PAGE_SIZE + 1) -/** \endcond */ - -/** - * \brief Get a pointer to the elements in a packet. - * - * Returns a pointer to the elements at the end of a page channel packet. - * - * \see VPageChannelElem - * \see VPageChannelPacket - */ - -#define VPAGECHANNEL_PACKET_ELEMS(packet) \ - (VPageChannelElem *)((char *)(packet) + \ - sizeof(VPageChannelPacket) + \ - packet->msgLen) - -/** - * \brief Get a pointer to the message in a packet. - * - * Returns a pointer to the message embedded in a page channel packet. - * - * \see VPageChannelPacket - */ - -#define VPAGECHANNEL_PACKET_MESSAGE(packet) \ - (char *)((char *)(packet) + sizeof(VPageChannelPacket)) - -/** - * \brief Notify client directly, and do not read packets. - * - * This flag indicates that the channel should invoke the client's receive - * callback directly when any packets are available. If not specified, then - * when a notification is received, packets are read from the channel and the - * callback invoked for each one separately. - * - * \note Not applicable to VMKernel. - * - * \see VPageChannel_CreateInVM() - */ - -#define VPAGECHANNEL_FLAGS_NOTIFY_ONLY 0x1 - -/** - * \brief Invoke client's receive callback in delayed context. - * - * This flag indicates that all callbacks run in a delayed context, and the - * caller and callback are allowed to block. If not specified, then callbacks - * run in interrupt context and the channel will not block, and the caller - * is not allowed to block. - * - * \note Not applicable to VMKernel. - * - * \see VPageChannel_CreateInVM() - */ - -#define VPAGECHANNEL_FLAGS_RECV_DELAYED 0x2 - -/** - * \brief Send from an atomic context. - * - * This flag indicates that the client wishes to call Send() from an atomic - * context and that the channel should not block. If the channel is not - * allowed to block, then the channel's pages are permanently mapped and - * pinned. Note that this will limit the total size of the channel to - * VMCI_MAX_PINNED_QP_MEMORY. - * - * \note Not applicable to VMKernel. - * - * \see VPageChannel_CreateInVM() - */ - -#define VPAGECHANNEL_FLAGS_SEND_WHILE_ATOMIC 0x4 - -/** - * \brief An element describing a data range. - * - * Describes a data range, starting at a base address and for a given - * length, i.e., an element of a scatter-gather list. Indicates physical - * address for the guest and machine address for hypervisor. Can be passed - * via packets or buffers. - * - * \note Structure is packed. - * - * \see VPageChannelPacket - * \see VPageChanelBuffer - */ - -typedef -#include "vmware_pack_begin.h" -struct VPageChannelElem { - union { - /** \brief Physical address for guest. */ - uint64 pa; - - /** \brief Machine address for hypervisor. */ - uint64 ma; - }; - - /** \brief Length of range. */ - uint32 le; -} -#include "vmware_pack_end.h" -VPageChannelElem; - -/** - * \brief Page channel page types. - * - * The various types of page channel packets. - * - * \see VPageChannelPacket - */ -typedef enum { - /** \brief Data packet. */ - VPCPacket_Data = 1, - - /** \brief Completion notification, from hypervisor to guest. */ - VPCPacket_Completion_Notify, - - /** \cond PRIVATE */ - /** \brief Connect to hypervisor, internal. */ - VPCPacket_GuestConnect, - - /** \brief Complete connection handshake, internal. */ - VPCPacket_HyperConnect, - - /** \brief Request buffers, internal. */ - VPCPacket_RequestBuffer, - - /** \brief Set buffers, internal. */ - VPCPacket_SetRecvBuffer, - - /** \brief Hypervisor channel disconnect, internal. */ - VPCPacket_HyperDisconnect, - - /** \brief Guest channel ACK hypervisor disconnect, internal. */ - VPCPacket_GuestDisconnect, - /** \endcond */ -} VPageChannelPacketType; - -/** - * \brief Page channel packet structure. - * - * A packet structure for passing control/data between guest and hypervisor. - * Can optionally contain a message and also a number of elements. - * - * \note Structure is packed. - * - * \see VPageChannelPacketType - */ -typedef -#include "vmware_pack_begin.h" -struct VPageChannelPacket { - /** \brief Type of packet. */ - VPageChannelPacketType type; - - /** \brief Length of optional message. */ - uint32 msgLen; - - /** \brief Number of optional elements in packet. */ - uint32 numElems; - - /** \brief Followed by msgLen of message and numElems VPageChannelElem. */ -} -#include "vmware_pack_end.h" -VPageChannelPacket; - -/** - * \brief Page channel buffer structure. - * - * A buffer of elements (a scatter-gather list). - * - * \note Structure is packed. - * - * \see VPageChannelElem - */ - -typedef -#include "vmware_pack_begin.h" -struct VPageChannelBuffer { - /** \brief Number of elements. */ - uint32 numElems; - - /** \brief First element. */ - VPageChannelElem elems[1]; - - /** \brief Followed by numElems - 1 of VPageChannelElem. */ -} -#include "vmware_pack_end.h" -VPageChannelBuffer; - -/** \cond PRIVATE */ -typedef -#include "vmware_pack_begin.h" -struct VPageChannelGuestConnectMessage { - - /** \brief Guest channel's datagram handle for control channel. */ - VMCIHandle dgHandle; - - /** \brief Guest channel's queuepair handle. */ - VMCIHandle qpHandle; - - /** \brief Size of producer queue in queuepair in bytes. */ - uint64 produceQSize; - - /** \brief Size of consumer queue in queuepair in bytes. */ - uint64 consumeQSize; - - /** \brief Guest channel's doorbell handle. */ - VMCIHandle doorbellHandle; -} -#include "vmware_pack_end.h" -VPageChannelGuestConnectMessage; - -typedef -#include "vmware_pack_begin.h" -struct VPageChannelHyperConnectMessage { - /** \brief Hypervisor's doorbell handle. */ - VMCIHandle doorbellHandle; -} -#include "vmware_pack_end.h" -VPageChannelHyperConnectMessage; -/** \endcond PRIVATE */ - -/** \cond PRIVATE */ -typedef enum VPageChannelState { - VPCState_Free = 0, - VPCState_Unconnected, - VPCState_Connecting, - VPCState_Connected, - VPCState_Disconnecting, - VPCState_Disconnected, -} VPageChannelState; -/** \endcond PRIVATE */ - -/** - * \brief Opaque page channel type. - */ - -struct VPageChannel; -typedef struct VPageChannel VPageChannel; - -/** - * \brief Client receive callback type. - * - * Type of receive callback, invoked when there are data packets in the - * channel. The client provides a callback with this type to - * VPageChannel_CreateInVM(). If VPAGECHANNEL_FLAGS_NOTIFY_ONLY is specified - * in the channel creation flags, then \c packet is \c NULL; otherwise, - * \c packet points to a channel packet. - * - * \see VPageChannel_CreateInVM() - * \see VPageChannelPacket - */ - -typedef void (*VPageChannelRecvCB)(void *clientData, - VPageChannelPacket *packet); - - -#if !defined(VMKERNEL) - -/** - * \brief Client element allocation callback type. - * - * Type of element allocation callback, invoked when the channel needs - * elements. The client provides a callback of this type to - * VPageChannel_CreateInVM(). - * - * \see VPageChannel_CreateInVM() - * \see VPageChannelElem - * \see VPageChannelFreeElemFn - */ - -typedef int (*VPageChannelAllocElemFn)(void *clientData, - VPageChannelElem *elems, - int numElems); - -/** - * \brief Client element release callback type. - * - * Type of element release callback, invoked when the channel releases - * elements. The client provides a callback of this type to - * VPageChannel_CreateInVM(). - * - * \see VPageChannel_CreateInVM() - * \see VPageChannelElem - * \see VPageChannelAllocElemFn - */ - -typedef void (*VPageChannelFreeElemFn)(void *clientData, - VPageChannelElem *elems, - int numElems); - -/* - ************************************************************************ - * VPageChannel_CreateInVM */ /** - * - * \brief Create guest page channel. - * - * Creates a page channel in the guest. The channel should be released - * with VPageChannel_Destroy(). - * - * \note Only applicable in the guest. - * - * \see VPageChannel_CreateInVMK() - * \see VPageChannel_Destroy() - * - * \param[out] channel Pointer to a newly constructed page - * channel if successful. - * \param[in] resourceId Resource ID on which the channel should - * register its control channel. - * \param[in] peerResourceId Resource ID of peer's control channel. - * \param[in] produceQSize Size of producer queue in queuepair in - * bytes. - * \param[in] consumeQSize Size of consumer queue in queuepair in - * bytes. - * \param[in] flags Channel flags. - * \param[in] recvCB Client's receive callback. - * \param[in] clientRecvData Client data for client's receive - * callback. - * \param[in] elemAlloc Element allocation callback for - * allocating page ranges (scatter-gather - * elements). - * \param[in] allocClientData Client data for element allocation - * callback. - * \param[in] elemFree Element release callback for elements. - * \param[in] freeClientData Client data for element release - * callback. - * \param[in] defRecvBufs Default number of elements sent to - * hypervisor channel. - * \param[in] maxRecvBufs Maximum number of elements that can be - * sent to the hypervisor channel. - * - * \retval VMCI_SUCCESS Creation succeeded, \c *channel contains - * a pointer to a valid channel. - * \retval other Failure. - * - ************************************************************************ - */ - -int VPageChannel_CreateInVM(VPageChannel **channel, - VMCIId resourceId, - VMCIId peerResourceId, - uint64 produceQSize, - uint64 consumeQSize, - uint32 flags, - VPageChannelRecvCB recvCB, - void *clientRecvData, - VPageChannelAllocElemFn elemAlloc, - void *allocClientData, - VPageChannelFreeElemFn elemFree, - void *freeClientData, - int defRecvBufs, - int maxRecvBufs); - -#else // VMKERNEL - -/** - * \brief Type of VM memory access off callback. - * - * This callback is invoked when the memory of the VM containing the peer - * endpoint becomes inaccessible, for example due to a crash. When this - * occurs, the client should unmap any guest pages and cleanup any state. - * This callback runs in a blockable context. The client is not allowed to - * call VPageChannel_Destroy() from inside the callback, or it will deadlock, - * since that function will wait for the callback to complete. - * - * \note Only applicable on VMKernel. - * - * \see VPageChannel_CreateInVMK() - */ - -typedef void (*VPageChannelMemAccessOffCB)(void *clientData); - -/* - ************************************************************************ - * VPageChannel_CreateInVMK */ /** - * - * \brief Create a page channel in VMKernel. - * - * Creates a page channel. The channel should be released with - * VPageChannel_Destroy(). - * - * \note Only applicable on VMKernel. - * - * \see VPageChannel_CreateInVM() - * \see VPageChannel_Destroy() - * - * \param[out] channel Pointer to a newly constructed page - * channel if successful. - * \param[in] resourceId Resource ID on which to register - * control channel. - * \param[in] recvCB Client's receive callback. - * \param[in] clientRecvData Client data for receive callback. - * \param[in] memAccessOffCB Client's mem access off callback. - * \param[in] memAccessOffData Client data for mem access off. - * - * \retval VMCI_SUCCESS Creation succeeded, \c *channel - * contains a pointer to a valid channel. - * \retval other Failure. - * - *********************************************************************** - */ - -int VPageChannel_CreateInVMK(VPageChannel **channel, - VMCIId resourceId, - VPageChannelRecvCB recvCB, - void *clientRecvData, - VPageChannelMemAccessOffCB memAccessOffCB, - void *memAccessOffData); - -/* - ************************************************************************ - * VPageChannel_ReserveBuffers */ /** - * - * \brief Reserve guest elements. - * - * Reserve sufficient guest elements to cover the given length. The - * buffers can then be posted to the guest. This allocates both the - * buffer and the elements within the buffer. - * - * \note Only applicable on VMKernel. - * - * \see VPageChannel_ReleaseBuffers() - * - * \param[in] channel Page channel. - * \param[in] dataLen Length to reserve in bytes. - * \param[out] buffer Pointer to a buffer containing elements to cover - * the given length if successful. - * - * \retval VMCI_SUCCESS Reservation succeeded, \c *buffer contains - * a pointer to a valid buffer. - * \retval other Failure. - * - ************************************************************************ - */ - -int VPageChannel_ReserveBuffers(VPageChannel *channel, - size_t dataLen, - VPageChannelBuffer **buffer); - -/* - ************************************************************************ - * VPageChannel_ReleaseBuffers */ /** - * - * \brief Release guest elements. - * - * \note Only applicable on VMKernel. - * - * \see VPageChannel_ReserveBuffers() - * - * Release guest elements previous reserved with - * VPageChannel_ReserveBuffers(). If the buffers were sent to the guest, - * then only the buffer itself should be released, i.e., - * \c returnToFreePool should be \c FALSE; the guest will release the - * buffers on completion. Otherwise, if for some reason they are not - * sent after reserving them, then \c returnToFreePool should be set to - * \c TRUE. - * - * \param[in] channel Page channel. - * \param[in] buffer Buffer to be released. - * \param[in] returnToFreePool If \c TRUE, then release the elements - * of the buffer along with the buffer - * itself. If \c FALSE, then release only - * the buffer pointer itself. - * - ************************************************************************ - */ - -void VPageChannel_ReleaseBuffers(VPageChannel *channel, - VPageChannelBuffer *buffer, - Bool returnToFreePool); - -/* - ************************************************************************ - * VPageChannel_CompletionNotify */ /** - * - * \brief Notify channel of completion. - * - * This function is called when the client is finished using the elements - * (scatter-gather list) of a packet. This will generated a notification - * to the guest to pass ownership of the buffers back to the guest. This - * can also be used to read back the data from the hypervisor and send - * it to the guest. - * - * \note Only applicable on VMKernel. - * - * \see VPageChannel_ReserveBuffers - * - * \param[in] channel Channel on which I/O is complete. - * \param[in] message Optional message to send to guest. - * \param[in] len Length of optional message. - * \param[in] buffer Buffer used for I/O. - * - ************************************************************************ - */ - -int VPageChannel_CompletionNotify(VPageChannel *channel, - char *message, - int len, - VPageChannelBuffer *buffer); - -/* - ************************************************************************ - * VPageChannel_MapToMa */ /** - * - * \brief Map guest PA in an element to a list of MAs. - * - * Map a guest physical address to a list of hypervisor machine - * addresses. - * - * \note Only applicable on VMKernel. - * - * \param[in] channel Channel on which to map. - * \param[in] paElem Guest's physical address. - * \param[out] maElems Hypervisor machine addresses. - * \param[in] numElems Max number of hypervisor elements. - * - * \retval elems Number of mapped elements. - * - ************************************************************************ - */ - -int VPageChannel_MapToMa(VPageChannel *channel, - VPageChannelElem paElem, - VPageChannelElem *maElems, - uint32 numElems); - -/* - ************************************************************************ - * VPageChannel_UnmapMa */ /** - * - * \brief Unmap MA for a buffer. - * - * Unmap hypervisor machine addresses referring to a guest physical - * addresses. - * - * \note Only applicable on VMKernel. - * - * \see VPageChannel_MapToMa - * - * \param[in] channel Channel for which to unmap. - * \param[in] buffer Buffer containing elements to unmap. - * \param[in] numElems Number of elements to unmap. - * - * \retval 0 Unmap successful. - * \retval -1 World not found for channel. - * - ************************************************************************ - */ - -int VPageChannel_UnmapMa(VPageChannel *channel, - VPageChannelBuffer *buffer, - int numElems); - -#endif // VMKERNEL - -/* - ************************************************************************ - * VPageChannel_Destroy */ /** - * - * \brief Destroy the given channel. - * - * Destroy the given channel. This will disconnect from the peer - * channel (if connected) and release all resources. - * - * \see VPageChannel_CreateInVMK - * \see VPageChannel_CreateInVM - * - * \param[in] channel The channel to be destroyed. - * - ************************************************************************ - */ - -void VPageChannel_Destroy(VPageChannel *channel); - -/* - ************************************************************************ - * VPageChannel_Send */ /** - * - * \brief Send a packet to the channel's peer. - * - * Send a packet to the channel's peer. A message and a number of - * elements may optionally be sent. If the send is successful, the - * elements are owned by the peer and only the buffer itself should - * be released, but not the elements within. If the send fails, the - * client should release the buffer and the elements. - * - * \see VPageChannel_SendPacket - * - * \param[in] channel Channel on which to send. - * \param[in] type Type of packet to send. - * \param[in] message Optional message to send. - * \param[in] len Length of optional message. - * \param[in] buffer Buffer (of elements) to send. - * - * \retval VMCI_SUCCESS Packet successfully sent, buffer elements - * owned by peer. - * \retval other Failure to send, client should release - * elements. - * - ************************************************************************ - */ - -int VPageChannel_Send(VPageChannel *channel, - VPageChannelPacketType type, - char *message, - int len, - VPageChannelBuffer *buffer); - -/* - ************************************************************************ - * VPageChannel_SendPacket */ /** - * - * \brief Send the given packet to the channel's peer. - * - * Send a client-constructed packet to the channel's peer. If the - * send is successful, any elements in the packet are owned by the - * peer. Otherwise, the client retains ownership. - * - * \see VPageChannel_Send - * - * \param[in] channel Channel on which to send. - * \param[in] packet Packet to be sent. - * - * \retval VMCI_SUCCESS Packet successfully sent, buffer elements - * owned by peer. - * \retval other Failure to send, client should release - * elements. - * - ************************************************************************ - */ - -int VPageChannel_SendPacket(VPageChannel *channel, - VPageChannelPacket *packet); - -/* - ************************************************************************ - * VPageChannel_PollRecvQ */ /** - * - * \brief Poll the channel's receive queue for packets. - * - * Poll the channel's receive queue for packets from the peer. If any - * packets are available, the channel's receive callback will be invoked. - * - * \param[in] channel Channel to poll. - * - ************************************************************************ - */ - -void VPageChannel_PollRecvQ(VPageChannel *channel); - -/* - ************************************************************************ - * VPageChannel_BufferLen */ /** - * - * \brief Determine the length of a packet. - * - * Determine the length of the given packet in bytes. - * - * \param[in] packet Packet for which length is to be determined. - * - * \retval bytes Size of the packet in bytes. - * - ************************************************************************ - */ - -static INLINE size_t -VPageChannelPacket_BufferLen(VPageChannelPacket *packet) // IN -{ - size_t len, i; - VPageChannelElem *elems; - - ASSERT(packet); - - len = 0; - elems = VPAGECHANNEL_PACKET_ELEMS(packet); - for (i = 0; i < packet->numElems; i++) { - len += elems[i].le; - } - - return len; -} - -/** \cond PRIVATE */ -#if defined(linux) && !defined(VMKERNEL) -#include "compat_pci.h" -#define vmci_pci_map_page(_pg, _off, _sz, _dir) \ - pci_map_page(NULL, (_pg), (_off), (_sz), (_dir)) -#define vmci_pci_unmap_page(_dma, _sz, _dir) \ - pci_unmap_page(NULL, (_dma), (_sz), (_dir)) -#endif // linux && !VMKERNEL -/** \endcond PRIVATE */ - -#endif // _VMCI_PACKET_H_ diff --git a/open-vm-tools/modules/linux/vmhgfs/Makefile b/open-vm-tools/modules/linux/vmhgfs/Makefile index e7e3eaf4..648dab58 100644 --- a/open-vm-tools/modules/linux/vmhgfs/Makefile +++ b/open-vm-tools/modules/linux/vmhgfs/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/make -f ########################################################## -# Copyright (C) 1998 VMware, Inc. All rights reserved. +# Copyright (C) 1998-2015 VMware, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/Makefile.kernel b/open-vm-tools/modules/linux/vmhgfs/Makefile.kernel index a8a2caab..c68a8087 100644 --- a/open-vm-tools/modules/linux/vmhgfs/Makefile.kernel +++ b/open-vm-tools/modules/linux/vmhgfs/Makefile.kernel @@ -1,6 +1,6 @@ #!/usr/bin/make -f ########################################################## -# Copyright (C) 1998 VMware, Inc. All rights reserved. +# Copyright (C) 1998-2015 VMware, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -28,11 +28,13 @@ EXTRA_CFLAGS := $(CC_OPTS) $(INCLUDE) EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/cachector.c, -DVMW_KMEMCR_CTOR_HAS_3_ARGS, ) EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/cachector1.c, -DVMW_KMEMCR_CTOR_HAS_2_ARGS, ) EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/file_operations_fsync.c, -DVMW_FSYNC_31, ) +EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/file_operations_flush.c, -DVMW_FLUSH_HAS_1_ARG, ) # Note: These tests are inverted EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/getsb1.c,, -DVMW_GETSB_2618) EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/statfs1.c,, -DVMW_STATFS_2618) EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/inode1.c,, -DVMW_INODE_2618) +EXTRA_CFLAGS += $(call vm_check_build, $(AUTOCONF_DIR)/dcount.c,, -DVMW_DCOUNT_311) MODPOST_VMCI_SYMVERS := $(wildcard $(MODULEBUILDDIR)/VMwareVMCIModule.symvers) diff --git a/open-vm-tools/modules/linux/vmhgfs/bdhandler.c b/open-vm-tools/modules/linux/vmhgfs/bdhandler.c index 5bcac3f5..b891019e 100644 --- a/open-vm-tools/modules/linux/vmhgfs/bdhandler.c +++ b/open-vm-tools/modules/linux/vmhgfs/bdhandler.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/dentry.c b/open-vm-tools/modules/linux/vmhgfs/dentry.c index 873ef103..2da16dcc 100644 --- a/open-vm-tools/modules/linux/vmhgfs/dentry.c +++ b/open-vm-tools/modules/linux/vmhgfs/dentry.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/dir.c b/open-vm-tools/modules/linux/vmhgfs/dir.c index e4e82b48..809611a1 100644 --- a/open-vm-tools/modules/linux/vmhgfs/dir.c +++ b/open-vm-tools/modules/linux/vmhgfs/dir.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -1157,7 +1157,8 @@ HgfsDoReaddir(struct file *file, // IN: Bool dotAndDotDotIgnore, // IN: ignore "." and ".." filldir_t filldirCb, // IN: system filler callback void *filldirCtx, // IN/OUT: system filler context - loff_t *entryPos) // IN/OUT: entry position + loff_t *fillPos, // IN/OUT: fill entry position + loff_t *currentPos) // IN/OUT: current position { char *entryName = NULL; // buf for escaped version of name size_t entryNameBufLen = NAME_MAX + 1; @@ -1179,7 +1180,7 @@ HgfsDoReaddir(struct file *file, // IN: __func__, file->f_dentry->d_name.name, file->f_dentry->d_inode->i_ino, - *entryPos)); + *currentPos)); /* * Refresh entries if required. See rm -rf 6.10+ breaking issue. @@ -1189,7 +1190,6 @@ HgfsDoReaddir(struct file *file, // IN: return result; } - /* * Some day when we're out of things to do we can move this to a slab * allocator. @@ -1207,7 +1207,7 @@ HgfsDoReaddir(struct file *file, // IN: uint32 entryType = DT_UNKNOWN; result = HgfsReaddirNextEntry(file, - *entryPos, + *currentPos, dotAndDotDotIgnore, entryNameBufLen, entryName, @@ -1228,20 +1228,20 @@ HgfsDoReaddir(struct file *file, // IN: } if (entryIgnore) { - *entryPos += 1; + *currentPos += 1; continue; } /* * Call the HGFS wrapper to the system fill function to set this dentry. */ - LOG(6, (KERN_DEBUG "VMware hgfs: %s: dir_emit(%s, %u, %Lu)\n", - __func__, entryName, entryNameLength, *entryPos)); + LOG(6, (KERN_DEBUG "VMware hgfs: %s: dir_emit(%s, %u, @ (fill %Lu HGFS %Lu)\n", + __func__, entryName, entryNameLength, *fillPos, *currentPos)); if (!HgfsReaddirFillEntry(filldirCb, /* filldir callback function */ filldirCtx, /* filldir callback struct */ entryName, /* name of dirent */ entryNameLength, /* length of name */ - *entryPos, /* entry position */ + *fillPos, /* fill entry position */ entryIno, /* inode number (0 makes it not show) */ entryType)) { /* type of dirent */ /* @@ -1254,7 +1254,8 @@ HgfsDoReaddir(struct file *file, // IN: result = 0; break; } - *entryPos += 1; + *currentPos += 1; + *fillPos += 1; } LOG(6, (KERN_DEBUG "VMware hgfs: %s: return\n",__func__)); @@ -1284,6 +1285,12 @@ static int HgfsReaddir(struct file *file, // IN: struct dir_context *ctx) // IN: { + HgfsFileInfo *fInfo = FILE_GET_FI_P(file); + + if (0 == ctx->pos) { + fInfo->direntPos = 0; + } + /* If either dot and dotdot are filled in for us we can exit. */ if (!dir_emit_dots(file, ctx)) { LOG(6, (KERN_DEBUG "VMware hgfs: %s: dir_emit_dots(%s, @ %Lu)\n", @@ -1292,7 +1299,7 @@ HgfsReaddir(struct file *file, // IN: } /* It is sufficient to pass the context as it contains the filler function. */ - return HgfsDoReaddir(file, TRUE, NULL, ctx, &ctx->pos); + return HgfsDoReaddir(file, TRUE, NULL, ctx, &ctx->pos, &fInfo->direntPos); } @@ -1367,7 +1374,13 @@ HgfsReaddir(struct file *file, // IN: Directory to read from void *dirent, // OUT: Buffer to copy dentries into filldir_t filldir) // IN: Filler function { - return HgfsDoReaddir(file, FALSE, filldir, dirent, &file->f_pos); + HgfsFileInfo *fInfo = FILE_GET_FI_P(file); + + if (0 == file->f_pos) { + fInfo->direntPos = 0; + } + + return HgfsDoReaddir(file, FALSE, filldir, dirent, &file->f_pos, &fInfo->direntPos); } diff --git a/open-vm-tools/modules/linux/vmhgfs/file.c b/open-vm-tools/modules/linux/vmhgfs/file.c index 3ddbfefd..bbde3f4b 100644 --- a/open-vm-tools/modules/linux/vmhgfs/file.c +++ b/open-vm-tools/modules/linux/vmhgfs/file.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -47,6 +47,31 @@ #include "vm_assert.h" #include "vm_basic_types.h" +/* + * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using + * the O_SYNC flag. We continue to use the existing numerical value + * for O_DSYNC semantics now, but using the correct symbolic name for it. + * This new value is used to request true Posix O_SYNC semantics. It is + * defined in this strange way to make sure applications compiled against + * new headers get at least O_DSYNC semantics on older kernels. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) +#define HGFS_FILECTL_SYNC(flags) ((flags) & O_DSYNC) +#else +#define HGFS_FILECTL_SYNC(flags) ((flags) & O_SYNC) +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +typedef struct iov_iter *hgfs_iov; +#define HGFS_IOV_TO_COUNT(iov, nr_segs) (iov_iter_count(iov)) +#define HGFS_IOV_TO_SEGS(iov, nr_segs) (0) +#define HGFS_IOCB_TO_POS(iocb, pos) (iocb->ki_pos) +#else +typedef const struct iovec *hgfs_iov; +#define HGFS_IOV_TO_COUNT(iov, nr_segs) (iov_length(iov, nr_segs)) +#define HGFS_IOV_TO_SEGS(iov, nr_segs) (nr_segs) +#define HGFS_IOCB_TO_POS(iocb, pos) (pos) +#endif + /* Private functions. */ static int HgfsPackOpenRequest(struct inode *inode, struct file *file, @@ -61,14 +86,21 @@ static int HgfsUnpackOpenReply(HgfsReq *req, static int HgfsOpen(struct inode *inode, struct file *file); #if defined VMW_USE_AIO -static ssize_t HgfsAioRead(struct kiocb *iocb, - const struct iovec *iov, - unsigned long numSegs, - loff_t offset); -static ssize_t HgfsAioWrite(struct kiocb *iocb, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +static ssize_t HgfsFileRead(struct kiocb *iocb, + struct iov_iter *to); +static ssize_t HgfsFileWrite(struct kiocb *iocb, + struct iov_iter *from); +#else // LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +static ssize_t HgfsFileRead(struct kiocb *iocb, const struct iovec *iov, unsigned long numSegs, loff_t offset); +static ssize_t HgfsFileWrite(struct kiocb *iocb, + const struct iovec *iov, + unsigned long numSegs, + loff_t offset); +#endif // LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) #else static ssize_t HgfsRead(struct file *file, char __user *buf, @@ -83,6 +115,15 @@ static ssize_t HgfsWrite(struct file *file, static loff_t HgfsSeek(struct file *file, loff_t offset, int origin); +static int HgfsFlush(struct file *file +#if !defined VMW_FLUSH_HAS_1_ARG + ,fl_owner_t id +#endif + ); + +#if !defined VMW_FSYNC_31 +static int HgfsDoFsync(struct inode *inode); +#endif static int HgfsFsync(struct file *file, #if defined VMW_FSYNC_OLD @@ -125,9 +166,19 @@ struct file_operations HgfsFileFileOperations = { .owner = THIS_MODULE, .open = HgfsOpen, .llseek = HgfsSeek, + .flush = HgfsFlush, #if defined VMW_USE_AIO - .aio_read = HgfsAioRead, - .aio_write = HgfsAioWrite, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) + .read = new_sync_read, + .write = new_sync_write, + .read_iter = HgfsFileRead, + .write_iter = HgfsFileWrite, +#else // LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) + .read = do_sync_read, + .write = do_sync_write, + .aio_read = HgfsFileRead, + .aio_write = HgfsFileWrite, +#endif // LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) #else .read = HgfsRead, .write = HgfsWrite, @@ -642,7 +693,51 @@ out: /* *---------------------------------------------------------------------- * - * HgfsAioRead -- + * HgfsGenericFileRead -- + * + * Called when the kernel initiates an asynchronous read from a file in + * our filesystem. Our function is just a thin wrapper around + * system generic read function. + * + * + * Results: + * Returns the number of bytes read on success, or an error on + * failure. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +static ssize_t +HgfsGenericFileRead(struct kiocb *iocb, // IN: I/O control block + hgfs_iov iov, // IN: Array of I/O vectors + unsigned long iovSegs, // IN: Count of I/O vectors + loff_t pos) // IN: Position at which to read +{ + ssize_t result; + + LOG(8, (KERN_DEBUG "VMware hgfs: %s(%lu@%Ld)\n", + __func__, (unsigned long)HGFS_IOV_TO_COUNT(iov, iovSegs), + (long long) pos)); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) + result = generic_file_read_iter(iocb, iov); +#else + result = generic_file_aio_read(iocb, iov, iovSegs, pos); +#endif + + LOG(8, (KERN_DEBUG "VMware hgfs: %s return %"FMTSZ"d\n", + __func__, result)); + return result; +} + + +/* + *---------------------------------------------------------------------- + * + * HgfsFileRead -- * * Called when the kernel initiates an asynchronous read to a file in * our filesystem. Our function is just a thin wrapper around @@ -658,35 +753,90 @@ out: *---------------------------------------------------------------------- */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) static ssize_t -HgfsAioRead(struct kiocb *iocb, // IN: I/O control block - const struct iovec *iov, // OUT: Array of I/O buffers - unsigned long numSegs, // IN: Number of buffers - loff_t offset) // IN: Offset at which to read +HgfsFileRead(struct kiocb *iocb, // IN: I/O control block + struct iov_iter *iov) // OUT: Array of I/O buffers +#else // LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +static ssize_t +HgfsFileRead(struct kiocb *iocb, // IN: I/O control block + const struct iovec *iov, // OUT: Array of I/O buffers + unsigned long numSegs, // IN: Number of buffers + loff_t offset) // IN: Offset at which to read +#endif // LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) { - int result; + ssize_t result; struct dentry *readDentry; + loff_t pos; + unsigned long iovSegs; ASSERT(iocb); ASSERT(iocb->ki_filp); ASSERT(iocb->ki_filp->f_dentry); ASSERT(iov); + pos = HGFS_IOCB_TO_POS(iocb, offset); + iovSegs = HGFS_IOV_TO_SEGS(iov, numSegs); + readDentry = iocb->ki_filp->f_dentry; - LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s, %lu@%lu)\n", + LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s)\n", __func__, readDentry->d_parent->d_name.name, - readDentry->d_name.name, - (unsigned long) iov_length(iov, numSegs), (unsigned long) offset)); + readDentry->d_name.name)); result = HgfsRevalidate(readDentry); if (result) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsAioRead: invalid dentry\n")); + LOG(4, (KERN_DEBUG "VMware hgfs: %s: invalid dentry\n", __func__)); goto out; } - result = generic_file_aio_read(iocb, iov, numSegs, offset); - out: + result = HgfsGenericFileRead(iocb, iov, iovSegs, pos); + +out: + return result; +} + + +/* + *---------------------------------------------------------------------- + * + * HgfsGenericFileWrite -- + * + * Called when the kernel initiates an asynchronous write to a file in + * our filesystem. Our function is just a thin wrapper around + * system generic write function. + * + * + * Results: + * Returns the number of bytes written on success, or an error on + * failure. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +static ssize_t +HgfsGenericFileWrite(struct kiocb *iocb, // IN: I/O control block + hgfs_iov iov, // IN: Array of I/O vectors + unsigned long iovSegs, // IN: Count of I/O vectors + loff_t pos) // IN: Position at which to write +{ + ssize_t result; + + LOG(8, (KERN_DEBUG "VMware hgfs: %s(%lu@%Ld)\n", + __func__, (unsigned long)HGFS_IOV_TO_COUNT(iov, iovSegs), + (long long) pos)); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) + result = generic_file_write_iter(iocb, iov); +#else + result = generic_file_aio_write(iocb, iov, iovSegs, pos); +#endif + + LOG(8, (KERN_DEBUG "VMware hgfs: %s return %"FMTSZ"d\n", + __func__, result)); return result; } @@ -694,7 +844,7 @@ HgfsAioRead(struct kiocb *iocb, // IN: I/O control block /* *---------------------------------------------------------------------- * - * HgfsAioWrite -- + * HgfsFileWrite -- * * Called when the kernel initiates an asynchronous write to a file in * our filesystem. Our function is just a thin wrapper around @@ -713,34 +863,60 @@ HgfsAioRead(struct kiocb *iocb, // IN: I/O control block *---------------------------------------------------------------------- */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +ssize_t +HgfsFileWrite(struct kiocb *iocb, // IN: I/O control block + struct iov_iter *iov) // IN: Array of I/O buffers +#else // LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) static ssize_t -HgfsAioWrite(struct kiocb *iocb, // IN: I/O control block - const struct iovec *iov, // IN: Array of I/O buffers - unsigned long numSegs, // IN: Number of buffers - loff_t offset) // IN: Offset at which to read +HgfsFileWrite(struct kiocb *iocb, // IN: I/O control block + const struct iovec *iov, // IN: Array of I/O buffers + unsigned long numSegs, // IN: Number of buffers + loff_t offset) // IN: Offset at which to write +#endif // LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) { - int result; + ssize_t result; struct dentry *writeDentry; + loff_t pos; + unsigned long iovSegs; ASSERT(iocb); ASSERT(iocb->ki_filp); ASSERT(iocb->ki_filp->f_dentry); ASSERT(iov); + pos = HGFS_IOCB_TO_POS(iocb, offset); + iovSegs = HGFS_IOV_TO_SEGS(iov, numSegs); + writeDentry = iocb->ki_filp->f_dentry; - LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s, %lu@%Ld)\n", + LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s)\n", __func__, writeDentry->d_parent->d_name.name, - writeDentry->d_name.name, - (unsigned long) iov_length(iov, numSegs), (long long) offset)); + writeDentry->d_name.name)); result = HgfsRevalidate(writeDentry); if (result) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsAioWrite: invalid dentry\n")); + LOG(4, (KERN_DEBUG "VMware hgfs: %s: invalid dentry\n", __func__)); goto out; } - result = generic_file_aio_write(iocb, iov, numSegs, offset); + result = HgfsGenericFileWrite(iocb, iov, iovSegs, pos); + + if (result >= 0) { + if (IS_SYNC(writeDentry->d_inode) || + HGFS_FILECTL_SYNC(iocb->ki_filp->f_flags)) { + int error; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) + error = vfs_fsync(iocb->ki_filp, 0); +#else + error = HgfsDoFsync(writeDentry->d_inode); +#endif + if (error < 0) { + result = error; + } + } + } + out: return result; } @@ -896,6 +1072,101 @@ HgfsSeek(struct file *file, // IN: File to seek } +#if !defined VMW_FSYNC_31 +/* + *---------------------------------------------------------------------- + * + * HgfsDoFsync -- + * + * Helper for HgfsFlush() and HgfsFsync(). + * + * The hgfs protocol doesn't support fsync explicityly yet. + * So for now, we flush all the pages to presumably honor the + * intent of an app calling fsync() which is to get the + * data onto persistent storage. As things stand now we're at + * the whim of the hgfs server code running on the host to fsync or + * not if and when it pleases. + * + * + * Results: + * Returns zero on success. Otherwise an error. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +HgfsDoFsync(struct inode *inode) // IN: File we operate on +{ + int ret; + + LOG(4, (KERN_DEBUG "VMware hgfs: %s(%"FMT64"u)\n", + __func__, INODE_GET_II_P(inode)->hostFileId)); + + ret = compat_filemap_write_and_wait(inode->i_mapping); + + LOG(4, (KERN_DEBUG "VMware hgfs: %s: returns %d\n", + __func__, ret)); + + return ret; +} +#endif + + +/* + *---------------------------------------------------------------------- + * + * HgfsFlush -- + * + * Called when user process calls fflush() on an hgfs file. + * Flush all dirty pages and check for write errors. + * + * + * Results: + * Returns zero on success. (Currently always succeeds). + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +HgfsFlush(struct file *file // IN: file to flush +#if !defined VMW_FLUSH_HAS_1_ARG + ,fl_owner_t id // IN: id not used +#endif + ) +{ + int ret = 0; + + LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s)\n", + __func__, file->f_dentry->d_parent->d_name.name, + file->f_dentry->d_name.name)); + + if ((file->f_mode & FMODE_WRITE) == 0) { + goto exit; + } + + + /* Flush writes to the server and return any errors */ + LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling vfs_sync ... \n", + __func__)); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) + ret = vfs_fsync(file, 0); +#else + ret = HgfsDoFsync(file->f_dentry->d_inode); +#endif + +exit: + LOG(4, (KERN_DEBUG "VMware hgfs: %s: returns %d\n", + __func__, ret)); + return ret; +} + + /* *---------------------------------------------------------------------- * @@ -903,21 +1174,13 @@ HgfsSeek(struct file *file, // IN: File to seek * * Called when user process calls fsync() on hgfs file. * - * The hgfs protocol doesn't support fsync yet, so for now, we punt - * and just return success. This is a little less sketchy than it - * might sound, because hgfs skips the buffer cache in the guest - * anyway (we always write to the host immediately). - * - * In the future we might want to try harder though, since - * presumably the intent of an app calling fsync() is to get the + * The hgfs protocol doesn't support fsync explicitly yet, + * so for now, we flush all the pages to presumably honor the + * intent of an app calling fsync() which is to get the * data onto persistent storage, and as things stand now we're at * the whim of the hgfs server code running on the host to fsync or * not if and when it pleases. * - * Note that do_fsync will call filemap_fdatawrite() before us and - * filemap_fdatawait() after us, so there's no need to do anything - * here w.r.t. writing out dirty pages. - * * Results: * Returns zero on success. (Currently always succeeds). * @@ -937,18 +1200,37 @@ HgfsFsync(struct file *file, // IN: File we operate on #endif int datasync) // IN: fdatasync or fsync { - LOG(6, (KERN_DEBUG "VMware hgfs: %s(%s/%s, %lld, %lld, %d)\n", + int ret = 0; + loff_t startRange; + loff_t endRange; + struct inode *inode; + +#if defined VMW_FSYNC_31 + startRange = start; + endRange = end; +#else + startRange = 0; + endRange = MAX_INT64; +#endif + + LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s, %lld, %lld, %d)\n", __func__, file->f_dentry->d_parent->d_name.name, file->f_dentry->d_name.name, + startRange, endRange, + datasync)); + + /* Flush writes to the server and return any errors */ + inode = file->f_dentry->d_inode; #if defined VMW_FSYNC_31 - start, end, + ret = filemap_write_and_wait_range(inode->i_mapping, startRange, endRange); #else - (loff_t)0, (loff_t)0, + ret = HgfsDoFsync(inode); #endif - datasync)); - return 0; + LOG(4, (KERN_DEBUG "VMware hgfs: %s: written pages %lld, %lld returns %d)\n", + __func__, startRange, endRange, ret)); + return ret; } diff --git a/open-vm-tools/modules/linux/vmhgfs/filesystem.c b/open-vm-tools/modules/linux/vmhgfs/filesystem.c index f101ca7a..33c4c56f 100644 --- a/open-vm-tools/modules/linux/vmhgfs/filesystem.c +++ b/open-vm-tools/modules/linux/vmhgfs/filesystem.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -83,7 +83,6 @@ HgfsOp hgfsVersionCreateSymlink; static inline unsigned long HgfsComputeBlockBits(unsigned long blockSize); static compat_kmem_cache_ctor HgfsInodeCacheCtor; static HgfsSuperInfo *HgfsInitSuperInfo(HgfsMountInfo *mountInfo); -static int HgfsGetRootDentry(struct super_block *sb, struct dentry **rootDentry); static int HgfsReadSuper(struct super_block *sb, void *rawData, int flags); @@ -123,8 +122,6 @@ static struct file_system_type hgfsType = { .kill_sb = kill_anon_super, }; -extern int USE_VMCI; - /* * Private functions implementations. */ @@ -228,16 +225,23 @@ HgfsInitSuperInfo(HgfsMountInfo *mountInfo) // IN: Passed down from the user * or gid given to us by the server. */ si->uidSet = mountInfo->uidSet; + si->uid = current_uid(); if (si->uidSet) { - si->uid = mountInfo->uid; - } else { - si->uid = current_uid(); + kuid_t mntUid = make_kuid(current_user_ns(), mountInfo->uid); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + if (uid_valid(mntUid)) +#endif + si->uid = mntUid; } + si->gidSet = mountInfo->gidSet; + si->gid = current_gid(); if (si->gidSet) { - si->gid = mountInfo->gid; - } else { - si->gid = current_gid(); + kgid_t mntGid = make_kgid(current_user_ns(), mountInfo->gid); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + if (gid_valid(mntGid)) +#endif + si->gid = mntGid; } si->fmask = mountInfo->fmask; si->dmask = mountInfo->dmask; @@ -327,103 +331,6 @@ HgfsInitSuperInfo(HgfsMountInfo *mountInfo) // IN: Passed down from the user /* - *---------------------------------------------------------------------------- - * - * HgfsGetRootDentry -- - * - * Gets the root dentry for a given super block. - * - * Results: - * zero and a valid root dentry on success - * negative value on failure - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -static int -HgfsGetRootDentry(struct super_block *sb, // IN: Super block object - struct dentry **rootDentry) // OUT: Root dentry -{ - int result = -ENOMEM; - struct inode *rootInode; - struct dentry *tempRootDentry = NULL; - struct HgfsAttrInfo rootDentryAttr; - HgfsInodeInfo *iinfo; - - ASSERT(sb); - ASSERT(rootDentry); - - LOG(6, (KERN_DEBUG "VMware hgfs: %s: entered\n", __func__)); - - rootInode = HgfsGetInode(sb, HGFS_ROOT_INO); - if (rootInode == NULL) { - LOG(6, (KERN_DEBUG "VMware hgfs: %s: Could not get the root inode\n", - __func__)); - goto exit; - } - - /* - * On an allocation failure in read_super, the inode will have been - * marked "bad". If it was, we certainly don't want to start playing with - * the HgfsInodeInfo. So quietly put the inode back and fail. - */ - if (is_bad_inode(rootInode)) { - LOG(6, (KERN_DEBUG "VMware hgfs: %s: encountered bad inode\n", - __func__)); - goto exit; - } - - tempRootDentry = d_make_root(rootInode); - /* - * d_make_root() does iput() on failure; if d_make_root() completes - * successfully then subsequent dput() will do iput() for us, so we - * should just ignore root inode from now on. - */ - rootInode = NULL; - - if (tempRootDentry == NULL) { - LOG(4, (KERN_WARNING "VMware hgfs: %s: Could not get " - "root dentry\n", __func__)); - goto exit; - } - - result = HgfsPrivateGetattr(tempRootDentry, &rootDentryAttr, NULL); - if (result) { - LOG(4, (KERN_WARNING "VMware hgfs: HgfsReadSuper: Could not" - "instantiate the root dentry\n")); - goto exit; - } - - iinfo = INODE_GET_II_P(tempRootDentry->d_inode); - iinfo->isFakeInodeNumber = FALSE; - iinfo->isReferencedInode = TRUE; - - if (rootDentryAttr.mask & HGFS_ATTR_VALID_FILEID) { - iinfo->hostFileId = rootDentryAttr.hostFileId; - } - - HgfsChangeFileAttributes(tempRootDentry->d_inode, &rootDentryAttr); - HgfsDentryAgeReset(tempRootDentry); - tempRootDentry->d_op = &HgfsDentryOperations; - - *rootDentry = tempRootDentry; - result = 0; - - LOG(6, (KERN_DEBUG "VMware hgfs: %s: finished\n", __func__)); -exit: - if (result) { - iput(rootInode); - dput(tempRootDentry); - *rootDentry = NULL; - } - return result; -} - - -/* *----------------------------------------------------------------------------- * * HgfsReadSuper -- @@ -503,7 +410,10 @@ HgfsReadSuper(struct super_block *sb, // OUT: Superblock object sb->s_blocksize_bits = HgfsComputeBlockBits(HGFS_BLOCKSIZE); sb->s_blocksize = 1 << sb->s_blocksize_bits; - result = HgfsGetRootDentry(sb, &rootDentry); + /* + * Create the root dentry and its corresponding inode. + */ + result = HgfsInstantiateRoot(sb, &rootDentry); if (result) { LOG(4, (KERN_WARNING "VMware hgfs: HgfsReadSuper: Could not instantiate " "root dentry\n")); @@ -646,12 +556,6 @@ HgfsResetOps(void) hgfsVersionRename = HGFS_OP_RENAME_V3; hgfsVersionQueryVolumeInfo = HGFS_OP_QUERY_VOLUME_INFO_V3; hgfsVersionCreateSymlink = HGFS_OP_CREATE_SYMLINK_V3; - - if (USE_VMCI) { - hgfsVersionRead = HGFS_OP_READ_FAST_V4; - hgfsVersionWrite = HGFS_OP_WRITE_FAST_V4; - } - } diff --git a/open-vm-tools/modules/linux/vmhgfs/filesystem.h b/open-vm-tools/modules/linux/vmhgfs/filesystem.h index b04c415b..b0bcb5b4 100644 --- a/open-vm-tools/modules/linux/vmhgfs/filesystem.h +++ b/open-vm-tools/modules/linux/vmhgfs/filesystem.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/fsutil.c b/open-vm-tools/modules/linux/vmhgfs/fsutil.c index 2b1bcff5..50233242 100644 --- a/open-vm-tools/modules/linux/vmhgfs/fsutil.c +++ b/open-vm-tools/modules/linux/vmhgfs/fsutil.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -53,10 +53,13 @@ static int HgfsUnpackGetattrReply(HgfsReq *req, HgfsAttrInfo *attr, char **fileName); static int HgfsPackGetattrRequest(HgfsReq *req, - struct dentry *dentry, + HgfsOp opUsed, Bool allowHandleReuse, - HgfsOp opUsed, + struct dentry *dentry, HgfsAttrInfo *attr); +static int HgfsBuildRootPath(char *buffer, + size_t bufferLen, + HgfsSuperInfo *si); /* * Private function implementations. @@ -236,13 +239,17 @@ HgfsUnpackGetattrReply(HgfsReq *req, // IN: Reply packet /* *---------------------------------------------------------------------- * - * HgfsPackGetattrRequest -- + * HgfsPackCommonattr -- * - * Setup the getattr request, depending on the op version. When possible, - * we will issue the getattr using an existing open HGFS handle. + * This function abstracts the HgfsAttr struct behind HgfsAttrInfo. + * Callers can pass one of four replies into it and receive back the + * attributes for those replies. + * + * Callers must populate attr->requestType so that we know whether to + * expect a V1 or V2 Attr struct. * * Results: - * Returns zero on success, or negative error on failure. + * Zero on success, non-zero otherwise. * * Side effects: * None @@ -251,22 +258,18 @@ HgfsUnpackGetattrReply(HgfsReq *req, // IN: Reply packet */ static int -HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer - struct dentry *dentry, // IN: Dentry containing name - Bool allowHandleReuse, // IN: Can we use a handle? - HgfsOp opUsed, // IN: Op to be used - HgfsAttrInfo *attr) // OUT: Attrs to update +HgfsPackCommonattr(HgfsReq *req, // IN/OUT: request buffer + HgfsOp opUsed, // IN: Op to be used + Bool allowHandleReuse, // IN: Can we use a handle? + struct inode *fileInode, // IN: file inode + size_t *reqSize, // OUT: request size + size_t *reqBufferSize, // OUT: request buffer size + char **fileName, // OUT: pointer to request file name + uint32 **fileNameLength, // OUT: pointer to request file name length + HgfsAttrInfo *attr) // OUT: Attrs to update { - size_t reqBufferSize; - size_t reqSize; - int result = 0; HgfsHandle handle; - char *fileName = NULL; - uint32 *fileNameLength = NULL; - - ASSERT(attr); - ASSERT(dentry); - ASSERT(req); + int result = 0; attr->requestType = opUsed; @@ -289,24 +292,25 @@ HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer * by name. */ requestV3->hints = 0; - if (allowHandleReuse && HgfsGetHandle(dentry->d_inode, + if (allowHandleReuse && HgfsGetHandle(fileInode, 0, &handle) == 0) { requestV3->fileName.flags = HGFS_FILE_NAME_USE_FILE_DESC; requestV3->fileName.fid = handle; requestV3->fileName.length = 0; requestV3->fileName.caseType = HGFS_FILE_NAME_DEFAULT_CASE; - fileName = NULL; + *fileName = NULL; + *fileNameLength = NULL; } else { - fileName = requestV3->fileName.name; - fileNameLength = &requestV3->fileName.length; + *fileName = requestV3->fileName.name; + *fileNameLength = &requestV3->fileName.length; requestV3->fileName.flags = 0; requestV3->fileName.fid = HGFS_INVALID_HANDLE; requestV3->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE; } requestV3->reserved = 0; - reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(requestV3); - reqBufferSize = HGFS_NAME_BUFFER_SIZET(req->bufferSize, reqSize); + *reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(requestV3); + *reqBufferSize = HGFS_NAME_BUFFER_SIZET(req->bufferSize, *reqSize); break; } @@ -323,19 +327,20 @@ HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer * correct regardless. If we don't find a handle, fall back on getattr * by name. */ - if (allowHandleReuse && HgfsGetHandle(dentry->d_inode, + if (allowHandleReuse && HgfsGetHandle(fileInode, 0, &handle) == 0) { requestV2->hints = HGFS_ATTR_HINT_USE_FILE_DESC; requestV2->file = handle; - fileName = NULL; + *fileName = NULL; + *fileNameLength = NULL; } else { requestV2->hints = 0; - fileName = requestV2->fileName.name; - fileNameLength = &requestV2->fileName.length; + *fileName = requestV2->fileName.name; + *fileNameLength = &requestV2->fileName.length; } - reqSize = sizeof *requestV2; - reqBufferSize = HGFS_NAME_BUFFER_SIZE(req->bufferSize, requestV2); + *reqSize = sizeof *requestV2; + *reqBufferSize = HGFS_NAME_BUFFER_SIZE(req->bufferSize, requestV2); break; } @@ -346,17 +351,67 @@ HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer requestV1->header.op = opUsed; requestV1->header.id = req->id; - fileName = requestV1->fileName.name; - fileNameLength = &requestV1->fileName.length; - reqSize = sizeof *requestV1; - reqBufferSize = HGFS_NAME_BUFFER_SIZE(req->bufferSize, requestV1); + *fileName = requestV1->fileName.name; + *fileNameLength = &requestV1->fileName.length; + *reqSize = sizeof *requestV1; + *reqBufferSize = HGFS_NAME_BUFFER_SIZE(req->bufferSize, requestV1); break; } default: - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackGetattrRequest: unexpected " - "OP type encountered\n")); + LOG(4, (KERN_DEBUG "VMware hgfs: %s: unexpected OP type encountered\n", __func__)); result = -EPROTO; + break; + } + + return result; +} + + +/* + *---------------------------------------------------------------------- + * + * HgfsPackGetattrRequest -- + * + * Setup the getattr request, depending on the op version. When possible, + * we will issue the getattr using an existing open HGFS handle. + * + * Results: + * Returns zero on success, or negative error on failure. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +static int +HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer + HgfsOp opUsed, // IN: Op to be used + Bool allowHandleReuse, // IN: Can we use a handle? + struct dentry *dentry, // IN: Dentry containing name + HgfsAttrInfo *attr) // OUT: Attrs to update +{ + size_t reqBufferSize; + size_t reqSize; + char *fileName = NULL; + uint32 *fileNameLength = NULL; + int result = 0; + + ASSERT(attr); + ASSERT(dentry); + ASSERT(req); + + result = HgfsPackCommonattr(req, + opUsed, + allowHandleReuse, + dentry->d_inode, + &reqSize, + &reqBufferSize, + &fileName, + &fileNameLength, + attr); + if (0 > result) { goto out; } @@ -366,29 +421,112 @@ HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer /* Build full name to send to server. */ if (HgfsBuildPath(fileName, reqBufferSize, dentry) < 0) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackGetattrRequest: build path " - "failed\n")); + LOG(4, (KERN_DEBUG "VMware hgfs: %s: build path failed\n", __func__)); result = -EINVAL; goto out; } - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsPackGetattrRequest: getting attrs " - "for \"%s\"\n", fileName)); + LOG(6, (KERN_DEBUG "VMware hgfs: %s: getting attrs for \"%s\"\n", + __func__, fileName)); /* Convert to CP name. */ result = CPName_ConvertTo(fileName, reqBufferSize, fileName); if (result < 0) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackGetattrRequest: CP " - "conversion failed\n")); + LOG(4, (KERN_DEBUG "VMware hgfs: %s: CP conversion failed\n", __func__)); result = -EINVAL; goto out; } *fileNameLength = result; } + req->payloadSize = reqSize + result; result = 0; + +out: + return result; +} + + +/* + *---------------------------------------------------------------------- + * + * HgfsPackGetattrRootRequest -- + * + * Setup the getattr request for the root of the HGFS file system. + * + * When possible, we will issue the getattr using an existing open HGFS handle. + * + * Results: + * Returns zero on success, or negative error on failure. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +static int +HgfsPackGetattrRootRequest(HgfsReq *req, // IN/OUT: Request buffer + HgfsOp opUsed, // IN: Op to be used + struct super_block *sb, // IN: Super block entry + HgfsAttrInfo *attr) // OUT: Attrs to update +{ + size_t reqBufferSize; + size_t reqSize; + char *fileName = NULL; + uint32 *fileNameLength = NULL; + int result = 0; + + ASSERT(attr); + ASSERT(sb); + ASSERT(req); + + result = HgfsPackCommonattr(req, + opUsed, + FALSE, + NULL, + &reqSize, + &reqBufferSize, + &fileName, + &fileNameLength, + attr); + if (0 > result) { + goto out; + } + + /* Avoid all this extra work when we're doing a getattr by handle. */ + if (fileName != NULL) { + HgfsSuperInfo *si = HGFS_SB_TO_COMMON(sb); + + /* Build full name to send to server. */ + if (HgfsBuildRootPath(fileName, + reqBufferSize, + si) < 0) { + LOG(4, (KERN_DEBUG "VMware hgfs: %s: build path failed\n", __func__)); + result = -EINVAL; + goto out; + } + LOG(6, (KERN_DEBUG "VMware hgfs: %s: getting attrs for \"%s\"\n", + __func__, fileName)); + + /* Convert to CP name. */ + result = CPName_ConvertTo(fileName, + reqBufferSize, + fileName); + if (result < 0) { + LOG(4, (KERN_DEBUG "VMware hgfs: %s: CP conversion failed\n", __func__)); + result = -EINVAL; + goto out; + } + + *fileNameLength = result; + } + + req->payloadSize = reqSize + result; + result = 0; + out: return result; } @@ -548,7 +686,7 @@ HgfsUnpackCommonAttr(HgfsReq *req, // IN: Reply packet /* *---------------------------------------------------------------------- * - * HgfsChangeFileAttributes -- + * HgfsCalcBlockSize -- * * Calculate the number of 512 byte blocks used. * @@ -565,6 +703,7 @@ HgfsUnpackCommonAttr(HgfsReq *req, // IN: Reply packet * *---------------------------------------------------------------------- */ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17) static inline blkcnt_t HgfsCalcBlockSize(uint64 tsize) @@ -585,6 +724,69 @@ HgfsCalcBlockSize(uint64 tsize) /* *---------------------------------------------------------------------- * + * HgfsSetInodeUidGid -- + * + * Set the UID and GID of the inode. + * + * Update an inode's UID and GID to match those of the HgfsAttr returned + * by the server. + * + * Results: + * The number of 512 byte blocks for the size. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +HgfsSetInodeUidGid(struct inode *inode, // IN/OUT: Inode + HgfsSuperInfo *si, // IN: New attrs + HgfsAttrInfo const *attr) // IN: New attrs +{ + /* + * Use the stored uid and gid if we were given them at mount-time, or if + * the server didn't give us a uid or gid. + */ + if (si->uidSet || (attr->mask & HGFS_ATTR_VALID_USERID) == 0) { + inode->i_uid = si->uid; + } else { + kuid_t attrUid = make_kuid(&init_user_ns, attr->userId); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + if (uid_valid(attrUid)) { + inode->i_uid = attrUid; + } else { + inode->i_uid = si->uid; + } +#else + inode->i_uid = attrUid; +#endif + LOG(6, (KERN_DEBUG "VMware hgfs: %s: inode uid %u\n", + __func__, from_kuid(&init_user_ns, inode->i_uid))); + } + if (si->gidSet || (attr->mask & HGFS_ATTR_VALID_GROUPID) == 0) { + inode->i_gid = si->gid; + } else { + kgid_t attrGid = make_kgid(&init_user_ns, attr->groupId); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + if (gid_valid(attrGid)) { + inode->i_gid = attrGid; + } else { + inode->i_gid = si->gid; + } +#else + inode->i_gid = attrGid; +#endif + LOG(6, (KERN_DEBUG "VMware hgfs: %s: inode gid %u\n", + __func__, from_kgid(&init_user_ns, inode->i_gid))); + } +} + + +/* + *---------------------------------------------------------------------- + * * HgfsChangeFileAttributes -- * * Update an inode's attributes to match those of the HgfsAttr. May @@ -674,20 +876,7 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode */ set_nlink(inode, 1); - /* - * Use the stored uid and gid if we were given them at mount-time, or if - * the server didn't give us a uid or gid. - */ - if (si->uidSet || (attr->mask & HGFS_ATTR_VALID_USERID) == 0) { - inode->i_uid = si->uid; - } else { - inode->i_uid = attr->userId; - } - if (si->gidSet || (attr->mask & HGFS_ATTR_VALID_GROUPID) == 0) { - inode->i_gid = si->gid; - } else { - inode->i_gid = attr->groupId; - } + HgfsSetInodeUidGid(inode, si, attr); inode->i_rdev = 0; /* Device nodes are not supported */ #if !defined VMW_INODE_2618 @@ -768,17 +957,14 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode /* *---------------------------------------------------------------------- * - * HgfsPrivateGetattr -- + * HgfsCanRetryGetattrRequest -- * - * Internal getattr routine. Send a getattr request to the server - * for the indicated remote name, and if it succeeds copy the - * results of the getattr into the provided HgfsAttrInfo. - * - * fileName (if supplied) will be set to a newly allocated string - * if the file is a symlink; it's the caller's duty to free it. + * Checks the getattr request version and downgrades the global getattr + * version if we can. * * Results: - * Returns zero on success, or a negative error on failure. + * Returns TRUE on success and downgrades the global getattr protocol version, + * or FALSE if no retry is possible. * * Side effects: * None @@ -786,42 +972,60 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode *---------------------------------------------------------------------- */ -int -HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name - HgfsAttrInfo *attr, // OUT: Attr to copy into - char **fileName) // OUT: pointer to allocated file name +static Bool +HgfsCanRetryGetattrRequest(HgfsOp getattrOp) // IN: getattrOp version used { - HgfsReq *req; - HgfsStatus replyStatus; - HgfsOp opUsed; - int result = 0; - Bool allowHandleReuse = TRUE; + Bool canRetry = FALSE; + + /* Retry with older version(s). Set globally. */ + if (getattrOp == HGFS_OP_GETATTR_V3) { + LOG(4, (KERN_DEBUG "VMware hgfs: %s: Version 3 " + "not supported. Falling back to version 2.\n", __func__)); + hgfsVersionGetattr = HGFS_OP_GETATTR_V2; + canRetry = TRUE; + } else if (getattrOp == HGFS_OP_GETATTR_V2) { + LOG(4, (KERN_DEBUG "VMware hgfs: %s: Version 2 " + "not supported. Falling back to version 1.\n", __func__)); + hgfsVersionGetattr = HGFS_OP_GETATTR; + canRetry = TRUE; + } + return canRetry; +} - ASSERT(dentry); - ASSERT(dentry->d_sb); - ASSERT(attr); - req = HgfsGetNewRequest(); - if (!req) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: out of memory " - "while getting new request\n")); - result = -ENOMEM; - goto out; - } +/* + *---------------------------------------------------------------------- + * + * HgfsSendGetattrRequest -- + * + * Send the getattr request and handle the reply. + * + * Results: + * Returns zero on success, or a negative error on failure. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ - retry: +int +HgfsSendGetattrRequest(HgfsReq *req, // IN: getattr request + Bool *doRetry, // OUT: Retry getattr request + Bool *allowHandleReuse, // IN/OUT: handle reuse + HgfsAttrInfo *attr, // OUT: Attr to copy into + char **fileName) // OUT: pointer to allocated file name +{ + int result; - opUsed = hgfsVersionGetattr; - result = HgfsPackGetattrRequest(req, dentry, allowHandleReuse, opUsed, attr); - if (result != 0) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: no attrs\n")); - goto out; - } + *doRetry = FALSE; result = HgfsSendRequest(req); if (result == 0) { - replyStatus = HgfsReplyStatus(req); + HgfsStatus replyStatus = HgfsReplyStatus(req); + result = HgfsStatusConvertToLinux(replyStatus); + LOG(6, (KERN_DEBUG "VMware hgfs: %s: reply status %d -> %d\n", __func__, replyStatus, result)); @@ -843,7 +1047,7 @@ HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name * and it doesn't display any valid shares too. So as a workaround, we * remap EIO to success and create minimal fake attributes. */ - LOG(1, (KERN_DEBUG "Hgfs:Server returned EIO on unknown file\n")); + LOG(1, (KERN_DEBUG "Hgfs: %s: Server returned EIO on unknown file\n", __func__)); /* Create fake attributes */ attr->mask = HGFS_ATTR_VALID_TYPE | HGFS_ATTR_VALID_SIZE; attr->type = HGFS_FILE_TYPE_DIRECTORY; @@ -860,9 +1064,9 @@ HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name * "goto retry" would cause an infinite loop. Instead, let's retry * with a getattr by name. */ - if (allowHandleReuse) { - allowHandleReuse = FALSE; - goto retry; + if (*allowHandleReuse) { + *allowHandleReuse = FALSE; + *doRetry = TRUE; } /* @@ -874,30 +1078,143 @@ HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name case -EPROTO: /* Retry with older version(s). Set globally. */ - if (attr->requestType == HGFS_OP_GETATTR_V3) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: Version 3 " - "not supported. Falling back to version 2.\n")); - hgfsVersionGetattr = HGFS_OP_GETATTR_V2; - goto retry; - } else if (attr->requestType == HGFS_OP_GETATTR_V2) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: Version 2 " - "not supported. Falling back to version 1.\n")); - hgfsVersionGetattr = HGFS_OP_GETATTR; - goto retry; + if (HgfsCanRetryGetattrRequest(attr->requestType)) { + *doRetry = TRUE; } + break; - /* Fallthrough. */ default: break; } } else if (result == -EIO) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: timed out\n")); + LOG(4, (KERN_DEBUG "VMware hgfs: %s: timed out\n", __func__)); } else if (result == -EPROTO) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: server " - "returned error: %d\n", result)); + LOG(4, (KERN_DEBUG "VMware hgfs: %s: protocol error: %d\n", + __func__, result)); } else { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: unknown error: " - "%d\n", result)); + LOG(4, (KERN_DEBUG "VMware hgfs: %s: unknown error: %d\n", + __func__, result)); + } + + return result; +} + + +/* + *---------------------------------------------------------------------- + * + * HgfsPrivateGetattrRoot -- + * + * The getattr for the root. Send a getattr request to the server + * for the indicated remote name, and if it succeeds copy the + * results of the getattr into the provided HgfsAttrInfo. + * + * fileName (of the root) will be set to a newly allocated string. + * + * Results: + * Returns zero on success, or a negative error on failure. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +int +HgfsPrivateGetattrRoot(struct super_block *sb, // IN: Super block object + HgfsAttrInfo *attr) // OUT: Attr to copy into +{ + HgfsReq *req; + HgfsOp opUsed; + int result = 0; + Bool doRetry; + Bool allowHandleReuse = FALSE; + + ASSERT(sb); + ASSERT(attr); + + req = HgfsGetNewRequest(); + if (!req) { + LOG(4, (KERN_DEBUG "VMware hgfs: %s: out of memory " + "while getting new request\n", __func__)); + result = -ENOMEM; + goto out; + } + +retry: + opUsed = hgfsVersionGetattr; + result = HgfsPackGetattrRootRequest(req, opUsed, sb, attr); + if (result != 0) { + LOG(4, (KERN_DEBUG "VMware hgfs: %s: no attrs\n", __func__)); + goto out; + } + + result = HgfsSendGetattrRequest(req, &doRetry, &allowHandleReuse, attr, NULL); + if (0 != result && doRetry) { + goto retry; + } + +out: + HgfsFreeRequest(req); + return result; +} + + +/* + *---------------------------------------------------------------------- + * + * HgfsPrivateGetattr -- + * + * Internal getattr routine. Send a getattr request to the server + * for the indicated remote name, and if it succeeds copy the + * results of the getattr into the provided HgfsAttrInfo. + * + * fileName (if supplied) will be set to a newly allocated string + * if the file is a symlink; it's the caller's duty to free it. + * + * Results: + * Returns zero on success, or a negative error on failure. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +int +HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name + HgfsAttrInfo *attr, // OUT: Attr to copy into + char **fileName) // OUT: pointer to allocated file name +{ + HgfsReq *req; + HgfsOp opUsed; + int result = 0; + Bool doRetry; + Bool allowHandleReuse = TRUE; + + ASSERT(dentry); + ASSERT(dentry->d_sb); + ASSERT(attr); + + req = HgfsGetNewRequest(); + if (!req) { + LOG(4, (KERN_DEBUG "VMware hgfs: %s: out of memory " + "while getting new request\n", __func__)); + result = -ENOMEM; + goto out; + } + +retry: + opUsed = hgfsVersionGetattr; + result = HgfsPackGetattrRequest(req, opUsed, allowHandleReuse, dentry, attr); + if (result != 0) { + LOG(4, (KERN_DEBUG "VMware hgfs: %s: no attrs\n", __func__)); + goto out; + } + + result = HgfsSendGetattrRequest(req, &doRetry, &allowHandleReuse, attr, fileName); + if (0 != result && doRetry) { + goto retry; } out: @@ -1053,6 +1370,108 @@ HgfsIget(struct super_block *sb, // IN: Superblock of this fs /* *----------------------------------------------------------------------------- * + * HgfsInstantiateRoot -- + * + * Gets the root dentry for a given super block. + * + * Results: + * zero and a valid root dentry on success + * negative value on failure + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +int +HgfsInstantiateRoot(struct super_block *sb, // IN: Super block object + struct dentry **rootDentry) // OUT: Root dentry +{ + int result = -ENOMEM; + struct inode *rootInode; + struct dentry *tempRootDentry = NULL; + struct HgfsAttrInfo rootDentryAttr; + HgfsInodeInfo *iinfo; + + ASSERT(sb); + ASSERT(rootDentry); + + LOG(6, (KERN_DEBUG "VMware hgfs: %s: entered\n", __func__)); + + rootInode = HgfsGetInode(sb, HGFS_ROOT_INO); + if (rootInode == NULL) { + LOG(6, (KERN_DEBUG "VMware hgfs: %s: Could not get the root inode\n", + __func__)); + goto exit; + } + + /* + * On an allocation failure in read_super, the inode will have been + * marked "bad". If it was, we certainly don't want to start playing with + * the HgfsInodeInfo. So quietly put the inode back and fail. + */ + if (is_bad_inode(rootInode)) { + LOG(6, (KERN_DEBUG "VMware hgfs: %s: encountered bad inode\n", + __func__)); + goto exit; + } + + LOG(8, (KERN_DEBUG "VMware hgfs: %s: retrieve root attrs\n", __func__)); + result = HgfsPrivateGetattrRoot(sb, &rootDentryAttr); + if (result) { + LOG(4, (KERN_WARNING "VMware hgfs: %s: Could not the root attrs\n", __func__)); + goto exit; + } + + iinfo = INODE_GET_II_P(rootInode); + iinfo->isFakeInodeNumber = FALSE; + iinfo->isReferencedInode = TRUE; + + if (rootDentryAttr.mask & HGFS_ATTR_VALID_FILEID) { + iinfo->hostFileId = rootDentryAttr.hostFileId; + } + + HgfsChangeFileAttributes(rootInode, &rootDentryAttr); + + /* + * Now the initialization of the inode is complete we can create + * the root dentry which has flags initialized from the inode itself. + */ + tempRootDentry = d_make_root(rootInode); + /* + * d_make_root() does iput() on failure; if d_make_root() completes + * successfully then subsequent dput() will do iput() for us, so we + * should just ignore root inode from now on. + */ + rootInode = NULL; + + if (tempRootDentry == NULL) { + LOG(4, (KERN_WARNING "VMware hgfs: %s: Could not get " + "root dentry\n", __func__)); + goto exit; + } + + HgfsDentryAgeReset(tempRootDentry); + tempRootDentry->d_op = &HgfsDentryOperations; + + *rootDentry = tempRootDentry; + result = 0; + + LOG(6, (KERN_DEBUG "VMware hgfs: %s: finished\n", __func__)); +exit: + if (result) { + iput(rootInode); + dput(tempRootDentry); + *rootDentry = NULL; + } + return result; +} + + +/* + *----------------------------------------------------------------------------- + * * HgfsInstantiate -- * * Tie a dentry to a looked up or created inode. Callers may choose to @@ -1117,6 +1536,45 @@ HgfsInstantiate(struct dentry *dentry, // IN: Dentry to use /* *----------------------------------------------------------------------------- * + * HgfsBuildRootPath -- + * + * Constructs the root path given the super info. + * + * Results: + * If non-negative, the length of the buffer written. + * Otherwise, an error code. + * + * Side effects: + * None + * + *----------------------------------------------------------------------------- + */ + +int +HgfsBuildRootPath(char *buffer, // IN/OUT: Buffer to write into + size_t bufferLen, // IN: Size of buffer + HgfsSuperInfo *si) // IN: First dentry to walk +{ + size_t shortestNameLength; + /* + * Buffer must hold at least the share name (which is already prefixed with + * a forward slash), and nul. + */ + shortestNameLength = si->shareNameLen + 1; + if (bufferLen < shortestNameLength) { + return -ENAMETOOLONG; + } + memcpy(buffer, si->shareName, shortestNameLength); + + /* Short-circuit if we're at the root already. */ + LOG(4, (KERN_DEBUG "VMware hgfs: %s: root path \"%s\"\n", __func__, buffer)); + return shortestNameLength; +} + + +/* + *----------------------------------------------------------------------------- + * * HgfsBuildPath -- * * Constructs the full path given a dentry by walking the dentry and its @@ -1138,7 +1596,7 @@ HgfsBuildPath(char *buffer, // IN/OUT: Buffer to write into size_t bufferLen, // IN: Size of buffer struct dentry *dentry) // IN: First dentry to walk { - int retval = 0; + int retval; size_t shortestNameLength; HgfsSuperInfo *si; @@ -1148,26 +1606,23 @@ HgfsBuildPath(char *buffer, // IN/OUT: Buffer to write into si = HGFS_SB_TO_COMMON(dentry->d_sb); - /* - * Buffer must hold at least the share name (which is already prefixed with - * a forward slash), and nul. - */ - shortestNameLength = si->shareNameLen + 1; - if (bufferLen < shortestNameLength) { - return -ENAMETOOLONG; + retval = HgfsBuildRootPath(buffer, bufferLen, si); + if (0 > retval) { + return retval; } - memcpy(buffer, si->shareName, shortestNameLength); /* Short-circuit if we're at the root already. */ if (IS_ROOT(dentry)) { LOG(4, (KERN_DEBUG "VMware hgfs: HgfsBuildPath: Sending root \"%s\"\n", buffer)); - return shortestNameLength; + return retval; } /* Skip the share name, but overwrite our previous nul. */ + shortestNameLength = retval; buffer += shortestNameLength - 1; bufferLen -= shortestNameLength - 1; + retval = 0; /* * Build the path string walking the tree backward from end to ROOT @@ -1499,6 +1954,7 @@ HgfsCreateFileInfo(struct file *file, // IN: File pointer to attach to /* So that readdir() reissues open request */ fileInfo->isStale = TRUE; + fileInfo->direntPos = 0; /* * I don't think we need any VFS locks since we're only touching the HGFS @@ -1747,11 +2203,13 @@ HgfsStatusConvertToLinux(HgfsStatus hgfsStatus) // IN: Status code to convert void HgfsSetUidGid(struct inode *parent, // IN: parent inode struct dentry *dentry, // IN: dentry of file to update - uid_t uid, // IN: uid to set - gid_t gid) // IN: gid to set + kuid_t uid, // IN: uid to set + kgid_t gid) // IN: gid to set { struct iattr setUidGid; + LOG(6, (KERN_DEBUG "VMware hgfs: %s: entered \n", __func__)); + setUidGid.ia_valid = ATTR_UID; setUidGid.ia_uid = uid; @@ -1775,6 +2233,8 @@ HgfsSetUidGid(struct inode *parent, // IN: parent inode HgfsDentryAgeForce(dentry); HgfsSetattr(dentry, &setUidGid); HgfsRevalidate(dentry); + + LOG(6, (KERN_DEBUG "VMware hgfs: %s: returns\n", __func__)); } diff --git a/open-vm-tools/modules/linux/vmhgfs/fsutil.h b/open-vm-tools/modules/linux/vmhgfs/fsutil.h index f332fb6d..ff15b15f 100644 --- a/open-vm-tools/modules/linux/vmhgfs/fsutil.h +++ b/open-vm-tools/modules/linux/vmhgfs/fsutil.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -32,6 +32,7 @@ #include <linux/signal.h> #include "compat_fs.h" +#include "module.h" /* For kuid_t kgid_t types. */ #include "inode.h" #include "request.h" #include "vm_basic_types.h" @@ -73,6 +74,8 @@ int HgfsPrivateGetattr(struct dentry *dentry, struct inode *HgfsIget(struct super_block *sb, ino_t ino, HgfsAttrInfo const *attr); +int HgfsInstantiateRoot(struct super_block *sb, + struct dentry **rootDentry); int HgfsInstantiate(struct dentry *dentry, ino_t ino, HgfsAttrInfo const *attr); @@ -92,8 +95,8 @@ int HgfsGetHandle(struct inode *inode, int HgfsStatusConvertToLinux(HgfsStatus hgfsStatus); void HgfsSetUidGid(struct inode *parent, struct dentry *dentry, - uid_t uid, - gid_t gid); + kuid_t uid, + kgid_t gid); struct inode *HgfsGetInode(struct super_block *sb, ino_t ino); void HgfsDoReadInode(struct inode *inode); diff --git a/open-vm-tools/modules/linux/vmhgfs/inode.c b/open-vm-tools/modules/linux/vmhgfs/inode.c index 2999b940..77b16691 100644 --- a/open-vm-tools/modules/linux/vmhgfs/inode.c +++ b/open-vm-tools/modules/linux/vmhgfs/inode.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -33,6 +33,7 @@ #include <linux/highmem.h> #include "compat_cred.h" +#include "compat_dcache.h" #include "compat_fs.h" #include "compat_kernel.h" #include "compat_mm.h" @@ -50,6 +51,23 @@ #include "fsutil.h" #include "vm_assert.h" + +#if defined VMW_DCOUNT_311 || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) +/* + * Linux Kernel versions that are version 3.11 version and newer or are compatible + * by having the d_count function replacement backported. + */ +#define hgfs_d_count(dentry) d_count(dentry) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) +/* + * Kernel versions that are not 3.11 version compatible or are just older will + * use the d_count field. + */ +#define hgfs_d_count(dentry) dentry->d_count +#else +#define hgfs_d_count(dentry) atomic_read(&dentry->d_count) +#endif + /* Private functions. */ static int HgfsDelete(struct inode *dir, struct dentry *dentry, @@ -429,6 +447,8 @@ HgfsPackSetattrRequest(struct iattr *iattr, // IN: Inode attrs to update from size_t reqBufferSize; size_t reqSize; int result = 0; + uid_t attrUid = -1; + gid_t attrGid = -1; ASSERT(iattr); ASSERT(dentry); @@ -437,6 +457,14 @@ HgfsPackSetattrRequest(struct iattr *iattr, // IN: Inode attrs to update from valid = iattr->ia_valid; + if (valid & ATTR_UID) { + attrUid = from_kuid(&init_user_ns, iattr->ia_uid); + } + + if (valid & ATTR_GID) { + attrGid = from_kgid(&init_user_ns, iattr->ia_gid); + } + switch (opUsed) { case HGFS_OP_SETATTR_V3: { HgfsRequest *requestHeader; @@ -513,13 +541,13 @@ HgfsPackSetattrRequest(struct iattr *iattr, // IN: Inode attrs to update from if (valid & ATTR_UID) { attrV2->mask |= HGFS_ATTR_VALID_USERID; - attrV2->userId = iattr->ia_uid; + attrV2->userId = attrUid; *changed = TRUE; } if (valid & ATTR_GID) { attrV2->mask |= HGFS_ATTR_VALID_GROUPID; - attrV2->groupId = iattr->ia_gid; + attrV2->groupId = attrGid; *changed = TRUE; } @@ -616,13 +644,13 @@ HgfsPackSetattrRequest(struct iattr *iattr, // IN: Inode attrs to update from if (valid & ATTR_UID) { attrV2->mask |= HGFS_ATTR_VALID_USERID; - attrV2->userId = iattr->ia_uid; + attrV2->userId = attrUid; *changed = TRUE; } if (valid & ATTR_GID) { attrV2->mask |= HGFS_ATTR_VALID_GROUPID; - attrV2->groupId = iattr->ia_gid; + attrV2->groupId = attrGid; *changed = TRUE; } @@ -1890,7 +1918,7 @@ HgfsPermission(struct inode *inode, #endif &inode->i_dentry, d_alias) { - int dcount = dentry->d_count; + int dcount = hgfs_d_count(dentry); if (dcount) { LOG(4, ("Found %s %d \n", dentry->d_name.name, dcount)); return HgfsAccessInt(dentry, mask & (MAY_READ | MAY_WRITE | MAY_EXEC)); @@ -1943,11 +1971,7 @@ HgfsPermission(struct inode *inode, list_for_each(pos, &inode->i_dentry) { int dcount; struct dentry *dentry = list_entry(pos, struct dentry, d_alias); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) - dcount = atomic_read(&dentry->d_count); -#else - dcount = dentry->d_count; -#endif + dcount = hgfs_d_count(dentry); if (dcount) { LOG(4, ("Found %s %d \n", (dentry)->d_name.name, dcount)); return HgfsAccessInt(dentry, mask & (MAY_READ | MAY_WRITE | MAY_EXEC)); diff --git a/open-vm-tools/modules/linux/vmhgfs/inode.h b/open-vm-tools/modules/linux/vmhgfs/inode.h index e5f758bb..c86f848d 100644 --- a/open-vm-tools/modules/linux/vmhgfs/inode.h +++ b/open-vm-tools/modules/linux/vmhgfs/inode.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/link.c b/open-vm-tools/modules/linux/vmhgfs/link.c index 65d8a237..06f693b9 100644 --- a/open-vm-tools/modules/linux/vmhgfs/link.c +++ b/open-vm-tools/modules/linux/vmhgfs/link.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -136,6 +136,13 @@ HgfsFollowlink(struct dentry *dentry, // IN: Dentry containing link #endif } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) +#define HGFS_DO_READLINK(dentry,buffer,buflen,fileName) \ + readlink_copy(buffer, buflen, fileName) +#else +#define HGFS_DO_READLINK(dentry,buffer,buflen,fileName) \ + vfs_readlink(dentry, buffer, buflen, fileName) +#endif /* *---------------------------------------------------------------------- @@ -185,7 +192,7 @@ HgfsReadlink(struct dentry *dentry, // IN: Dentry containing link } else { LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling vfs_readlink %s\n", __func__, fileName)); - error = vfs_readlink(dentry, buffer, buflen, fileName); + error = HGFS_DO_READLINK(dentry, buffer, buflen, fileName); LOG(6, (KERN_DEBUG "VMware hgfs: %s: vfs_readlink %s ret %dn", __func__, fileName, error)); } diff --git a/open-vm-tools/modules/linux/vmhgfs/module.c b/open-vm-tools/modules/linux/vmhgfs/module.c index 4bce943f..aa961283 100644 --- a/open-vm-tools/modules/linux/vmhgfs/module.c +++ b/open-vm-tools/modules/linux/vmhgfs/module.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/module.h b/open-vm-tools/modules/linux/vmhgfs/module.h index 911ba8b7..9c123323 100644 --- a/open-vm-tools/modules/linux/vmhgfs/module.h +++ b/open-vm-tools/modules/linux/vmhgfs/module.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -74,6 +74,17 @@ extern int LOGLEVEL_THRESHOLD; * Macros for accessing members that are private to this code in * sb/inode/file structs. */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) +typedef uid_t kuid_t; +typedef gid_t kgid_t; +#define from_kuid(_ns, _kuid) (_kuid) +#define from_kgid(_ns, _kgid) (_kgid) +#define make_kuid(_ns, _uid) (_uid) +#define make_kgid(_ns, _gid) (_gid) +#endif + + #define HGFS_SET_SB_TO_COMMON(sb, common) do { (sb)->s_fs_info = (common); } while (0) #define HGFS_SB_TO_COMMON(sb) ((HgfsSuperInfo *)(sb)->s_fs_info) @@ -110,9 +121,9 @@ extern int LOGLEVEL_THRESHOLD; /* Data kept in each superblock in sb->u. */ typedef struct HgfsSuperInfo { - uid_t uid; /* UID of user who mounted this fs. */ + kuid_t uid; /* UID of user who mounted this fs. */ + kgid_t gid; /* GID of user who mounted this fs. */ Bool uidSet; /* Was the UID specified at mount-time? */ - gid_t gid; /* GID of user who mounted this fs. */ Bool gidSet; /* Was the GID specified at mount-time? */ mode_t fmask; /* File permission mask. */ mode_t dmask; /* Directory permission mask. */ @@ -167,6 +178,9 @@ typedef struct HgfsFileInfo { */ Bool isStale; + /* Directory read position for tracking. */ + loff_t direntPos; + } HgfsFileInfo; diff --git a/open-vm-tools/modules/linux/vmhgfs/page.c b/open-vm-tools/modules/linux/vmhgfs/page.c index 387bc02f..56f98621 100644 --- a/open-vm-tools/modules/linux/vmhgfs/page.c +++ b/open-vm-tools/modules/linux/vmhgfs/page.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/request.c b/open-vm-tools/modules/linux/vmhgfs/request.c index 71758371..dccf481e 100644 --- a/open-vm-tools/modules/linux/vmhgfs/request.c +++ b/open-vm-tools/modules/linux/vmhgfs/request.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/request.h b/open-vm-tools/modules/linux/vmhgfs/request.h index 055f857d..4303924b 100644 --- a/open-vm-tools/modules/linux/vmhgfs/request.h +++ b/open-vm-tools/modules/linux/vmhgfs/request.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/stubs.c b/open-vm-tools/modules/linux/vmhgfs/stubs.c index f79b7656..029d833c 100644 --- a/open-vm-tools/modules/linux/vmhgfs/stubs.c +++ b/open-vm-tools/modules/linux/vmhgfs/stubs.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/super.c b/open-vm-tools/modules/linux/vmhgfs/super.c index 1502513b..04a21920 100644 --- a/open-vm-tools/modules/linux/vmhgfs/super.c +++ b/open-vm-tools/modules/linux/vmhgfs/super.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmhgfs/transport.c b/open-vm-tools/modules/linux/vmhgfs/transport.c index a45e3e77..760ae7bf 100644 --- a/open-vm-tools/modules/linux/vmhgfs/transport.c +++ b/open-vm-tools/modules/linux/vmhgfs/transport.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2009 VMware, Inc. All rights reserved. + * Copyright (C) 2009-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -52,8 +52,6 @@ #include "transport.h" #include "vm_assert.h" -extern int USE_VMCI; - static HgfsTransportChannel *hgfsChannel; /* Current active channel. */ static compat_mutex_t hgfsChannelLock; /* Lock to protect hgfsChannel. */ static struct list_head hgfsRepPending; /* Reply pending queue. */ @@ -156,17 +154,6 @@ HgfsTransportSetupNewChannel(void) { HgfsTransportChannel *newChannel; - newChannel = HgfsGetVmciChannel(); - if (newChannel != NULL) { - if (HgfsTransportOpenChannel(newChannel)) { - hgfsChannel = newChannel; - LOG(10, ("CHANNEL: Vmci channel\n")); - return TRUE; - } - } - - USE_VMCI = 0; - newChannel = HgfsGetBdChannel(); LOG(10, ("CHANNEL: Bd channel\n")); ASSERT(newChannel); diff --git a/open-vm-tools/modules/linux/vmhgfs/transport.h b/open-vm-tools/modules/linux/vmhgfs/transport.h index 7caac3e8..0c0c9542 100644 --- a/open-vm-tools/modules/linux/vmhgfs/transport.h +++ b/open-vm-tools/modules/linux/vmhgfs/transport.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2009 VMware, Inc. All rights reserved. + * Copyright (C) 2009-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -66,7 +66,6 @@ void HgfsTransportFinishRequest(HgfsReq *req, Bool success, Bool do_put); void HgfsTransportFlushRequests(void); void HgfsTransportMarkDead(void); -HgfsTransportChannel* HgfsGetVmciChannel(void); HgfsTransportChannel *HgfsGetBdChannel(void); #endif // _HGFS_DRIVER_TRANSPORT_H_ diff --git a/open-vm-tools/modules/linux/vmhgfs/vmci.c b/open-vm-tools/modules/linux/vmhgfs/vmci.c deleted file mode 100644 index 027fec77..00000000 --- a/open-vm-tools/modules/linux/vmhgfs/vmci.c +++ /dev/null @@ -1,815 +0,0 @@ -/********************************************************* - * Copyright (C) 2010 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *********************************************************/ - -/* - * vmci.c -- - * - * Provides VMCI transport channel to the HGFS client. - */ - -/* Must come before any kernel header file. */ -#include "driver-config.h" - -#include <linux/errno.h> -#include <linux/moduleparam.h> -#include <linux/interrupt.h> /* for spin_lock_bh */ -#include <asm/io.h> - -#include "compat_mm.h" -#include "hgfsProto.h" -#include "hgfsTransport.h" -#include "module.h" -#include "request.h" -#include "transport.h" -#include "vm_assert.h" -#include "vmci_call_defs.h" -#include "vmci_defs.h" -#include "vmciKernelAPI1.h" - -static Bool HgfsVmciChannelOpen(HgfsTransportChannel *channel); -static void HgfsVmciChannelClose(HgfsTransportChannel *channel); -static HgfsReq * HgfsVmciChannelAllocate(size_t payloadSize); -void HgfsVmciChannelFree(HgfsReq *req); -static int HgfsVmciChannelSend(HgfsTransportChannel *channel, HgfsReq *req); -static void HgfsRequestAsyncDispatch(char *payload, uint32 size); - -int USE_VMCI = 0; -module_param(USE_VMCI, int, 0444); - -static HgfsTransportChannel channel = { - .name = "vmci", - .ops.open = HgfsVmciChannelOpen, - .ops.close = HgfsVmciChannelClose, - .ops.allocate = HgfsVmciChannelAllocate, - .ops.free = HgfsVmciChannelFree, - .ops.send = HgfsVmciChannelSend, - .priv = NULL, - .status = HGFS_CHANNEL_NOTCONNECTED -}; - -static spinlock_t vmciRequestProcessLock; - -typedef struct HgfsShmemPage { - uint64 va; - uint64 pa; - Bool free; -} HgfsShmemPage; - -typedef struct HgfsShmemPages { - HgfsShmemPage *list; - uint32 totalPageCount; - uint32 freePageCount; -} HgfsShmemPages; - -HgfsShmemPages gHgfsShmemPages; -#define HGFS_VMCI_SHMEM_PAGES (16) - - -/* - *---------------------------------------------------------------------- - * - * HgfsRequestAsyncDispatch -- - * - * XXX Main dispatcher function. Currently just a stub. Needs to run - * in atomic context. - * - * Results: - * None - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -static void -HgfsRequestAsyncDispatch(char *payload, // IN: request header - uint32 size) // IN: size of payload -{ - HgfsRequest *reqHeader = (HgfsRequest *)payload; - - LOG(4, (KERN_WARNING "Size in Dispatch %u\n", size)); - - switch (reqHeader->op) { - case HGFS_OP_NOTIFY_V4: { - LOG(4, (KERN_WARNING "Calling HGFS_OP_NOTIFY_V4 dispatch function\n")); - break; - } - default: - LOG(4, (KERN_WARNING "%s: Unknown opcode = %d", __func__, reqHeader->op)); - } -} - - -/* - *---------------------------------------------------------------------- - * - * HgfsRequestAsyncShmemDispatch -- - * - * Shared memory dispatcher. It extracts packets from the shared - * memory and dispatches to the main hgfs dispatcher function. When - * the buffer is larger than 4K, we may fail do deliver notifications. - * Main dispatcher function should run in atomic context. - * - * Results: - * None - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -static void -HgfsRequestAsyncShmemDispatch(HgfsAsyncIov *iov, // IN: request vectors - uint32 count) // IN: number of iovs -{ - uint32 i; - char *buf = NULL; - uint32 size = 0; - Bool chainStarted = FALSE; - uint32 offset = 0; - uint32 copySize; - uint64 prevIndex = -1; - uint64 currIndex; - size_t va; - - LOG(10, (KERN_WARNING "%s count = %u\n",__FUNCTION__, count)); - - /* - * When requests cross 4K boundary we have to chain pages together - * since guest passes 4k pages to the host. Here is how chaining works - * - * - All the vectors except the last one in the chain sets iov[].chain - * to TRUE. - * - Every iov[].len field indicates remaining bytes. So the first - * vector will contain total size of the request while the last vector - * will contain only size of data present in last vector. - */ - - for (i = 0; i < count; i++) { - va = (size_t)iov[i].va; - currIndex = iov[i].index; - - if (LIKELY(!iov[i].chain)) { - /* When the chain ends we dispatch the datagram.*/ - if (!chainStarted) { - buf = (char *)va; - LOG(8, (KERN_WARNING " Chain wasn't started...\n")); - size = iov[i].len; - } else { - memcpy(buf + offset, (char *)va, iov[i].len); - } - ASSERT(buf && size); - HgfsRequestAsyncDispatch(buf, size); - if (chainStarted) { - /* Well chain just ended, we shall free the buffer. */ - chainStarted = FALSE; - kfree(buf); - } - } else { - if (!chainStarted) { - LOG(8, (KERN_WARNING "Started chain ...\n")); - size = iov[i].len; - buf = kmalloc(size, GFP_ATOMIC); - ASSERT_DEVEL(buf); - if (!buf) { - /* Skip this notification, move onto next. */ - i += (size - 1) / PAGE_SIZE; - continue; - } - chainStarted = TRUE; - offset = 0; - } - copySize = MIN(iov[i].len, PAGE_SIZE); - memcpy(buf + offset, (char *)va, copySize); - offset += copySize; - } - - if (currIndex != prevIndex) { - /* This is new page. Mark is as free. */ - gHgfsShmemPages.list[currIndex].free = TRUE; - gHgfsShmemPages.freePageCount++; - } - prevIndex = currIndex; - } - - ASSERT(gHgfsShmemPages.freePageCount <= gHgfsShmemPages.totalPageCount); - LOG(8, (KERN_WARNING "Page count %u %u ...\n", gHgfsShmemPages.freePageCount, - gHgfsShmemPages.totalPageCount)); -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVmciChannelPassGuestPages -- - * - * Passes down free pages to the hgfs Server. HgfsServer will use this pages - * for sending change notification, oplock breaks etc. - * - * XXX It seems safe to call vmci_datagram_send in atomic context. - * - * Results: - * None - * - * Side effects: - * None - * - *----------------------------------------------------------------------------- - */ - -static Bool -HgfsVmciChannelPassGuestPages(HgfsTransportChannel *channel) // IN: -{ - Bool retVal = TRUE; - int ret; - int i; - int j = 0; - size_t transportHeaderSize; - HgfsVmciTransportHeader *transportHeader = NULL; - HgfsVmciHeaderNode *headerNode; - VMCIDatagram *dg; - - if (!gHgfsShmemPages.freePageCount) { - return TRUE; - } - - transportHeaderSize = sizeof (HgfsVmciTransportHeader) + - (gHgfsShmemPages.freePageCount - 1) * sizeof (HgfsAsyncIov); - - dg = kmalloc(sizeof *dg + transportHeaderSize, GFP_ATOMIC); - if (!dg) { - LOG(4, (KERN_WARNING "%s failed to allocate\n", __func__)); - retVal = FALSE; - goto exit; - } - - transportHeader = VMCI_DG_PAYLOAD(dg); - headerNode = &transportHeader->node; - - for (i = 0; i < gHgfsShmemPages.totalPageCount; i++) { - if (gHgfsShmemPages.list[i].free) { - transportHeader->asyncIov[j].index = i; - transportHeader->asyncIov[j].va = gHgfsShmemPages.list[i].va; - transportHeader->asyncIov[j].pa = gHgfsShmemPages.list[i].pa; - transportHeader->asyncIov[j].len = PAGE_SIZE; - j++; - } - } - - dg->src = *(VMCIHandle *)channel->priv; - dg->dst = VMCI_MAKE_HANDLE(VMCI_HYPERVISOR_CONTEXT_ID, VMCI_HGFS_TRANSPORT); - dg->payloadSize = transportHeaderSize; - - headerNode->version = HGFS_VMCI_VERSION_1; - headerNode->pktType = HGFS_TH_REP_GET_PAGES; - - ASSERT(gHgfsShmemPages.freePageCount == j); - transportHeader->iovCount = j; - - LOG(10, (KERN_WARNING "Sending %d Guest pages \n", i)); - if ((ret = vmci_datagram_send(dg)) < VMCI_SUCCESS) { - if (ret == HGFS_VMCI_TRANSPORT_ERROR) { - LOG(0, (KERN_WARNING "HGFS Transport error occured. Don't blame VMCI\n")); - } - retVal = FALSE; - } - -exit: - if (retVal) { - /* We successfully sent pages the the host. Mark all pages as allocated */ - for (i = 0; i < gHgfsShmemPages.totalPageCount; i++) { - gHgfsShmemPages.list[i].free = FALSE; - } - gHgfsShmemPages.freePageCount = 0; - } - kfree(dg); - return retVal; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVmciChannelCompleteRequest -- - * - * Completes the request that was serviced asynchronously by the server. - * - * Results: - * None - * - * Side effects: - * Request may be removed from the queue and sleeping thread is woken up. - * - *----------------------------------------------------------------------------- - */ - -void -HgfsVmciChannelCompleteRequest(uint64 id) // IN: Request ID -{ - HgfsVmciTransportStatus *transportStatus; - HgfsReq *req; - - spin_lock_bh(&vmciRequestProcessLock); - - /* Reference is taken here */ - req = HgfsTransportGetPendingRequest(id); - if (!req) { - LOG(0, (KERN_WARNING "No request with id %"FMT64"u \n", id)); - goto exit; - } - - transportStatus = (HgfsVmciTransportStatus *)req->buffer; - if (transportStatus->status != HGFS_TS_IO_COMPLETE) { - LOG(0, (KERN_WARNING "Request not completed with id %"FMT64"u \n", id)); - goto exit; - } - - /* Request is completed (yay!), let's remove it from the list */ - HgfsTransportRemovePendingRequest(req); - - req->payloadSize = transportStatus->size; - HgfsCompleteReq(req); - -exit: - if (req) { - /* Drop the reference taken in *GetPendingRequest */ - HgfsRequestPutRef(req); - } - spin_unlock_bh(&vmciRequestProcessLock); -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVmciChannelCallback -- - * - * Called when VMCI datagram is received. Note: This function runs inside - * tasklet. It means that this function cannot run concurrently with - * itself, thus it is safe to manipulate gHgfsShmemPages without locks. If this - * ever changes, please consider using appropriate locks. - * - * Results: - * 0 on Success, < 0 on Failure. - * - * Side effects: - * None - * - *----------------------------------------------------------------------------- - */ - -static int HgfsVmciChannelCallback(void *data, // IN: unused - VMCIDatagram *dg) // IN: datagram -{ - HgfsVmciAsyncReply *reply = (HgfsVmciAsyncReply *)VMCI_DG_PAYLOAD(dg); - HgfsVmciHeaderNode *replyNode = &reply->node; - HgfsTransportChannel *channel; - - LOG(10, (KERN_WARNING "Received VMCI channel Callback \n")); - - if (replyNode->version != HGFS_VMCI_VERSION_1) { - return HGFS_VMCI_VERSION_MISMATCH; - } - - switch (replyNode->pktType) { - - case HGFS_ASYNC_IOREP: - LOG(10, (KERN_WARNING "Received ID%"FMT64"x \n", reply->response.id)); - HgfsVmciChannelCompleteRequest(reply->response.id); - break; - - case HGFS_ASYNC_IOREQ_SHMEM: - HgfsRequestAsyncShmemDispatch(reply->shmem.iov, reply->shmem.count); - break; - - case HGFS_ASYNC_IOREQ_GET_PAGES: - channel = HgfsGetVmciChannel(); - LOG(10, (KERN_WARNING "Should send pages to the host\n")); - HgfsVmciChannelPassGuestPages(channel); - break; - - default: - ASSERT(0); - return HGFS_VMCI_TRANSPORT_ERROR; - } - - return 0; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVmciChannelOpen -- - * - * Opens VMCI channel and passes guest pages to the host. - * - * Results: - * TRUE on success, FALSE on failure. - * - * Side effects: - * None - * - *----------------------------------------------------------------------------- - */ - -static Bool -HgfsVmciChannelOpen(HgfsTransportChannel *channel) // IN: Channel -{ - int ret; - int i; - - ASSERT(channel->status == HGFS_CHANNEL_NOTCONNECTED); - ASSERT(channel->priv == NULL); - memset(&gHgfsShmemPages, 0, sizeof gHgfsShmemPages); - - if (USE_VMCI == 0) { - goto error; - } - - spin_lock_init(&vmciRequestProcessLock); - - channel->priv = kmalloc(sizeof(VMCIHandle), GFP_KERNEL); - if (!channel->priv) { - goto error; - } - - ret = vmci_datagram_create_handle( - VMCI_INVALID_ID, /* Resource ID */ - VMCI_FLAG_DG_NONE, /* Flags */ - HgfsVmciChannelCallback,/* Datagram Recv Callback */ - NULL, /* Callback data */ - channel->priv); /* VMCI outhandle */ - if (ret != VMCI_SUCCESS) { - LOG(1, (KERN_WARNING "Failed to create VMCI handle %d\n", ret)); - goto error; - } - - gHgfsShmemPages.list = kmalloc(sizeof *gHgfsShmemPages.list * HGFS_VMCI_SHMEM_PAGES, - GFP_KERNEL); - if (!gHgfsShmemPages.list) { - goto error; - } - - memset(gHgfsShmemPages.list, 0, sizeof *gHgfsShmemPages.list * HGFS_VMCI_SHMEM_PAGES); - - for (i = 0; i < HGFS_VMCI_SHMEM_PAGES; i++) { - gHgfsShmemPages.list[i].va = __get_free_page(GFP_KERNEL); - if (!gHgfsShmemPages.list[i].va) { - LOG(1, (KERN_WARNING "__get_free_page returned error \n")); - if (i == 0) { - /* Ouch. We failed on first call to __get_free_page */ - goto error; - } - /* It's ok. We can still send few pages to the host */ - break; - } - gHgfsShmemPages.list[i].pa = virt_to_phys((void *)(size_t)gHgfsShmemPages.list[i].va); - gHgfsShmemPages.list[i].free = TRUE; - } - - gHgfsShmemPages.totalPageCount = i; - gHgfsShmemPages.freePageCount = i; - - ret = HgfsVmciChannelPassGuestPages(channel); - if (!ret) { - for (i = 0; i < gHgfsShmemPages.totalPageCount; i++) { - LOG(1, (KERN_WARNING "Freeing pages\n")); - free_page(gHgfsShmemPages.list[i].va); - } - LOG(1, (KERN_WARNING "Failed to pass pages to the guest %d\n", ret)); - goto error; - } - - return TRUE; - -error: - kfree(gHgfsShmemPages.list); - kfree(channel->priv); - return FALSE; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVmciChannelTerminateSession -- - * - * Terminate session with the server. - * - * Results: - * 0 on success and < 0 on error. - * - * Side effects: - * None - * - *----------------------------------------------------------------------------- - */ - -static int -HgfsVmciChannelTerminateSession(HgfsTransportChannel *channel) { - - int ret = 0; - VMCIDatagram *dg; - HgfsVmciTransportHeader *transportHeader; - HgfsVmciHeaderNode *headerNode; - - dg = kmalloc(sizeof *dg + sizeof *transportHeader, GFP_KERNEL); - if (NULL == dg) { - LOG(4, (KERN_WARNING "%s failed to allocate\n", __func__)); - return -ENOMEM; - } - - /* Initialize datagram */ - dg->src = *(VMCIHandle *)channel->priv; - dg->dst = VMCI_MAKE_HANDLE(VMCI_HYPERVISOR_CONTEXT_ID, VMCI_HGFS_TRANSPORT); - dg->payloadSize = sizeof *transportHeader; - - transportHeader = VMCI_DG_PAYLOAD(dg); - headerNode = &transportHeader->node; - - headerNode->pktType = HGFS_TH_TERMINATE_SESSION; - headerNode->version = HGFS_VMCI_VERSION_1; - - transportHeader->iovCount = 0; - - LOG(1, (KERN_WARNING "Terminating session with host \n")); - if ((ret = vmci_datagram_send(dg)) < VMCI_SUCCESS) { - if (ret == HGFS_VMCI_TRANSPORT_ERROR) { - LOG(0, (KERN_WARNING "HGFS Transport error occured. Don't blame VMCI\n")); - } - LOG(0, (KERN_WARNING "Cannot communicate with Server.\n")); - } else { - int i; - for (i = 0; i < gHgfsShmemPages.totalPageCount; i++) { - free_page(gHgfsShmemPages.list[i].va); - } - } - - kfree(dg); - return ret; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVmciChannelClose -- - * - * Destroy vmci handle. - * - * Results: - * None - * - * Side effects: - * None - * - *----------------------------------------------------------------------------- - */ - -static void -HgfsVmciChannelClose(HgfsTransportChannel *channel) // IN: Channel -{ - ASSERT(channel->priv != NULL); - HgfsVmciChannelTerminateSession(channel); - vmci_datagram_destroy_handle(*(VMCIHandle *)channel->priv); - kfree(channel->priv); - kfree(gHgfsShmemPages.list); - channel->priv = NULL; - - LOG(8, ("VMware hgfs: %s: vmci closed.\n", __func__)); -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVmciChannelAllocate -- - * - * Allocate request in the way that is suitable for sending through - * vmci. Today, we just allocate a page for the request and we ignore - * payloadSize. We need this to support variable sized requests in future. - * - * Results: - * NULL on failure; otherwise address of the new request. - * - * Side effects: - * None - * - *----------------------------------------------------------------------------- - */ - -static HgfsReq * -HgfsVmciChannelAllocate(size_t payloadSize) // IN: Ignored -{ - HgfsReq *req = NULL; - const size_t size = PAGE_SIZE; - - req = kmalloc(size, GFP_KERNEL); - if (likely(req)) { - req->payload = req->buffer + sizeof (HgfsVmciTransportStatus); - req->bufferSize = size - sizeof (HgfsVmciTransportStatus) - sizeof *req; - } - - LOG(10, (KERN_WARNING "%s: Allocated Request\n", __func__)); - return req; -} - - -/* - *----------------------------------------------------------------------------- - * - * HgfsVmciChannelFree -- - * - * Free previously allocated request. - * - * Results: - * None. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -void -HgfsVmciChannelFree(HgfsReq *req) -{ - ASSERT(req); - kfree(req); -} - - -/* - *---------------------------------------------------------------------- - * - * HgfsVmciChannelSend -- - * - * Send a request via vmci. - * - * Results: - * 0 on success, negative error on failure. - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -static int -HgfsVmciChannelSend(HgfsTransportChannel *channel, // IN: Channel - HgfsReq *req) // IN: request to send -{ - int ret; - int iovCount = 0; - VMCIDatagram *dg; - HgfsVmciTransportHeader *transportHeader; - HgfsVmciHeaderNode *headerNode; - HgfsVmciTransportStatus *transportStatus; - size_t transportHeaderSize; - size_t bufferSize; - size_t total; - uint64 pa; - uint64 len; - uint64 id; - int j; - - ASSERT(req); - ASSERT(req->buffer); - ASSERT(req->state == HGFS_REQ_STATE_UNSENT || req->state == HGFS_REQ_STATE_ALLOCATED); - ASSERT(req->payloadSize <= req->bufferSize); - - /* Note that req->bufferSize does not include chunk used by the transport. */ - total = req->bufferSize + sizeof (HgfsVmciTransportStatus); - - /* Calculate number of entries for metaPacket */ - iovCount = (total + (size_t)req->buffer % PAGE_SIZE - 1)/ PAGE_SIZE + 1; - ASSERT(total + (size_t)req->buffer % PAGE_SIZE <= PAGE_SIZE); - - transportHeaderSize = sizeof *transportHeader + - (iovCount + req->numEntries - 1) * sizeof (HgfsIov); - dg = kmalloc(sizeof *dg + transportHeaderSize, GFP_KERNEL); - if (NULL == dg) { - LOG(4, (KERN_WARNING "%s failed to allocate\n", __func__)); - return -ENOMEM; - } - - /* Initialize datagram */ - dg->src = *(VMCIHandle *)channel->priv; - dg->dst = VMCI_MAKE_HANDLE(VMCI_HYPERVISOR_CONTEXT_ID, VMCI_HGFS_TRANSPORT); - dg->payloadSize = transportHeaderSize; - - transportHeader = VMCI_DG_PAYLOAD(dg); - headerNode = &transportHeader->node; - - headerNode->version = HGFS_VMCI_VERSION_1; - headerNode->pktType = HGFS_TH_REQUEST; - - total = req->bufferSize + sizeof (HgfsVmciTransportStatus); - bufferSize = 0; - for (iovCount = 0; bufferSize < req->bufferSize; iovCount++) { - /* - * req->buffer should have been allocated by kmalloc()/ __get_free_pages(). - * Specifically, it cannot be a buffer that is mapped from high memory. - * virt_to_phys() does not work for those. - */ - pa = virt_to_phys(req->buffer + bufferSize); - len = total < (PAGE_SIZE - pa % PAGE_SIZE) ? total : (PAGE_SIZE - pa % PAGE_SIZE); - bufferSize += len; - total -= len; - transportHeader->iov[iovCount].pa = pa; - transportHeader->iov[iovCount].len = len; - LOG(8, ("iovCount = %u PA = %"FMT64"x len=%u\n", iovCount, - transportHeader->iov[iovCount].pa, transportHeader->iov[iovCount].len)); - } - - /* Right now we do not expect discontigous request packet */ - ASSERT(iovCount == 1); - ASSERT(total == 0); - ASSERT(bufferSize == req->bufferSize + sizeof (HgfsVmciTransportStatus)); - - LOG(0, (KERN_WARNING "Size of request is %Zu\n", req->payloadSize)); - - for (j = 0; j < req->numEntries; j++, iovCount++) { - /* I will have to probably do page table walk here, haven't figured it out yet */ - ASSERT(req->dataPacket); - transportHeader->iov[iovCount].pa = page_to_phys(req->dataPacket[j].page); - transportHeader->iov[iovCount].pa += req->dataPacket[j].offset; - transportHeader->iov[iovCount].len = req->dataPacket[j].len; - LOG(8, ("iovCount = %u PA = %"FMT64"x len=%u\n", iovCount, - transportHeader->iov[iovCount].pa, - transportHeader->iov[iovCount].len)); - } - - transportHeader->iovCount = iovCount; - - /* Initialize transport Status */ - transportStatus = (HgfsVmciTransportStatus *)req->buffer; - transportStatus->status = HGFS_TS_IO_PENDING; - transportStatus->size = req->bufferSize + sizeof (HgfsVmciTransportStatus); - - /* - * Don't try to set req->state after vmci_datagram_send(). - * It may be too late then. We could have received a datagram by then and - * datagram handler expects request's state to be submitted. - */ - req->state = HGFS_REQ_STATE_SUBMITTED; - id = req->id; - - if ((ret = vmci_datagram_send(dg)) < VMCI_SUCCESS) { - if (ret == HGFS_VMCI_TRANSPORT_ERROR) { - LOG(0, (KERN_WARNING "HGFS Transport error occured. Don't blame VMCI\n")); - } else if (ret == HGFS_VMCI_VERSION_MISMATCH) { - LOG(0, (KERN_WARNING "Version mismatch\n")); - } - req->state = HGFS_REQ_STATE_UNSENT; - kfree(dg); - return -EIO; - } - - LOG(0, (KERN_WARNING "Hgfs Received response\n")); - HgfsVmciChannelCompleteRequest(id); - - kfree(dg); - return 0; -} - - -/* - *---------------------------------------------------------------------- - * - * HgfsGetVmciChannel -- - * - * Initialize Vmci channel. - * - * Results: - * Always return pointer to Vmci channel. - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -HgfsTransportChannel* -HgfsGetVmciChannel(void) -{ - return &channel; -} diff --git a/open-vm-tools/modules/linux/vmhgfs/vmhgfs_version.h b/open-vm-tools/modules/linux/vmhgfs/vmhgfs_version.h index 1ed35935..c5f19dcc 100644 --- a/open-vm-tools/modules/linux/vmhgfs/vmhgfs_version.h +++ b/open-vm-tools/modules/linux/vmhgfs/vmhgfs_version.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. + * Copyright (C) 2007-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmsync/Makefile b/open-vm-tools/modules/linux/vmsync/Makefile index 4d81760c..3c681a36 100644 --- a/open-vm-tools/modules/linux/vmsync/Makefile +++ b/open-vm-tools/modules/linux/vmsync/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/make -f ########################################################## -# Copyright (C) 1998 VMware, Inc. All rights reserved. +# Copyright (C) 1998-2015 VMware, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmxnet/Makefile b/open-vm-tools/modules/linux/vmxnet/Makefile index 4264b475..1c1bfd80 100644 --- a/open-vm-tools/modules/linux/vmxnet/Makefile +++ b/open-vm-tools/modules/linux/vmxnet/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/make -f ########################################################## -# Copyright (C) 1998 VMware, Inc. All rights reserved. +# Copyright (C) 1998-2015 VMware, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vmxnet/vmxnet.c b/open-vm-tools/modules/linux/vmxnet/vmxnet.c index 54b4590c..33afb9b9 100644 --- a/open-vm-tools/modules/linux/vmxnet/vmxnet.c +++ b/open-vm-tools/modules/linux/vmxnet/vmxnet.c @@ -80,10 +80,6 @@ static int vmxnet_close(struct net_device *dev); static void vmxnet_set_multicast_list(struct net_device *dev); static int vmxnet_set_mac_address(struct net_device *dev, void *addr); static struct net_device_stats *vmxnet_get_stats(struct net_device *dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) -static int vmxnet_set_features(struct net_device *netdev, compat_netdev_features_t - features); -#endif #if defined(HAVE_CHANGE_MTU) || defined(HAVE_NET_DEVICE_OPS) static int vmxnet_change_mtu(struct net_device *dev, int new_mtu); #endif @@ -992,14 +988,18 @@ vmxnet_probe_device(struct pci_dev *pdev, // IN: vmxnet PCI device const struct pci_device_id *id) // IN: matching device ID { #ifdef HAVE_NET_DEVICE_OPS + /* + * .ndo_set_features not required as existing initialization + * takes care of the necessary checks. The init routine appropriately + * sets netdev->hw_features after validating the device capabilities. + * ndo_set_features only required if driver is changing + * any other intenal variables besides the netdev->features. + */ static const struct net_device_ops vmxnet_netdev_ops = { .ndo_open = &vmxnet_open, .ndo_start_xmit = &vmxnet_start_tx, .ndo_stop = &vmxnet_close, .ndo_get_stats = &vmxnet_get_stats, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) - .ndo_set_features = vmxnet_set_features, -#endif #if COMPAT_LINUX_VERSION_CHECK_LT(3, 2, 0) .ndo_set_multicast_list = &vmxnet_set_multicast_list, #else @@ -1315,6 +1315,11 @@ vmxnet_probe_features(struct net_device *dev, // IN: } #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) + dev->features |= NETIF_F_RXCSUM; + printk( " rxCsum"); +#endif + #ifdef VMXNET_DO_ZERO_COPY if (lp->capabilities & VMNET_CAP_SG && lp->features & VMXNET_FEATURE_ZERO_COPY_TX){ @@ -1362,6 +1367,10 @@ vmxnet_probe_features(struct net_device *dev, // IN: #endif #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) + dev->hw_features = dev->features & (~NETIF_F_RXCSUM); +#endif + printk("\n"); /* check if this is enhanced vmxnet device */ @@ -3119,20 +3128,6 @@ vmxnet_get_stats(struct net_device *dev) return &lp->stats; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) -static int -vmxnet_set_features(struct net_device *netdev, compat_netdev_features_t features) -{ - compat_netdev_features_t changed = features ^ netdev->features; - - if (changed & (NETIF_F_RXCSUM)) { - if (features & NETIF_F_RXCSUM) - return 0; - } - return -1; -} -#endif - module_init(vmxnet_init); module_exit(vmxnet_exit); MODULE_DEVICE_TABLE(pci, vmxnet_chips); diff --git a/open-vm-tools/modules/linux/vmxnet/vmxnet_version.h b/open-vm-tools/modules/linux/vmxnet/vmxnet_version.h index a58bb408..fe2ad538 100644 --- a/open-vm-tools/modules/linux/vmxnet/vmxnet_version.h +++ b/open-vm-tools/modules/linux/vmxnet/vmxnet_version.h @@ -25,8 +25,8 @@ #ifndef _VMXNET_VERSION_H_ #define _VMXNET_VERSION_H_ -#define VMXNET_DRIVER_VERSION 2.0.15.0 -#define VMXNET_DRIVER_VERSION_COMMAS 2,0,15,0 -#define VMXNET_DRIVER_VERSION_STRING "2.0.15.0" +#define VMXNET_DRIVER_VERSION 2.1.0.0 +#define VMXNET_DRIVER_VERSION_COMMAS 2,1,0,0 +#define VMXNET_DRIVER_VERSION_STRING "2.1.0.0" #endif /* _VMXNET_VERSION_H_ */ diff --git a/open-vm-tools/modules/linux/vsock/Makefile b/open-vm-tools/modules/linux/vsock/Makefile index 852c9345..7549fa50 100644 --- a/open-vm-tools/modules/linux/vsock/Makefile +++ b/open-vm-tools/modules/linux/vsock/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/make -f ########################################################## -# Copyright (C) 1998 VMware, Inc. All rights reserved. +# Copyright (C) 1998-2015 VMware, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the diff --git a/open-vm-tools/modules/linux/vsock/Makefile.kernel b/open-vm-tools/modules/linux/vsock/Makefile.kernel index b4629eee..5218df2f 100644 --- a/open-vm-tools/modules/linux/vsock/Makefile.kernel +++ b/open-vm-tools/modules/linux/vsock/Makefile.kernel @@ -1,6 +1,6 @@ #!/usr/bin/make -f ########################################################## -# Copyright (C) 2007 VMware, Inc. All rights reserved. +# Copyright (C) 2007,2014 VMware, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -64,9 +64,9 @@ clean: prebuild:: ifneq ($(MODULEBUILDDIR),) ifeq ($(MODPOST_VMCI_SYMVERS),) - $(shell echo >&2 "Building VMCI Sockets without VMCI module symbols.") + $(shell echo >&2 "Building vSockets without VMCI module symbols.") else - $(shell echo >&2 "Building VMCI Sockets with VMCI module symbols.") + $(shell echo >&2 "Building vSockets with VMCI module symbols.") cp -f $(MODPOST_VMCI_SYMVERS) $(SRCROOT)/Module.symvers endif endif diff --git a/open-vm-tools/modules/linux/vsock/linux/af_vsock.c b/open-vm-tools/modules/linux/vsock/linux/af_vsock.c index e278e152..bde14970 100644 --- a/open-vm-tools/modules/linux/vsock/linux/af_vsock.c +++ b/open-vm-tools/modules/linux/vsock/linux/af_vsock.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2007-2011 VMware, Inc. All rights reserved. + * Copyright (C) 2007-2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -19,7 +19,7 @@ /* * af_vsock.c -- * - * Linux socket module for the VMCI Sockets protocol family. + * Linux socket module for the vSockets protocol family. */ @@ -591,7 +591,7 @@ VSockVmciAllowDgram(VSockVmciSock *vsock, // IN: Local socket * VMCISock_GetAFValue -- * * Kernel interface that allows external kernel modules to get the current - * VMCI Sockets address family. + * vSockets address family. * This version of the function is exported to kernel clients and should not * change. * @@ -613,7 +613,7 @@ VMCISock_GetAFValue(void) /* * Kernel clients are required to explicitly register themselves before they - * can use VMCI Sockets. + * can use vSockets. */ if (vsockVmciKernClientCount <= 0) { afvalue = -1; @@ -657,7 +657,7 @@ VMCISock_GetLocalCID(void) /* * Kernel clients are required to explicitly register themselves before they - * can use VMCI Sockets. + * can use vSockets. */ if (vsockVmciKernClientCount <= 0) { cid = -1; @@ -678,7 +678,7 @@ EXPORT_SYMBOL(VMCISock_GetLocalCID); * * VMCISock_KernelRegister -- * - * Allows a kernel client to register with VMCI Sockets. Must be called + * Allows a kernel client to register with vSockets. Must be called * before VMCISock_GetAFValue within a kernel module. Note that we don't * actually register the address family until the first time the module * needs to use it. @@ -707,7 +707,7 @@ EXPORT_SYMBOL(VMCISock_KernelRegister); * * VMCISock_KernelDeregister -- * - * Allows a kernel client to unregister with VMCI Sockets. Every call + * Allows a kernel client to unregister with vSockets. Every call * to VMCISock_KernRegister must be matched with a call to * VMCISock_KernUnregister. * @@ -3080,7 +3080,7 @@ VSockVmciQueueRcvSkb(struct sock *sk, // IN * * VSockVmciRegisterProto -- * - * Registers the vmci sockets protocol family. + * Registers the vSockets protocol family. * * Results: * Zero on success, error code on failure. @@ -3124,7 +3124,7 @@ VSockVmciRegisterProto(void) * * VSockVmciUnregisterProto -- * - * Unregisters the vmci sockets protocol family. + * Unregisters the vSockets protocol family. * * Results: * None. diff --git a/open-vm-tools/modules/linux/vsock/linux/af_vsock.h b/open-vm-tools/modules/linux/vsock/linux/af_vsock.h index 30600ae5..08e437d0 100644 --- a/open-vm-tools/modules/linux/vsock/linux/af_vsock.h +++ b/open-vm-tools/modules/linux/vsock/linux/af_vsock.h @@ -60,7 +60,11 @@ typedef struct VSockVmciSock { Bool trusted; Bool cachedPeerAllowDgram; /* Dgram communication allowed to cached peer? */ VMCIId cachedPeer; /* Context ID of last dgram destination check. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + kuid_t owner; +#else uid_t owner; +#endif VMCIHandle dgHandle; /* For SOCK_DGRAM only. */ /* Rest are SOCK_STREAM only. */ VMCIHandle qpHandle; diff --git a/open-vm-tools/modules/linux/vsock/linux/stats.h b/open-vm-tools/modules/linux/vsock/linux/stats.h index b47b3552..c42f5757 100644 --- a/open-vm-tools/modules/linux/vsock/linux/stats.h +++ b/open-vm-tools/modules/linux/vsock/linux/stats.h @@ -68,9 +68,9 @@ extern Atomic_uint64 vSockStatsProduceTotal; ++vSockStatsCtlPktCount[pktType]; \ } while (0) #define VSOCK_STATS_STREAM_CONSUME(bytes) \ - Atomic_FetchAndAdd64(&vSockStatsConsumeTotal, bytes) + Atomic_ReadAdd64(&vSockStatsConsumeTotal, bytes) #define VSOCK_STATS_STREAM_PRODUCE(bytes) \ - Atomic_FetchAndAdd64(&vSockStatsProduceTotal, bytes) + Atomic_ReadAdd64(&vSockStatsProduceTotal, bytes) #define VSOCK_STATS_CTLPKT_DUMP_ALL() VSockVmciStatsCtlPktDumpAll() #define VSOCK_STATS_HIST_DUMP_ALL() VSockVmciStatsHistDumpAll() #define VSOCK_STATS_TOTALS_DUMP_ALL() VSockVmciStatsTotalsDumpAll() diff --git a/open-vm-tools/modules/linux/vsock/linux/vmci_sockets_int.h b/open-vm-tools/modules/linux/vsock/linux/vmci_sockets_int.h index 4c5d9904..91654c34 100644 --- a/open-vm-tools/modules/linux/vsock/linux/vmci_sockets_int.h +++ b/open-vm-tools/modules/linux/vsock/linux/vmci_sockets_int.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2009 VMware, Inc. All rights reserved. + * Copyright (C) 2009,2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -19,7 +19,7 @@ /* * vmci_sockets_int.h -- * - * VMCI sockets private constants and types. + * vSockets private constants and types. * * This file is internal only, we do not ship the kernel interface yet. * You need to include this file *before* vmci_sockets.h in your kernel diff --git a/open-vm-tools/modules/linux/vsock/linux/vmci_sockets_packet.h b/open-vm-tools/modules/linux/vsock/linux/vmci_sockets_packet.h index 603835b5..abc42ade 100644 --- a/open-vm-tools/modules/linux/vsock/linux/vmci_sockets_packet.h +++ b/open-vm-tools/modules/linux/vsock/linux/vmci_sockets_packet.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2012 VMware, Inc. All rights reserved. + * Copyright (C) 2012,2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -19,7 +19,7 @@ /* * vmci_sockets_packet.h -- * - * Definition of VMCI Sockets packet format, constants, and types. + * Definition of vSockets packet format, constants, and types. */ #ifndef _VMCI_SOCKETS_PACKET_H_ @@ -108,51 +108,11 @@ typedef struct VSockPacket { } VSockPacket; /* - * SEQPACKET packets. - */ - -#define VSOCK_SEQ_PACKET_VERSION_1 1 -#define VSOCK_SEQ_PACKET_VERSION VSOCK_SEQ_PACKET_VERSION_1 - -/* Get the packet's payload size in bytes. */ -#define VSOCK_SEQ_PACKET_PAYLOAD_SIZE(_pkt) \ - (VMCI_DG_SIZE(&(_pkt)->hdr.dg) - (_pkt)->hdr.offset) - -/* Get a pointer to the packet's payload. */ -#define VSOCK_SEQ_PACKET_PAYLOAD(_pkt) \ - (void *)((char *)_pkt + (_pkt)->hdr.offset) - -typedef enum VSockSeqPacketType { - VSOCK_SEQ_PACKET_TYPE_INVALID = 0, // Invalid type. - VSOCK_SEQ_PACKET_TYPE_CONNECT, // Connection request. - VSOCK_SEQ_PACKET_TYPE_DATA, // Data. - VSOCK_SEQ_PACKET_TYPE_SHUTDOWN, // Shutdown. - VSOCK_SEQ_PACKET_TYPE_CLOSE, // Close (graceful or error). -} VSockSeqPacketType; - -/* Header for all packet versions. */ -typedef struct VSockSeqPacketHdr { - VMCIDatagram dg; // Datagram header. - uint8 version; // Version. - uint8 type; // Type of message. - uint16 offset; // Offset of data from start of packet. - int32 val; // Value. -} VSockSeqPacketHdr; - -/* Combination of all versions. */ -typedef struct VSockSeqPacket { - VSockSeqPacketHdr hdr; - /* Other versions go here. */ - /* Data is at base + hdr.offset. */ -} VSockSeqPacket; - -/* * Size assertions. */ MY_ASSERTS(VSockSeqPacketAsserts, ASSERT_ON_COMPILE(sizeof (VSockPacket) == 56); - ASSERT_ON_COMPILE(sizeof (VSockSeqPacket) == 32); ) #endif // _VMCI_SOCKETS_PACKET_H_ diff --git a/open-vm-tools/modules/linux/vsock/linux/vsockCommon.h b/open-vm-tools/modules/linux/vsock/linux/vsockCommon.h index 745c8474..f86f2148 100644 --- a/open-vm-tools/modules/linux/vsock/linux/vsockCommon.h +++ b/open-vm-tools/modules/linux/vsock/linux/vsockCommon.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. + * Copyright (C) 2007,2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -31,7 +31,7 @@ * it is used in several different contexts. In particular it is called from * vsockAddr.c which gets compiled into both our kernel modules as well as * the user level vsock library. In the linux kernel we need different behavior - * than external kernel modules using VMCI Sockets api inside the kernel. + * than external kernel modules using vSockets API inside the kernel. */ #if defined VMX86_VMX @@ -51,7 +51,7 @@ /* In the kernel we can't call into the provider. */ # define VMCISockGetAFValueInt() VMCI_SOCKETS_AF_VALUE # else // WINNT_DDK - /* In userland, just use the normal exported userlevel api. */ + /* In userland, just use the normal exported userlevel API. */ # define VMCISockGetAFValueInt() VMCISock_GetAFValue() # include <windows.h> # endif // WINNT_DDK @@ -72,7 +72,7 @@ extern int VSockVmci_GetAFValue(void); # define VMCISockGetAFValueInt() VSockVmci_GetAFValue() # else // __KERNEL__ - /* In userland, just use the normal exported userlevel api. */ + /* In userland, just use the normal exported userlevel API. */ # define VMCISockGetAFValueInt() VMCISock_GetAFValue() # endif #elif defined __APPLE__ @@ -189,7 +189,7 @@ __declspec(selectany) extern const WSAPROTOCOL_INFOW vsockProtocolInfos[] = { 0, /* Assigned by Winsock. */ { 1, 0 }, /* Base provider. */ 0, /* Version 0. */ - VMCI_SOCKETS_AF_VALUE, /* VMCI sockets protocol. */ + VMCI_SOCKETS_AF_VALUE, /* vSockets protocol. */ 16, /* Maximum address length in bytes. */ 16, /* Minimum address length in bytes. */ SOCK_DGRAM, /* STREAM. */ @@ -199,7 +199,7 @@ __declspec(selectany) extern const WSAPROTOCOL_INFOW vsockProtocolInfos[] = { SECURITY_PROTOCOL_NONE, /* No security. */ 0, /* Message size unimportant. */ 0, /* None. */ - L"VMCI sockets DGRAM" /* Protocol name. */ + L"vSockets DGRAM" /* Protocol name. */ }, { (XP1_GUARANTEED_DELIVERY | /* Guaranteed delivery. */ @@ -213,7 +213,7 @@ __declspec(selectany) extern const WSAPROTOCOL_INFOW vsockProtocolInfos[] = { 0, /* Assigned by Winsock. */ { 1, 0 }, /* Base provider. */ 0, /* Version 0. */ - VMCI_SOCKETS_AF_VALUE, /* VMCI sockets protocol. */ + VMCI_SOCKETS_AF_VALUE, /* vSockets protocol. */ 16, /* Maximum address length in bytes. */ 16, /* Minimum address length in bytes. */ SOCK_STREAM, /* STREAM. */ @@ -223,7 +223,7 @@ __declspec(selectany) extern const WSAPROTOCOL_INFOW vsockProtocolInfos[] = { SECURITY_PROTOCOL_NONE, /* No security. */ 0, /* Message size unimportant. */ 0, /* None. */ - L"VMCI sockets STREAM" /* Protocol name. */ + L"vSockets STREAM" /* Protocol name. */ }, }; diff --git a/open-vm-tools/modules/linux/vsock/linux/vsock_version.h b/open-vm-tools/modules/linux/vsock/linux/vsock_version.h index ae39173a..f46bf539 100644 --- a/open-vm-tools/modules/linux/vsock/linux/vsock_version.h +++ b/open-vm-tools/modules/linux/vsock/linux/vsock_version.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2011-2013 VMware, Inc. All rights reserved. + * Copyright (C) 2011-2014 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -25,8 +25,8 @@ #ifndef _VSOCK_VERSION_H_ #define _VSOCK_VERSION_H_ -#define VSOCK_DRIVER_VERSION 9.6.0.0 -#define VSOCK_DRIVER_VERSION_COMMAS 9,6,0,0 -#define VSOCK_DRIVER_VERSION_STRING "9.6.0.0" +#define VSOCK_DRIVER_VERSION 9.7.1.0 +#define VSOCK_DRIVER_VERSION_COMMAS 9,7,1,0 +#define VSOCK_DRIVER_VERSION_STRING "9.7.1.0" #endif /* _VSOCK_VERSION_H_ */ diff --git a/open-vm-tools/modules/shared/vmblock/block.c b/open-vm-tools/modules/shared/vmblock/block.c index 72e4af98..d81a44d2 100644 --- a/open-vm-tools/modules/shared/vmblock/block.c +++ b/open-vm-tools/modules/shared/vmblock/block.c @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmblock/block.h b/open-vm-tools/modules/shared/vmblock/block.h index 7171e59d..29e21183 100644 --- a/open-vm-tools/modules/shared/vmblock/block.h +++ b/open-vm-tools/modules/shared/vmblock/block.h @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmblock/stubs.c b/open-vm-tools/modules/shared/vmblock/stubs.c index cc284da4..cc158bc2 100644 --- a/open-vm-tools/modules/shared/vmblock/stubs.c +++ b/open-vm-tools/modules/shared/vmblock/stubs.c @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c b/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c index 3189af91..3ea87736 100644 --- a/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c +++ b/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h b/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h index f2289802..5e26ebe8 100644 --- a/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h +++ b/open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmmemctl/balloonInt.h b/open-vm-tools/modules/shared/vmmemctl/balloonInt.h index 684af098..5c472124 100644 --- a/open-vm-tools/modules/shared/vmmemctl/balloonInt.h +++ b/open-vm-tools/modules/shared/vmmemctl/balloonInt.h @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmmemctl/balloon_def.h b/open-vm-tools/modules/shared/vmmemctl/balloon_def.h index ef870cda..0ba139cf 100644 --- a/open-vm-tools/modules/shared/vmmemctl/balloon_def.h +++ b/open-vm-tools/modules/shared/vmmemctl/balloon_def.h @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmmemctl/dbllnklst.h b/open-vm-tools/modules/shared/vmmemctl/dbllnklst.h index c996f1a5..95745826 100644 --- a/open-vm-tools/modules/shared/vmmemctl/dbllnklst.h +++ b/open-vm-tools/modules/shared/vmmemctl/dbllnklst.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 1998 VMware, Inc. All rights reserved. + * Copyright (C) 1998-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmmemctl/kernelStubs.h b/open-vm-tools/modules/shared/vmmemctl/kernelStubs.h index 2fecd043..d0a53ad7 100644 --- a/open-vm-tools/modules/shared/vmmemctl/kernelStubs.h +++ b/open-vm-tools/modules/shared/vmmemctl/kernelStubs.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -69,6 +66,21 @@ #ifndef __KERNELSTUBS_H__ #define __KERNELSTUBS_H__ +#define KRNL_STUBS_DRIVER_TYPE_POSIX 1 +#define KRNL_STUBS_DRIVER_TYPE_GDI 2 +#define KRNL_STUBS_DRIVER_TYPE_WDM 3 +#define KRNL_STUBS_DRIVER_TYPE_NDIS 4 + +// For now (vsphere-2015), choose a good default. Later we'll modify all the +// build files using KernelStubs to set this. +#ifndef KRNL_STUBS_DRIVER_TYPE +# if defined(_WIN32) +# define KRNL_STUBS_DRIVER_TYPE KRNL_STUBS_DRIVER_TYPE_WDM +# else +# define KRNL_STUBS_DRIVER_TYPE KRNL_STUBS_DRIVER_TYPE_POSIX +# endif +#endif + #ifdef linux # ifndef __KERNEL__ # error "__KERNEL__ is not defined" @@ -78,12 +90,32 @@ # include <linux/kernel.h> # include <linux/string.h> #elif defined(_WIN32) -# include "vm_basic_types.h" -# include <ntddk.h> /* kernel memory APIs */ -# include <stdio.h> /* for _vsnprintf, vsprintf */ -# include <stdarg.h> /* for va_start stuff */ -# include <stdlib.h> /* for min macro. */ -# include "vm_assert.h" /* Our assert macros */ +# define _CRT_ALLOCATION_DEFINED // prevent malloc.h from defining malloc et. all +# if KRNL_STUBS_DRIVER_TYPE == KRNL_STUBS_DRIVER_TYPE_GDI +# include <d3d9.h> +# include <winddi.h> +# include <stdio.h> +# include "vm_basic_types.h" +# include "vm_basic_defs.h" +# include "vm_assert.h" +# elif KRNL_STUBS_DRIVER_TYPE == KRNL_STUBS_DRIVER_TYPE_NDIS +# include "vm_basic_types.h" +# include <ndis.h> +# elif KRNL_STUBS_DRIVER_TYPE == KRNL_STUBS_DRIVER_TYPE_WDM +# include "vm_basic_types.h" +# if defined(NTDDI_WINXP) && (NTDDI_VERSION >= NTDDI_WINXP) +# include <wdm.h> /* kernel memory APIs, DbgPrintEx */ +# else +# include <ntddk.h> /* kernel memory APIs */ +# endif +# include <stdio.h> /* for _vsnprintf, vsprintf */ +# include <stdarg.h> /* for va_start stuff */ +# include <stdlib.h> /* for min macro. */ +# include "vm_basic_defs.h" +# include "vm_assert.h" /* Our assert macros */ +# else +# error Type KRNL_STUBS_DRIVER_TYPE must be defined. +# endif #elif defined(__FreeBSD__) # include "vm_basic_types.h" # ifndef _KERNEL @@ -107,6 +139,7 @@ # include <sys/types.h> # include <sys/varargs.h> #endif +#include "kernelStubsSal.h" /* * Function Prototypes @@ -126,19 +159,41 @@ void *realloc(void *ptr, size_t newSize); #elif defined(_WIN32) /* } else if (_WIN32) { */ -#if (_WIN32_WINNT == 0x0400) -/* The following declarations are missing on NT4. */ -typedef unsigned int UINT_PTR; -typedef unsigned int SIZE_T; +_Ret_allocates_malloc_mem_opt_bytecap_(_Size) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS _CRTRESTRICT +void * __cdecl malloc( + _In_ size_t _Size); -/* No free with tag availaible on NT4 kernel! */ -#define KRNL_STUBS_FREE(P,T) ExFreePool((P)) +_Ret_allocates_malloc_mem_opt_bytecount_(_Count*_Size) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS _CRTRESTRICT +void * __cdecl calloc( + _In_ size_t _Count, + _In_ size_t _Size); -#else /* _WIN32_WINNT */ -#define KRNL_STUBS_FREE(P,T) ExFreePoolWithTag((P),(T)) -/* Win 2K and later useful kernel function, documented but not declared! */ -NTKERNELAPI VOID ExFreePoolWithTag(IN PVOID P, IN ULONG Tag); -#endif /* _WIN32_WINNT */ +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS +void __cdecl free( + _In_frees_malloc_mem_opt_ void * _Memory); + +_Success_(return != 0) +_When_(_Memory != 0, _Ret_reallocates_malloc_mem_opt_newbytecap_oldbytecap_(_NewSize, ((uintptr_t*)_Memory)[-1])) +_When_(_Memory == 0, _Ret_reallocates_malloc_mem_opt_newbytecap_(_NewSize)) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS _CRTRESTRICT +void * __cdecl realloc( + _In_reallocates_malloc_mem_opt_oldptr_ void * _Memory, + _In_ size_t _NewSize); + +_Success_(return != 0) +_Ret_allocates_malloc_mem_opt_z_ +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTIMP +char * __cdecl _strdup_impl( + _In_opt_z_ const char * _Src); + +#define strdup _strdup_impl #elif defined(__FreeBSD__) /* } else if (FreeBSD) { */ @@ -169,23 +224,84 @@ __compat_malloc(unsigned long size, struct malloc_type *type, int flags) { #endif /* } */ +_Ret_writes_z_(maxSize) +char *Str_Strcpy( + _Out_z_cap_(maxSize) char *buf, + _In_z_ const char *src, + _In_ size_t maxSize); + +_Ret_writes_z_(maxSize) +char *Str_Strcat( + _Inout_z_cap_(maxSize) char *buf, + _In_z_ const char *src, + _In_ size_t maxSize); + +_Success_(return >= 0) +int Str_Sprintf( + _Out_z_cap_(maxSize) _Post_z_count_(return+1) char *buf, + _In_ size_t maxSize, + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(3, 4); + +_Success_(return != -1) +int Str_Vsnprintf( + _Out_z_cap_(size) _Post_z_count_(return+1) char *str, + _In_ size_t size, + _In_z_ _Printf_format_string_ const char *format, + _In_ va_list ap) PRINTF_DECL(3, 0); + +_Success_(return != 0) +_When_(length != 0, _Ret_allocates_malloc_mem_opt_z_bytecount_(*length)) +_When_(length == 0, _Ret_allocates_malloc_mem_opt_z_) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +char *Str_Vasprintf( + _Out_opt_ size_t *length, + _In_z_ _Printf_format_string_ const char *format, + _In_ va_list arguments) PRINTF_DECL(2, 0); + +_Success_(return != 0) +_When_(length != 0, _Ret_allocates_malloc_mem_opt_z_bytecount_(*length)) +_When_(length == 0, _Ret_allocates_malloc_mem_opt_z_) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +char *Str_Asprintf( + _Out_opt_ size_t *length, + _In_z_ _Printf_format_string_ const char *format, + ...) PRINTF_DECL(2, 3); + +#ifdef _WIN32 +#pragma warning(push) +#pragma warning(disable: 28301) // Suppress complaint that first declaration lacked annotations +#endif + +// For now (vsphere-2015), we don't implement Panic, Warning, or Debug in the +// GDI case. +#if KRNL_STUBS_DRIVER_TYPE != KRNL_STUBS_DRIVER_TYPE_GDI + /* * Stub functions we provide. */ +#ifdef _WIN32 +NORETURN +#endif +void Panic( + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(1, 2); -void Panic(const char *fmt, ...); - -char *Str_Strcpy(char *buf, const char *src, size_t maxSize); -int Str_Vsnprintf(char *str, size_t size, const char *format, - va_list arguments); -char *Str_Vasprintf(size_t *length, const char *format, - va_list arguments); -char *Str_Asprintf(size_t *length, const char *Format, ...); +void Warning( + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(1, 2); /* * Functions the driver must implement for the stubs. */ -EXTERN void Debug(const char *fmt, ...); +EXTERN void Debug( + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(1, 2); +#endif // KRNL_STUBS_DRIVER_TYPE != KRNL_STUBS_DRIVER_TYPE_GDI + +#ifdef _WIN32 +#pragma warning(pop) +#endif #endif /* __KERNELSTUBS_H__ */ diff --git a/open-vm-tools/modules/shared/vmmemctl/os.h b/open-vm-tools/modules/shared/vmmemctl/os.h index e8f1d48b..e02bc67f 100644 --- a/open-vm-tools/modules/shared/vmmemctl/os.h +++ b/open-vm-tools/modules/shared/vmmemctl/os.h @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmmemctl/vmballoon.c b/open-vm-tools/modules/shared/vmmemctl/vmballoon.c index 70add0d1..0590f99e 100644 --- a/open-vm-tools/modules/shared/vmmemctl/vmballoon.c +++ b/open-vm-tools/modules/shared/vmmemctl/vmballoon.c @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmmemctl/vmballoon.h b/open-vm-tools/modules/shared/vmmemctl/vmballoon.h index 295b1b7b..b8193b0a 100644 --- a/open-vm-tools/modules/shared/vmmemctl/vmballoon.h +++ b/open-vm-tools/modules/shared/vmmemctl/vmballoon.h @@ -26,9 +26,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of VMware Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission of VMware Inc. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/open-vm-tools/modules/shared/vmxnet/eth_public.h b/open-vm-tools/modules/shared/vmxnet/eth_public.h index f606c9f8..6a75f245 100644 --- a/open-vm-tools/modules/shared/vmxnet/eth_public.h +++ b/open-vm-tools/modules/shared/vmxnet/eth_public.h @@ -47,6 +47,8 @@ #define INCLUDE_ALLOW_USERLEVEL #include "includeCheck.h" +#include "vm_basic_defs.h" + #define ETH_LADRF_LEN 2 #define ETH_ADDR_LENGTH 6 diff --git a/open-vm-tools/modules/shared/vmxnet/vmnet_def.h b/open-vm-tools/modules/shared/vmxnet/vmnet_def.h index d9b75c7a..73252067 100644 --- a/open-vm-tools/modules/shared/vmxnet/vmnet_def.h +++ b/open-vm-tools/modules/shared/vmxnet/vmnet_def.h @@ -57,57 +57,62 @@ * (eg VLAN support is in the virtual switch) so even vlance * can use them */ -#define VMNET_CAP_SG CONST64U(0x0001) /* Can do scatter-gather transmits. */ -#define VMNET_CAP_IP4_CSUM CONST64U(0x0002) /* Can checksum only TCP/UDP over IPv4. */ -#define VMNET_CAP_HW_CSUM CONST64U(0x0004) /* Can checksum all packets. */ -#define VMNET_CAP_HIGH_DMA CONST64U(0x0008) /* Can DMA to high memory. */ -#define VMNET_CAP_TOE CONST64U(0x0010) /* Supports TCP/IP offload. */ -#define VMNET_CAP_TSO CONST64U(0x0020) /* Supports TCP Segmentation offload */ -#define VMNET_CAP_SW_TSO CONST64U(0x0040) /* Supports SW TCP Segmentation */ -#define VMNET_CAP_VMXNET_APROM CONST64U(0x0080) /* Vmxnet APROM support */ -#define VMNET_CAP_HW_TX_VLAN CONST64U(0x0100) /* Can we do VLAN tagging in HW */ -#define VMNET_CAP_HW_RX_VLAN CONST64U(0x0200) /* Can we do VLAN untagging in HW */ -#define VMNET_CAP_SW_VLAN CONST64U(0x0400) /* Can we do VLAN tagging/untagging in SW */ -#define VMNET_CAP_WAKE_PCKT_RCV CONST64U(0x0800) /* Can wake on network packet recv? */ -#define VMNET_CAP_ENABLE_INT_INLINE CONST64U(0x1000) /* Enable Interrupt Inline */ -#define VMNET_CAP_ENABLE_HEADER_COPY CONST64U(0x2000) /* copy header for vmkernel */ -#define VMNET_CAP_TX_CHAIN CONST64U(0x4000) /* Guest can use multiple tx entries for a pkt */ -#define VMNET_CAP_RX_CHAIN CONST64U(0x8000) /* a pkt can span multiple rx entries */ -#define VMNET_CAP_LPD CONST64U(0x10000) /* large pkt delivery */ -#define VMNET_CAP_BPF CONST64U(0x20000) /* BPF Support in VMXNET Virtual Hardware */ -#define VMNET_CAP_SG_SPAN_PAGES CONST64U(0x40000) /* Can do scatter-gather span multiple pages transmits. */ -#define VMNET_CAP_IP6_CSUM CONST64U(0x80000) /* Can do IPv6 csum offload. */ -#define VMNET_CAP_TSO6 CONST64U(0x100000) /* Can do TSO segmentation offload for IPv6 pkts. */ -#define VMNET_CAP_TSO256k CONST64U(0x200000) /* Can do TSO segmentation offload for pkts up to 256kB. */ -#define VMNET_CAP_UPT CONST64U(0x400000) /* Support UPT */ -#define VMNET_CAP_RDONLY_INETHDRS CONST64U(0x800000) /* Modifies inet headers for TSO/CSUm */ -#define VMNET_CAP_ENCAP CONST64U(0x1000000) /* NPA not used, so redefining for ENCAP support */ -#define VMNET_CAP_DCB CONST64U(0x2000000) /* Support DCB */ -#define VMNET_CAP_OFFLOAD_8OFFSET CONST64U(0x4000000) /* supports 8bit parameterized offsets */ -#define VMNET_CAP_OFFLOAD_16OFFSET CONST64U(0x8000000) /* supports 16bit parameterized offsets */ -#define VMNET_CAP_IP6_CSUM_EXT_HDRS CONST64U(0x10000000) /* support csum of ip6 ext hdrs */ -#define VMNET_CAP_TSO6_EXT_HDRS CONST64U(0x20000000) /* support TSO for ip6 ext hdrs */ -#define VMNET_CAP_SCHED CONST64U(0x40000000) /* compliant with network scheduling */ -#define VMNET_CAP_SRIOV CONST64U(0x80000000) /* Supports SR-IOV */ +#define VMNET_CAP_SG CONST64U(0x0001) /* Can do scatter-gather transmits. */ +#define VMNET_CAP_IP4_CSUM CONST64U(0x0002) /* Can checksum only TCP/UDP over IPv4. */ +#define VMNET_CAP_HW_CSUM CONST64U(0x0004) /* Can checksum all packets. */ +#define VMNET_CAP_HIGH_DMA CONST64U(0x0008) /* Can DMA to high memory. */ +#define VMNET_CAP_TOE CONST64U(0x0010) /* Supports TCP/IP offload. */ +#define VMNET_CAP_TSO CONST64U(0x0020) /* Supports TCP Segmentation offload */ +#define VMNET_CAP_SW_TSO CONST64U(0x0040) /* Supports SW TCP Segmentation */ +#define VMNET_CAP_VMXNET_APROM CONST64U(0x0080) /* Vmxnet APROM support */ +#define VMNET_CAP_HW_TX_VLAN CONST64U(0x0100) /* Can we do VLAN tagging in HW */ +#define VMNET_CAP_HW_RX_VLAN CONST64U(0x0200) /* Can we do VLAN untagging in HW */ +#define VMNET_CAP_SW_VLAN CONST64U(0x0400) /* Can we do VLAN tagging/untagging in SW */ +#define VMNET_CAP_WAKE_PCKT_RCV CONST64U(0x0800) /* Can wake on network packet recv? */ +#define VMNET_CAP_ENABLE_INT_INLINE CONST64U(0x1000) /* Enable Interrupt Inline */ +#define VMNET_CAP_ENABLE_HEADER_COPY CONST64U(0x2000) /* copy header for vmkernel */ +#define VMNET_CAP_TX_CHAIN CONST64U(0x4000) /* Guest can use multiple tx entries for a pkt */ +#define VMNET_CAP_RX_CHAIN CONST64U(0x8000) /* a pkt can span multiple rx entries */ +#define VMNET_CAP_LPD CONST64U(0x10000) /* large pkt delivery */ +#define VMNET_CAP_BPF CONST64U(0x20000) /* BPF Support in VMXNET Virtual Hardware */ +#define VMNET_CAP_SG_SPAN_PAGES CONST64U(0x40000) /* Can do scatter-gather span multiple pages transmits. */ +#define VMNET_CAP_IP6_CSUM CONST64U(0x80000) /* Can do IPv6 csum offload. */ +#define VMNET_CAP_TSO6 CONST64U(0x100000) /* Can do TSO segmentation offload for IPv6 pkts. */ +#define VMNET_CAP_TSO256k CONST64U(0x200000) /* Can do TSO segmentation offload for pkts up to 256kB. */ +#define VMNET_CAP_UPT CONST64U(0x400000) /* Support UPT */ +#define VMNET_CAP_RDONLY_INETHDRS CONST64U(0x800000) /* Modifies inet headers for TSO/CSUm */ +#define VMNET_CAP_ENCAP CONST64U(0x1000000) /* NPA not used, so redefining for ENCAP support */ +#define VMNET_CAP_DCB CONST64U(0x2000000) /* Support DCB */ +#define VMNET_CAP_OFFSET_BASED_OFFLOAD CONST64U(0x4000000) /* Support offload based offload */ +#define VMNET_CAP_GENEVE_OFFLOAD CONST64U(0x8000000) /* Support Geneve encapsulation offload */ +#define VMNET_CAP_IP6_CSUM_EXT_HDRS CONST64U(0x10000000) /* support csum of ip6 ext hdrs */ +#define VMNET_CAP_TSO6_EXT_HDRS CONST64U(0x20000000) /* support TSO for ip6 ext hdrs */ +#define VMNET_CAP_SCHED CONST64U(0x40000000) /* compliant with network scheduling */ +#define VMNET_CAP_SRIOV CONST64U(0x80000000) /* Supports SR-IOV */ -#define VMNET_CAP_SG_TX VMNET_CAP_SG -#define VMNET_CAP_SG_RX CONST64U(0x200000000) /* Scatter-gather receive capability */ -#define VMNET_CAP_PRIV_STATS CONST64U(0x400000000) /* Driver supports accessing private stats */ -#define VMNET_CAP_LINK_STATUS_SET CONST64U(0x800000000) /* Driver supports changing link status */ -#define VMNET_CAP_MAC_ADDR_SET CONST64U(0x1000000000) /* Driver supports changing the interface MAC address */ -#define VMNET_CAP_COALESCE_PARAMS CONST64U(0x2000000000) /* Driver supports changing interrupt coalescing parameters */ -#define VMNET_CAP_VLAN_FILTER CONST64U(0x4000000000) /* VLAN Filtering capability */ -#define VMNET_CAP_WAKE_ON_LAN CONST64U(0x8000000000) /* Wake-On-LAN capability */ -#define VMNET_CAP_NETWORK_DUMP CONST64U(0x10000000000) /* Network core dumping capability */ -#define VMNET_CAP_MULTI_QUEUE CONST64U(0x20000000000) /* Multiple queue capability */ -#define VMNET_CAP_EEPROM CONST64U(0x40000000000) /* EEPROM dump capability */ -#define VMNET_CAP_REGDUMP CONST64U(0x80000000000) /* Register dump capability */ -#define VMNET_CAP_SELF_TEST CONST64U(0x100000000000) /* Self-test capability */ -#define VMNET_CAP_PAUSE_PARAMS CONST64U(0x200000000000) /* Pause frame parameter adjusting */ -#define VMNET_CAP_RESTART_NEG CONST64U(0x400000000000) /* Ability to restart negotiation of link speed/duplexity */ -#define VMNET_CAP_LRO CONST64U(0x800000000000) /* Hardware supported LRO */ -#define VMNET_CAP_OFFLOAD_ALIGN_ANY CONST64U(0x1000000000000) /* Nic requires no header alignment */ -#define VMNET_CAP_GENERIC_OFFLOAD CONST64U(0x2000000000000) /* Generic hardware offloading (eg. vxlan encap offload and offset based offload) */ -#define VMNET_CAP_LEGACY CONST64U(0x8000000000000000) /* Uplink is compatible with vmklinux drivers */ +#define VMNET_CAP_SG_TX VMNET_CAP_SG +#define VMNET_CAP_SG_RX CONST64U(0x200000000) /* Scatter-gather receive capability */ +#define VMNET_CAP_PRIV_STATS CONST64U(0x400000000) /* Driver supports accessing private stats */ +#define VMNET_CAP_LINK_STATUS_SET CONST64U(0x800000000) /* Driver supports changing link status */ +#define VMNET_CAP_MAC_ADDR_SET CONST64U(0x1000000000) /* Driver supports changing the interface MAC address */ +#define VMNET_CAP_COALESCE_PARAMS CONST64U(0x2000000000) /* Driver supports changing interrupt coalescing parameters */ +#define VMNET_CAP_VLAN_FILTER CONST64U(0x4000000000) /* VLAN Filtering capability */ +#define VMNET_CAP_WAKE_ON_LAN CONST64U(0x8000000000) /* Wake-On-LAN capability */ +#define VMNET_CAP_NETWORK_DUMP CONST64U(0x10000000000) /* Network core dumping capability */ +#define VMNET_CAP_MULTI_QUEUE CONST64U(0x20000000000) /* Multiple queue capability */ +#define VMNET_CAP_EEPROM CONST64U(0x40000000000) /* EEPROM dump capability */ +#define VMNET_CAP_REGDUMP CONST64U(0x80000000000) /* Register dump capability */ +#define VMNET_CAP_SELF_TEST CONST64U(0x100000000000) /* Self-test capability */ +#define VMNET_CAP_PAUSE_PARAMS CONST64U(0x200000000000) /* Pause frame parameter adjusting */ +#define VMNET_CAP_RESTART_NEG CONST64U(0x400000000000) /* Ability to restart negotiation of link speed/duplexity */ +#define VMNET_CAP_LRO CONST64U(0x800000000000) /* Hardware supported LRO */ +#define VMNET_CAP_OFFLOAD_ALIGN_ANY CONST64U(0x1000000000000) /* Nic requires no header alignment */ +#define VMNET_CAP_GENERIC_OFFLOAD CONST64U(0x2000000000000) /* Generic hardware offloading (eg. vxlan encap offload and offset based offload) */ +#define VMNET_CAP_CABLE_TYPE CONST64U(0x4000000000000) /* Uplink supports getting and setting cable type. */ +#define VMNET_CAP_PHY_ADDRESS CONST64U(0x8000000000000) /* Uplink supports getting and setting PHY address. */ +#define VMNET_CAP_TRANSCEIVER_TYPE CONST64U(0x10000000000000) /* Uplink supports getting and setting transceiver type. */ +#define VMNET_CAP_MESSAGE_LEVEL CONST64U(0x20000000000000) /* Uplink supports getting and setting message level. */ +#define VMNET_CAP_RING_PARAMS CONST64U(0x40000000000000) /* Support getting/setting RX/TX ring size parameters */ +#define VMNET_CAP_LEGACY CONST64U(0x8000000000000000) /* Uplink is compatible with vmklinux drivers */ #endif // _VMNET_DEF_H_ diff --git a/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h b/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h index eb9af751..b79ecdb4 100644 --- a/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h +++ b/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h @@ -347,6 +347,18 @@ struct Vmxnet3_RxCompDesc { #include "vmware_pack_end.h" Vmxnet3_RxCompDesc; +typedef +#include "vmware_pack_begin.h" +struct Vmxnet3_RxCompDescExt { + __le32 dword1; + uint8 segCnt; /* Number of aggregated packets */ + uint8 dupAckCnt; /* Number of duplicate Acks */ + __le16 tsDelta; /* TCP timestamp difference */ + __le32 dword2[2]; +} +#include "vmware_pack_end.h" +Vmxnet3_RxCompDescExt; + /* fields in RxCompDesc we access via Vmxnet3_GenericDesc.dword[3] */ #define VMXNET3_RCD_TUC_SHIFT 16 #define VMXNET3_RCD_IPC_SHIFT 19 @@ -367,17 +379,20 @@ Vmxnet3_RxCompDesc; /* a union for accessing all cmd/completion descriptors */ typedef union Vmxnet3_GenericDesc { - __le64 qword[2]; - __le32 dword[4]; - __le16 word[8]; - Vmxnet3_TxDesc txd; - Vmxnet3_RxDesc rxd; - Vmxnet3_TxCompDesc tcd; - Vmxnet3_RxCompDesc rcd; + __le64 qword[2]; + __le32 dword[4]; + __le16 word[8]; + Vmxnet3_TxDesc txd; + Vmxnet3_RxDesc rxd; + Vmxnet3_TxCompDesc tcd; + Vmxnet3_RxCompDesc rcd; + Vmxnet3_RxCompDescExt rcdExt; } Vmxnet3_GenericDesc; #define VMXNET3_INIT_GEN 1 +#define VMXNET3_INVALID_QUEUEID -1 + /* Max size of a single tx buffer */ #define VMXNET3_MAX_TX_BUF_SIZE (1 << 14) @@ -405,6 +420,7 @@ typedef union Vmxnet3_GenericDesc { #define VMXNET3_TX_RING_MAX_SIZE 4096 #define VMXNET3_TC_RING_MAX_SIZE 4096 #define VMXNET3_RX_RING_MAX_SIZE 4096 +#define VMXNET3_RX_RING2_MAX_SIZE 2048 #define VMXNET3_RC_RING_MAX_SIZE 8192 /* a list of reasons for queue stop */ diff --git a/open-vm-tools/modules/solaris/vmhgfs/Makefile b/open-vm-tools/modules/solaris/vmhgfs/Makefile index ef086918..1979d435 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/Makefile +++ b/open-vm-tools/modules/solaris/vmhgfs/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/make -f ########################################################## -# Copyright (C) 2008 VMware, Inc. All rights reserved. +# Copyright (C) 2008-2015 VMware, Inc. All rights reserved. # # The contents of this file are subject to the terms of the Common # Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/debug.c b/open-vm-tools/modules/solaris/vmhgfs/debug.c index b82476fd..25039e08 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/debug.c +++ b/open-vm-tools/modules/solaris/vmhgfs/debug.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/debug.h b/open-vm-tools/modules/solaris/vmhgfs/debug.h index 657eff0f..44096ae4 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/debug.h +++ b/open-vm-tools/modules/solaris/vmhgfs/debug.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/filesystem.c b/open-vm-tools/modules/solaris/vmhgfs/filesystem.c index 7f4d9994..187be2c9 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/filesystem.c +++ b/open-vm-tools/modules/solaris/vmhgfs/filesystem.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/filesystem.h b/open-vm-tools/modules/solaris/vmhgfs/filesystem.h index 3773eb6c..709fc218 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/filesystem.h +++ b/open-vm-tools/modules/solaris/vmhgfs/filesystem.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/hgfsBdGlue.c b/open-vm-tools/modules/solaris/vmhgfs/hgfsBdGlue.c index 8d302abd..4b52814b 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/hgfsBdGlue.c +++ b/open-vm-tools/modules/solaris/vmhgfs/hgfsBdGlue.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2009 VMware, Inc. All rights reserved. + * Copyright (C) 2009-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 @@ -25,6 +25,7 @@ #include "request.h" #include "hgfsBdGlue.h" #include "hgfsBd.h" +#include "vm_basic_defs.h" #include "vm_assert.h" #include "debug.h" diff --git a/open-vm-tools/modules/solaris/vmhgfs/hgfsBdGlue.h b/open-vm-tools/modules/solaris/vmhgfs/hgfsBdGlue.h index b39bc504..eb27ec21 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/hgfsBdGlue.h +++ b/open-vm-tools/modules/solaris/vmhgfs/hgfsBdGlue.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2009 VMware, Inc. All rights reserved. + * Copyright (C) 2009-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/hgfsSolaris.h b/open-vm-tools/modules/solaris/vmhgfs/hgfsSolaris.h index 5a1f8871..506d9a23 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/hgfsSolaris.h +++ b/open-vm-tools/modules/solaris/vmhgfs/hgfsSolaris.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 @@ -62,6 +62,7 @@ #ifdef _KERNEL #include "dbllnklst.h" +#include "vm_basic_defs.h" #include "vm_assert.h" #endif /* _KERNEL */ diff --git a/open-vm-tools/modules/solaris/vmhgfs/hgfsState.c b/open-vm-tools/modules/solaris/vmhgfs/hgfsState.c index 56a00471..77c2ff0b 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/hgfsState.c +++ b/open-vm-tools/modules/solaris/vmhgfs/hgfsState.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 @@ -32,8 +32,9 @@ #include "hgfsState.h" #include "debug.h" -#include "vm_assert.h" #include "vm_basic_types.h" +#include "vm_basic_defs.h" +#include "vm_assert.h" #include "sha1.h" /* SHA-1 for Node ID calculation */ diff --git a/open-vm-tools/modules/solaris/vmhgfs/hgfsState.h b/open-vm-tools/modules/solaris/vmhgfs/hgfsState.h index bfaa4423..9fc349a4 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/hgfsState.h +++ b/open-vm-tools/modules/solaris/vmhgfs/hgfsState.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/kernelStubs.h b/open-vm-tools/modules/solaris/vmhgfs/kernelStubs.h index f6e83166..1f8fef07 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/kernelStubs.h +++ b/open-vm-tools/modules/solaris/vmhgfs/kernelStubs.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 @@ -25,6 +25,21 @@ #ifndef __KERNELSTUBS_H__ #define __KERNELSTUBS_H__ +#define KRNL_STUBS_DRIVER_TYPE_POSIX 1 +#define KRNL_STUBS_DRIVER_TYPE_GDI 2 +#define KRNL_STUBS_DRIVER_TYPE_WDM 3 +#define KRNL_STUBS_DRIVER_TYPE_NDIS 4 + +// For now (vsphere-2015), choose a good default. Later we'll modify all the +// build files using KernelStubs to set this. +#ifndef KRNL_STUBS_DRIVER_TYPE +# if defined(_WIN32) +# define KRNL_STUBS_DRIVER_TYPE KRNL_STUBS_DRIVER_TYPE_WDM +# else +# define KRNL_STUBS_DRIVER_TYPE KRNL_STUBS_DRIVER_TYPE_POSIX +# endif +#endif + #ifdef linux # ifndef __KERNEL__ # error "__KERNEL__ is not defined" @@ -34,12 +49,32 @@ # include <linux/kernel.h> # include <linux/string.h> #elif defined(_WIN32) -# include "vm_basic_types.h" -# include <ntddk.h> /* kernel memory APIs */ -# include <stdio.h> /* for _vsnprintf, vsprintf */ -# include <stdarg.h> /* for va_start stuff */ -# include <stdlib.h> /* for min macro. */ -# include "vm_assert.h" /* Our assert macros */ +# define _CRT_ALLOCATION_DEFINED // prevent malloc.h from defining malloc et. all +# if KRNL_STUBS_DRIVER_TYPE == KRNL_STUBS_DRIVER_TYPE_GDI +# include <d3d9.h> +# include <winddi.h> +# include <stdio.h> +# include "vm_basic_types.h" +# include "vm_basic_defs.h" +# include "vm_assert.h" +# elif KRNL_STUBS_DRIVER_TYPE == KRNL_STUBS_DRIVER_TYPE_NDIS +# include "vm_basic_types.h" +# include <ndis.h> +# elif KRNL_STUBS_DRIVER_TYPE == KRNL_STUBS_DRIVER_TYPE_WDM +# include "vm_basic_types.h" +# if defined(NTDDI_WINXP) && (NTDDI_VERSION >= NTDDI_WINXP) +# include <wdm.h> /* kernel memory APIs, DbgPrintEx */ +# else +# include <ntddk.h> /* kernel memory APIs */ +# endif +# include <stdio.h> /* for _vsnprintf, vsprintf */ +# include <stdarg.h> /* for va_start stuff */ +# include <stdlib.h> /* for min macro. */ +# include "vm_basic_defs.h" +# include "vm_assert.h" /* Our assert macros */ +# else +# error Type KRNL_STUBS_DRIVER_TYPE must be defined. +# endif #elif defined(__FreeBSD__) # include "vm_basic_types.h" # ifndef _KERNEL @@ -63,6 +98,7 @@ # include <sys/types.h> # include <sys/varargs.h> #endif +#include "kernelStubsSal.h" /* * Function Prototypes @@ -82,19 +118,41 @@ void *realloc(void *ptr, size_t newSize); #elif defined(_WIN32) /* } else if (_WIN32) { */ -#if (_WIN32_WINNT == 0x0400) -/* The following declarations are missing on NT4. */ -typedef unsigned int UINT_PTR; -typedef unsigned int SIZE_T; +_Ret_allocates_malloc_mem_opt_bytecap_(_Size) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS _CRTRESTRICT +void * __cdecl malloc( + _In_ size_t _Size); -/* No free with tag availaible on NT4 kernel! */ -#define KRNL_STUBS_FREE(P,T) ExFreePool((P)) +_Ret_allocates_malloc_mem_opt_bytecount_(_Count*_Size) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS _CRTRESTRICT +void * __cdecl calloc( + _In_ size_t _Count, + _In_ size_t _Size); -#else /* _WIN32_WINNT */ -#define KRNL_STUBS_FREE(P,T) ExFreePoolWithTag((P),(T)) -/* Win 2K and later useful kernel function, documented but not declared! */ -NTKERNELAPI VOID ExFreePoolWithTag(IN PVOID P, IN ULONG Tag); -#endif /* _WIN32_WINNT */ +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS +void __cdecl free( + _In_frees_malloc_mem_opt_ void * _Memory); + +_Success_(return != 0) +_When_(_Memory != 0, _Ret_reallocates_malloc_mem_opt_newbytecap_oldbytecap_(_NewSize, ((uintptr_t*)_Memory)[-1])) +_When_(_Memory == 0, _Ret_reallocates_malloc_mem_opt_newbytecap_(_NewSize)) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTNOALIAS _CRTRESTRICT +void * __cdecl realloc( + _In_reallocates_malloc_mem_opt_oldptr_ void * _Memory, + _In_ size_t _NewSize); + +_Success_(return != 0) +_Ret_allocates_malloc_mem_opt_z_ +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +_CRTIMP +char * __cdecl _strdup_impl( + _In_opt_z_ const char * _Src); + +#define strdup _strdup_impl #elif defined(__FreeBSD__) /* } else if (FreeBSD) { */ @@ -125,23 +183,84 @@ __compat_malloc(unsigned long size, struct malloc_type *type, int flags) { #endif /* } */ +_Ret_writes_z_(maxSize) +char *Str_Strcpy( + _Out_z_cap_(maxSize) char *buf, + _In_z_ const char *src, + _In_ size_t maxSize); + +_Ret_writes_z_(maxSize) +char *Str_Strcat( + _Inout_z_cap_(maxSize) char *buf, + _In_z_ const char *src, + _In_ size_t maxSize); + +_Success_(return >= 0) +int Str_Sprintf( + _Out_z_cap_(maxSize) _Post_z_count_(return+1) char *buf, + _In_ size_t maxSize, + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(3, 4); + +_Success_(return != -1) +int Str_Vsnprintf( + _Out_z_cap_(size) _Post_z_count_(return+1) char *str, + _In_ size_t size, + _In_z_ _Printf_format_string_ const char *format, + _In_ va_list ap) PRINTF_DECL(3, 0); + +_Success_(return != 0) +_When_(length != 0, _Ret_allocates_malloc_mem_opt_z_bytecount_(*length)) +_When_(length == 0, _Ret_allocates_malloc_mem_opt_z_) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +char *Str_Vasprintf( + _Out_opt_ size_t *length, + _In_z_ _Printf_format_string_ const char *format, + _In_ va_list arguments) PRINTF_DECL(2, 0); + +_Success_(return != 0) +_When_(length != 0, _Ret_allocates_malloc_mem_opt_z_bytecount_(*length)) +_When_(length == 0, _Ret_allocates_malloc_mem_opt_z_) +_When_windrv_(_IRQL_requires_max_(DISPATCH_LEVEL)) +char *Str_Asprintf( + _Out_opt_ size_t *length, + _In_z_ _Printf_format_string_ const char *format, + ...) PRINTF_DECL(2, 3); + +#ifdef _WIN32 +#pragma warning(push) +#pragma warning(disable: 28301) // Suppress complaint that first declaration lacked annotations +#endif + +// For now (vsphere-2015), we don't implement Panic, Warning, or Debug in the +// GDI case. +#if KRNL_STUBS_DRIVER_TYPE != KRNL_STUBS_DRIVER_TYPE_GDI + /* * Stub functions we provide. */ +#ifdef _WIN32 +NORETURN +#endif +void Panic( + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(1, 2); -void Panic(const char *fmt, ...); - -char *Str_Strcpy(char *buf, const char *src, size_t maxSize); -int Str_Vsnprintf(char *str, size_t size, const char *format, - va_list arguments); -char *Str_Vasprintf(size_t *length, const char *format, - va_list arguments); -char *Str_Asprintf(size_t *length, const char *Format, ...); +void Warning( + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(1, 2); /* * Functions the driver must implement for the stubs. */ -EXTERN void Debug(const char *fmt, ...); +EXTERN void Debug( + _In_z_ _Printf_format_string_ const char *fmt, + ...) PRINTF_DECL(1, 2); +#endif // KRNL_STUBS_DRIVER_TYPE != KRNL_STUBS_DRIVER_TYPE_GDI + +#ifdef _WIN32 +#pragma warning(pop) +#endif #endif /* __KERNELSTUBS_H__ */ diff --git a/open-vm-tools/modules/solaris/vmhgfs/kernelStubsSolaris.c b/open-vm-tools/modules/solaris/vmhgfs/kernelStubsSolaris.c index 75ae9b9f..947ff8e2 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/kernelStubsSolaris.c +++ b/open-vm-tools/modules/solaris/vmhgfs/kernelStubsSolaris.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2009 VMware, Inc. All rights reserved. + * Copyright (C) 2009-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/module.c b/open-vm-tools/modules/solaris/vmhgfs/module.c index 62cef6b6..07bd7570 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/module.c +++ b/open-vm-tools/modules/solaris/vmhgfs/module.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/module.h b/open-vm-tools/modules/solaris/vmhgfs/module.h index 1dab9d6d..164c2bf6 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/module.h +++ b/open-vm-tools/modules/solaris/vmhgfs/module.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/request.c b/open-vm-tools/modules/solaris/vmhgfs/request.c index 644a437d..293e71be 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/request.c +++ b/open-vm-tools/modules/solaris/vmhgfs/request.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/request.h b/open-vm-tools/modules/solaris/vmhgfs/request.h index 6d081bc7..d735e680 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/request.h +++ b/open-vm-tools/modules/solaris/vmhgfs/request.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/vnode.c b/open-vm-tools/modules/solaris/vmhgfs/vnode.c index 88548c11..b746403a 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/vnode.c +++ b/open-vm-tools/modules/solaris/vmhgfs/vnode.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmhgfs/vnode.h b/open-vm-tools/modules/solaris/vmhgfs/vnode.h index e1a1551a..a9265ac1 100644 --- a/open-vm-tools/modules/solaris/vmhgfs/vnode.h +++ b/open-vm-tools/modules/solaris/vmhgfs/vnode.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmmemctl/kernelStubsSolaris.c b/open-vm-tools/modules/solaris/vmmemctl/kernelStubsSolaris.c index 75ae9b9f..947ff8e2 100644 --- a/open-vm-tools/modules/solaris/vmmemctl/kernelStubsSolaris.c +++ b/open-vm-tools/modules/solaris/vmmemctl/kernelStubsSolaris.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2009 VMware, Inc. All rights reserved. + * Copyright (C) 2009-2015 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 diff --git a/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_main.c b/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_main.c index 8b9a07f2..a2675e80 100644 --- a/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_main.c +++ b/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_main.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. + * Copyright (C) 2007-2014 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 @@ -36,9 +36,30 @@ static int vmxnet3_multicst(void *, boolean_t, const uint8_t *); static int vmxnet3_unicst(void *, const uint8_t *); static boolean_t vmxnet3_getcapab(void *, mac_capab_t, void *); +#ifdef SOL11 +static int vmxnet3_get_prop(void *, + const char *, + mac_prop_id_t, + uint_t, + void *); +static int vmxnet3_set_prop(void *, + const char *, + mac_prop_id_t, + uint_t, + const void *); +static void vmxnet3_prop_info(void *, + const char *, + mac_prop_id_t, + mac_prop_info_handle_t); +#endif + /* MAC callbacks */ static mac_callbacks_t vmxnet3_mac_callbacks = { +#ifdef SOL11 + .mc_callbacks = MC_GETCAPAB | MC_IOCTL | MC_GETPROP | MC_SETPROP | MC_PROPINFO, +#else .mc_callbacks = MC_GETCAPAB | MC_IOCTL, +#endif .mc_getstat = vmxnet3_getstat, .mc_start = vmxnet3_start, .mc_stop = vmxnet3_stop, @@ -46,6 +67,11 @@ static mac_callbacks_t vmxnet3_mac_callbacks = { .mc_multicst = vmxnet3_multicst, .mc_unicst = vmxnet3_unicst, .mc_tx = vmxnet3_tx, +#ifdef SOL11 + .mc_getprop = vmxnet3_get_prop, + .mc_setprop = vmxnet3_set_prop, + .mc_propinfo = vmxnet3_prop_info, +#endif #ifndef OPEN_SOLARIS #ifndef SOL11 .mc_resources = NULL, @@ -977,12 +1003,15 @@ vmxnet3_change_mtu(vmxnet3_softc_t *dp, uint32_t new_mtu) VMXNET3_WARN(dp, "New MTU not in valid range [%d, %d].\n", VMXNET3_MIN_MTU, VMXNET3_MAX_MTU); return EINVAL; - } else if (new_mtu > ETHERMTU && !dp->allow_jumbo) { + } +#if defined(SOL9) || defined (SOL10) || defined (OPEN_SOLARIS) + if (new_mtu > ETHERMTU && !dp->allow_jumbo) { VMXNET3_WARN(dp, "MTU cannot be greater than %d because accept-jumbo " "is not enabled.\n", ETHERMTU); return EINVAL; } +#endif if (dp->devEnabled) { do_reset = 1; @@ -991,7 +1020,8 @@ vmxnet3_change_mtu(vmxnet3_softc_t *dp, uint32_t new_mtu) } dp->cur_mtu = new_mtu; -#if defined (SOL11) || defined (OPEN_SOLARIS) + +#ifdef OPEN_SOLARIS mac_maxsdu_update(dp->mac, new_mtu); #endif @@ -1159,6 +1189,80 @@ vmxnet3_getcapab(void *data, mac_capab_t capab, void *arg) return ret; } +#ifdef SOL11 +static int +vmxnet3_get_prop(void *data, + const char *prop_name, + mac_prop_id_t prop_id, + uint_t prop_val_size, + void *prop_val) +{ + vmxnet3_softc_t *dp = data; + int ret = 0; + + switch (prop_id) { + case MAC_PROP_MTU: { + ASSERT(prop_val_size >= sizeof (uint32_t)); + bcopy(&dp->cur_mtu, prop_val, sizeof (uint32_t)); + break; + } + default: { + VMXNET3_WARN(dp, "vmxnet3_get_prop property %d not supported", prop_id); + ret = ENOTSUP; + } + } + return (0); +} + + +static int +vmxnet3_set_prop(void *data, + const char *prop_name, + mac_prop_id_t prop_id, + uint_t prop_val_size, + const void *prop_val) +{ + vmxnet3_softc_t *dp = data; + int ret; + + switch (prop_id) { + case MAC_PROP_MTU: { + uint32_t new_mtu; + ASSERT(prop_val_size >= sizeof (uint32_t)); + bcopy(prop_val, &new_mtu, sizeof (new_mtu)); + ret = vmxnet3_change_mtu(dp, new_mtu); + break; + } + default: { + VMXNET3_WARN(dp, "vmxnet3_set_prop property %d not supported", prop_id); + ret = ENOTSUP; + } + } + + return ret; +} + + +static void +vmxnet3_prop_info(void *data, + const char *prop_name, + mac_prop_id_t prop_id, + mac_prop_info_handle_t prop_handle) +{ + vmxnet3_softc_t *dp = data; + + switch (prop_id) { + case MAC_PROP_MTU: { + mac_prop_info_set_range_uint32(prop_handle, VMXNET3_MIN_MTU, VMXNET3_MAX_MTU); + break; + } + default: { + VMXNET3_WARN(dp, "vmxnet3_prop_info: property %d not supported", prop_id); + } + } +} +#endif + /* *--------------------------------------------------------------------------- @@ -1636,7 +1740,7 @@ vmxnet3_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) * Structures used by the Solaris module loader */ -#define VMXNET3_IDENT "VMware EtherAdapter v3 b" BUILD_NUMBER_NUMERIC_STRING +#define VMXNET3_IDENT "VMware EtherAdapter v3 " VMXNET3_DRIVER_VERSION_STRING COMPAT_DDI_DEFINE_STREAM_OPS(vmxnet3_dev_ops, nulldev, diff --git a/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_solaris.h b/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_solaris.h index bf812b3a..368b96d7 100644 --- a/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_solaris.h +++ b/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_solaris.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2007 VMware, Inc. All rights reserved. + * Copyright (C) 2007-2014 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 @@ -178,6 +178,7 @@ void vmxnet3_rxqueue_fini(vmxnet3_softc_t *dp, vmxnet3_rxqueue_t *rxq); extern ddi_device_acc_attr_t vmxnet3_dev_attr; #define VMXNET3_MODNAME "vmxnet3s" +#define VMXNET3_DRIVER_VERSION_STRING "1.1.0.0" /* Logging stuff */ #define VMXNET3_LOG(Level, Device, Format, Args...) \ diff --git a/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_tx.c b/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_tx.c index 586c4ec6..9b2af6a0 100644 --- a/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_tx.c +++ b/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_tx.c @@ -103,14 +103,16 @@ vmxnet3_tx_prepare_offload(vmxnet3_softc_t *dp, mblk_t *mp) { int ret = 0; - uint32_t start, stuff, value, flags; + uint32_t start, stuff, value, flags, lso_flag, mss; ol->om = VMXNET3_OM_NONE; ol->hlen = 0; ol->msscof = 0; hcksum_retrieve(mp, NULL, NULL, &start, &stuff, NULL, &value, &flags); - if (flags) { + mac_lso_get(mp, &mss, &lso_flag); + + if (flags || lso_flag) { struct ether_vlan_header *eth = (void *) mp->b_rptr; uint8_t ethLen; @@ -123,12 +125,7 @@ vmxnet3_tx_prepare_offload(vmxnet3_softc_t *dp, VMXNET3_DEBUG(dp, 4, "flags=0x%x, ethLen=%u, start=%u, stuff=%u, value=%u\n", flags, ethLen, start, stuff, value); - if (flags & HCK_PARTIALCKSUM) { - ol->om = VMXNET3_OM_CSUM; - ol->hlen = start + ethLen; - ol->msscof = stuff + ethLen; - } - if (flags & HW_LSO) { + if (lso_flag & HW_LSO) { mblk_t *mblk = mp; uint8_t *ip, *tcp; uint8_t ipLen, tcpLen; @@ -157,13 +154,17 @@ vmxnet3_tx_prepare_offload(vmxnet3_softc_t *dp, ol->om = VMXNET3_OM_TSO; ol->hlen = ethLen + ipLen + tcpLen; - /* OpenSolaris fills 'value' with the MSS but Solaris doesn't. */ - ol->msscof = DB_LSOMSS(mp); + ol->msscof = mss; if (mblk != mp) { ret = ol->hlen; } + } else if (flags & HCK_PARTIALCKSUM) { + ol->om = VMXNET3_OM_CSUM; + ol->hlen = start + ethLen; + ol->msscof = stuff + ethLen; } + } return ret; |