* 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:
Salvatore Benedetto
2008-08-22 19:19:35 +00:00
parent 2e39d2c54f
commit 9fd15595d6
2 changed files with 139 additions and 132 deletions
+137 -130
View File
@@ -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();