Autor Thema: cdi.fs  (Gelesen 16271 mal)

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #20 am: 17. February 2008, 14:51 »
Hi,

Dann muss ich mir das wohl noch mal genauer anschauen...

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #21 am: 17. February 2008, 20:44 »
Hallo

Ich verfolg euere Diskusion gerade ein bischen.

Hab ich das ungefähr richtig verstanden?

Lost hat im Kernel ein, Ich nene es mal FS - SUB system, das Dateisystem operationen aus dem Userspace entgegennimt ( durch bereitstellen entsprechender Funktionen ) die dann dort in den Kernelspace übertragen werden. Das FS-SUB greift dann auf die entsprechenden CDI.FS Treiber zurück um dann die Dateioperatioen schlussendlich durchzuführen.

Das CDI.FS bildet somit die schnittstelle für alle möglichen Dateisysteme. Nicht nur die echten wie z.B. FAT12/16/32 ext2/3 reiserfs, ... als auch die unechten / virtuellen wie z.B. prog / sys (sollten aus linux bekannt sein) sowie die Gerähtetreiber

Der Datenfluss könnte für ein FS_open dann etwa so aussehen.

FS_open -> FS - Sub - > FAT - > Block DEV HDA1
FS_open -> FS - Sub - > FAT - > FS - Sub -> DEV HDA - > HW

das ganze mal grafisch aufbereitet


  F S - S U B  System
=======================
F E  . | P S .  | D .   \
A X  . | R Y .  | E .    \ Implementiert
T T  . | O S .  | V .    / CDI.FS
  2    | G      |       /
=======================
Block  | Kernel | Hard
device | infos  | Ware

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #22 am: 17. February 2008, 20:57 »
Lost hat im Kernel ein, Ich nene es mal FS - SUB system, das Dateisystem operationen aus dem Userspace entgegennimt ( durch bereitstellen entsprechender Funktionen ) die dann dort in den Kernelspace übertragen werden. Das FS-SUB greift dann auf die entsprechenden CDI.FS Treiber zurück um dann die Dateioperatioen schlussendlich durchzuführen.
Jein. Das FS-Subsystem wie du es nennst (LostIO) sitzt nicht im Kernel, sondern in der libc der Userspace-Programme. Die Kommunikation läuft über die ganz normalen RPC-Funktionen.

Zitat
Das CDI.FS bildet somit die schnittstelle für alle möglichen Dateisysteme. Nicht nur die echten wie z.B. FAT12/16/32 ext2/3 reiserfs, ... als auch die unechten / virtuellen wie z.B. prog / sys (sollten aus linux bekannt sein) sowie die Gerähtetreiber
cdi.fs deckt nur die echten Dateisysteme ab, wo es sinnvoll ist, eine OS-unabhängige Schnittstelle zu haben. Beim Rest wird direkt auf LostIO aufgesetzt.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #23 am: 18. February 2008, 18:02 »
Hi,

Wobei soetwas wie ramfs auch noch möglich wäre. Denn man kann über CDI ja Speicher anfordern. Außerdem ist CDI doch eh kompatibel zur libc, von daher könnte man ganz schön viel damit anstellen. Da müsste man sich mal einen Weg ausdenken, wie der FS-Treiber CDI mitteilt, ob er überhaupt ein Speichermedium braucht.

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #24 am: 16. March 2008, 19:46 »
Hi,

Müsste man in struct cdi_fs_driver nicht noch eine Liste der Dateisysteme rein machen? Oder wo werden die Dateisysteme (struct cdi_fs_filesystem) verlinkt.

Wie soll struct cdi_fs_obj_flags aussehen?

Ansonsten hab ich mal ein paar Fehler rausgemacht (fehlende Semikolons usw.):
#ifndef _CDI_FS_H_
#define _CDI_FS_H_

#include "types.h"
#include "cdi.h"
#include "cdi/lists.h"

struct cdi_fs_driver {
  struct cdi_driver drv;
};

struct cdi_fs_device {
  struct cdi_device dev;
};

