See Changelog nfs-utils-1-0-2-pre5
authorneilbrown <neilbrown>
Wed, 26 Mar 2003 00:26:36 +0000 (00:26 +0000)
committerneilbrown <neilbrown>
Wed, 26 Mar 2003 00:26:36 +0000 (00:26 +0000)
ChangeLog
support/include/nfslib.h
support/nfs/Makefile
support/nfs/cacheio.c [new file with mode: 0644]
support/nfs/nfsexport.c

index 4245164..2c466d7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2003-03-26 NeilBrown <neilb@cse.unsw.edu.au>
+
+       * support/nfs/cacheio.c: New File - support for read/writing
+       to export cache in /proc/rpc/*/channel
+       * support/nfs/Makefile: compile cacheio.c
+       * support/include/nfslib.h: declare cacheio.c functions
+       * support/nfs/nfsexport.c: export and unexport through
+       /proc/rpc/*/channel if possible, as old syscall interface
+       may not survive into 2.6 on all architectures.
+       
 2003-02-19 NeilBrown <neilb@cse.unsw.edu.au>   
        Ben Leslie <benno@sesgroup.net>
 
index 95c3fe7..90bd33a 100644 (file)
@@ -122,6 +122,11 @@ struct nfs_fh_len *        getfh_old(struct sockaddr *addr, dev_t dev, ino_t ino);
 struct nfs_fh_len *    getfh(struct sockaddr *addr, const char *);
 struct nfs_fh_len *    getfh_size(struct sockaddr *addr, const char *, int size);
 
+void qword_print(FILE *f, char *str);
+void qword_printhex(FILE *f, char *str, int slen);
+void qword_printint(FILE *f, int num);
+void qword_eol(FILE *f);
+
 /* lockd. */
 int                    lockdsvc();
 
index 12a44e8..4e4a375 100644 (file)
@@ -6,7 +6,7 @@ LIBNAME = libnfs.a
 OBJS   = exports.o rmtab.o xio.o \
          rpcmisc.o rpcdispatch.o xlog.o xmalloc.o wildmat.o \
          nfssvc.o nfsclient.o nfsexport.o getfh.o nfsctl.o \
-         lockdsvc.o svc_socket.o
+         lockdsvc.o svc_socket.o cacheio.o
 
 include $(TOP)rules.mk
 
diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c
new file mode 100644 (file)
index 0000000..960d801
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * support/nfs/cacheio.c
+ * support IO on the cache channel files in 2.5 and beyond.
+ * These use 'qwords' which are like words, but with a little quoting.
+ *
+ */
+
+
+/*
+ * Support routines for text-based upcalls.
+ * Fields are separated by spaces.
+ * Fields are either mangled to quote space tab newline slosh with slosh
+ * or a hexified with a leading \x
+ * Record is terminated with newline.
+ *
+ */
+
+#include <nfslib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+
+void qword_add(char **bpp, int *lp, char *str)
+{
+       char *bp = *bpp;
+       int len = *lp;
+       char c;
+
+       if (len < 0) return;
+
+       while ((c=*str++) && len)
+               switch(c) {
+               case ' ':
+               case '\t':
+               case '\n':
+               case '\\':
+                       if (len >= 4) {
+                               *bp++ = '\\';
+                               *bp++ = '0' + ((c & 0300)>>6);
+                               *bp++ = '0' + ((c & 0070)>>3);
+                               *bp++ = '0' + ((c & 0007)>>0);
+                       }
+                       len -= 4;
+                       break;
+               default:
+                       *bp++ = c;
+                       len--;
+               }
+       if (c || len <1) len = -1;
+       else {
+               *bp++ = ' ';
+               len--;
+       }
+       *bpp = bp;
+       *lp = len;
+}
+
+void qword_addhex(char **bpp, int *lp, char *buf, int blen)
+{
+       char *bp = *bpp;
+       int len = *lp;
+
+       if (len < 0) return;
+
+       if (len > 2) {
+               *bp++ = '\\';
+               *bp++ = 'x';
+               len -= 2;
+               while (blen && len >= 2) {
+                       unsigned char c = *buf++;
+                       *bp++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
+                       *bp++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
+                       len -= 2;
+                       blen--;
+               }
+       }
+       if (blen || len<1) len = -1;
+       else {
+               *bp++ = ' ';
+               len--;
+       }
+       *bpp = bp;
+       *lp = len;
+}
+
+static char qword_buf[8192];
+void qword_print(FILE *f, char *str)
+{
+       char *bp = qword_buf;
+       int len = sizeof(qword_buf);
+       qword_add(&bp, &len, str);
+       fwrite(qword_buf, bp-qword_buf, 1, f);
+}
+
+void qword_printhex(FILE *f, char *str, int slen)
+{
+       char *bp = qword_buf;
+       int len = sizeof(qword_buf);
+       qword_addhex(&bp, &len, str, slen);
+       fwrite(qword_buf, bp-qword_buf, 1, f);
+}
+
+void qword_printint(FILE *f, int num)
+{
+       fprintf(f, "%d ", num);
+}
+
+void qword_eol(FILE *f)
+{
+       fprintf(f,"\n");
+       fflush(f);
+}
+
+
+
+#define isodigit(c) (isdigit(c) && c <= '7')
+int qword_get(char **bpp, char *dest, int bufsize)
+{
+       /* return bytes copied, or -1 on error */
+       char *bp = *bpp;
+       int len = 0;
+
+       while (*bp == ' ') bp++;
+
+       if (bp[0] == '\\' && bp[1] == 'x') {
+               /* HEX STRING */
+               bp += 2;
+               while (isxdigit(bp[0]) && isxdigit(bp[1]) && len < bufsize) {
+                       int byte = isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
+                       bp++;
+                       byte <<= 4;
+                       byte |= isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
+                       *dest++ = byte;
+                       bp++;
+                       len++;
+               }
+       } else {
+               /* text with \nnn octal quoting */
+               while (*bp != ' ' && *bp != '\n' && *bp && len < bufsize-1) {
+                       if (*bp == '\\' &&
+                           isodigit(bp[1]) && (bp[1] <= '3') &&
+                           isodigit(bp[2]) &&
+                           isodigit(bp[3])) {
+                               int byte = (*++bp -'0');
+                               bp++;
+                               byte = (byte << 3) | (*bp++ - '0');
+                               byte = (byte << 3) | (*bp++ - '0');
+                               *dest++ = byte;
+                               len++;
+                       } else {
+                               *dest++ = *bp++;
+                               len++;
+                       }
+               }
+       }
+
+       if (*bp != ' ' && *bp != '\n' && *bp != '\0')
+               return -1;
+       while (*bp == ' ') bp++;
+       *bpp = bp;
+       *dest = '\0';
+       return len;
+}
+
+int qword_get_int(char **bpp, int *anint)
+{
+       char buf[50];
+       char *ep;
+       int rv;
+       int len = qword_get(bpp, buf, 50);
+       if (len < 0) return -1;
+       if (len ==0) return -1;
+       rv = strtol(buf, &ep, 0);
+       if (*ep) return -1;
+       *anint = rv;
+       return 0;
+}
+
+int readline(int fd, char **buf, int *lenp)
+{
+       /* read a line into *buf, which is malloced *len long
+        * realloc if needed until we find a \n
+        * nul out the \n and return
+        * 0 of eof, 1 of success 
+        */
+       int len = *lenp;
+
+       if (len == 0) {
+               char *b = malloc(128);
+               if (b == NULL)
+                       return 0;
+               *buf = b;
+               *lenp = 128;
+       }
+       len = read(fd, *buf, len);
+       if (len <= 0)
+               return 0;
+       while ((*buf)[len-1] != '\n') {
+       /* now the less common case.  There was no newline,
+        * so we have to keep reading after re-alloc
+        */
+               char *new;
+               int nl;
+               *lenp += 128;
+               new = realloc(*buf, *lenp);
+               if (new == NULL)
+                       return 0;
+               nl = read(fd, *buf +len, *lenp - len);
+               if (nl <= 0 )
+                       return 0;
+               new += nl;
+       }
+       (*buf)[len-1] = 0;
+       return 1;
+}
+
index ce8b867..97de651 100644 (file)
@@ -9,13 +9,87 @@
 #include "config.h"
 
 #include <string.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
 #include "nfslib.h"
 
