When we truncate or resize the file we need to trim the write_buffers. Otherwise
we waste space, but we also incorrectly fail to update the size for all writes that do not go beyond the previous file size. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32825 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -154,6 +154,8 @@ public:
|
|||||||
overlay_dirent **entry);
|
overlay_dirent **entry);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _TrimBuffers();
|
||||||
|
|
||||||
status_t _PopulateDirents();
|
status_t _PopulateDirents();
|
||||||
status_t _CreateCommon(const char *name, int type, int perms,
|
status_t _CreateCommon(const char *name, int type, int perms,
|
||||||
ino_t *newInodeNumber, OverlayInode **node);
|
ino_t *newInodeNumber, OverlayInode **node);
|
||||||
@@ -388,8 +390,10 @@ OverlayInode::WriteStat(const struct stat *stat, uint32 statMask)
|
|||||||
if (!fHasStat)
|
if (!fHasStat)
|
||||||
ReadStat(NULL);
|
ReadStat(NULL);
|
||||||
|
|
||||||
if (statMask & B_STAT_SIZE)
|
if (statMask & B_STAT_SIZE) {
|
||||||
fStat.st_size = stat->st_size;
|
fStat.st_size = stat->st_size;
|
||||||
|
_TrimBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
if (statMask & B_STAT_MODE)
|
if (statMask & B_STAT_MODE)
|
||||||
fStat.st_mode = (fStat.st_mode & ~S_IUMSK) | (stat->st_mode & S_IUMSK);
|
fStat.st_mode = (fStat.st_mode & ~S_IUMSK) | (stat->st_mode & S_IUMSK);
|
||||||
@@ -445,8 +449,10 @@ OverlayInode::Open(int openMode, void **_cookie)
|
|||||||
*_cookie = cookie;
|
*_cookie = cookie;
|
||||||
|
|
||||||
if (fIsVirtual) {
|
if (fIsVirtual) {
|
||||||
if (openMode & O_TRUNC)
|
if (openMode & O_TRUNC) {
|
||||||
fStat.st_size = 0;
|
fStat.st_size = 0;
|
||||||
|
_TrimBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -466,6 +472,7 @@ OverlayInode::Open(int openMode, void **_cookie)
|
|||||||
|
|
||||||
if (openMode & O_TRUNC) {
|
if (openMode & O_TRUNC) {
|
||||||
fStat.st_size = 0;
|
fStat.st_size = 0;
|
||||||
|
_TrimBuffers();
|
||||||
if (!fIsModified)
|
if (!fIsModified)
|
||||||
SetModified();
|
SetModified();
|
||||||
}
|
}
|
||||||
@@ -889,6 +896,57 @@ OverlayInode::RemoveEntry(const char *name, overlay_dirent **_entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
OverlayInode::_TrimBuffers()
|
||||||
|
{
|
||||||
|
// the file size has been changed and we want to trim
|
||||||
|
// off everything that goes beyond the new size
|
||||||
|
write_buffer **link = &fWriteBuffers;
|
||||||
|
write_buffer *buffer = fWriteBuffers;
|
||||||
|
|
||||||
|
while (buffer != NULL) {
|
||||||
|
off_t bufferEnd = buffer->position + buffer->length;
|
||||||
|
if (bufferEnd > fStat.st_size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
link = &buffer->next;
|
||||||
|
buffer = buffer->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
// didn't find anything crossing or past the end
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->position < fStat.st_size) {
|
||||||
|
// got a crossing buffer to resize
|
||||||
|
size_t newLength = fStat.st_size - buffer->position;
|
||||||
|
write_buffer *newBuffer = (write_buffer *)realloc(buffer,
|
||||||
|
sizeof(write_buffer) - 1 + newLength);
|
||||||
|
|
||||||
|
if (newBuffer != NULL) {
|
||||||
|
buffer = newBuffer;
|
||||||
|
*link = newBuffer;
|
||||||
|
} else {
|
||||||
|
// we don't really care if it worked, if it didn't we simply
|
||||||
|
// keep the old buffer and reset it's size
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->length = newLength;
|
||||||
|
link = &buffer->next;
|
||||||
|
buffer = buffer->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// everything else we can throw away
|
||||||
|
*link = NULL;
|
||||||
|
while (buffer != NULL) {
|
||||||
|
write_buffer *next = buffer->next;
|
||||||
|
free(buffer);
|
||||||
|
buffer = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
OverlayInode::_PopulateDirents()
|
OverlayInode::_PopulateDirents()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user