View | Details | Raw Unified | Return to bug 245865 | Differences between
and this patch

Collapse All | Expand All

(-)b/vboxvfs.h (-3 / +4 lines)
Lines 224-229 struct vboxfs_node { Link Here
224
	struct vnode		*sf_vnode;	/* vnode if active */
224
	struct vnode		*sf_vnode;	/* vnode if active */
225
	sfp_file_t		*sf_file;	/* non NULL if open */
225
	sfp_file_t		*sf_file;	/* non NULL if open */
226
	struct vboxfs_node	*sf_parent;	/* parent sfnode of this one */
226
	struct vboxfs_node	*sf_parent;	/* parent sfnode of this one */
227
	uint32_t		sf_opencnt;	/* sf_file reference counter */
227
	uint16_t		sf_children;	/* number of children sfnodes */
228
	uint16_t		sf_children;	/* number of children sfnodes */
228
	uint8_t			sf_type;	/* VDIR or VREG */
229
	uint8_t			sf_type;	/* VDIR or VREG */
229
	uint8_t			sf_vpstate;	/* XXX: ADD COMMENT */
230
	uint8_t			sf_vpstate;	/* XXX: ADD COMMENT */
Lines 232-238 struct vboxfs_node { Link Here
232
	uint64_t		sf_stat_time;	/* last-modified time of sf_stat */
233
	uint64_t		sf_stat_time;	/* last-modified time of sf_stat */
233
	sffs_dirents_t		*sf_dir_list;	/* list of entries for this directory */
234
	sffs_dirents_t		*sf_dir_list;	/* list of entries for this directory */
234
235
235
	/* interlock to protect sf_vpstate */
236
	/* interlock to protect sf_vpstate, sf_file and sf_opencnt */
236
	struct mtx		sf_interlock;
237
	struct mtx		sf_interlock;
237
};
238
};
238
239
Lines 340-346 typedef struct sffs_fsinfo { Link Here
340
extern int sfprov_get_fsinfo(sfp_mount_t *, sffs_fsinfo_t *);
341
extern int sfprov_get_fsinfo(sfp_mount_t *, sffs_fsinfo_t *);
341
342
342
extern int sfprov_create(sfp_mount_t *, char *path, mode_t mode,
343
extern int sfprov_create(sfp_mount_t *, char *path, mode_t mode,
343
    sfp_file_t **fp, sffs_stat_t *stat);
344
    sffs_stat_t *stat);
344
extern int sfprov_open(sfp_mount_t *, char *path, sfp_file_t **fp);
345
extern int sfprov_open(sfp_mount_t *, char *path, sfp_file_t **fp);
345
extern int sfprov_close(sfp_file_t *fp);
346
extern int sfprov_close(sfp_file_t *fp);
346
extern int sfprov_read(sfp_file_t *, char * buffer, uint64_t offset,
347
extern int sfprov_read(sfp_file_t *, char * buffer, uint64_t offset,
Lines 370-376 extern int sfprov_set_size(sfp_mount_t *, char *, uint64_t); Link Here
370
extern int sfprov_trunc(sfp_mount_t *, char *);
371
extern int sfprov_trunc(sfp_mount_t *, char *);
371
extern int sfprov_remove(sfp_mount_t *, char *path, u_int is_link);
372
extern int sfprov_remove(sfp_mount_t *, char *path, u_int is_link);
372
extern int sfprov_mkdir(sfp_mount_t *, char *path, mode_t mode,
373
extern int sfprov_mkdir(sfp_mount_t *, char *path, mode_t mode,
373
    sfp_file_t **fp, sffs_stat_t *stat);
374
    sffs_stat_t *stat);
374
extern int sfprov_rmdir(sfp_mount_t *, char *path);
375
extern int sfprov_rmdir(sfp_mount_t *, char *path);
375
extern int sfprov_rename(sfp_mount_t *, char *from, char *to, u_int is_dir);
376
extern int sfprov_rename(sfp_mount_t *, char *from, char *to, u_int is_dir);
376
377
(-)b/vboxvfs_prov.c (-11 / +2 lines)
Lines 305-311 sfprov_create( Link Here
305
	sfp_mount_t *mnt,
305
	sfp_mount_t *mnt,
306
	char *path,
306
	char *path,
307
	mode_t mode,
307
	mode_t mode,
308
	sfp_file_t **fp,
309
	sffs_stat_t *stat)
308
	sffs_stat_t *stat)
310
{
309
{
311
	int rc;
310
	int rc;
Lines 330-339 sfprov_create( Link Here
330
			return (EEXIST);
329
			return (EEXIST);
331
		return (ENOENT);
330
		return (ENOENT);
332
	}
331
	}
333
	newfp = malloc(sizeof(sfp_file_t), M_VBOXVFS, M_WAITOK | M_ZERO);
332
	(void)VbglR0SfClose(&vbox_client, &mnt->map, parms.Handle);
334
	newfp->handle = parms.Handle;
335
	newfp->map = mnt->map;
336
	*fp = newfp;
337
	sfprov_stat_from_info(stat, &parms.Info);
333
	sfprov_stat_from_info(stat, &parms.Info);
338
	return (0);
334
	return (0);
339
}
335
}
Lines 710-723 sfprov_mkdir( Link Here
710
	sfp_mount_t *mnt,
706
	sfp_mount_t *mnt,
711
	char *path,
707
	char *path,
712
	mode_t mode,
708
	mode_t mode,
713
	sfp_file_t **fp,
714
	sffs_stat_t *stat)
709
	sffs_stat_t *stat)