struct cdi_fs_object;
/**
* Diese Struktur wird fuer jedes eingebundene Dateisystem einmal erstellt.
*/
struct cdi_fs_filesystem {
    // Wurzelobjekt fuer die Baumstruktur
    struct cdi_fs_object*   root_object;

    // Falls ein gravierender Fehler auftritt, wird diese Fehlernummer gesetzt.
    // Wenn sie != 0 ist wird das Dateisystem fuer Schreibzugriffe gesperrt.
    int                     error;

    // Das Dateisystem darf nicht geschrieben werden. Damit schlaegt unter
    // anderem cdi_fs_write_data fehl.
    int                     read_only;

    // Hier sollte man wohl noch ein paar allgemeine Mount-Optionen oder
    // sonstige Flags die das ganze Dateisystem betreffen.
};


// XXX Bei den Fehlernummern weiss ich noch nicht wirklich, was da notwendig
// ist, deshalb lasse ich das mal so stehen.
typedef enum {
    CDI_FS_ERROR_NONE = 0,
    // Operation nicht unterstuetzt
    CDI_FS_ERROR_ONS,
    // Ressource nicht gefunden
    CDI_FS_ERROR_RNF,
    // Beim lesen einer Datei wurde das Ende erreicht
    CDI_FS_ERROR_EOF,
    // Interner Fehler
    CDI_FS_ERROR_INTERNAL,
    // Unbekannter Fehler
    CDI_FS_ERROR_UNKNOWN,
} cdi_fs_error_t;

/**
* Der Stream stellt die Verbindung zwischen Aufrufer und Ressource dar.
*/
struct cdi_fs_stream {
    // Betroffene Ressource
    struct cdi_fs_resource* res;

    // Fehlernummer
    cdi_fs_error_t          error;
};


/**
* Metaeigenschaften, die Ressourcen haben koennen
*/
typedef enum {
    // R  Groesse der Datei auslesen
    CDI_FS_META_SIZE,
    // R  Anzahl der Benutzten Dateisystemblocks (Irgendwo muesste man dann
    //    auch auf diese Blockgroesse zurgreiffen koennen)
    CDI_FS_META_USEDBLOCKS,
    // R  Optimale Blockgroesse mit der man auf die Datei zugreiffen sollte
    CDI_FS_META_BESTBLOCKSZ,
    // R  Zeitpunkt an dem die Ressource erstellt wurde
    CDI_FS_META_CREATETIME,
    // RW Letzter Zugriff auf die Ressource, auch lesend
    CDI_FS_META_ACCESSTIME,
    // RW Letzte Veraenderung der Ressource
    CDI_FS_META_CHANGETIME
} cdi_fs_meta_t;


/**
* Siese Struktur stellt die Moeglichkeiten, die an einer Ressource zur
* Verfuegung stehen, dar.
*/
struct cdi_fs_res_flags {
    // Ressource loeschen
    int                 remove;
    // Ressource umbenennen
    int                 rename;
    // Ressource verschieben
    int                 move;
    // Lesender Zugriff gestattet
    int                 read;
    // Schreibender Zugriff gestattet
    int                 write;
    // Ausfuehren gestattet
    int                 execute;
    // Auflisten der Verzeichniseintraege gestattet
    int                 browse;
    // Aufloesen des Links
    int                 read_link;
    // Aendern des Links
    int                 write_link;
    // Anlegen eines Untereintrags
    int                 create_child;
};


struct cdi_fs_res_file;
struct cdi_fs_res_dir;
struct cdi_fs_res_link;
struct cdi_fs_res_special;

/**
* Typ der eine Ressource, die zu der Klasse der Spezialdateien gehoert noch
* genauer beschreibt
*/
typedef enum {
    CDI_FS_BLOCK,
    CDI_FS_CHAR,
    CDI_FS_FIFO,
    CDI_FS_SOCKET
} cdi_fs_res_type_t;

