[freenos] [freenos commit] r216 - Added initial implementation of the LinnFS filesystem server.

  • From: codesite-noreply@xxxxxxxxxx
  • To: freenos@xxxxxxxxxxxxx
  • Date: Wed, 08 Jul 2009 22:53:56 +0000

Author: nieklinnenbank
Date: Wed Jul  8 15:47:03 2009
New Revision: 216

Added:
   trunk/srv/filesystem/linn/LinnDirectory.cpp
   trunk/srv/filesystem/linn/LinnDirectory.h
   trunk/srv/filesystem/linn/LinnFile.cpp
   trunk/srv/filesystem/linn/LinnFile.h
   trunk/srv/filesystem/linn/LinnFileSystem.cpp
   trunk/srv/filesystem/linn/LinnFileSystem.h
Modified:
   trunk/srv/filesystem/linn/LinnCreate.cpp
   trunk/srv/filesystem/linn/LinnDirectoryEntry.h
   trunk/srv/filesystem/linn/SConscript

Log:
Added initial implementation of the LinnFS filesystem server.


Modified: trunk/srv/filesystem/linn/LinnCreate.cpp
==============================================================================
--- trunk/srv/filesystem/linn/LinnCreate.cpp    (original)
+++ trunk/srv/filesystem/linn/LinnCreate.cpp    Wed Jul  8 15:47:03 2009
@@ -287,9 +287,8 @@
        /* Fill it. */
        entry->inode = entryInode;
        entry->type  = type;
-       memcpy(entry->name, name,
-              strlen(name) < LINN_DIRENT_NAME_LEN ?
-              strlen(name) : LINN_DIRENT_NAME_LEN);
+       strncpy(entry->name, name, LINN_DIRENT_NAME_LEN);
+       entry->name[LINN_DIRENT_NAME_LEN - 1] = ZERO;
     }
     /* Indirect block. */
     else

Added: trunk/srv/filesystem/linn/LinnDirectory.cpp
==============================================================================
--- (empty file)
+++ trunk/srv/filesystem/linn/LinnDirectory.cpp Wed Jul  8 15:47:03 2009
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009 Niek Linnenbank
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <API/VMCopy.h>
+#include "LinnDirectory.h"
+
+LinnDirectory::LinnDirectory(LinnFileSystem *f,
+                            LinnInode *i)
+    : fs(f), inode(i)
+{
+    size = inode->size;
+}
+
+Error LinnDirectory::read(FileSystemMessage *msg)
+{
+    LinnSuperBlock *sb = fs->getSuperBlock();
+    LinnDirectoryEntry dent;
+    LinnInode *dInode;
+    Size bytes = ZERO;
+    Dirent tmp, *buf = (Dirent *) msg->buffer;
+    Error e;
+
+    /* Loop all direct blocks. */
+    for (u64 blk = 0; blk < LINN_INODE_DIR_BLOCKS; blk++)
+    {
+       /* Read directory entries. */
+       for (u64 ent = 0; ent < LINN_DIRENT_PER_BLOCK(sb); ent++)
+       {
+           /* Calculate offset to read. */
+           u64 offset = (inode->block[blk] * sb->blockSize) +
+                        (ent * sizeof(LinnDirectoryEntry));
+
+           /* Get the next entry. */
+           if (fs->getStorage()->read(offset, (u8 *) &dent,
+                                      sizeof(LinnDirectoryEntry)) < 0)
+           {
+               return EACCES;
+           }
+           /* Can we read another entry? */
+            if (bytes + sizeof(Dirent) <= msg->size)
+            {
+               /* Fill in the Dirent. */
+               if (!(dInode = fs->getInode(dent.inode)))
+               {
+                   return EINVAL;
+               }
+               strlcpy(tmp.name, dent.name, LINN_DIRENT_NAME_LEN);
+               tmp.type = (FileType) dInode->type;
+
+               /* Copy to the remote process. */               
+                if ((e = VMCopy(msg->procID, Write, (Address) &tmp,
+                               (Address) (buf++), sizeof(Dirent))) < 0)
+                {
+                    return e;
+                }
+                bytes += e;
+            }
+           /* No more buffer space left. */
+            else return EFAULT;
+       }
+    }
+    /* All done. */
+    msg->size = bytes;
+    return ESUCCESS;
+}
+
+Error LinnDirectory::getEntry(LinnDirectoryEntry *dent, char *name)
+{
+    LinnSuperBlock *sb = fs->getSuperBlock();
+    u64 offset;
+
+    /* Loop all blocks. */
+    for (u64 blk = 0; blk < LINN_INODE_NUM_BLOCKS(sb, inode); blk++)
+    {
+       /* Read directory entries. */
+       for (u64 ent = 0; ent < LINN_DIRENT_PER_BLOCK(sb); ent++)
+       {
+           /* Calculate offset to read. */
+           offset = (inode->block[blk] * sb->blockSize) +
+                    (sizeof(LinnDirectoryEntry) * ent);
+
+           /* Get the next entry. */
+           if (fs->getStorage()->read(offset, (u8 *) dent,
+                                      sizeof(LinnDirectoryEntry)) < 0)
+           {
+               return EACCES;
+           }
+           /* Is it the entry we are looking for? */
+           if (strcmp(name, dent->name) == 0)
+           {
+               return ESUCCESS;
+           }
+       }
+    }
+    /* Not found. */
+    return ENOENT;
+}

