VirtualBox

Changeset 77461 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Feb 25, 2019 3:44:39 PM (6 years ago)
Author:
vboxsync
Message:

linux/vboxsf: Optimized sf_inode_revalidate for open files/dirs. bugref:9172

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/linux/sharedfolders/utils.c

    r77424 r77461  
    182182}
    183183
     184/**
     185 * Update the inode with new object info from the host.
     186 */
     187void sf_update_inode(struct inode *pInode, PSHFLFSOBJINFO pObjInfo, struct sf_glob_info *sf_g)
     188{
     189        /** @todo  make lock/rcu safe.  */
     190        sf_init_inode(sf_g, pInode, pObjInfo);
     191}
     192
     193
    184194int sf_stat(const char *caller, struct sf_glob_info *sf_g,
    185195            SHFLSTRING *path, PSHFLFSOBJINFO result, int ok_to_fail)
     
    223233}
    224234
    225 /* this is called directly as iop on 2.4, indirectly as dop
    226    [sf_dentry_revalidate] on 2.4/2.6, indirectly as iop through
    227    [sf_getattr] on 2.6. the job is to find out whether dentry/inode is
    228    still valid. the test is failed if [dentry] does not have an inode
    229    or [sf_stat] is unsuccessful, otherwise we return success and
    230    update inode attributes */
     235/**
     236 * Revalidate an inode.
     237 *
     238 * This is called directly as inode-op on 2.4, indirectly as dir-op
     239 * sf_dentry_revalidate() on 2.4/2.6, indirectly as inode-op through
     240 * sf_getattr() on 2.6.  The job is to find out whether dentry/inode is still
     241 * valid.  The test fails if @a dentry does not have an inode or sf_stat() is
     242 * unsuccessful, otherwise we return success and update inode attributes.
     243 */
    231244int sf_inode_revalidate(struct dentry *dentry)
    232245{
    233         int err;
    234         struct sf_glob_info *sf_g;
    235         struct sf_inode_info *sf_i;
    236         SHFLFSOBJINFO info;
    237 
    238         TRACE();
    239         if (!dentry || !dentry->d_inode) {
    240                 LogFunc(("no dentry(%p) or inode(%p)\n", dentry, dentry ? dentry->d_inode : NULL));
    241                 return -EINVAL;
    242         }
    243 
    244         sf_g = GET_GLOB_INFO(dentry->d_inode->i_sb);
    245         sf_i = GET_INODE_INFO(dentry->d_inode);
    246 
    247 #if 0
    248         printk("%s called by %p:%p\n",
    249                sf_i->path->String.utf8,
    250                __builtin_return_address(0), __builtin_return_address(1));
    251 #endif
    252 
    253         BUG_ON(!sf_g);
    254         BUG_ON(!sf_i);
    255 
    256         if (!sf_i->force_restat) {
    257                 if (jiffies - dentry->d_time < sf_g->ttl)
    258                         return 0;
    259         }
    260 
    261         err = sf_stat(__func__, sf_g, sf_i->path, &info, 1);
    262         if (err)
    263                 return err;
    264 
    265         dentry->d_time = jiffies;
    266 /** @todo bird has severe inode locking / rcu concerns here:  */
    267         sf_init_inode(sf_g, dentry->d_inode, &info);
    268         return 0;
     246        int rc;
     247        struct inode *pInode = dentry ? dentry->d_inode : NULL;
     248        if (pInode) {
     249                struct sf_inode_info *sf_i = GET_INODE_INFO(pInode);
     250                struct sf_glob_info  *sf_g = GET_GLOB_INFO(pInode->i_sb);
     251                AssertReturn(sf_i, -EINVAL);
     252                AssertReturn(sf_g, -EINVAL);
     253
     254                /*
     255                 * Can we get away without any action here?
     256                 */
     257                if (   !sf_i->force_restat
     258                    && jiffies - dentry->d_time < sf_g->ttl)
     259                        rc = 0;
     260                else {
     261                        /*
     262                         * No, we have to query the file info from the host.
     263                         * Try get a handle we can query, any kind of handle will do here.
     264                         */
     265                        struct sf_handle *pHandle = sf_handle_find(sf_i, 0, 0);
     266                        if (pHandle) {
     267                                /* Query thru pHandle. */
     268                                VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     269                                if (pReq) {
     270                                        RT_ZERO(*pReq);
     271                                        rc = VbglR0SfHostReqQueryObjInfo(sf_g->map.root, pReq, pHandle->hHost);
     272                                        if (RT_SUCCESS(rc)) {
     273                                                /*
     274                                                 * Reset the TTL and copy the info over into the inode structure.
     275                                                 */
     276                                                dentry->d_time = jiffies;
     277                                                sf_update_inode(pInode, &pReq->ObjInfo, sf_g);
     278                                        } else if (rc == VERR_INVALID_HANDLE) {
     279                                                rc = -ENOENT; /* Restore.*/
     280                                        } else {
     281                                                LogFunc(("VbglR0SfHostReqQueryObjInfo failed on %#RX64: %Rrc\n", pHandle->hHost, rc));
     282                                                rc = -RTErrConvertToErrno(rc);
     283                                        }
     284                                        VbglR0PhysHeapFree(pReq);
     285                                } else
     286                                        rc = -ENOMEM;
     287                                sf_handle_release(pHandle, sf_g, "sf_inode_revalidate");
     288
     289                        } else {
     290                                /* Query via path. */
     291                                SHFLSTRING      *pPath = sf_i->path;
     292                                VBOXSFCREATEREQ *pReq  = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + pPath->u16Size);
     293                                if (pReq) {
     294                                        RT_ZERO(*pReq);
     295                                        memcpy(&pReq->StrPath, pPath, SHFLSTRING_HEADER_SIZE + pPath->u16Size);
     296                                        pReq->CreateParms.Handle      = SHFL_HANDLE_NIL;
     297                                        pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
     298
     299                                        rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq);
     300                                        if (RT_SUCCESS(rc)) {
     301                                                if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) {
     302                                                        /*
     303                                                         * Reset the TTL and copy the info over into the inode structure.
     304                                                         */
     305                                                        dentry->d_time = jiffies;
     306                                                        sf_update_inode(pInode, &pReq->CreateParms.Info, sf_g);
     307                                                        rc = 0;
     308                                                } else {
     309                                                        rc = -ENOENT;
     310                                                }
     311                                        } else if (rc == VERR_INVALID_NAME) {
     312                                                rc = -ENOENT; /* this can happen for names like 'foo*' on a Windows host */
     313                                        } else {
     314                                                LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc\n", pPath->String.ach, rc));
     315                                                rc = -EPROTO;
     316                                        }
     317                                        VbglR0PhysHeapFree(pReq);
     318                                }
     319                                else
     320                                        rc = -ENOMEM;
     321                        }
     322                }
     323        } else {
     324                LogFunc(("no dentry(%p) or inode(%p)\n", dentry, pInode));
     325                rc = -EINVAL;
     326        }
     327        return rc;
    269328}
    270329
     
    306365                                         */
    307366                                        dentry->d_time = jiffies;
    308 /** @todo bird has severe inode locking / rcu concerns here:  */
    309                                         sf_init_inode(sf_g, pInode, &pReq->ObjInfo);
     367                                        sf_update_inode(pInode, &pReq->ObjInfo, sf_g);
    310368                                } else {
    311369                                        LogFunc(("VbglR0SfHostReqQueryObjInfo failed on %#RX64: %Rrc\n", hHostFile, err));
     
    362420# endif
    363421{
    364         int err;
     422        int            rc;
    365423# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
    366424        struct dentry *dentry = path->dentry;
    367425# endif
    368426
    369         TRACE();
    370         err = sf_inode_revalidate(dentry);
    371         if (err)
    372                 return err;
    373 
    374         generic_fillattr(dentry->d_inode, kstat);
    375 
    376         /*
    377          * FsPerf shows the following numbers for sequential file access against
    378          * a tmpfs folder on an AMD 1950X host running debian buster/sid:
    379          *
    380          * block size = r128600    ----- r128755 -----
    381          *               reads      reads     writes
    382          *    4096 KB = 2254 MB/s  4953 MB/s 3668 MB/s
    383          *    2048 KB = 2368 MB/s  4908 MB/s 3541 MB/s
    384          *    1024 KB = 2208 MB/s  4011 MB/s 3291 MB/s
    385          *     512 KB = 1908 MB/s  3399 MB/s 2721 MB/s
    386          *     256 KB = 1625 MB/s  2679 MB/s 2251 MB/s
    387          *     128 KB = 1413 MB/s  1967 MB/s 1684 MB/s
    388          *      64 KB = 1152 MB/s  1409 MB/s 1265 MB/s
    389          *      32 KB =  726 MB/s   815 MB/s  783 MB/s
    390          *      16 KB =             683 MB/s  475 MB/s
    391          *       8 KB =             294 MB/s  286 MB/s
    392          *       4 KB =  145 MB/s   156 MB/s  149 MB/s
    393          *
    394          */
    395         if (S_ISREG(kstat->mode))
    396                 kstat->blksize = _1M;
    397         else if (S_ISDIR(kstat->mode))
    398                 /** @todo this may need more tuning after we rewrite the directory handling. */
    399                 kstat->blksize = _16K;
    400         return 0;
     427# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
     428        SFLOGFLOW(("sf_getattr: dentry=%p request_mask=%#x flags=%#x\n", dentry, request_mask, flags));
     429# else
     430        SFLOGFLOW(("sf_getattr: dentry=%p\n", dentry));
     431# endif
     432
     433        rc = sf_inode_revalidate(dentry);
     434        if (rc == 0) {
     435                generic_fillattr(dentry->d_inode, kstat);
     436
     437                /*
     438                 * FsPerf shows the following numbers for sequential file access against
     439                 * a tmpfs folder on an AMD 1950X host running debian buster/sid:
     440                 *
     441                 * block size = r128600    ----- r128755 -----
     442                 *               reads      reads     writes
     443                 *    4096 KB = 2254 MB/s  4953 MB/s 3668 MB/s
     444                 *    2048 KB = 2368 MB/s  4908 MB/s 3541 MB/s
     445                 *    1024 KB = 2208 MB/s  4011 MB/s 3291 MB/s
     446                 *     512 KB = 1908 MB/s  3399 MB/s 2721 MB/s
     447                 *     256 KB = 1625 MB/s  2679 MB/s 2251 MB/s
     448                 *     128 KB = 1413 MB/s  1967 MB/s 1684 MB/s
     449                 *      64 KB = 1152 MB/s  1409 MB/s 1265 MB/s
     450                 *      32 KB =  726 MB/s   815 MB/s  783 MB/s
     451                 *      16 KB =             683 MB/s  475 MB/s
     452                 *       8 KB =             294 MB/s  286 MB/s
     453                 *       4 KB =  145 MB/s   156 MB/s  149 MB/s
     454                 *
     455                 */
     456                if (S_ISREG(kstat->mode))
     457                        kstat->blksize = _1M;
     458                else if (S_ISDIR(kstat->mode))
     459                        /** @todo this may need more tuning after we rewrite the directory handling. */
     460                        kstat->blksize = _16K;
     461        }
     462        return rc;
    401463}
    402464
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