Print this page
pbchk
cleanup port_free_event_local() semantics


   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright (c) 2015 Joyent, Inc.  All rights reserved.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/systm.h>
  33 #include <sys/cred.h>
  34 #include <sys/modctl.h>
  35 #include <sys/vfs.h>
  36 #include <sys/vfs_opreg.h>
  37 #include <sys/sysmacros.h>
  38 #include <sys/cmn_err.h>
  39 #include <sys/stat.h>
  40 #include <sys/errno.h>
  41 #include <sys/kmem.h>
  42 #include <sys/file.h>
  43 #include <sys/kstat.h>
  44 #include <sys/port_impl.h>
  45 #include <sys/task.h>
  46 #include <sys/project.h>
  47 
  48 /*


1389                 } else {
1390                         kevp = kmem_alloc(eventsz * nmax, KM_NOSLEEP);
1391                         if (kevp == NULL) {
1392                                 if (nmax > pp->port_max_list)
1393                                         nmax = pp->port_max_list;
1394                                 kevp = kmem_alloc(eventsz * nmax, KM_SLEEP);
1395                         }
1396                 }
1397 
1398                 results = kevp;
1399                 lev = NULL;     /* start with first event in the queue */
1400                 for (nevents = 0; nevents < nmax; ) {
1401                         pev = port_get_kevent(glist, lev);
1402                         if (pev == NULL)        /* no more events available */
1403                                 break;
1404                         if (pev->portkev_flags & PORT_KEV_FREE) {
1405                                 /* Just discard event */
1406                                 list_remove(glist, pev);
1407                                 pev->portkev_flags &= ~(PORT_CLEANUP_DONE);
1408                                 if (PORT_FREE_EVENT(pev))
1409                                         port_free_event_local(pev, 0);
1410                                 tnent--;
1411                                 continue;
1412                         }
1413 
1414                         /* move event data to copyout list */
1415                         if (port_copy_event(&kevp[nevents], pev, glist)) {
1416                                 /*
1417                                  * Event can not be delivered to the
1418                                  * current process.
1419                                  */
1420                                 if (lev != NULL)
1421                                         list_insert_after(glist, lev, pev);
1422                                 else
1423                                         list_insert_head(glist, pev);
1424                                 lev = pev;  /* last checked event */
1425                         } else {
1426                                 nevents++;      /* # of events ready */
1427                         }
1428                 }
1429 #ifdef  _SYSCALL32_IMPL


1437                 } else {
1438                         kevp32 = kmem_alloc(eventsz * nmax, KM_NOSLEEP);
1439                         if (kevp32 == NULL) {
1440                                 if (nmax > pp->port_max_list)
1441                                         nmax = pp->port_max_list;
1442                                 kevp32 = kmem_alloc(eventsz * nmax, KM_SLEEP);
1443                         }
1444                 }
1445 
1446                 results = kevp32;
1447                 lev = NULL;     /* start with first event in the queue */
1448                 for (nevents = 0; nevents < nmax; ) {
1449                         pev = port_get_kevent(glist, lev);
1450                         if (pev == NULL)        /* no more events available */
1451                                 break;
1452                         if (pev->portkev_flags & PORT_KEV_FREE) {
1453                                 /* Just discard event */
1454                                 list_remove(glist, pev);
1455                                 pev->portkev_flags &= ~(PORT_CLEANUP_DONE);
1456                                 if (PORT_FREE_EVENT(pev))
1457                                         port_free_event_local(pev, 0);
1458                                 tnent--;
1459                                 continue;
1460                         }
1461 
1462                         /* move event data to copyout list */
1463                         if (port_copy_event32(&kevp32[nevents], pev, glist)) {
1464                                 /*
1465                                  * Event can not be delivered to the
1466                                  * current process.
1467                                  */
1468                                 if (lev != NULL)
1469                                         list_insert_after(glist, lev, pev);
1470                                 else
1471                                         list_insert_head(glist, pev);
1472                                 lev = pev;  /* last checked event */
1473                         } else {
1474                                 nevents++;      /* # of events ready */
1475                         }
1476                 }
1477 #endif  /* _SYSCALL32_IMPL */