/**
* Konstanten fuer die einzelnen Klassen, um sie beim Funktionsaufruf zum
* zuweisen einer Klasse, identifizieren zu koennen.
*/
typedef enum {
    CDI_FS_CLASS_FILE,
    CDI_FS_CLASS_DIR,
    CDI_FS_CLASS_LINK,
    CDI_FS_CLASS_SPECIAL
} cdi_fs_res_class_t;

/**
* Dieser Typ dient dazu Ressourcen ganz oder teilweise zu sperren
*/
typedef enum {
    CDI_FS_LOCK_NONE,
    CDI_FS_LOCK_WRITE,
    CDI_FS_LOCK_ALL
} cdi_fs_lock_t;

/**
* Das Dateisystem wird hier nur mit abstrakten Strukturen vom Typ
* cdi_fs_resource dargestellt. Diese können beispielsweise sowohl regulaere
* Datei als auch Verzeichnis gleichzeitig darstellen.
*
* Weiter gilt, dass Ressourcen, die zu keiner Klasse gehoeren, nicht
* persistent sind.
*/
struct cdi_fs_resource {
    // Name der Ressource
    char*                   name;

    // Lock fuer diese Ressource
    cdi_fs_lock_t           lock;

    // Verweis auf das Elternobjekt
    struct cdi_fs_object*  parent;
    // Liste mit allfaelligen Kindobjekten
    cdi_list_t              children;

    // Link-Pfad
    char*                   link_path;

    // ACL; siehe Unten
    cdi_list_t              acl;
    // Flags
    struct cdi_fs_obj_flags flags;

    // Einzelne Klassen, zu denen die Ressourcen gehoeren kann, oder Null falls
    // es zu einer Bestimmten Klasse nicht gehoert.
    struct cdi_fs_res_file* file;
    struct cdi_fs_res_dir*  dir;
    struct cdi_fs_res_link* link;
    struct cdi_fs_res_special* special;

    // Falls die Ressource zu einer Spezialklasse gehoert, wird hier angegeben,
    // um welchen Typ von Spezialressource sie gehoert.
    cdi_fs_res_type_t        type;
};



/**
* Diese Dateisystemobjekte werden in Klassen eingeteilt, die das eigentliche
* "Verhalten" der Ressourcen steuern. Diese Klassen beinhalten die moeglichen
* Operationen und auch die Eigenschaften, die fuer die Ressourcen gelten,
* denen diese Klassen zugeordnet sind.
* Das Definieren der einzelnen Klassen uebernehmen dann die einzelnen Treiber.
*
* Die Flags koennen von der Ressource ueberschrieben werden. Es koennen
* allerdings nur Flags deaktiviert werden, die in der Klasse gesetzt sind un
* nicht umgekehrt.
* Das Selbe gilt auch fuer Klassen bei denen NULL-Pointer fuer Operationen
* eingetragen sind. Wenn zum Beispiel fuer write NULL eingetragen wird, dann
* bringt ein gesetztes write-Flag nichts.
*/

/**
* Diese Klasse gilt unabhaengig von den andern, also egal welche anderen
* Klassen angegeben sind, diese muss angegeben werden.
*/
struct cdi_fs_obj_obj {
    /**
     * Ressource entfernen
     *
     * @param stream Stream
     *
     * @return Falls die Ressource erfolgreich geloescht wurde 1, sonst 0
     */
    int (*remove)(struct cdi_fs_stream* stream);

    /**
     * Namen einer Ressource aendern. Der Parameter name ist nur der
     * Resourcennamen ohne Pfad. Zum verschieben wird move() benutzt.
     *
     * @param stream Stream
     * @param name Neuer Name
     *
     * @return Falls die Ressource erfolgreich umbenennt wurde 1, sonst 0
     */
    int (*rename)(struct cdi_fs_stream* stream, const char* name);

    /**
     * Ressource innerhalb des Dateisystems verschieben. Das Verschieben ueber
     * Dateisystemgrenzen hinweg wird per kopieren und loeschen durchgefuehrt.
     *
     * @param stream Stream
     * @param dest Pointer auf die Ressource, in die die Ressource verschoben
     *             werden soll
     *
     * @return Falls die Ressource erfolgreich verschoben wurde 1, sonst 0
     */
    int (*move)(struct cdi_fs_stream* stream, struct cdi_fs_resource* dest);

