[BACK]Return to puffs_msgif.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_msgif.c between version 1.20.2.1 and 1.21

version 1.20.2.1, 2007/03/29 19:27:54 version 1.21, 2007/03/20 10:21:58
Line 45  __KERNEL_RCSID(0, "$NetBSD$");
Line 45  __KERNEL_RCSID(0, "$NetBSD$");
 #include <fs/puffs/puffs_msgif.h>  #include <fs/puffs/puffs_msgif.h>
 #include <fs/puffs/puffs_sys.h>  #include <fs/puffs/puffs_sys.h>
   
 /*  
  * waitq data structures  
  */  
   
 /*  
  * While a request is going to userspace, park the caller within the  
  * kernel.  This is the kernel counterpart of "struct puffs_req".  
  */  
 struct puffs_park {  
         struct puffs_req        *park_preq;     /* req followed by buf  */  
         uint64_t                park_id;        /* duplicate of preq_id */  
   
         size_t                  park_copylen;   /* userspace copylength */  
         size_t                  park_maxlen;    /* max size in comeback */  
         struct buf              *park_bp;       /* bp, ASYNCBIOREAD     */  
   
         int                     park_flags;  
   
         kcondvar_t              park_cv;  
         kmutex_t                park_ilck;  
   
         TAILQ_ENTRY(puffs_park) park_entries;  
 };  
 #define PARKFLAG_WAITERGONE     0x01  
 #define PARKFLAG_PROCESSING     0x02  
 #define PARKFLAG_ASYNCBIOREAD   0x04  
   
 static struct pool_cache parkpc;  
 static struct pool parkpool;  
   
 static int  
 makepark(void *arg, void *obj, int flags)  
 {  
         struct puffs_park *park = obj;  
   
         cv_init(&park->park_cv, "puffsrpl");  
   
         return 0;  
 }  
   
 static void  
 nukepark(void *arg, void *obj)  
 {  
         struct puffs_park *park = obj;  
   
         cv_destroy(&park->park_cv);  
 }  
   
 void  
 puffs_msgif_init()  
 {  
   
         pool_init(&parkpool, sizeof(struct puffs_park), 0, 0, 0,  
             "puffprkl", &pool_allocator_nointr, IPL_NONE);  
         pool_cache_init(&parkpc, &parkpool, makepark, nukepark, NULL);  
 }  
   
 void  
 puffs_msgif_destroy()  
 {  
   
         pool_cache_destroy(&parkpc);  
         pool_destroy(&parkpool);  
 }  
   
 void *  
 puffs_parkmem_alloc(int waitok)  
 {  
   
         return pool_cache_get(&parkpc, waitok ? PR_WAITOK : PR_NOWAIT);  
 }  
   
 void  
 puffs_parkmem_free(void *ppark)  
 {  
   
         pool_cache_put(&parkpc, ppark);  
 }  
   
   
 /*  
  * Converts a non-FAF op to a FAF.  This simply involves making copies  
  * of the park and request structures and tagging the request as a FAF.  
  * It is safe to block here, since the original op is not a FAF.  
  */  
 #if 0  
 static void  
 puffs_reqtofaf(struct puffs_park *ppark)  
 {  
         struct puffs_req *newpreq;  
   
         KASSERT((ppark->park_preq->preq_opclass & PUFFSOPFLAG_FAF) == 0);  
   
         MALLOC(newpreq, struct puffs_req *, ppark->park_copylen,  
             M_PUFFS, M_ZERO | M_WAITOK);  
   
         memcpy(newpreq, ppark->park_preq, ppark->park_copylen);  
   
         ppark->park_preq = newpreq;  
         ppark->park_preq->preq_opclass |= PUFFSOPFLAG_FAF;  
 }  
 #endif  
   
   
 /*  /*
  * kernel-user-kernel waitqueues   * kernel-user-kernel waitqueues
Line 161  puffs_getreqid(struct puffs_mount *pmp)
Line 58  puffs_getreqid(struct puffs_mount *pmp)
 {  {
         uint64_t rv;          uint64_t rv;
   
         mutex_enter(&pmp->pmp_lock);          simple_lock(&pmp->pmp_lock);
         rv = pmp->pmp_nextreq++;          rv = pmp->pmp_nextreq++;
         mutex_exit(&pmp->pmp_lock);          simple_unlock(&pmp->pmp_lock);
   
         return rv;          return rv;
 }  }
Line 172  puffs_getreqid(struct puffs_mount *pmp)
Line 69  puffs_getreqid(struct puffs_mount *pmp)
 int  int
 puffs_vfstouser(struct puffs_mount *pmp, int optype, void *kbuf, size_t buflen)  puffs_vfstouser(struct puffs_mount *pmp, int optype, void *kbuf, size_t buflen)
 {  {
         struct puffs_park *ppark;          struct puffs_park park;
   
         ppark = pool_cache_get(&parkpc, PR_WAITOK);          park.park_preq = kbuf;
         ppark->park_preq = kbuf;  
   
         ppark->park_preq->preq_opclass = PUFFSOP_VFS;          park.park_preq->preq_opclass = PUFFSOP_VFS;
         ppark->park_preq->preq_optype = optype;          park.park_preq->preq_optype = optype;
   
         ppark->park_maxlen = ppark->park_copylen = buflen;          park.park_maxlen = park.park_copylen = buflen;
         ppark->park_flags = 0;          park.park_flags = 0;
   
         return touser(pmp, ppark, puffs_getreqid(pmp), NULL, NULL);          return touser(pmp, &park, puffs_getreqid(pmp), NULL, NULL);
 }  }
   
 void  void
Line 194  puffs_suspendtouser(struct puffs_mount *
Line 90  puffs_suspendtouser(struct puffs_mount *
   
         pvfsr_susp = malloc(sizeof(struct puffs_vfsreq_suspend),          pvfsr_susp = malloc(sizeof(struct puffs_vfsreq_suspend),
             M_PUFFS, M_WAITOK | M_ZERO);              M_PUFFS, M_WAITOK | M_ZERO);
         ppark = pool_cache_get(&parkpc, PR_WAITOK);          ppark = malloc(sizeof(struct puffs_park), M_PUFFS, M_WAITOK | M_ZERO);
   
         pvfsr_susp->pvfsr_status = status;          pvfsr_susp->pvfsr_status = status;
         ppark->park_preq = (struct puffs_req *)pvfsr_susp;          ppark->park_preq = (struct puffs_req *)pvfsr_susp;
Line 217  puffs_vntouser(struct puffs_mount *pmp, 
Line 113  puffs_vntouser(struct puffs_mount *pmp, 
         void *kbuf, size_t buflen, void *cookie,          void *kbuf, size_t buflen, void *cookie,
         struct vnode *vp1, struct vnode *vp2)          struct vnode *vp1, struct vnode *vp2)
 {  {
         struct puffs_park *ppark;          struct puffs_park park;
   
         ppark = pool_cache_get(&parkpc, PR_WAITOK);          park.park_preq = kbuf;
         ppark->park_preq = kbuf;  
   
         ppark->park_preq->preq_opclass = PUFFSOP_VN;          park.park_preq->preq_opclass = PUFFSOP_VN;
         ppark->park_preq->preq_optype = optype;          park.park_preq->preq_optype = optype;
         ppark->park_preq->preq_cookie = cookie;          park.park_preq->preq_cookie = cookie;
   
         ppark->park_maxlen = ppark->park_copylen = buflen;          park.park_maxlen = park.park_copylen = buflen;
         ppark->park_flags = 0;          park.park_flags = 0;
   
         return touser(pmp, ppark, puffs_getreqid(pmp), vp1, vp2);          return touser(pmp, &park, puffs_getreqid(pmp), vp1, vp2);
 }  }
   
 /*  /*
Line 240  puffs_vntouser_req(struct puffs_mount *p
Line 135  puffs_vntouser_req(struct puffs_mount *p
         void *kbuf, size_t buflen, void *cookie, uint64_t reqid,          void *kbuf, size_t buflen, void *cookie, uint64_t reqid,
         struct vnode *vp1, struct vnode *vp2)          struct vnode *vp1, struct vnode *vp2)
 {  {
         struct puffs_park *ppark;          struct puffs_park park;
   
         ppark = pool_cache_get(&parkpc, PR_WAITOK);          park.park_preq = kbuf;
         ppark->park_preq = kbuf;  
   
         ppark->park_preq->preq_opclass = PUFFSOP_VN;          park.park_preq->preq_opclass = PUFFSOP_VN;
         ppark->park_preq->preq_optype = optype;          park.park_preq->preq_optype = optype;
         ppark->park_preq->preq_cookie = cookie;          park.park_preq->preq_cookie = cookie;
   
         ppark->park_maxlen = ppark->park_copylen = buflen;          park.park_maxlen = park.park_copylen = buflen;
         ppark->park_flags = 0;          park.park_flags = 0;
   
         return touser(pmp, ppark, reqid, vp1, vp2);          return touser(pmp, &park, reqid, vp1, vp2);
 }  }
   
   /*
    * vnode level request, copy routines can adjust "kernbuf".
    */
 int  int
 puffs_vntouser_delta(struct puffs_mount *pmp, int optype,  puffs_vntouser_adjbuf(struct puffs_mount *pmp, int optype,
         void *kbuf, size_t buflen, size_t maxdelta,          void **kbuf, size_t *buflen, size_t maxdelta,
         void *cookie, struct vnode *vp1, struct vnode *vp2)          void *cookie, struct vnode *vp1, struct vnode *vp2)
 {  {
         struct puffs_park *ppark;          struct puffs_park park;
           int error;
   
         ppark = pool_cache_get(&parkpc, PR_WAITOK);          park.park_preq = *kbuf;
         ppark->park_preq = kbuf;  
   
         ppark->park_preq->preq_opclass = PUFFSOP_VN;          park.park_preq->preq_opclass = PUFFSOP_VN;
         ppark->park_preq->preq_optype = optype;          park.park_preq->preq_optype = optype;
         ppark->park_preq->preq_cookie = cookie;          park.park_preq->preq_cookie = cookie;
   
         ppark->park_copylen = buflen;          park.park_copylen = *buflen;
         ppark->park_maxlen = buflen + maxdelta;          park.park_maxlen = maxdelta + *buflen;
         ppark->park_flags = 0;          park.park_flags = PUFFS_PARKFLAG_ADJUSTABLE;
   
           error = touser(pmp, &park, puffs_getreqid(pmp), vp1, vp2);
   
           *kbuf = park.park_preq;
           *buflen = park.park_copylen;
   
         return touser(pmp, ppark, puffs_getreqid(pmp), vp1, vp2);          return error;
 }  }
   
 /*  /*
  * File server interaction is async from caller perspective.   * File server interaction is async from caller perspective.
  * biodone(bp) is signalled in putop.   * biodone(bp)J is signalled in putop.
  */   */
 void  void
 puffs_vntouser_bioread_async(struct puffs_mount *pmp, void *cookie,  puffs_vntouser_bioread_async(struct puffs_mount *pmp, void *cookie,
Line 288  puffs_vntouser_bioread_async(struct puff
Line 190  puffs_vntouser_bioread_async(struct puff
         struct puffs_park *ppark;          struct puffs_park *ppark;
         struct puffs_vnreq_read *read_argp;          struct puffs_vnreq_read *read_argp;
   
         ppark = pool_cache_get(&parkpc, PR_WAITOK);          MALLOC(ppark, struct puffs_park *, sizeof(struct puffs_park),
               M_PUFFS, M_WAITOK);
         MALLOC(read_argp, struct puffs_vnreq_read *,          MALLOC(read_argp, struct puffs_vnreq_read *,
             sizeof(struct puffs_vnreq_read) + tomove,              sizeof(struct puffs_vnreq_read), M_PUFFS, M_WAITOK | M_ZERO);
             M_PUFFS, M_WAITOK | M_ZERO);  
   
         read_argp->pvnr_ioflag = 0;          read_argp->pvnr_ioflag = 0;
         read_argp->pvnr_resid = tomove;          read_argp->pvnr_resid = tomove;
Line 306  puffs_vntouser_bioread_async(struct puff
Line 208  puffs_vntouser_bioread_async(struct puff
         ppark->park_copylen = sizeof(struct puffs_vnreq_read);          ppark->park_copylen = sizeof(struct puffs_vnreq_read);
         ppark->park_maxlen = sizeof(struct puffs_vnreq_read) + tomove;          ppark->park_maxlen = sizeof(struct puffs_vnreq_read) + tomove;
         ppark->park_bp = bp;          ppark->park_bp = bp;
         ppark->park_flags = PARKFLAG_ASYNCBIOREAD;          ppark->park_flags
               = PUFFS_PARKFLAG_ADJUSTABLE | PUFFS_PARKFLAG_ASYNCBIOREAD;
   
         (void)touser(pmp, ppark, puffs_getreqid(pmp), vp1, vp2);          (void)touser(pmp, ppark, puffs_getreqid(pmp), vp1, vp2);
 }  }
Line 323  puffs_vntouser_faf(struct puffs_mount *p
Line 226  puffs_vntouser_faf(struct puffs_mount *p
         struct puffs_park *ppark;          struct puffs_park *ppark;
   
         /* XXX: is it allowable to sleep here? */          /* XXX: is it allowable to sleep here? */
         ppark = pool_cache_get(&parkpc, PR_NOWAIT);          ppark = malloc(sizeof(struct puffs_park), M_PUFFS, M_NOWAIT | M_ZERO);
         if (ppark == NULL)          if (ppark == NULL)
                 return; /* 2bad */                  return; /* 2bad */
   
Line 368  static int
Line 271  static int
 touser(struct puffs_mount *pmp, struct puffs_park *ppark, uint64_t reqid,  touser(struct puffs_mount *pmp, struct puffs_park *ppark, uint64_t reqid,
         struct vnode *vp1, struct vnode *vp2)          struct vnode *vp1, struct vnode *vp2)
 {  {
           struct lwp *l = curlwp;
         struct mount *mp;          struct mount *mp;
         struct puffs_req *preq;          struct puffs_req *preq;
         int rv = 0;          int rv = 0;
Line 377  touser(struct puffs_mount *pmp, struct p
Line 281  touser(struct puffs_mount *pmp, struct p
         preq->preq_id = ppark->park_id = reqid;          preq->preq_id = ppark->park_id = reqid;
         preq->preq_buflen = ALIGN(ppark->park_maxlen);          preq->preq_buflen = ALIGN(ppark->park_maxlen);
   
 #if 0  
         /*  
          * We don't trap signals currently  
          */  
         struct lwp *l = curlwp;  
   
         /*          /*
          * To support PCATCH, yet another movie: check if there are signals           * To support PCATCH, yet another movie: check if there are signals
          * pending and we are issueing a non-FAF.  If so, return an error           * pending and we are issueing a non-FAF.  If so, return an error
Line 390  touser(struct puffs_mount *pmp, struct p
Line 288  touser(struct puffs_mount *pmp, struct p
          * it to a FAF, fire off to the file server and return an error.           * it to a FAF, fire off to the file server and return an error.
          * Yes, this is bordering disgusting.  Barfbags are on me.           * Yes, this is bordering disgusting.  Barfbags are on me.
          */           */
         if (PUFFSOP_WANTREPLY(preq->preq_opclass)          if (PUFFSOP_WANTREPLY(ppark->park_preq->preq_opclass)
            && (ppark->park_flags & PARKFLAG_ASYNCBIOREAD) == 0             && (ppark->park_flags & PUFFS_PARKFLAG_ASYNCBIOREAD) == 0
            && (l->l_flag & LW_PENDSIG) != 0 && sigispending(l, 0)) {             && (l->l_flag & LW_PENDSIG) != 0 && sigispending(l, 0)) {
                 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN                  if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN
                     && preq->preq_optype == PUFFS_VN_INACTIVE) {                      && preq->preq_optype == PUFFS_VN_INACTIVE) {
                         puffs_reqtofaf(ppark);                          struct puffs_park *newpark;
                         DPRINTF(("puffs touser: converted to FAF %p\n", ppark));  
                           newpark = puffs_reqtofaf(ppark);
                           DPRINTF(("puffs touser: converted to FAF, old %p, "
                               "new %p\n", ppark, newpark));
                           ppark = newpark;
                         rv = EINTR;                          rv = EINTR;
                 } else {                  } else {
                         return EINTR;                          return EINTR;
                 }                  }
         }          }
 #endif  
   
         /*          /*
          * test for suspension lock.           * test for suspension lock.
Line 427  touser(struct puffs_mount *pmp, struct p
Line 328  touser(struct puffs_mount *pmp, struct p
          * in the kernel while the fs is suspending.  It's not a very           * in the kernel while the fs is suspending.  It's not a very
          * likely event, but it needs to be fixed some day.           * likely event, but it needs to be fixed some day.
          */           */
   
         /*  
          * MOREXXX: once PUFFS_WCACHEINFO is enabled, we can't take  
          * the mutex here, since getpages() might be called locked.  
          */  
         fstrans_start(mp, FSTRANS_NORMAL);          fstrans_start(mp, FSTRANS_NORMAL);
         mutex_enter(&pmp->pmp_lock);          simple_lock(&pmp->pmp_lock);
         fstrans_done(mp);          fstrans_done(mp);
   
         if (pmp->pmp_status != PUFFSTAT_RUNNING) {          if (pmp->pmp_status != PUFFSTAT_RUNNING) {
                 mutex_exit(&pmp->pmp_lock);                  simple_unlock(&pmp->pmp_lock);
                 pool_cache_put(&parkpc, ppark);  
                 return ENXIO;                  return ENXIO;
         }          }
   
         TAILQ_INSERT_TAIL(&pmp->pmp_req_touser, ppark, park_entries);          TAILQ_INSERT_TAIL(&pmp->pmp_req_touser, ppark, park_entries);
         pmp->pmp_req_waiters++;          pmp->pmp_req_touser_waiters++;
   
 #if 0  
         /*          /*
          * Don't do unlock-relock dance yet.  There are a couple of           * Don't do unlock-relock dance yet.  There are a couple of
          * unsolved issues with it.  If we don't unlock, we can have           * unsolved issues with it.  If we don't unlock, we can have
Line 454  touser(struct puffs_mount *pmp, struct p
Line 348  touser(struct puffs_mount *pmp, struct p
          * would of course be nicer to have antilocking in the userspace           * would of course be nicer to have antilocking in the userspace
          * interface protocol itself.. your patience will be rewarded.           * interface protocol itself.. your patience will be rewarded.
          */           */
   #if 0
         /* unlock */          /* unlock */
         if (vp2)          if (vp2)
                 VOP_UNLOCK(vp2, 0);                  VOP_UNLOCK(vp2, 0);
Line 461  touser(struct puffs_mount *pmp, struct p
Line 356  touser(struct puffs_mount *pmp, struct p
                 VOP_UNLOCK(vp1, 0);                  VOP_UNLOCK(vp1, 0);
 #endif  #endif
   
           /*
            * XXX: does releasing the lock here cause trouble?  Can't hold
            * it, because otherwise the below would cause locking against
            * oneself-problems in the kqueue stuff.  yes, it is a
            * theoretical race, so it must be solved
            */
           simple_unlock(&pmp->pmp_lock);
   
         DPRINTF(("touser: req %" PRIu64 ", preq: %p, park: %p, "          DPRINTF(("touser: req %" PRIu64 ", preq: %p, park: %p, "
             "c/t: 0x%x/0x%x, f: 0x%x\n", preq->preq_id, preq, ppark,              "c/t: 0x%x/0x%x, f: 0x%x\n", preq->preq_id, preq, ppark,
             preq->preq_opclass, preq->preq_optype, ppark->park_flags));              preq->preq_opclass, preq->preq_optype, ppark->park_flags));
   
         cv_broadcast(&pmp->pmp_req_waiter_cv);          wakeup(&pmp->pmp_req_touser);
         selnotify(pmp->pmp_sel, 0);          selnotify(pmp->pmp_sel, 0);
   
         if (PUFFSOP_WANTREPLY(preq->preq_opclass)          if (PUFFSOP_WANTREPLY(ppark->park_preq->preq_opclass)
             && (ppark->park_flags & PARKFLAG_ASYNCBIOREAD) == 0) {              && (ppark->park_flags & PUFFS_PARKFLAG_ASYNCBIOREAD) == 0) {
                   struct puffs_park *valetpark = NULL;
                 int error;                  int error;
   
                 error = 0; /* XXX: no interrupt for now */                  error = ltsleep(ppark, PUSER | PCATCH, "puffs1", 0, NULL);
                   rv = ppark->park_preq->preq_rv;
   
                   /*
                    * Ok, so it gets a bit tricky around here once again.
                    * We want to give interruptibility to the sleep to work
                    * around all kinds of locking-against-oneself problems
                    * and the file system recursing into itself and so forth.
                    * So if we break out of the ltsleep() for anything except
                    * natural causes, we need to caution ourselves.
                    *
                    * The stages at which we can break out are:
                    *  1) operation waiting to be fetched by file server
                    *  2) operation being copied to userspace, not on either queue
                    *  3) file server operating on .. err .. operation
                    *  4) putop: locate the correct park structure from the queue
                    *  5) putop: copy response from userspace
                    *  6) putop: wakeup waiter
                    *
                    * If we are still at stage 1, no problem, just remove
                    * ourselves from the queue to userspace.  If we are at
                    * the stage before 4 has completed, replace the park structure
                    * with a park structure indicating that the caller is
                    * no more and no proper reply is required.  If the server
                    * is already copying data from userspace to the kernel,
                    * wait for it to finish and return the real return value to
                    * the caller.
                    */
    checkagain:
                   if (valetpark) {
                           FREE(valetpark, M_PUFFS);
                           valetpark = NULL;
                   }
   
                 cv_wait(&ppark->park_cv, &pmp->pmp_lock);  
                 if (error) {                  if (error) {
                         ppark->park_flags |= PARKFLAG_WAITERGONE;                          DPRINTF(("puffs touser: got %d from ltsleep, "
                         if (ppark->park_flags & PARKFLAG_PROCESSING) {                              "(unlocked) flags 0x%x (park %p)\n",
                                 cv_wait(&ppark->park_cv, &pmp->pmp_lock);                              error, ppark->park_flags, ppark));
                                 rv = preq->preq_rv;                          rv = error;
   
                           MALLOC(valetpark, struct puffs_park *,
                               sizeof(struct puffs_park), M_PUFFS,
                               M_ZERO | M_WAITOK);
   
                           simple_lock(&pmp->pmp_lock);
   
                           /*
                            * The order here for the clauses, per description
                            * in comment above, is:
                            *   1, after 6, after 4, 2-3.
                            */
                           if ((ppark->park_flags&PUFFS_PARKFLAG_PROCESSING)==0) {
                                   TAILQ_REMOVE(&pmp->pmp_req_touser, ppark,
                                       park_entries);
                                   simple_unlock(&pmp->pmp_lock);
                                   FREE(valetpark, M_PUFFS);
                                   DPRINTF(("puffs touser: park %p removed "
                                       "from queue one\n", ppark));
                           } else if
                              (ppark->park_flags & PUFFS_PARKFLAG_RECVREPLY) {
                                   if (ppark->park_flags & PUFFS_PARKFLAG_DONE) {
                                           rv = ppark->park_preq->preq_rv;
                                           simple_unlock(&pmp->pmp_lock);
                                           FREE(valetpark, M_PUFFS);
                                   } else {
                                           error = ltsleep(ppark,
                                               PUSER | PCATCH | PNORELOCK,
                                               "puffsre1", 0, &pmp->pmp_lock);
                                           goto checkagain;
                                   }
                         } else {                          } else {
                                 rv = error;                                  valetpark->park_flags
                                       = PUFFS_PARKFLAG_WAITERGONE;
                                   ppark->park_flags |= PUFFS_PARKFLAG_WAITERGONE;
                                   valetpark->park_id = ppark->park_id;
   
                                   if (ppark->park_flags & PUFFS_PARKFLAG_RQUEUE) {
                                           TAILQ_INSERT_BEFORE(ppark, valetpark,
                                               park_entries);
                                           TAILQ_REMOVE(&pmp->pmp_req_replywait,
                                               ppark, park_entries);
                                   } else {
                                           TAILQ_INSERT_TAIL(
                                               &pmp->pmp_req_replywait,
                                               valetpark, park_entries);
                                   }
   
                                   simple_unlock(&pmp->pmp_lock);
                                   DPRINTF(("puffs touser: replaced park %p "
                                       "with valet park %p\n", ppark, valetpark));
                         }                          }
                 } else {  
                         rv = preq->preq_rv;  
                 }                  }
                 mutex_exit(&pmp->pmp_lock);  
                 pool_cache_put(&parkpc, ppark);  
   
                 /*                  /*
                  * retake the lock and release.  This makes sure (haha,                   * retake the lock and release.  This makes sure (haha,
                  * I'm humorous) that we don't process the same vnode in                   * I'm humorous) that we don't process the same vnode in
Line 502  touser(struct puffs_mount *pmp, struct p
Line 482  touser(struct puffs_mount *pmp, struct p
                         fstrans_start(mp, FSTRANS_NORMAL);                          fstrans_start(mp, FSTRANS_NORMAL);
                         fstrans_done(mp);                          fstrans_done(mp);
                 }                  }
         } else {  
                 mutex_exit(&pmp->pmp_lock);  
         }          }
   
 #if 0  #if 0
Line 514  touser(struct puffs_mount *pmp, struct p
Line 492  touser(struct puffs_mount *pmp, struct p
                 KASSERT(vn_lock(vp2, LK_EXCLUSIVE | LK_RETRY) == 0);                  KASSERT(vn_lock(vp2, LK_EXCLUSIVE | LK_RETRY) == 0);
 #endif  #endif
   
         mutex_enter(&pmp->pmp_lock);          simple_lock(&pmp->pmp_lock);
         if (--pmp->pmp_req_waiters == 0) {          if (--pmp->pmp_req_touser_waiters == 0)
                 KASSERT(cv_has_waiters(&pmp->pmp_req_waitersink_cv) <= 1);                  wakeup(&pmp->pmp_req_touser_waiters);
                 cv_signal(&pmp->pmp_req_waitersink_cv);          simple_unlock(&pmp->pmp_lock);
         }  
         mutex_exit(&pmp->pmp_lock);  
   
         return rv;          return rv;
 }  }
Line 546  puffs_getop(struct puffs_mount *pmp, str
Line 522  puffs_getop(struct puffs_mount *pmp, str
         donesome = error = 0;          donesome = error = 0;
         bufpos = phg->phg_buf;          bufpos = phg->phg_buf;
   
         mutex_enter(&pmp->pmp_lock);          simple_lock(&pmp->pmp_lock);
         while (phg->phg_nops == 0 || donesome != phg->phg_nops) {          while (phg->phg_nops == 0 || donesome != phg->phg_nops) {
  again:   again:
                 if (pmp->pmp_status != PUFFSTAT_RUNNING) {                  if (pmp->pmp_status != PUFFSTAT_RUNNING) {
Line 563  puffs_getop(struct puffs_mount *pmp, str
Line 539  puffs_getop(struct puffs_mount *pmp, str
                                 goto out;                                  goto out;
                         }                          }
   
                         error = cv_wait_sig(&pmp->pmp_req_waiter_cv,                          error = ltsleep(&pmp->pmp_req_touser, PUSER | PCATCH,
                             &pmp->pmp_lock);                              "puffs2", 0, &pmp->pmp_lock);
                         if (error)                          if (error)
                                 goto out;                                  goto out;
                         else                          else
Line 573  puffs_getop(struct puffs_mount *pmp, str
Line 549  puffs_getop(struct puffs_mount *pmp, str
   
                 park = TAILQ_FIRST(&pmp->pmp_req_touser);                  park = TAILQ_FIRST(&pmp->pmp_req_touser);
                 preq = park->park_preq;                  preq = park->park_preq;
   
                 if (phg->phg_buflen < preq->preq_buflen) {                  if (phg->phg_buflen < preq->preq_buflen) {
                         if (!donesome)                          if (!donesome)
                                 error = E2BIG;                                  error = E2BIG;
                         goto out;                          goto out;
                 }                  }
                 TAILQ_REMOVE(&pmp->pmp_req_touser, park, park_entries);                  TAILQ_REMOVE(&pmp->pmp_req_touser, park, park_entries);
                   park->park_flags |= PUFFS_PARKFLAG_PROCESSING;
                 /* If it's a goner, don't process any furher */                  simple_unlock(&pmp->pmp_lock);
                 if (park->park_flags & PARKFLAG_WAITERGONE) {  
                         panic("impossible for now");  
                         pool_cache_put(&parkpc, park);  
                         continue;  
                 }  
   
                 mutex_exit(&pmp->pmp_lock);  
   
                 DPRINTF(("puffsgetop: get op %" PRIu64 " (%d.), from %p "                  DPRINTF(("puffsgetop: get op %" PRIu64 " (%d.), from %p "
                     "len %zu (buflen %zu), target %p\n", preq->preq_id,                      "len %zu (buflen %zu), target %p\n", preq->preq_id,
Line 595  puffs_getop(struct puffs_mount *pmp, str
Line 565  puffs_getop(struct puffs_mount *pmp, str
                     bufpos));                      bufpos));
   
                 if ((error = copyout(preq, bufpos, park->park_copylen)) != 0) {                  if ((error = copyout(preq, bufpos, park->park_copylen)) != 0) {
                         DPRINTF(("puffs_getop: copyout failed\n"));                          DPRINTF(("    FAILED %d\n", error));
                         /*                          /*
                          * ok, user server is probably trying to cheat.                           * ok, user server is probably trying to cheat.
                          * stuff op back & return error to user                           * stuff op back & return error to user
                          */                           */
                          mutex_enter(&pmp->pmp_lock);                           simple_lock(&pmp->pmp_lock);
                          TAILQ_INSERT_HEAD(&pmp->pmp_req_touser, park,                           TAILQ_INSERT_HEAD(&pmp->pmp_req_touser, park,
                              park_entries);                               park_entries);
   
Line 612  puffs_getop(struct puffs_mount *pmp, str
Line 582  puffs_getop(struct puffs_mount *pmp, str
                 phg->phg_buflen -= preq->preq_buflen;                  phg->phg_buflen -= preq->preq_buflen;
                 donesome++;                  donesome++;
   
                 mutex_enter(&pmp->pmp_lock);                  simple_lock(&pmp->pmp_lock);
                 if (PUFFSOP_WANTREPLY(preq->preq_opclass)) {                  if (PUFFSOP_WANTREPLY(preq->preq_opclass)) {
                         TAILQ_INSERT_TAIL(&pmp->pmp_req_replywait, park,                          if ((park->park_flags & PUFFS_PARKFLAG_WAITERGONE)==0) {
                             park_entries);                                  TAILQ_INSERT_TAIL(&pmp->pmp_req_replywait, park,
                                       park_entries);
                                   park->park_flags |= PUFFS_PARKFLAG_RQUEUE;
                           }
                 } else {                  } else {
                           simple_unlock(&pmp->pmp_lock);
                         free(preq, M_PUFFS);                          free(preq, M_PUFFS);
                         pool_cache_put(&parkpc, park);                          free(park, M_PUFFS);
                           simple_lock(&pmp->pmp_lock);
                 }                  }
         }          }
   
  out:   out:
         phg->phg_more = pmp->pmp_req_waiters;          phg->phg_more = pmp->pmp_req_touser_waiters;
         mutex_exit(&pmp->pmp_lock);          simple_unlock(&pmp->pmp_lock);
   
         phg->phg_nops = donesome;          phg->phg_nops = donesome;
   
         return error;          return error;
 }  }
   
   /*
    * urgh, too complex, be very very careful while editing, i.e. NEEDS CLEANUP
    */
 int  int
 puffs_putop(struct puffs_mount *pmp, struct puffs_reqh_put *php)  puffs_putop(struct puffs_mount *pmp, struct puffs_reqh_put *php)
 {  {
Line 649  puffs_putop(struct puffs_mount *pmp, str
Line 627  puffs_putop(struct puffs_mount *pmp, str
         userbuf = php->php_buf;          userbuf = php->php_buf;
         reqlen = php->php_buflen;          reqlen = php->php_buflen;
   
         mutex_enter(&pmp->pmp_lock);          simple_lock(&pmp->pmp_lock);
         while (donesome != php->php_nops) {          while (donesome != php->php_nops) {
 #ifdef PUFFSDEBUG  #ifdef PUFFSDEBUG
                   simple_unlock(&pmp->pmp_lock);
                 DPRINTF(("puffsputop: searching for %" PRIu64 ", ubuf: %p, "                  DPRINTF(("puffsputop: searching for %" PRIu64 ", ubuf: %p, "
                     "len %zu\n", id, userbuf, reqlen));                      "len %zu\n", id, userbuf, reqlen));
                   simple_lock(&pmp->pmp_lock);
 #endif  #endif
                 TAILQ_FOREACH(park, &pmp->pmp_req_replywait, park_entries) {                  TAILQ_FOREACH(park, &pmp->pmp_req_replywait, park_entries) {
                         if (park->park_id == id)                          if (park->park_id == id)
Line 665  puffs_putop(struct puffs_mount *pmp, str
Line 645  puffs_putop(struct puffs_mount *pmp, str
                         break;                          break;
                 }                  }
                 TAILQ_REMOVE(&pmp->pmp_req_replywait, park, park_entries);                  TAILQ_REMOVE(&pmp->pmp_req_replywait, park, park_entries);
                 wgone = park->park_flags & PARKFLAG_WAITERGONE;                  park->park_flags |= PUFFS_PARKFLAG_RECVREPLY;
                 park->park_flags |= PARKFLAG_PROCESSING;                  simple_unlock(&pmp->pmp_lock);
                 mutex_exit(&pmp->pmp_lock);  
   
                 /*                  /*
                  * If the caller has gone south, go to next, collect                   * If the caller has gone south, go to next, collect
                  * $200 and free the structure there instead of wakeup.                   * $200 and free the structure there instead of wakeup.
                  * We also need to copyin the                   * We also need to copyin the
                  */                   */
                 if (wgone) {                  if (park->park_flags & PUFFS_PARKFLAG_WAITERGONE) {
                         panic("puffs: wgone impossible for now\n");  
                         DPRINTF(("puffs_putop: bad service - waiter gone for "                          DPRINTF(("puffs_putop: bad service - waiter gone for "
                             "park %p\n", park));                              "park %p\n", park));
                           wgone = 1;
                         error = copyin(userbuf, &tmpreq,                          error = copyin(userbuf, &tmpreq,
                             sizeof(struct puffs_req));                              sizeof(struct puffs_req));
                         if (error)                          if (error)
Line 686  puffs_putop(struct puffs_mount *pmp, str
Line 665  puffs_putop(struct puffs_mount *pmp, str
                         goto next;                          goto next;
                 }                  }
   
                 if (reqlen == 0 || reqlen > park->park_maxlen) {                  if (park->park_flags & PUFFS_PARKFLAG_ADJUSTABLE) {
                         reqlen = park->park_maxlen;                          /* sanitycheck size of incoming transmission. */
                         DPRINTF(("puffsputop: kernel bufsize override: "                          if (reqlen > pmp->pmp_req_maxsize) {
                             "%zu\n", reqlen));                                  DPRINTF(("puffsputop: outrageous user buf "
                                       "size: %zu\n", reqlen));
                                   error = EINVAL;
                                   goto loopout;
                           }
   
                           if (reqlen > park->park_copylen) {
                                   if (reqlen > park->park_maxlen) {
                                           DPRINTF(("puffsputop: adj copysize "
                                               "> max size, %zu vs %zu\n",
                                               reqlen, park->park_maxlen));
                                           error = EINVAL;
                                           goto loopout;
                                   }
                                   free(park->park_preq, M_PUFFS);
                                   park->park_preq = malloc(reqlen,
                                       M_PUFFS, M_WAITOK);
   
                                   park->park_copylen = reqlen;
                                   DPRINTF(("puffsputop: adjbuf, new addr %p, "
                                       "len %zu\n", park->park_preq, reqlen));
                           }
                   } else {
                           if (reqlen == 0 || reqlen > park->park_copylen) {
                                   reqlen = park->park_copylen;
                                   DPRINTF(("puffsputop: kernel bufsize override: "
                                       "%zu\n", reqlen));
                           }
                 }                  }
   
                 DPRINTF(("puffsputpop: copyin from %p to %p, len %zu\n",                  DPRINTF(("puffsputpop: copyin from %p to %p, len %zu\n",
Line 700  puffs_putop(struct puffs_mount *pmp, str
Line 706  puffs_putop(struct puffs_mount *pmp, str
                 nextpreq = park->park_preq;                  nextpreq = park->park_preq;
                 bp = park->park_bp;                  bp = park->park_bp;
   
                 if (park->park_flags & PARKFLAG_ASYNCBIOREAD) {                  if (park->park_flags & PUFFS_PARKFLAG_ASYNCBIOREAD) {
                         struct puffs_vnreq_read *read_argp;                          struct puffs_vnreq_read *read_argp;
                         size_t moved;                          size_t moved;
   
Line 730  puffs_putop(struct puffs_mount *pmp, str
Line 736  puffs_putop(struct puffs_mount *pmp, str
  loopout:   loopout:
                 if (error && park->park_preq) {                  if (error && park->park_preq) {
                         park->park_preq->preq_rv = error;                          park->park_preq->preq_rv = error;
                         if (park->park_flags & PARKFLAG_ASYNCBIOREAD) {                          if (park->park_flags & PUFFS_PARKFLAG_ASYNCBIOREAD) {
                                 bp = park->park_bp;                                  bp = park->park_bp;
                                 bp->b_error = error;                                  bp->b_error = error;
                                 bp->b_flags |= B_ERROR;                                  bp->b_flags |= B_ERROR;
Line 738  puffs_putop(struct puffs_mount *pmp, str
Line 744  puffs_putop(struct puffs_mount *pmp, str
                         }                          }
                 }                  }
   
                 mutex_enter(&pmp->pmp_lock);                  if (wgone) {
                 if (!wgone) {                          FREE(park, M_PUFFS);
                         if (park->park_flags & PARKFLAG_ASYNCBIOREAD) {                          simple_lock(&pmp->pmp_lock);
                                 free(park->park_preq, M_PUFFS);                  } else if (park->park_flags & PUFFS_PARKFLAG_ASYNCBIOREAD) {
                                 pool_cache_put(&parkpc, park);                          free(park->park_preq, M_PUFFS);
                         } else {                          FREE(park, M_PUFFS);
                                 DPRINTF(("puffs_putop: flagging done for "                          simple_lock(&pmp->pmp_lock);
                                     "park %p\n", park));                  } else {
                           DPRINTF(("puffs_putop: flagging done for park %p\n",
                                 cv_signal(&park->park_cv);                              park));
                         }                          simple_lock(&pmp->pmp_lock);
                           park->park_flags |= PUFFS_PARKFLAG_DONE;
                           wakeup(park);
                 }                  }
   
                 if (error)                  if (error)
Line 756  puffs_putop(struct puffs_mount *pmp, str
Line 764  puffs_putop(struct puffs_mount *pmp, str
                 wgone = 0;                  wgone = 0;
         }          }
   
         mutex_exit(&pmp->pmp_lock);          simple_unlock(&pmp->pmp_lock);
         php->php_nops -= donesome;          php->php_nops -= donesome;
   
         return error;          return error;
 }  }
   
 /*  
  * We're dead, kaput, RIP, slightly more than merely pining for the  
  * fjords, belly-up, fallen, lifeless, finished, expired, gone to meet  
  * our maker, ceased to be, etcetc.  YASD.  It's a dead FS!  
  *  
  * Caller must hold puffs mutex.  
  */  
 void  
 puffs_userdead(struct puffs_mount *pmp)  
 {  
         struct puffs_park *park;  
         struct buf *bp;  
   
         /*  
          * Mark filesystem status as dying so that operations don't  
          * attempt to march to userspace any longer.  
          */  
         pmp->pmp_status = PUFFSTAT_DYING;  
   
         /* signal waiters on REQUEST TO file server queue */  
         TAILQ_FOREACH(park, &pmp->pmp_req_touser, park_entries) {  
                 uint8_t opclass;  
   
                 opclass = park->park_preq->preq_rv;  
                 park->park_preq->preq_rv = ENXIO;  
   
                 TAILQ_REMOVE(&pmp->pmp_req_touser, park, park_entries);  
   
                 if (park->park_flags & PARKFLAG_ASYNCBIOREAD) {  
                         bp = park->park_bp;  
                         bp->b_error = ENXIO;  
                         bp->b_flags |= B_ERROR;  
                         biodone(bp);  
                         free(park->park_preq, M_PUFFS);  
                         pool_cache_put(&parkpc, park);  
                 } else if (!PUFFSOP_WANTREPLY(opclass)) {  
                         free(park->park_preq, M_PUFFS);  
                         pool_cache_put(&parkpc, park);  
                 } else {  
                         cv_signal(&park->park_cv);  
                 }  
         }  
   
         /* signal waiters on RESPONSE FROM file server queue */  
         TAILQ_FOREACH(park, &pmp->pmp_req_replywait, park_entries) {  
                 KASSERT(PUFFSOP_WANTREPLY(park->park_preq->preq_opclass));  
   
                 park->park_preq->preq_rv = ENXIO;  
                 TAILQ_REMOVE(&pmp->pmp_req_replywait, park, park_entries);  
   
                 if (park->park_flags & PARKFLAG_ASYNCBIOREAD) {  
                         bp = park->park_bp;  
                         bp->b_error = ENXIO;  
                         bp->b_flags |= B_ERROR;  
                         biodone(bp);  
                         free(park->park_preq, M_PUFFS);  
                         pool_cache_put(&parkpc, park);  
                 } else {  
                         cv_signal(&park->park_cv);  
                 }  
         }  
 }  
   
 /* this is probably going to die away at some point? */  /* this is probably going to die away at some point? */
 /*  /*
  * XXX: currently bitrotted   * XXX: currently bitrotted
Line 839  puffssizeop(struct puffs_mount *pmp, str
Line 784  puffssizeop(struct puffs_mount *pmp, str
         int error;          int error;
   
         /* locate correct op */          /* locate correct op */
         mutex_enter(&pmp->pmp_lock);          simple_lock(&pmp->pmp_lock);
         TAILQ_FOREACH(pspark, &pmp->pmp_req_sizepark, pkso_entries) {          TAILQ_FOREACH(pspark, &pmp->pmp_req_sizepark, pkso_entries) {
                 if (pspark->pkso_reqid == psop_user->pso_reqid) {                  if (pspark->pkso_reqid == psop_user->pso_reqid) {
                         TAILQ_REMOVE(&pmp->pmp_req_sizepark, pspark,                          TAILQ_REMOVE(&pmp->pmp_req_sizepark, pspark,
Line 847  puffssizeop(struct puffs_mount *pmp, str
Line 792  puffssizeop(struct puffs_mount *pmp, str
                         break;                          break;
                 }                  }
         }          }
         mutex_exit(&pmp->pmp_lock);          simple_unlock(&pmp->pmp_lock);
   
         if (pspark == NULL)          if (pspark == NULL)
                 return EINVAL;                  return EINVAL;

Legend:
Removed from v.1.20.2.1  
changed lines
  Added in v.1.21

CVSweb <webmaster@jp.NetBSD.org>