715
{
710
{
716
	int rc;
711
	int rc;
717
	SHFLCREATEPARMS parms;
712
	SHFLCREATEPARMS parms;
718
	SHFLSTRING *str;
713
	SHFLSTRING *str;
719
	int size;
714
	int size;
720
	sfp_file_t *newfp;
721
715
722
	str = sfprov_string(path, &size);
716
	str = sfprov_string(path, &size);
723
	parms.Handle = SHFL_HANDLE_NIL;
717
	parms.Handle = SHFL_HANDLE_NIL;
Lines 735-744 sfprov_mkdir( Link Here
735
			return (EEXIST);
729
			return (EEXIST);
736
		return (ENOENT);
730
		return (ENOENT);
737
	}
731
	}
738
	newfp = malloc(sizeof(sfp_file_t), M_VBOXVFS, M_WAITOK | M_ZERO);
732
	(void)VbglR0SfClose(&vbox_client, &mnt->map, parms.Handle);
739
	newfp->handle = parms.Handle;
740
	newfp->map = mnt->map;
741
	*fp = newfp;
742
	sfprov_stat_from_info(stat, &parms.Info);
733
	sfprov_stat_from_info(stat, &parms.Info);
743
	return (0);
734
	return (0);
744
}
735
}
(-)b/vboxvfs_vnops.c (-58 / +110 lines)
Lines 55-61 static vop_write_t vboxfs_write; Link Here
55
static vop_fsync_t	vboxfs_fsync;
55
static vop_fsync_t	vboxfs_fsync;
56
static vop_remove_t	vboxfs_remove;
56
static vop_remove_t	vboxfs_remove;
57
static vop_link_t	vboxfs_link;
57
static vop_link_t	vboxfs_link;
58
static vop_cachedlookup_t	vboxfs_lookup;
58
static vop_lookup_t	vboxfs_lookup;
59
static vop_cachedlookup_t	vboxfs_cachedlookup;
59
static vop_rename_t	vboxfs_rename;
60
static vop_rename_t	vboxfs_rename;
60
static vop_mkdir_t	vboxfs_mkdir;
61
static vop_mkdir_t	vboxfs_mkdir;
61
static vop_rmdir_t	vboxfs_rmdir;
62
static vop_rmdir_t	vboxfs_rmdir;
Lines 82-89 struct vop_vector vboxfs_vnodeops = { Link Here
82
	.vop_inactive	= vboxfs_inactive,
83
	.vop_inactive	= vboxfs_inactive,
83
	.vop_ioctl	= vboxfs_ioctl,
84
	.vop_ioctl	= vboxfs_ioctl,
84
	.vop_link	= vboxfs_link,
85
	.vop_link	= vboxfs_link,
85
	.vop_lookup	= vfs_cache_lookup,
86
	.vop_lookup	= vboxfs_lookup,
86
	.vop_cachedlookup	= vboxfs_lookup,
87
	.vop_cachedlookup	= vboxfs_cachedlookup,
87
	.vop_mkdir	= vboxfs_mkdir,
88
	.vop_mkdir	= vboxfs_mkdir,
88
	.vop_mknod	= VOP_EOPNOTSUPP,
89
	.vop_mknod	= VOP_EOPNOTSUPP,
89
	.vop_open	= vboxfs_open,
90
	.vop_open	= vboxfs_open,
Lines 386-398 static char * Link Here
386
sfnode_construct_path(struct vboxfs_node *node, char *tail, int len)
387
sfnode_construct_path(struct vboxfs_node *node, char *tail, int len)
387
{
388
{
388
	char *p;
389
	char *p;
390
	size_t dstsz;
389
391
390
	if (len <= 2 && tail[0] == '.' && (len == 1 || tail[1] == '.'))
392
	if (len <= 2 && tail[0] == '.' && (len == 1 || tail[1] == '.'))
391
		panic("construct path for %s", tail);
393
		panic("construct path for %s", tail);
392
	p = malloc(strlen(node->sf_path) + 1 + len + 1, M_VBOXVFS, M_WAITOK);
394
	dstsz = strlen(node->sf_path) + 1 + len + 1;
395
	p = malloc(dstsz, M_VBOXVFS, M_WAITOK);
393
	strcpy(p, node->sf_path);
396
	strcpy(p, node->sf_path);
394
	strcat(p, "/");
397
	strcat(p, "/");
395
	strcat(p, tail);
398
	strlcat(p, tail, dstsz);
396
	return (p);
399
	return (p);
397
}
400
}
398
401
Lines 449-471 vfsnode_clear_dir_list(struct vboxfs_node *np) Link Here
449
	}
