diff -uNr rrdtool-trunk-02/src/rrd.h rrdtool-trunk-03/src/rrd.h
--- rrdtool-trunk-02/src/rrd.h	2008-10-17 10:39:42.000000000 +0100
+++ rrdtool-trunk-03/src/rrd.h	2008-10-17 14:58:11.000000000 +0100
@@ -78,10 +78,12 @@
 /* END rrd_format.h */
 
 /* information about an rrd file */
+    struct rrd_vfs_t;
     typedef struct rrd_file_t {
         off_t     header_len;   /* length of the header of this rrd file */
         off_t     file_len; /* total size of the rrd file */
         off_t     pos;  /* current pos in file */
+        struct rrd_vfs_t *vfs;
         void      *pvt;
     } rrd_file_t;
 
@@ -347,44 +349,76 @@
     unsigned rdwr)
               RRD_DEPRECATED;
 
-    void      rrd_dontneed(
+/* Macros that delegate function calls to the virtual
+   filesystem/block driver implementation, so that existing
+   code need not be changed immediately */
+#define rrd_lock(rrd_file) rrd_file->vfs->lock(rrd_file)
+#define rrd_dontneed(rrd_file, rrd) \
+    rrd_file->vfs->dontneed(rrd_file, rrd)
+#define rrd_close(rrd_file) rrd_file->vfs->close(rrd_file)
+#define rrd_seek(rrd_file, off, whence) \
+    rrd_file->vfs->seek(rrd_file, off, whence)
+#define rrd_tell(rrd_file) rrd_file->vfs->tell(rrd_file)
+#define rrd_read(rrd_file, buf, count) \
+    rrd_file->vfs->read(rrd_file, buf, count)
+#define rrd_write(rrd_file, buf, count) \
+    rrd_file->vfs->write(rrd_file, buf, count)
+#define rrd_flush(rrd_file) rrd_file->vfs->flush(rrd_file)
+#define rrd_notify_row(rrd_file, rra_idx, rra_row, rra_time) \
+    rrd_file->vfs->notify_row(rrd_file, rra_idx, rra_row, rra_time)
+#define rrd_select_initial_row(rrd_file, rra_idx, rra) \
+    rrd_file->vfs->select_initial_row(rrd_file, rra_idx, rra)
+
+/* These functions are the default/traditional implementation, based
+   on use of the C library and/or mmap API for access to individual
+   RRD files on disk */
+
+    rrd_file_t *rrd_simple_open_impl(
+    rrd_file_t *rrd_file,
+    const char *const file_name,
+    rrd_t *rrd,
+    unsigned rdwr,
+    off_t file_size)
+              RRD_DEPRECATED;
+
+    void      rrd_simple_dontneed(
     rrd_file_t *rrd_file,
     rrd_t *rrd)
               RRD_DEPRECATED;
-    int       rrd_close(
+    int       rrd_simple_close(
     rrd_file_t *rrd_file)
               RRD_DEPRECATED;
-    ssize_t   rrd_read(
+    ssize_t   rrd_simple_read(
     rrd_file_t *rrd_file,
     void *buf,
     size_t count)
               RRD_DEPRECATED;
-    ssize_t   rrd_write(
+    ssize_t   rrd_simple_write(
     rrd_file_t *rrd_file,
     const void *buf,
     size_t count)
               RRD_DEPRECATED;
-    void      rrd_flush(
+    void      rrd_simple_flush(
     rrd_file_t *rrd_file)
               RRD_DEPRECATED;
-    off_t     rrd_seek(
+    off_t     rrd_simple_seek(
     rrd_file_t *rrd_file,
     off_t off,
     int whence)
               RRD_DEPRECATED;
-    off_t     rrd_tell(
+    off_t     rrd_simple_tell(
     rrd_file_t *rrd_file)
               RRD_DEPRECATED;
-    int       rrd_lock(
+    int       rrd_simple_lock(
     rrd_file_t *file)
               RRD_DEPRECATED;
-    void      rrd_notify_row(
+    void      rrd_simple_notify_row(
     rrd_file_t *rrd_file,
     int rra_idx,
     unsigned long rra_row,
     time_t rra_time)
               RRD_DEPRECATED;
-    unsigned long rrd_select_initial_row(
+    unsigned long rrd_simple_select_initial_row(
     rrd_file_t *rrd_file,
     int rra_idx,
     rra_def_t *rra
diff -uNr rrdtool-trunk-02/src/rrd_open.c rrdtool-trunk-03/src/rrd_open.c
--- rrdtool-trunk-02/src/rrd_open.c	2008-10-17 11:01:54.000000000 +0100
+++ rrdtool-trunk-03/src/rrd_open.c	2008-10-17 15:25:58.000000000 +0100
@@ -10,6 +10,31 @@
 #include "unused.h"
 #define MEMBLK 8192
 
+
+static rrd_vfs_t vfs_implementations[] = {
+
+    /* The traditional implementation, each RRD file is a real file on disk */
+    {
+        "",
+        rrd_simple_open_impl,
+        rrd_simple_close,
+        rrd_simple_dontneed,
+        rrd_simple_seek,
+        rrd_simple_tell,
+        rrd_simple_read,
+        rrd_simple_write,
+        rrd_simple_flush,
+        rrd_simple_lock,
+        rrd_simple_select_initial_row,
+        rrd_simple_notify_row
+        /* rrd_simple_free */
+    },
+
+    /* End of variable-length array */
+    { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+
 /* DEBUG 2 prints information obtained via mincore(2) */
 #define DEBUG 1
 /* do not calculate exact madvise hints but assume 1 page for headers and
@@ -17,20 +42,6 @@
 /* Avoid calling madvise on areas that were already hinted. May be benefical if
  * your syscalls are very slow */
 
-#ifdef HAVE_MMAP
-/* the cast to void* is there to avoid this warning seen on ia64 with certain
-   versions of gcc: 'cast increases required alignment of target type'
-*/
-#define __rrd_read(dst, dst_t, cnt) { \
-	size_t wanted = sizeof(dst_t)*(cnt); \
-	if (offset + wanted > rrd_file->file_len) { \
-		rrd_set_error("reached EOF while loading header " #dst); \
-		goto out_nullify_head; \
-	} \
-	(dst) = (dst_t*)(void*) (data + offset); \
-	offset += wanted; \
-    }
-#else
 #define __rrd_read(dst, dst_t, cnt) { \
 	size_t wanted = sizeof(dst_t)*(cnt); \
         size_t got; \
@@ -38,14 +49,13 @@
 		rrd_set_error(#dst " malloc"); \
 		goto out_nullify_head; \
 	} \
-        got = read (rrd_simple_file->fd, dst, wanted); \
+        got = rrd_file->vfs->read (rrd_file, dst, wanted); \
 	if (got != wanted) { \
 		rrd_set_error("short read while reading header " #dst); \
                 goto out_nullify_head; \
 	} \
 	offset += got; \
     }
-#endif
 
 /* get the address of the start of this page */
 #if defined USE_MADVISE || defined HAVE_POSIX_FADVISE
@@ -58,6 +68,22 @@
     rra_def_t *);
 
 
+/* Choose a VFS for a particular filename,
+   return NULL if no VFS matches */
+rrd_vfs_t *rrd_choose_vfs(
+    const char *const file_name)
+{
+    rrd_vfs_t *p = vfs_implementations;
+    while (p != NULL)
+    {
+        if(strncmp(file_name, p->prefix, strlen(p->prefix))==0)
+            return p;
+        p++;
+    }
+    return NULL;
+}
+
+
 /* Open a database file, return its header and an open filehandle,
  * positioned to the first cdp in the first rra.
  * In the error path of rrd_open, only rrd_free(&rrd) has to be called
@@ -68,55 +94,27 @@
  * rrd_init(rrd) prior to invoking rrd_open
  */
 
-rrd_file_t *rrd_open(
+rrd_file_t *rrd_simple_open_impl(
+    rrd_file_t *rrd_file,
     const char *const file_name,
     rrd_t *rrd,
-    unsigned rdwr)
+    unsigned rdwr,
+    off_t file_size)
 {
-    int i;
     int       flags = 0;
     mode_t    mode = S_IRUSR;
-    int       version;
 
 #ifdef HAVE_MMAP
     ssize_t   _page_size = sysconf(_SC_PAGESIZE);
     char     *data = MAP_FAILED;
 #endif
+    off_t     newfile_size = 0;
     off_t     offset = 0;
     struct stat statb;
-    rrd_file_t *rrd_file = NULL;
     rrd_simple_file_t *rrd_simple_file = NULL;
-    off_t     newfile_size = 0;
-    off_t header_len, value_cnt, data_len;
 
-    /* Are we creating a new file? */
-    if((rdwr & RRD_CREAT) && (rrd->stat_head != NULL))
-    {
-        header_len = \
-          sizeof(stat_head_t) + \
-          sizeof(ds_def_t) * rrd->stat_head->ds_cnt + \
-          sizeof(rra_def_t) * rrd->stat_head->rra_cnt + \
-          sizeof(time_t) + \
-          sizeof(live_head_t) + \
-          sizeof(pdp_prep_t) * rrd->stat_head->ds_cnt + \
-          sizeof(cdp_prep_t) * rrd->stat_head->ds_cnt * rrd->stat_head->rra_cnt + \
-          sizeof(rra_ptr_t) * rrd->stat_head->rra_cnt;
-
-        value_cnt = 0;
-        for (i = 0; i < rrd->stat_head->rra_cnt; i++)
-            value_cnt += rrd->stat_head->ds_cnt * rrd->rra_def[i].row_cnt;
-
-        data_len = sizeof(rrd_value_t) * value_cnt;
-
-        newfile_size = header_len + data_len;
-    }
-    
-    rrd_file = malloc(sizeof(rrd_file_t));
-    if (rrd_file == NULL) {
-        rrd_set_error("allocating rrd_file descriptor for '%s'", file_name);
-        return NULL;
-    }
-    memset(rrd_file, 0, sizeof(rrd_file_t));
+    if(rdwr & RRD_CREAT)
+        newfile_size = file_size;
 
     rrd_file->pvt = malloc(sizeof(rrd_simple_file_t));
     if(rrd_file->pvt == NULL) {
@@ -126,15 +124,6 @@
     memset(rrd_file->pvt, 0, sizeof(rrd_simple_file_t));
     rrd_simple_file = (rrd_simple_file_t *)rrd_file->pvt;
 
-#ifdef DEBUG
-    if ((rdwr & (RRD_READONLY | RRD_READWRITE)) ==
-        (RRD_READONLY | RRD_READWRITE)) {
-        /* Both READONLY and READWRITE were given, which is invalid.  */
-        rrd_set_error("in read/write request mask");
-        exit(-1);
-    }
-#endif
-
 #ifdef HAVE_MMAP
     rrd_simple_file->mm_prot = PROT_READ;
     rrd_simple_file->mm_flags = 0;
@@ -240,9 +229,96 @@
         madvise(data, sizeof(stat_head_t), MADV_WILLNEED | MADV_RANDOM);
     }
 #endif
+   
+    out_done:
+        return (rrd_file);
+    out_nullify_head:
+        rrd->stat_head = NULL;
+    out_close:
+#ifdef HAVE_MMAP
+        if (data != MAP_FAILED)
+            munmap(data, rrd_file->file_len);
+#endif
+        close(rrd_simple_file->fd);
+    out_free:
+        free(rrd_file->pvt);
+        free(rrd_file);
+        return NULL;
+
+
+}
+
+/* Open a database file, return its header and an open filehandle,
+ * positioned to the first cdp in the first rra.
+ * In the error path of rrd_open, only rrd_free(&rrd) has to be called
+ * before returning an error. Do not call rrd_close upon failure of rrd_open.
+ */
+rrd_file_t *rrd_open(
+    const char *const file_name,
+    rrd_t *rrd,
+    unsigned rdwr)
+{
+    rrd_file_t *rrd_file = NULL;
+
+    off_t     offset = 0;
+    off_t     newfile_size = 0;
+    off_t header_len, value_cnt, data_len;
+    int       version;
+    int       i;
+
+    /* Are we creating a new file? */
+    if((rdwr & RRD_CREAT) && (rrd->stat_head != NULL))
+    {
+        header_len = \
+          sizeof(stat_head_t) + \
+          sizeof(ds_def_t) * rrd->stat_head->ds_cnt + \
+          sizeof(rra_def_t) * rrd->stat_head->rra_cnt + \
+          sizeof(time_t) + \
+          sizeof(live_head_t) + \
+          sizeof(pdp_prep_t) * rrd->stat_head->ds_cnt + \
+          sizeof(cdp_prep_t) * rrd->stat_head->ds_cnt * rrd->stat_head->rra_cnt + \
+          sizeof(rra_ptr_t) * rrd->stat_head->rra_cnt;
+
+        value_cnt = 0;
+        for (i = 0; i < rrd->stat_head->rra_cnt; i++)
+            value_cnt += rrd->stat_head->ds_cnt * rrd->rra_def[i].row_cnt;
+
+        data_len = sizeof(rrd_value_t) * value_cnt;
+
+        newfile_size = header_len + data_len;
+    }
+
+    rrd_file = malloc(sizeof(rrd_file_t));
+    if (rrd_file == NULL) {
+        rrd_set_error("allocating rrd_file descriptor for '%s'", file_name);
+        return NULL;
+    }
+    memset(rrd_file, 0, sizeof(rrd_file_t));
+
+#ifdef DEBUG
+    if ((rdwr & (RRD_READONLY | RRD_READWRITE)) ==
+        (RRD_READONLY | RRD_READWRITE)) {
+        /* Both READONLY and READWRITE were given, which is invalid.  */
+        rrd_set_error("in read/write request mask");
+        exit(-1);
+    }
+#endif
 
-    __rrd_read(rrd->stat_head, stat_head_t,
-               1);
+    if((rrd_file->vfs = rrd_choose_vfs(file_name))==NULL)
+    {
+        rrd_set_error("no VFS found for '%s'", file_name);
+        goto out_free;
+    }
+
+    if(rrd_file->vfs->open_impl(rrd_file, file_name, rrd, rdwr, newfile_size) == NULL)
+    {
+        goto out_free;
+    }
+
+    if(rdwr & RRD_CREAT)
+        goto out_done;
+
+    __rrd_read(rrd->stat_head, stat_head_t, 1);
 
     /* lets do some test if we are on track ... */
     if (memcmp(rrd->stat_head->cookie, RRD_COOKIE, sizeof(RRD_COOKIE)) != 0) {
@@ -262,21 +338,10 @@
                       rrd->stat_head->version);
         goto out_nullify_head;
     }
-#if defined USE_MADVISE
-    /* the ds_def will be needed soonish, so hint accordingly */
-    madvise(data + PAGE_START(offset),
-            sizeof(ds_def_t) * rrd->stat_head->ds_cnt, MADV_WILLNEED);
-#endif
-    __rrd_read(rrd->ds_def, ds_def_t,
-               rrd->stat_head->ds_cnt);
-
-#if defined USE_MADVISE
-    /* the rra_def will be needed soonish, so hint accordingly */
-    madvise(data + PAGE_START(offset),
-            sizeof(rra_def_t) * rrd->stat_head->rra_cnt, MADV_WILLNEED);
-#endif
-    __rrd_read(rrd->rra_def, rra_def_t,
-               rrd->stat_head->rra_cnt);
+
+    __rrd_read(rrd->ds_def, ds_def_t, rrd->stat_head->ds_cnt);
+
+    __rrd_read(rrd->rra_def, rra_def_t, rrd->stat_head->rra_cnt);
 
     /* handle different format for the live_head */
     if (version < 3) {
@@ -285,30 +350,17 @@
             rrd_set_error("live_head_t malloc");
             goto out_close;
         }
-#if defined USE_MADVISE
-        /* the live_head will be needed soonish, so hint accordingly */
-        madvise(data + PAGE_START(offset), sizeof(time_t), MADV_WILLNEED);
-#endif
-        __rrd_read(rrd->legacy_last_up, time_t,
-                   1);
+        __rrd_read(rrd->legacy_last_up, time_t, 1);
 
         rrd->live_head->last_up = *rrd->legacy_last_up;
         rrd->live_head->last_up_usec = 0;
     } else {
-#if defined USE_MADVISE
-        /* the live_head will be needed soonish, so hint accordingly */
-        madvise(data + PAGE_START(offset),
-                sizeof(live_head_t), MADV_WILLNEED);
-#endif
-        __rrd_read(rrd->live_head, live_head_t,
-                   1);
-    }
-    __rrd_read(rrd->pdp_prep, pdp_prep_t,
-               rrd->stat_head->ds_cnt);
-    __rrd_read(rrd->cdp_prep, cdp_prep_t,
-               rrd->stat_head->rra_cnt * rrd->stat_head->ds_cnt);
-    __rrd_read(rrd->rra_ptr, rra_ptr_t,
-               rrd->stat_head->rra_cnt);
+        __rrd_read(rrd->live_head, live_head_t, 1);
+    }
+    __rrd_read(rrd->pdp_prep, pdp_prep_t, rrd->stat_head->ds_cnt);
+    __rrd_read(rrd->cdp_prep, cdp_prep_t, 
+        rrd->stat_head->rra_cnt * rrd->stat_head->ds_cnt);
+    __rrd_read(rrd->rra_ptr, rra_ptr_t, rrd->stat_head->rra_cnt);
 
     rrd_file->header_len = offset;
     rrd_file->pos = offset;
@@ -336,72 +388,20 @@
   out_nullify_head:
     rrd->stat_head = NULL;
   out_close:
-#ifdef HAVE_MMAP
-    if (data != MAP_FAILED)
-      munmap(data, rrd_file->file_len);
-#endif
-    close(rrd_simple_file->fd);
+    rrd_file->vfs->close(rrd_file);
+    return NULL;
   out_free:
-    free(rrd_file->pvt);
     free(rrd_file);
     return NULL;
 }
 
-
-#if defined DEBUG && DEBUG > 1
-/* Print list of in-core pages of a the current rrd_file.  */
-static
-void mincore_print(
-    rrd_file_t *rrd_file,
-    char *mark)
-{
-    rrd_simple_file_t *rrd_simple_file;
-    rrd_simple_file = (rrd_simple_file_t *)rrd_file->pvt;
-#ifdef HAVE_MMAP
-    /* pretty print blocks in core */
-    off_t     off;
-    unsigned char *vec;
-    ssize_t   _page_size = sysconf(_SC_PAGESIZE);
-
-    off = rrd_file->file_len +
-        ((rrd_file->file_len + _page_size - 1) / _page_size);
-    vec = malloc(off);
-    if (vec != NULL) {
-        memset(vec, 0, off);
-        if (mincore(rrd_simple_file->file_start, rrd_file->file_len, vec) == 0) {
-            int       prev;
-            unsigned  is_in = 0, was_in = 0;
-
-            for (off = 0, prev = 0; off < rrd_file->file_len; ++off) {
-                is_in = vec[off] & 1;   /* if lsb set then is core resident */
-                if (off == 0)
-                    was_in = is_in;
-                if (was_in != is_in) {
-                    fprintf(stderr, "%s: %sin core: %p len %ld\n", mark,
-                            was_in ? "" : "not ", vec + prev, off - prev);
-                    was_in = is_in;
-                    prev = off;
-                }
-            }
-            fprintf(stderr,
-                    "%s: %sin core: %p len %ld\n", mark,
-                    was_in ? "" : "not ", vec + prev, off - prev);
-        } else
-            fprintf(stderr, "mincore: %s", rrd_strerror(errno));
-    }
-#else
-    fprintf(stderr, "sorry mincore only works with mmap");
-#endif
-}
-#endif                          /* defined DEBUG && DEBUG > 1 */
-
 /*
  * get exclusive lock to whole file.
  * lock gets removed when we close the file
  *
  * returns 0 on success
  */
-int rrd_lock(
+int rrd_simple_lock(
     rrd_file_t *rrd_file)
 {
     int       rcstat;
@@ -434,7 +434,7 @@
 
 
 /* drop cache except for the header and the active pages */
-void rrd_dontneed(
+void rrd_simple_dontneed(
     rrd_file_t *rrd_file,
     rrd_t *rrd)
 {
@@ -512,7 +512,7 @@
 
 
 
-int rrd_close(
+int rrd_simple_close(
     rrd_file_t *rrd_file)
 {
     rrd_simple_file_t *rrd_simple_file;
@@ -539,7 +539,7 @@
 
 /* Set position of rrd_file.  */
 
-off_t rrd_seek(
+off_t rrd_simple_seek(
     rrd_file_t *rrd_file,
     off_t off,
     int whence)
@@ -568,7 +568,7 @@
 
 /* Get current position in rrd_file.  */
 
-off_t rrd_tell(
+off_t rrd_simple_tell(
     rrd_file_t *rrd_file)
 {
     return rrd_file->pos;
@@ -578,7 +578,7 @@
 /* Read count bytes into buffer buf, starting at rrd_file->pos.
  * Returns the number of bytes read or <0 on error.  */
 
-ssize_t rrd_read(
+ssize_t rrd_simple_read(
     rrd_file_t *rrd_file,
     void *buf,
     size_t count)
@@ -617,7 +617,7 @@
  * rrd_file->pos of rrd_simple_file->fd.
  * Returns the number of bytes written or <0 on error.  */
 
-ssize_t rrd_write(
+ssize_t rrd_simple_write(
     rrd_file_t *rrd_file,
     const void *buf,
     size_t count)
@@ -650,7 +650,7 @@
 
 /* flush all data pending to be written to FD.  */
 
-void rrd_flush(
+void rrd_simple_flush(
     rrd_file_t *rrd_file)
 {
     rrd_simple_file_t *rrd_simple_file;
@@ -681,15 +681,6 @@
 
 /* free RRD header data.  */
 
-#ifdef HAVE_MMAP
-void rrd_free(
-    rrd_t *rrd)
-{
-    if (rrd->legacy_last_up) {  /* this gets set for version < 3 only */
-        free(rrd->live_head);
-    }
-}
-#else
 void rrd_free(
     rrd_t *rrd)
 {
@@ -702,7 +693,6 @@
     free(rrd->cdp_prep);
     free(rrd->rrd_value);
 }
-#endif
 
 
 /* routine used by external libraries to free memory allocated by
@@ -719,7 +709,7 @@
  * The low level storage API may use this information for
  * aligning RRAs within stripes, or other performance enhancements
  */
-void rrd_notify_row(
+void rrd_simple_notify_row(
     rrd_file_t *rrd_file,
     int rra_idx,
     unsigned long rra_row,
@@ -734,7 +724,7 @@
  * The default implementation is random, to ensure that all RRAs
  * don't change to a new disk block at the same time
  */
-unsigned long rrd_select_initial_row(
+unsigned long rrd_simple_select_initial_row(
     rrd_file_t *rrd_file,
     int rra_idx,
     rra_def_t *rra
diff -uNr rrdtool-trunk-02/src/rrd_tool.h rrdtool-trunk-03/src/rrd_tool.h
--- rrdtool-trunk-02/src/rrd_tool.h	2008-10-17 10:18:23.000000000 +0100
+++ rrdtool-trunk-03/src/rrd_tool.h	2008-10-17 14:16:03.000000000 +0100
@@ -58,6 +58,7 @@
 #endif
 
 #include "rrd_format.h"
+#include "rrd_vfs.h"
 
 #ifndef max
 #define max(a,b) ((a) > (b) ? (a) : (b))
diff -uNr rrdtool-trunk-02/src/rrd_vfs.h rrdtool-trunk-03/src/rrd_vfs.h
--- rrdtool-trunk-02/src/rrd_vfs.h	1970-01-01 01:00:00.000000000 +0100
+++ rrdtool-trunk-03/src/rrd_vfs.h	2008-10-17 14:58:50.000000000 +0100
@@ -0,0 +1,68 @@
+/*****************************************************************************
+ * RRDtool 1.3.2  Copyright by Tobi Oetiker, 1997-2008
+ *                Virtual filesystem contribution copyright Daniel Pocock 2008
+ *****************************************************************************
+ * rrd_vfs.h     RRD virtual filesystems
+ *****************************************************************************/
+
+#ifndef _RRD_FS_H
+#define _RRD_FS_H
+
+/* 
+ * _RRD_TOOL_H
+ *   We're building RRDTool itself.
+ *
+ * RRD_EXPORT_DEPRECATED
+ *   User is requesting internal function which need this struct. They have
+ *   been told that this will change and have agreed to adapt their programs.
+ */
+#if !defined(_RRD_TOOL_H) && !defined(RRD_EXPORT_DEPRECATED)
+# error "Do not include rrd_format.h directly. Include rrd.h instead!"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "rrd.h"
+
+
+typedef struct rrd_vfs_t {
+    /* The filename prefix that this VFS handles */
+    const char *prefix;
+
+    /* Open/create the file
+       The pathname passed to open includes the prefix.
+       This method gets invoked by rrd_open from rrd_open.c, 
+       which is responsible for any generic initialisation tasks.
+    */
+    rrd_file_t *(*open_impl)(rrd_file_t *rrd_file, 
+        const char *const file_name, rrd_t *rrd, unsigned rdwr, 
+        off_t file_size);
+
+    int (*close)(rrd_file_t *rrd_file);
+
+    void (*dontneed)(rrd_file_t *rrd_file, rrd_t *rrd);
+
+    off_t (*seek)(rrd_file_t *rrd_file, off_t off, int whence);
+    off_t (*tell)(rrd_file_t *rrd_file);
+
+    ssize_t (*read)(rrd_file_t *rrd_file, void *buf, size_t count);
+    ssize_t (*write)(rrd_file_t *rrd_file, const void *buf, size_t count);
+
+    void (*flush)(rrd_file_t *rrd_file);
+
+    int (*lock)(rrd_file_t *rrd_file);
+
+    unsigned long (*select_initial_row)(rrd_file_t *rrd_file,
+        int rra_idx, rra_def_t *rra);
+    void (*notify_row)(rrd_file_t *rrd_file, int rra_idx,
+        unsigned long rra_row, time_t rra_time); 
+
+    /* void (*rrd_free)(void *mem); */
+  
+} rrd_vfs_t;
+
+
+#endif
+
