collect lock holder when locking inodes
[unix-history] / usr / src / sys / ufs / ffs / ufs_vfsops.c
index a649377..f36295a 100644 (file)
@@ -4,15 +4,21 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)ufs_vfsops.c        7.57 (Berkeley) %G%
+ *     @(#)ufs_vfsops.c        7.65 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
+#include <net/radix.h>
+#include <sys/domain.h>
+#include <sys/socket.h>
+#include <sys/mbuf.h>
 #include <sys/mount.h>
 #include <sys/proc.h>
 #include <sys/buf.h>
 #include <sys/vnode.h>
 #include <sys/mount.h>
 #include <sys/proc.h>
 #include <sys/buf.h>
 #include <sys/vnode.h>
-#include <sys/specdev.h>
+#include <sys/malloc.h>
+
+#include <miscfs/specfs/specdev.h>
 #include "ioctl.h"
 #include "disklabel.h"
 #include "stat.h"
 #include "ioctl.h"
 #include "disklabel.h"
 #include "stat.h"
@@ -48,31 +54,6 @@ ufs_start(mp, flags, p)
        return (error);
 }
 
        return (error);
 }
 
-/*
- * Return root of a filesystem
- */
-int
-ufs_root(mp, vpp)
-       struct mount *mp;
-       struct vnode **vpp;
-{
-       register struct inode *ip;
-       struct ufsmount *ump;
-       struct inode *nip;
-       struct vnode tvp;
-       int error;
-
-       ump = VFSTOUFS(mp);
-       tvp.v_mount = mp;
-       ip = VTOI(&tvp);
-       ip->i_vnode = &tvp;
-       ip->i_dev = ump->um_dev;
-       if (error = (ump->um_iget)(ip, (ino_t)ROOTINO, &nip))
-               return (error);
-       *vpp = ITOV(nip);
-       return (0);
-}
-
 /*
  * Do operations associated with quotas
  */
 /*
  * Do operations associated with quotas
  */
@@ -80,11 +61,10 @@ int
 ufs_quotactl(mp, cmds, uid, arg, p)
        struct mount *mp;
        int cmds;
 ufs_quotactl(mp, cmds, uid, arg, p)
        struct mount *mp;
        int cmds;
-       u_int uid;
+       uid_t uid;
        caddr_t arg;
        struct proc *p;
 {
        caddr_t arg;
        struct proc *p;
 {
-       struct ufsmount *ump = VFSTOUFS(mp);
        int cmd, type, error;
 
 #ifndef QUOTA
        int cmd, type, error;
 
 #ifndef QUOTA
@@ -144,101 +124,173 @@ ufs_quotactl(mp, cmds, uid, arg, p)
 #endif
 }
 
 #endif
 }
 
-int syncprt = 0;
+/*
+ * Build hash lists of net addresses and hang them off the mount point.
+ * Called by ufs_mount() to set up the lists of export addresses.
+ */
+ufs_hang_addrlist(mp, argp)
+       struct mount *mp;
+       struct ufs_args *argp;
+{
+       register struct netcred *np;
+       register struct radix_node_head *rnh;
+       register int i;
+       struct radix_node *rn;
+       struct ufsmount *ump;
+       struct sockaddr *saddr, *smask = 0;
+       struct domain *dom;
+       int error;
+
+       if (argp->slen == 0) {
+               if (mp->mnt_flag & MNT_DEFEXPORTED)
+                       return (EPERM);
+               np = &ump->um_defexported;
+               np->netc_exflags = argp->exflags;
+               np->netc_anon = argp->anon;
+               np->netc_anon.cr_ref = 1;
+               mp->mnt_flag |= MNT_DEFEXPORTED;
+               return (0);
+       }
+       i = sizeof(struct netcred) + argp->slen + argp->msklen;
+       np = (struct netcred *)malloc(i, M_NETADDR, M_WAITOK);
+       bzero((caddr_t)np, i);
+       saddr = (struct sockaddr *)(np + 1);
+       if (error = copyin(argp->saddr, (caddr_t)saddr, argp->slen))
+               goto out;
+       if (saddr->sa_len > argp->slen)
+               saddr->sa_len = argp->slen;
+       if (argp->msklen) {
+               smask = (struct sockaddr *)((caddr_t)saddr + argp->slen);
+               if (error = copyin(argp->saddr, (caddr_t)smask, argp->msklen))
+                       goto out;
+               if (smask->sa_len > argp->msklen)
+                       smask->sa_len = argp->msklen;
+       }
+       ump = VFSTOUFS(mp);
+       i = saddr->sa_family;
+       if ((rnh = ump->um_rtable[i]) == 0) {
+               /*
+                * Seems silly to initialize every AF when most are not
+                * used, do so on demand here
+                */
+               for (dom = domains; dom; dom = dom->dom_next)
+                       if (dom->dom_family == i && dom->dom_rtattach) {
+                               dom->dom_rtattach((void **)&ump->um_rtable[i],
+                                       dom->dom_rtoffset);
+                               break;
+                       }
+               if ((rnh = ump->um_rtable[i]) == 0) {
+                       error = ENOBUFS;
+                       goto out;
+               }
+       }
+       rn = (*rnh->rnh_add)((caddr_t)saddr, (caddr_t)smask, rnh->rnh_treetop,
+           np->netc_rnodes);
+       if (rn == 0 || np != (struct netcred *)rn) { /* already exists */
+               error = EPERM;
+               goto out;
+       }
+       np->netc_exflags = argp->exflags;
+       np->netc_anon = argp->anon;
+       np->netc_anon.cr_ref = 1;
+       return (0);
+out:
+       free(np, M_NETADDR);
+       return (error);
+}
+
+/* ARGSUSED */
+static int
+ufs_free_netcred(rn, w)
+       struct radix_node *rn;
+       caddr_t w;
+{
+       free((caddr_t)rn, M_NETADDR);
+}
+       
 
 /*
 
 /*
- * Print out statistics on the current allocation of the buffer pool.
- * Can be enabled to print out on every ``sync'' by setting "syncprt"
- * above.
+ * Free the net address hash lists that are hanging off the mount points.
  */
 void
  */
 void
