Added CachedBlock::BlockSize(), and CachedBlock::BlockShift() methods as

suggested by Mike Nordell.
Some code cleanups, added a comment in Inode::SetFileSize() to point out
that Stream<Cache>::WriteAt() denies growing the file size its own.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1060 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2002-09-16 16:03:05 +00:00
parent 850b731e4d
commit d801dfdd1c
3 changed files with 48 additions and 42 deletions
@@ -1452,7 +1452,7 @@ Inode::ShrinkStream(Transaction *transaction, off_t size)
} }
if (data->max_direct_range > size) { if (data->max_direct_range > size) {
off_t offset = 0; off_t offset = 0;
FreeStreamArray(transaction,data->direct,NUM_DIRECT_BLOCKS,size,offset,data->max_direct_range); FreeStreamArray(transaction, data->direct, NUM_DIRECT_BLOCKS, size, offset, data->max_direct_range);
} }
data->size = size; data->size = size;
@@ -1464,7 +1464,9 @@ status_t
Inode::SetFileSize(Transaction *transaction, off_t size) Inode::SetFileSize(Transaction *transaction, off_t size)
{ {
if (size < 0 if (size < 0
// uncached files can't be resized // uncached files can't be resized (Stream<Cache>::WriteAt() specifically
// denies growing uncached files because of efficiency, so it had to be
// adapted if this ever changes [which will probably happen in OpenBeOS]).
|| Flags() & INODE_NO_CACHE) || Flags() & INODE_NO_CACHE)
return B_BAD_VALUE; return B_BAD_VALUE;
+11 -9
View File
@@ -57,20 +57,20 @@ class CachedBlock {
{ {
} }
CachedBlock(Volume *volume,off_t block,bool empty = false) CachedBlock(Volume *volume, off_t block, bool empty = false)
: :
fVolume(volume), fVolume(volume),
fBlock(NULL) fBlock(NULL)
{ {
SetTo(block,empty); SetTo(block, empty);
} }
CachedBlock(Volume *volume,block_run run,bool empty = false) CachedBlock(Volume *volume, block_run run, bool empty = false)
: :
fVolume(volume), fVolume(volume),
fBlock(NULL) fBlock(NULL)
{ {
SetTo(volume->ToBlock(run),empty); SetTo(volume->ToBlock(run), empty);
} }
~CachedBlock() ~CachedBlock()
@@ -81,20 +81,20 @@ class CachedBlock {
void Unset() void Unset()
{ {
if (fBlock != NULL) if (fBlock != NULL)
release_block(fVolume->Device(),fBlockNumber); release_block(fVolume->Device(), fBlockNumber);
} }
uint8 *SetTo(off_t block, bool empty = false) uint8 *SetTo(off_t block, bool empty = false)
{ {
Unset(); Unset();
fBlockNumber = block; fBlockNumber = block;
return fBlock = empty ? (uint8 *)get_empty_block(fVolume->Device(),block,fVolume->BlockSize()) return fBlock = empty ? (uint8 *)get_empty_block(fVolume->Device(), block, BlockSize())
: (uint8 *)get_block(fVolume->Device(),block,fVolume->BlockSize()); : (uint8 *)get_block(fVolume->Device(), block, BlockSize());
} }
uint8 *SetTo(block_run run, bool empty = false) uint8 *SetTo(block_run run, bool empty = false)
{ {
return SetTo(fVolume->ToBlock(run),empty); return SetTo(fVolume->ToBlock(run), empty);
} }
status_t WriteBack(Transaction *transaction) status_t WriteBack(Transaction *transaction)
@@ -102,11 +102,13 @@ class CachedBlock {
if (transaction == NULL || fBlock == NULL) if (transaction == NULL || fBlock == NULL)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
return transaction->WriteBlocks(fBlockNumber,fBlock); return transaction->WriteBlocks(fBlockNumber, fBlock);
} }
uint8 *Block() const { return fBlock; } uint8 *Block() const { return fBlock; }
off_t BlockNumber() const { return fBlockNumber; } off_t BlockNumber() const { return fBlockNumber; }
uint32 BlockSize() const { return fVolume->BlockSize(); }
uint32 BlockShift() const { return fVolume->BlockShift(); }
protected: protected:
Volume *fVolume; Volume *fVolume;
+33 -31
View File
@@ -24,7 +24,7 @@ namespace Access {
class Uncached { class Uncached {
public: public:
Uncached(Volume *volume); Uncached(Volume *volume);
Uncached(Volume *volume,off_t block, bool empty = false); Uncached(Volume *volume, off_t block, bool empty = false);
Uncached(Volume *volume, block_run run, bool empty = false); Uncached(Volume *volume, block_run run, bool empty = false);
~Uncached(); ~Uncached();
@@ -35,11 +35,13 @@ class Uncached {
uint8 *Block() const { return fBlock; } uint8 *Block() const { return fBlock; }
off_t BlockNumber() const { return fBlockNumber; } off_t BlockNumber() const { return fBlockNumber; }
uint32 BlockSize() const { return fVolume->BlockSize(); }
uint32 BlockShift() const { return fVolume->BlockShift(); }
static status_t Read(Volume *volume, block_run run, uint8 *buffer); static status_t Read(Volume *volume, block_run run, uint8 *buffer);
static status_t Write(Transaction *transaction, Volume *volume, block_run run, const uint8 *buffer); static status_t Write(Transaction *transaction, Volume *volume, block_run run, const uint8 *buffer);
protected: private:
Volume *fVolume; Volume *fVolume;
off_t fBlockNumber; off_t fBlockNumber;
uint8 *fBlock; uint8 *fBlock;
@@ -48,7 +50,7 @@ class Uncached {
class Cached : public CachedBlock { class Cached : public CachedBlock {
public: public:
Cached(Volume *volume); Cached(Volume *volume);
Cached(Volume *volume,off_t block, bool empty = false); Cached(Volume *volume, off_t block, bool empty = false);
Cached(Volume *volume, block_run run, bool empty = false); Cached(Volume *volume, block_run run, bool empty = false);
status_t WriteBack(Transaction *transaction); status_t WriteBack(Transaction *transaction);
@@ -116,18 +118,18 @@ Uncached::SetTo(off_t block, bool empty = false)
return NULL; return NULL;
if (empty) if (empty)
memset(fBlock, 0, fVolume->BlockSize()); memset(fBlock, 0, BlockSize());
else else
read_pos(fVolume->Device(), fBlockNumber << fVolume->BlockShift(), fBlock, fVolume->BlockSize()); read_pos(fVolume->Device(), fBlockNumber << BlockShift(), fBlock, BlockSize());
return fBlock; return fBlock;
} }
uint8 * uint8 *
Uncached::SetTo(block_run run,bool empty = false) Uncached::SetTo(block_run run, bool empty = false)
{ {
return SetTo(fVolume->ToBlock(run),empty); return SetTo(fVolume->ToBlock(run), empty);
} }
@@ -137,7 +139,7 @@ Uncached::WriteBack(Transaction *transaction)
if (fBlock == NULL) if (fBlock == NULL)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
return write_pos(fVolume->Device(), fBlockNumber << fVolume->BlockShift(), fBlock, fVolume->BlockSize()); return write_pos(fVolume->Device(), fBlockNumber << BlockShift(), fBlock, BlockSize());
} }
@@ -209,13 +211,13 @@ Logged::Logged(Volume *volume)
} }
Logged::Logged(Volume *volume,off_t block,bool empty = false) Logged::Logged(Volume *volume, off_t block, bool empty = false)
: CachedBlock(volume, block, empty) : CachedBlock(volume, block, empty)
{ {
} }
Logged::Logged(Volume *volume,block_run run,bool empty = false) Logged::Logged(Volume *volume, block_run run, bool empty = false)
: CachedBlock(volume, run, empty) : CachedBlock(volume, run, empty)
{ {
} }
@@ -247,15 +249,15 @@ Logged::Write(Transaction *transaction, Volume *volume, block_run run, const uin
template<class Cache> template<class Cache>
class Stream : public Inode { class Stream : public Inode {
public: private:
// The constructor only exists to make the compiler happy - it // The constructor only exists to make the compiler happy - it
// is never called in the code itself // is never called in the code itself
Stream() : Inode(NULL, -1) {} Stream() : Inode(NULL, -1) {}
public:
status_t FindBlockRun(off_t pos, block_run &run, off_t &offset); status_t FindBlockRun(off_t pos, block_run &run, off_t &offset);
status_t ReadAt(off_t pos, uint8 *buffer, size_t *length); status_t ReadAt(off_t pos, uint8 *buffer, size_t *length);
status_t WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer, size_t *length); status_t WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer, size_t *length);
}; };
@@ -263,7 +265,7 @@ class Stream : public Inode {
template<class Cache> template<class Cache>
status_t status_t
Stream<Cache>::FindBlockRun(off_t pos,block_run &run,off_t &offset) Stream<Cache>::FindBlockRun(off_t pos, block_run &run, off_t &offset)
{ {
data_stream *data = &Node()->data; data_stream *data = &Node()->data;
@@ -276,11 +278,11 @@ Stream<Cache>::FindBlockRun(off_t pos,block_run &run,off_t &offset)
Cache cached(fVolume); Cache cached(fVolume);
off_t start = pos - data->max_indirect_range; off_t start = pos - data->max_indirect_range;
int32 indirectSize = (1L << (INDIRECT_BLOCKS_SHIFT + fVolume->BlockShift())) int32 indirectSize = (1L << (INDIRECT_BLOCKS_SHIFT + cached.BlockShift()))
* (fVolume->BlockSize() / sizeof(block_run)); * (fVolume->BlockSize() / sizeof(block_run));
int32 directSize = NUM_ARRAY_BLOCKS << fVolume->BlockShift(); int32 directSize = NUM_ARRAY_BLOCKS << cached.BlockShift();
int32 index = start / indirectSize; int32 index = start / indirectSize;
int32 runsPerBlock = fVolume->BlockSize() / sizeof(block_run); int32 runsPerBlock = cached.BlockSize() / sizeof(block_run);
block_run *indirect = (block_run *)cached.SetTo( block_run *indirect = (block_run *)cached.SetTo(
fVolume->ToBlock(data->double_indirect) + index / runsPerBlock); fVolume->ToBlock(data->double_indirect) + index / runsPerBlock);
@@ -319,10 +321,10 @@ Stream<Cache>::FindBlockRun(off_t pos,block_run &run,off_t &offset)
if (indirect[current].IsZero()) if (indirect[current].IsZero())
break; break;
runBlockEnd += indirect[current].length << fVolume->BlockShift(); runBlockEnd += indirect[current].length << cached.BlockShift();
if (runBlockEnd > pos) { if (runBlockEnd > pos) {
run = indirect[current]; run = indirect[current];
offset = runBlockEnd - (run.length << fVolume->BlockShift()); offset = runBlockEnd - (run.length << cached.BlockShift());
//printf("reading from indirect block: %ld,%d\n",fRun.allocation_group,fRun.start); //printf("reading from indirect block: %ld,%d\n",fRun.allocation_group,fRun.start);
//printf("### indirect-run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset); //printf("### indirect-run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset);
return fVolume->IsValidBlockRun(run); return fVolume->IsValidBlockRun(run);
@@ -358,7 +360,7 @@ Stream<Cache>::FindBlockRun(off_t pos,block_run &run,off_t &offset)
template<class Cache> template<class Cache>
status_t status_t
Stream<Cache>::ReadAt(off_t pos,uint8 *buffer,size_t *_length) Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
{ {
// set/check boundaries for pos/length // set/check boundaries for pos/length
@@ -376,7 +378,7 @@ Stream<Cache>::ReadAt(off_t pos,uint8 *buffer,size_t *_length)
block_run run; block_run run;
off_t offset; off_t offset;
if (FindBlockRun(pos,run,offset) < B_OK) { if (FindBlockRun(pos, run, offset) < B_OK) {
*_length = 0; *_length = 0;
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
} }
@@ -404,7 +406,7 @@ Stream<Cache>::ReadAt(off_t pos,uint8 *buffer,size_t *_length)
if (length < bytesRead) if (length < bytesRead)
bytesRead = length; bytesRead = length;
memcpy(buffer,block + (pos % blockSize),bytesRead); memcpy(buffer, block + (pos % blockSize), bytesRead);
pos += bytesRead; pos += bytesRead;
length -= bytesRead; length -= bytesRead;
@@ -413,7 +415,7 @@ Stream<Cache>::ReadAt(off_t pos,uint8 *buffer,size_t *_length)
return B_OK; return B_OK;
} }
if (FindBlockRun(pos,run,offset) < B_OK) { if (FindBlockRun(pos, run, offset) < B_OK) {
*_length = bytesRead; *_length = bytesRead;
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
} }
@@ -432,12 +434,12 @@ Stream<Cache>::ReadAt(off_t pos,uint8 *buffer,size_t *_length)
if ((run.length << blockShift) > length) { if ((run.length << blockShift) > length) {
if (length < blockSize) { if (length < blockSize) {
Cache cached(fVolume,run); Cache cached(fVolume, run);
if ((block = cached.Block()) == NULL) { if ((block = cached.Block()) == NULL) {
*_length = bytesRead; *_length = bytesRead;
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
} }
memcpy(buffer + bytesRead,block,length); memcpy(buffer + bytesRead, block, length);
bytesRead += length; bytesRead += length;
break; break;
} }
@@ -506,19 +508,19 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
// If the position of the write was beyond the file size, we // If the position of the write was beyond the file size, we
// have to fill the gap between that position and the old file // have to fill the gap between that position and the old file
// size with zeros. // size with zeros.
FillGapWithZeros(oldSize,pos); FillGapWithZeros(oldSize, pos);
} }
block_run run; block_run run;
off_t offset; off_t offset;
if (FindBlockRun(pos,run,offset) < B_OK) { if (FindBlockRun(pos, run, offset) < B_OK) {
*_length = 0; *_length = 0;
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
} }
bool logStream = (Flags() & INODE_LOGGED) == INODE_LOGGED; bool logStream = (Flags() & INODE_LOGGED) == INODE_LOGGED;
if (logStream) if (logStream)
transaction->Start(fVolume,BlockNumber()); transaction->Start(fVolume, BlockNumber());
uint32 bytesWritten = 0; uint32 bytesWritten = 0;
uint32 blockSize = fVolume->BlockSize(); uint32 blockSize = fVolume->BlockSize();
@@ -533,7 +535,7 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
run.start += (pos - offset) / blockSize; run.start += (pos - offset) / blockSize;
run.length -= (pos - offset) / blockSize; run.length -= (pos - offset) / blockSize;
Cache cached(fVolume,run); Cache cached(fVolume, run);
if ((block = cached.Block()) == NULL) { if ((block = cached.Block()) == NULL) {
*_length = 0; *_length = 0;
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
@@ -555,7 +557,7 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
return B_OK; return B_OK;
} }
if (FindBlockRun(pos,run,offset) < B_OK) { if (FindBlockRun(pos, run, offset) < B_OK) {
*_length = bytesWritten; *_length = bytesWritten;
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
} }
@@ -579,7 +581,7 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
*_length = bytesWritten; *_length = bytesWritten;
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
} }
memcpy(block,buffer + bytesWritten,length); memcpy(block, buffer + bytesWritten, length);
cached.WriteBack(transaction); cached.WriteBack(transaction);
@@ -609,7 +611,7 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
run.start += run.length; run.start += run.length;
run.length = 1; run.length = 1;
offset = pos; offset = pos;
} else if (FindBlockRun(pos,run,offset) < B_OK) { } else if (FindBlockRun(pos, run, offset) < B_OK) {
*_length = bytesWritten; *_length = bytesWritten;
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
} }