VirtualBox

Changeset 85492 in vbox for trunk/src/VBox/Runtime/r3/posix


Ignore:
Timestamp:
Jul 28, 2020 4:36:42 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
139548
Message:

IPRT/fileio-posix.cpp: Fix binary search in RTFileQueryMaxSizeEx, and make it cover a bigger range (ext4 handles almost 16TB per file), with the help of a quicker "find the approximate order of magnitude" approach all the way up to INT64_MAX, which is the theoretical maximum for the seekable range in many OSes anyway.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/fileio-posix.cpp

    r84506 r85492  
    756756        return rc;
    757757
    758     /*
    759      * Perform a binary search for the max file size.
    760      */
    761758    uint64_t offLow  =       0;
    762     uint64_t offHigh = 8 * _1T; /* we don't need bigger files */
     759    uint64_t offHigh = INT64_MAX; /* we don't need bigger files */
    763760    /** @todo Unfortunately this does not work for certain file system types,
    764761     * for instance cifs mounts. Even worse, statvfs.f_fsid returns 0 for such
    765762     * file systems. */
    766     //uint64_t offHigh = INT64_MAX;
    767     for (;;)
    768     {
    769         uint64_t cbInterval = (offHigh - offLow) >> 1;
    770         if (cbInterval == 0)
    771         {
    772             if (pcbMax)
    773                 *pcbMax = offLow;
    774             return RTFileSeek(hFile, offOld, RTFILE_SEEK_BEGIN, NULL);
    775         }
    776 
    777         rc = RTFileSeek(hFile, offLow + cbInterval, RTFILE_SEEK_BEGIN, NULL);
     763
     764    /*
     765     * Quickly guess the order of magnitude for offHigh and offLow.
     766     */
     767    {
     768        uint64_t offHighPrev = offHigh;
     769        while (offHigh >= INT32_MAX)
     770        {
     771            rc = RTFileSeek(hFile, offHigh, RTFILE_SEEK_BEGIN, NULL);
     772            if (RT_SUCCESS(rc))
     773            {
     774                offLow = offHigh;
     775                offHigh = offHighPrev;
     776                break;
     777            }
     778            else
     779            {
     780                offHighPrev = offHigh;
     781                offHigh >>= 8;
     782            }
     783        }
     784    }
     785
     786    /*
     787     * Sanity: if the seek to the initial offHigh (INT64_MAX) works, then
     788     * this algorithm cannot possibly work. Declare defeat.
     789     */
     790    if (offLow == offHigh)
     791        return VERR_NOT_SUPPORTED;
     792
     793    /*
     794     * Perform a binary search for the max file size.
     795     */
     796    while (offLow <= offHigh)
     797    {
     798        uint64_t offMid = offLow + (offHigh - offLow) / 2;
     799        rc = RTFileSeek(hFile, offMid, RTFILE_SEEK_BEGIN, NULL);
    778800        if (RT_FAILURE(rc))
    779             offHigh = offLow + cbInterval;
     801            offHigh = offMid - 1;
    780802        else
    781             offLow  = offLow + cbInterval;
    782     }
     803            offLow  = offMid + 1;
     804    }
     805
     806    if (pcbMax)
     807        *pcbMax = RT_MIN(offLow, offHigh);
     808    return RTFileSeek(hFile, offOld, RTFILE_SEEK_BEGIN, NULL);
    783809}
    784810
Note: See TracChangeset for help on using the changeset viewer.

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