Re: [AVFS] resurrection of AVFS

Miklos Szeredi <[email protected]> Mon, 28 Feb 2005 13:56:13 +0100
Newsgroups gmane.comp.file-systems.avfs.user
Message-ID <[email protected]>
> Source code is nearly uncommented :( No tutorial, no API
> documentation, this situation could not attract more developers to
> use this library in their projects. I could write a basic tutorial
> with examples of use with some help from you.  Investigating
> runtest.c is a good start point, are there more examples anywhere
> else?

Libavfs is mainly used by 'avfscoda' and 'preload' neither of which is
a very good example.

> Well, as an API I could count functions from "virtual.h". Correct me
> if I'm wrong.  There is no documentation but functions from
> virtual.h seem s to behave like their libc counterpards. Function
> virt_read() behaves like read() but with support for reading from
> archives, it takes the same arguments, it return the same error
> codes and so on.

Yes, that is how it's supposed to work.

> Can I use AVFS for reading ordinary (real) files from local?
> I hope I can.

Yes though there are problems with this (see discussion with Ralf
Hoffmann).

> How to set temporary directory for archive cache?

/tmp is used, and this can't be changed currently.  There's a patch by
Peter Kundrat that fixes this (attached), but there's a possible
buffer overflow in this, and I haven't yet integrated a fixed version.

> When is cache cleaned? Am I supposed to do it explicitly?
>     fd = virt_open("/#avfsstat/cache/clear", O_WRONLY, 0);
>     res = virt_write(fd, "1", 1);
>     res = virt_close(fd);
> ..striped function flush_cache() in runtest.c

Yes.  This is equivalent to "echo 1 > /#avfsstat/cache/clear"

> How you test archive change the situation someone copy file into the
> ZIP file.  In which sourcefile, which function I can foud it?  Is
> there something like 'dirty flag'?

The file modification time and other parameters are checked.  The
function is arch_same() in archive.c.

> Is some kind of server started to keep tracks of opened archives?
> (suppose using avfs as library, no avfscoda, preload or fuse)

No.  If you want to have persistent cache, then you must create a
server which uses libfuse, and client library which communicates with
the server.  Basically this is what preload does.

> >From sourcecode organisation it looks like AVFS comes in four flavour.
> - library (layer libary above some functions from glibc)
> - avfscoda
> - preload (overload some methods in libc/glibc, so applications use avfs transparetly without)
> - fuse module
> 
> In documentation only flavours 2 and 3 are mentioned!
> 
> >From further investigation of mail-lists - only flavour 1 is fully
> >operational now, flavours 2 - 4 seems not to be fully operational
> >(or not operational at all) in newer glibc and kernels (>2.6.x).

1 (libavfs) is system independent, and hence should work in any UNIX
like environment.

2 (avfscoda) works on 2.4 kernels, and there's an effort by Olivier
Valentin to make it work on 2.6 kernels too.  Attached his patch which
makes avfscoda compile under 2.6.

3 (avfs-preload) worked on older Solaris versions (I don't have a
Solaris machine anymore, so I can't test newer versions).

4 (avfs-fuse) works on 2.4 and 2.6, but is in an experimental state.

Thanks,
Miklos
avfs-tmpdir.patch (application/octet-stream, 1.2 KB)
diff -ur avfs-0.9.3.orig/avfscoda/dispatch.c avfs-0.9.3/avfscoda/dispatch.c
--- avfs-0.9.3.orig/avfscoda/dispatch.c	2001-10-24 11:51:25.000000000 +0200
+++ avfs-0.9.3/avfscoda/dispatch.c	2004-11-22 01:48:20.000000000 +0100
@@ -1301,10 +1301,13 @@
             open_file(req, of);
         }
         else {
-            char tmpname[64];
+            char tmpname[64], *tmp;
             int fd;
 			
-            strcpy(tmpname, "/tmp/.avfs_coda_XXXXXX");
+	    tmp = getenv("TMPDIR");
+	    if (!tmp)
+		tmp="/tmp";
+	    sprintf(tmpname, "%s/.avfs_coda_XXXXXX", tmp);
             fd = mkstemp(tmpname);
 			
             if(fd == -1) {
diff -ur avfs-0.9.3.orig/src/tmpfile.c avfs-0.9.3/src/tmpfile.c
--- avfs-0.9.3.orig/src/tmpfile.c	2001-12-26 19:12:23.000000000 +0100
+++ avfs-0.9.3/src/tmpfile.c	2004-11-22 01:45:45.000000000 +0100
@@ -115,9 +115,13 @@
   
     AV_LOCK(tmplock);
     if(tmpdir == NULL) {
-        char *path;
+        char *path, *tmp;
 
-        path = av_strdup("/tmp/.avfs_tmp_XXXXXX");
+	tmp = getenv("TMPDIR");
+	if (!tmp)
+	    tmp="/tmp";
+	sprintf(buf, "%s/.avfs_tmp_XXXXXX", tmp);
+        path = av_strdup(buf);
         res = make_tmp_dir(path);
         if(res < 0)
             av_free(path);
avfs-0.9.3-to-2.6-kernel-woRedir.patch (application/octet-stream, 8.7 KB)
diff -Naur ./avfscoda/avfscoda.h ../../avfs-0.9.3/avfscoda/avfscoda.h
--- ./avfscoda/avfscoda.h	2001-05-11 19:29:01.000000000 +0200
+++ ../../avfs-0.9.3/avfscoda/avfscoda.h	2005-02-08 10:43:09.000000000 +0100
@@ -14,6 +14,12 @@
     int path2size;
 };
 
+struct AvfsFid { /* maps the content of opaque CodaFid for Avfs */
+    u_int32_t Unused0;
+    u_int32_t Unused1;
+    u_int32_t Unused2;
+    u_int32_t Unique;
+};
 
 extern void run(int cfs, const char *codadir, int dm);
 extern void child_process(int infd, int outfd);
diff -Naur ./avfscoda/child.c ../../avfs-0.9.3/avfscoda/child.c
--- ./avfscoda/child.c	2001-10-24 11:51:24.000000000 +0200
+++ ../../avfs-0.9.3/avfscoda/child.c	2005-02-08 10:54:59.000000000 +0100
@@ -16,8 +16,8 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <pthread.h>
-
 #include <sys/stat.h>
+#include <signal.h>
 
 /* #include "KERNINCLUDE/linux/coda.h" */
 #include CODAINCLUDE
@@ -59,7 +59,7 @@
 }
 
 
-static void st2attr(struct stat *s, struct coda_vattr *a, ViceFid *id)
+static void st2attr(struct stat *s, struct coda_vattr *a, struct CodaFid *id)
 {
     memset(a, 0, sizeof(struct coda_vattr));
     a->va_type = st2type(s);
@@ -434,10 +434,12 @@
 	if(ret == -1) 
 	    rep->oh.result = errno;
 	else {
+        struct AvfsFid *id = (struct AvfsFid *)&rep->coda_lookup.VFid;
 	    /* We don't know these */
-	    rep->coda_lookup.VFid.Volume = 0;
-	    rep->coda_lookup.VFid.Vnode  = 0;
-	    rep->coda_lookup.VFid.Unique = 0; 
+	    id->Unused0 = 0;
+	    id->Unused1 = 0;
+	    id->Unused2 = 0;
+	    id->Unique = 0;
 	    rep->coda_lookup.vtype = st2type(&stbuf);
 	}
 	break;
diff -Naur ./avfscoda/dispatch.c ../../avfs-0.9.3/avfscoda/dispatch.c
--- ./avfscoda/dispatch.c	2001-10-24 11:51:25.000000000 +0200
+++ ../../avfs-0.9.3/avfscoda/dispatch.c	2005-02-08 10:43:11.000000000 +0100
@@ -98,6 +98,7 @@
     struct openfile *ofs;
 };
 
+
 #define FMAPSIZE 65536
 static struct fileinfo *fmap[FMAPSIZE];
 static unsigned int nextunique = 0;
@@ -319,13 +320,17 @@
     return fi;
 }
 
-static struct fileinfo *look_info(ViceFid *id)
+static struct fileinfo *look_info(struct CodaFid *cid)
 {
+    struct AvfsFid *id = (struct AvfsFid *)cid;
     struct fileinfo *fi;
 	
-    if ((id->Volume != 0) || (id->Vnode != 0)) {
-        logerr("Bad handle passed %lx/%lx/%lx\n", 
-            id->Volume, id->Vnode, id->Unique );
+    if ((id->Unused0 != 0) || (id->Unused1 != 0) || (id->Unused2 != 0)) {
+        logerr("Bad handle passed %lx/%lx/%lx/%lx\n", 
+            (long unsigned int)id->Unused0,
+            (long unsigned int)id->Unused1,
+            (long unsigned int)id->Unused2,
+            (long unsigned int)id->Unique );
         clean_exit(1);
     }
 	
@@ -345,7 +350,7 @@
     }
 }
 
-static char *look_name(ViceFid *id)
+static char *look_name(struct CodaFid *id)
 {
     struct fileinfo *fi;
 	
@@ -358,7 +363,7 @@
     return fi->path;
 }
 
-static void ref_fid(ViceFid *fid)
+static void ref_fid(struct CodaFid *fid)
 {
     struct fileinfo *fi = look_info(fid);
 
@@ -366,7 +371,7 @@
         fi->use ++;
 }
 
-static void unref_fid(ViceFid *fid)
+static void unref_fid(struct CodaFid *fid)
 {
     struct fileinfo *fi = look_info(fid);
 
@@ -398,9 +403,10 @@
     }
 }
 