    /**
     * Neue Ressource in der Aktuellen erstellen. Diese wird erstmal noch
     * keiner Klasse zugewiesen. Diese Funktion wird mit einem NULL-Pointer als
     * Ressource im Stream aufgerufen. Dieser NULL-Pointer muss bei
     * Erfolgreichem Beenden durch einen Pointer auf die neue Ressource ersetzt
     * worden sein.
     *
     * @param stream Mit NULL-Pointer als Ressource
     * @param parent Ressource, der die neue Ressource als Kindressource
     *               zugeordnet werden soll.
     *
     * @return Falls die Ressource erfolgreich erstellt wurde 1, sonst 0
     */
    int (*create_child)(struct cdi_fs_stream* stream,
        struct cdi_fs_resource* parent);

    /**
     * Diese Ressource einer neuen Klasse zuweisen. Dieser Aufruf schlaegt
     * fehl, wenn die Ressource dieser Klasse schon zugewiesen ist.
     *
     * @param stream Stream
     * @param class Konstante fuer den Typ der klasse, der die Ressource
     *              zugewiesen werden soll.
     *
     * @return 1 falls die Ressource erfolgreich der Klasse zugewiesen wurde, 0
     *         sonst
     */
     int (*assign_class)(struct cdi_fs_stream* stream,
        cdi_fs_res_class_t class);

    /**
     * Metaeigenschaft lesen
     *
     * @param stream Stream
     * @param meta Konstante fuer die gewuenschte Metaeigenschaft
     *
     * @return Wert der Metaeigenschaft
     */
    uint64_t (*meta_read)(struct cdi_fs_stream* stream, cdi_fs_meta_t meta);

    /**
     * Metaeigenschaft schreiben
     *
     * @param stream Stream
     * @param meta Konstante fuer die gewuenschte Metaeigenschaft
     * @param value Neuen Wert fuer die Metaeigenschaft
     *
     * @return Falls die Metaeigenschaft erfolgreich geaendert wurde 1, sonst 0
     */
    uint64_t (*meta_write)(struct cdi_fs_stream* stream, cdi_fs_meta_t meta, uint64_t value);

};

struct cdi_fs_obj_file {
    // XXX (Aber wie geht das, wenn eine Datei nicht lesbar, aber ausfuehrbar
    // sein soll?)
    int                     executable;

    /**
     * Daten aus dieser Datei lesen. Wird nur aufgerufen, wenn es durch die
     * Flags oder Berechtigungen nicht verhindert wird.
     *
     * Im Fehlerfall wird je nach Fehler die Fehlernummer im Handle und die im
     * Device gesetzt.
     *
     * @param stream Stream
     * @param start Position von der an gelesen werden soll
     * @param size Groesse der zu lesenden Daten
     * @param buffer Puffer in den die Daten gelsen werden sollen
     *
     * @return Gelesene Bytes, oder 0 im Fehlerfall
     */
    size_t (*read)(struct cdi_fs_stream* stream,uint64_t start, size_t size, void* buffer);

    /**
     * Daten in diese Datei schreiben. Wird nur aufgerufen, wenn es durch die
     * Flags oder Berechtigungen nicht verhindert wird.
     *
     * Im Fehlerfall wird je nach Fehler die Fehlernummer im Handle und die im
     * Device gesetzt.
     *
     * @param stream Stream
     * @param start Position an die geschrieben werden soll
     * @param size Groesse der zu schreibenden Daten
     * @param buffer Puffer aus dem die Daten gelesen werden sollen
     *
     * @return Geschriebene Bytes oder 0 im Fehlerfall
     */
    size_t (*write)(struct cdi_fs_stream* stream, uint64_t start, size_t size, void* buffer);
};

struct cdi_fs_obj_dir {
    // XXX Ein browsable Flag koennen wir vermutlich hier eindeutig welgassen,
    // waere ja irgenwie witzlos. ;-)

