VirtualBox

Changeset 30519 in vbox


Ignore:
Timestamp:
Jun 30, 2010 8:04:26 AM (15 years ago)
Author:
vboxsync
Message:

Additions/Solaris/SharedFolders: stat caching to reduce number of host calls. introduced stat_ttl option during mount.

Location:
trunk/src/VBox/Additions/solaris/SharedFolders
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs.h

    r28800 r30519  
    2525#define MAX_HOST_NAME   256
    2626#define MAX_NLS_NAME    32
     27/** Default stat cache ttl (in ms) */
     28#define DEF_STAT_TTL_MS 200
    2729
    2830/** The module name. */
     
    3335#include "../../common/VBoxGuestLib/VBoxCalls.h"
    3436#include <sys/vfs.h>
    35 #include <sys/vfs_opreg.h>
    3637
    3738/** VNode for VBoxVFS */
  • trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_mount.c

    r28800 r30519  
    5353           "     uid=UID            set the default file owner user id to UID\n"
    5454           "     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"
    5556           "     ttl=TTL            set the \"time to live\" to TID for the dentry\n"
    5657           "     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);
    5859    fprintf(stderr, "Less common used options:\n"
    5960           "     noexec,exec,nodev,dev,nosuid,suid\n");
  • trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c

    r30504 r30519  
    825825        sfp_mount_t *mnt,
    826826        char *path,
    827         sffs_dirents_t **dirents)
     827        sffs_dirents_t **dirents,
     828        sffs_stats_t **stats)
    828829{
    829830        int error;
     
    840841        uint32_t cnt;
    841842        sffs_dirents_t *cur_buf;
     843        sffs_stats_t *cur_stats;
    842844        struct dirent64 *dirent;
     845        sffs_stat_t *stat;
    843846        unsigned short reclen;
    844847
    845848        *dirents = NULL;
     849        *stats = NULL;
    846850
    847851        error = sfprov_open(mnt, path, &fp);
     
    850854
    851855        /*
    852          * Allocate the first dirents buffer.
     856         * Allocate the first dirents and stats buffers.
    853857         */
    854858        *dirents = kmem_alloc(SFFS_DIRENTS_SIZE, KM_SLEEP);
     
    860864        cur_buf->sf_next = NULL;
    861865        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;
    862875
    863876        /*
     
    907920
    908921                /*
    909                  * Create the dirent_t's for each name
     922                 * Create the dirent_t's and save the stats for each name
    910923                 */
    911924                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 */
    913926                        reclen = DIRENT64_RECLEN(strlen(info->name.String.utf8));
    914927                        if (SFFS_DIRENTS_OFF + cur_buf->sf_len + reclen > SFFS_DIRENTS_SIZE) {
     
    923936                        }
    924937
     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
    925949                        /* create the dirent with the name, offset, and len */
    926950                        dirent = (dirent64_t *)
     
    933957                        ++cnt;
    934958
     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 */
    935970                        size = offsetof (SHFLDIRINFO, name.String) + info->name.u16Size;
    936971                        info = (SHFLDIRINFO *) ((uintptr_t) info + size);
     
    951986                        *dirents = cur_buf;
    952987                }
     988                while (*stats) {
     989                        cur_stats = (*stats)->sf_next;
     990                        kmem_free(*stats, sizeof(**stats));
     991                        *stats = cur_stats;
     992                }
    953993        }
    954994        if (infobuff != NULL)
  • trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h

    r30504 r30519  
    123123} sffs_dirents_t;
    124124
    125 extern int sfprov_readdir(sfp_mount_t *mnt, char *path, sffs_dirents_t **dirents);
    126 
    127125#define SFFS_DIRENTS_SIZE       8192
    128126#define SFFS_DIRENTS_OFF        (offsetof(sffs_dirents_t, sf_entries[0]))
     127#define SFFS_STATS_LEN          100
     128
     129typedef 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
     137typedef 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
     143extern int sfprov_readdir(sfp_mount_t *mnt, char *path, sffs_dirents_t **dirents,
     144    sffs_stats_t **stats);
    129145
    130146#ifdef  __cplusplus
  • trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c

    r28800 r30519  
    3636#include "vboxfs_vnode.h"
    3737#include "vboxfs_vfs.h"
     38#include "vboxfs.h"
    3839
    3940#ifdef u
     
    6465        /* Option       Cancels Opt     Arg     Flags           Data */
    6566        {"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}
    6769};
    6870
     
    227229        uid_t uid = 0;
    228230        gid_t gid = 0;
     231        int stat_ttl = DEF_STAT_TTL_MS;
    229232        char *optval;
    230233        long val;
     
    287290            (gid_t)val == val)
    288291                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;
    289300
    290301        /*
     
    339350        sffs->sf_uid = uid;
    340351        sffs->sf_gid = gid;
     352        sffs->sf_stat_ttl = stat_ttl;
    341353        sffs->sf_share_name = share_name;
    342354        sffs->sf_mntpath = mount_point;
     
    362374        strcpy(path, ".");
    363375        mutex_enter(&sffs_lock);
    364         sfnode = sfnode_make(sffs, path, VDIR, NULL, NULL);
     376        sfnode = sfnode_make(sffs, path, VDIR, NULL, NULL, NULL, 0);
    365377        sffs->sf_rootnode = sfnode_get_vnode(sfnode);
    366378        sffs->sf_rootnode->v_flag |= VROOT;
  • trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.h

    r28800 r30519  
    3131        uid_t           sf_uid;         /* owner of all shared folders */
    3232        gid_t           sf_gid;         /* group of all shared folders */
     33        int             sf_stat_ttl;    /* ttl for stat caches (in ms) */
    3334        char            *sf_share_name;
    3435        char            *sf_mntpath;    /* name of mount point */
     
    4344
    4445#endif  /* !___VBoxFS_vfs_Solaris_h */
     46
  • trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c

    r30504 r30519  
    7979#include <sys/dirent.h>
    8080#include <sys/fs_subr.h>
     81#include <sys/time.h>
    8182#include "vboxfs_prov.h"
    8283#include "vboxfs_vnode.h"
     
    155156                kmem_free(node->sf_dir_list, SFFS_DIRENTS_SIZE);
    156157                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;
    157164        }
    158165}
     
    211218        vtype_t         type,
    212219        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)
    214223{
    215224        sfnode_t        *node;
     
    236245                ++parent->sf_children;
    237246        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        }
    238254
    239255        /*
     
    364380                avl_insert(&stale_sfnodes, node, where);
    365381        }
     382}
     383
     384static uint64_t
     385sfnode_cur_time_usec(void)
     386{
     387        timestruc_t now = hrestime;
     388        return (now.tv_sec * 1000000L + now.tv_nsec / 1000L);
     389}
     390
     391static int
     392sfnode_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
     398static int
     399sfnode_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
     405static void
     406sfnode_invalidate_stat_cache(sfnode_t *node)
     407{
     408        node->sf_stat_time = 0;
     409}
     410
     411static int
     412sfnode_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);
    366424}
    367425
     
    471529 */
    472530static sfnode_t *
    473 sfnode_lookup(sfnode_t *dir, char *name, vtype_t create)
     531sfnode_lookup(
     532        sfnode_t *dir,
     533        char *name,
     534        vtype_t create,
     535        sffs_stat_t *stat,
     536        uint64_t stat_time)
    474537{
    475538        avl_index_t     where;
     
    480543        char            *fullpath;
    481544        sfp_file_t      *fp;
     545        sffs_stat_t     tmp_stat;
    482546
    483547        ASSERT(MUTEX_HELD(&sffs_lock));
     
    525589                fp = NULL;
    526590                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;
    529600                if (error != 0)
    530601                        error = ENOENT;
     
    542613                return (NULL);
    543614        }
    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);
    545617        return (node);
    546618}
     
    562634
    563635        /*
    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;
    572643
    573644        /*
     
    609680        struct dirent64 *dirent;
    610681        sffs_dirents_t *cur_buf;
     682        sffs_stats_t *cur_stats;
     683        int cur_snum;
    611684        offset_t offset;
    612685        int dummy_eof;
     
    637710        if (dir->sf_dir_list == NULL) {
    638711                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);
    640713                if (error != 0)
    641714                        goto done;
     
    648721        offset = 0;
    649722        cur_buf = dir->sf_dir_list;
     723        cur_stats = dir->sf_dir_stats;
     724        cur_snum = 0;
    650725        while (cur_buf != NULL) {
    651726                if (offset + cur_buf->sf_len <= uiop->uio_loffset) {
     
    653728                        cur_buf = cur_buf->sf_next;
    654729                        continue;
     730                }
     731
     732                if (cur_snum >= SFFS_STATS_LEN) {
     733                        cur_stats = cur_stats->sf_next;
     734                        cur_snum = 0;
    655735                }
    656736
     
    668748                                node = dir;
    669749                } 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());
    671753                        if (node == NULL)
    672754                                panic("sffs_readdir() lookup failed");
     
    675757
    676758                error = uiomove(dirent, dirent->d_reclen, UIO_READ, uiop);
     759                ++cur_snum;
    677760                if (error != 0)
    678761                        break;
     
    726809        sffs_data_t     *sffs = node->sf_sffs;
    727810        mode_t          mode;
    728         uint64_t        x;
    729         int             error;
     811        int             error = 0;
    730812
    731813        mutex_enter(&sffs_lock);
     
    739821        vap->va_seq = 0;
    740822
    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;
    747834        vap->va_mode = mode & MODEMASK;
    748835        if (S_ISDIR(mode))
     
    761848                vap->va_type = VSOCK;
    762849
    763         vap->va_size = x;
     850        vap->va_size = node->sf_stat.sf_size;
    764851        vap->va_blksize = 512;
    765         vap->va_nblocks = (x + 511) / 512;
     852        vap->va_nblocks = (vap->va_size + 511) / 512;
    766853
    767854done:
     
    800887        mutex_enter(&sffs_lock);
    801888
     889        sfnode_invalidate_stat_cache(node);
    802890        error = sfprov_set_attr(node->sf_sffs->sf_handle, node->sf_path,
    803891            vap->va_mask, mode, vap->va_atime, vap->va_mtime, vap->va_ctime);
     
    827915
    828916        mutex_enter(&sffs_lock);
     917
     918        sfnode_invalidate_stat_cache(node);
    829919
    830920        error = sfprov_set_size(node->sf_sffs->sf_handle, node->sf_path,
     
    9221012                return (EINVAL);
    9231013        }
     1014
     1015        sfnode_invalidate_stat_cache(node);
     1016
    9241017        if (ioflag & FAPPEND) {
    9251018                uint64_t endoffile;
     
    10641157         * Lookup the node.
    10651158         */
    1066         node = sfnode_lookup(VN2SFN(dvp), name, VNON);
     1159        node = sfnode_lookup(VN2SFN(dvp), name, VNON, NULL, 0);
    10671160        if (node != NULL)
    10681161                *vpp = sfnode_get_vnode(node);
     
    11301223                        return (error);
    11311224                }
     1225
     1226                sfnode_invalidate_stat_cache(VN2SFN(dvp));
    11321227
    11331228                /*
     
    11571252         */
    11581253        mutex_enter(&sffs_lock);
    1159         node = sfnode_lookup(VN2SFN(dvp), name, VNON);
     1254        node = sfnode_lookup(VN2SFN(dvp), name, VNON, NULL, 0);
    11601255        if (node != NULL) {
    11611256                mutex_exit(&sffs_lock);
     
    11661261         * Doesn't exist yet and we have the lock, so create it.
    11671262         */
    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);
    11691265        if (node && (vap->va_mask & AT_MODE)) {
    11701266                timestruc_t dummy;
     
    12311327        }
    12321328
    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);
    12341332        if (node && (va->va_mask & AT_MODE)) {
    12351333                timestruc_t dummy;
     
    13191417         * Remove the directory on the host and mark the node as stale.
    13201418         */
     1419        sfnode_invalidate_stat_cache(VN2SFN(dvp));
    13211420        error = sfprov_rmdir(node->sf_sffs->sf_handle, node->sf_path);
    13221421        if (error == ENOENT || error == 0)
     
    13811480         * Remove the file on the host and mark the node as stale.
    13821481         */
     1482        sfnode_invalidate_stat_cache(VN2SFN(dvp));
     1483
    13831484        error = sfprov_remove(node->sf_sffs->sf_handle, node->sf_path);
    13841485        if (error == ENOENT || error == 0)
     
    14261527                goto done;
    14271528
    1428         node = sfnode_lookup(VN2SFN(old_dir), old_nm, VNON);
     1529        node = sfnode_lookup(VN2SFN(old_dir), old_nm, VNON, NULL, 0);
    14291530        if (node == NULL) {
    14301531                error = ENOENT;
     
    14321533        }
    14331534
    1434 
    14351535        /*
    14361536         * Rename the file on the host and in our caches.
    14371537         */
     1538        sfnode_invalidate_stat_cache(node);
     1539        sfnode_invalidate_stat_cache(VN2SFN(old_dir));
     1540        sfnode_invalidate_stat_cache(VN2SFN(new_dir));
     1541
    14381542        newpath = sfnode_construct_path(VN2SFN(new_dir), new_nm);
    14391543        error = sfprov_rename(node->sf_sffs->sf_handle, node->sf_path, newpath,
     
    15771681         */
    15781682        sfnode_clear_dir_list(node);
     1683
     1684        sfnode_invalidate_stat_cache(node);
    15791685
    15801686        mutex_exit(&sffs_lock);
  • trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.h

    r30446 r30519  
    4848        uint8_t         sf_type;        /* VDIR or VREG */
    4949        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 */
    5052        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 */
    5154} sfnode_t;
    5255
     
    5760extern void sffs_vnode_fini(void);
    5861extern 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);
    6063extern vnode_t *sfnode_get_vnode(sfnode_t *);
    6164
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette