* Replace wrong file_cache call with block_cache_get_etc() in Icb::_Read()
* Clean up I've succefully copied data from a udf partition. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27159 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -143,153 +143,160 @@ template <class DescriptorList>
|
||||
status_t
|
||||
Icb::_Read(DescriptorList &list, off_t pos, void *_buffer, size_t *length, uint32 *block)
|
||||
{
|
||||
TRACE(("Icb::_Read(): list: %p, pos: %Ld, buffer: %p, length: (%p)->%ld\n",
|
||||
&list, pos, _buffer, length, (length ? *length : 0)));
|
||||
TRACE(("Icb::_Read(): list = %p, pos = %Ld, buffer = %p, length = %ld\n",
|
||||
&list, pos, _buffer, (length ? *length : 0)));
|
||||
|
||||
uint64 bytesLeftInFile = uint64(pos) > Length() ? 0 : Length() - pos;
|
||||
size_t bytesLeft = (*length >= bytesLeftInFile) ? bytesLeftInFile : *length;
|
||||
size_t bytesRead = 0;
|
||||
|
||||
Volume *volume = GetVolume();
|
||||
status_t error = B_OK;
|
||||
status_t status = B_OK;
|
||||
uint8 *buffer = (uint8 *)_buffer;
|
||||
bool isFirstBlock = true;
|
||||
|
||||
while (bytesLeft > 0 && !error) {
|
||||
|
||||
TRACE(("Icb::_Read(): pos: %Ld\n, bytesLeft: %ld\n", pos, bytesLeft));
|
||||
while (bytesLeft > 0) {
|
||||
|
||||
TRACE(("Icb::_Read(): pos: %Ld, bytesLeft: %ld\n", pos, bytesLeft));
|
||||
long_address extent;
|
||||
bool isEmpty = false;
|
||||
error = list.FindExtent(pos, &extent, &isEmpty);
|
||||
if (!error) {
|
||||
TRACE(("Icb::_Read(): found extent for offset %Ld: (block: %ld, "
|
||||
"partition: %d, length: %ld, type: %d)\n", pos, extent.block(),
|
||||
extent.partition(), extent.length(), extent.type()));
|
||||
|
||||
switch (extent.type()) {
|
||||
case EXTENT_TYPE_RECORDED:
|
||||
isEmpty = false;
|
||||
break;
|
||||
|
||||
case EXTENT_TYPE_ALLOCATED:
|
||||
case EXTENT_TYPE_UNALLOCATED:
|
||||
isEmpty = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE_ERROR(("Icb::_Read(): Invalid extent type "
|
||||
"found: %d\n", extent.type()));
|
||||
error = B_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
// Note the unmapped first block of the total read in
|
||||
// the block output parameter if provided
|
||||
if (isFirstBlock) {
|
||||
isFirstBlock = false;
|
||||
if (block)
|
||||
*block = extent.block();
|
||||
}
|
||||
|
||||
off_t blockOffset = pos - off_t((pos >> volume->BlockShift())
|
||||
<< volume->BlockShift());
|
||||
size_t fullBlocksLeft = bytesLeft >> volume->BlockShift();
|
||||
|
||||
if (fullBlocksLeft > 0 && blockOffset == 0) {
|
||||
TRACE(("Icb::_Read(): reading full block (or more)\n"));
|
||||
// Block aligned and at least one full block left. Read
|
||||
// in using cached_read() calls.
|
||||
off_t diskBlock;
|
||||
error = volume->MapBlock(extent, &diskBlock);
|
||||
if (!error) {
|
||||
size_t fullBlockBytesLeft =
|
||||
fullBlocksLeft << volume->BlockShift();
|
||||
size_t readLength = fullBlockBytesLeft < extent.length()
|
||||
? fullBlockBytesLeft : extent.length();
|
||||
|
||||
if (isEmpty) {
|
||||
TRACE(("Icb::_Read(): reading %ld empty bytes "
|
||||
"as zeros\n", readLength));
|
||||
memset(buffer, 0, readLength);
|
||||
} else {
|
||||
off_t diskBlock;
|
||||
error = volume->MapBlock(extent, &diskBlock);
|
||||
if (!error) {
|
||||
TRACE(("Icb::_Read(): reading %ld bytes from "
|
||||
"disk block %Ld using cached_read()\n",
|
||||
readLength, diskBlock));
|
||||
size_t length = readLength >> volume->BlockShift();
|
||||
error = file_cache_read(volume->BlockCache(),
|
||||
NULL, pos, buffer, &length);
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
bytesLeft -= readLength;
|
||||
bytesRead += readLength;
|
||||
pos += readLength;
|
||||
buffer += readLength;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
PRINT(("partial block\n"));
|
||||
off_t partialOffset;
|
||||
size_t partialLength;
|
||||
if (blockOffset == 0) {
|
||||
// Block aligned, but only a partial block's worth remaining. Read
|
||||
// in remaining bytes of file
|
||||
partialOffset = 0;
|
||||
partialLength = bytesLeft;
|
||||
} else {
|
||||
// Not block aligned, so just read up to the next block boundary.
|
||||
partialOffset = blockOffset;
|
||||
partialLength = volume->BlockSize() - blockOffset;
|
||||
if (bytesLeft < partialLength)
|
||||
partialLength = bytesLeft;
|
||||
}
|
||||
|
||||
PRINT(("partialOffset: %Ld\n", partialOffset));
|
||||
PRINT(("partialLength: %ld\n", partialLength));
|
||||
|
||||
if (isEmpty) {
|
||||
PRINT(("reading %ld empty bytes as zeros\n", partialLength));
|
||||
memset(buffer, 0, partialLength);
|
||||
} else {
|
||||
off_t diskBlock;
|
||||
error = volume->MapBlock(extent, &diskBlock);
|
||||
if (!error) {
|
||||
PRINT(("reading %ld bytes from disk block %Ld using get_block()\n",
|
||||
partialLength, diskBlock));
|
||||
uint8 *data = (uint8*)block_cache_get_etc((void*)volume->BlockCache(), diskBlock, 0, partialLength);
|
||||
error = data ? B_OK : B_BAD_DATA;
|
||||
if (!error) {
|
||||
memcpy(buffer, data+partialOffset, partialLength);
|
||||
block_cache_put(volume->BlockCache(), diskBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
bytesLeft -= partialLength;
|
||||
bytesRead += partialLength;
|
||||
pos += partialLength;
|
||||
buffer += partialLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PRINT(("error finding extent for offset %Ld: 0x%lx, `%s'", pos,
|
||||
error, strerror(error)));
|
||||
status = list.FindExtent(pos, &extent, &isEmpty);
|
||||
if (status != B_OK) {
|
||||
TRACE_ERROR(("Icb::_Read: error finding extent for offset %Ld. "
|
||||
"status = 0x%lx `%s'\n", pos, status, strerror(status)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE(("Icb::_Read(): found extent for offset %Ld: (block: %ld, "
|
||||
"partition: %d, length: %ld, type: %d)\n", pos, extent.block(),
|
||||
extent.partition(), extent.length(), extent.type()));
|
||||
|
||||
switch (extent.type()) {
|
||||
case EXTENT_TYPE_RECORDED:
|
||||
isEmpty = false;
|
||||
break;
|
||||
|
||||
case EXTENT_TYPE_ALLOCATED:
|
||||
case EXTENT_TYPE_UNALLOCATED:
|
||||
isEmpty = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE_ERROR(("Icb::_Read(): Invalid extent type found: %d\n",
|
||||
extent.type()));
|
||||
status = B_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status != B_OK)
|
||||
break;
|
||||
|
||||
// Note the unmapped first block of the total read in
|
||||
// the block output parameter if provided
|
||||
if (isFirstBlock) {
|
||||
isFirstBlock = false;
|
||||
if (block)
|
||||
*block = extent.block();
|
||||
}
|
||||
|
||||
off_t blockOffset
|
||||
= pos - off_t((pos >> volume->BlockShift()) << volume->BlockShift());
|
||||
|
||||
size_t fullBlocksLeft = bytesLeft >> volume->BlockShift();
|
||||
|
||||
if (fullBlocksLeft > 0 && blockOffset == 0) {
|
||||
TRACE(("Icb::_Read(): reading full block (or more)\n"));
|
||||
// Block aligned and at least one full block left. Read
|
||||
// in using block_cache_get_etc() calls.
|
||||
off_t diskBlock;
|
||||
status = volume->MapBlock(extent, &diskBlock);
|
||||
if (status != B_OK) {
|
||||
TRACE_ERROR(("Icb::_Read: could not map extent\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
size_t fullBlockBytesLeft = fullBlocksLeft << volume->BlockShift();
|
||||
size_t readLength = fullBlockBytesLeft < extent.length()
|
||||
? fullBlockBytesLeft : extent.length();
|
||||
|
||||
if (isEmpty) {
|
||||
TRACE(("Icb::_Read(): reading %ld empty bytes as zeros\n",
|
||||
readLength));
|
||||
memset(buffer, 0, readLength);
|
||||
} else {
|
||||
off_t diskBlock;
|
||||
status = volume->MapBlock(extent, &diskBlock);
|
||||
if (status != B_OK) {
|
||||
TRACE_ERROR(("Icb::_Read: could not map extent\n"));
|
||||
break;
|
||||
}
|
||||
TRACE(("Icb::_Read(): reading %ld bytes from disk block %Ld "
|
||||
"using block_cache_get_etc()\n", readLength, diskBlock));
|
||||
size_t length = readLength >> volume->BlockShift();
|
||||
uint8 *data = (uint8*)block_cache_get_etc(volume->BlockCache(),
|
||||
diskBlock, pos, length);
|
||||
if (data == NULL) {
|
||||
status = B_BAD_DATA;
|
||||
break;
|
||||
}
|
||||
memcpy(buffer, data, length);
|
||||
block_cache_put(volume->BlockCache(), diskBlock);
|
||||
}
|
||||
|
||||
bytesLeft -= readLength;
|
||||
bytesRead += readLength;
|
||||
pos += readLength;
|
||||
buffer += readLength;
|
||||
} else {
|
||||
off_t partialOffset;
|
||||
size_t partialLength;
|
||||
if (blockOffset == 0) {
|
||||
// Block aligned, but only a partial block's worth remaining.
|
||||
// Read in remaining bytes of file
|
||||
partialOffset = 0;
|
||||
partialLength = bytesLeft;
|
||||
} else {
|
||||
// Not block aligned, so just read up to the next block boundary.
|
||||
partialOffset = blockOffset;
|
||||
partialLength = volume->BlockSize() - blockOffset;
|
||||
if (bytesLeft < partialLength)
|
||||
partialLength = bytesLeft;
|
||||
}
|
||||
TRACE(("Icb::_Read: reading partial block. partialOffset = %Ld, "
|
||||
"partialLength: %ld\n",partialOffset, partialLength));
|
||||
|
||||
if (isEmpty) {
|
||||
TRACE(("Icb::_Read: reading %ld empty bytes as zeros\n",
|
||||
partialLength));
|
||||
memset(buffer, 0, partialLength);
|
||||
} else {
|
||||
off_t diskBlock;
|
||||
status = volume->MapBlock(extent, &diskBlock);
|
||||
if (status != B_OK) {
|
||||
TRACE_ERROR(("Icb::_Read: could not map extent\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE(("Icb::_Read: %ld bytes from disk block %Ld using "
|
||||
"block_cache_get_etc()\n", partialLength, diskBlock));
|
||||
uint8 *data = (uint8*)block_cache_get_etc(volume->BlockCache(),
|
||||
diskBlock, 0, partialLength);
|
||||
if (data == NULL)
|
||||
break;
|
||||
memcpy(buffer, data + partialOffset, partialLength);
|
||||
block_cache_put(volume->BlockCache(), diskBlock);
|
||||
}
|
||||
|
||||
bytesLeft -= partialLength;
|
||||
bytesRead += partialLength;
|
||||
pos += partialLength;
|
||||
buffer += partialLength;
|
||||
}
|
||||
}
|
||||
|
||||
*length = bytesRead;
|
||||
|
||||
RETURN(error);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,8 +40,7 @@ Volume::~Volume()
|
||||
|
||||
/*! \brief Attempts to mount the given device.
|
||||
|
||||
\param volumeStart The block on the given device whereat the volume begins.
|
||||
\param volumeLength The block length of the volume on the given device.
|
||||
\param lenght The length of the device in number of blocks
|
||||
*/
|
||||
status_t
|
||||
Volume::Mount(const char *deviceName, off_t offset, off_t length,
|
||||
@@ -282,6 +281,7 @@ Volume::Mount(const char *deviceName, off_t offset, off_t length,
|
||||
RETURN(status);
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
Volume::Name() const {
|
||||
return fName.Utf8();
|
||||
|
||||
Reference in New Issue
Block a user