September update from Rick Macklem to add accept protocol to NQMFS
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Thu, 1 Oct 1992 08:07:54 +0000 (00:07 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Thu, 1 Oct 1992 08:07:54 +0000 (00:07 -0800)
SCCS-vsn: sys/nfs/nfs_nqlease.c 7.12
SCCS-vsn: sys/nfs/nfs_serv.c 7.60
SCCS-vsn: sys/nfs/nfs_socket.c 7.38
SCCS-vsn: sys/nfs/nfs_srvcache.c 7.18
SCCS-vsn: sys/nfs/nfs_subs.c 7.65
SCCS-vsn: sys/nfs/nfs_vnops.c 7.93
SCCS-vsn: sys/nfs/nfsnode.h 7.30
SCCS-vsn: sys/nfs/nfsproto.h 7.11

usr/src/sys/nfs/nfs_nqlease.c
usr/src/sys/nfs/nfs_serv.c
usr/src/sys/nfs/nfs_socket.c
usr/src/sys/nfs/nfs_srvcache.c
usr/src/sys/nfs/nfs_subs.c
usr/src/sys/nfs/nfs_vnops.c
usr/src/sys/nfs/nfsnode.h
usr/src/sys/nfs/nfsproto.h

index cf2645a..a170397 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_nqlease.c       7.11 (Berkeley) %G%
+ *     @(#)nfs_nqlease.c       7.12 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -93,6 +93,7 @@ int nqnfs_piggy[NFS_NPROCS] = {
        0,
        0,
        0,
        0,
        0,
        0,
+       0,
 };
 
 int nnnnnn = sizeof (struct nqlease);
 };
 
 int nnnnnn = sizeof (struct nqlease);
@@ -392,11 +393,9 @@ nqsrv_cmpnam(slp, nam, lph)
        else
                addr = slp->ns_nam;
        if (lph->lph_flag & LC_UDP)
        else
                addr = slp->ns_nam;
        if (lph->lph_flag & LC_UDP)
-               ret = netaddr_match(AF_INET, &lph->lph_haddr,
-                       (union nethostaddr *)0, addr);
+               ret = netaddr_match(AF_INET, &lph->lph_haddr, addr);
        else if (lph->lph_flag & LC_CLTP)
        else if (lph->lph_flag & LC_CLTP)
-               ret = netaddr_match(AF_ISO, &lph->lph_claddr,
-                       (union nethostaddr *)0, addr);
+               ret = netaddr_match(AF_ISO, &lph->lph_claddr, addr);
        else {
                if ((lph->lph_slp->ns_flag & SLP_VALID) == 0)
                        return (0);
        else {
                if ((lph->lph_slp->ns_flag & SLP_VALID) == 0)
                        return (0);
@@ -405,8 +404,7 @@ nqsrv_cmpnam(slp, nam, lph)
                        lhaddr.had_inetaddr = saddr->sin_addr.s_addr;
                else
                        lhaddr.had_nam = lph->lph_slp->ns_nam;
                        lhaddr.had_inetaddr = saddr->sin_addr.s_addr;
                else
                        lhaddr.had_nam = lph->lph_slp->ns_nam;
-               ret = netaddr_match(saddr->sin_family, &lhaddr,
-                       (union nethostaddr *)0, addr);
+               ret = netaddr_match(saddr->sin_family, &lhaddr, addr);
        }
        return (ret);
 }
        }
        return (ret);
 }
index 97a41be..001bcee 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_serv.c  7.59 (Berkeley) %G%
+ *     @(#)nfs_serv.c  7.60 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -59,6 +59,44 @@ extern u_long nfs_false, nfs_true;
 nfstype nfs_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
                      NFCHR, NFNON };
 
 nfstype nfs_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
                      NFCHR, NFNON };
 
