[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [tyndur-devel] [PATCH] ramoverlay hinzugefuegt



On Sat, Dec 05 11:02, Kevin Wolf wrote:
> + ramoverlay: Ein LostIO-Service, der ueber eine schreibgeschuetze
>   Ressource (z.B. eine CD-ROM) einen COW-Ramdisk legt, um temporaere
>   Schreibzugriffe zu erlauben
> 
> Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
> ---
>  src/modules/ramoverlay/Makefile.all |    6 +
>  src/modules/ramoverlay/main.c       |  282 +++++++++++++++++++++++++++++++++++
>  2 files changed, 288 insertions(+), 0 deletions(-)
>  create mode 100644 src/modules/ramoverlay/Makefile.all
>  create mode 100644 src/modules/ramoverlay/main.c
> 
> diff --git a/src/modules/ramoverlay/Makefile.all b/src/modules/ramoverlay/Makefile.all
> new file mode 100644
> index 0000000..8eacb97
> --- /dev/null
> +++ b/src/modules/ramoverlay/Makefile.all
> @@ -0,0 +1,6 @@
> +shopt -s extglob
> +source $LOST_BUILDMK_ROOT/config.sh
> +
> +echo "LD   $1/modules/ramoverlay"
> +$LOST_TOOLS_LD -Ttext=0x40000000 -oramoverlay.mod  *.o --start-group $2 --end-group
> +$LOST_TOOLS_STRIP -s ramoverlay.mod -o $1/modules/ramoverlay
> diff --git a/src/modules/ramoverlay/main.c b/src/modules/ramoverlay/main.c
> new file mode 100644
> index 0000000..654c383
> --- /dev/null
> +++ b/src/modules/ramoverlay/main.c
> @@ -0,0 +1,282 @@
> +/*
> + * Copyright (c) 2009 The tyndur Project. All rights reserved.
> + *
> + * This code is derived from software contributed to the tyndur Project
> + * by Kevin Wolf.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. All advertising materials mentioning features or use of this software
> + *    must display the following acknowledgement:
> + *     This product includes software developed by the tyndur Project
> + *     and its contributors.
> + * 4. Neither the name of the tyndur Project nor the names of its
> + *    contributors may be used to endorse or promote products derived
> + *    from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
> + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
> + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
> + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
> + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <init.h>
> +#include <lostio.h>
> +#include <stdint.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <syscall.h>
> +
> +#define BLOCK_SIZE (256 * 1024)
> +
> +void   overlay_post_open(lostio_filehandle_t* fh);
> +size_t overlay_read(lostio_filehandle_t*,void*,size_t,size_t);
> +size_t overlay_write(lostio_filehandle_t*,size_t,size_t,void*);
> +int    overlay_seek(lostio_filehandle_t* fh, uint64_t offset, int origin);
> +int    overlay_close(lostio_filehandle_t*);
> +
> +#define TYPEHANDLE_OVERLAY 255
> +
> +typehandle_t th_overlay = {
> +    .id             = TYPEHANDLE_OVERLAY,
> +    .post_open      = overlay_post_open,
> +    .seek           = overlay_seek,
> +    .read           = overlay_read,
> +    .write          = overlay_write,
> +    .seek           = overlay_seek,
> +    .close          = overlay_close,
> +};
> +
> +typedef enum {
> +    OVERLAY_READ_CACHE,
> +    OVERLAY_COW,
> +} cache_t;
> +
> +struct overlay {
> +    size_t      backing_size;
> +    void**      blocks;
> +    cache_t     type;
> +};
> +
> +int main(int argc, char* argv[])
> +{
> +    lostio_init();
> +    lostio_type_directory_use();
> +
> +    lostio_register_typehandle(&th_overlay);
> +
> +    vfstree_create_node("/cached", TYPEHANDLE_OVERLAY, 0,
> +        (void*) OVERLAY_READ_CACHE, LOSTIO_FLAG_NOAUTOEOF);
> +    vfstree_create_node("/cow", TYPEHANDLE_OVERLAY, 0,
> +        (void*) OVERLAY_COW, LOSTIO_FLAG_NOAUTOEOF);
> +
> +    init_service_register("ramoverlay");
> +
> +    while(1) {
> +        wait_for_rpc();
> +    }
> +}
> +
> +void overlay_post_open(lostio_filehandle_t* fh)
> +{
> +    size_t backing_size;
> +    struct overlay* overlay;
> +    size_t num_blocks;
> +    void** blocks;
> +
> +    // Groesse der unterliegenden Datei
> +    fseek(fh->source, 0, SEEK_END);
> +    backing_size = ftell(fh->source);
> +    fseek(fh->source, 0, SEEK_SET);
> +
> +    // Blocktabelle anlegen
> +    num_blocks = (backing_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
> +    blocks = calloc(sizeof(void*), num_blocks);
> +
> +    // Overlay-Strukur anlegen
> +    overlay = calloc(1, sizeof(*overlay));
> +    overlay->backing_size = backing_size;
> +    overlay->blocks = blocks;
> +    overlay->type = (cache_t) fh->node->data;
> +
> +    fh->data = overlay;
> +}
> +
> +size_t overlay_read(lostio_filehandle_t* fh, void* buf, size_t bs, size_t nb)
> +{
> +    struct overlay* overlay = fh->data;
> +    size_t blocknum;
> +    void*  block;
> +    size_t size, max_size;
> +
> +    // Blockpointer raussuchen
> +    blocknum = fh->pos / BLOCK_SIZE;
> +    block = overlay->blocks[blocknum];

Hm ist das nicht unter Umständen ein overflow? Also ich denke jetzt an
den Fall wenn fh->pos == overlay->backing_size...

> +
> +    // Die Requestgroesse darf keine Blockgrenzen ueberschreiten

Hat das einen tieferen Grund, oder war das nur faulheit und du wollest
unten keine schleife machen? ;-)
Ah ich sehe grad dass die Blokgroesse recht grosszügig gewählt wurde, da
funktioniert wohl das Argument mit den gesparten RPCs nur bedingt... ;-)

> +    size = bs * nb;
> +    max_size = BLOCK_SIZE - (fh->pos % BLOCK_SIZE);
> +
> +    if (size > max_size) {
> +        size = max_size;
> +    }
> +
> +    if (fh->pos + size > overlay->backing_size) {
> +        size = overlay->backing_size - fh->pos;
> +    }
> +
> +    // Wenn der Lesecache aktiviert ist, ganzen Block laden
> +    if ((block == NULL) && (overlay->type == OVERLAY_READ_CACHE)) {
> +        int ret;
> +        block = overlay->blocks[blocknum] = malloc(BLOCK_SIZE);
> +        fseek(fh->source, blocknum * BLOCK_SIZE, SEEK_SET);
> +        ret = fread(block, 1, BLOCK_SIZE, fh->source);
> +        if (ret != BLOCK_SIZE) {
> +            return -1;

Hm ob das gut kommt mit der -1 als size_t? Ich bin mir nicht ganz sicher
was dabei rauskommen müsste, aber ich tippe auf einen OOM, zumindest
wenn kein SHM benutzt wird zum lesen, und er dann ((size_t) -1) Bytes
zuruecksenden moechte. Da wäre wohl 0 die richtige Wahl (plus natürlich
das imaginäre Flag für ferror() *hust*).


> +        }
> +    }
> +
> +    // Daten lesen
> +    if (block == NULL) {
> +        fseek(fh->source, fh->pos, SEEK_SET);
> +        size = fread(buf, 1, size, fh->source);
> +    } else {
> +        memcpy(buf, ((uint8_t*) block) + (fh->pos % BLOCK_SIZE), size);
> +

Oha, wichtige Leerzeile ;-)

> +    }
> +
> +    if (size > 0) {

Hm, das if ist doch nur bedingt sinnvoll, size ist unsigned, also geht
doch nur noch die alternative size == 0, und das dürfte ja fh->pos nicht
speziell beeindrucken...

> +        fh->pos += size;
> +    }
> +
> +    // EOF setzen, falls noetig
> +    if (fh->pos >= overlay->backing_size) {
> +        fh->flags |= LOSTIO_FLAG_EOF;
> +    }
> +
> +    return size;
> +}
> +
> +size_t overlay_write(lostio_filehandle_t* fh,size_t bs,size_t nb, void* buf)
> +{
> +    struct overlay* overlay = fh->data;
> +    size_t blocknum;
> +    void*  block;
> +    size_t size, max_size;
> +    size_t ret;
> +
> +    // Blockpointer raussuchen
> +    blocknum = fh->pos / BLOCK_SIZE;
> +    block = overlay->blocks[blocknum];
> +
> +    // Die Requestgroesse darf keine Blockgrenzen ueberschreiten
> +    size = bs * nb;
> +    max_size = BLOCK_SIZE - (fh->pos % BLOCK_SIZE);
> +
> +    if (size > max_size) {
> +        size = max_size;
> +    }
> +
> +    if (fh->pos + size > overlay->backing_size) {
> +        size = overlay->backing_size - fh->pos;
> +    }
> +
> +    // Copy on Write
> +    if (block == NULL) {
> +        size_t offset;
> +
> +        block = overlay->blocks[blocknum] = malloc(BLOCK_SIZE);
> +
> +        offset = fh->pos % BLOCK_SIZE;
> +        if (offset) {
> +            fseek(fh->source, fh->pos, SEEK_SET);
> +            ret = fread(block, 1, offset, fh->source);
> +            if (ret != offset) {
> +                return -1;

Auch hier wieder eine -1, die dürfte aber diesmal nur die Aufrufer
verwirren, wenn der Rueckgabewert von fwrite groesser ist als erwartet.

> +            }
> +        }
> +
> +        offset = (fh->pos + size) % BLOCK_SIZE;
> +        if (offset < BLOCK_SIZE) {
> +            fseek(fh->source, fh->pos + offset, SEEK_SET);
> +            ret = fread(((uint8_t*) block) + offset, 1, BLOCK_SIZE - offset,
> +                fh->source);
> +            if (ret != BLOCK_SIZE - offset) {
> +                return -1;

Und nochmal.

> +            }
> +        }
> +    }
> +
> +    // Daten schreiben
> +    memcpy(((uint8_t*) block) + (fh->pos % BLOCK_SIZE), buf, size);
> +
> +    if (size > 0) {

Hier wärs wohl nochmal das selbe wie in read oben.

> +        fh->pos += size;
> +    }
> +
> +    return size;
> +}
> +
> +int overlay_seek(lostio_filehandle_t* fh, uint64_t offset, int origin)
> +{
> +    struct overlay* overlay = fh->data;
> +    uint64_t new_pos = fh->pos;
> +    uint64_t size = overlay->backing_size;
> +
> +    switch (origin)  {
> +        case SEEK_SET:
> +            new_pos = offset;
> +            break;
> +
> +        case SEEK_CUR:
> +            new_pos += offset;
> +            break;
> +
> +        case SEEK_END:
> +            new_pos = size;
> +            break;
> +    }
> +
> +    // Position nur aktualisieren, wenn sie nicht ausserhalb des Datentraegers
> +    // liegt.
> +    if (new_pos > size) {
> +        return -1;
> +    } else if (new_pos == size) {
> +        // Gegebenen Falles noch EOF setzen
> +        fh->flags |= LOSTIO_FLAG_EOF;
> +    } else {
> +        // Sonst EOF loeschen
> +        fh->flags &= ~LOSTIO_FLAG_EOF;
> +    }
> +    fh->pos = new_pos;
> +    return 0;
> +}
> +
> +int overlay_close(lostio_filehandle_t* fh)
> +{
> +    struct overlay* overlay = fh->data;
> +    size_t i;
> +
> +    for (i = (overlay->backing_size - 1) / BLOCK_SIZE; i > 0; i--)

Hm erwischst du da den ersten block auch? Und gibts da einen Grund,
warum das rückwärts sein muss? ;-)

> +    {
> +        free(overlay->blocks[i]);
> +    }
> +
> +    free(overlay->blocks);
> +    free(overlay);
> +
> +    return 0;
> +}

Sonst sieht das vernünftig aus, glaube ich... ;-)

-- 
Antoine Kaufmann
<toni@xxxxxxxxxxxxxxxx>

Attachment: pgpe9dzGHVhqR.pgp
Description: PGP signature