Added: trunk/srv/filesystem/linn/LinnDirectory.h
==============================================================================
--- (empty file)
+++ trunk/srv/filesystem/linn/LinnDirectory.h   Wed Jul  8 15:47:03 2009
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 Niek Linnenbank
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FILESYSTEM_LINN_DIRECTORY_H
+#define __FILESYSTEM_LINN_DIRECTORY_H
+#ifndef __HOST__
+
+#include <FileSystemMessage.h>
+#include <Directory.h>
+#include <Types.h>
+#include <Error.h>
+#include "LinnDirectoryEntry.h"
+#include "LinnFileSystem.h"
+#include "LinnInode.h"
+
+/**
+ * @defgroup linn Linnenbank Filesystem (LinnFS)
+ * @{
+ */
+
+/**
+ * Represents an directory on a LinnFS filesystem.
+ * @see Directory
+ * @see LinnDirectoryEntry
+ * @see LinnFileSystem
+ */
+class LinnDirectory : public Directory
+{
+    public:
+
+       /**
+        * Constructor function.
+        * @param fs Filesystem pointer.
+        * @param inode Inode pointer.
+        * @see LinnFileSystem
+        * @see LinnInode
+        */
+       LinnDirectory(LinnFileSystem *fs, LinnInode *inode);
+
+        /**
+         * Read directory entries.
+         * @param msg Read request.
+         * @return Number of bytes read on success, Error on failure.
+         */
+       Error read(FileSystemMessage *msg);
+
+       /**
+        * Retrieve a directory entry.
+        * @param dent LinnDirectoryEntry buffer pointer.
+        * @param name Unique name of the entry.
+        * @return ESUCCESS if found, or an error code otherwise.
+        */
+       Error getEntry(LinnDirectoryEntry *dent, char *name);
+
+    private:
+
+       /** Filesystem pointer. */
+       LinnFileSystem *fs;
+
+       /** Inode which describes the directory. */
+       LinnInode *inode;
+};
+
+/**
+ * @}
+ */
+
+#endif /* __HOST__ */
+#endif /* __FILESYSTEM_EXT2DIRECTORY_H */

Modified: trunk/srv/filesystem/linn/LinnDirectoryEntry.h
==============================================================================
--- trunk/srv/filesystem/linn/LinnDirectoryEntry.h      (original)
+++ trunk/srv/filesystem/linn/LinnDirectoryEntry.h      Wed Jul  8 15:47:03 2009
@@ -20,6 +20,18 @@

 #include <Types.h>