    /**
     * Diese Funktion gibt einen Pointer auf die Liste mit den Eintraegen
     * zurueck. Hier wird nicht einfach fix der Pointer in fs_obj genommen,
     * damit dort auch "versteckte" Eintraege vorhanden sein koennten. (Ich
     * meine hier nicht irgend ein versteckt-Flag dass die Dateien vor dem
     * Benutzer Verstecken soll, sondern eher von fuer den Internen gebrauch
     * angelegten Eintraegen.
     *
     * @param stream Stream
     *
     * @return Pointer auf eine Liste mit den Untereintraegen.
     */
     cdi_list_t* (*list)(struct cdi_fs_stream* stream);
};

struct cdi_fs_obj_link {
    // XXX Ich glaube auch hier brauchen wir kein resolvable-Flag

    /**
     * Diese Funktion liest den Pfad aus, auf den der Link zeigt
     *
     * @param stream Stream
     *
     * @return Pointer auf einen Ouffer der den Pfad beinhaltet. Dieses Puffer
     *         darf vom Aufrufer nicht veraendert werden.
     */
    const char* (*read_link)(struct cdi_fs_stream* stream);

    /**
     * Aendert den Pfad auf den der Link zeigt
     *
     * @param stream Stream
     * @param path Neuer Pfad
     *
     * XXX Hm ist diese Funktion so vielleicht noch ein bisschen zu
     * optimistisch?
     */
    void (*write_link)(struct cdi_fs_stream* stream);
};

struct cdi_fs_res_special {
    // XXX Reicht das so?

    /**
     * Geraeteadresse der Spezialdatei Lesen
     *
     * @param stream Stream
     * @param dev Pointer auf die Variable in der die Geraeteadresse
     *            gespeichert werden soll.
     *
     * @return Falls die Geraeteadresse erfolgreich gelesen wurde 1, sonst 0
     */
    int (*dev_read)(struct cdi_fs_stream* stream, dev_t* dev);

    /**
     * Geraeteadresse der Spezialdatei Aendern
     *
     * @param stream Stream
     * @param dev Die neue Geraeteadresse
     *
     * @return Falls die Geraeteadresse erfolgreich geaendert wurde 1, sonst 0
     */
    int (*dev_write)(struct cdi_fs_stream* stream, dev_t dev);
};

/**
* Der Basiseintrag in einer ACL, von dem die anderen Typen der Eintraege
* abgeleitet sind.
*/
struct cdi_fs_acl_entry {
    // Typ des Eintrages, eine der obigen Konstanten
    enum {
        /**
         * Die Berechtigunen werden mit Access controll lists, kurz ACLs verwaltet.
         * Diese werden in Form von Listen gespeichert. Diese Listen enthalten
         * eintraege von verschiedenen Typen.
         */
        /// Eine UID
        CDI_FS_ACL_USER_NUMERIC,
        /// Ein Benutzername als String
        CDI_FS_ACL_USER_STRING,
        /// Eine GID
        CDI_FS_ACL_GROUP_NUMERIC,
        /// Ein Gruppenname als String
        CDI_FS_ACL_GROUP_STRING
    } type;

    // Flags
    struct cdi_fs_obj_flags flags;
};

/**
* Eintraege fuer die einzelnen Typen
*/
struct cdi_fs_acl_entry_usr_num {
    struct cdi_fs_acl_entry entry;

    // Benutzer-ID
    uid_t                   user_id;
};

struct cdi_fs_acl_entry_usr_str {
    struct cdi_fs_acl_entry entry;

    // Benutzername
    char*                   user_name;
};

struct cdi_fs_acl_entry_grp_num {
    struct cdi_fs_acl_entry entry;

    // Gruppen-ID
    gid_t                   group_id;
};

struct cdi_fs_acl_entry_grp_str {
    struct cdi_fs_acl_entry entry;

    // Gruppenname
    char*                   group_name;
};



void cdi_fs_driver_init(struct cdi_fs_driver* driver);
void cdi_fs_driver_destroy(struct cdi_fs_driver* driver);
void cdi_fs_driver_register(struct cdi_fs_driver* driver);


