[BACK]Return to kernfs_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / miscfs / kernfs

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/miscfs/kernfs/kernfs_vnops.c between version 1.112 and 1.153

version 1.112, 2005/09/01 06:25:26 version 1.153, 2014/07/20 13:58:04
Line 41 
Line 41 
 #include <sys/cdefs.h>  #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD$");  __KERNEL_RCSID(0, "$NetBSD$");
   
 #ifdef _KERNEL_OPT  
 #include "opt_ipsec.h"  
 #endif  
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/kernel.h>  #include <sys/kernel.h>
Line 63  __KERNEL_RCSID(0, "$NetBSD$");
Line 59  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <miscfs/genfs/genfs.h>  #include <miscfs/genfs/genfs.h>
 #include <miscfs/kernfs/kernfs.h>  #include <miscfs/kernfs/kernfs.h>
   #include <miscfs/specfs/specdev.h>
 #ifdef IPSEC  
 #include <sys/mbuf.h>  
 #include <net/route.h>  
 #include <netinet/in.h>  
 #include <netinet6/ipsec.h>  
 #include <netkey/key.h>  
 #endif  
   
 #include <uvm/uvm_extern.h>  #include <uvm/uvm_extern.h>
   
Line 95  const struct kern_target kern_targets[] 
Line 84  const struct kern_target kern_targets[] 
                                              KFSstring,      VREG, READ_MODE  },                                               KFSstring,      VREG, READ_MODE  },
      { DT_REG, N("hostname"),  0,            KFShostname,    VREG, WRITE_MODE },       { DT_REG, N("hostname"),  0,            KFShostname,    VREG, WRITE_MODE },
      { DT_REG, N("hz"),        &hz,          KFSint,         VREG, READ_MODE  },       { DT_REG, N("hz"),        &hz,          KFSint,         VREG, READ_MODE  },
 #ifdef IPSEC  
      { DT_DIR, N("ipsecsa"),   0,            KFSipsecsadir,  VDIR, UDIR_MODE  },  
      { DT_DIR, N("ipsecsp"),   0,            KFSipsecspdir,  VDIR, UDIR_MODE  },  
 #endif  
      { DT_REG, N("loadavg"),   0,            KFSavenrun,     VREG, READ_MODE  },       { DT_REG, N("loadavg"),   0,            KFSavenrun,     VREG, READ_MODE  },
      { DT_REG, N("msgbuf"),    0,            KFSmsgbuf,      VREG, READ_MODE  },       { DT_REG, N("msgbuf"),    0,            KFSmsgbuf,      VREG, READ_MODE  },
      { DT_REG, N("pagesize"),  &uvmexp.pagesize, KFSint,     VREG, READ_MODE  },       { DT_REG, N("pagesize"),  &uvmexp.pagesize, KFSint,     VREG, READ_MODE  },
Line 119  const struct kern_target subdir_targets[
Line 104  const struct kern_target subdir_targets[
      { DT_DIR, N("."),         0,            KFSsubdir,      VDIR, DIR_MODE   },       { DT_DIR, N("."),         0,            KFSsubdir,      VDIR, DIR_MODE   },
      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },       { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
 };  };
 #ifdef IPSEC  
 const struct kern_target ipsecsa_targets[] = {  
 /* NOTE: The name must be less than UIO_MX-16 chars in length */  
      /*        name            data          tag           type  ro/rw */  
      { DT_DIR, N("."),         0,            KFSipsecsadir,  VDIR, DIR_MODE   },  
      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },  
 };  
 const struct kern_target ipsecsp_targets[] = {  
 /* NOTE: The name must be less than UIO_MX-16 chars in length */  
      /*        name            data          tag           type  ro/rw */  
      { DT_DIR, N("."),         0,            KFSipsecspdir,  VDIR, DIR_MODE   },  
      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },  
 };  
 const struct kern_target ipsecsa_kt =  
      { DT_DIR, N(""),          0,            KFSipsecsa,     VREG, UREAD_MODE };  
 const struct kern_target ipsecsp_kt =  
      { DT_DIR, N(""),          0,            KFSipsecsp,     VREG, UREAD_MODE };  
 #endif  
 #undef N  #undef N
 SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =  SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =
         SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);          SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);
 int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);  int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
 const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);  const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
 #ifdef IPSEC  
 int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]);  
 int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]);  
 int nkern_dirs = 4; /* 2 extra subdirs */  
 #else  
 int nkern_dirs = 2;  int nkern_dirs = 2;
 #endif  
   
 int kernfs_try_fileop(kfstype, kfsfileop, void *, int);  int kernfs_try_fileop(kfstype, kfsfileop, void *, int);
   int kernfs_try_xread(kfstype, const struct kernfs_node *, char **,
       size_t, int);
 int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,  int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
     size_t, int);      size_t, int);
   
   static int kernfs_default_xread(void *v);
 static int kernfs_default_xwrite(void *v);  static int kernfs_default_xwrite(void *v);
 static int kernfs_default_fileop_getattr(void *);  static int kernfs_default_fileop_getattr(void *);
   
 /* must include all fileop's */  /* must include all fileop's */
 const struct kernfs_fileop kernfs_default_fileops[] = {  const struct kernfs_fileop kernfs_default_fileops[] = {
     { .kf_fileop = KERNFS_XREAD },
   { .kf_fileop = KERNFS_XWRITE },    { .kf_fileop = KERNFS_XWRITE },
   { .kf_fileop = KERNFS_FILEOP_OPEN },    { .kf_fileop = KERNFS_FILEOP_OPEN },
   { .kf_fileop = KERNFS_FILEOP_GETATTR,    { .kf_fileop = KERNFS_FILEOP_GETATTR,
     .kf_genop = {kernfs_default_fileop_getattr} },      .kf_vop = kernfs_default_fileop_getattr },
   { .kf_fileop = KERNFS_FILEOP_IOCTL },    { .kf_fileop = KERNFS_FILEOP_IOCTL },
   { .kf_fileop = KERNFS_FILEOP_CLOSE },    { .kf_fileop = KERNFS_FILEOP_CLOSE },
   { .kf_fileop = KERNFS_FILEOP_WRITE, .kf_genop = {kernfs_default_xwrite} },    { .kf_fileop = KERNFS_FILEOP_READ,
       .kf_vop = kernfs_default_xread },
     { .kf_fileop = KERNFS_FILEOP_WRITE,
       .kf_vop = kernfs_default_xwrite },
 };  };
   
 int     kernfs_lookup(void *);  int     kernfs_lookup(void *);
