Print this page
patch as-lock-macro-simplification


8353         }
8354 
8355         /*
8356          * For longterm locking the addr must pertain to a seg_vn segment or
8357          * or a seg_spt segment.
8358          * If the segment pertains to a regular file, it cannot be
8359          * mapped MAP_SHARED.
8360          * This is to prevent a deadlock if a file truncation is attempted
8361          * after the locking is done.
8362          * Doing this after as_pagelock guarantees persistence of the as; if
8363          * an unacceptable segment is found, the cleanup includes calling
8364          * as_pageunlock before returning EFAULT.
8365          *
8366          * segdev is allowed here as it is already locked.  This allows
8367          * for memory exported by drivers through mmap() (which is already
8368          * locked) to be allowed for LONGTERM.
8369          */
8370         if (flags & DDI_UMEMLOCK_LONGTERM) {
8371                 extern  struct seg_ops segspt_shmops;
8372                 extern  struct seg_ops segdev_ops;
8373                 AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
8374                 for (seg = as_segat(as, addr); ; seg = AS_SEGNEXT(as, seg)) {
8375                         if (seg == NULL || seg->s_base > addr + len)
8376                                 break;
8377                         if (seg->s_ops == &segdev_ops)
8378                                 continue;
8379                         if (((seg->s_ops != &segvn_ops) &&
8380                             (seg->s_ops != &segspt_shmops)) ||
8381                             ((SEGOP_GETVP(seg, addr, &vp) == 0 &&
8382                             vp != NULL && vp->v_type == VREG) &&
8383                             (SEGOP_GETTYPE(seg, addr) & MAP_SHARED))) {
8384                                 as_pageunlock(as, p->pparray,
8385                                     addr, len, p->s_flags);
8386                                 AS_LOCK_EXIT(as, &as->a_lock);
8387                                 umem_decr_devlockmem(p);
8388                                 kmem_free(p, sizeof (struct ddi_umem_cookie));
8389                                 *cookie = (ddi_umem_cookie_t)NULL;
8390                                 return (EFAULT);
8391                         }
8392                 }
8393                 AS_LOCK_EXIT(as, &as->a_lock);
8394         }
8395 
8396 
8397         /* Initialize the fields in the ddi_umem_cookie */
8398         p->cvaddr = addr;
8399         p->type = UMEM_LOCKED;
8400         if (driver_callback != NULL) {
8401                 /* i_ddi_umem_unlock and umem_lock_undo may need the cookie */
8402                 p->cook_refcnt = 2;
8403                 p->callbacks = *ops_vector;
8404         } else {
8405                 /* only i_ddi_umme_unlock needs the cookie */
8406                 p->cook_refcnt = 1;
8407         }
8408 
8409         *cookie = (ddi_umem_cookie_t)p;
8410 
8411         /*
8412          * If a driver callback was specified, add an entry to the
8413          * as struct callback list. The as_pagelock above guarantees




8353         }
8354 
8355         /*
8356          * For longterm locking the addr must pertain to a seg_vn segment or
8357          * or a seg_spt segment.
8358          * If the segment pertains to a regular file, it cannot be
8359          * mapped MAP_SHARED.
8360          * This is to prevent a deadlock if a file truncation is attempted
8361          * after the locking is done.
8362          * Doing this after as_pagelock guarantees persistence of the as; if
8363          * an unacceptable segment is found, the cleanup includes calling
8364          * as_pageunlock before returning EFAULT.
8365          *
8366          * segdev is allowed here as it is already locked.  This allows
8367          * for memory exported by drivers through mmap() (which is already
8368          * locked) to be allowed for LONGTERM.
8369          */
8370         if (flags & DDI_UMEMLOCK_LONGTERM) {
8371                 extern  struct seg_ops segspt_shmops;
8372                 extern  struct seg_ops segdev_ops;
8373                 AS_LOCK_ENTER(as, RW_READER);
8374                 for (seg = as_segat(as, addr); ; seg = AS_SEGNEXT(as, seg)) {
8375                         if (seg == NULL || seg->s_base > addr + len)
8376                                 break;
8377                         if (seg->s_ops == &segdev_ops)
8378                                 continue;
8379                         if (((seg->s_ops != &segvn_ops) &&
8380                             (seg->s_ops != &segspt_shmops)) ||
8381                             ((SEGOP_GETVP(seg, addr, &vp) == 0 &&
8382                             vp != NULL && vp->v_type == VREG) &&
8383                             (SEGOP_GETTYPE(seg, addr) & MAP_SHARED))) {
8384                                 as_pageunlock(as, p->pparray,
8385                                     addr, len, p->s_flags);
8386                                 AS_LOCK_EXIT(as);
8387                                 umem_decr_devlockmem(p);
8388                                 kmem_free(p, sizeof (struct ddi_umem_cookie));
8389                                 *cookie = (ddi_umem_cookie_t)NULL;
8390                                 return (EFAULT);
8391                         }
8392                 }
8393                 AS_LOCK_EXIT(as);
8394         }
8395 
8396 
8397         /* Initialize the fields in the ddi_umem_cookie */
8398         p->cvaddr = addr;
8399         p->type = UMEM_LOCKED;
8400         if (driver_callback != NULL) {
8401                 /* i_ddi_umem_unlock and umem_lock_undo may need the cookie */
8402                 p->cook_refcnt = 2;
8403                 p->callbacks = *ops_vector;
8404         } else {
8405                 /* only i_ddi_umme_unlock needs the cookie */
8406                 p->cook_refcnt = 1;
8407         }
8408 
8409         *cookie = (ddi_umem_cookie_t)p;
8410 
8411         /*
8412          * If a driver callback was specified, add an entry to the
8413          * as struct callback list. The as_pagelock above guarantees