+       /* if /proc/net/rpc/... exists, then 
+        * write to it, as that interface is more stable.
+        * Write:
+        *  client fsidtype fsid path
+        * to /proc/net/rpc/nfsd.fh/channel
+        * and
+        *  client path expiry flags anonuid anongid fsid
+        * to /proc/net/rpc/nfsd.export/channel
+        */
+
+static int
+exp_unexp(struct nfsctl_export *exp, int export)
+{
+       FILE *f;
+       struct stat stb;
+       __u32 fsid;
+       char fsidstr[8];
+       __u16 dev;
+       __u32 inode;
+
+
+       f = fopen("/proc/net/rpc/nfsd.export/channel", "w");
+       if (f == NULL) return -1;
+       qword_print(f, exp->ex_client);
+       qword_print(f, exp->ex_path);
+       qword_printint(f, 0x7fffffff);
+       if (export) {
+               qword_printint(f, exp->ex_flags);
+               qword_printint(f, exp->ex_anon_uid);
+               qword_printint(f, exp->ex_anon_gid);
+               qword_printint(f, exp->ex_dev);
+       }
+       qword_eol(f);
+       fclose(f);
+
+       if (stat(exp->ex_path, &stb) != 0)
+               return -1;
+       f = fopen("/proc/net/rpc/nfsd.fh/channel", "w");
+       if (f==NULL) return -1;
+       if (exp->ex_flags & NFSEXP_FSID) {
+               qword_print(f,exp->ex_client);
+               qword_printint(f,1);
+               fsid = exp->ex_dev;
+               qword_printhex(f, (char*)&fsid, 4);
+               qword_printint(f, 0x7fffffff);
+               if (export)
+                       qword_print(f, exp->ex_path);
+               qword_eol(f);
+       }
+       qword_print(f,exp->ex_client);
+       qword_printint(f,0);
+       dev = htons(major(stb.st_dev)); memcpy(fsidstr, &dev, 2);
+       dev = htons(minor(stb.st_dev)); memcpy(fsidstr+2, &dev, 2);
+       inode = stb.st_ino; memcpy(fsidstr+4, &inode, 4);
+       
+       qword_printhex(f, fsidstr, 8);
+       qword_printint(f, 0x7fffffff);
+       if (export)
+               qword_print(f, exp->ex_path);
+       qword_eol(f);
+       fclose(f);
+       return 0;
+}
+
 int
 nfsexport(struct nfsctl_export *exp)
 {
        struct nfsctl_arg       arg;
-
+       int fd;
+       if ((fd=open("/proc/net/rpc/nfsd.fh/channel", O_RDWR))>= 0) {
+               close(fd);
+               return exp_unexp(exp, 1);
+       }
        arg.ca_version = NFSCTL_VERSION;
        memcpy(&arg.ca_export, exp, sizeof(arg.ca_export));
        return nfsctl(NFSCTL_EXPORT, &arg, NULL);
@@ -26,6 +100,12 @@ nfsunexport(struct nfsctl_export *exp)
 {
        struct nfsctl_arg       arg;
 
+       int fd;
+       if ((fd=open("/proc/net/rpc/nfsd.fh/channel", O_RDWR))>= 0) {
+               close(fd);
+               return exp_unexp(exp, 0);
+       }
+
        arg.ca_version = NFSCTL_VERSION;
        memcpy(&arg.ca_export, exp, sizeof(arg.ca_export));
        return nfsctl(NFSCTL_UNEXPORT, &arg, NULL);