1609         if (pkevp->portkev_flags & PORT_KEV_WIRED)
1610                 pkevp->portkev_flags &= ~PORT_KEV_DONEQ;
1611         else
1612                 free_event = 1;
1613 
1614         if (pkevp->portkev_callback) {
1615                 error = (*pkevp->portkev_callback)(pkevp->portkev_arg,
1616                     &puevp->portev_events, pkevp->portkev_pid,
1617                     PORT_CALLBACK_DEFAULT, pkevp);
1618 
1619                 if (error) {
1620                         /*
1621                          * Event can not be delivered.
1622                          * Caller must reinsert the event into the queue.
1623                          */
1624                         pkevp->portkev_flags = flags;
1625                         return (error);
1626                 }
1627         }
1628         if (free_event)
1629                 port_free_event_local(pkevp, 0);
1630         return (0);
1631 }
1632 
1633 #ifdef  _SYSCALL32_IMPL
1634 /*
1635  * 1. copy kernel event structure to user event structure.
1636  * 2. PORT_KEV_WIRED event structures will be reused by the "source"
1637  * 3. Remove PORT_KEV_DONEQ flag (event removed from the event queue)
1638  * 4. Other types of event structures can be delivered back to the port cache
1639  *    (port_free_event_local()).
1640  * 5. The event source callback function is the last opportunity for the
1641  *    event source to update events, to free local resources associated with
1642  *    the event or to deny the delivery of the event.
1643  */
1644 static int
1645 port_copy_event32(port_event32_t *puevp, port_kevent_t *pkevp, list_t *list)
1646 {
1647         int     free_event = 0;
1648         int     error;
1649         int     flags;


1664         flags = pkevp->portkev_flags;
1665         if (pkevp->portkev_flags & PORT_KEV_WIRED)
1666                 pkevp->portkev_flags &= ~PORT_KEV_DONEQ;
1667         else
1668                 free_event = 1;
1669 
1670         if (pkevp->portkev_callback != NULL) {
1671                 error = (*pkevp->portkev_callback)(pkevp->portkev_arg,
1672                     &puevp->portev_events, pkevp->portkev_pid,
1673                     PORT_CALLBACK_DEFAULT, pkevp);
1674                 if (error) {
1675                         /*
1676                          * Event can not be delivered.
1677                          * Caller must reinsert the event into the queue.
1678                          */
1679                         pkevp->portkev_flags = flags;
1680                         return (error);
1681                 }
1682         }
1683         if (free_event)
1684                 port_free_event_local(pkevp, 0);
1685         return (0);
1686 }
1687 #endif  /* _SYSCALL32_IMPL */
1688 
1689 /*
1690  * copyout alert event.
1691  */
1692 static int
1693 port_get_alert(port_alert_t *pa, port_event_t *uevp)
1694 {
1695         model_t model = get_udatamodel();
1696 
1697         /* copyout alert event structures to user space */
1698         if (model == DATAMODEL_NATIVE) {
1699                 port_event_t    uev;
1700                 uev.portev_source = PORT_SOURCE_ALERT;
1701                 uev.portev_object = pa->portal_object;
1702                 uev.portev_events = pa->portal_events;
1703                 uev.portev_user = pa->portal_user;
1704                 if (copyout(&uev, uevp, sizeof (port_event_t)))




   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright 2020 Joyent, Inc.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/systm.h>
  33 #include <sys/cred.h>
  34 #include <sys/modctl.h>
  35 #include <sys/vfs.h>
  36 #include <sys/vfs_opreg.h>
  37 #include <sys/sysmacros.h>
  38 #include <sys/cmn_err.h>
  39 #include <sys/stat.h>
  40 #include <sys/errno.h>
  41 #include <sys/kmem.h>
  42 #include <sys/file.h>
  43 #include <sys/kstat.h>
  44 #include <sys/port_impl.h>
  45 #include <sys/task.h>
  46 #include <sys/project.h>
  47 
  48 /*


1389                 } else {
1390                         kevp = kmem_alloc(eventsz * nmax, KM_NOSLEEP);
1391                         if (kevp == NULL) {
1392                                 if (nmax > pp->port_max_list)
1393                                         nmax = pp->port_max_list;
1394                                 kevp = kmem_alloc(eventsz * nmax, KM_SLEEP);
1395                         }
1396                 }
1397 
1398                 results = kevp;
1399                 lev = NULL;     /* start with first event in the queue */
1400                 for (nevents = 0; nevents < nmax; ) {
1401                         pev = port_get_kevent(glist, lev);
1402                         if (pev == NULL)        /* no more events available */
1403                                 break;
1404                         if (pev->portkev_flags & PORT_KEV_FREE) {
1405                                 /* Just discard event */
1406                                 list_remove(glist, pev);
1407                                 pev->portkev_flags &= ~(PORT_CLEANUP_DONE);
1408                                 if (PORT_FREE_EVENT(pev))
1409                                         port_free_event_local(pev, B_TRUE);
1410                                 tnent--;
1411                                 continue;
1412                         }
1413 
1414                         /* move event data to copyout list */
1415                         if (port_copy_event(&kevp[nevents], pev, glist)) {
1416                                 /*
1417                                  * Event can not be delivered to the
1418                                  * current process.
1419                                  */
1420                                 if (lev != NULL)
1421                                         list_insert_after(glist, lev, pev);
1422                                 else
1423                                         list_insert_head(glist, pev);
1424                                 lev = pev;  /* last checked event */
1425                         } else {
1426                                 nevents++;      /* # of events ready */
1427                         }
1428                 }
1429 #ifdef  _SYSCALL32_IMPL


1437                 } else {
1438                         kevp32 = kmem_alloc(eventsz * nmax, KM_NOSLEEP);
1439                         if (kevp32 == NULL) {
1440                                 if (nmax > pp->port_max_list)
1441                                         nmax = pp->port_max_list;
1442                                 kevp32 = kmem_alloc(eventsz * nmax, KM_SLEEP);
1443                         }
1444                 }
1445 
1446                 results = kevp32;
1447                 lev = NULL;     /* start with first event in the queue */
1448                 for (nevents = 0; nevents < nmax; ) {
1449                         pev = port_get_kevent(glist, lev);
1450                         if (pev == NULL)        /* no more events available */
1451                                 break;
1452                         if (pev->portkev_flags & PORT_KEV_FREE) {
1453                                 /* Just discard event */
1454                                 list_remove(glist, pev);
1455                                 pev->portkev_flags &= ~(PORT_CLEANUP_DONE);
1456                                 if (PORT_FREE_EVENT(pev))
1457                                         port_free_event_local(pev, B_TRUE);
1458                                 tnent--;
1459                                 continue;
1460                         }
1461 
1462                         /* move event data to copyout list */
1463                         if (port_copy_event32(&kevp32[nevents], pev, glist)) {
1464                                 /*
1465                                  * Event can not be delivered to the
1466                                  * current process.
1467                                  */
1468                                 if (lev != NULL)
1469                                         list_insert_after(glist, lev, pev);
1470                                 else
1471                                         list_insert_head(glist, pev);
1472                                 lev = pev;  /* last checked event */
1473                         } else {
1474                                 nevents++;      /* # of events ready */
1475                         }
1476                 }
1477 #endif  /* _SYSCALL32_IMPL */


1609         if (pkevp->portkev_flags & PORT_KEV_WIRED)
1610                 pkevp->portkev_flags &= ~PORT_KEV_DONEQ;
1611         else
1612                 free_event = 1;
1613 
1614         if (pkevp->portkev_callback) {
1615                 error = (*pkevp->portkev_callback)(pkevp->portkev_arg,
1616                     &puevp->portev_events, pkevp->portkev_pid,
1617                     PORT_CALLBACK_DEFAULT, pkevp);
1618 
1619                 if (error) {
1620                         /*
1621                          * Event can not be delivered.
1622                          * Caller must reinsert the event into the queue.
1623                          */
1624                         pkevp->portkev_flags = flags;
1625                         return (error);
1626                 }
1627         }
1628         if (free_event)
1629                 port_free_event_local(pkevp, B_TRUE);
1630         return (0);
1631 }
1632 
1633 #ifdef  _SYSCALL32_IMPL
1634 /*
1635  * 1. copy kernel event structure to user event structure.
1636  * 2. PORT_KEV_WIRED event structures will be reused by the "source"
1637  * 3. Remove PORT_KEV_DONEQ flag (event removed from the event queue)
1638  * 4. Other types of event structures can be delivered back to the port cache
1639  *    (port_free_event_local()).
1640  * 5. The event source callback function is the last opportunity for the
1641  *    event source to update events, to free local resources associated with
1642  *    the event or to deny the delivery of the event.
1643  */
1644 static int
1645 port_copy_event32(port_event32_t *puevp, port_kevent_t *pkevp, list_t *list)
1646 {
1647         int     free_event = 0;
1648         int     error;
1649         int     flags;


1664         flags = pkevp->portkev_flags;
1665         if (pkevp->portkev_flags & PORT_KEV_WIRED)
1666                 pkevp->portkev_flags &= ~PORT_KEV_DONEQ;
1667         else
1668                 free_event = 1;
1669 
1670         if (pkevp->portkev_callback != NULL) {
1671                 error = (*pkevp->portkev_callback)(pkevp->portkev_arg,
1672                     &puevp->portev_events, pkevp->portkev_pid,
1673                     PORT_CALLBACK_DEFAULT, pkevp);
1674                 if (error) {
1675                         /*
1676                          * Event can not be delivered.
1677                          * Caller must reinsert the event into the queue.
1678                          */
1679                         pkevp->portkev_flags = flags;
1680                         return (error);
1681                 }
1682         }
1683         if (free_event)
1684                 port_free_event_local(pkevp, B_TRUE);
1685         return (0);
1686 }
1687 #endif  /* _SYSCALL32_IMPL */
1688 
1689 /*
1690  * copyout alert event.
1691  */
1692 static int
1693 port_get_alert(port_alert_t *pa, port_event_t *uevp)
1694 {
1695         model_t model = get_udatamodel();
1696 
1697         /* copyout alert event structures to user space */
1698         if (model == DATAMODEL_NATIVE) {
1699                 port_event_t    uev;
1700                 uev.portev_source = PORT_SOURCE_ALERT;
1701                 uev.portev_object = pa->portal_object;
1702                 uev.portev_events = pa->portal_events;
1703                 uev.portev_user = pa->portal_user;
1704                 if (copyout(&uev, uevp, sizeof (port_event_t)))