[freenos] r289 committed - Modified the FileSystem to only perform synchroneous communication wit...

  • From: codesite-noreply@xxxxxxxxxx
  • To: freenos@xxxxxxxxxxxxx
  • Date: Sun, 02 Aug 2009 13:55:50 +0000

Revision: 289
Author: nieklinnenbank
Date: Sun Aug  2 05:28:09 2009
Log: Modified the FileSystem to only perform synchroneous communication with user processes. The VirtualFileSystem (and the whole asynchroneous implementation) has been removed. FileSystems now simply communicate using blocking IPC to serve requests and do *not* forward or multiplex requests anymore. User processes use the FileSystemMounts table to find the correct FileSystem or Device to IPC with.

http://code.google.com/p/freenos/source/detail?r=289

Deleted:
 /trunk/srv/filesystem/Device.h
 /trunk/srv/filesystem/virtual
Modified:
 /trunk/srv/filesystem/FileSystem.h
 /trunk/srv/filesystem/SConscript

=======================================
--- /trunk/srv/filesystem/Device.h      Mon Jun 29 00:56:11 2009
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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_DEVICE_H
-#define __FILESYSTEM_DEVICE_H
-
-#include <API/VMCopy.h>
-#include <Types.h>
-#include <Error.h>
-#include "File.h"
-#include "FileSystemMessage.h"
-
-/**
- * Abstract device which is represented as a File.
- */
-class Device : public File
-{
-    public:
-
-       /**
-        * Constructor function.
-        * @param id Unique identity of the device.
-        * @param t Type of device.
-        */
-       Device(DeviceID id, FileType t = CharacterDeviceFile)
-            : File(t), deviceID(id)
-       {
-       }
-
-       /**
-        * Opens the Device.
-        * @param msg Open request.
-         * @return Always EAGAIN. The Device will send an IODone
-        *         when it has completed the request.
-        */
-       Error open(FileSystemMessage *msg)
-       {
-           msg->action   = OpenFile;
-           msg->deviceID = deviceID;
-           msg->ipc(deviceID.major, Send, sizeof(*msg));
-           return EAGAIN;
-       }
-
-        /**
-         * Reads out the buffer.
-        * @param msg Read request.
-         * @return Always EAGAIN. The Device will send an IODone
-        *         when it has completed the request.
-         */
-        Error read(FileSystemMessage *msg)
-       {
-           msg->action   = ReadFile;
-           msg->deviceID = deviceID;
-           msg->ipc(deviceID.major, Send, sizeof(*msg));
-           return EAGAIN;
-       }
-
-        /**
-         * Writes data from the buffer to the device.
-        * @param msg Write request.
-         * @return Always EAGAIN. The Device will send an IODone
-        *         when it has completed the request.
-         */
-       Error write(FileSystemMessage *msg)
-       {
-           msg->action   = WriteFile;
-           msg->deviceID = deviceID;
-           msg->ipc(deviceID.major, Send, sizeof(*msg));
-           return EAGAIN;
-       }
-
-        /**
-         * Retrieve file statistics.
-        * @param msg Describes the status request.
-        * @return Error code status.
-         */
-        Error status(FileSystemMessage *msg)
-        {
-           FileStat st;
-           Error e;
-
-           /* Fill in the status structure. */
-           st.type = type;
-            st.size = size;
-            st.userID   = uid;
-            st.groupID  = gid;
-           st.deviceID = deviceID;
-
-           /* Write to remote process' buffer. */
-           if ((e = VMCopy(msg->procID, Write, (Address) &st,
-                          (Address) msg->stat, sizeof(st))) > 0)
-           {
-               return ESUCCESS;
-           }
-           else
-           {
-               return e;
-           }
-        }
-
-    private:
-
-       /** Device ID numbers. */
-       DeviceID deviceID;
-};
-
-#endif /* __FILESYSTEM_DEVICE_H */
=======================================
--- /trunk/srv/filesystem/FileSystem.h  Fri Jul 10 09:07:14 2009
+++ /trunk/srv/filesystem/FileSystem.h  Sun Aug  2 05:28:09 2009
@@ -21,16 +21,20 @@
 #include <API/IPCMessage.h>
 #include <API/VMCopy.h>
 #include <IPCServer.h>
+#include <UserProcess.h>
 #include <Config.h>
+#include <Shared.h>
+#include <Array.h>
 #include <HashTable.h>
 #include <HashIterator.h>