+/**
+ * @defgroup linn Linnenbank Filesystem (LinnFS)
+ * @{
+ */
+
+/**
+ * Calculates the number of LinnDirectoryEntry's fitting in one block.
+ * @return Number of entries.
+ */
+#define LINN_DIRENT_PER_BLOCK(sb) \
+    ((sb)->blockSize / sizeof(LinnDirectoryEntry))
+
 /** Length of the name field in an directory entry. */
 #define LINN_DIRENT_NAME_LEN 55

@@ -34,7 +46,7 @@
     /** Type of file, as an FileType. */
     u8 type;

-    /** File name. */
+    /** File name. Null terminated. */
     char name[LINN_DIRENT_NAME_LEN];
 }
 LinnDirectoryEntry;

Added: trunk/srv/filesystem/linn/LinnFile.cpp
==============================================================================
--- (empty file)
+++ trunk/srv/filesystem/linn/LinnFile.cpp      Wed Jul  8 15:47:03 2009
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009 Niek Linnenbank
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <API/VMCopy.h>
+#include "LinnFile.h"
+#include <string.h>
+
+LinnFile::LinnFile(LinnFileSystem *f, LinnInode *i)
+    : fs(f), inode(i)
+{
+    size = inode->size;
+}
+
+LinnFile::~LinnFile()
+{
+}
+
+Error LinnFile::read(FileSystemMessage *msg)
+{
+    LinnSuperBlock *sb;
+    u8 *block, *buffer;
+    Size bytes = 0, total = 0, blockNr = 0;
+    u64 storageOffset, copyOffset = msg->offset;
+    Error e = ESUCCESS;
+
+    /* Initialize variables. */
+    sb     = fs->getSuperBlock();
+    block  = new u8[sb->blockSize];
+    buffer = (u8 *) msg->buffer;
+
+    /* Skip ahead blocks. */
+    while ((sb->blockSize * (blockNr + 1)) <= copyOffset)
+    {
+       blockNr++;
+    }
+    /* Adjust the copy offset within this block. */
+    copyOffset -= sb->blockSize * blockNr;
+
+    /* Loop all blocks. */
+    while (blockNr < LINN_INODE_NUM_BLOCKS(sb, inode) - 1 &&
+          total   < msg->size &&
+          inode->size - (msg->offset + total))
+    {
+       /* Calculate the offset in storage for this block. */
+       storageOffset = fs->getOffset(inode, blockNr);
+
+        /* Fetch the next block. */
+ if (fs->getStorage()->read(storageOffset, block, sb->blockSize) < 0)
+       {
+           e = EACCES;
+           break;
+       }
+       /* Calculate the number of bytes to copy. */
+       bytes = sb->blockSize - copyOffset;
+       
+       /* Respect the inode size. */
+       if (bytes > inode->size - (msg->offset + total))
+       {
+           bytes = inode->size - (msg->offset + total);
+       }
+       /* Respect the remote process buffer. */
+       if (bytes > msg->size - total)
+       {
+           bytes = msg->size - total;
+       }
+        /* Copy to the remote process. */
+        if ((e = VMCopy(msg->procID, Write,
+                      ((Address) (block)) + copyOffset,
+                        (Address) (buffer), bytes)) < 0)
+        {
+           break;
+       }
+       /* Update state. */
+       buffer     += bytes;
+       total      += bytes;
+       copyOffset  = 0;
+       e           = ESUCCESS;
+       blockNr++;
+    }
+    /* Success. */
+    msg->size = total;
+    delete block;
+    return e;
+}
+
+Error LinnFile::write(FileSystemMessage *msg)
+{
+    return ENOTSUP;
+}

