diff --git a/headers/os/drivers/fs_cache.h b/headers/os/drivers/fs_cache.h index 2dd1b1bba3..4aeb98dda9 100644 --- a/headers/os/drivers/fs_cache.h +++ b/headers/os/drivers/fs_cache.h @@ -67,7 +67,7 @@ extern status_t file_cache_write(void *_cacheRef, void *cookie, off_t offset, const void *buffer, size_t *_size); /* file map */ -extern void *file_map_create(dev_t mountID, ino_t vnodeID); +extern void *file_map_create(dev_t mountID, ino_t vnodeID, off_t size); extern void file_map_delete(void *_map); extern void file_map_set_size(void *_map, off_t size); extern void file_map_invalidate(void *_map, off_t offset, off_t size); diff --git a/headers/private/fs_shell/fssh_fs_cache.h b/headers/private/fs_shell/fssh_fs_cache.h index e3841a5644..335068761e 100644 --- a/headers/private/fs_shell/fssh_fs_cache.h +++ b/headers/private/fs_shell/fssh_fs_cache.h @@ -84,7 +84,7 @@ extern fssh_status_t fssh_file_cache_write(void *_cacheRef, void *cookie, /* file map */ extern void * fssh_file_map_create(fssh_mount_id mountID, - fssh_vnode_id vnodeID); + fssh_vnode_id vnodeID, fssh_off_t size); extern void fssh_file_map_delete(void *_map); extern void fssh_file_map_set_size(void *_map, fssh_off_t size); extern void fssh_file_map_invalidate(void *_map, fssh_off_t offset, diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index 7e0ddd673b..d2bb3312ca 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -195,7 +195,7 @@ Inode::Inode(Volume *volume, ino_t id) fTree = new BPlusTree(this); if (IsFile() || IsAttribute()) { SetFileCache(file_cache_create(fVolume->ID(), ID(), Size())); - SetMap(file_map_create(volume->ID(), ID())); + SetMap(file_map_create(volume->ID(), ID(), Size())); } } @@ -2417,7 +2417,8 @@ Inode::Create(Transaction &transaction, Inode *parent, const char *name, if (inode->IsFile() || inode->IsAttribute()) { inode->SetFileCache(file_cache_create(volume->ID(), inode->ID(), inode->Size())); - inode->SetMap(file_map_create(volume->ID(), inode->ID())); + inode->SetMap(file_map_create(volume->ID(), inode->ID(), + inode->Size())); } if (_created) 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 5ff5bfdf75..7059003ecb 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -858,7 +858,7 @@ bfs_create_symlink(void *_ns, void *_directory, const char *name, // links usually don't have a file cache attached - but we now need one link->SetFileCache(file_cache_create(volume->ID(), link->ID(), 0)); - link->SetMap(file_map_create(volume->ID(), link->ID())); + link->SetMap(file_map_create(volume->ID(), link->ID(), 0)); // The following call will have to write the inode back, so // we don't have to do that here... diff --git a/src/add-ons/kernel/file_systems/fat/dir.c b/src/add-ons/kernel/file_systems/fat/dir.c index 6f91779515..d2450fae55 100644 --- a/src/add-ons/kernel/file_systems/fat/dir.c +++ b/src/add-ons/kernel/file_systems/fat/dir.c @@ -1039,7 +1039,7 @@ dosfs_read_vnode(void *_vol, ino_t vnid, void **_node, bool reenter) if (entry->filename) strcpy(entry->filename, filename); #endif entry->cache = file_cache_create(vol->id, vnid, entry->st_size); - entry->file_map = file_map_create(vol->id, vnid); + entry->file_map = file_map_create(vol->id, vnid, entry->st_size); if (!(entry->mode & FAT_SUBDIR)) set_mime_type(entry, filename); diff --git a/src/system/kernel/cache/file_map.cpp b/src/system/kernel/cache/file_map.cpp index e93642bbd2..ffeb4ed8cc 100644 --- a/src/system/kernel/cache/file_map.cpp +++ b/src/system/kernel/cache/file_map.cpp @@ -40,7 +40,7 @@ struct file_extent { }; struct file_map { - file_map(); + file_map(off_t size); ~file_map(); file_extent *operator[](uint32 index); @@ -54,13 +54,15 @@ struct file_map { }; size_t count; struct vnode *vnode; + off_t size; }; -file_map::file_map() +file_map::file_map(off_t _size) { array = NULL; count = 0; + size = _size; } @@ -179,11 +181,12 @@ find_file_extent(file_map &map, off_t offset, uint32 *_index) extern "C" void * -file_map_create(dev_t mountID, ino_t vnodeID) +file_map_create(dev_t mountID, ino_t vnodeID, off_t size) { - TRACE(("file_map_create(mountID = %ld, vnodeID = %Ld)\n", mountID, vnodeID)); + TRACE(("file_map_create(mountID = %ld, vnodeID = %Ld, size = %Ld)\n", + mountID, vnodeID, size)); - file_map *map = new file_map; + file_map *map = new file_map(size); if (map == NULL) return NULL; @@ -218,7 +221,9 @@ file_map_set_size(void *_map, off_t size) // TODO: honour offset/size parameters file_map *map = (file_map *)_map; - map->Free(); + if (size < map->size) + map->Free(); + map->size = size; } @@ -248,6 +253,13 @@ file_map_translate(void *_map, off_t offset, size_t size, file_io_vec *vecs, size_t maxVecs = *_count; status_t status = B_OK; + if (offset > map.size) { + *_count = 0; + return B_OK; + } + if (offset + size > map.size) + size = map.size - offset; + if (map.count == 0) { // we don't yet have the map of this file, so let's grab it // (ordered by offset, so that we can do a binary search on them) diff --git a/src/tools/fs_shell/file_map.cpp b/src/tools/fs_shell/file_map.cpp index 3d75ce3045..df81128df5 100644 --- a/src/tools/fs_shell/file_map.cpp +++ b/src/tools/fs_shell/file_map.cpp @@ -34,7 +34,7 @@ struct file_extent { }; struct file_map { - file_map(); + file_map(fssh_off_t size); ~file_map(); file_extent *operator[](uint32_t index); @@ -49,13 +49,15 @@ struct file_map { }; fssh_size_t count; void *vnode; + fssh_off_t size; }; -file_map::file_map() +file_map::file_map(fssh_off_t _size) { array = NULL; count = 0; + size = size; } @@ -178,11 +180,12 @@ find_file_extent(file_map &map, fssh_off_t offset, uint32_t *_index) extern "C" void * -fssh_file_map_create(fssh_mount_id mountID, fssh_vnode_id vnodeID) +fssh_file_map_create(fssh_mount_id mountID, fssh_vnode_id vnodeID, + fssh_off_t size) { TRACE(("file_map_create(mountID = %ld, vnodeID = %Ld)\n", mountID, vnodeID)); - file_map *map = new file_map; + file_map *map = new file_map(size); if (map == NULL) return NULL; @@ -217,7 +220,9 @@ fssh_file_map_set_size(void *_map, fssh_off_t size) // TODO: honour offset/size parameters file_map *map = (file_map *)_map; - map->Free(); + if (size < map->size) + map->Free(); + map->size = size; } @@ -244,6 +249,13 @@ fssh_file_map_translate(void *_map, fssh_off_t offset, fssh_size_t size, fssh_size_t maxVecs = *_count; fssh_status_t status = FSSH_B_OK; + if (offset > map.size) { + *_count = 0; + return FSSH_B_OK; + } + if (offset + size > map.size) + size = map.size - offset; + if (map.count == 0) { // we don't yet have the map of this file, so let's grab it // (ordered by offset, so that we can do a binary search on them)