+#include <POSIXSupport.h>
 #include "Directory.h"
 #include "File.h"
 #include "FileSystemPath.h"
 #include "FileSystemMessage.h"
-
-/** Maximum length of a filesystem path. */
-#define PATHLEN 64
+#include "FileSystemMount.h"
+#include "FileDescriptor.h"
+#include <unistd.h>

 /**
  * Cached in-memory file.
@@ -48,7 +52,6 @@
     {
        if (p && p != this)
        {
-           file->incrementRefCount();
            p->entries.insert(new String(path->base()), this);
        }
     }
@@ -87,25 +90,33 @@
         */
        FileSystem(const char *path)
            : IPCServer<FileSystem, FileSystemMessage>(this),
-             root(ZERO), mountPath((char*)path)
-       {
-           FileSystemMessage msg;
-
+             root(ZERO), mountPath(path)
+       {
            /* Register message handlers. */
-           addIPCHandler(CreateFile, &FileSystem::ioHandler, false);
-           addIPCHandler(OpenFile,   &FileSystem::ioHandler, false);
-           addIPCHandler(ReadFile,   &FileSystem::ioHandler, false);
-           addIPCHandler(WriteFile,  &FileSystem::ioHandler, false);
-           addIPCHandler(CloseFile,  &FileSystem::ioHandler, false);
-           addIPCHandler(StatFile,   &FileSystem::ioHandler, false);
-           addIPCHandler(IODone,     &FileSystem::ioDoneHandler, false);
+           addIPCHandler(CreateFile, &FileSystem::pathHandler);
+           addIPCHandler(OpenFile,   &FileSystem::pathHandler);
+           addIPCHandler(StatFile,   &FileSystem::pathHandler);
+           addIPCHandler(ReadFile,   &FileSystem::fileDescriptorHandler);
+           addIPCHandler(WriteFile,  &FileSystem::fileDescriptorHandler);
+           addIPCHandler(CloseFile,  &FileSystem::fileDescriptorHandler);
+           addIPCHandler(SeekFile,   &FileSystem::fileDescriptorHandler);
+
+           /* Load shared tables. */
+           procs.load(USER_PROCESS_KEY, MAX_PROCS);
+           mounts.load(FILE_SYSTEM_MOUNT_KEY, MAX_MOUNTS);
+           files = new Array<Shared<FileDescriptor> >(MAX_PROCS);

            /* Mount ourselves. */
-           msg.action = Mount;
-           msg.buffer = (char *) path;
-
-           /* Request VFS mount. */
-           IPCMessage(VFSSRV_PID, SendReceive, &msg, sizeof(msg));
+           for (Size i = 0; i < MAX_MOUNTS; i++)
+           {
+               if (!mounts[i]->path[0] || !strcmp(mounts[i]->path, path))
+               {
+                   strlcpy(mounts[i]->path, path, PATHLEN);
+                   mounts[i]->procID  = getpid();
+                   mounts[i]->options = ZERO;
+                   break;
+               }
+           }
        }

        /**
@@ -137,154 +148,149 @@
        }

        /**
-         * Perform Input/Output on a file.
-        * @param msg Incoming message.
+         * @brief Process an incoming filesystem request using a path.
+        *
+        * This message handler is responsible for processing any
+        * kind of FileSystemMessages which have an FileSystemAction using
+        * the path field, such as OpenFile.
+        *
+        * @param msg Incoming request message.
+        * @see FileSystemMessage
+        * @see FileSystemAction
          */
-       void ioHandler(FileSystemMessage *msg)
-       {
-           FileSystemMessage vfs;
+       void pathHandler(FileSystemMessage *msg)
+       {
            FileSystemPath path;
-           FileCache *fc = ZERO;
-           File *f = ZERO;
+           FileCache *cache = ZERO;
+           File *file;
+           ProcessID pid;
+           Address ident;
            char buf[PATHLEN], tmp[PATHLEN];
-
+
            /*
-            * Find the file, either in cache, storage or via
-            * the message itself.
+            * Attempt to copy the input path first.
             */
-           switch (msg->action)
-           {
-               case CreateFile:
-               case OpenFile:
-               case StatFile:
-
-                   /* Copy the path first. */
-                   if (VMCopy(msg->procID, Read, (Address) buf,
-                             (Address) msg->buffer, PATHLEN) <= 0)
-                   {
-                       msg->error(EACCES, IODone);
-                       return;
-                   }
-                   else
-                   {
-                       /* Is the path relative? */
-                       if (buf[0] != '/')
-                       {
-                           vfs.action = GetCurrentDir;
-                           vfs.buffer = tmp;
-                           vfs.procID = msg->procID;
-
-                           /*
-                            * Ask for their current directory.
-                            * TODO: this can be much more efficient, if we can
-                            *       map the user process table in our address 
space!
- * TODO: this is also buggy... what if VFS tries to contact us meanwhile...
-                            */
-                           IPCMessage(VFSSRV_PID, SendReceive, &vfs, 
sizeof(vfs));
-
-                           /* Reconstruct path. */
-                           snprintf(tmp, sizeof(tmp), "%s/%s", tmp,
-                                    buf);
-                           path.parse(tmp);
-                       }
-                       else
-                           path.parse(buf + strlen(mountPath));
-
-                       /* No need to lookup caches for creation. */
-                       if (msg->action == CreateFile)
-                       {
-                           break;
-                       }
-                       /* Do we have this file cached? */
-                       if ((fc = findFileCache(&path)) || (fc = 
lookupFile(&path)))
-                       {
-                           f = fc->file;
-                           f->incrementRefCount();
-                           msg->ident = (Address) f;
-                       }
-                       else
-                       {
-                           msg->error(ENOENT, IODone);
-                           return;
-                       }
-                   }
-                   break;
-
-               default:
-
-                   /* Simply use the message identity. */
-                   f = (File *) msg->ident;
-           }
+           if ((msg->result = VMCopy(msg->from, Read, (Address) buf,
+                                    (Address) msg->buffer, PATHLEN)) <= 0)
+           {
+               return;
+           }
+           /* Is the path relative? */
+           if (buf[0] != '/')
+           {
+               /* Reconstruct path. */
+               snprintf(tmp, sizeof(tmp), "%s/%s",
+                        procs[msg->from]->currentDirectory, buf);
+               path.parse(tmp);
+           }
+           else
+               path.parse(buf + strlen(mountPath));
+
+           /*
+            * Do we have this file cached?
+            */
+           if ((cache = findFileCache(&path)) ||
+               (cache = lookupFile(&path)))
+           {
+               file = cache->file;
+           }
+           /* Sorry, no such file! */
+           else if (msg->action != CreateFile)
+           {
+               msg->result = ENOENT;
+               return;
+           }
            /* Perform I/O on the file. */
            switch (msg->action)
            {
                case CreateFile:
-                   msg->result = createFile(msg, &path);
+                   if (cache)
+                       msg->result = EEXIST;
+                   else
+                       msg->result = createFile(msg, &path);
                    break;

                case OpenFile:
-                   msg->result = f->open(msg);
+
+                   /*
+                    * Attempt to open the file.
+                    */
+                   pid   = getpid();
+                   ident = (Address) file;
+                   msg->result = cache->file->open(msg, &pid, &ident);
+
+                   /* Create a FileDescriptor on success. */
+                   if (msg->result == ESUCCESS)
+                   {
+                       msg->fd = insertFileDescriptor(msg->from, pid, ident);
+                   }
                    break;

                case StatFile:
-                   msg->result = f->status(msg);
+               default:
+                   msg->result = file->status(msg);
                    break;
-
+           }
+       }
+
+       /**
+ * @brief Process an incoming filesystem request using a FileDescriptor.
+        *
+        * This message handler is responsible for processing any
+        * kind of FileSystemMessages which have an FileSystemAction using
+        * a FileDescriptor, such as ReadFile.
+        *
+        * @param msg Incoming request message.
+        * @see FileSystemMessage
+        * @see FileSystemAction
+        * @see FileDescriptor
+         */
+       void fileDescriptorHandler(FileSystemMessage *msg)
+       {
+           FileDescriptor *fd;
+           File *file = ZERO;
+
+           /*
+            * Obtain the FileDescriptor.
+            */
+           if (!(fd = getFileDescriptor(files, msg->from, msg->fd)))
+           {
+               msg->result = EBADF;
+               return;
+           }
+           /* Copy FileDescriptor properties. */
+           if (msg->action != SeekFile)
+           {
+               msg->offset = fd->position;
+               file = (File *) fd->identifier;
+           }
+           /* Perform I/O on the file. */
+           switch (msg->action)
+           {
                case ReadFile:
-                   msg->result = f->read(msg);
+                   msg->result   = file->read(msg);
+                   fd->position += msg->size;
                    break;

                case WriteFile:
-                   msg->result = f->write(msg);
+                   msg->result = file->write(msg);
+                   fd->position += msg->size;
                    break;
-
+
                case CloseFile:
- msg->result = ESUCCESS; // TODO: for devices, we must inform them!!!
-                                               // TODO: 
incrementReferenceCount() here aswell.
+                   msg->result = file->close(msg);
+                   memset(getFileDescriptor(files, msg->from, msg->fd), 0,
+                          sizeof(FileDescriptor));
                    break;

+               case SeekFile:
                default:
-                   msg->error(ENOTSUP);
+                   fd->position = msg->offset;
+                   msg->result  = ESUCCESS;
                    break;
            }
-           /* Did the operation complete already? */
-           if (msg->result != EAGAIN)
-           {
-               ioDoneHandler(msg);
-           }
-       }
-
-       /**
- * Allows devices to inform the filesystem that an I/O operation has completed.
-        * @param msg Incoming message.
-        */
-       void ioDoneHandler(FileSystemMessage *msg)
-       {
-           File *f = (File *) msg->ident;
-
-           if (msg->result == ESUCCESS)
-           {
-               switch (msg->savedAction)
-               {
-                   case OpenFile:
-                       f->incrementOpenCount();
-
-                   case StatFile:
-                       f->decrementRefCount();
-                       break;
-
-                   case CloseFile:
-                       f->decrementOpenCount();
-                       // TODO: decrementReferenceCount()
-                       break;
-
-                   default:
-                       ;
-               }
-           }
-           msg->ioDone(VFSSRV_PID, msg->procID, msg->size, msg->result);
-       }
-
+       }
+
     protected:

        /**
@@ -409,18 +415,16 @@
                    clearFileCache(i.current());

                    /* May we remove reference to this entry? */
-                   if (i.current()->file->getRefCount()  >= 1 &&
-                       i.current()->file->getOpenCount() == 0)
+                   if (i.current()->file->getOpenCount() == 0)

                    {
-                       i.current()->file->decrementRefCount();
                        cache->entries.remove(i.key(), true);
                    }
                }
            }
            /* Remove the entry itself, if empty. */