Added: trunk/srv/filesystem/linn/LinnFile.h
==============================================================================
--- (empty file)
+++ trunk/srv/filesystem/linn/LinnFile.h        Wed Jul  8 15:47:03 2009
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009 Niek Linnenbank
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FILESYSTEM_LINN_FILE_H
+#define __FILESYSTEM_LINN_FILE_H
+#ifndef __HOST__
+
+#include <File.h>
+#include <FileSystemMessage.h>
+#include <Types.h>
+#include <Error.h>
+#include "LinnFileSystem.h"
+#include "LinnInode.h"
+
+/**
+ * @defgroup linn Linnenbank Filesystem (LinnFS)
+ * @{
+ */
+
+/**
+ * Represents a file on a mounted LinnFS filesystem.
+ */
+class LinnFile : public File
+{
+    public:
+
+       /**
+        * Constructor function.
+        * @param fs LinnFS filesystem pointer.
+        * @param inode Inode pointer.
+        */
+       LinnFile(LinnFileSystem *fs, LinnInode *inode);
+
+       /**
+        * Destructor function.
+        */
+       ~LinnFile();
+
+       /**
+        * Read out the file.
+        * @param msg Read request.
+        * @return Number of bytes read, or Error number.
+        */
+       Error read(FileSystemMessage *msg);
+
+        /**
+         * Write bytes to the file.
+        * @param msg Write request.
+         * @return Number of bytes written on success, Error on failure.
+         */
+       Error write(FileSystemMessage *msg);
+
+    private:
+
+       /** Filesystem pointer. */
+       LinnFileSystem *fs;
+       
+       /** Inode pointer. */
+       LinnInode *inode;
+};
+
+/**
+ * @}
+ */
+
+#endif /* __HOST__ */
+#endif /* __FILESYSTEM_LINN_FILE_H */

