From 9b906ccf04dba976f4267598ecf755841a866dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 30 Aug 2006 23:18:31 +0000 Subject: [PATCH] * You can now create the block cache in read-only mode (using an additional parameter during construction). * Doing so will now result in a kernel panic whenever your file system tries to write to a block. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18719 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/drivers/fs_cache.h | 2 +- src/add-ons/kernel/file_systems/bfs/Volume.cpp | 4 ++-- src/add-ons/kernel/file_systems/dos/dosfs.c | 5 +++-- src/add-ons/kernel/file_systems/iso9660/iso.c | 4 ++-- src/system/kernel/cache/block_cache.cpp | 16 ++++++++++++---- src/system/kernel/cache/block_cache_private.h | 4 +++- 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/headers/os/drivers/fs_cache.h b/headers/os/drivers/fs_cache.h index 8f8cb0b3f3..cfa7f911d8 100644 --- a/headers/os/drivers/fs_cache.h +++ b/headers/os/drivers/fs_cache.h @@ -31,7 +31,7 @@ extern int32 cache_blocks_in_sub_transaction(void *_cache, int32 id); /* block cache */ extern void block_cache_delete(void *_cache, bool allowWrites); -extern void *block_cache_create(int fd, off_t numBlocks, size_t blockSize); +extern void *block_cache_create(int fd, off_t numBlocks, size_t blockSize, bool readOnly); extern status_t block_cache_sync(void *_cache); extern status_t block_cache_make_writable(void *_cache, off_t blockNumber, int32 transaction); diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.cpp b/src/add-ons/kernel/file_systems/bfs/Volume.cpp index 7ad70e831b..027e95ca26 100644 --- a/src/add-ons/kernel/file_systems/bfs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Volume.cpp @@ -106,7 +106,7 @@ DeviceOpener::Open(const char *device, int mode) void * DeviceOpener::InitCache(off_t numBlocks, uint32 blockSize) { - return block_cache_create(fDevice, numBlocks, blockSize); + return block_cache_create(fDevice, numBlocks, blockSize, fMode == O_RDONLY); } @@ -152,7 +152,7 @@ DeviceOpener::GetSize(off_t *_size, uint32 *_blockSize) if (_size) { *_size = 1LL * geometry.head_count * geometry.cylinder_count - * geometry.sectors_per_track * geometry.bytes_per_sector; + * geometry.sectors_per_track * geometry.bytes_per_sector; } if (_blockSize) *_blockSize = geometry.bytes_per_sector; diff --git a/src/add-ons/kernel/file_systems/dos/dosfs.c b/src/add-ons/kernel/file_systems/dos/dosfs.c index 7b05eebff7..0fc70a4a26 100644 --- a/src/add-ons/kernel/file_systems/dos/dosfs.c +++ b/src/add-ons/kernel/file_systems/dos/dosfs.c @@ -436,12 +436,13 @@ static status_t mount_fat_disk(const char *path, mount_id nsid, } // initialize block cache - vol->fBlockCache = block_cache_create(vol->fd, vol->total_sectors, vol->bytes_per_sector); + vol->fBlockCache = block_cache_create(vol->fd, vol->total_sectors, + vol->bytes_per_sector, (vol->flags & B_FS_IS_READONLY) != 0); if (vol->fBlockCache == NULL) { dprintf("error initializing block cache\n"); goto error; } - + // as well as the vnode cache if (init_vcache(vol) != B_OK) { dprintf("error initializing vnode cache\n"); diff --git a/src/add-ons/kernel/file_systems/iso9660/iso.c b/src/add-ons/kernel/file_systems/iso9660/iso.c index 81a2d39a80..3a3f5766f1 100644 --- a/src/add-ons/kernel/file_systems/iso9660/iso.c +++ b/src/add-ons/kernel/file_systems/iso9660/iso.c @@ -267,7 +267,8 @@ ISOMount(const char *path, const int flags, nspace **newVol, bool allow_joliet) /* Initialize access to the cache so that we can do cached i/o */ TRACE(("ISO9660: cache init: dev %d, max blocks %Ld\n", vol->fd, maxBlocks)); - vol->fBlockCache = block_cache_create(vol->fd, maxBlocks, vol->logicalBlkSize[FS_DATA_FORMAT]); + vol->fBlockCache = block_cache_create(vol->fd, maxBlocks, + vol->logicalBlkSize[FS_DATA_FORMAT], true); is_iso = true; } else if ((*buffer == 0x02) && is_iso && allow_joliet) { // ISO_VD_SUPPLEMENTARY @@ -287,7 +288,6 @@ ISOMount(const char *path, const int flags, nspace **newVol, bool allow_joliet) // update root directory record. if (vol->joliet_level > 0) InitNode(&(vol->rootDirRec), &buffer[156], NULL, 0); - } } else if (*(unsigned char *)buffer == 0xff) { // ISO_VD_END diff --git a/src/system/kernel/cache/block_cache.cpp b/src/system/kernel/cache/block_cache.cpp index ee20bafab4..0d169c16b1 100644 --- a/src/system/kernel/cache/block_cache.cpp +++ b/src/system/kernel/cache/block_cache.cpp @@ -149,7 +149,7 @@ cached_block::Hash(void *_cacheEntry, const void *_block, uint32 range) // #pragma mark - block_cache -block_cache::block_cache(int _fd, off_t numBlocks, size_t blockSize) +block_cache::block_cache(int _fd, off_t numBlocks, size_t blockSize, bool readOnly) : hash(NULL), fd(_fd), @@ -158,7 +158,8 @@ block_cache::block_cache(int _fd, off_t numBlocks, size_t blockSize) next_transaction_id(1), last_transaction(NULL), transaction_hash(NULL), - ranges_hash(NULL) + ranges_hash(NULL), + read_only(readOnly) { hash = hash_init(32, 0, &cached_block::Compare, &cached_block::Hash); if (hash == NULL) @@ -1078,9 +1079,9 @@ block_cache_delete(void *_cache, bool allowWrites) extern "C" void * -block_cache_create(int fd, off_t numBlocks, size_t blockSize) +block_cache_create(int fd, off_t numBlocks, size_t blockSize, bool readOnly) { - block_cache *cache = new block_cache(fd, numBlocks, blockSize); + block_cache *cache = new block_cache(fd, numBlocks, blockSize, readOnly); if (cache == NULL) return NULL; @@ -1126,6 +1127,9 @@ block_cache_make_writable(void *_cache, off_t blockNumber, int32 transaction) block_cache *cache = (block_cache *)_cache; BenaphoreLocker locker(&cache->lock); + if (cache->read_only) + panic("tried to make block writable on a read-only cache!"); + // ToDo: this can be done better! void *block = get_writable_cached_block(cache, blockNumber, blockNumber, 1, transaction, false); @@ -1147,6 +1151,8 @@ block_cache_get_writable_etc(void *_cache, off_t blockNumber, off_t base, TRACE(("block_cache_get_writable_etc(block = %Ld, transaction = %ld)\n", blockNumber, transaction)); + if (cache->read_only) + panic("tried to get writable block on a read-only cache!"); return get_writable_cached_block(cache, blockNumber, base, length, transaction, false); @@ -1169,6 +1175,8 @@ block_cache_get_empty(void *_cache, off_t blockNumber, int32 transaction) TRACE(("block_cache_get_empty(block = %Ld, transaction = %ld)\n", blockNumber, transaction)); + if (cache->read_only) + panic("tried to get empty writable block on a read-only cache!"); return get_writable_cached_block((block_cache *)_cache, blockNumber, blockNumber, 1, transaction, true); diff --git a/src/system/kernel/cache/block_cache_private.h b/src/system/kernel/cache/block_cache_private.h index 11a652aa46..daddd0639d 100644 --- a/src/system/kernel/cache/block_cache_private.h +++ b/src/system/kernel/cache/block_cache_private.h @@ -116,7 +116,9 @@ struct block_cache { block_list unmapped_blocks; block_list unused_blocks; - block_cache(int fd, off_t numBlocks, size_t blockSize); + bool read_only; + + block_cache(int fd, off_t numBlocks, size_t blockSize, bool readOnly); ~block_cache(); status_t InitCheck();