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:
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user