Added: trunk/srv/filesystem/linn/LinnFileSystem.cpp
==============================================================================
--- (empty file)
+++ trunk/srv/filesystem/linn/LinnFileSystem.cpp        Wed Jul  8 15:47:03 2009
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2009 Niek Linnenbank
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Types.h>
+#include <BootModule.h>
+#include <Storage.h>
+#include <LogMessage.h>
+#include "LinnFileSystem.h"
+#include "LinnInode.h"
+#include "LinnFile.h"
+#include "LinnDirectory.h"
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+    BootModule module("/boot/boot.linn");
+
+    if (module.load())
+    {
+        LinnFileSystem server("/mnt", &module);
+        return server.run();
+    }
+    return EXIT_FAILURE;
+}
+
+LinnFileSystem::LinnFileSystem(const char *p, Storage *s)
+    : FileSystem(p), storage(s), groups(ZERO)
+{
+    FileSystemPath slash("/");
+    LinnInode *rootInode;
+    LinnGroup *group;
+    Size offset;
+    Error e;
+
+    /* Read out the superblock. */
+    if ((e = s->read(LINN_SUPER_OFFSET, (u8 *) &super,
+                    sizeof(super))) <= 0)
+    {
+       log("LinnFS: reading superblock failed: %s",
+            strerror(e));
+       exit(EXIT_FAILURE);
+    }
+    /* Verify magic. */
+    if (super.magic0 != LINN_SUPER_MAGIC0 ||
+        super.magic1 != LINN_SUPER_MAGIC1)
+    {
+       log("LinnFS: magic mismatch");
+       exit(EXIT_FAILURE);
+    }
+    /* Create groups vector. */
+    Size cnt = LINN_GROUP_COUNT(&super);
+    groups   = new Array<LinnGroup>(cnt);
+
+    /* Read out group descriptors. */
+    for (le64 i = 0; i < LINN_GROUP_COUNT(&super); i++)
+    {
+       /* Allocate buffer. */
+       group  = new LinnGroup;
+       offset = (super.groupsTable * super.blockSize) +
+                (sizeof(LinnGroup)  * i);
+
+       /* Read from storage. */
+       if ((e = s->read(offset, (u8 *) group, sizeof(LinnGroup))) <= 0)
+       {
+           log("LinnFS: reading group descriptor failed: %s",
+                strerror(e));
+           exit(EXIT_FAILURE);
+       }
+       /* Insert in the groups vector. */
+       groups->insert(i, group);
+    }
+    log("LinnFS: %d group descriptors",
+        LINN_GROUP_COUNT(&super));
+
+    /* Debug out superblock information. */
+    log("LinnFS: %d inodes, %d blocks",
+        super.inodesCount - super.freeInodesCount,
+        super.blocksCount - super.freeBlocksCount);
+
+    /* Read out the root directory. */
+    rootInode = getInode(LINN_INODE_ROOT);
+    root = new FileCache(&slash, new LinnDirectory(this, rootInode), ZERO);
+
+    /* Done. */
+    log("LinnFS: mounted '%s'", p);
+}
+
+Error LinnFileSystem::createFile(FileSystemMessage *msg,
+                                FileSystemPath *path)
+{
+    return ENOTSUP;
+}
+
+LinnInode * LinnFileSystem::getInode(u64 inodeNum)
+{
+    LinnGroup *group;
+    LinnInode *inode;
+    Size offset;
+    Error e;
+    Integer<u64> inodeInt = inodeNum;
+
+    /* Validate the inode number. */
+    if (inodeNum >= super.inodesCount)
+    {
+       return ZERO;
+    }
+    /* Do we have this Inode cached already? */
+    if ((inode = inodes[&inodeInt]))
+    {
+       return inode;
+    }
+    /* Get the group descriptor. */
+    if (!(group = getGroupByInode(inodeNum)))
+    {
+       return ZERO;
+    }
+    /* Allocate inode buffer. */
+    inode  = new LinnInode;
+    offset = (group->inodeTable * super.blockSize) +
+            (inodeNum % super.inodesPerGroup);
+       
+    /* Read inode from storage. */
+    if ((e = storage->read(offset, (u8 *) inode, sizeof(LinnInode))) <= 0)
+    {
+        log("LinnFS: reading inode failed: %s",
+            strerror(e));
+       return ZERO;
+    }
+    /* Insert into the cache. */
+    inodes.insert(new Integer<u64>(inodeNum), inode);
+    return inode;
+}
+
+LinnGroup * LinnFileSystem::getGroup(u64 groupNum)
+{
+    return (*groups)[groupNum];
+}
+
+LinnGroup * LinnFileSystem::getGroupByInode(u64 inodeNum)
+{
+    return getGroup((inodeNum - 1) / super.inodesPerGroup);
+}
+
+u64 LinnFileSystem::getOffset(LinnInode *inode, u64 blk)
+{
+    u64 numPerBlock = LINN_SUPER_NUM_PTRS(&super), offset;
+    u64 *block = ZERO;
+    Size depth = ZERO;
+
+    /* Direct blocks. */
+    if (blk < LINN_INODE_DIR_BLOCKS)
+    {
+       return inode->block[blk] * super.blockSize;
+    }
+    /* Indirect blocks. */
+    if (blk - LINN_INODE_DIR_BLOCKS < numPerBlock)
+    {
+       depth = 1;
+    }
+    /* Double indirect blocks. */
+    else if (blk - LINN_INODE_DIR_BLOCKS < numPerBlock * numPerBlock)
+    {
+       depth = 2;
+    }
+    /* Tripple indirect blocks. */
+    else
+       depth = 3;
+
+    /* Allocate temporary block. */
+    block   = new u64[LINN_SUPER_NUM_PTRS(&super)];
+    offset  = inode->block[(LINN_INODE_DIR_BLOCKS + depth - 1)];
+    offset *= super.blockSize;
+
+    /* Lookup the block number. */
+    while (depth > 0)
+    {
+       /* Fetch block. */
+       if (storage->read(offset, (u8 *) block, super.blockSize) < 0)
+       {
+           delete block;
+           return 0;
+       }
+       /* Calculate the number of blocks remaining per entry. */
+       Size remain = LINN_SUPER_NUM_PTRS(&super);
+       
+       /* Effectively the pow() function. */
+       for (Size i = 0; i < depth - 1; i++)
+       {
+           remain *= remain;
+       }
+       /* Calculate the next offset. */
+       offset  = block[ remain / (blk - LINN_INODE_DIR_BLOCKS + 1) ];
+       offset *= super.blockSize;
+       depth--;
+    }
+    /* Calculate the final offset. */
+    offset  = block[ (blk - LINN_INODE_DIR_BLOCKS) %
+                     LINN_SUPER_NUM_PTRS(&super) ];
+    offset *= super.blockSize;
+
+    /* All done. */
+    delete block;
+    return offset;     
+}
+
+FileCache * LinnFileSystem::lookupFile(FileSystemPath *path)
+{
+    List<String> *entries = path->split();
+    FileCache *c = root;
+    LinnInode *inode;
+    LinnDirectoryEntry entry;
+    LinnDirectory *dir;
+
+    /* Loop the entire path. */
+    for (ListIterator<String> i(entries); i.hasNext(); i++)
+    {
+       /* Do we have this entry? */
+        if (!c->entries[i.current()])
+       {
+           /* If this isn't a directory, we cannot perform a lookup. */
+           if (c->file->getType() != DirectoryFile)
+           {
+               return ZERO;
+           }
+           dir = (LinnDirectory *) c->file;
+       
+           /* Then retrieve it, if possible. */        
+           if (dir->getEntry(&entry, **i.current()) != ESUCCESS)
+           {
+               return ZERO;
+           }
+           /* Lookup corresponding inode. */
+           if (!(inode = getInode(entry.inode)))
+           {
+               return ZERO;
+           }
+           /* Create the appropriate in-memory file. */
+           switch ((FileType)inode->type)
+           {
+               case DirectoryFile:
+                   c = insertFileCache(new LinnDirectory(this, inode),
+                                       **i.current());
+                   break;
+
+               case RegularFile:
+                   c = insertFileCache(new LinnFile(this, inode),
+                                       **i.current());
+                   break;
+
+               default:
+                   return ZERO;
+           }
+       }
+       /* Move to the next entry. */
+       else
+           c = c->entries[i.current()];
+    }
+    return c;
+}

