* Implement read/write_pages using Read()/Write(), io will follow later.

* Create a file cache for created overlay nodes. It is unused and disabled, but
  causes a vnode cache to be created. This is required for mapping a file, which
  in turn is required for executables to be loaded. With that copied or newly
  created executables should work on top of write_overlay. Will think about and
  implement a more direct way of getting that cache later today.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30910 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2009-05-29 02:52:11 +00:00
parent 7515c32c1f
commit 57a5e69604
1 changed files with 89 additions and 6 deletions

View File

@ -14,6 +14,7 @@
#include <util/kernel_cpp.h>
#include <fs_cache.h>
#include <fs_info.h>
#include <fs_interface.h>
@ -99,6 +100,8 @@ public:
fs_vnode * SuperVnode() { return &fSuperVnode; }
ino_t InodeNumber() { return fInodeNumber; }
void CreateCache();
void SetParentDir(OverlayInode *parentDir);
OverlayInode * ParentDir() { return fParentDir; }
@ -154,6 +157,7 @@ private:
bool fHasStat;
bool fHasDirents;
bool fIsVirtual;
void * fFileCache;
};
@ -187,7 +191,8 @@ OverlayInode::OverlayInode(OverlayVolume *volume, fs_vnode *superVnode,
fDirentCount(0),
fHasStat(false),
fHasDirents(false),
fIsVirtual(superVnode == NULL)
fIsVirtual(superVnode == NULL),
fFileCache(NULL)
{
TRACE("inode created %lld\n", fInodeNumber);
@ -214,6 +219,9 @@ OverlayInode::OverlayInode(OverlayVolume *volume, fs_vnode *superVnode,
OverlayInode::~OverlayInode()
{
TRACE("inode destroyed %lld\n", fInodeNumber);
if (fFileCache != NULL)
file_cache_delete(fFileCache);
write_buffer *element = fWriteBuffers;
while (element) {
write_buffer *next = element->next;
@ -234,6 +242,17 @@ OverlayInode::InitCheck()
}
void
OverlayInode::CreateCache()
{
if (!S_ISDIR(fStat.st_mode) && !S_ISLNK(fStat.st_mode)) {
fFileCache = file_cache_create(fStat.st_dev, fStat.st_ino, 0);
if (fFileCache != NULL)
file_cache_disable(fFileCache);
}
}
void
OverlayInode::SetParentDir(OverlayInode *parentDir)
{
@ -437,10 +456,19 @@ OverlayInode::Read(void *_cookie, off_t position, void *buffer, size_t *length)
}
if (position < fOriginalNodeLength) {
open_cookie *cookie = (open_cookie *)_cookie;
void *superCookie = NULL;
if (_cookie != NULL)
superCookie = ((open_cookie *)_cookie)->super_cookie;
size_t readLength = MIN(fOriginalNodeLength - position, *length);
status_t result = fSuperVnode.ops->read(SuperVolume(), &fSuperVnode,
cookie->super_cookie, position, buffer, &readLength);
iovec vector;
vector.iov_base = buffer;
vector.iov_len = readLength;
status_t result = fSuperVnode.ops->read_pages(SuperVolume(),
&fSuperVnode, superCookie, position, &vector, 1, &readLength);
if (result != B_OK)
return result;
@ -547,6 +575,9 @@ OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
if (newEnd > fStat.st_size) {
fStat.st_size = newEnd;
sizeChanged = true;
if (fFileCache)
file_cache_set_size(fFileCache, newEnd);
}
// populate the buffer with the existing chunks
@ -899,6 +930,8 @@ OverlayInode::_CreateCommon(const char *name, int type, int perms,
return result;
}
node->CreateCache();
if (newInodeNumber != NULL)
*newInodeNumber = entry->inode_number;
if (_node != NULL)
@ -1030,7 +1063,32 @@ static status_t
overlay_read_pages(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
const iovec *vecs, size_t count, size_t *numBytes)
{
OVERLAY_CALL(read_pages, cookie, pos, vecs, count, numBytes)
OverlayInode *node = (OverlayInode *)vnode->private_node;
size_t bytesLeft = *numBytes;
for (size_t i = 0; i < count; i++) {
size_t transferBytes = MIN(vecs[i].iov_len, bytesLeft);
status_t result = node->Read(cookie, pos, vecs[i].iov_base,
&transferBytes);
if (result != B_OK) {
*numBytes -= bytesLeft;
return result;
}
bytesLeft -= transferBytes;
if (bytesLeft == 0)
return B_OK;
if (transferBytes < vecs[i].iov_len) {
*numBytes -= bytesLeft;
return B_OK;
}
pos += transferBytes;
}
*numBytes = 0;
return B_OK;
}
@ -1038,7 +1096,32 @@ static status_t
overlay_write_pages(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
const iovec *vecs, size_t count, size_t *numBytes)
{
OVERLAY_CALL(write_pages, cookie, pos, vecs, count, numBytes)
OverlayInode *node = (OverlayInode *)vnode->private_node;
size_t bytesLeft = *numBytes;
for (size_t i = 0; i < count; i++) {
size_t transferBytes = MIN(vecs[i].iov_len, bytesLeft);
status_t result = node->Write(cookie, pos, vecs[i].iov_base,
&transferBytes);
if (result != B_OK) {
*numBytes -= bytesLeft;
return result;
}
bytesLeft -= transferBytes;
if (bytesLeft == 0)
return B_OK;
if (transferBytes < vecs[i].iov_len) {
*numBytes -= bytesLeft;
return B_OK;
}
pos += transferBytes;
}
*numBytes = 0;
return B_OK;
}