452
	}
450
}
453
}
451
454
455
static int
456
vboxfs_get_sfp_file(struct vboxfs_node *np)
457
{
458
	sfp_file_t *fp;
459
	int error;
460
461
	fp = NULL;
462
	VBOXFS_NODE_LOCK(np);
463
	for (;;) {
464
		if (np->sf_file != NULL) {
465
			if (fp != NULL)
466
				(void) sfprov_close(fp);
467
			np->sf_opencnt++;
468
			fp = np->sf_file;
469
			break;
470
		} else if (fp != NULL) {
471
			np->sf_file = fp;
472
			KASSERT(np->sf_opencnt == 0,
473
				("np %p opencnt (%d) must be zero.",
474
				 np, np->sf_opencnt));
475
			np->sf_opencnt = 1;
476
			break;
477
		}
478
		VBOXFS_NODE_UNLOCK(np);
479
		error = sfprov_open(np->vboxfsmp->sf_handle, np->sf_path, &fp);
480
		if (error != 0)
481
			return (error);
482
		VBOXFS_NODE_LOCK(np);
483
	}
484
	VBOXFS_NODE_UNLOCK(np);
485
486
	return (0);
487
}
488
489
static void
490
vboxfs_put_sfp_file(struct vboxfs_node *np)
491
{
492
	VBOXFS_NODE_LOCK(np);
493
	np->sf_opencnt--;
494
	if (np->sf_opencnt == 0) {
495
		(void) sfprov_close(np->sf_file);
496
		np->sf_file = NULL;
497
	}
498
	VBOXFS_NODE_UNLOCK(np);
499
}
500
452
static int
501
static int
453
vboxfs_open(struct vop_open_args *ap)
502
vboxfs_open(struct vop_open_args *ap)
454
{
503
{
455
	struct vboxfs_node *np;
504
	struct vboxfs_node *np;
456
	sfp_file_t *fp;
457
	int error;
505
	int error;
458
506
459
	MPASS(VOP_ISLOCKED(vp));
507
	MPASS(VOP_ISLOCKED(vp));
460
508
461
	np = VP_TO_VBOXFS_NODE(ap->a_vp);
509
	np = VP_TO_VBOXFS_NODE(ap->a_vp);
462
	error = sfprov_open(np->vboxfsmp->sf_handle, np->sf_path, &fp);
510
	error = vboxfs_get_sfp_file(np);
463
	if (error != 0)
511
	if (error != 0)
464
		goto out;
512
		goto out;
465
513
466
	np->sf_file = fp;
467
	vnode_create_vobject(ap->a_vp, 0, ap->a_td);
514
	vnode_create_vobject(ap->a_vp, 0, ap->a_td);
468
469
out:
515
out:
470
	MPASS(VOP_ISLOCKED(vp));
516
	MPASS(VOP_ISLOCKED(vp));
471
517
Lines 499-508 vboxfs_close(struct vop_close_args *ap) Link Here
499
545
500
	vfsnode_invalidate_stat_cache(np);
546
	vfsnode_invalidate_stat_cache(np);
501
547
502
	if (np->sf_file != NULL && vp->v_usecount <= 1) {
548
	vboxfs_put_sfp_file(np);
503
		(void) sfprov_close(np->sf_file);
504
		np->sf_file = NULL;
505
	}
506
549
507
	return (0);
550
	return (0);
508
}
551
}
Lines 684-689 vboxfs_read(struct vop_read_args *ap) Link Here
684
	if (tmpbuf == 0)