+/*
+ * nqnfs access service
+ */
+nqnfsrv_access(nfsd, mrep, md, dpos, cred, nam, mrq)
+       struct nfsd *nfsd;
+       struct mbuf *mrep, *md;
+       caddr_t dpos;
+       struct ucred *cred;
+       struct mbuf *nam, **mrq;
+{
+       struct vnode *vp;
+       nfsv2fh_t nfh;
+       fhandle_t *fhp;
+       register u_long *tl;
+       register long t1;
+       caddr_t bpos;
+       int error = 0, rdonly, cache, mode = 0;
+       char *cp2;
+       struct mbuf *mb, *mb2, *mreq;
+       u_quad_t frev;
+
+       fhp = &nfh.fh_generic;
+       nfsm_srvmtofh(fhp);
+       nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
+       if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
+               nfsm_reply(0);
+       if (*tl++ == nfs_true)
+               mode |= VREAD;
+       if (*tl++ == nfs_true)
+               mode |= VWRITE;
+       if (*tl == nfs_true)
+               mode |= VEXEC;
+       error = nfsrv_access(vp, mode, cred, rdonly, nfsd->nd_procp);
+       vput(vp);
+       nfsm_reply(0);
+       nfsm_srvdone;
+}
+
 /*
  * nfs getattr service
  */
 /*
  * nfs getattr service
  */