Line 203  int kernfs_print(void *);
Line 171  int kernfs_print(void *);
 #define kernfs_islocked genfs_islocked  #define kernfs_islocked genfs_islocked
 int     kernfs_pathconf(void *);  int     kernfs_pathconf(void *);
 #define kernfs_advlock  genfs_einval  #define kernfs_advlock  genfs_einval
 #define kernfs_blkatoff genfs_eopnotsupp  
 #define kernfs_valloc   genfs_eopnotsupp  
 #define kernfs_vfree    genfs_nullop  
 #define kernfs_truncate genfs_eopnotsupp  
 #define kernfs_update   genfs_nullop  
 #define kernfs_bwrite   genfs_eopnotsupp  #define kernfs_bwrite   genfs_eopnotsupp
 #define kernfs_putpages genfs_putpages  #define kernfs_putpages genfs_putpages
   
Line 253  const struct vnodeopv_entry_desc kernfs_
Line 216  const struct vnodeopv_entry_desc kernfs_
         { &vop_islocked_desc, kernfs_islocked },        /* islocked */          { &vop_islocked_desc, kernfs_islocked },        /* islocked */
         { &vop_pathconf_desc, kernfs_pathconf },        /* pathconf */          { &vop_pathconf_desc, kernfs_pathconf },        /* pathconf */
         { &vop_advlock_desc, kernfs_advlock },          /* advlock */          { &vop_advlock_desc, kernfs_advlock },          /* advlock */
         { &vop_blkatoff_desc, kernfs_blkatoff },        /* blkatoff */  
         { &vop_valloc_desc, kernfs_valloc },            /* valloc */  
         { &vop_vfree_desc, kernfs_vfree },              /* vfree */  
         { &vop_truncate_desc, kernfs_truncate },        /* truncate */  
         { &vop_update_desc, kernfs_update },            /* update */  
         { &vop_bwrite_desc, kernfs_bwrite },            /* bwrite */          { &vop_bwrite_desc, kernfs_bwrite },            /* bwrite */
         { &vop_putpages_desc, kernfs_putpages },        /* putpages */          { &vop_putpages_desc, kernfs_putpages },        /* putpages */
         { NULL, NULL }          { NULL, NULL }
Line 265  const struct vnodeopv_entry_desc kernfs_
Line 223  const struct vnodeopv_entry_desc kernfs_
 const struct vnodeopv_desc kernfs_vnodeop_opv_desc =  const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
         { &kernfs_vnodeop_p, kernfs_vnodeop_entries };          { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
   
 static __inline int  static inline int
 kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)  kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
 {  {
         if (a->kf_type < b->kf_type)          if (a->kf_type < b->kf_type)
Line 306  kernfs_alloctype(int nkf, const struct k
Line 264  kernfs_alloctype(int nkf, const struct k
                 skf.kf_type = nextfreetype;                  skf.kf_type = nextfreetype;
                 skf.kf_fileop = kf[i].kf_fileop;                  skf.kf_fileop = kf[i].kf_fileop;
                 if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))                  if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
                         fkf->kf_genop = kf[i].kf_genop;                          fkf->kf_vop = kf[i].kf_vop;
         }          }
   
         return nextfreetype++;          return nextfreetype++;