-static struct fileinfo *create_file(const char *filename, ViceFid *parentid,
-                                    ViceFid *newid)
+static struct fileinfo *create_file(const char *filename, struct CodaFid *parentid,
+                                    struct CodaFid *newcid)
 {
+    struct AvfsFid *newid = (struct AvfsFid *)newcid;
     struct fileinfo *fi;
 
     fi = look_info(parentid);
@@ -408,8 +414,9 @@
         return NULL;
     fi = get_file(fi, filename);
 
-    newid->Volume = 0;
-    newid->Vnode = 0;
+    newid->Unused0 = 0;
+    newid->Unused1 = 0;
+    newid->Unused2 = 0;
     newid->Unique = fi->unique;
 
     return fi;
@@ -418,6 +425,7 @@
 static void purge_file(struct fileinfo *fi)
 {
     union outputArgs rep;
+    struct AvfsFid *id;
 
     log("=================================================================\n");
     log_date();
@@ -427,15 +435,18 @@
     rep.oh.opcode = CODA_PURGEFID;
     rep.oh.result = 0;
     rep.oh.unique = 0;
-    rep.coda_purgefid.CodaFid.Volume = 0;
-    rep.coda_purgefid.CodaFid.Vnode  = 0;
-    rep.coda_purgefid.CodaFid.Unique = fi->unique;
+    id = (struct AvfsFid *)&rep.coda_purgefid.CodaFid;
+    id->Unused0 = 0;
+    id->Unused1 = 0;
+    id->Unused2 = 0;
+    id->Unique = fi->unique;
     
     send_to_kernel(&rep, sizeof(rep.coda_purgefid));
 }
 
 static void zap_file(struct fileinfo *fi)
 {
+    struct AvfsFid *id;
     union outputArgs rep;
 
     log("=================================================================\n");
@@ -446,9 +457,11 @@
     rep.oh.opcode = CODA_ZAPFILE;
     rep.oh.result = 0;
     rep.oh.unique = 0;
-    rep.coda_zapfile.CodaFid.Volume = 0;
-    rep.coda_zapfile.CodaFid.Vnode  = 0;
-    rep.coda_zapfile.CodaFid.Unique = fi->unique;
+    id = (struct AvfsFid *)&rep.coda_zapfile.CodaFid;
+    id->Unused0 = 0;
+    id->Unused1 = 0;
+    id->Unused2 = 0;
+    id->Unique = fi->unique;
     
     send_to_kernel(&rep, sizeof(rep.coda_zapfile));
 }
@@ -582,7 +595,7 @@
 }
 
 static void close_file(struct openfile *of, struct openfile **ofp,
-                       ViceFid *fid)
+                       struct CodaFid *fid)
 {
     
     if(of->use > 0) of->use --;
@@ -681,7 +694,10 @@
         user->uid, user->gid, user->serverpid);
     log_date();
     log("%i (%i) bytes: opcode: %li, result: %i, unique: %li\n", 
-        numread, insize, rep->oh.opcode, (int) rep->oh.result, rep->oh.unique);
+        numread, insize,
+        (unsigned long int)rep->oh.opcode,
+        (unsigned int)rep->oh.result,
+        (unsigned long int)rep->oh.unique);
 	
     for(opp = &user->ops; *opp != NULL; opp = &(*opp)->next) 
         if((*opp)->req->ih.unique == rep->oh.unique) break;
