From owner-svn-soc-all@FreeBSD.ORG Wed Jul 24 13:01:54 2013 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id D7865E3C for ; Wed, 24 Jul 2013 13:01:54 +0000 (UTC) (envelope-from oleksandr@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id BA82C2E89 for ; Wed, 24 Jul 2013 13:01:54 +0000 (UTC) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.7/8.14.7) with ESMTP id r6OD1sYn088945 for ; Wed, 24 Jul 2013 13:01:54 GMT (envelope-from oleksandr@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.7/8.14.6/Submit) id r6OD1stR088941 for svn-soc-all@FreeBSD.org; Wed, 24 Jul 2013 13:01:54 GMT (envelope-from oleksandr@FreeBSD.org) Date: Wed, 24 Jul 2013 13:01:54 GMT Message-Id: <201307241301.r6OD1stR088941@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to oleksandr@FreeBSD.org using -f From: oleksandr@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r255111 - soc2013/oleksandr/ports/emulators/virtualbox-ose-additions/files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 Jul 2013 13:01:54 -0000 Author: oleksandr Date: Wed Jul 24 13:01:54 2013 New Revision: 255111 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=255111 Log: Implemented access, open and close function for vboxvfs_vnops Modified: soc2013/oleksandr/ports/emulators/virtualbox-ose-additions/files/patch-src-VBox-Additions-freebsd.kmk Modified: soc2013/oleksandr/ports/emulators/virtualbox-ose-additions/files/patch-src-VBox-Additions-freebsd.kmk ============================================================================== --- soc2013/oleksandr/ports/emulators/virtualbox-ose-additions/files/patch-src-VBox-Additions-freebsd.kmk Wed Jul 24 11:32:58 2013 (r255110) +++ soc2013/oleksandr/ports/emulators/virtualbox-ose-additions/files/patch-src-VBox-Additions-freebsd.kmk Wed Jul 24 13:01:54 2013 (r255111) @@ -12,7 +12,7 @@ #include #include #include -@@ -33,7 +32,28 @@ +@@ -33,7 +32,29 @@ #include #include @@ -21,6 +21,7 @@ +#include +#include +#include ++#include +#include +#include +#include @@ -41,7 +42,7 @@ /* * Prototypes for VBOXVFS vnode operations */ -@@ -56,6 +76,7 @@ +@@ -56,6 +77,7 @@ static vop_symlink_t vboxvfs_symlink; static vop_readdir_t vboxvfs_readdir; static vop_strategy_t vboxvfs_strategy; @@ -49,7 +50,7 @@ static vop_print_t vboxvfs_print; static vop_pathconf_t vboxvfs_pathconf; static vop_advlock_t vboxvfs_advlock; -@@ -65,177 +86,633 @@ +@@ -65,177 +87,755 @@ static vop_inactive_t vboxvfs_inactive; static vop_putpages_t vboxvfs_putpages; static vop_reclaim_t vboxvfs_reclaim; @@ -118,19 +119,68 @@ + .vop_symlink = vboxvfs_symlink, + .vop_write = vboxvfs_write, }; ++/* ++ * uid and gid in sffs determine owner and group for all files. ++ */ ++#if 0 ++static int ++sfnode_access(sfnode_t *node, mode_t mode, cred_t *cr) ++{ ++ sffs_data_t *sffs = node->sf_sffs; ++ mode_t m; ++ int shift = 0; ++ int error; ++ vnode_t *vp; ++ ASSERT(MUTEX_HELD(&sffs_lock)); ++ ++ /* ++ * get the mode from the cache or provider ++ */ ++ if (sfnode_stat_cached(node)) ++ error = 0; ++ else ++ error = sfnode_update_stat_cache(node); ++ m = (error == 0) ? node->sf_stat.sf_mode : 0; ++ ++ /* ++ * mask off the permissions based on uid/gid ++ */ ++ if (crgetuid(cr) != sffs->sf_uid) { ++ shift += 3; ++ if (groupmember(sffs->sf_gid, cr) == 0) ++ shift += 3; ++ } ++ mode &= ~(m << shift); ++ ++ if (mode == 0) { ++ error = 0; ++ } else { ++ vp = sfnode_get_vnode(node); ++ error = secpolicy_vnode_access(cr, vp, sffs->sf_uid, mode); ++ VN_RELE(vp); ++ } ++ return (error); ++} ++#endif static int vboxvfs_access(struct vop_access_args *ap) { - return 0; +#if 0 -+ struct vnode *vp; -+ accmode_t accmode; ++ sfnode_t *node = VN2SFN(vp->a_vp); ++ int error; + -+ vp = ap->a_vp; -+ accmode = ap->a_accmode; ++ mutex_enter(&sffs_lock); ++ error = sfnode_access(node, mode, cr); ++ mutex_exit(&sffs_lock); + -+ if (accmode & VWRITE) { -+ switch (vp->v_type) { ++ return (error); ++#endif ++ struct vnode *vp = ap->a_vp; ++ accmode_t accmode = ap->a_accmode; ++ ++ if ((accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { ++ switch (vp->v_type) { + case VDIR: + case VLNK: + case VREG: @@ -139,36 +189,109 @@ + default: + break; + } -+ } -+ ++ } + return (vaccess(vp->v_type, 0444, 0, 0, + accmode, ap->a_cred, NULL)); -+#endif -+ return (0); } ++/* ++ * Clears the (cached) directory listing for the node. ++ */ ++static void ++vfsnode_clear_dir_list(struct vboxvfs_node *np) ++{ ++ while (np->sf_dir_list != NULL) { ++ sffs_dirents_t *next = np->sf_dir_list->sf_next; ++ free(np->sf_dir_list, M_VBOXVFS); ++ np->sf_dir_list = next; ++ } ++} ++ ++/* ++ * Open the provider file associated with a vnode. Holding the file open is ++ * the only way we have of trying to have a vnode continue to refer to the ++ * same host file in the host in light of the possibility of host side renames. ++ */ ++static void ++vfsnode_open(struct vboxvfs_node *np) ++{ ++ int error; ++ sfp_file_t *fp; ++ ++ if (np->sf_file != NULL) ++ return; ++ error = sfprov_open(np->vboxvfsmp->sf_handle, np->sf_path, &fp); ++ if (error == 0) ++ np->sf_file = fp; ++} ++ static int vboxvfs_open(struct vop_open_args *ap) { - return 0; -+#if 0 -+ struct vboxvfs_node *np = VTON(ap->a_vp); ++ struct vnode *vp = ap->a_vp; ++ struct vboxvfs_node *np; ++ int error = 0; + off_t fsize; + ++ np = VTOVBOXFS(vp); ++ vfsnode_open(np); ++ if (np->sf_file == NULL) ++ error = EINVAL; ++ + fsize = np->vboxvfsmp->size; + vnode_create_vobject(ap->a_vp, fsize, ap->a_td); -+#endif -+ return (0); ++ ++ return (error); } ++#if 0 ++static uint64_t ++sfnode_cur_time_usec(void) ++{ ++ clock_t now = drv_hztousec(ddi_get_lbolt()); ++ return now; ++} ++static int ++sfnode_stat_cached(sfnode_t *node) ++{ ++ return (sfnode_cur_time_usec() - node->sf_stat_time) < ++ node->sf_sffs->sf_stat_ttl * 1000L; ++} ++#endif ++static void ++vfsnode_invalidate_stat_cache(struct vboxvfs_node *np) ++{ ++ np->sf_stat_time = 0; ++} ++ static int vboxvfs_close(struct vop_close_args *ap) { - return 0; -+#if 0 -+ int rc; -+ -+ rc = vboxCallClose(&vbox_client, &fp->map, fp->handle); -+ kmem_free(fp, sizeof(sfp_file_t)); -+#endif ++ ++ struct vnode *vp = ap->a_vp; ++ struct vboxvfs_node *np; ++ ++ np = VTOVBOXFS(vp); ++ ++ /* ++ * Free the directory entries for the node. We do this on this call ++ * here because the directory node may not become inactive for a long ++ * time after the readdir is over. Case in point, if somebody cd's into ++ * the directory then it won't become inactive until they cd away again. ++ * In such a case we would end up with the directory listing not getting ++ * updated (i.e. the result of 'ls' always being the same) until they ++ * change the working directory. ++ */ ++ vfsnode_clear_dir_list(np); ++ ++ vfsnode_invalidate_stat_cache(np); ++ ++ if (np->sf_file != NULL) ++ { ++ (void)sfprov_close(np->sf_file); ++ np->sf_file = NULL; ++ } ++ + return (0); } @@ -744,7 +867,7 @@ =================================================================== --- src/VBox/Additions/freebsd/vboxvfs/vboxvfs.h (revision 4) +++ src/VBox/Additions/freebsd/vboxvfs/vboxvfs.h (working copy) -@@ -21,24 +21,130 @@ +@@ -21,46 +21,193 @@ #define VBOXVFS_VFSNAME "vboxvfs" #define VBOXVFS_VERSION 1 @@ -761,8 +884,8 @@ - int ttl; -}; +/** Helper macros */ -+#define VFSTOVBOXFS(mp) ((vboxvfs_mnt_t *)((mp)->mnt_data)) -+#define VTON(vp) ((vboxvfs_node *)((vp)->v_data)) ++#define VFSTOVBOXFS(mp) ((struct vboxvfs_mnt *)((mp)->mnt_data)) ++#define VTOVBOXFS(vp) ((struct vboxvfs_node *)(vp)->v_data) +MALLOC_DECLARE(M_VBOXVFS); + @@ -788,7 +911,6 @@ +#include "../../../../../include/iprt/time.h" +#include "../../../../../include/iprt/types.h" +#include "../../../../../include/iprt/uni.h" -+#include "../../common/VBoxGuestLib/SysHlp.h" +#include "../../../../../include/iprt/nocrt/limits.h" +#include "../../../../../include/iprt/alloc.h" +#include "../../../../../include/iprt/asm.h" @@ -816,22 +938,81 @@ #include -#include +#include ++#include -struct vboxvfsmount { +- uid_t uid; +- gid_t gid; +- mode_t file_mode; +- mode_t dir_mode; +- struct mount *mp; +- struct ucred *owner; +- u_int flags; +- long nextino; +- int caseopt; +- int didrele; +/* + * representation of an active mount point + */ +struct sfp_mount { + VBSFMAP map; + }; + +-/* structs - stolen from the linux shared module code */ ++/* ++ * Mount / Unmount a shared folder. ++ * ++ * sfprov_mount() takes as input the connection pointer and the name of ++ * the shared folder. On success, it returns zero and supplies an ++ * sfp_mount_t handle. On failure it returns any relevant errno value. ++ * ++ * sfprov_unmount() unmounts the mounted file system. It returns 0 on ++ * success and any relevant errno on failure. ++ */ ++typedef struct sfp_mount sfp_mount_t; ++ ++struct sfp_file { ++ SHFLHANDLE handle; ++ VBSFMAP map; /* need this again for the close operation */ +}; + -+typedef struct sfp_mount sfp_mount_t; ++typedef struct sfp_file sfp_file_t; ++ ++/* ++ * File operations: open/close/read/write/etc. ++ * ++ * open/create can return any relevant errno, however ENOENT ++ * generally means that the host file didn't exist. ++ */ ++typedef struct sffs_stat { ++ mode_t sf_mode; ++ off_t sf_size; ++ off_t sf_alloc; ++ struct timespec sf_atime; ++ struct timespec sf_mtime; ++ struct timespec sf_ctime; ++} sffs_stat_t; + ++/* ++ * Read directory entries. ++ */ ++/* ++ * a singly linked list of buffers, each containing an array of stat's+dirent's. ++ * sf_len is length of the sf_entries array, in bytes. ++ */ ++typedef struct sffs_dirents { ++ struct sffs_dirents *sf_next; ++ unsigned long long int sf_len; ++ struct sffs_dirent { ++ sffs_stat_t sf_stat; ++ struct dirent sf_entry; /* this is variable length */ ++ } sf_entries[1]; ++} sffs_dirents_t; + +/* + * Shared Folders filesystem per-mount data structure. + */ -+typedef struct vboxvfs_mnt { ++struct vboxvfs_mnt { + struct mount *sf_vfsp; /* filesystem's vfs struct */ + struct vnode *sf_rootnode; /* of vnode of the root directory */ + uid_t sf_uid; /* owner of all shared folders */ @@ -846,7 +1027,30 @@ + char *sf_mntpath; /* name of mount point */ + sfp_mount_t *sf_handle; + uint64_t sf_ino; /* per FS ino generator */ -+} vboxvfs_mnt_t; ++ off_t size; ++}; ++ ++/* ++ * vboxvfs_node is the file system dependent vnode data for vboxsf. ++ * vboxvfs_node's also track all files ever accessed, both open and closed. ++ * It duplicates some of the information in vnode, since it holds ++ * information for files that may have been completely closed. ++ * ++ */ ++struct vboxvfs_node { ++ struct vboxvfs_mnt *vboxvfsmp; /* containing mounted file system */ ++ char *sf_path; /* full pathname to file or dir */ ++ uint64_t sf_ino; /* assigned unique ID number */ ++ struct vnode *sf_vnode; /* vnode if active */ ++ sfp_file_t *sf_file; /* non NULL if open */ ++ struct vboxvfs_node *sf_parent; /* parent sfnode of this one */ ++ uint16_t sf_children; /* number of children sfnodes */ ++ uint8_t sf_type; /* VDIR or VREG */ ++ uint8_t sf_is_stale; /* this is stale and should be purged */ ++ sffs_stat_t sf_stat; /* cached file attrs for this node */ ++ uint64_t sf_stat_time; /* last-modified time of sf_stat */ ++ sffs_dirents_t *sf_dir_list; /* list of entries for this directory */ ++}; + +struct vboxvfs_mount_info { + char name[MAX_HOST_NAME]; @@ -856,43 +1060,6 @@ + int ttl; +}; + -+#if 0 -+struct vboxvfs_mnt -+{ -+ VBSFMAP map; -+ int im_flags; -+ struct mount *im_mountp; -+ struct g_consumer *im_cp; -+ struct bufobj *im_bo; -+ struct cdev *im_dev; -+ struct vnode *im_devvp; -+ off_t size; -+ int bsize; -+ int bshift; -+ int bmask; -+ int use_devvp; -+}; -+#endif -+ -+/** VNode for VBoxVFS */ -+typedef struct vboxvfs_node -+{ -+ struct vnode *i_vnode; -+ struct vboxvfs_mnt *vboxvfsmp; -+ ino_t hash_id; -+} vboxvfs_vnode_t; -+#if 0 -+struct vboxvfs_mount { - uid_t uid; - gid_t gid; - mode_t file_mode; -@@ -50,17 +156,27 @@ - int caseopt; - int didrele; - }; -- --/* structs - stolen from the linux shared module code */ -+#endif struct sf_glob_info { - VBSFMAP map; + VBSFMAP map; @@ -910,17 +1077,104 @@ +/** Per-file system mount instance data. */ +typedef struct vboxvfs_globinfo +{ -+ VBSFMAP Map; -+ int Ttl; -+ int Uid; -+ int Gid; -+ struct mount *pVFS; -+ vboxvfs_vnode_t *pVNodeRoot; ++ VBSFMAP Map; ++ int Ttl; ++ int Uid; ++ int Gid; ++ struct mount *pVFS; ++ struct vboxvfs_node *pVNodeRoot; +} vboxvfs_globinfo_t; + struct sf_inode_info { SHFLSTRING *path; int force_restat; +@@ -86,6 +233,86 @@ + SHFLHANDLE handle; + }; + ++/* ++ * Initialization and termination. ++ * sfprov_connect() is called once before any other interfaces and returns ++ * a handle used in further calls. The argument should be SFPROV_VERSION ++ * from above. On failure it returns a NULL pointer. ++ * ++ * sfprov_disconnect() must only be called after all sf file systems have been ++ * unmounted. ++ */ ++typedef struct sfp_connection sfp_connection_t; ++ ++extern sfp_connection_t *sfprov_connect(int); ++extern void sfprov_disconnect(sfp_connection_t *); ++extern int sfprov_mount(sfp_connection_t *, char *, sfp_mount_t **); ++extern int sfprov_unmount(sfp_mount_t *); ++ ++/* ++ * query information about a mounted file system ++ */ ++typedef struct sffs_fsinfo { ++ uint64_t blksize; ++ uint64_t blksused; ++ uint64_t blksavail; ++ uint32_t maxnamesize; ++ uint32_t readonly; ++} sffs_fsinfo_t; ++ ++extern int sfprov_get_fsinfo(sfp_mount_t *, sffs_fsinfo_t *); ++ ++extern int sfprov_create(sfp_mount_t *, char *path, mode_t mode, ++ sfp_file_t **fp, sffs_stat_t *stat); ++extern int sfprov_open(sfp_mount_t *, char *path, sfp_file_t **fp); ++extern int sfprov_close(sfp_file_t *fp); ++extern int sfprov_read(sfp_file_t *, char * buffer, uint64_t offset, ++ uint32_t *numbytes); ++extern int sfprov_write(sfp_file_t *, char * buffer, uint64_t offset, ++ uint32_t *numbytes); ++extern int sfprov_fsync(sfp_file_t *fp); ++ ++ ++/* ++ * get/set information about a file (or directory) using pathname ++ */ ++extern int sfprov_get_mode(sfp_mount_t *, char *, mode_t *); ++extern int sfprov_get_size(sfp_mount_t *, char *, uint64_t *); ++extern int sfprov_get_atime(sfp_mount_t *, char *, struct timespec *); ++extern int sfprov_get_mtime(sfp_mount_t *, char *, struct timespec *); ++extern int sfprov_get_ctime(sfp_mount_t *, char *, struct timespec *); ++extern int sfprov_get_attr(sfp_mount_t *, char *, sffs_stat_t *); ++extern int sfprov_set_attr(sfp_mount_t *, char *, u_int, mode_t, ++ struct timespec, struct timespec, struct timespec); ++extern int sfprov_set_size(sfp_mount_t *, char *, uint64_t); ++ ++ ++/* ++ * File/Directory operations ++ */ ++extern int sfprov_trunc(sfp_mount_t *, char *); ++extern int sfprov_remove(sfp_mount_t *, char *path, u_int is_link); ++extern int sfprov_mkdir(sfp_mount_t *, char *path, mode_t mode, ++ sfp_file_t **fp, sffs_stat_t *stat); ++extern int sfprov_rmdir(sfp_mount_t *, char *path); ++extern int sfprov_rename(sfp_mount_t *, char *from, char *to, u_int is_dir); ++ ++ ++/* ++ * Symbolic link operations ++ */ ++extern int sfprov_set_show_symlinks(void); ++extern int sfprov_readlink(sfp_mount_t *, char *path, char *target, ++ size_t tgt_size); ++extern int sfprov_symlink(sfp_mount_t *, char *linkname, char *target, ++ sffs_stat_t *stat); ++ ++#define SFFS_DIRENTS_SIZE 8192 ++#define SFFS_DIRENTS_OFF (offsetof(sffs_dirents_t, sf_entries[0])) ++ ++/*extern int sfprov_readdir(sfp_mount_t *mnt, char *path, ++ sffs_dirents_t **dirents); */ ++ + #endif /* KERNEL */ + + #endif /* !___VBOXVFS_H___ */ Index: src/VBox/Additions/freebsd/vboxvfs/Makefile.kmk =================================================================== --- src/VBox/Additions/freebsd/vboxvfs/Makefile.kmk (revision 4) @@ -961,13 +1215,12 @@ #include #include #include -@@ -29,8 +29,35 @@ +@@ -29,10 +29,40 @@ #include #include -#include +#include "vboxvfs.h" -+#include "vboxvfs_prov.h" +#if 0 +#include +#include @@ -997,8 +1250,14 @@ + #define VFSMP2SFGLOBINFO(mp) ((struct sf_glob_info *)mp->mnt_data) ++#ifdef MALLOC_DECLARE ++MALLOC_DEFINE(M_VBOXVFS, "vboxvfs", "VBOX VFS"); ++#endif ++ static int vboxvfs_version = VBOXVFS_VERSION; -@@ -51,15 +78,15 @@ + + SYSCTL_NODE(_vfs, OID_AUTO, vboxvfs, CTLFLAG_RW, 0, "VirtualBox shared filesystem"); +@@ -51,15 +81,15 @@ static vfs_unmount_t vboxvfs_unmount; static struct vfsops vboxvfs_vfsops = { @@ -1023,7 +1282,7 @@ }; -@@ -66,193 +93,238 @@ +@@ -66,193 +96,238 @@ VFS_SET(vboxvfs_vfsops, vboxvfs, VFCF_NETWORK); MODULE_DEPEND(vboxvfs, vboxguest, 1, 1, 1); @@ -1358,7 +1617,7 @@ +int vboxvfs_statfs(struct mount *mp, struct statfs *sbp) { - return 0; -+ vboxvfs_mnt_t *vboxvfsmp; ++ struct vboxvfs_mnt *vboxvfsmp; + sffs_fsinfo_t fsinfo; +// dev32_t d32; + int error; @@ -1390,7 +1649,7 @@ =================================================================== --- src/VBox/Additions/freebsd/vboxvfs/vboxvfs_prov.c (revision 0) +++ src/VBox/Additions/freebsd/vboxvfs/vboxvfs_prov.c (working copy) -@@ -0,0 +1,1021 @@ +@@ -0,0 +1,1011 @@ +/** @file + * VirtualBox File System for FreeBSD Guests, provider implementation. + * Portions contributed by: Ronald. @@ -1429,15 +1688,10 @@ +#include +#include +#include -+#include -+#include "vboxvfs_prov.h" ++#include "vboxvfs.h" + +#define SFPROV_VERSION 1 + -+#ifdef MALLOC_DECLARE -+MALLOC_DEFINE(M_VBOXVFS, "vboxvfs", "VBOX VFS"); -+#endif -+ +static VBSFCLIENT vbox_client; + +static int sfprov_vbox2errno(int rc) @@ -1689,11 +1943,6 @@ + * open/create can return any relevant errno, however ENOENT + * generally means that the host file didn't exist. + */ -+struct sfp_file { -+ SHFLHANDLE handle; -+ VBSFMAP map; /* need this again for the close operation */ -+}; -+ +int +sfprov_create( + sfp_mount_t *mnt, @@ -2416,7 +2665,7 @@ =================================================================== --- src/VBox/Additions/freebsd/vboxvfs/vboxvfs_prov.h (revision 0) +++ src/VBox/Additions/freebsd/vboxvfs/vboxvfs_prov.h (working copy) -@@ -0,0 +1,152 @@ +@@ -0,0 +1,154 @@ +/* $Id: vboxfs_prov.h $ */ +/** @file + * VirtualBox File System for FreeBSD Guests, provider header. @@ -2469,6 +2718,7 @@ +extern sfp_connection_t *sfprov_connect(int); +extern void sfprov_disconnect(sfp_connection_t *); +extern int sfprov_mount(sfp_connection_t *, char *, sfp_mount_t **); ++ +extern int sfprov_unmount(sfp_mount_t *); + +/* @@ -2498,6 +2748,7 @@ + struct timespec sf_mtime; + struct timespec sf_ctime; +} sffs_stat_t; ++ +typedef struct sfp_file sfp_file_t; + +extern int sfprov_create(sfp_mount_t *, char *path, mode_t mode,