-ufs_bufstats()
+ufs_free_addrlist(ump)
+       struct ufsmount *ump;
 {
 {
-       int s, i, j, count;
-       register struct buf *bp, *dp;
-       int counts[MAXBSIZE/CLBYTES+1];
-       static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
-
-       for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
-               count = 0;
-               for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
-                       counts[j] = 0;
-               s = splbio();
-               for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
-                       counts[dp->b_bufsize/CLBYTES]++;
-                       count++;
+       register int i;
+       register struct radix_node_head *rnh;
+
+       for (i = 0; i <= AF_MAX; i++)
+               if (rnh = ump->um_rtable[i]) {
+                       (*rnh->rnh_walk)(rnh->rnh_treetop,
+                               ufs_free_netcred, (caddr_t)0);
+                       free((caddr_t)rnh, M_RTABLE);
+                       ump->um_rtable[i] = 0;
                }
                }
-               splx(s);
-               printf("%s: total-%d", bname[i], count);
-               for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
-                       if (counts[j] != 0)
-                               printf(", %d-%d", j * CLBYTES, counts[j]);
-               printf("\n");
-       }
 }
 
 /*
 }
 
 /*
- * File handle to vnode
+ * This is the generic part of fhtovp called after the underlying
+ * filesystem has validated the file handle.
  *
  *
- * Have to be really careful about stale file handles:
- * - check that the inode number is valid
- * - call iget() to get the locked inode
- * - check for an unallocated inode (i_mode == 0)
- * - check that the generation number matches
+ * Verify that a host should have access to a filesystem, and if so
+ * return a vnode for the presented file handle.
  */
 int
  */
 int
-ufs_fhtovp(mp, fhp, vpp)
+ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)
        register struct mount *mp;
        register struct mount *mp;
-       struct fid *fhp;
+       struct ufid *ufhp;
+       struct mbuf *nam;
        struct vnode **vpp;
        struct vnode **vpp;
+       int *exflagsp;
+       struct ucred **credanonp;
 {
        register struct inode *ip;
 {
        register struct inode *ip;
-       register struct ufid *ufhp;
-       struct ufsmount *ump;
-       struct inode *nip;
-       struct vnode tvp;
+       register struct netcred *np;
+       register struct ufsmount *ump = VFSTOUFS(mp);
+       register struct radix_node_head *rnh;
+       struct vnode *nvp;
+       struct sockaddr *saddr;
        int error;
 
        int error;
 
-       ufhp = (struct ufid *)fhp;
-       ump = VFSTOUFS(mp);
-       tvp.v_mount = mp;
-       ip = VTOI(&tvp);
-       ip->i_vnode = &tvp;
-       ip->i_dev = ump->um_dev;
-       if (error = (ump->um_iget)(ip, ufhp->ufid_ino, &nip)) {
-               *vpp = NULLVP;
-               return (error);
+       /*
+        * Get the export permission structure for this <mp, client> tuple.
+        */
+       if ((mp->mnt_flag & MNT_EXPORTED) == 0)
+               return (EACCES);
+       if (nam == NULL) {
+               np = NULL;
+       } else {
+               saddr = mtod(nam, struct sockaddr *);
+               rnh = ump->um_rtable[saddr->sa_family];
+               if (rnh == NULL) {
+                       np = NULL;
+               } else {
+                       np = (struct netcred *)
+                           (*rnh->rnh_match)((caddr_t)saddr, rnh->rnh_treetop);
+                       if (np->netc_rnodes->rn_flags & RNF_ROOT)
+                               np = NULL;
+               }
+       }
+       if (np == NULL) {
+               /*
+                * If no address match, use the default if it exists.
+                */
+               if ((mp->mnt_flag & MNT_DEFEXPORTED) == 0)
+                       return (EACCES);
+               np = &ump->um_defexported;
        }
        }
-       ip = nip;
-       if (ip->i_mode == 0) {
-               ufs_iput(ip);
+       if (error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) {
                *vpp = NULLVP;
                *vpp = NULLVP;
-               return (EINVAL);
+               return (error);
        }
        }
-       if (ip->i_gen != ufhp->ufid_gen) {
-               ufs_iput(ip);
+       ip = VTOI(nvp);
+       if (ip->i_mode == 0 || ip->i_gen != ufhp->ufid_gen) {
+               vput(nvp);
                *vpp = NULLVP;
                *vpp = NULLVP;
-               return (EINVAL);
+               return (ESTALE);
        }
        }
-       *vpp = ITOV(ip);
-       return (0);
-}
-
-/*
- * Vnode pointer to File handle
- */
-/* ARGSUSED */
-ufs_vptofh(vp, fhp)
-       struct vnode *vp;
-       struct fid *fhp;
-{
-       register struct inode *ip;
-       register struct ufid *ufhp;
-
-       ip = VTOI(vp);
-       ufhp = (struct ufid *)fhp;
-       ufhp->ufid_len = sizeof(struct ufid);
-       ufhp->ufid_ino = ip->i_number;
-       ufhp->ufid_gen = ip->i_gen;
+       *vpp = nvp;
+       *exflagsp = np->netc_exflags;
+       *credanonp = &np->netc_anon;
        return (0);
 }
        return (0);
 }