Added: trunk/srv/filesystem/linn/LinnFileSystem.h
==============================================================================
--- (empty file)
+++ trunk/srv/filesystem/linn/LinnFileSystem.h  Wed Jul  8 15:47:03 2009
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2009 Niek Linnenbank
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FILESYSTEM_LINN_FILESYSTEM_H
+#define __FILESYSTEM_LINN_FILESYSTEM_H
+
+#include <FileSystem.h>
+#include <FileSystemPath.h>
+#include <FileSystemMessage.h>
+#include <Storage.h>
+#include <Types.h>
+#include <Array.h>
+#include <HashTable.h>
+#include <Integer.h>
+#include "LinnSuperBlock.h"
+#include "LinnInode.h"
+#include "LinnGroup.h"
+
+/**
+ * @defgroup linn Linnenbank Filesystem (LinnFS)
+ * @{
+ */
+
+/**
+ * @name Filesystem limits.
+ * @{
+ */
+
+/** Minimum blocksize. */
+#define LINN_MIN_BLOCK_SIZE 1024
+
+/** Maximum blocksize. */
+#define        LINN_MAX_BLOCK_SIZE 8192
+
+/**
+ * @}
+ */
+
+#ifndef __HOST__
+
+/**
+ * Linnenbank FileSystem (LinnFS).
+ */
+class LinnFileSystem : public FileSystem
+{
+    public:
+
+       /**
+        * Class constructor function.
+        * @param path Path to which we are mounted.
+        * @param storage Storage provider.
+        */
+       LinnFileSystem(const char *path, Storage *storage);
+
+       /**
+        * Retrieve the superblock pointer.
+        * @return Pointer to the superblock for this filesystem.
+        * @see LinnSuperBlock
+        */
+       LinnSuperBlock * getSuperBlock()
+       {
+           return &super;
+       }
+
+       /**
+        * Get the underlying Storage object.
+        * @return Storage pointer.
+        * @see Storage
+        */
+       Storage * getStorage()
+       {
+           return storage;
+       }
+
+       /**
+        * Read an inode from the filesystem.
+        * @param inodeNum Inode number.
+        * @return Pointer to an LinnInode on success, ZERO on failure.
+        * @see LinnInode
+        */
+       LinnInode * getInode(u64 inodeNum);
+
+       /**
+        * Read a group descriptor from the filesystem.
+        * @param groupNum Group descriptor number.
+        * @return Pointer to an LinnGroup on success, ZERO on failure.
+        * @see LinnGroup
+        */
+       LinnGroup * getGroup(u64 groupNum);
+
+       /**
+        * Read a group descriptor from the filesystem, given an inode number.
+        * @param inodeNum Find the corresponding group via this inode number.
+        * @return Pointer to an LinnGroup on success, ZERO on failure.
+        * @see LinnGroup
+        * @see LinnInode
+        */
+       LinnGroup * getGroupByInode(u64 inodeNum);
+
+       /**
+        * Calculates the offset inside storage for a given block.
+        * @param inode LinnInode pointer.
+        * @param blk Calculate the offset for this block.
+        * @return Offset in bytes in storage.
+        * @see LinnInode
+        */
+       u64 getOffset(LinnInode *inode, u64 blk);
+
+       /**
+ * Load a file corresponding to the given path from underlying storage.
+         * @param path Full path to the file to load.
+ * @return Pointer to FileCache object if the file exists, or ZERO otherwise.
+         */
+       FileCache * lookupFile(FileSystemPath *path);
+
+    private:
+       
+       /**
+        * Creates a new LinnFile.
+        * @param msg Describes the file creation request.
+        * @param path Full path to the file to create.
+        */
+       Error createFile(FileSystemMessage *msg,
+                         FileSystemPath *path);
+
+       /** Provides storage. */
+       Storage *storage;
+       
+       /** Describes the filesystem. */
+       LinnSuperBlock super;
+       
+       /** Group descriptors. */
+       Array<LinnGroup> *groups;
+
+       /** Inode cache. */
+       HashTable<Integer<u64>,LinnInode> inodes;
+};
+
+#endif /* __HOST__ */
+
+/**
+ * @}
+ */
+
+#endif /* __FILESYSTEM_LINN_FILESYSTEM_H */

