Changeset 26523

Show
Ignore:
Timestamp:
07/20/08 12:29:12 (4 months ago)
Author:
bonefish
Message:

axeld + bonefish + mmlr:
* FileMap::_InvalidateAfter():

  • Off-by-one error. The last extend (which normally should be kept) was thrown away, too, but still accessed afterwards. Worst case could be a write to free()d memory.
  • Drop the last extend when it would be truncated to zero size.

* FileMap::Translate():

  • Incorrect handling of B_BUFFER_OVERFLOW case in the vfs_get_file_map() loop. After the loop the function would return incorrectly, making the caller think all vectors in the provided array had been initialized correctly. This could cause a file system implementation using the file map to read from or write to random disk locations, in the latter case possibly corrupting the file system.
  • Some readability improvements in the final loop. Removed incorrect check.
Files:
1 modified

Legend:

Unmodified
Added
Removed
  • haiku/trunk/src/system/kernel/cache/file_map.cpp

    r26295 r26523  
    172172        if (count <= CACHED_FILE_EXTENTS) { 
    173173                // just use the reserved area in the file_cache_ref structure 
    174                 if (count <= CACHED_FILE_EXTENTS && fCount > CACHED_FILE_EXTENTS) { 
     174                if (fCount > CACHED_FILE_EXTENTS) { 
    175175                        // the new size is smaller than the minimal array size 
    176176                        file_extent *array = fIndirect.array; 
     
    271271        file_extent* extent = _FindExtent(offset, &index); 
    272272        if (extent != NULL) { 
    273                 _MakeSpace(index); 
    274  
    275                 if (extent->offset + extent->disk.length > offset) 
     273                _MakeSpace(index + 1); 
     274 
     275                if (extent->offset + extent->disk.length > offset) { 
    276276                        extent->disk.length = offset - extent->offset; 
     277                        if (extent->disk.length == 0) 
     278                                _MakeSpace(index); 
     279                } 
    277280        } 
    278281} 
     
    346349        off_t end = offset + size; 
    347350 
    348         while (mapOffset < end) { 
     351        while (status == B_OK && mapOffset < end) { 
    349352                // We don't have the requested extents yet, retrieve them 
    350353                size_t vecCount = maxVecs; 
    351354                status = vfs_get_file_map(Vnode(), mapOffset, ~0UL, vecs, &vecCount); 
    352                 if (status < B_OK && status != B_BUFFER_OVERFLOW) 
    353                         return status; 
    354  
    355                 status_t addStatus = _Add(vecs, vecCount, mapOffset); 
    356                 if (addStatus != B_OK) { 
    357                         // only clobber the status in case of failure 
    358                         status = addStatus; 
    359                 } 
    360  
    361                 if (status != B_BUFFER_OVERFLOW) 
    362                         break; 
     355                if (status == B_OK || status == B_BUFFER_OVERFLOW) 
     356                        status = _Add(vecs, vecCount, mapOffset); 
    363357        } 
    364358 
     
    376370        vecs[0].length = fileExtent->disk.length - offset; 
    377371 
    378         if (vecs[0].length >= size || index >= fCount - 1) { 
     372        if (vecs[0].length >= size) { 
     373                if (vecs[0].length > size) 
     374                        vecs[0].length = size; 
    379375                *_count = 1; 
    380376                return B_OK; 
     
    384380 
    385381        size -= vecs[0].length; 
    386  
    387         for (index = 1; index < fCount;) { 
     382        uint32 vecIndex = 1; 
     383 
     384        while (true) { 
    388385                fileExtent++; 
    389386 
    390                 vecs[index] = fileExtent->disk; 
    391                 index++; 
    392  
    393                 if (size <= fileExtent->disk.length) 
     387                vecs[vecIndex++] = fileExtent->disk; 
     388 
     389                if (size <= fileExtent->disk.length) { 
     390                        if (size < fileExtent->disk.length) 
     391                                vecs[vecIndex - 1].length = size; 
    394392                        break; 
    395  
    396                 if (index >= maxVecs) { 
    397                         *_count = index; 
     393                } 
     394 
     395                if (vecIndex >= maxVecs) { 
     396                        *_count = vecIndex; 
    398397                        return B_BUFFER_OVERFLOW; 
    399398                } 
     
    402401        } 
    403402 
    404         *_count = index; 
     403        *_count = vecIndex; 
    405404        return B_OK; 
    406405}