727
	if (tmpbuf == 0)
685
		return (ENOMEM);
728
		return (ENOMEM);
686
729
730
	/*
731
	 * XXX VOP_READ() is called without VOP_OPEN() on exec case.
732
	 * We need to ensure the file is opened here.
733
	 */
734
	error = vboxfs_get_sfp_file(np);
735
	if (error != 0)	/* Maybe removed on the host. */
736
		return (EIO);
687
	do {
737
	do {
688
		offset = uio->uio_offset;
738
		offset = uio->uio_offset;
689
		done = bytes = min(PAGE_SIZE, uio->uio_resid);
739
		done = bytes = min(PAGE_SIZE, uio->uio_resid);
Lines 692-697 vboxfs_read(struct vop_read_args *ap) Link Here
692
		if (error == 0 && done > 0)
742
		if (error == 0 && done > 0)
693
			error = uiomove(tmpbuf, done, uio);
743
			error = uiomove(tmpbuf, done, uio);
694
	} while (error == 0 && uio->uio_resid > 0 && done > 0);
744
	} while (error == 0 && uio->uio_resid > 0 && done > 0);
745
	vboxfs_put_sfp_file(np);
695
746
696
	contigfree(tmpbuf, PAGE_SIZE, M_DEVBUF);
747
	contigfree(tmpbuf, PAGE_SIZE, M_DEVBUF);
697
748
Lines 771-777 vboxfs_create(struct vop_create_args *ap) Link Here
771
	sffs_stat_t	stat;
822
	sffs_stat_t	stat;
772
	char	*fullpath = NULL;
823
	char	*fullpath = NULL;
773
	struct vboxfs_node *dir = VP_TO_VBOXFS_NODE(dvp);
824
	struct vboxfs_node *dir = VP_TO_VBOXFS_NODE(dvp);
774
	sfp_file_t *fp;
775
	int error;
825
	int error;
776
	struct 	vboxfs_mnt *vboxfsmp = dir->vboxfsmp;
826
	struct 	vboxfs_mnt *vboxfsmp = dir->vboxfsmp;
777
827
Lines 779-785 vboxfs_create(struct vop_create_args *ap) Link Here
779
829
780
	fullpath = sfnode_construct_path(dir, cnp->cn_nameptr, cnp->cn_namelen);
830
	fullpath = sfnode_construct_path(dir, cnp->cn_nameptr, cnp->cn_namelen);
781
	error = sfprov_create(dir->vboxfsmp->sf_handle, fullpath, vap->va_mode,
831
	error = sfprov_create(dir->vboxfsmp->sf_handle, fullpath, vap->va_mode,
782
	    &fp, &stat);
832
	    &stat);
783
833
784
	if (error)
834
	if (error)
785
		goto out;
835
		goto out;
