* Directories now only preallocate 4 KB.
* Reworked how preallocations are chosen, and also take the grow rate into account. * Also, the preallocation is now rounded to the next multiple of the preallocation size (previously, a 64K write would only allocate 64K). * This should also close bug #2573. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31253 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1585,6 +1585,10 @@ Inode::_AllocateBlockArray(Transaction& transaction, block_run& run)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Grows the stream to \a size, and fills the direct/indirect/double indirect
|
||||||
|
ranges with the runs.
|
||||||
|
This method will also determine the size of the preallocation, if any.
|
||||||
|
*/
|
||||||
status_t
|
status_t
|
||||||
Inode::_GrowStream(Transaction& transaction, off_t size)
|
Inode::_GrowStream(Transaction& transaction, off_t size)
|
||||||
{
|
{
|
||||||
@@ -1615,12 +1619,12 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
|||||||
bytes = size - data->Size();
|
bytes = size - data->Size();
|
||||||
|
|
||||||
// do we have enough free blocks on the disk?
|
// do we have enough free blocks on the disk?
|
||||||
off_t blocksRequested = (bytes + fVolume->BlockSize() - 1)
|
off_t blocksNeeded = (bytes + fVolume->BlockSize() - 1)
|
||||||
>> fVolume->BlockShift();
|
>> fVolume->BlockShift();
|
||||||
if (blocksRequested > fVolume->FreeBlocks())
|
if (blocksNeeded > fVolume->FreeBlocks())
|
||||||
return B_DEVICE_FULL;
|
return B_DEVICE_FULL;
|
||||||
|
|
||||||
off_t blocksNeeded = blocksRequested;
|
off_t blocksRequested = blocksNeeded;
|
||||||
// because of preallocations and partial allocations, the number of
|
// because of preallocations and partial allocations, the number of
|
||||||
// blocks we need to allocate may be different from the one we request
|
// blocks we need to allocate may be different from the one we request
|
||||||
// from the block allocator
|
// from the block allocator
|
||||||
@@ -1629,27 +1633,33 @@ Inode::_GrowStream(Transaction& transaction, off_t size)
|
|||||||
// Attributes, attribute directories, and long symlinks usually won't get
|
// Attributes, attribute directories, and long symlinks usually won't get
|
||||||
// that big, and should stay close to the inode - preallocating could be
|
// that big, and should stay close to the inode - preallocating could be
|
||||||
// counterproductive.
|
// counterproductive.
|
||||||
// Also, if free disk space is tight, we probably don't want to do this as
|
// Also, if free disk space is tight, don't preallocate.
|
||||||
// well.
|
|
||||||
if (!IsAttribute() && !IsAttributeDirectory() && !IsSymLink()
|
if (!IsAttribute() && !IsAttributeDirectory() && !IsSymLink()
|
||||||
&& blocksRequested < (65536 >> fVolume->BlockShift())
|
|
||||||
&& fVolume->FreeBlocks() > 128) {
|
&& fVolume->FreeBlocks() > 128) {
|
||||||
// preallocate 64 KB at minimum
|
off_t roundTo = 0;
|
||||||
if (IsFile()) {
|
if (IsFile()) {
|
||||||
// request preallocated blocks depending on the file size
|
// Request preallocated blocks depending on the file size and growth
|
||||||
if (size < 1 * 1024 * 1024) {
|
if (size < 1 * 1024 * 1024 && bytes < 512 * 1024) {
|
||||||
// preallocate 64 KB for file sizes < 1 MB
|
// Preallocate 64 KB for file sizes <1 MB and grow rates <512 KB
|
||||||
blocksRequested = 65536 >> fVolume->BlockShift();
|
roundTo = 65536 >> fVolume->BlockShift();
|
||||||
} else if (size < 32 * 1024 * 1024) {
|
} else if (size < 32 * 1024 * 1024 && bytes <= 1 * 1024 * 1024) {
|
||||||
// preallocate 512 KB for file sizes between 1 MB and 32 MB
|
// Preallocate 512 KB for file sizes between 1 MB and 32 MB, and
|
||||||
blocksRequested = (512 * 1024) >> fVolume->BlockShift();
|
// grow rates smaller than 1 MB
|
||||||
|
roundTo = (512 * 1024) >> fVolume->BlockShift();
|
||||||
} else {
|
} else {
|
||||||
// preallocate 1/16 of the file size (ie. 4 MB for 64 MB,
|
// Preallocate 1/16 of the file size (ie. 4 MB for 64 MB,
|
||||||
// 64 MB for 1 GB)
|
// 64 MB for 1 GB)
|
||||||
blocksRequested = size >> (fVolume->BlockShift() + 4);
|
roundTo = size >> (fVolume->BlockShift() + 4);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
blocksRequested = 65536 >> fVolume->BlockShift();
|
// Preallocate only 4 KB - directories only get trimmed when their
|
||||||
|
// vnode is flushed, which might not happen very often.
|
||||||
|
roundTo = 4096 >> fVolume->BlockShift();
|
||||||
|
}
|
||||||
|
if (roundTo > 1) {
|
||||||
|
// Round to next "roundTo" block count
|
||||||
|
blocksRequested = ((blocksNeeded + roundTo) / roundTo) * roundTo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (blocksNeeded > 0) {
|
while (blocksNeeded > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user