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 |
{ |