From: neilbrown Date: Wed, 26 Mar 2003 00:26:36 +0000 (+0000) Subject: See Changelog X-Git-Tag: nfs-utils-1-0-2-pre5^0 X-Git-Url: https://git.decadent.org.uk/gitweb/?a=commitdiff_plain;h=f6a8d3907cd24a4c255234b0161c868763736fdf;p=nfs-utils.git See Changelog --- diff --git a/ChangeLog b/ChangeLog index 4245164..2c466d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2003-03-26 NeilBrown + + * 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 Ben Leslie diff --git a/support/include/nfslib.h b/support/include/nfslib.h index 95c3fe7..90bd33a 100644 --- a/support/include/nfslib.h +++ b/support/include/nfslib.h @@ -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(); diff --git a/support/nfs/Makefile b/support/nfs/Makefile index 12a44e8..4e4a375 100644 --- a/support/nfs/Makefile +++ b/support/nfs/Makefile @@ -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 index 0000000..960d801 --- /dev/null +++ b/support/nfs/cacheio.c @@ -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 +#include +#include +#include + +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; +} + diff --git a/support/nfs/nfsexport.c b/support/nfs/nfsexport.c index ce8b867..97de651 100644 --- a/support/nfs/nfsexport.c +++ b/support/nfs/nfsexport.c @@ -9,13 +9,87 @@ #include "config.h" #include +#include +#include +#include +#include +#include + #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);