From 57a5e69604a2a38e1b99989662c864120e363ca9 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 29 May 2009 02:52:11 +0000 Subject: [PATCH] * 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 --- .../layers/write_overlay/write_overlay.cpp | 95 +++++++++++++++++-- 1 file changed, 89 insertions(+), 6 deletions(-) diff --git a/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp b/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp index 64e26ea2f3..e11247764b 100644 --- a/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp +++ b/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp @@ -14,6 +14,7 @@ #include +#include #include #include @@ -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; }