Line 326  kernfs_try_fileop(kfstype type, kfsfileo
Line 284  kernfs_try_fileop(kfstype type, kfsfileo
 }  }
   
 int  int
   kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, char **bfp,
       size_t len, int error)
   {
           struct kernfs_fileop *kf, skf;
   
           skf.kf_type = type;
           skf.kf_fileop = KERNFS_XREAD;
           if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
                   if (kf->kf_xread)
                           return kf->kf_xread(kfs, bfp, len);
           return error;
   }
   
   int
 kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf,  kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf,
     size_t len, int error)      size_t len, int error)
 {  {
Line 369  kernfs_addentry(kernfs_parentdir_t *pkt,
Line 341  kernfs_addentry(kernfs_parentdir_t *pkt,
 }  }
   
 static int  static int
 kernfs_xread(kfs, off, bufp, len, wrlen)  kernfs_xread(struct kernfs_node *kfs, int off, char **bufp, size_t len, size_t *wrlen)
         struct kernfs_node *kfs;  
         int off;  
         char **bufp;  
         size_t len;  
         size_t *wrlen;  
 {  {
         const struct kern_target *kt;          const struct kern_target *kt;
 #ifdef IPSEC          int err;
         struct mbuf *m;  
 #endif  
   
         kt = kfs->kfs_kt;          kt = kfs->kfs_kt;
   
Line 388  kernfs_xread(kfs, off, bufp, len, wrlen)
Line 353  kernfs_xread(kfs, off, bufp, len, wrlen)
                 struct timeval tv;                  struct timeval tv;
   
                 microtime(&tv);                  microtime(&tv);
                 snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);                  snprintf(*bufp, len, "%lld %ld\n", (long long)tv.tv_sec,
                       (long)tv.tv_usec);
                 break;                  break;
         }          }
   
Line 442  kernfs_xread(kfs, off, bufp, len, wrlen)
Line 408  kernfs_xread(kfs, off, bufp, len, wrlen)
   
         case KFShostname: {          case KFShostname: {
                 char *cp = hostname;                  char *cp = hostname;
                 int xlen = hostnamelen;                  size_t xlen = hostnamelen;
   
                 if (xlen >= (len - 2))                  if (xlen >= (len - 2))
                         return (EINVAL);                          return (EINVAL);
Line 450  kernfs_xread(kfs, off, bufp, len, wrlen)
Line 416  kernfs_xread(kfs, off, bufp, len, wrlen)
                 memcpy(*bufp, cp, xlen);                  memcpy(*bufp, cp, xlen);
                 (*bufp)[xlen] = '\n';                  (*bufp)[xlen] = '\n';
                 (*bufp)[xlen+1] = '\0';                  (*bufp)[xlen+1] = '\0';
                 len = strlen(*bufp);  
                 break;                  break;
         }          }
   
Line 461  kernfs_xread(kfs, off, bufp, len, wrlen)
Line 426  kernfs_xread(kfs, off, bufp, len, wrlen)
                     averunnable.ldavg[2], averunnable.fscale);                      averunnable.ldavg[2], averunnable.fscale);
                 break;                  break;
   
 #ifdef IPSEC  
         case KFSipsecsa:  
                 /*  
                  * Note that SA configuration could be changed during the  
                  * read operation, resulting in garbled output.  
                  */  
                 m = key_setdumpsa_spi(htonl(kfs->kfs_value));  
                 if (!m)  
                         return (ENOBUFS);  
                 if (off >= m->m_pkthdr.len) {  
                         *wrlen = 0;  
                         m_freem(m);  
                         return (0);  
                 }  
                 if (len > m->m_pkthdr.len - off)  
                         len = m->m_pkthdr.len - off;  
                 m_copydata(m, off, len, *bufp);  
                 *wrlen = len;  
                 m_freem(m);  
                 return (0);  
   
         case KFSipsecsp:  
                 /*  
                  * Note that SP configuration could be changed during the  
                  * read operation, resulting in garbled output.  
                  */  
                 if (!kfs->kfs_v) {  
                         struct secpolicy *sp;  
   
                         sp = key_getspbyid(kfs->kfs_value);  
                         if (sp)  
                                 kfs->kfs_v = sp;  
                         else  
                                 return (ENOENT);  
                 }  
                 m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,  
                     SADB_X_SPDGET, 0, 0);  
                 if (!m)  
                         return (ENOBUFS);  
                 if (off >= m->m_pkthdr.len) {  
                         *wrlen = 0;  
                         m_freem(m);  
                         return (0);  
                 }  
                 if (len > m->m_pkthdr.len - off)  
                         len = m->m_pkthdr.len - off;  
                 m_copydata(m, off, len, *bufp);  
                 *wrlen = len;  
                 m_freem(m);  
                 return (0);  
 #endif  
   
         default:          default:
                 *wrlen = 0;                  err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len,
                 return (0);                      EOPNOTSUPP);
                   if (err)
                           return err;
         }          }
   
         len = strlen(*bufp);          len = strlen(*bufp);
