* 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
|
status_t
|
||||||
Icb::_Read(DescriptorList &list, off_t pos, void *_buffer, size_t *length, uint32 *block)
|
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",
|
TRACE(("Icb::_Read(): list = %p, pos = %Ld, buffer = %p, length = %ld\n",
|
||||||
&list, pos, _buffer, length, (length ? *length : 0)));
|
&list, pos, _buffer, (length ? *length : 0)));
|
||||||
|
|
||||||
uint64 bytesLeftInFile = uint64(pos) > Length() ? 0 : Length() - pos;
|
uint64 bytesLeftInFile = uint64(pos) > Length() ? 0 : Length() - pos;
|
||||||
size_t bytesLeft = (*length >= bytesLeftInFile) ? bytesLeftInFile : *length;
|
size_t bytesLeft = (*length >= bytesLeftInFile) ? bytesLeftInFile : *length;
|
||||||
size_t bytesRead = 0;
|
size_t bytesRead = 0;
|
||||||
|
|
||||||
Volume *volume = GetVolume();
|
Volume *volume = GetVolume();
|
||||||
status_t error = B_OK;
|
status_t status = B_OK;
|
||||||
uint8 *buffer = (uint8 *)_buffer;
|
uint8 *buffer = (uint8 *)_buffer;
|
||||||
bool isFirstBlock = true;
|
bool isFirstBlock = true;
|
||||||
|
|
||||||
while (bytesLeft > 0 && !error) {
|
while (bytesLeft > 0) {
|
||||||
|
|
||||||
TRACE(("Icb::_Read(): pos: %Ld\n, bytesLeft: %ld\n", pos, bytesLeft));
|
|
||||||
|
|
||||||
|
TRACE(("Icb::_Read(): pos: %Ld, bytesLeft: %ld\n", pos, bytesLeft));
|
||||||
long_address extent;
|
long_address extent;
|
||||||
bool isEmpty = false;
|
bool isEmpty = false;
|
||||||
error = list.FindExtent(pos, &extent, &isEmpty);
|
status = list.FindExtent(pos, &extent, &isEmpty);
|
||||||
if (!error) {
|
if (status != B_OK) {
|
||||||
TRACE(("Icb::_Read(): found extent for offset %Ld: (block: %ld, "
|
TRACE_ERROR(("Icb::_Read: error finding extent for offset %Ld. "
|
||||||
"partition: %d, length: %ld, type: %d)\n", pos, extent.block(),
|
"status = 0x%lx `%s'\n", pos, status, strerror(status)));
|
||||||
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)));
|
|
||||||
break;
|
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;
|
*length = bytesRead;
|
||||||
|
|
||||||
RETURN(error);
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ Volume::~Volume()
|
|||||||
|
|
||||||
/*! \brief Attempts to mount the given device.
|
/*! \brief Attempts to mount the given device.
|
||||||
|
|
||||||
\param volumeStart The block on the given device whereat the volume begins.
|
\param lenght The length of the device in number of blocks
|
||||||
\param volumeLength The block length of the volume on the given device.
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
Volume::Mount(const char *deviceName, off_t offset, off_t length,
|
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);
|
RETURN(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
Volume::Name() const {
|
Volume::Name() const {
|
||||||
return fName.Utf8();
|
return fName.Utf8();
|
||||||
|
|||||||
Reference in New Issue
Block a user