-           if (!cache->valid && cache->file->getRefCount() == 0 &&
-                cache->entries.count() == 0 && cache->file->getOpenCount() == 
0)
+           if (!cache->valid && cache->entries.count() == 0 &&
+                cache->file->getOpenCount() == 0)
            {
                delete cache->file;
                delete cache;
@@ -431,7 +435,46 @@
        FileCache *root;

        /** Mount point. */
-       char *mountPath;
+       const char *mountPath;
+
+        /** Mounted filesystems. */
+        Shared<FileSystemMount> mounts;
+
+        /** User process table. */
+        Shared<UserProcess> procs;
+
+        /** Per-process File descriptors. */
+        Array<Shared<FileDescriptor> > *files;
+
+    private:
+
+       /**
+         * Fills a new FileDescriptor entry.
+         * @param procID Process Identity to insert the FileDescriptor for.
+         * @param mount Process identity of the filesystem server.
+         * @param ident Unique identifier for the file.
+         * @return FileDescriptor index number.
+         */
+        int insertFileDescriptor(ProcessID procID, ProcessID mount,
+                                 Address ident)
+       {
+           Shared<FileDescriptor> *fds = getFileDescriptors(files, procID);
+
+           /* Loop the FileDescriptor table. */
+           for (Size i = 0; i < FILE_DESCRIPTOR_MAX; i++)
+           {
+               /* Use the entry, if the mount field is ZERO. */
+               if (!fds->get(i)->mount)
+               {
+                   fds->get(i)->mount      = mount;
+                   fds->get(i)->identifier = ident;
+                   fds->get(i)->position   = ZERO;
+                   return i;
+               }
+           }
+           /* Maximum number of FileDescriptors reached. */
+           return -1;
+       }
 };

 #endif /* __FILESYSTEM_FILESYSTEM_H */
=======================================
--- /trunk/srv/filesystem/SConscript    Sat Jul  4 09:38:42 2009
+++ /trunk/srv/filesystem/SConscript    Sun Aug  2 05:28:09 2009
@@ -15,4 +15,4 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #

-SConscript(dirs = [ 'ext2', 'linn', 'proc', 'tmp', 'virtual' ])
+SConscript(dirs = [ 'ext2', 'linn', 'proc', 'tmp' ])

Other related posts:

  • » [freenos] r289 committed - Modified the FileSystem to only perform synchroneous communication wit... - codesite-noreply