Modified: trunk/srv/filesystem/linn/SConscript
==============================================================================
--- trunk/srv/filesystem/linn/SConscript        (original)
+++ trunk/srv/filesystem/linn/SConscript        Wed Jul  8 15:47:03 2009
@@ -20,7 +20,7 @@
 #
 # Target system environment.
 #
-targetEnv = Prepare(target, [ 'libcrt', 'liballoc', 'libposix', 'libexec', 'libc' ], +targetEnv = Prepare(target, [ 'libcrt', 'liballoc', 'libposix', 'libexec', 'libc', 'libgcc' ],
                            [ 'filesystem', 'process', 'log' ])

 #
@@ -39,3 +39,10 @@
 #
 hostEnv.Program('host/dump', [ 'host/LinnDump.cpp' ],
                 LIBS = hostEnv['LIBS'], LIBPATH = hostEnv['LIBPATH'])
+
+#
+# Linnenbank FileSystem server.
+#
+targetEnv.Program('server', [ 'LinnFileSystem.cpp', 'LinnFile.cpp',
+                             'LinnDirectory.cpp' ],
+                  LIBS = targetEnv['LIBS'], LIBPATH = targetEnv['LIBPATH'])

Other related posts:

  • » [freenos] [freenos commit] r216 - Added initial implementation of the LinnFS filesystem server. - codesite-noreply