index 7d29ae7..1f64127 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_socket.c        7.37 (Berkeley) %G%
+ *     @(#)nfs_socket.c        7.38 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -105,7 +105,7 @@ static int nfsrv_errmap[ELAST] = {
  * 4 - write
  */
 static int proct[NFS_NPROCS] = {
  * 4 - write
  */
 static int proct[NFS_NPROCS] = {
-       0, 1, 0, 0, 2, 3, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0,
+       0, 1, 0, 0, 2, 3, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0,
 };
 
 /*
 };
 
 /*
@@ -151,7 +151,8 @@ int nfsrv_null(),
        nfsrv_noop(),
        nqnfsrv_readdirlook(),
        nqnfsrv_getlease(),
        nfsrv_noop(),
        nqnfsrv_readdirlook(),
        nqnfsrv_getlease(),
-       nqnfsrv_vacated();
+       nqnfsrv_vacated(),
+       nqnfsrv_access();
 
 int (*nfsrv_procs[NFS_NPROCS])() = {
        nfsrv_null,
 
 int (*nfsrv_procs[NFS_NPROCS])() = {
        nfsrv_null,
@@ -175,6 +176,8 @@ int (*nfsrv_procs[NFS_NPROCS])() = {
        nqnfsrv_readdirlook,
        nqnfsrv_getlease,
        nqnfsrv_vacated,
        nqnfsrv_readdirlook,
        nqnfsrv_getlease,
        nqnfsrv_vacated,
+       nfsrv_noop,
+       nqnfsrv_access,
 };
 
 struct nfsreq nfsreqh;
 };
 
 struct nfsreq nfsreqh;
index f112ada..dd7a906 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_srvcache.c      7.17 (Berkeley) %G%
+ *     @(#)nfs_srvcache.c      7.18 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -75,6 +75,7 @@ int nonidempotent[NFS_NPROCS] = {
        FALSE,
        FALSE,
        FALSE,
        FALSE,
        FALSE,
        FALSE,
+       FALSE,
 };
 
 /* True iff the rpc reply is an nfs status ONLY! */
 };
 
 /* True iff the rpc reply is an nfs status ONLY! */
@@ -101,6 +102,7 @@ static int repliesstatus[NFS_NPROCS] = {
        FALSE,
        FALSE,
        FALSE,
        FALSE,
        FALSE,
        FALSE,
+       TRUE,
 };
 
 /*
 };
 
 /*
@@ -143,7 +145,7 @@ nfsrv_getcache(nam, nd, repp)
 loop:
        for (rp = *rpp; rp; rp = rp->rc_forw) {
            if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
 loop:
        for (rp = *rpp; rp; rp = rp->rc_forw) {
            if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
-               netaddr_match(NETFAMILY(rp), &rp->rc_haddr, (union nethostaddr *)0, nam)) {
+               netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nam)) {
                        if ((rp->rc_flag & RC_LOCKED) != 0) {
                                rp->rc_flag |= RC_WANTED;
                                (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
                        if ((rp->rc_flag & RC_LOCKED) != 0) {
                                rp->rc_flag |= RC_WANTED;
                                (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
@@ -271,7 +273,7 @@ nfsrv_updatecache(nam, nd, repvalid, repmbuf)
 loop:
        for (rp = rheadhtbl[NFSRCHASH(nd->nd_retxid)]; rp; rp = rp->rc_forw) {
            if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
 loop:
        for (rp = rheadhtbl[NFSRCHASH(nd->nd_retxid)]; rp; rp = rp->rc_forw) {
            if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
-               netaddr_match(NETFAMILY(rp), &rp->rc_haddr, (union nethostaddr *)0, nam)) {
+               netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nam)) {
                        if ((rp->rc_flag & RC_LOCKED) != 0) {
                                rp->rc_flag |= RC_WANTED;
                                (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
                        if ((rp->rc_flag & RC_LOCKED) != 0) {
                                rp->rc_flag |= RC_WANTED;
                                (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
index 6c9f3e8..bcd5134 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_subs.c  7.64 (Berkeley) %G%
+ *     @(#)nfs_subs.c  7.65 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -1048,41 +1048,34 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp)
  * The AF_INET family is handled as a special case so that address mbufs
  * don't need to be saved to store "struct in_addr", which is only 4 bytes.
  */
  * The AF_INET family is handled as a special case so that address mbufs
  * don't need to be saved to store "struct in_addr", which is only 4 bytes.
  */
-netaddr_match(family, haddr, hmask, nam)
+netaddr_match(family, haddr, nam)
        int family;
        union nethostaddr *haddr;
        int family;
        union nethostaddr *haddr;
-       union nethostaddr *hmask;
        struct mbuf *nam;
 {
        register struct sockaddr_in *inetaddr;
        struct mbuf *nam;
 {
        register struct sockaddr_in *inetaddr;
-#ifdef ISO
-       register struct sockaddr_iso *isoaddr1, *isoaddr2;
-#endif
-
 
        switch (family) {
        case AF_INET:
                inetaddr = mtod(nam, struct sockaddr_in *);
 
        switch (family) {
        case AF_INET:
                inetaddr = mtod(nam, struct sockaddr_in *);
-               if (inetaddr->sin_family != AF_INET)
-                       return (0);
-               if (hmask) {
-                       if ((inetaddr->sin_addr.s_addr & hmask->had_inetaddr) ==
-                           (haddr->had_inetaddr & hmask->had_inetaddr))
-                               return (1);
-               } else if (inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
+               if (inetaddr->sin_family == AF_INET &&
+                   inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
                        return (1);
                break;
 #ifdef ISO
        case AF_ISO:
                        return (1);
                break;
 #ifdef ISO
        case AF_ISO:
+           {
+               register struct sockaddr_iso *isoaddr1, *isoaddr2;
+
                isoaddr1 = mtod(nam, struct sockaddr_iso *);
                isoaddr1 = mtod(nam, struct sockaddr_iso *);
-               if (isoaddr1->siso_family != AF_ISO)
-                       return (0);
                isoaddr2 = mtod(haddr->had_nam, struct sockaddr_iso *);
                isoaddr2 = mtod(haddr->had_nam, struct sockaddr_iso *);
-               if (isoaddr1->siso_nlen > 0 &&
+               if (isoaddr1->siso_family == AF_ISO &&
+                   isoaddr1->siso_nlen > 0 &&
                    isoaddr1->siso_nlen == isoaddr2->siso_nlen &&
                    SAME_ISOADDR(isoaddr1, isoaddr2))
                        return (1);
                break;
                    isoaddr1->siso_nlen == isoaddr2->siso_nlen &&
                    SAME_ISOADDR(isoaddr1, isoaddr2))
                        return (1);
                break;
+           }
 #endif /* ISO */
        default:
                break;
 #endif /* ISO */
        default:
                break;
index 45da098..ae9b08d 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_vnops.c 7.92 (Berkeley) %G%
+ *     @(#)nfs_vnops.c 7.93 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -107,7 +107,7 @@ struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
        { &vop_mknod_desc, spec_mknod },        /* mknod */
        { &vop_open_desc, spec_open },          /* open */
        { &vop_close_desc, nfsspec_close },     /* close */
        { &vop_mknod_desc, spec_mknod },        /* mknod */
        { &vop_open_desc, spec_open },          /* open */
        { &vop_close_desc, nfsspec_close },     /* close */
-       { &vop_access_desc, nfs_access },       /* access */
+       { &vop_access_desc, nfsspec_access },   /* access */
        { &vop_getattr_desc, nfs_getattr },     /* getattr */
        { &vop_setattr_desc, nfs_setattr },     /* setattr */
        { &vop_read_desc, nfsspec_read },       /* read */
        { &vop_getattr_desc, nfs_getattr },     /* getattr */
        { &vop_setattr_desc, nfs_setattr },     /* setattr */
        { &vop_read_desc, nfsspec_read },       /* read */
@@ -155,7 +155,7 @@ struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
        { &vop_mknod_desc, fifo_mknod },        /* mknod */
        { &vop_open_desc, fifo_open },          /* open */
        { &vop_close_desc, nfsfifo_close },     /* close */
        { &vop_mknod_desc, fifo_mknod },        /* mknod */
        { &vop_open_desc, fifo_open },          /* open */
        { &vop_close_desc, nfsfifo_close },     /* close */
-       { &vop_access_desc, nfs_access },       /* access */
+       { &vop_access_desc, nfsspec_access },   /* access */
        { &vop_getattr_desc, nfs_getattr },     /* getattr */
        { &vop_setattr_desc, nfs_setattr },     /* setattr */
        { &vop_read_desc, nfsfifo_read },       /* read */
        { &vop_getattr_desc, nfs_getattr },     /* getattr */
        { &vop_setattr_desc, nfs_setattr },     /* setattr */
        { &vop_read_desc, nfsfifo_read },       /* read */
@@ -201,7 +201,7 @@ void nqnfs_clientlease();
  * Global variables
  */
 extern u_long nfs_procids[NFS_NPROCS];
  * Global variables
  */
 extern u_long nfs_procids[NFS_NPROCS];
-extern u_long nfs_prog, nfs_vers;
+extern u_long nfs_prog, nfs_vers, nfs_true, nfs_false;
 extern char nfsiobuf[MAXPHYS+NBPG];
 struct buf nfs_bqueue;         /* Queue head for nfsiod's */
 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
 extern char nfsiobuf[MAXPHYS+NBPG];
 struct buf nfs_bqueue;         /* Queue head for nfsiod's */
 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
@@ -229,7 +229,9 @@ nfs_null(vp, cred, procp)
 
 /*
  * nfs access vnode op.
 
 /*
  * nfs access vnode op.
- * Essentially just get vattr and then imitate iaccess()
+ * For nfs, just return ok. File accesses may fail later.
+ * For nqnfs, use the access rpc to check accessibility. If file modes are
+ * changed on the server, accesses might still fail later.
  */
 int
 nfs_access(ap)
  */
 int
 nfs_access(ap)
@@ -240,41 +242,39 @@ nfs_access(ap)
                struct proc *a_p;
        } */ *ap;
 {
                struct proc *a_p;
        } */ *ap;
 {
-       register struct vattr *vap;
-       register gid_t *gp;
-       register struct ucred *cred = ap->a_cred;
-       mode_t mode = ap->a_mode;
-       struct vattr vattr;
-       register int i;
-       int error;
+       register struct vnode *vp = ap->a_vp;
+       register u_long *tl;
+       register caddr_t cp;
+       caddr_t bpos, dpos;
+       int error = 0;
+       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        /*
 
        /*
-        * If you're the super-user,
-        * you always get access.
+        * There is no way to check accessibility via. ordinary nfs, so if
+        * access isn't allowed they will get burned later.
         */
         */
-       if (cred->cr_uid == 0)
-               return (0);
-       vap = &vattr;
-       if (error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p))
+       if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) {
+               nfsstats.rpccnt[NQNFSPROC_ACCESS]++;
+               nfsm_reqhead(vp, NQNFSPROC_ACCESS, NFSX_FH + 3 * NFSX_UNSIGNED);
+               nfsm_fhtom(vp);
+               nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
+               if (ap->a_mode & VREAD)
+                       *tl++ = nfs_true;
+               else
+                       *tl++ = nfs_false;
+               if (ap->a_mode & VWRITE)
+                       *tl++ = nfs_true;
+               else
+                       *tl++ = nfs_false;
+               if (ap->a_mode & VEXEC)
+                       *tl = nfs_true;
+               else
+                       *tl = nfs_false;
+               nfsm_request(vp, NQNFSPROC_ACCESS, ap->a_p, ap->a_cred);
+               nfsm_reqdone;
                return (error);
                return (error);
-       /*
-        * Access check is based on only one of owner, group, public.
-        * If not owner, then check group. If not a member of the
-        * group, then check public access.
-        */
-       if (cred->cr_uid != vap->va_uid) {
-               mode >>= 3;
-               gp = cred->cr_groups;
-               for (i = 0; i < cred->cr_ngroups; i++, gp++)
-                       if (vap->va_gid == *gp)
-                               goto found;
-               mode >>= 3;
-found:
-               ;
-       }
-       if ((vap->va_mode & mode) != 0)
+       } else
                return (0);
                return (0);
-       return (EACCES);
 }
 
 /*
 }
 
 /*
@@ -2324,6 +2324,57 @@ nfs_update(ap)
        return (EOPNOTSUPP);
 }
 
        return (EOPNOTSUPP);
 }
 
+/*
+ * nfs special file access vnode op.
+ * Essentially just get vattr and then imitate iaccess() since the device is
+ * local to the client.
+ */
+int
+nfsspec_access(ap)
+       struct vop_access_args /* {
+               struct vnode *a_vp;
+               int  a_mode;
+               struct ucred *a_cred;
+               struct proc *a_p;
+       } */ *ap;
+{
+       register struct vattr *vap;
+       register gid_t *gp;
+       register struct ucred *cred = ap->a_cred;
+       mode_t mode = ap->a_mode;
+       struct vattr vattr;
+       register int i;
+       int error;
+
+       /*
+        * If you're the super-user,
+        * you always get access.
+        */
+       if (cred->cr_uid == 0)
+               return (0);
+       vap = &vattr;
+       if (error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p))
+               return (error);
+       /*
+        * Access check is based on only one of owner, group, public.
+        * If not owner, then check group. If not a member of the
+        * group, then check public access.
+        */
+       if (cred->cr_uid != vap->va_uid) {
+               mode >>= 3;
+               gp = cred->cr_groups;
+               for (i = 0; i < cred->cr_ngroups; i++, gp++)
+                       if (vap->va_gid == *gp)
+                               goto found;
+               mode >>= 3;
+found:
+               ;
+       }
+       if ((vap->va_mode & mode) != 0)
+               return (0);
+       return (EACCES);
+}
+
 /*
  * Read wrapper for special devices.
  */
 /*
  * Read wrapper for special devices.
  */
index 1e86470..553b3e1 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfsnode.h   7.29 (Berkeley) %G%
+ *     @(#)nfsnode.h   7.30 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -87,6 +87,7 @@ int   nfsspec_close __P((struct vop_close_args *));
 int    nfsfifo_close __P((struct vop_close_args *));
 #endif
 int    nfs_access __P((struct vop_access_args *));
 int    nfsfifo_close __P((struct vop_close_args *));
 #endif
 int    nfs_access __P((struct vop_access_args *));
+int    nfsspec_access __P((struct vop_access_args *));
 int    nfs_getattr __P((struct vop_getattr_args *));
 int    nfs_setattr __P((struct vop_setattr_args *));
 int    nfs_read __P((struct vop_read_args *));
 int    nfs_getattr __P((struct vop_getattr_args *));
 int    nfs_setattr __P((struct vop_setattr_args *));
 int    nfs_read __P((struct vop_read_args *));
index e17bcad..6f3f580 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfsproto.h  7.10 (Berkeley) %G%
+ *     @(#)nfsproto.h  7.11 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -92,8 +92,9 @@
 #define        NQNFSPROC_GETLEASE      19
 #define        NQNFSPROC_VACATED       20
 #define        NQNFSPROC_EVICTED       21
 #define        NQNFSPROC_GETLEASE      19
 #define        NQNFSPROC_VACATED       20
 #define        NQNFSPROC_EVICTED       21
+#define        NQNFSPROC_ACCESS        22
 
 
-#define        NFS_NPROCS              22
+#define        NFS_NPROCS              23
 /* Conversion macros */
 extern int             vttoif_tab[];
 #define        vtonfs_mode(t,m) \
 /* Conversion macros */
 extern int             vttoif_tab[];
 #define        vtonfs_mode(t,m) \