[BACK]Return to puffs_vfsops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / puffs

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

Diff for /src/sys/fs/puffs/puffs_vfsops.c between version 1.16.2.3 and 1.16.2.4

version 1.16.2.3, 2007/02/26 09:10:58 version 1.16.2.4, 2007/09/03 14:40:30
Line 15 
Line 15 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    documentation and/or other materials provided with the distribution.
  * 3. The name of the company nor the name of the author may be used to  
  *    endorse or promote products derived from this software without specific  
  *    prior written permission.  
  *   *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED   * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Line 44  __KERNEL_RCSID(0, "$NetBSD$");
Line 41  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/dirent.h>  #include <sys/dirent.h>
 #include <sys/kauth.h>  #include <sys/kauth.h>
 #include <sys/fstrans.h>  #include <sys/fstrans.h>
   #include <sys/proc.h>
   
 #include <lib/libkern/libkern.h>  #include <lib/libkern/libkern.h>
   
 #include <fs/puffs/puffs_msgif.h>  #include <fs/puffs/puffs_msgif.h>
 #include <fs/puffs/puffs_sys.h>  #include <fs/puffs/puffs_sys.h>
   
   #include <nfs/nfsproto.h> /* for fh sizes */
   
 VFS_PROTOS(puffs);  VFS_PROTOS(puffs);
   
 MALLOC_DEFINE(M_PUFFS, "puffs", "pass-to-userspace file system structures");  MALLOC_JUSTDEFINE(M_PUFFS, "puffs", "Pass-to-Userspace Framework File System");
   
 #ifndef PUFFS_PNODEBUCKETS  #ifndef PUFFS_PNODEBUCKETS
 #define PUFFS_PNODEBUCKETS 256  #define PUFFS_PNODEBUCKETS 256
 #endif  #endif
 #ifndef PUFFS_MAXPNODEBUCKETS  #ifndef PUFFS_MAXPNODEBUCKETS
 #define PUFFS_MAXPNODEBUCKETS 65536  #define PUFFS_MAXPNODEBUCKETS 8192
 #endif  #endif
 int puffs_pnodebuckets = PUFFS_PNODEBUCKETS;  int puffs_pnodebuckets_default = PUFFS_PNODEBUCKETS;
   int puffs_maxpnodebuckets = PUFFS_MAXPNODEBUCKETS;
   
 int  int
 puffs_mount(struct mount *mp, const char *path, void *data,  puffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len,
             struct nameidata *ndp, struct lwp *l)              struct lwp *l)
 {  {
         struct puffs_mount *pmp = NULL;          struct puffs_mount *pmp = NULL;
         struct puffs_args *args;          struct puffs_kargs *args;
         char namebuf[PUFFSNAMESIZE+sizeof(PUFFS_NAMEPREFIX)+1]; /* spooky */          char fstype[_VFS_NAMELEN];
           char *p;
         int error = 0, i;          int error = 0, i;
   
           if (*data_len < sizeof *args)
                   return EINVAL;
   
         if (mp->mnt_flag & MNT_GETARGS) {          if (mp->mnt_flag & MNT_GETARGS) {
                 pmp = MPTOPUFFSMP(mp);                  pmp = MPTOPUFFSMP(mp);
                 return copyout(&pmp->pmp_args, data, sizeof(struct puffs_args));                  *(struct puffs_kargs *)data = pmp->pmp_args;
                   *data_len = sizeof *args;
                   return 0;
         }          }
   
         /* update is not supported currently */          /* update is not supported currently */
Line 86  puffs_mount(struct mount *mp, const char
Line 93  puffs_mount(struct mount *mp, const char
         if (!data)          if (!data)
                 return EINVAL;                  return EINVAL;
   
         MALLOC(args, struct puffs_args *, sizeof(struct puffs_args),          MALLOC(args, struct puffs_kargs *, sizeof(struct puffs_kargs),
             M_PUFFS, M_WAITOK);              M_PUFFS, M_WAITOK);
   
         error = copyin(data, args, sizeof(struct puffs_args));          *args = *(struct puffs_kargs *)data;
         if (error)  
                 goto out;  
   
         /* devel phase */          /* devel phase */
         if (args->pa_vers != (PUFFSVERSION | PUFFSDEVELVERS)) {          if (args->pa_vers != (PUFFSVERSION | PUFFSDEVELVERS)) {
Line 100  puffs_mount(struct mount *mp, const char
Line 105  puffs_mount(struct mount *mp, const char
                 goto out;                  goto out;
         }          }
   
         /* nuke spy bits */          if ((args->pa_flags & ~PUFFS_KFLAG_MASK) != 0) {
         args->pa_flags &= PUFFS_KFLAG_MASK;                  printf("puffs_mount: invalid KFLAGs 0x%x\n", args->pa_flags);
                   error = EINVAL;
                   goto out;
           }
           if ((args->pa_fhflags & ~PUFFS_FHFLAG_MASK) != 0) {
                   printf("puffs_mount: invalid FHFLAGs 0x%x\n", args->pa_fhflags);
                   error = EINVAL;
                   goto out;
           }
   
           /* use dummy value for passthrough */
           if (args->pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH)
                   args->pa_fhsize = sizeof(struct fid);
   
           /* sanitize file handle length */
           if (PUFFS_TOFHSIZE(args->pa_fhsize) > FHANDLE_SIZE_MAX) {
                   printf("puffs_mount: handle size %zu too large\n",
                       args->pa_fhsize);
                   error = EINVAL;
                   goto out;
           }
           /* sanity check file handle max sizes */
           if (args->pa_fhsize && args->pa_fhflags & PUFFS_FHFLAG_PROTOMASK) {
                   size_t kfhsize = PUFFS_TOFHSIZE(args->pa_fhsize);
   
                   if (args->pa_fhflags & PUFFS_FHFLAG_NFSV2) {
                           if (NFSX_FHTOOBIG_P(kfhsize, 0)) {
                                   printf("puffs_mount: fhsize larger than "
                                       "NFSv2 max %d\n",
                                       PUFFS_FROMFHSIZE(NFSX_V2FH));
                                   error = EINVAL;
                                   goto out;
                           }
                   }
   
                   if (args->pa_fhflags & PUFFS_FHFLAG_NFSV3) {
                           if (NFSX_FHTOOBIG_P(kfhsize, 1)) {
                                   printf("puffs_mount: fhsize larger than "
                                       "NFSv3 max %d\n",
                                       PUFFS_FROMFHSIZE(NFSX_V3FHMAX));
                                   error = EINVAL;
                                   goto out;
                           }
                   }
           }
   
           /* don't allow non-printing characters (like my sweet umlauts.. snif) */
           args->pa_typename[sizeof(args->pa_typename)-1] = '\0';
           for (p = args->pa_typename; *p; p++)
                   if (*p < ' ' || *p > '~')
                           *p = '.';
   
           args->pa_mntfromname[sizeof(args->pa_mntfromname)-1] = '\0';
           for (p = args->pa_mntfromname; *p; p++)
                   if (*p < ' ' || *p > '~')
                           *p = '.';
   
         /* build real name */          /* build real name */
         (void)strlcpy(namebuf, PUFFS_NAMEPREFIX, sizeof(namebuf));          (void)strlcpy(fstype, PUFFS_TYPEPREFIX, sizeof(fstype));
         (void)strlcat(namebuf, args->pa_name, sizeof(namebuf));          (void)strlcat(fstype, args->pa_typename, sizeof(fstype));
   
         /* inform user server if it got the max request size it wanted */          /* inform user server if it got the max request size it wanted */
         if (args->pa_maxreqlen == 0 || args->pa_maxreqlen > PUFFS_REQ_MAXSIZE)          if (args->pa_maxreqlen == 0 || args->pa_maxreqlen > PUFFS_REQ_MAXSIZE)
                 args->pa_maxreqlen = PUFFS_REQ_MAXSIZE;                  args->pa_maxreqlen = PUFFS_REQ_MAXSIZE;
         else if (args->pa_maxreqlen < PUFFS_REQSTRUCT_MAX)          else if (args->pa_maxreqlen < 2*PUFFS_REQSTRUCT_MAX)
                 args->pa_maxreqlen = PUFFS_REQSTRUCT_MAX;                  args->pa_maxreqlen = 2*PUFFS_REQSTRUCT_MAX;
         (void)strlcpy(args->pa_name, namebuf, sizeof(args->pa_name));          (void)strlcpy(args->pa_typename, fstype, sizeof(args->pa_typename));
   
         error = copyout(args, data, sizeof(struct puffs_args));          if (args->pa_nhashbuckets == 0)
         if (error)                  args->pa_nhashbuckets = puffs_pnodebuckets_default;
                 goto out;          if (args->pa_nhashbuckets < 1)
                   args->pa_nhashbuckets = 1;
           if (args->pa_nhashbuckets > PUFFS_MAXPNODEBUCKETS) {
                   args->pa_nhashbuckets = puffs_maxpnodebuckets;
                   printf("puffs_mount: using %d hash buckets. "
                       "adjust puffs_maxpnodebuckets for more\n",
                       puffs_maxpnodebuckets);
           }
   
         error = set_statvfs_info(path, UIO_USERSPACE, namebuf,          error = set_statvfs_info(path, UIO_USERSPACE, args->pa_mntfromname,
             UIO_SYSSPACE, mp, l);              UIO_SYSSPACE, fstype, mp, l);
         if (error)          if (error)
                 goto out;                  goto out;
         mp->mnt_stat.f_iosize = DEV_BSIZE;          mp->mnt_stat.f_iosize = DEV_BSIZE;
   
           /*
            * We can't handle the VFS_STATVFS() mount_domount() does
            * after VFS_MOUNT() because we'd deadlock, so handle it
            * here already.
            */
           copy_statvfs_info(&args->pa_svfsb, mp);
           (void)memcpy(&mp->mnt_stat, &args->pa_svfsb, sizeof(mp->mnt_stat));
   
         MALLOC(pmp, struct puffs_mount *, sizeof(struct puffs_mount),          MALLOC(pmp, struct puffs_mount *, sizeof(struct puffs_mount),
             M_PUFFS, M_WAITOK | M_ZERO);              M_PUFFS, M_WAITOK | M_ZERO);
   
Line 139  puffs_mount(struct mount *mp, const char
Line 214  puffs_mount(struct mount *mp, const char
         pmp->pmp_req_maxsize = args->pa_maxreqlen;          pmp->pmp_req_maxsize = args->pa_maxreqlen;
         pmp->pmp_args = *args;          pmp->pmp_args = *args;
   
         /* puffs_node hash buckets */          pmp->pmp_npnodehash = args->pa_nhashbuckets;
         pmp->pmp_npnodehash = puffs_pnodebuckets;  
         if (pmp->pmp_npnodehash < 1)  
                 pmp->pmp_npnodehash = 1;  
         if (pmp->pmp_npnodehash > PUFFS_MAXPNODEBUCKETS)  
                 pmp->pmp_npnodehash = PUFFS_MAXPNODEBUCKETS;  
         pmp->pmp_pnodehash = malloc          pmp->pmp_pnodehash = malloc
             (sizeof(struct puffs_pnode_hashlist *) * pmp->pmp_npnodehash,              (sizeof(struct puffs_pnode_hashlist *) * pmp->pmp_npnodehash,
             M_PUFFS, M_WAITOK);              M_PUFFS, M_WAITOK);
Line 161  puffs_mount(struct mount *mp, const char
Line 231  puffs_mount(struct mount *mp, const char
                 goto out;                  goto out;
         }          }
   
         simple_lock_init(&pmp->pmp_lock);          /* XXX: check parameters */
           pmp->pmp_root_cookie = args->pa_root_cookie;
           pmp->pmp_root_vtype = args->pa_root_vtype;
           pmp->pmp_root_vsize = args->pa_root_vsize;
           pmp->pmp_root_rdev = args->pa_root_rdev;
   
           mutex_init(&pmp->pmp_lock, MUTEX_DEFAULT, IPL_NONE);
           cv_init(&pmp->pmp_req_waiter_cv, "puffsget");
           cv_init(&pmp->pmp_refcount_cv, "puffsref");
           cv_init(&pmp->pmp_unmounting_cv, "puffsum");
         TAILQ_INIT(&pmp->pmp_req_touser);          TAILQ_INIT(&pmp->pmp_req_touser);
         TAILQ_INIT(&pmp->pmp_req_replywait);          TAILQ_INIT(&pmp->pmp_req_replywait);
         TAILQ_INIT(&pmp->pmp_req_sizepark);          TAILQ_INIT(&pmp->pmp_req_sizepark);
Line 180  puffs_mount(struct mount *mp, const char
Line 259  puffs_mount(struct mount *mp, const char
         return error;          return error;
 }  }
   
 /*  
  * This is called from the first "Hello, I'm alive" ioctl  
  * from userspace.  
  */  
 int  int
 puffs_start2(struct puffs_mount *pmp, struct puffs_startreq *sreq)  puffs_start(struct mount *mp, int flags, struct lwp *l)
 {  {
         struct puffs_node *pn;          struct puffs_mount *pmp = MPTOPUFFSMP(mp);
         struct mount *mp;  
   
         mp = PMPTOMP(pmp);  
   
         simple_lock(&pmp->pmp_lock);          KASSERT(pmp->pmp_status == PUFFSTAT_MOUNTING);
   
         /*  
          * if someone has issued a VFS_ROOT() already, fill in the  
          * vnode cookie.  
          */  
         pn = NULL;  
         if (pmp->pmp_root) {  
                 pn = VPTOPP(pmp->pmp_root);  
                 pn->pn_cookie = sreq->psr_cookie;  
         }  
   
         /* We're good to fly */  
         pmp->pmp_rootcookie = sreq->psr_cookie;  
         pmp->pmp_status = PUFFSTAT_RUNNING;          pmp->pmp_status = PUFFSTAT_RUNNING;
         simple_unlock(&pmp->pmp_lock);  
   
         /* do the VFS_STATVFS() we missed out on in sys_mount() */  
         copy_statvfs_info(&sreq->psr_sb, mp);  
         (void)memcpy(&mp->mnt_stat, &sreq->psr_sb, sizeof(mp->mnt_stat));  
         mp->mnt_stat.f_iosize = DEV_BSIZE;  
   
         DPRINTF(("puffs_start2: root vp %p, cur root pnode %p, cookie %p\n",  
             pmp->pmp_root, pn, sreq->psr_cookie));  
   
         return 0;          return 0;
 }  }
   
 int  int
 puffs_start(struct mount *mp, int flags, struct lwp *l)  
 {  
   
         /*  
          * This cannot travel to userspace, as this is called from  
          * the kernel context of the process doing mount(2).  But  
          * it's probably a safe bet that the process doing mount(2)  
          * realizes it needs to start the filesystem also...  
          */  
         return 0;  
 }  
   
 int  
 puffs_unmount(struct mount *mp, int mntflags, struct lwp *l)  puffs_unmount(struct mount *mp, int mntflags, struct lwp *l)
 {  {
         struct puffs_mount *pmp;          struct puffs_mount *pmp;
Line 264  puffs_unmount(struct mount *mp, int mntf
Line 301  puffs_unmount(struct mount *mp, int mntf
          * If we are not DYING, we should ask userspace's opinion           * If we are not DYING, we should ask userspace's opinion
          * about the situation           * about the situation
          */           */
         simple_lock(&pmp->pmp_lock);          mutex_enter(&pmp->pmp_lock);
         if (pmp->pmp_status != PUFFSTAT_DYING) {          if (pmp->pmp_status != PUFFSTAT_DYING) {
                 pmp->pmp_unmounting = 1;                  pmp->pmp_unmounting = 1;
                 simple_unlock(&pmp->pmp_lock);                  mutex_exit(&pmp->pmp_lock);
   
                 unmount_arg.pvfsr_flags = mntflags;                  unmount_arg.pvfsr_flags = mntflags;
                 unmount_arg.pvfsr_pid = puffs_lwp2pid(l);                  puffs_cidcvt(&unmount_arg.pvfsr_cid, l);
   
                 error = puffs_vfstouser(pmp, PUFFS_VFS_UNMOUNT,                  error = puffs_vfstouser(pmp, PUFFS_VFS_UNMOUNT,
                      &unmount_arg, sizeof(unmount_arg));                       &unmount_arg, sizeof(unmount_arg));
                 DPRINTF(("puffs_unmount: error %d force %d\n", error, force));                  DPRINTF(("puffs_unmount: error %d force %d\n", error, force));
   
                 simple_lock(&pmp->pmp_lock);                  mutex_enter(&pmp->pmp_lock);
                 pmp->pmp_unmounting = 0;                  pmp->pmp_unmounting = 0;
                 wakeup(&pmp->pmp_unmounting);                  cv_broadcast(&pmp->pmp_unmounting_cv);
         }          }
   
         /*          /*
Line 291  puffs_unmount(struct mount *mp, int mntf
Line 328  puffs_unmount(struct mount *mp, int mntf
                 puffs_nukebypmp(pmp);                  puffs_nukebypmp(pmp);
   
                 /*                  /*
                  * Sink waiters.  This is still not perfect, since the                   * Wait until there are no more users for the mount resource.
                  * draining is done after userret, not when they really                   * Notice that this is hooked against transport_close
                  * exit the file system.  It will probably work as almost                   * and return from touser.  In an ideal world, it would
                  * no call will block and therefore cause a context switch                   * be hooked against final return from all operations.
                  * and therefore will protected by the biglock after                   * But currently it works well enough, since nobody
                  * exiting userspace.  But ... it's an imperfect world.                   * does weird blocking voodoo after return from touser().
                  */                   */
                 while (pmp->pmp_req_touser_waiters != 0)                  while (pmp->pmp_refcount != 0)
                         ltsleep(&pmp->pmp_req_touser_waiters, PVFS,                          cv_wait(&pmp->pmp_refcount_cv, &pmp->pmp_lock);
                             "puffsink", 0, &pmp->pmp_lock);                  mutex_exit(&pmp->pmp_lock);
                 simple_unlock(&pmp->pmp_lock);  
   
                 /* free resources now that we hopefully have no waiters left */                  /* free resources now that we hopefully have no waiters left */
                   cv_destroy(&pmp->pmp_unmounting_cv);
                   cv_destroy(&pmp->pmp_refcount_cv);
                   cv_destroy(&pmp->pmp_req_waiter_cv);
                   mutex_destroy(&pmp->pmp_lock);
   
                 free(pmp->pmp_pnodehash, M_PUFFS);                  free(pmp->pmp_pnodehash, M_PUFFS);
                 FREE(pmp, M_PUFFS);                  FREE(pmp, M_PUFFS);
                 error = 0;                  error = 0;
         } else {          } else {
                 simple_unlock(&pmp->pmp_lock);                  mutex_exit(&pmp->pmp_lock);
         }          }
   
  out:   out:
Line 322  puffs_unmount(struct mount *mp, int mntf
Line 363  puffs_unmount(struct mount *mp, int mntf
 int  int
 puffs_root(struct mount *mp, struct vnode **vpp)  puffs_root(struct mount *mp, struct vnode **vpp)
 {  {
         struct puffs_mount *pmp;          struct puffs_mount *pmp = MPTOPUFFSMP(mp);
         struct puffs_node *pn;  
         struct vnode *vp;  
   
         pmp = MPTOPUFFSMP(mp);          return puffs_pnode2vnode(pmp, pmp->pmp_root_cookie, 1, vpp);
   
         /*  
          * pmp_lock must be held if vref()'ing or vrele()'ing the  
          * root vnode.  the latter is controlled by puffs_inactive().  
          */  
         simple_lock(&pmp->pmp_lock);  
         vp = pmp->pmp_root;  
         if (vp) {  
                 simple_lock(&vp->v_interlock);  
                 simple_unlock(&pmp->pmp_lock);  
                 pn = VPTOPP(vp);  
                 if (vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_INTERLOCK))  
                         goto grabnew;  
                 *vpp = vp;  
                 return 0;  
         } else  
                 simple_unlock(&pmp->pmp_lock);  
   
         /* XXX: this is wrong, so FIXME */  
  grabnew:  
   
         /*  
          * So, didn't have the magic root vnode available.  
          * No matter, grab another an stuff it with the cookie.  
          */  
         if (puffs_getvnode(mp, pmp->pmp_rootcookie, VDIR, 0, 0, &vp))  
                 panic("sloppy programming");  
   
         simple_lock(&pmp->pmp_lock);  
         /*  
          * check if by mysterious force someone else created a root  
          * vnode while we were executing.  
          */  
         if (pmp->pmp_root) {  
                 vref(pmp->pmp_root);  
                 simple_unlock(&pmp->pmp_lock);  
                 puffs_putvnode(vp);  
                 vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);  
                 *vpp = pmp->pmp_root;  
                 return 0;  
         }  
   
         /* store cache */  
         vp->v_flag = VROOT;  
         pmp->pmp_root = vp;  
         simple_unlock(&pmp->pmp_lock);  
   
         vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);  
   
         *vpp = vp;  
         return 0;  
 }  
   
 int  
 puffs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg, struct lwp *l)  
 {  
   
         return EOPNOTSUPP;  
 }  }
   
 int  int
Line 408  puffs_statvfs(struct mount *mp, struct s
Line 389  puffs_statvfs(struct mount *mp, struct s
         /* too big for stack */          /* too big for stack */
         MALLOC(statvfs_arg, struct puffs_vfsreq_statvfs *,          MALLOC(statvfs_arg, struct puffs_vfsreq_statvfs *,
             sizeof(struct puffs_vfsreq_statvfs), M_PUFFS, M_WAITOK | M_ZERO);              sizeof(struct puffs_vfsreq_statvfs), M_PUFFS, M_WAITOK | M_ZERO);
         statvfs_arg->pvfsr_pid = puffs_lwp2pid(l);          puffs_cidcvt(&statvfs_arg->pvfsr_cid, l);
   
         error = puffs_vfstouser(pmp, PUFFS_VFS_STATVFS,          error = puffs_vfstouser(pmp, PUFFS_VFS_STATVFS,
             statvfs_arg, sizeof(*statvfs_arg));              statvfs_arg, sizeof(*statvfs_arg));
Line 433  puffs_statvfs(struct mount *mp, struct s
Line 414  puffs_statvfs(struct mount *mp, struct s
 }  }
   
 static int  static int
 pageflush(struct mount *mp, int waitfor, int suspending)  pageflush(struct mount *mp, kauth_cred_t cred,
           int waitfor, int suspending, struct lwp *l)
 {  {
         struct puffs_node *pn;          struct puffs_node *pn;
         struct vnode *vp, *nvp;          struct vnode *vp, *nvp;
         int error, rv, ppflags;          int error, rv;
   
         KASSERT(((waitfor == MNT_WAIT) && suspending) == 0);          KASSERT(((waitfor == MNT_WAIT) && suspending) == 0);
         KASSERT((suspending == 0)          KASSERT((suspending == 0)
Line 445  pageflush(struct mount *mp, int waitfor,
Line 427  pageflush(struct mount *mp, int waitfor,
               && fstrans_getstate(mp) == FSTRANS_SUSPENDING));                && fstrans_getstate(mp) == FSTRANS_SUSPENDING));
   
         error = 0;          error = 0;
         ppflags = PGO_CLEANIT | PGO_ALLPAGES;  
         if (waitfor == MNT_WAIT)  
                 ppflags |= PGO_SYNCIO;  
   
         /*          /*
          * Sync all cached data from regular vnodes (which are not           * Sync all cached data from regular vnodes (which are not
Line 520  pageflush(struct mount *mp, int waitfor,
Line 499  pageflush(struct mount *mp, int waitfor,
                  * storage.                   * storage.
                  * TODO: Maybe also hint the user server of this twist?                   * TODO: Maybe also hint the user server of this twist?
                  */                   */
                 simple_lock(&vp->v_interlock);                  if (suspending || waitfor == MNT_LAZY) {
                 if (suspending || waitfor == MNT_LAZY)                          simple_lock(&vp->v_interlock);
                         pn->pn_stat |= PNODE_SUSPEND;                          pn->pn_stat |= PNODE_SUSPEND;
                 rv = VOP_PUTPAGES(vp, 0, 0, ppflags);                          simple_unlock(&vp->v_interlock);
                   }
                   rv = VOP_FSYNC(vp, cred, waitfor, 0, 0, l);
                 if (suspending || waitfor == MNT_LAZY) {                  if (suspending || waitfor == MNT_LAZY) {
                         simple_lock(&vp->v_interlock);                          simple_lock(&vp->v_interlock);
                         pn->pn_stat &= ~PNODE_SUSPEND;                          pn->pn_stat &= ~PNODE_SUSPEND;
Line 547  puffs_sync(struct mount *mp, int waitfor
Line 528  puffs_sync(struct mount *mp, int waitfor
   
         PUFFS_VFSREQ(sync);          PUFFS_VFSREQ(sync);
   
         error = pageflush(mp, waitfor, 0);          error = pageflush(mp, cred, waitfor, 0, l);
   
         /* sync fs */          /* sync fs */
         sync_arg.pvfsr_waitfor = waitfor;          sync_arg.pvfsr_waitfor = waitfor;
         puffs_credcvt(&sync_arg.pvfsr_cred, cred);          puffs_credcvt(&sync_arg.pvfsr_cred, cred);
         sync_arg.pvfsr_pid = puffs_lwp2pid(l);          puffs_cidcvt(&sync_arg.pvfsr_cid, l);
   
         rv = puffs_vfstouser(MPTOPUFFSMP(mp), PUFFS_VFS_SYNC,          rv = puffs_vfstouser(MPTOPUFFSMP(mp), PUFFS_VFS_SYNC,
             &sync_arg, sizeof(sync_arg));              &sync_arg, sizeof(sync_arg));
Line 563  puffs_sync(struct mount *mp, int waitfor
Line 544  puffs_sync(struct mount *mp, int waitfor
 }  }
   
 int  int
 puffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)  puffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
 {  {
           struct puffs_mount *pmp = MPTOPUFFSMP(mp);
           struct puffs_vfsreq_fhtonode *fhtonode_argp;
           struct vnode *vp;
           void *fhdata;
           size_t argsize, fhlen;
           int error;
   
         return EOPNOTSUPP;          if (pmp->pmp_args.pa_fhsize == 0)
 }                  return EOPNOTSUPP;
   
 #if 0          if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) {
 /*ARGSUSED*/                  fhlen = fhp->fid_len;
 int                  fhdata = fhp;
 puffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)          } else {
 {                  fhlen = PUFFS_FROMFHSIZE(fhp->fid_len);
                   fhdata = fhp->fid_data;
   
         return EOPNOTSUPP;                  if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC) {
                           if (pmp->pmp_args.pa_fhsize < fhlen)
                                   return EINVAL;
                   } else {
                           if (pmp->pmp_args.pa_fhsize != fhlen)
                                   return EINVAL;
                   }
           }
   
           argsize = sizeof(struct puffs_vfsreq_fhtonode) + fhlen;
           fhtonode_argp = malloc(argsize, M_PUFFS, M_ZERO | M_WAITOK);
           fhtonode_argp->pvfsr_dsize = fhlen;
           memcpy(fhtonode_argp->pvfsr_data, fhdata, fhlen);
   
           error = puffs_vfstouser(pmp, PUFFS_VFS_FHTOVP, fhtonode_argp, argsize);
           if (error)
                   goto out;
   
           error = puffs_pnode2vnode(pmp, fhtonode_argp->pvfsr_fhcookie, 1, &vp);
           DPRINTF(("puffs_fhtovp: got cookie %p, existing vnode %p\n",
               fhtonode_argp->pvfsr_fhcookie, vp));
           if (error) {
                   error = puffs_getvnode(mp, fhtonode_argp->pvfsr_fhcookie,
                       fhtonode_argp->pvfsr_vtype, fhtonode_argp->pvfsr_size,
                       fhtonode_argp->pvfsr_rdev, &vp);
                   if (error)
                           goto out;
                   vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
           }
   
           *vpp = vp;
    out:
           free(fhtonode_argp, M_PUFFS);
           return error;
 }  }
   
 /*ARGSUSED*/  
 int  int
 puffs_vptofh(struct vnode *vp, struct fid *fhp)  puffs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
 {  {
           struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
           struct puffs_vfsreq_nodetofh *nodetofh_argp;
           size_t argsize, fhlen;
           int error;
   
         return EOPNOTSUPP;          if (pmp->pmp_args.pa_fhsize == 0)
                   return EOPNOTSUPP;
   
           /* if file handles are static len, we can test len immediately */
           if (((pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC) == 0)
               && ((pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) == 0)
               && (PUFFS_FROMFHSIZE(*fh_size) < pmp->pmp_args.pa_fhsize)) {
                   *fh_size = PUFFS_TOFHSIZE(pmp->pmp_args.pa_fhsize);
                   return E2BIG;
           }
   
           if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH)
                   fhlen = *fh_size;
           else
                   fhlen = PUFFS_FROMFHSIZE(*fh_size);
   
           argsize = sizeof(struct puffs_vfsreq_nodetofh) + fhlen;
           nodetofh_argp = malloc(argsize, M_PUFFS, M_ZERO | M_WAITOK);
           nodetofh_argp->pvfsr_fhcookie = VPTOPNC(vp);
           nodetofh_argp->pvfsr_dsize = fhlen;
   
           error = puffs_vfstouser(pmp, PUFFS_VFS_VPTOFH, nodetofh_argp, argsize);
   
           if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH)
                   fhlen = nodetofh_argp->pvfsr_dsize;
           else if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC)
                   fhlen = PUFFS_TOFHSIZE(nodetofh_argp->pvfsr_dsize);
           else
                   fhlen = PUFFS_TOFHSIZE(pmp->pmp_args.pa_fhsize);
   
           if (error) {
                   if (error == E2BIG)
                           *fh_size = fhlen;
                   goto out;
           }
   
           if (fhlen > FHANDLE_SIZE_MAX) {
                   /* XXX: wrong direction */
                   error = EINVAL;
                   goto out;
           }
   
           if (*fh_size < fhlen) {
                   *fh_size = fhlen;
                   error = E2BIG;
                   goto out;
           }
           *fh_size = fhlen;
   
           if (fhp) {
                   if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) {
                           memcpy(fhp, nodetofh_argp->pvfsr_data, fhlen);
                   } else {
                           fhp->fid_len = *fh_size;
                           memcpy(fhp->fid_data, nodetofh_argp->pvfsr_data,
                               nodetofh_argp->pvfsr_dsize);
                   }
           }
   
    out:
           free(nodetofh_argp, M_PUFFS);
           return error;
 }  }
 #endif  
   
 void  void
 puffs_init()  puffs_init()
 {  {
   
 #ifdef _LKM  
         malloc_type_attach(M_PUFFS);          malloc_type_attach(M_PUFFS);
         pool_init(&puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0,  
             "puffspnpl", &pool_allocator_nointr);  
 #endif  
   
         return;          pool_init(&puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0,
               "puffpnpl", &pool_allocator_nointr, IPL_NONE);
           puffs_transport_init();
           puffs_msgif_init();
 }  }
   
 void  void
 puffs_done()  puffs_done()
 {  {
   
 #ifdef _LKM          puffs_msgif_destroy();
           puffs_transport_destroy();
         pool_destroy(&puffs_pnpool);          pool_destroy(&puffs_pnpool);
         malloc_type_detach(M_PUFFS);  
 #endif  
   
         return;          malloc_type_detach(M_PUFFS);
 }  }
   
 int  int
Line 633  puffs_suspendctl(struct mount *mp, int c
Line 715  puffs_suspendctl(struct mount *mp, int c
                         break;                          break;
                 puffs_suspendtouser(pmp, PUFFS_SUSPEND_START);                  puffs_suspendtouser(pmp, PUFFS_SUSPEND_START);
   
                 error = pageflush(mp, 0, 1);                  error = pageflush(mp, FSCRED, 0, 1, curlwp);
                 if (error == 0)                  if (error == 0)
                         error = fstrans_setstate(mp, FSTRANS_SUSPENDED);                          error = fstrans_setstate(mp, FSTRANS_SUSPENDED);
   
Line 673  const struct vnodeopv_desc * const puffs
Line 755  const struct vnodeopv_desc * const puffs
   
 struct vfsops puffs_vfsops = {  struct vfsops puffs_vfsops = {
         MOUNT_PUFFS,          MOUNT_PUFFS,
           sizeof (struct puffs_kargs),
         puffs_mount,            /* mount        */          puffs_mount,            /* mount        */
         puffs_start,            /* start        */          puffs_start,            /* start        */
         puffs_unmount,          /* unmount      */          puffs_unmount,          /* unmount      */
         puffs_root,             /* root         */          puffs_root,             /* root         */
         puffs_quotactl,         /* quotactl     */          (void *)eopnotsupp,     /* quotactl     */
         puffs_statvfs,          /* statvfs      */          puffs_statvfs,          /* statvfs      */
         puffs_sync,             /* sync         */          puffs_sync,             /* sync         */
         puffs_vget,             /* vget         */          (void *)eopnotsupp,     /* vget         */
         (void *)eopnotsupp,     /* fhtovp       */          puffs_fhtovp,           /* fhtovp       */
         (void *)eopnotsupp,     /* vptofh       */          puffs_vptofh,           /* vptofh       */
         puffs_init,             /* init         */          puffs_init,             /* init         */
         NULL,                   /* reinit       */          NULL,                   /* reinit       */
         puffs_done,             /* done         */          puffs_done,             /* done         */

Legend:
Removed from v.1.16.2.3  
changed lines
  Added in v.1.16.2.4

CVSweb <webmaster@jp.NetBSD.org>