@@ -691,7 +707,7 @@
     if(op == NULL)
         logerr("Operation not found!!!!\n");
     else {
-        log("Found operation: %li\n", op->req->ih.unique);
+        log("Found operation: %li\n", (unsigned long int)op->req->ih.unique);
 		
         switch(rep->oh.opcode) {
 #ifdef CODA_OPEN_BY_FD
@@ -819,7 +835,7 @@
     if(user->ops != NULL) {
         log("Remaining operations: ");
         for(op = user->ops; op != NULL; op = op->next)
-            log("%li ", op->req->ih.unique);
+            log("%li ", (unsigned long int)op->req->ih.unique);
         log("\n");
     }	
 }
@@ -1058,8 +1074,8 @@
 			  char *path2)
 {
     struct operation *op;
-    uid_t uid = req->ih.cred.cr_fsuid;
-    gid_t gid = req->ih.cred.cr_fsgid;
+    uid_t uid = req->ih.uid;
+    gid_t gid = req->ih.pgid;
     struct userinfo *user;
     int msgsize;
     struct child_message msg;
@@ -1109,7 +1125,7 @@
     memcpy(mp, req, msg.reqsize);
     mp += msg.reqsize;
 	
-    log("****** opcode: %li\n", req->ih.opcode);
+    log("****** opcode: %li\n", (unsigned long int)req->ih.opcode);
     log("****** msgsize: %i, msgoff: %i, msg.reqsize: %i, \n", 
         msgsize, msgoff, msg.reqsize);
 	
@@ -1140,7 +1156,7 @@
 }
 
 static void send_with_path(union inputArgs *req, int reqsize, char *filename,
-                           ViceFid *id, char *path2)
+                           struct CodaFid *id, char *path2)
 {
     char pathbuf[1024];
     struct fileinfo *fi;
@@ -1239,19 +1255,25 @@
     log("=================================================================\n");
     log_date();
     log("%i bytes: opcode: %li, unique: %li\n", 
-        numread, req->ih.opcode, req->ih.unique);
+        numread,
+        (unsigned long int)req->ih.opcode,
+        (unsigned long int)req->ih.unique);
 	
     switch (req->ih.opcode) {
     case CODA_ROOT:
         log("CODA_ROOT\n");
-		
+        
         rep.oh.opcode = req->ih.opcode;
         rep.oh.unique = req->ih.unique;
         rep.oh.result = 0;
-        rep.coda_root.VFid.Volume = 0;
-        rep.coda_root.VFid.Vnode  = 0;
-        rep.coda_root.VFid.Unique = 0;           /* 0 means root */
-		
+        {
+            struct AvfsFid *fid;
+            fid = (struct AvfsFid *)&rep.coda_root.VFid;
+            fid->Unused0 = 0;
+            fid->Unused1 = 0;
+            fid->Unused2 = 0;
+            fid->Unique = 0;           /* 0 means root */
+        }
         send_to_kernel(&rep, sizeof(rep.coda_root));
         break;
 		
@@ -1312,7 +1334,7 @@
                 reply(req, ENFILE);
             }
             else {
-                fchown(fd, req->ih.cred.cr_fsuid, req->ih.cred.cr_fsgid);
+                fchown(fd, req->ih.uid, req->ih.pgid);
                 close(fd);
 
                 of = malloc(sizeof(struct openfile));
@@ -1523,6 +1545,7 @@
                 break;
 
             default:                
+                logerr("Unknown opcode!!!!\n");
             }
 
             release_fids(op->req);