* 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
@@ -14,6 +14,7 @@
#include <util/kernel_cpp.h> #include <util/kernel_cpp.h>
#include <fs_cache.h>
#include <fs_info.h> #include <fs_info.h>
#include <fs_interface.h> #include <fs_interface.h>
@@ -99,6 +100,8 @@ public:
fs_vnode * SuperVnode() { return &fSuperVnode; } fs_vnode * SuperVnode() { return &fSuperVnode; }
ino_t InodeNumber() { return fInodeNumber; } ino_t InodeNumber() { return fInodeNumber; }
void CreateCache();
void SetParentDir(OverlayInode *parentDir); void SetParentDir(OverlayInode *parentDir);
OverlayInode * ParentDir() { return fParentDir; } OverlayInode * ParentDir() { return fParentDir; }
@@ -154,6 +157,7 @@ private:
bool fHasStat; bool fHasStat;
bool fHasDirents; bool fHasDirents;
bool fIsVirtual; bool fIsVirtual;
void * fFileCache;
}; };
@@ -187,7 +191,8 @@ OverlayInode::OverlayInode(OverlayVolume *volume, fs_vnode *superVnode,
fDirentCount(0), fDirentCount(0),
fHasStat(false), fHasStat(false),
fHasDirents(false), fHasDirents(false),
fIsVirtual(superVnode == NULL) fIsVirtual(superVnode == NULL),
fFileCache(NULL)
{ {
TRACE("inode created %lld\n", fInodeNumber); TRACE("inode created %lld\n", fInodeNumber);
@@ -214,6 +219,9 @@ OverlayInode::OverlayInode(OverlayVolume *volume, fs_vnode *superVnode,
OverlayInode::~OverlayInode() OverlayInode::~OverlayInode()
{ {
TRACE("inode destroyed %lld\n", fInodeNumber); TRACE("inode destroyed %lld\n", fInodeNumber);
if (fFileCache != NULL)
file_cache_delete(fFileCache);
write_buffer *element = fWriteBuffers; write_buffer *element = fWriteBuffers;
while (element) { while (element) {
write_buffer *next = element->next; 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 void
OverlayInode::SetParentDir(OverlayInode *parentDir) OverlayInode::SetParentDir(OverlayInode *parentDir)
{ {
@@ -437,10 +456,19 @@ OverlayInode::Read(void *_cookie, off_t position, void *buffer, size_t *length)
} }
if (position < fOriginalNodeLength) { 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); 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) if (result != B_OK)
return result; return result;
@@ -547,6 +575,9 @@ OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
if (newEnd > fStat.st_size) { if (newEnd > fStat.st_size) {
fStat.st_size = newEnd; fStat.st_size = newEnd;
sizeChanged = true; sizeChanged = true;
if (fFileCache)
file_cache_set_size(fFileCache, newEnd);
} }
// populate the buffer with the existing chunks // populate the buffer with the existing chunks
@@ -899,6 +930,8 @@ OverlayInode::_CreateCommon(const char *name, int type, int perms,
return result; return result;
} }
node->CreateCache();
if (newInodeNumber != NULL) if (newInodeNumber != NULL)
*newInodeNumber = entry->inode_number; *newInodeNumber = entry->inode_number;
if (_node != NULL) if (_node != NULL)
@@ -1030,7 +1063,32 @@ static status_t
overlay_read_pages(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, overlay_read_pages(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
const iovec *vecs, size_t count, size_t *numBytes) 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, overlay_write_pages(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
const iovec *vecs, size_t count, size_t *numBytes) 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;
} }