diff --git a/common/types.go b/common/types.go index baefaf59f..707b60d96 100644 --- a/common/types.go +++ b/common/types.go @@ -70,6 +70,8 @@ const ( FuseAllowedFlags = "invalid FUSE options. Allowed FUSE configurations are: `-o attr_timeout=TIMEOUT`, `-o negative_timeout=TIMEOUT`, `-o entry_timeout=TIMEOUT` `-o allow_other`, `-o allow_root`, `-o umask=PERMISSIONS -o default_permissions`, `-o ro`" UserAgentHeader = "User-Agent" + + BlockCacheRWErrMsg = "Notice: The random write flow using block cache is temporarily blocked due to potential data integrity issues. This is a precautionary measure. \nIf you see this message, contact blobfusedev@microsoft.com or create a GitHub issue. We're working on a fix. More details: https://aka.ms/blobfuse2warnings." ) func FuseIgnoredFlags() []string { diff --git a/component/block_cache/block_cache.go b/component/block_cache/block_cache.go index c843741c1..166a1a4de 100644 --- a/component/block_cache/block_cache.go +++ b/component/block_cache/block_cache.go @@ -1008,8 +1008,8 @@ func (bc *BlockCache) getOrCreateBlock(handle *handlemap.Handle, offset uint64) // block not present in the buffer list // check if it is a random write case and should be blocked if bc.blockRandomWrite(handle, index) { - log.Err("BlockCache::WriteFile : Random write detection for write offset %v and block %v, where handle size is %v", offset, index, handle.Size) - return nil, fmt.Errorf("blocking random write for write offset %v and block %v where handle size is %v", offset, index, handle.Size) + log.Err("BlockCache::WriteFile : Random write detection for write offset %v and block %v, where handle size is %v\n%v", offset, index, handle.Size, common.BlockCacheRWErrMsg) + return nil, fmt.Errorf("blocking random write for write offset %v and block %v where handle size is %v\n%v", offset, index, handle.Size, common.BlockCacheRWErrMsg) } // If too many buffers are piled up for this file then try to evict some of those which are already uploaded @@ -1035,8 +1035,8 @@ func (bc *BlockCache) getOrCreateBlock(handle *handlemap.Handle, offset uint64) // if a block has been staged and deleted from the buffer list, then we should commit the existing blocks // TODO: commit the dirty blocks and download the given block if shouldCommit { - log.Err("BlockCache::getOrCreateBlock : Fetching an uncommitted block %v for %v=>%s", block.id, handle.ID, handle.Path) - return nil, fmt.Errorf("fetching an uncommitted block %v for %v=>%s", block.id, handle.ID, handle.Path) + log.Err("BlockCache::getOrCreateBlock : Fetching an uncommitted block %v for %v=>%s\n%v", block.id, handle.ID, handle.Path, common.BlockCacheRWErrMsg) + return nil, fmt.Errorf("fetching an uncommitted block %v for %v=>%s\n%v", block.id, handle.ID, handle.Path, common.BlockCacheRWErrMsg) } // download the block if, @@ -1411,8 +1411,8 @@ func (bc *BlockCache) getBlockIDList(handle *handlemap.Handle) ([]string, error) if index == offsets[i] { // TODO: when a staged block (not last block) has data less than block size if i != len(offsets)-1 && listMap[offsets[i]].size != bc.blockSize { - log.Err("BlockCache::getBlockIDList : Staged block %v has less data %v for %v=>%s", offsets[i], listMap[offsets[i]].size, handle.ID, handle.Path) - return nil, fmt.Errorf("staged block %v has less data %v for %v=>%s", offsets[i], listMap[offsets[i]].size, handle.ID, handle.Path) + log.Err("BlockCache::getBlockIDList : Staged block %v has less data %v for %v=>%s\n%v", offsets[i], listMap[offsets[i]].size, handle.ID, handle.Path, common.BlockCacheRWErrMsg) + return nil, fmt.Errorf("staged block %v has less data %v for %v=>%s\n%v", offsets[i], listMap[offsets[i]].size, handle.ID, handle.Path, common.BlockCacheRWErrMsg) } blockIDList = append(blockIDList, listMap[offsets[i]].id) diff --git a/component/block_cache/block_cache_test.go b/component/block_cache/block_cache_test.go index 16f4e5c7d..645b4bab8 100644 --- a/component/block_cache/block_cache_test.go +++ b/component/block_cache/block_cache_test.go @@ -1645,6 +1645,7 @@ func (suite *blockCacheTestSuite) TestDisableRandomWrite() { // write 1MB data back at offset 0 n, err := tobj.blockCache.WriteFile(internal.WriteFileOptions{Handle: h, Offset: 0, Data: dataBuff[0:_1MB]}) suite.assert.NotNil(err) + suite.ErrorContains(err, common.BlockCacheRWErrMsg) suite.assert.Equal(n, 0) fs, err := os.Stat(storagePath) @@ -1694,6 +1695,7 @@ func (suite *blockCacheTestSuite) TestDisableRandomWriteExistingFile() { // write randomly in new handle at offset 2MB n, err = tobj.blockCache.WriteFile(internal.WriteFileOptions{Handle: nh, Offset: int64(2 * _1MB), Data: dataBuff[0:10]}) suite.assert.NotNil(err) + suite.ErrorContains(err, common.BlockCacheRWErrMsg) suite.assert.Equal(n, 0) }