Changeset 30519 in vbox
- Timestamp:
- Jun 30, 2010 8:04:26 AM (15 years ago)
- Location:
- trunk/src/VBox/Additions/solaris/SharedFolders
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs.h
r28800 r30519 25 25 #define MAX_HOST_NAME 256 26 26 #define MAX_NLS_NAME 32 27 /** Default stat cache ttl (in ms) */ 28 #define DEF_STAT_TTL_MS 200 27 29 28 30 /** The module name. */ … … 33 35 #include "../../common/VBoxGuestLib/VBoxCalls.h" 34 36 #include <sys/vfs.h> 35 #include <sys/vfs_opreg.h>36 37 37 38 /** VNode for VBoxVFS */ -
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_mount.c
r28800 r30519 53 53 " uid=UID set the default file owner user id to UID\n" 54 54 " gid=GID set the default file owner group id to GID\n" 55 " stat_ttl=TTL set the \"time to live\" (in ms) for the stat caches (default %d)\n" 55 56 " ttl=TTL set the \"time to live\" to TID for the dentry\n" 56 57 " iocharset CHARSET use the character set CHARSET for i/o operations (default utf8)\n" 57 " convertcp CHARSET convert the shared folder name from the character set CHARSET to utf8\n\n" );58 " convertcp CHARSET convert the shared folder name from the character set CHARSET to utf8\n\n", DEF_STAT_TTL_MS); 58 59 fprintf(stderr, "Less common used options:\n" 59 60 " noexec,exec,nodev,dev,nosuid,suid\n"); -
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
r30504 r30519 825 825 sfp_mount_t *mnt, 826 826 char *path, 827 sffs_dirents_t **dirents) 827 sffs_dirents_t **dirents, 828 sffs_stats_t **stats) 828 829 { 829 830 int error; … … 840 841 uint32_t cnt; 841 842 sffs_dirents_t *cur_buf; 843 sffs_stats_t *cur_stats; 842 844 struct dirent64 *dirent; 845 sffs_stat_t *stat; 843 846 unsigned short reclen; 844 847 845 848 *dirents = NULL; 849 *stats = NULL; 846 850 847 851 error = sfprov_open(mnt, path, &fp); … … 850 854 851 855 /* 852 * Allocate the first dirents buffer.856 * Allocate the first dirents and stats buffers. 853 857 */ 854 858 *dirents = kmem_alloc(SFFS_DIRENTS_SIZE, KM_SLEEP); … … 860 864 cur_buf->sf_next = NULL; 861 865 cur_buf->sf_len = 0; 866 867 *stats = kmem_alloc(sizeof(**stats), KM_SLEEP); 868 if (*stats == NULL) { 869 error = (ENOSPC); 870 goto done; 871 } 872 cur_stats = *stats; 873 cur_stats->sf_next = NULL; 874 cur_stats->sf_num = 0; 862 875 863 876 /* … … 907 920 908 921 /* 909 * Create the dirent_t's for each name922 * Create the dirent_t's and save the stats for each name 910 923 */ 911 924 for (info = infobuff; (char *) info < (char *) infobuff + numbytes; nents--) { 912 /* expand buffer if we need more space */925 /* expand buffers if we need more space */ 913 926 reclen = DIRENT64_RECLEN(strlen(info->name.String.utf8)); 914 927 if (SFFS_DIRENTS_OFF + cur_buf->sf_len + reclen > SFFS_DIRENTS_SIZE) { … … 923 936 } 924 937 938 if (cur_stats->sf_num >= SFFS_STATS_LEN) { 939 cur_stats->sf_next = kmem_alloc(sizeof(**stats), KM_SLEEP); 940 if (cur_stats->sf_next == NULL) { 941 error = (ENOSPC); 942 goto done; 943 } 944 cur_stats = cur_stats->sf_next; 945 cur_stats->sf_next = NULL; 946 cur_stats->sf_num = 0; 947 } 948 925 949 /* create the dirent with the name, offset, and len */ 926 950 dirent = (dirent64_t *) … … 933 957 ++cnt; 934 958 959 /* save the stats */ 960 stat = &cur_stats->sf_stats[cur_stats->sf_num]; 961 ++cur_stats->sf_num; 962 963 sfprov_mode_from_fmode(&stat->sf_mode, info->Info.Attr.fMode); 964 stat->sf_size = info->Info.cbObject; 965 sfprov_ftime_from_timespec(&stat->sf_atime, &info->Info.AccessTime); 966 sfprov_ftime_from_timespec(&stat->sf_mtime, &info->Info.ModificationTime); 967 sfprov_ftime_from_timespec(&stat->sf_ctime, &info->Info.ChangeTime); 968 969 /* next info */ 935 970 size = offsetof (SHFLDIRINFO, name.String) + info->name.u16Size; 936 971 info = (SHFLDIRINFO *) ((uintptr_t) info + size); … … 951 986 *dirents = cur_buf; 952 987 } 988 while (*stats) { 989 cur_stats = (*stats)->sf_next; 990 kmem_free(*stats, sizeof(**stats)); 991 *stats = cur_stats; 992 } 953 993 } 954 994 if (infobuff != NULL) -
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h
r30504 r30519 123 123 } sffs_dirents_t; 124 124 125 extern int sfprov_readdir(sfp_mount_t *mnt, char *path, sffs_dirents_t **dirents);126 127 125 #define SFFS_DIRENTS_SIZE 8192 128 126 #define SFFS_DIRENTS_OFF (offsetof(sffs_dirents_t, sf_entries[0])) 127 #define SFFS_STATS_LEN 100 128 129 typedef struct sffs_stat { 130 mode_t sf_mode; 131 off_t sf_size; 132 timestruc_t sf_atime; 133 timestruc_t sf_mtime; 134 timestruc_t sf_ctime; 135 } sffs_stat_t; 136 137 typedef struct sffs_stats { 138 struct sffs_stats *sf_next; 139 len_t sf_num; 140 sffs_stat_t sf_stats[SFFS_STATS_LEN]; 141 } sffs_stats_t; 142 143 extern int sfprov_readdir(sfp_mount_t *mnt, char *path, sffs_dirents_t **dirents, 144 sffs_stats_t **stats); 129 145 130 146 #ifdef __cplusplus -
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c
r28800 r30519 36 36 #include "vboxfs_vnode.h" 37 37 #include "vboxfs_vfs.h" 38 #include "vboxfs.h" 38 39 39 40 #ifdef u … … 64 65 /* Option Cancels Opt Arg Flags Data */ 65 66 {"uid", NULL, NULL, MO_HASVALUE, NULL}, 66 {"gid", NULL, NULL, MO_HASVALUE, NULL} 67 {"gid", NULL, NULL, MO_HASVALUE, NULL}, 68 {"stat_ttl", NULL, NULL, MO_HASVALUE, NULL} 67 69 }; 68 70 … … 227 229 uid_t uid = 0; 228 230 gid_t gid = 0; 231 int stat_ttl = DEF_STAT_TTL_MS; 229 232 char *optval; 230 233 long val; … … 287 290 (gid_t)val == val) 288 291 gid = val; 292 293 /* 294 * ttl to use for stat caches 295 */ 296 if (vfs_optionisset(vfsp, "stat_ttl", &optval) && 297 ddi_strtol(optval, NULL, 10, &val) == 0 && 298 (int)val == val) 299 stat_ttl = val; 289 300 290 301 /* … … 339 350 sffs->sf_uid = uid; 340 351 sffs->sf_gid = gid; 352 sffs->sf_stat_ttl = stat_ttl; 341 353 sffs->sf_share_name = share_name; 342 354 sffs->sf_mntpath = mount_point; … … 362 374 strcpy(path, "."); 363 375 mutex_enter(&sffs_lock); 364 sfnode = sfnode_make(sffs, path, VDIR, NULL, NULL );376 sfnode = sfnode_make(sffs, path, VDIR, NULL, NULL, NULL, 0); 365 377 sffs->sf_rootnode = sfnode_get_vnode(sfnode); 366 378 sffs->sf_rootnode->v_flag |= VROOT; -
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.h
r28800 r30519 31 31 uid_t sf_uid; /* owner of all shared folders */ 32 32 gid_t sf_gid; /* group of all shared folders */ 33 int sf_stat_ttl; /* ttl for stat caches (in ms) */ 33 34 char *sf_share_name; 34 35 char *sf_mntpath; /* name of mount point */ … … 43 44 44 45 #endif /* !___VBoxFS_vfs_Solaris_h */ 46 -
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c
r30504 r30519 79 79 #include <sys/dirent.h> 80 80 #include <sys/fs_subr.h> 81 #include <sys/time.h> 81 82 #include "vboxfs_prov.h" 82 83 #include "vboxfs_vnode.h" … … 155 156 kmem_free(node->sf_dir_list, SFFS_DIRENTS_SIZE); 156 157 node->sf_dir_list = next; 158 } 159 160 while (node->sf_dir_stats != NULL) { 161 sffs_stats_t *next = node->sf_dir_stats->sf_next; 162 kmem_free(node->sf_dir_stats, sizeof(*node->sf_dir_stats)); 163 node->sf_dir_stats = next; 157 164 } 158 165 } … … 211 218 vtype_t type, 212 219 sfp_file_t *fp, 213 sfnode_t *parent) /* can be NULL for root */ 220 sfnode_t *parent, /* can be NULL for root */ 221 sffs_stat_t *stat, 222 uint64_t stat_time) 214 223 { 215 224 sfnode_t *node; … … 236 245 ++parent->sf_children; 237 246 node->sf_dir_list = NULL; 247 node->sf_dir_stats = NULL; 248 if (stat != NULL) { 249 node->sf_stat = *stat; 250 node->sf_stat_time = stat_time; 251 } else { 252 node->sf_stat_time = 0; 253 } 238 254 239 255 /* … … 364 380 avl_insert(&stale_sfnodes, node, where); 365 381 } 382 } 383 384 static uint64_t 385 sfnode_cur_time_usec(void) 386 { 387 timestruc_t now = hrestime; 388 return (now.tv_sec * 1000000L + now.tv_nsec / 1000L); 389 } 390 391 static int 392 sfnode_stat_cached(sfnode_t *node) 393 { 394 return (sfnode_cur_time_usec() - node->sf_stat_time) < 395 node->sf_sffs->sf_stat_ttl * 1000L; 396 } 397 398 static int 399 sfnode_get_stat(sfp_mount_t *mnt, char *path, sffs_stat_t *stat) 400 { 401 return sfprov_get_attr(mnt, path, &stat->sf_mode, &stat->sf_size, 402 &stat->sf_atime, &stat->sf_mtime, &stat->sf_ctime); 403 } 404 405 static void 406 sfnode_invalidate_stat_cache(sfnode_t *node) 407 { 408 node->sf_stat_time = 0; 409 } 410 411 static int 412 sfnode_update_stat_cache(sfnode_t *node) 413 { 414 int error; 415 416 error = sfnode_get_stat(node->sf_sffs->sf_handle, node->sf_path, 417 &node->sf_stat); 418 if (error == ENOENT) 419 sfnode_make_stale(node); 420 if (error == 0) 421 node->sf_stat_time = sfnode_cur_time_usec(); 422 423 return (error); 366 424 } 367 425 … … 471 529 */ 472 530 static sfnode_t * 473 sfnode_lookup(sfnode_t *dir, char *name, vtype_t create) 531 sfnode_lookup( 532 sfnode_t *dir, 533 char *name, 534 vtype_t create, 535 sffs_stat_t *stat, 536 uint64_t stat_time) 474 537 { 475 538 avl_index_t where; … … 480 543 char *fullpath; 481 544 sfp_file_t *fp; 545 sffs_stat_t tmp_stat; 482 546 483 547 ASSERT(MUTEX_HELD(&sffs_lock)); … … 525 589 fp = NULL; 526 590 type = VNON; 527 error = 528 sfprov_get_mode(dir->sf_sffs->sf_handle, fullpath, &m); 591 if (stat == NULL) { 592 stat = &tmp_stat; 593 error = sfnode_get_stat(dir->sf_sffs->sf_handle, 594 fullpath, stat); 595 stat_time = sfnode_cur_time_usec(); 596 } else { 597 error = 0; 598 } 599 m = stat->sf_mode; 529 600 if (error != 0) 530 601 error = ENOENT; … … 542 613 return (NULL); 543 614 } 544 node = sfnode_make(dir->sf_sffs, fullpath, type, fp, dir); 615 node = sfnode_make(dir->sf_sffs, fullpath, type, fp, dir, stat, 616 stat_time); 545 617 return (node); 546 618 } … … 562 634 563 635 /* 564 * get the mode from the provider 565 */ 566 error = sfprov_get_mode(node->sf_sffs->sf_handle, node->sf_path, &m); 567 if (error != 0) { 568 m = 0; 569 if (error == ENOENT) 570 sfnode_make_stale(node); 571 } 636 * get the mode from the cache or provider 637 */ 638 if (sfnode_stat_cached(node)) 639 error = 0; 640 else 641 error = sfnode_update_stat_cache(node); 642 m = (error == 0) ? node->sf_stat.sf_mode : 0; 572 643 573 644 /* … … 609 680 struct dirent64 *dirent; 610 681 sffs_dirents_t *cur_buf; 682 sffs_stats_t *cur_stats; 683 int cur_snum; 611 684 offset_t offset; 612 685 int dummy_eof; … … 637 710 if (dir->sf_dir_list == NULL) { 638 711 error = sfprov_readdir(dir->sf_sffs->sf_handle, dir->sf_path, 639 &dir->sf_dir_list );712 &dir->sf_dir_list, &dir->sf_dir_stats); 640 713 if (error != 0) 641 714 goto done; … … 648 721 offset = 0; 649 722 cur_buf = dir->sf_dir_list; 723 cur_stats = dir->sf_dir_stats; 724 cur_snum = 0; 650 725 while (cur_buf != NULL) { 651 726 if (offset + cur_buf->sf_len <= uiop->uio_loffset) { … … 653 728 cur_buf = cur_buf->sf_next; 654 729 continue; 730 } 731 732 if (cur_snum >= SFFS_STATS_LEN) { 733 cur_stats = cur_stats->sf_next; 734 cur_snum = 0; 655 735 } 656 736 … … 668 748 node = dir; 669 749 } else { 670 node = sfnode_lookup(dir, dirent->d_name, VNON); 750 node = sfnode_lookup(dir, dirent->d_name, VNON, 751 &cur_stats->sf_stats[cur_snum], 752 sfnode_cur_time_usec()); 671 753 if (node == NULL) 672 754 panic("sffs_readdir() lookup failed"); … … 675 757 676 758 error = uiomove(dirent, dirent->d_reclen, UIO_READ, uiop); 759 ++cur_snum; 677 760 if (error != 0) 678 761 break; … … 726 809 sffs_data_t *sffs = node->sf_sffs; 727 810 mode_t mode; 728 uint64_t x; 729 int error; 811 int error = 0; 730 812 731 813 mutex_enter(&sffs_lock); … … 739 821 vap->va_seq = 0; 740 822 741 error = sfprov_get_attr(node->sf_sffs->sf_handle, node->sf_path, &mode, 742 &x, &vap->va_atime, &vap->va_mtime, &vap->va_ctime); 743 if (error == ENOENT) 744 sfnode_make_stale(node); 745 if (error != 0) 746 goto done; 823 if (!sfnode_stat_cached(node)) { 824 error = sfnode_update_stat_cache(node); 825 if (error != 0) 826 goto done; 827 } 828 829 vap->va_atime = node->sf_stat.sf_atime; 830 vap->va_mtime = node->sf_stat.sf_mtime; 831 vap->va_ctime = node->sf_stat.sf_ctime; 832 833 mode = node->sf_stat.sf_mode; 747 834 vap->va_mode = mode & MODEMASK; 748 835 if (S_ISDIR(mode)) … … 761 848 vap->va_type = VSOCK; 762 849 763 vap->va_size = x;850 vap->va_size = node->sf_stat.sf_size; 764 851 vap->va_blksize = 512; 765 vap->va_nblocks = ( x+ 511) / 512;852 vap->va_nblocks = (vap->va_size + 511) / 512; 766 853 767 854 done: … … 800 887 mutex_enter(&sffs_lock); 801 888 889 sfnode_invalidate_stat_cache(node); 802 890 error = sfprov_set_attr(node->sf_sffs->sf_handle, node->sf_path, 803 891 vap->va_mask, mode, vap->va_atime, vap->va_mtime, vap->va_ctime); … … 827 915 828 916 mutex_enter(&sffs_lock); 917 918 sfnode_invalidate_stat_cache(node); 829 919 830 920 error = sfprov_set_size(node->sf_sffs->sf_handle, node->sf_path, … … 922 1012 return (EINVAL); 923 1013 } 1014 1015 sfnode_invalidate_stat_cache(node); 1016 924 1017 if (ioflag & FAPPEND) { 925 1018 uint64_t endoffile; … … 1064 1157 * Lookup the node. 1065 1158 */ 1066 node = sfnode_lookup(VN2SFN(dvp), name, VNON );1159 node = sfnode_lookup(VN2SFN(dvp), name, VNON, NULL, 0); 1067 1160 if (node != NULL) 1068 1161 *vpp = sfnode_get_vnode(node); … … 1130 1223 return (error); 1131 1224 } 1225 1226 sfnode_invalidate_stat_cache(VN2SFN(dvp)); 1132 1227 1133 1228 /* … … 1157 1252 */ 1158 1253 mutex_enter(&sffs_lock); 1159 node = sfnode_lookup(VN2SFN(dvp), name, VNON );1254 node = sfnode_lookup(VN2SFN(dvp), name, VNON, NULL, 0); 1160 1255 if (node != NULL) { 1161 1256 mutex_exit(&sffs_lock); … … 1166 1261 * Doesn't exist yet and we have the lock, so create it. 1167 1262 */ 1168 node = sfnode_lookup(VN2SFN(dvp), name, VREG); 1263 sfnode_invalidate_stat_cache(VN2SFN(dvp)); 1264 node = sfnode_lookup(VN2SFN(dvp), name, VREG, NULL, 0); 1169 1265 if (node && (vap->va_mask & AT_MODE)) { 1170 1266 timestruc_t dummy; … … 1231 1327 } 1232 1328 1233 node = sfnode_lookup(VN2SFN(dvp), nm, VDIR); 1329 sfnode_invalidate_stat_cache(VN2SFN(dvp)); 1330 1331 node = sfnode_lookup(VN2SFN(dvp), nm, VDIR, NULL, 0); 1234 1332 if (node && (va->va_mask & AT_MODE)) { 1235 1333 timestruc_t dummy; … … 1319 1417 * Remove the directory on the host and mark the node as stale. 1320 1418 */ 1419 sfnode_invalidate_stat_cache(VN2SFN(dvp)); 1321 1420 error = sfprov_rmdir(node->sf_sffs->sf_handle, node->sf_path); 1322 1421 if (error == ENOENT || error == 0) … … 1381 1480 * Remove the file on the host and mark the node as stale. 1382 1481 */ 1482 sfnode_invalidate_stat_cache(VN2SFN(dvp)); 1483 1383 1484 error = sfprov_remove(node->sf_sffs->sf_handle, node->sf_path); 1384 1485 if (error == ENOENT || error == 0) … … 1426 1527 goto done; 1427 1528 1428 node = sfnode_lookup(VN2SFN(old_dir), old_nm, VNON );1529 node = sfnode_lookup(VN2SFN(old_dir), old_nm, VNON, NULL, 0); 1429 1530 if (node == NULL) { 1430 1531 error = ENOENT; … … 1432 1533 } 1433 1534 1434 1435 1535 /* 1436 1536 * Rename the file on the host and in our caches. 1437 1537 */ 1538 sfnode_invalidate_stat_cache(node); 1539 sfnode_invalidate_stat_cache(VN2SFN(old_dir)); 1540 sfnode_invalidate_stat_cache(VN2SFN(new_dir)); 1541 1438 1542 newpath = sfnode_construct_path(VN2SFN(new_dir), new_nm); 1439 1543 error = sfprov_rename(node->sf_sffs->sf_handle, node->sf_path, newpath, … … 1577 1681 */ 1578 1682 sfnode_clear_dir_list(node); 1683 1684 sfnode_invalidate_stat_cache(node); 1579 1685 1580 1686 mutex_exit(&sffs_lock); -
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.h
r30446 r30519 48 48 uint8_t sf_type; /* VDIR or VREG */ 49 49 uint8_t sf_is_stale; /* this is stale and should be purged */ 50 sffs_stat_t sf_stat; /* cached file attrs for this node */ 51 uint64_t sf_stat_time; /* last-modified time of sf_stat */ 50 52 sffs_dirents_t *sf_dir_list; /* list of entries for this directory */ 53 sffs_stats_t *sf_dir_stats; /* file attrs for the above entries */ 51 54 } sfnode_t; 52 55 … … 57 60 extern void sffs_vnode_fini(void); 58 61 extern sfnode_t *sfnode_make(struct sffs_data *, char *, vtype_t, sfp_file_t *, 59 sfnode_t *parent);62 sfnode_t *parent, sffs_stat_t *, uint64_t stat_time); 60 63 extern vnode_t *sfnode_get_vnode(sfnode_t *); 61 64
Note:
See TracChangeset
for help on using the changeset viewer.