Lines 816-837 vboxfs_remove(struct vop_remove_args *ap) Link Here
816
	np = VP_TO_VBOXFS_NODE(vp);
866
	np = VP_TO_VBOXFS_NODE(vp);
817
	dir = VP_TO_VBOXFS_NODE(vp);
867
	dir = VP_TO_VBOXFS_NODE(vp);
818
868
819
	/*
820
	 * If anything else is using this vnode, then fail the remove.
821
	 * Why?  Windows hosts can't sfprov_remove() a file that is open,
822
	 * so we have to sfprov_close() it first.
823
	 * There is no errno for this - since it's not a problem on UNIX,
824
	 * but ETXTBSY is the closest.
825
	 */
826
	if (np->sf_file != NULL) {
827
		if (vp->v_usecount > 1) {
828
			error = ETXTBSY;
829
			goto out;
830
		}
831
		sfprov_close(np->sf_file);
832
		np->sf_file = NULL;
833
	}
834
835
	error = sfprov_remove(np->vboxfsmp->sf_handle, np->sf_path,
869
	error = sfprov_remove(np->vboxfsmp->sf_handle, np->sf_path,
836
	    np->sf_type == VLNK);
870
	    np->sf_type == VLNK);
837
871
Lines 938-944 vboxfs_mkdir(struct vop_mkdir_args *ap) Link Here
938
	sffs_stat_t	stat;
972
	sffs_stat_t	stat;
939
	char	*fullpath = NULL;
973
	char	*fullpath = NULL;
940
	struct vboxfs_node *dir = VP_TO_VBOXFS_NODE(dvp);
974
	struct vboxfs_node *dir = VP_TO_VBOXFS_NODE(dvp);
941
	sfp_file_t *fp;
942
	int error;
975
	int error;
943
	struct 	vboxfs_mnt *vboxfsmp = dir->vboxfsmp;
976
	struct 	vboxfs_mnt *vboxfsmp = dir->vboxfsmp;
944
977
Lines 946-952 vboxfs_mkdir(struct vop_mkdir_args *ap) Link Here
946
979
947
	fullpath = sfnode_construct_path(dir, cnp->cn_nameptr, cnp->cn_namelen);
980
	fullpath = sfnode_construct_path(dir, cnp->cn_nameptr, cnp->cn_namelen);
948
	error = sfprov_mkdir(dir->vboxfsmp->sf_handle, fullpath, vap->va_mode,
981
	error = sfprov_mkdir(dir->vboxfsmp->sf_handle, fullpath, vap->va_mode,
949
	    &fp, &stat);
982
	    &stat);
950
983
951
	if (error)
984
	if (error)
952
		goto out;
985
		goto out;
Lines 980-1001 vboxfs_rmdir(struct vop_rmdir_args *ap) Link Here
980
	np = VP_TO_VBOXFS_NODE(vp);
1013
	np = VP_TO_VBOXFS_NODE(vp);
981
	dir = VP_TO_VBOXFS_NODE(vp);
1014
	dir = VP_TO_VBOXFS_NODE(vp);
982
1015
983
	/*
984
	 * If anything else is using this vnode, then fail the remove.
985
	 * Why?  Windows hosts can't sfprov_remove() a file that is open,
986
	 * so we have to sfprov_close() it first.
987
	 * There is no errno for this - since it's not a problem on UNIX,
988
	 * but ETXTBSY is the closest.
989
	 */
990
	if (np->sf_file != NULL) {
991
		if (vp->v_usecount > 1) {
992
			error = ETXTBSY;
993
			goto out;
994
		}
995
		sfprov_close(np->sf_file);
996
		np->sf_file = NULL;
997
	}
998
999
	error = sfprov_rmdir(np->vboxfsmp->sf_handle, np->sf_path);
1016
	error = sfprov_rmdir(np->vboxfsmp->sf_handle, np->sf_path);
1000
1017
1001
#if 0
1018
#if 0
Lines 1235-1251 vboxfs_ioctl(struct vop_ioctl_args *ap) Link Here
1235
 * Lookup an entry in a directory and create a new vnode if found.
1252
 * Lookup an entry in a directory and create a new vnode if found.
1236
 */
1253
 */
