diff --git a/headers/os/drivers/fs_cache.h b/headers/os/drivers/fs_cache.h index 44a843da7e..2ecd3c4d3a 100644 --- a/headers/os/drivers/fs_cache.h +++ b/headers/os/drivers/fs_cache.h @@ -97,7 +97,7 @@ extern void file_map_set_size(void *_map, off_t size); extern void file_map_invalidate(void *_map, off_t offset, off_t size); extern status_t file_map_set_mode(void *_map, uint32 mode); extern status_t file_map_translate(void *_map, off_t offset, size_t size, - struct file_io_vec *vecs, size_t *_count); + struct file_io_vec *vecs, size_t *_count, size_t align); #ifdef __cplusplus } diff --git a/headers/private/fs_shell/fssh_fs_cache.h b/headers/private/fs_shell/fssh_fs_cache.h index 3082f77c19..c0135beead 100644 --- a/headers/private/fs_shell/fssh_fs_cache.h +++ b/headers/private/fs_shell/fssh_fs_cache.h @@ -118,7 +118,7 @@ extern void fssh_file_map_invalidate(void *_map, fssh_off_t offset, extern fssh_status_t fssh_file_map_set_mode(void *_map, uint32_t mode); extern fssh_status_t fssh_file_map_translate(void *_map, fssh_off_t offset, fssh_size_t size, struct fssh_file_io_vec *vecs, - fssh_size_t *_count); + fssh_size_t *_count, fssh_size_t align); #ifdef __cplusplus } diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index 2f20e2849c..5973bbd6a0 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -64,7 +64,9 @@ iterative_io_get_vecs_hook(void* cookie, io_request* request, off_t offset, size_t size, struct file_io_vec* vecs, size_t* _count) { Inode* inode = (Inode*)cookie; - return file_map_translate(inode->Map(), offset, size, vecs, _count); + return file_map_translate(inode->Map(), offset, size, vecs, _count, 512); + // TODO: Use the actual block size of the underlying device for the + // alignment! } @@ -382,7 +384,7 @@ bfs_read_pages(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 fileVecCount = 8; status = file_map_translate(inode->Map(), pos, bytesLeft, fileVecs, - &fileVecCount); + &fileVecCount, 0); if (status != B_OK && status != B_BUFFER_OVERFLOW) break; @@ -427,7 +429,7 @@ bfs_write_pages(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 fileVecCount = 8; status = file_map_translate(inode->Map(), pos, bytesLeft, fileVecs, - &fileVecCount); + &fileVecCount, 0); if (status != B_OK && status != B_BUFFER_OVERFLOW) break; diff --git a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp index d27c2d11c3..c3f6668a88 100644 --- a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp @@ -219,7 +219,7 @@ ext2_read_pages(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 fileVecCount = 8; status = file_map_translate(inode->Map(), pos, bytesLeft, fileVecs, - &fileVecCount); + &fileVecCount, 0); if (status != B_OK && status != B_BUFFER_OVERFLOW) break; diff --git a/src/add-ons/kernel/file_systems/fat/file.c b/src/add-ons/kernel/file_systems/fat/file.c index b71046a35e..683459e820 100644 --- a/src/add-ons/kernel/file_systems/fat/file.c +++ b/src/add-ons/kernel/file_systems/fat/file.c @@ -1533,7 +1533,7 @@ dosfs_read_pages(fs_volume *_vol, fs_vnode *_node, void *_cookie, size_t bytes = bytesLeft; status = file_map_translate(node->file_map, pos, bytesLeft, fileVecs, - &fileVecCount); + &fileVecCount, 0); if (status != B_OK && status != B_BUFFER_OVERFLOW) break; @@ -1586,7 +1586,7 @@ dosfs_write_pages(fs_volume *_vol, fs_vnode *_node, void *_cookie, size_t bytes = bytesLeft; status = file_map_translate(node->file_map, pos, bytesLeft, fileVecs, - &fileVecCount); + &fileVecCount, 0); if (status != B_OK && status != B_BUFFER_OVERFLOW) break; diff --git a/src/system/kernel/cache/file_map.cpp b/src/system/kernel/cache/file_map.cpp index 07abcef09a..556bae16be 100644 --- a/src/system/kernel/cache/file_map.cpp +++ b/src/system/kernel/cache/file_map.cpp @@ -63,7 +63,8 @@ public: void SetSize(off_t size); status_t Translate(off_t offset, size_t size, - file_io_vec* vecs, size_t* _count); + file_io_vec* vecs, size_t* _count, + size_t align); file_extent* ExtentAt(uint32 index); @@ -383,18 +384,26 @@ FileMap::SetMode(uint32 mode) status_t -FileMap::Translate(off_t offset, size_t size, file_io_vec* vecs, size_t* _count) +FileMap::Translate(off_t offset, size_t size, file_io_vec* vecs, size_t* _count, + size_t align) { MutexLocker _(fLock); size_t maxVecs = *_count; + size_t padLastVec = 0; if (offset >= Size()) { *_count = 0; return B_OK; } - if (offset + size > fSize) + if (offset + size > fSize) { + if (align > 1) { + off_t alignedSize = (fSize + align - 1) & ~(off_t)(align - 1); + if (offset + size >= alignedSize) + padLastVec = alignedSize - fSize; + } size = fSize - offset; + } // First, we need to make sure that we have already cached all file // extents needed for this request. @@ -414,8 +423,7 @@ FileMap::Translate(off_t offset, size_t size, file_io_vec* vecs, size_t* _count) vecs[0].length = fileExtent->disk.length - offset; if (vecs[0].length >= size) { - if (vecs[0].length > size) - vecs[0].length = size; + vecs[0].length = size + padLastVec; *_count = 1; return B_OK; } @@ -431,8 +439,7 @@ FileMap::Translate(off_t offset, size_t size, file_io_vec* vecs, size_t* _count) vecs[vecIndex++] = fileExtent->disk; if (size <= fileExtent->disk.length) { - if (size < fileExtent->disk.length) - vecs[vecIndex - 1].length = size; + vecs[vecIndex - 1].length = size + padLastVec; break; } @@ -627,7 +634,7 @@ file_map_set_mode(void* _map, uint32 mode) extern "C" status_t file_map_translate(void* _map, off_t offset, size_t size, file_io_vec* vecs, - size_t* _count) + size_t* _count, size_t align) { TRACE(("file_map_translate(map %p, offset %Ld, size %ld)\n", _map, offset, size)); @@ -636,6 +643,6 @@ file_map_translate(void* _map, off_t offset, size_t size, file_io_vec* vecs, if (map == NULL) return B_BAD_VALUE; - return map->Translate(offset, size, vecs, _count); + return map->Translate(offset, size, vecs, _count, align); } diff --git a/src/tools/fs_shell/file_map.cpp b/src/tools/fs_shell/file_map.cpp index 1380f4c527..79632da6cb 100644 --- a/src/tools/fs_shell/file_map.cpp +++ b/src/tools/fs_shell/file_map.cpp @@ -48,7 +48,8 @@ public: void SetSize(fssh_off_t size); fssh_status_t Translate(fssh_off_t offset, fssh_size_t size, - fssh_file_io_vec* vecs, fssh_size_t* _count); + fssh_file_io_vec* vecs, fssh_size_t* _count, + fssh_size_t align); file_extent* ExtentAt(uint32_t index); @@ -354,18 +355,25 @@ FileMap::SetMode(uint32_t mode) fssh_status_t FileMap::Translate(fssh_off_t offset, fssh_size_t size, fssh_file_io_vec* vecs, - fssh_size_t* _count) + fssh_size_t* _count, fssh_size_t align) { MutexLocker _(fLock); fssh_size_t maxVecs = *_count; + fssh_size_t padLastVec = 0; if (offset >= Size()) { *_count = 0; return FSSH_B_OK; } - if (offset + size > fSize) + if (offset + size > fSize) { + if (align > 1) { + fssh_off_t alignedSize = (fSize + align - 1) & ~(off_t)(align - 1); + if (offset + size >= alignedSize) + padLastVec = alignedSize - fSize; + } size = fSize - offset; + } // First, we need to make sure that we have already cached all file // extents needed for this request. @@ -385,8 +393,7 @@ FileMap::Translate(fssh_off_t offset, fssh_size_t size, fssh_file_io_vec* vecs, vecs[0].length = fileExtent->disk.length - offset; if (vecs[0].length >= size) { - if (vecs[0].length > size) - vecs[0].length = size; + vecs[0].length = size + padLastVec; *_count = 1; return FSSH_B_OK; } @@ -402,8 +409,7 @@ FileMap::Translate(fssh_off_t offset, fssh_size_t size, fssh_file_io_vec* vecs, vecs[vecIndex++] = fileExtent->disk; if (size <= fileExtent->disk.length) { - if (size < fileExtent->disk.length) - vecs[vecIndex - 1].length = size; + vecs[vecIndex - 1].length = size + padLastVec; break; } @@ -490,7 +496,7 @@ fssh_file_map_set_mode(void* _map, uint32_t mode) extern "C" fssh_status_t fssh_file_map_translate(void* _map, fssh_off_t offset, fssh_size_t size, - fssh_file_io_vec* vecs, fssh_size_t* _count) + fssh_file_io_vec* vecs, fssh_size_t* _count, fssh_size_t align) { TRACE(("file_map_translate(map %p, offset %Ld, size %ld)\n", _map, offset, size)); @@ -499,6 +505,6 @@ fssh_file_map_translate(void* _map, fssh_off_t offset, fssh_size_t size, if (map == NULL) return FSSH_B_BAD_VALUE; - return map->Translate(offset, size, vecs, _count); + return map->Translate(offset, size, vecs, _count, align); }