Line 529  kernfs_xread(kfs, off, bufp, len, wrlen)
Line 444  kernfs_xread(kfs, off, bufp, len, wrlen)
 }  }
   
 static int  static int
 kernfs_xwrite(kfs, bf, len)  kernfs_xwrite(const struct kernfs_node *kfs, char *bf, size_t len)
         const struct kernfs_node *kfs;  
         char *bf;  
         size_t len;  
 {  {
   
         switch (kfs->kfs_type) {          switch (kfs->kfs_type) {
Line 555  kernfs_xwrite(kfs, bf, len)
Line 467  kernfs_xwrite(kfs, bf, len)
  * ndp is the name to locate in that directory...   * ndp is the name to locate in that directory...
  */   */
 int  int
 kernfs_lookup(v)  kernfs_lookup(void *v)
         void *v;  
 {  {
         struct vop_lookup_args /* {          struct vop_lookup_v2_args /* {
                 struct vnode * a_dvp;                  struct vnode * a_dvp;
                 struct vnode ** a_vpp;                  struct vnode ** a_vpp;
                 struct componentname * a_cnp;                  struct componentname * a_cnp;
Line 571  kernfs_lookup(v)
Line 482  kernfs_lookup(v)
         const struct kern_target *kt;          const struct kern_target *kt;
         const struct dyn_kern_target *dkt;          const struct dyn_kern_target *dkt;
         const struct kernfs_subdir *ks;          const struct kernfs_subdir *ks;
         int error, i, wantpunlock;          int error, i;
 #ifdef IPSEC  
         char *ep;  
         u_int32_t id;  
 #endif  
   
         *vpp = NULLVP;          *vpp = NULLVP;
         cnp->cn_flags &= ~PDIRUNLOCK;  
   
         if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)          if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
                 return (EROFS);                  return (EROFS);
   
         if (cnp->cn_namelen == 1 && *pname == '.') {          if (cnp->cn_namelen == 1 && *pname == '.') {
                 *vpp = dvp;                  *vpp = dvp;
                 VREF(dvp);                  vref(dvp);
                 return (0);                  return (0);
         }          }
   
         wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));  
         kfs = VTOKERN(dvp);          kfs = VTOKERN(dvp);
         switch (kfs->kfs_type) {          switch (kfs->kfs_type) {
         case KFSkern:          case KFSkern:
Line 615  kernfs_lookup(v)
Line 520  kernfs_lookup(v)
                 break;                  break;
   
         found:          found:
                 error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);                  error = vcache_get(dvp->v_mount, &kt, sizeof(kt), vpp);
                 if ((error == 0) && wantpunlock) {                  return error;
                         VOP_UNLOCK(dvp, 0);  
                         cnp->cn_flags |= PDIRUNLOCK;  
                 }  
                 return (error);  
   
         case KFSsubdir:          case KFSsubdir:
                 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;                  ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
Line 638  kernfs_lookup(v)
Line 539  kernfs_lookup(v)
                 }                  }
                 break;                  break;
   
 #ifdef IPSEC  
         case KFSipsecsadir:  
                 if (cnp->cn_flags & ISDOTDOT) {  
                         kt = &kern_targets[0];  
                         goto found;  
                 }  
   
                 for (i = 2; i < nipsecsa_targets; i++) {  
                         kt = &ipsecsa_targets[i];  
                         if (cnp->cn_namelen == kt->kt_namlen &&  
                             memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)  
                                 goto found;  
                 }  
   
                 ep = NULL;  
                 id = strtoul(pname, &ep, 10);  
                 if (!ep || *ep || ep == pname)  
                         break;  
   
                 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);  
                 if ((error == 0) && wantpunlock) {  
                         VOP_UNLOCK(dvp, 0);  
                         cnp->cn_flags |= PDIRUNLOCK;  
                 }  
                 return (error);  
   
         case KFSipsecspdir:  
                 if (cnp->cn_flags & ISDOTDOT) {  
                         kt = &kern_targets[0];  
                         goto found;  
                 }  
   
                 for (i = 2; i < nipsecsp_targets; i++) {  
                         kt = &ipsecsp_targets[i];  
                         if (cnp->cn_namelen == kt->kt_namlen &&  
                             memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)  
                                 goto found;  
                 }  
   
                 ep = NULL;  
                 id = strtoul(pname, &ep, 10);  
                 if (!ep || *ep || ep == pname)  
                         break;  
   
                 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);  
                 if ((error == 0) && wantpunlock) {  
                         VOP_UNLOCK(dvp, 0);  
                         cnp->cn_flags |= PDIRUNLOCK;  
                 }  
                 return (error);  
 #endif  
   
         default:          default:
                 return (ENOTDIR);                  return (ENOTDIR);
         }          }
Line 698  kernfs_lookup(v)
Line 547  kernfs_lookup(v)
 }  }
   
 int  int
 kernfs_open(v)  kernfs_open(void *v)
         void *v;  
 {  {
         struct vop_open_args /* {          struct vop_open_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 int a_mode;                  int a_mode;
                 struct ucred *a_cred;                  kauth_cred_t a_cred;
                 struct proc *a_p;  
         } */ *ap = v;          } */ *ap = v;
         struct kernfs_node *kfs = VTOKERN(ap->a_vp);          struct kernfs_node *kfs = VTOKERN(ap->a_vp);
 #ifdef IPSEC  
         struct mbuf *m;  
         struct secpolicy *sp;  
 #endif  
   
         switch (kfs->kfs_type) {          return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN, v, 0);
 #ifdef IPSEC  
         case KFSipsecsa:  
                 m = key_setdumpsa_spi(htonl(kfs->kfs_value));  
                 if (m) {  
                         m_freem(m);  
                         return (0);  
                 } else  
                         return (ENOENT);  
   
         case KFSipsecsp:  
                 sp = key_getspbyid(kfs->kfs_value);  
                 if (sp) {  
                         kfs->kfs_v = sp;  
                         return (0);  
                 } else  
                         return (ENOENT);  
 #endif  
   
         default:  
                 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN,  
                     v, 0);  
         }  
 }  }
   
 int  int
 kernfs_close(v)  kernfs_close(void *v)
         void *v;  
 {  {
         struct vop_close_args /* {          struct vop_close_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 int a_fflag;                  int a_fflag;
                 struct ucred *a_cred;                  kauth_cred_t a_cred;
                 struct proc *a_p;  
         } */ *ap = v;          } */ *ap = v;
         struct kernfs_node *kfs = VTOKERN(ap->a_vp);          struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   
         switch (kfs->kfs_type) {          return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE, v, 0);
 #ifdef IPSEC  
         case KFSipsecsp:  
                 key_freesp((struct secpolicy *)kfs->kfs_v);  
                 break;  
 #endif  
   
         default:  
                 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE,  
                     v, 0);  
         }  
   
         return (0);  
 }  }
   
 int  int
 kernfs_access(v)  kernfs_access(void *v)
         void *v;  
 {  {
         struct vop_access_args /* {          struct vop_access_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 int a_mode;                  int a_mode;
                 struct ucred *a_cred;                  kauth_cred_t a_cred;
                 struct proc *a_p;  
         } */ *ap = v;          } */ *ap = v;
         struct vattr va;          struct vattr va;
         int error;          int error;
   
         if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0)          if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0)
                 return (error);                  return (error);
   
         return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,          return kauth_authorize_vnode(ap->a_cred,
             ap->a_mode, ap->a_cred));              KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode),
               ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode,
               va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
 }  }
   
 static int  static int
 kernfs_default_fileop_getattr(v)  kernfs_default_fileop_getattr(void *v)
         void *v;  
 {  {
         struct vop_getattr_args /* {          struct vop_getattr_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 struct vattr *a_vap;                  struct vattr *a_vap;
                 struct ucred *a_cred;                  kauth_cred_t a_cred;
                 struct proc *a_p;  
         } */ *ap = v;          } */ *ap = v;
         struct vattr *vap = ap->a_vap;          struct vattr *vap = ap->a_vap;
   
Line 804  kernfs_default_fileop_getattr(v)
Line 609  kernfs_default_fileop_getattr(v)
 }  }
   
 int  int
 kernfs_getattr(v)  kernfs_getattr(void *v)
         void *v;  
 {  {
         struct vop_getattr_args /* {          struct vop_getattr_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 struct vattr *a_vap;                  struct vattr *a_vap;
                 struct ucred *a_cred;                  kauth_cred_t a_cred;
                 struct proc *a_p;  
         } */ *ap = v;          } */ *ap = v;
         struct kernfs_node *kfs = VTOKERN(ap->a_vp);          struct kernfs_node *kfs = VTOKERN(ap->a_vp);
         struct kernfs_subdir *ks;          struct kernfs_subdir *ks;
Line 820  kernfs_getattr(v)
Line 623  kernfs_getattr(v)
         char strbuf[KSTRING], *bf;          char strbuf[KSTRING], *bf;
         size_t nread, total;          size_t nread, total;
   
         VATTR_NULL(vap);          vattr_null(vap);
         vap->va_type = ap->a_vp->v_type;          vap->va_type = ap->a_vp->v_type;
         vap->va_uid = 0;          vap->va_uid = 0;
         vap->va_gid = 0;          vap->va_gid = 0;
Line 829  kernfs_getattr(v)
Line 632  kernfs_getattr(v)
         vap->va_flags = 0;          vap->va_flags = 0;
         vap->va_size = 0;          vap->va_size = 0;
         vap->va_blocksize = DEV_BSIZE;          vap->va_blocksize = DEV_BSIZE;
         /*          /* Make all times be current TOD, except for the "boottime" node. */
          * Make all times be current TOD, except for the "boottime" node.          if (kfs->kfs_kt->kt_namlen == 8 &&
          * Avoid microtime(9), it's slow.  
          * We don't guard the read from time(9) with splclock(9) since we  
          * don't actually need to be THAT sure the access is atomic.  
          */  
         if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 &&  
             !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {              !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
                 TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);                  vap->va_ctime = boottime;
         } else {          } else {
                 TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime);                  getnanotime(&vap->va_ctime);
         }          }
         vap->va_atime = vap->va_mtime = vap->va_ctime;          vap->va_atime = vap->va_mtime = vap->va_ctime;
         vap->va_gen = 0;          vap->va_gen = 0;
Line 853  kernfs_getattr(v)
Line 651  kernfs_getattr(v)
                 vap->va_bytes = vap->va_size = DEV_BSIZE;                  vap->va_bytes = vap->va_size = DEV_BSIZE;
                 break;                  break;
   
           case KFSdevice:
                   vap->va_nlink = 1;
                   vap->va_rdev = ap->a_vp->v_rdev;
                   break;
   
         case KFSroot:          case KFSroot:
                 vap->va_nlink = 1;                  vap->va_nlink = 1;
                 vap->va_bytes = vap->va_size = DEV_BSIZE;                  vap->va_bytes = vap->va_size = DEV_BSIZE;
Line 870  kernfs_getattr(v)
Line 673  kernfs_getattr(v)
         case KFSstring:          case KFSstring:
         case KFShostname:          case KFShostname:
         case KFSavenrun:          case KFSavenrun:
         case KFSdevice:  
         case KFSmsgbuf:          case KFSmsgbuf:
 #ifdef IPSEC  
         case KFSipsecsa:  
         case KFSipsecsp:  
 #endif  
                 vap->va_nlink = 1;                  vap->va_nlink = 1;
                 total = 0;                  total = 0;
                 do {                  do {
Line 887  kernfs_getattr(v)
Line 685  kernfs_getattr(v)
                 vap->va_bytes = vap->va_size = total;                  vap->va_bytes = vap->va_size = total;
                 break;                  break;
   
 #ifdef IPSEC  
         case KFSipsecsadir:  
         case KFSipsecspdir:  
                 vap->va_nlink = 2;  
                 vap->va_bytes = vap->va_size = DEV_BSIZE;  
                 break;  
 #endif  
   
         default:          default:
                 error = kernfs_try_fileop(kfs->kfs_type,                  error = kernfs_try_fileop(kfs->kfs_type,
                     KERNFS_FILEOP_GETATTR, v, EINVAL);                      KERNFS_FILEOP_GETATTR, v, EINVAL);
Line 906  kernfs_getattr(v)
Line 696  kernfs_getattr(v)
   
 /*ARGSUSED*/  /*ARGSUSED*/
 int  int
 kernfs_setattr(v)  kernfs_setattr(void *v)
         void *v;  
 {  {
   
         /*          /*
Line 920  kernfs_setattr(v)
Line 709  kernfs_setattr(v)
 }  }
   
 int  int
 kernfs_read(v)  kernfs_default_xread(void *v)
         void *v;  
 {  {
         struct vop_read_args /* {          struct vop_read_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 struct uio *a_uio;                  struct uio *a_uio;
                 int  a_ioflag;                  int  a_ioflag;
                 struct ucred *a_cred;                  kauth_cred_t a_cred;
         } */ *ap = v;          } */ *ap = v;
         struct uio *uio = ap->a_uio;          struct uio *uio = ap->a_uio;
         struct kernfs_node *kfs = VTOKERN(ap->a_vp);          struct kernfs_node *kfs = VTOKERN(ap->a_vp);
         char strbuf[KSTRING], *bf;          char strbuf[KSTRING], *bf;
         off_t off;          int off;
         size_t len;          size_t len;
         int error;          int error;
   
         if (ap->a_vp->v_type == VDIR)          if (ap->a_vp->v_type == VDIR)
                 return (EOPNOTSUPP);                  return EISDIR;
   
           off = (int)uio->uio_offset;
         /* Don't allow negative offsets */          /* Don't allow negative offsets */
         if (uio->uio_offset < 0)          if (off < 0)
                 return EINVAL;                  return EINVAL;
   
         off = uio->uio_offset;  
         bf = strbuf;          bf = strbuf;
         if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0)          if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0)
                 error = uiomove(bf, len, uio);                  error = uiomove(bf, len, uio);
         return (error);          return (error);
 }  }
   
   int
   kernfs_read(void *v)
   {
           struct vop_read_args /* {
                   struct vnode *a_vp;
                   struct uio *a_uio;
                   int  a_ioflag;
                   struct ucred *a_cred;
           } */ *ap = v;
           struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   
           if (kfs->kfs_type < KFSlasttype) {
                   /* use default function */
                   return kernfs_default_xread(v);
           }
           return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v,
              EOPNOTSUPP);
   }
   
 static int  static int
 kernfs_default_xwrite(v)  kernfs_default_xwrite(void *v)
         void *v;  
 {  {
         struct vop_write_args /* {          struct vop_write_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 struct uio *a_uio;                  struct uio *a_uio;
                 int  a_ioflag;                  int  a_ioflag;
                 struct ucred *a_cred;                  kauth_cred_t a_cred;
         } */ *ap = v;          } */ *ap = v;
         struct kernfs_node *kfs = VTOKERN(ap->a_vp);          struct kernfs_node *kfs = VTOKERN(ap->a_vp);
         struct uio *uio = ap->a_uio;          struct uio *uio = ap->a_uio;
         int error, xlen;          int error;
           size_t xlen;
         char strbuf[KSTRING];          char strbuf[KSTRING];
   
         if (uio->uio_offset != 0)          if (uio->uio_offset != 0)
Line 981  kernfs_default_xwrite(v)
Line 788  kernfs_default_xwrite(v)
 }  }
   
 int  int
 kernfs_write(v)  kernfs_write(void *v)
         void *v;  
 {  {
         struct vop_write_args /* {          struct vop_write_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 struct uio *a_uio;                  struct uio *a_uio;
                 int  a_ioflag;                  int  a_ioflag;
                 struct ucred *a_cred;                  kauth_cred_t a_cred;
         } */ *ap = v;          } */ *ap = v;
         struct kernfs_node *kfs = VTOKERN(ap->a_vp);          struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   
         return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 0);          if (kfs->kfs_type < KFSlasttype) {
                   /* use default function */
                   return kernfs_default_xwrite(v);
           }
           return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v,
               EOPNOTSUPP);
 }  }
   
 int  int
 kernfs_ioctl(v)  kernfs_ioctl(void *v)
         void *v;  
 {  {
         struct vop_ioctl_args /* {          struct vop_ioctl_args /* {
                 const struct vnodeop_desc *a_desc;                  const struct vnodeop_desc *a_desc;
Line 1005  kernfs_ioctl(v)
Line 815  kernfs_ioctl(v)
                 u_long a_command;                  u_long a_command;
                 void *a_data;                  void *a_data;
                 int a_fflag;                  int a_fflag;
                 struct ucred *a_cred;                  kauth_cred_t a_cred;
                 struct proc *a_p;  
         } */ *ap = v;          } */ *ap = v;
         struct kernfs_node *kfs = VTOKERN(ap->a_vp);          struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   
Line 1016  kernfs_ioctl(v)
Line 825  kernfs_ioctl(v)
   
 static int  static int
 kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,  kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
     u_int32_t value, struct vop_readdir_args *ap)      struct vop_readdir_args *ap)
 {  {
         struct kernfs_node *kfs;          struct kernfs_node *kfs;
         struct vnode *vp;          struct vnode *vp;
         int error;          int error;
   
         if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,          if ((error = vcache_get(ap->a_vp->v_mount, &kt, sizeof(kt), &vp)) != 0)
             value)) != 0)  
                 return error;                  return error;
         if (kt->kt_tag == KFSdevice) {          kfs = VTOKERN(vp);
                 struct vattr va;          d->d_fileno = kfs->kfs_fileno;
                 if ((error = VOP_GETATTR(vp, &va, ap->a_cred,          vrele(vp);
                     ap->a_uio->uio_segflg == UIO_USERSPACE ?  
                     ap->a_uio->uio_procp : &proc0)) != 0)  
                         return (error);  
                 d->d_fileno = va.va_fileid;  
         } else {  
                 kfs = VTOKERN(vp);  
                 d->d_fileno = kfs->kfs_fileno;  
         }  
         vput(vp);  
         return 0;          return 0;
 }  }
   
Line 1060  kernfs_setdirentfileno(struct dirent *d,
Line 859  kernfs_setdirentfileno(struct dirent *d,
                 break;                  break;
         }          }
         if (ikt != thisdir_kfs->kfs_kt) {          if (ikt != thisdir_kfs->kfs_kt) {
                 if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)                  if ((error = kernfs_setdirentfileno_kt(d, ikt, ap)) != 0)
                         return error;                          return error;
         } else          } else
                 d->d_fileno = thisdir_kfs->kfs_fileno;                  d->d_fileno = thisdir_kfs->kfs_fileno;
Line 1068  kernfs_setdirentfileno(struct dirent *d,
Line 867  kernfs_setdirentfileno(struct dirent *d,
 }  }
   
 int  int
 kernfs_readdir(v)  kernfs_readdir(void *v)
         void *v;  
 {  {
         struct vop_readdir_args /* {          struct vop_readdir_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 struct uio *a_uio;                  struct uio *a_uio;
                 struct ucred *a_cred;                  kauth_cred_t a_cred;
                 int *a_eofflag;                  int *a_eofflag;
                 off_t **a_cookies;                  off_t **a_cookies;
                 int a_*ncookies;                  int a_*ncookies;
Line 1089  kernfs_readdir(v)
Line 887  kernfs_readdir(v)
         int error;          int error;
         off_t *cookies = NULL;          off_t *cookies = NULL;
         int ncookies = 0, n;          int ncookies = 0, n;
 #ifdef IPSEC  
         struct secasvar *sav, *sav2;  
         struct secpolicy *sp;  
 #endif  
   
         if (uio->uio_resid < UIO_MX)          if (uio->uio_resid < UIO_MX)
                 return (EINVAL);                  return (EINVAL);
Line 1131  kernfs_readdir(v)
Line 925  kernfs_readdir(v)
                                                 break;                                                  break;
                                 } else {                                  } else {
                                         dkt = SIMPLEQ_NEXT(dkt, dkt_queue);                                          dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
                                         if (dkt == NULL)  
                                                 break;  
                                 }                                  }
                                   if (dkt == NULL)
                                           break;
                                 kt = &dkt->dkt_kt;                                  kt = &dkt->dkt_kt;
                         }                          }
                         if (kt->kt_tag == KFSdevice) {                          if (kt->kt_tag == KFSdevice) {
Line 1143  kernfs_readdir(v)
Line 937  kernfs_readdir(v)
                                 if (*dp == NODEV ||                                  if (*dp == NODEV ||
                                     !vfinddev(*dp, kt->kt_vtype, &fvp))                                      !vfinddev(*dp, kt->kt_vtype, &fvp))
                                         continue;                                          continue;
                                   vrele(fvp);
                           }
                           if (kt->kt_tag == KFSmsgbuf) {
                                   if (!msgbufenabled
                                       || msgbufp->msg_magic != MSG_MAGIC) {
                                           continue;
                                   }
                         }                          }
                         d.d_namlen = kt->kt_namlen;                          d.d_namlen = kt->kt_namlen;
                         if ((error = kernfs_setdirentfileno(&d, i, kfs,                          if ((error = kernfs_setdirentfileno(&d, i, kfs,
Line 1219  kernfs_readdir(v)
Line 1020  kernfs_readdir(v)
                                 if (*dp == NODEV ||                                  if (*dp == NODEV ||
                                     !vfinddev(*dp, kt->kt_vtype, &fvp))                                      !vfinddev(*dp, kt->kt_vtype, &fvp))
                                         continue;                                          continue;
                                   vrele(fvp);
                         }                          }
                         d.d_namlen = kt->kt_namlen;                          d.d_namlen = kt->kt_namlen;
                         if ((error = kernfs_setdirentfileno(&d, i, kfs,                          if ((error = kernfs_setdirentfileno(&d, i, kfs,
Line 1235  kernfs_readdir(v)
Line 1037  kernfs_readdir(v)
                 ncookies = n;                  ncookies = n;
                 break;                  break;
   
 #ifdef IPSEC  
         case KFSipsecsadir:  
                 /* count SA in the system */  
                 n = 0;  
                 TAILQ_FOREACH(sav, &satailq, tailq) {  
                         for (sav2 = TAILQ_FIRST(&satailq);  
                             sav2 != sav;  
                             sav2 = TAILQ_NEXT(sav2, tailq)) {  
                                 if (sav->spi == sav2->spi) {  
                                         /* multiple SA with same SPI */  
                                         break;  
                                 }  
                         }  
                         if (sav == sav2 || sav->spi != sav2->spi)  
                                 n++;  
                 }  
   
                 if (i >= nipsecsa_targets + n)  
                         return (0);  
   
                 if (ap->a_ncookies) {  
                         ncookies = min(ncookies, (n - i));  
                         cookies = malloc(ncookies * sizeof(off_t), M_TEMP,  
                             M_WAITOK);  
                         *ap->a_cookies = cookies;  
                 }  
   
                 n = 0;  
                 for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {  
                         kt = &ipsecsa_targets[i];  
                         d.d_namlen = kt->kt_namlen;  
                         if ((error = kernfs_setdirentfileno(&d, i, kfs,  
                             &kern_targets[0], kt, ap)) != 0)  
                                 break;  
                         memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);  
                         d.d_type = kt->kt_type;  
                         if ((error = uiomove(&d, UIO_MX, uio)) != 0)  
                                 break;  
                         if (cookies)  
                                 *cookies++ = i + 1;  
                         n++;  
                 }  
                 if (error) {  
                         ncookies = n;  
                         break;  
                 }  
   
                 TAILQ_FOREACH(sav, &satailq, tailq) {  
                         for (sav2 = TAILQ_FIRST(&satailq);  
                             sav2 != sav;  
                             sav2 = TAILQ_NEXT(sav2, tailq)) {  
                                 if (sav->spi == sav2->spi) {  
                                         /* multiple SA with same SPI */  
                                         break;  
                                 }  
                         }  
                         if (sav != sav2 && sav->spi == sav2->spi)  
                                 continue;  
                         if (uio->uio_resid < UIO_MX)  
                                 break;  
                         if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,  
                             sav->spi, ap)) != 0)  
                                 break;  
                         d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),  
                             "%u", ntohl(sav->spi));  
                         d.d_type = DT_REG;  
                         if ((error = uiomove(&d, UIO_MX, uio)) != 0)  
                                 break;  
                         if (cookies)  
                                 *cookies++ = i + 1;  
                         n++;  
                         i++;  
                 }  
                 ncookies = n;  
                 break;  
   
         case KFSipsecspdir:  
                 /* count SP in the system */  
                 n = 0;  
                 TAILQ_FOREACH(sp, &sptailq, tailq)  
                         n++;  
   
                 if (i >= nipsecsp_targets + n)  
                         return (0);  
   
                 if (ap->a_ncookies) {  
                         ncookies = min(ncookies, (n - i));  
                         cookies = malloc(ncookies * sizeof(off_t), M_TEMP,  
                             M_WAITOK);  
                         *ap->a_cookies = cookies;  
                 }  
   
                 n = 0;  
                 for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {  
                         kt = &ipsecsp_targets[i];  
                         d.d_namlen = kt->kt_namlen;  
                         if ((error = kernfs_setdirentfileno(&d, i, kfs,  
                             &kern_targets[0], kt, ap)) != 0)  
                                 break;  
                         memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);  
                         d.d_type = kt->kt_type;  
                         if ((error = uiomove(&d, UIO_MX, uio)) != 0)  
                                 break;  
                         if (cookies)  
                                 *cookies++ = i + 1;  
                         n++;  
                 }  
                 if (error) {  
                         ncookies = n;  
                         break;  
                 }  
   
                 TAILQ_FOREACH(sp, &sptailq, tailq) {  
                         if (uio->uio_resid < UIO_MX)  
                                 break;  
                         if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,  
                             sp->id, ap)) != 0)  
                                 break;  
                         d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),  
                             "%u", sp->id);  
                         d.d_type = DT_REG;  
                         if ((error = uiomove(&d, UIO_MX, uio)) != 0)  
                                 break;  
                         if (cookies)  
                                 *cookies++ = i + 1;  
                         n++;  
                         i++;  
                 }  
                 ncookies = n;  
                 break;  
 #endif  
   
         default:          default:
                 error = ENOTDIR;                  error = ENOTDIR;
                 break;                  break;
Line 1387  kernfs_readdir(v)
Line 1057  kernfs_readdir(v)
 }  }
   
 int  int
 kernfs_inactive(v)  kernfs_inactive(void *v)
         void *v;  
 {  {
         struct vop_inactive_args /* {          struct vop_inactive_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
                 struct proc *a_p;                  bool *a_recycle;
         } */ *ap = v;          } */ *ap = v;
         struct vnode *vp = ap->a_vp;          struct vnode *vp = ap->a_vp;
         const struct kernfs_node *kfs = VTOKERN(ap->a_vp);  
 #ifdef IPSEC  
         struct mbuf *m;  
         struct secpolicy *sp;  
 #endif  
   
         VOP_UNLOCK(vp, 0);          *ap->a_recycle = false;
         switch (kfs->kfs_type) {          VOP_UNLOCK(vp);
 #ifdef IPSEC  
         case KFSipsecsa:  
                 m = key_setdumpsa_spi(htonl(kfs->kfs_value));  
                 if (m)  
                         m_freem(m);  
                 else  
                         vgone(vp);  
                 break;  
         case KFSipsecsp:  
                 sp = key_getspbyid(kfs->kfs_value);  
                 if (sp)  
                         key_freesp(sp);  
                 else {  
                         /* should never happen as we hold a refcnt */  
                         vgone(vp);  
                 }  
                 break;  
 #endif  
         default:  
                 break;  
         }  
         return (0);          return (0);
 }  }
   
 int  int
 kernfs_reclaim(v)  kernfs_reclaim(void *v)
         void *v;  
 {  {
         struct vop_reclaim_args /* {          struct vop_reclaim_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
         } */ *ap = v;          } */ *ap = v;
           struct vnode *vp = ap->a_vp;
           struct kernfs_node *kfs = VTOKERN(vp);
   
         return (kernfs_freevp(ap->a_vp));          vp->v_data = NULL;
           vcache_remove(vp->v_mount, &kfs->kfs_kt, sizeof(kfs->kfs_kt));
           mutex_enter(&kfs_lock);
           TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list);
           mutex_exit(&kfs_lock);
           kmem_free(kfs, sizeof(struct kernfs_node));
   
           return 0;
 }  }
   
 /*  /*
  * Return POSIX pathconf information applicable to special devices.   * Return POSIX pathconf information applicable to special devices.
  */   */
 int  int
 kernfs_pathconf(v)  kernfs_pathconf(void *v)
         void *v;  
 {  {
         struct vop_pathconf_args /* {          struct vop_pathconf_args /* {
                 struct vnode *a_vp;                  struct vnode *a_vp;
Line 1484  kernfs_pathconf(v)
Line 1134  kernfs_pathconf(v)
  */   */
 /* ARGSUSED */  /* ARGSUSED */
 int  int
 kernfs_print(v)  kernfs_print(void *v)
         void *v;  
 {  {
   
         printf("tag VT_KERNFS, kernfs vnode\n");          printf("tag VT_KERNFS, kernfs vnode\n");
Line 1493  kernfs_print(v)
Line 1142  kernfs_print(v)
 }  }
   
 int  int
 kernfs_link(v)  kernfs_link(void *v)
         void *v;  
 {  {
         struct vop_link_args /* {          struct vop_link_args /* {
                 struct vnode *a_dvp;                  struct vnode *a_dvp;
Line 1508  kernfs_link(v)
Line 1156  kernfs_link(v)
 }  }
   
 int  int
 kernfs_symlink(v)  kernfs_symlink(void *v)
         void *v;  
 {  {
         struct vop_symlink_args /* {          struct vop_symlink_v3_args /* {
                 struct vnode *a_dvp;                  struct vnode *a_dvp;
                 struct vnode **a_vpp;                  struct vnode **a_vpp;
                 struct componentname *a_cnp;                  struct componentname *a_cnp;
Line 1520  kernfs_symlink(v)
Line 1167  kernfs_symlink(v)
         } */ *ap = v;          } */ *ap = v;
   
         VOP_ABORTOP(ap->a_dvp, ap->a_cnp);          VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
         vput(ap->a_dvp);  
         return (EROFS);          return (EROFS);
 }  }

Legend:
Removed from v.1.112  
changed lines
  Added in v.1.153

CVSweb <webmaster@jp.NetBSD.org>