1237
static int
1254
static int
1238
vboxfs_lookup(struct vop_cachedlookup_args /* {
1255
vboxfs_lookup1(struct vnode *dvp, struct vnode **vpp,
1239
		struct vnodeop_desc *a_desc;
1256
    struct componentname *cnp)
1240
		struct vnode *a_dvp;
1241
		struct vnode **a_vpp;
1242
		struct componentname *a_cnp;
1243
	} */ *ap)
1244
{
1257
{
1245
	struct 	componentname *cnp = ap->a_cnp;
1246
	struct 	vnode *dvp = ap->a_dvp;		/* the directory vnode */
1247
	char	*nameptr = cnp->cn_nameptr;	/* the name of the file or directory */
1258
	char	*nameptr = cnp->cn_nameptr;	/* the name of the file or directory */
1248
	struct	vnode **vpp = ap->a_vpp;	/* the vnode we found or NULL */
1249
	struct  vnode *tdp = NULL;
1259
	struct  vnode *tdp = NULL;
1250
	struct 	vboxfs_node *node = VP_TO_VBOXFS_NODE(dvp);
1260
	struct 	vboxfs_node *node = VP_TO_VBOXFS_NODE(dvp);
1251
	struct 	vboxfs_mnt *vboxfsmp = node->vboxfsmp;
1261
	struct 	vboxfs_mnt *vboxfsmp = node->vboxfsmp;
Lines 1258-1263 vboxfs_lookup(struct vop_cachedlookup_args /* { Link Here
1258
	int 	lkflags = cnp->cn_lkflags;
1268
	int 	lkflags = cnp->cn_lkflags;
1259
	char	*fullpath = NULL;
1269
	char	*fullpath = NULL;
1260
1270
1271
	*vpp = NULLVP;
1261
	error = ENOENT;
1272
	error = ENOENT;
1262
	if (cnp->cn_flags & ISDOTDOT) {
1273
	if (cnp->cn_flags & ISDOTDOT) {
1263
		error = vn_vget_ino_gen(dvp, vboxfs_vn_get_ino_alloc,
1274
		error = vn_vget_ino_gen(dvp, vboxfs_vn_get_ino_alloc,
Lines 1329-1334 out: Link Here
1329
	return (error);
1340
	return (error);
1330
}
1341
}
1331
1342
1343
static int
1344
vboxfs_cachedlookup(struct vop_cachedlookup_args *ap)
1345
{
1346
	return (vboxfs_lookup1(ap->a_dvp, ap->a_vpp, ap->a_cnp));
1347
}
1348
1349
static int
1350
vboxfs_lookup(struct vop_lookup_args *ap)
1351
{
1352
	struct vnode *dvp = ap->a_dvp;
1353
	struct componentname *cnp = ap->a_cnp;
1354
	struct vboxfs_node *np = VP_TO_VBOXFS_NODE(dvp);
1355
	struct timespec mtime;
1356
	int flags = cnp->cn_flags;
1357
	int error;
1358
1359
	if (dvp->v_type != VDIR)
1360
		return (ENOTDIR);
1361
1362
	if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
1363
	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
1364
		return (EROFS);
1365
1366
	error = vn_dir_check_exec(dvp, cnp);
1367
	if (error != 0)
1368
		return (error);
1369
1370
	/* Check if the directory is unmodified on the host. */
1371
	mtime = np->sf_stat.sf_mtime;
1372
	error = vsfnode_update_stat_cache(np);
1373
	if (error == 0) {
1374
		if (mtime.tv_sec == np->sf_stat.sf_mtime.tv_sec &&
1375
		    mtime.tv_nsec == np->sf_stat.sf_mtime.tv_nsec)
1376
			return (vfs_cache_lookup(ap));
1377
	}
1378
1379
	cache_purge(dvp);
1380
1381
	return (vboxfs_lookup1(ap->a_dvp, ap->a_vpp, ap->a_cnp));
1382
}
1383
1332
static int
1384
static int
1333
vboxfs_inactive(struct vop_inactive_args *ap)
1385
vboxfs_inactive(struct vop_inactive_args *ap)
1334
{
1386
{

Return to bug 245865