VirtualBox

Ticket #4154: vbox.sf.sol.readdir_perf.patch

File vbox.sf.sol.readdir_perf.patch, 3.7 KB (added by foobar42, 14 years ago)

Improve performance of readdir. Instead of reading one directory entry at a time (i.e. making one guest call per entry) we read in whole chunks at a time. This speeds up the operation by 10 to 20 times.

  • src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c

    diff a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
    a b sfprov_readdir(  
    623623        SHFLSTRING *mask_str = NULL;    /* must be path with "/*" appended */
    624624        int mask_size;
    625625        sfp_file_t *fp;
    626         static char infobuff[2 * MAXNAMELEN];   /* not on stack!! */
    627         SHFLDIRINFO *info = (SHFLDIRINFO *)&infobuff;
     626        uint32_t infobuff_alloc = 16384;
     627        SHFLDIRINFO *infobuff = NULL, *info;
    628628        uint32_t numbytes;
    629         uint32_t justone;
     629        uint32_t nents;
     630        uint32_t size;
    630631        uint32_t cnt;
    631632        sffs_dirents_t *cur_buf;
    632633        struct dirent64 *dirent;
    sfprov_readdir(  
    666667        kmem_free(cp, len);
    667668
    668669        /*
    669          * Now loop using vboxCallDirInfo to get one file name at a time
     670         * Now loop using vboxCallDirInfo
    670671         */
     672        infobuff = kmem_alloc(infobuff_alloc, KM_SLEEP);
     673        if (infobuff == NULL) {
     674                error = (ENOSPC);
     675                goto done;
     676        }
     677
    671678        cnt = 0;
    672679        for (;;) {
    673                 justone = 1;
    674                 numbytes = sizeof (infobuff);
     680                numbytes = infobuff_alloc;
    675681                error = vboxCallDirInfo(&vbox_client, &fp->map, fp->handle,
    676                     mask_str, SHFL_LIST_RETURN_ONE, 0, &numbytes, info,
    677                     &justone);
    678                 if (error == VERR_NO_MORE_FILES) {
    679                         break;
    680                 }
    681                 else if (error == VERR_NO_TRANSLATION) {
    682                         continue;       /* ?? just skip this one */
    683                 }
    684                 else if (error != VINF_SUCCESS || justone != 1) {
    685                         error = EINVAL;
    686                         goto done;
     682                    mask_str, 0, 0, &numbytes, infobuff, &nents);
     683                switch (error) {
     684                        case VINF_SUCCESS:
     685                                /* fallthrough */
     686                        case VERR_NO_MORE_FILES:
     687                                break;
     688
     689                        case VERR_NO_TRANSLATION:
     690                                /* XXX ??? */
     691                                break;
     692
     693                        default:
     694                                error = RTErrConvertToErrno(error);
     695                                goto done;
    687696                }
    688697
    689698                /*
    690                  * Put this name in the buffer, expand if we run out of room.
     699                 * Create the dirent_t's for each name
    691700                 */
    692                 reclen = DIRENT64_RECLEN(strlen(info->name.String.utf8));
    693                 if (SFFS_DIRENTS_OFF + cur_buf->sf_len + reclen > SFFS_DIRENTS_SIZE) {
    694                         cur_buf->sf_next = kmem_alloc(SFFS_DIRENTS_SIZE, KM_SLEEP);
    695                         if (cur_buf->sf_next == NULL) {
    696                                 error = ENOSPC;
    697                                 goto done;
     701                for (info = infobuff; (char *) info < (char *) infobuff + numbytes; nents--) {
     702                        /* expand buffer if we need more space */
     703                        reclen = DIRENT64_RECLEN(strlen(info->name.String.utf8));
     704                        if (SFFS_DIRENTS_OFF + cur_buf->sf_len + reclen > SFFS_DIRENTS_SIZE) {
     705                                cur_buf->sf_next = kmem_alloc(SFFS_DIRENTS_SIZE, KM_SLEEP);
     706                                if (cur_buf->sf_next == NULL) {
     707                                        error = ENOSPC;
     708                                        goto done;
     709                                }
     710                                cur_buf = cur_buf->sf_next;
     711                                cur_buf->sf_next = NULL;
     712                                cur_buf->sf_len = 0;
    698713                        }
    699                         cur_buf = cur_buf->sf_next;
    700                         cur_buf->sf_next = NULL;
    701                         cur_buf->sf_len = 0;
    702                 }
    703714
    704                 dirent = (dirent64_t *)
    705                         (((char *) &cur_buf->sf_entries[0]) + cur_buf->sf_len);
    706                 strcpy(&dirent->d_name[0], info->name.String.utf8);
    707                 dirent->d_reclen = reclen;
    708                 dirent->d_off = cnt;
     715                        /* create the dirent with the name, offset, and len */
     716                        dirent = (dirent64_t *)
     717                                (((char *) &cur_buf->sf_entries[0]) + cur_buf->sf_len);
     718                        strcpy(&dirent->d_name[0], info->name.String.utf8);
     719                        dirent->d_reclen = reclen;
     720                        dirent->d_off = cnt;
     721
     722                        cur_buf->sf_len += reclen;
     723                        ++cnt;
    709724
    710                 cur_buf->sf_len += reclen;
    711                 ++cnt;
     725                        size = offsetof (SHFLDIRINFO, name.String) + info->name.u16Size;
     726                        info = (SHFLDIRINFO *) ((uintptr_t) info + size);
     727                }
     728                ASSERT(nents == 0);
     729                ASSERT((char *) info == (char *) infobuff + numbytes);
     730
     731                if (error == VERR_NO_MORE_FILES)
     732                        break;
    712733        }
    713734        error = 0;
    714735
    done:  
    720741                        *dirents = cur_buf;
    721742                }
    722743        }
     744        if (infobuff != NULL)
     745                kmem_free(infobuff, infobuff_alloc);
    723746        if (mask_str != NULL)
    724747                kmem_free(mask_str, mask_size);
    725748        sfprov_close(fp);

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