/**
* Quelldateien fuer ein Dateisystem lesen
* XXX Brauchen wir hier auch noch irgendwas errno-Maessiges?
*
* @param device Pointer auf die Device-Struktur des Dateisystems
* @param start Position von der an gelesen werden soll
* @param size Groesse des zu lesenden Datenblocks
* @param buffer Puffer in dem die Daten abgelegt werden sollen
*
* @return die Anzahl der gelesenen Bytes
*/
size_t cdi_fs_data_read(struct cdi_fs_device* device, uint64_t start, size_t size, void* buffer);

/**
* Quellmedium eines Dateisystems beschreiben
* XXX Brauchen wir hier auch noch irgendwas errno-Maessiges?
*
* @param device Pointer auf die Device-Struktur des Dateisystems
* @param start Position an die geschrieben werden soll
* @param size Groesse des zu schreibenden Datenblocks
* @param buffer Puffer aus dem die Daten gelesen werden sollen
*
* @return die Anzahl der geschriebenen Bytes
*/
size_t cdi_fs_data_write(struct cdi_fs_device* device, uint64_t start, size_t size, void* buffer);


#endif
« Letzte Änderung: 16. March 2008, 20:26 von jgraef »

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #25 am: 16. March 2008, 20:10 »
Worin siehst du den Nutzen von sowas?

Ich habe das eigentlich so vorgesehen, dass die Implementation das selbst irgendwie Regelt. Bei LOST kann ich sowas beispielsweise direkt in LostIO unterbringen.

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #26 am: 16. March 2008, 20:29 »
Worin siehst du den Nutzen von sowas?

Ich habe das eigentlich so vorgesehen, dass die Implementation das selbst irgendwie Regelt. Bei LOST kann ich sowas beispielsweise direkt in LostIO unterbringen.

Wenn ich der FS-Treiber bin und ich fülle jetzt fs_filesystem aus. Wem sage ich, wo CDI die Struktur findet? Wie teilst du CDI mit, dass er das Dateisystem bei LostIO anmelden soll?

EDIT: Sehe ich das richtig, dass der Treiber direkt nach dem Laden, den ganzen Verzeichnisbaum laden muss?
« Letzte Änderung: 16. March 2008, 20:32 von jgraef »

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #27 am: 16. March 2008, 20:49 »
Das läuft eher anders rum: Die Implementation erhälrt über LostIO die Nachricht das Dateisystem einzubinden. Sie ruft dann die wohl noch nicht vorhandene cdi_fs_init_fs auf. ;-)

Nein. Der Treiber muss nur das Root-Verzeichnis laden und es als noch nicht geladen markieren. Dabei fällt mir noch auf, dass dafür auch noch ein Flag fehlt. Wenn dann darauf zugegriffen werden soll kann das Laden nachgeholt werden.

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #28 am: 16. March 2008, 21:53 »
Das läuft eher anders rum: Die Implementation erhälrt über LostIO die Nachricht das Dateisystem einzubinden. Sie ruft dann die wohl noch nicht vorhandene cdi_fs_init_fs auf. ;-)

Nein. Der Treiber muss nur das Root-Verzeichnis laden und es als noch nicht geladen markieren. Dabei fällt mir noch auf, dass dafür auch noch ein Flag fehlt. Wenn dann darauf zugegriffen werden soll kann das Laden nachgeholt werden.

Dann muss der FS-Treiber aber irgendwo (z.B Treibername) den Typ des Dateisystems angeben, damit LostIO (bzw. bei meinOS VFS) weiß, wann das Dateisystem gebraucht wird. Und cdi_fs_init_fs muss irgenwo verlinkt sein, damit CDI das auch aufrufen kann

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #29 am: 16. March 2008, 21:58 »
Dafür ist doch der Treibername vorgesehen, wie bei den anderen CDI-Treibern auch. Da trägt man halt dann ext2 ein, und wenn ich in LOST ein cd ata:/ata00_p1|ext2:/ mache, weiss LostIO welcher Treiber gemeint ist.

 

Einloggen