Print this page
8634 epoll fails to wake on certain edge-triggered conditions
8635 epoll should not emit POLLNVAL
8636 recursive epoll should emit EPOLLRDNORM
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <igor@dilos.org>


   6  * You may not use this file except in compliance with the License.
   7  *
   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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright 2012 Milan Jurik. All rights reserved.
  25  * Copyright (c) 2016 by Delphix. All rights reserved.

  26  */
  27 
  28 
  29 /*
  30  * Overview of the RSM Kernel Agent:
  31  * ---------------------------------
  32  *
  33  * rsm.c constitutes the implementation of the RSM kernel agent. The RSM
  34  * kernel agent is a pseudo device driver which makes use of the RSMPI
  35  * interface on behalf of the RSMAPI user library.
  36  *
  37  * The kernel agent functionality can be categorized into the following
  38  * components:
  39  * 1. Driver Infrastructure
  40  * 2. Export/Import Segment Management
  41  * 3. Internal resource allocation/deallocation
  42  *
  43  * The driver infrastructure includes the basic module loading entry points
  44  * like _init, _info, _fini to load, unload and report information about
  45  * the driver module. The driver infrastructure also includes the


2402                                 rsmka_release_adapter(adapter);
2403                                 e = RSMERR_BAD_ADDR;
2404                         }
2405                 }
2406 #endif
2407                 if (ddi_copyout((caddr_t)&msg->rnum,
2408                     (caddr_t)&((rsm_ioctlmsg_t *)dataptr)->rnum,
2409                     sizeof (minor_t), mode)) {
2410                         rsmka_release_adapter(adapter);
2411                         e = RSMERR_BAD_ADDR;
2412                 }
2413         }
2414 
2415         DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_bind done\n"));
2416 
2417         return (e);
2418 }
2419 
2420 static void
2421 rsm_remap_local_importers(rsm_node_id_t src_nodeid,
2422     rsm_memseg_id_t ex_segid,
2423     ddi_umem_cookie_t cookie)
2424 
2425 {
2426         rsmresource_t   *p = NULL;
2427         rsmhash_table_t *rhash = &rsm_import_segs;
2428         uint_t          index;
2429 
2430         DBG_PRINTF((RSM_KERNEL_AGENT | RSM_FUNC_ALL, RSM_DEBUG_VERBOSE,
2431             "rsm_remap_local_importers enter\n"));
2432 
2433         index = rsmhash(ex_segid);
2434 
2435         rw_enter(&rhash->rsmhash_rw, RW_READER);
2436 
2437         p = rsmhash_getbkt(rhash, index);
2438 
2439         for (; p; p = p->rsmrc_next) {
2440                 rsmseg_t *seg = (rsmseg_t *)p;
2441                 rsmseglock_acquire(seg);
2442                 /*
2443                  * Change the s_cookie value of only the local importers
2444                  * which have been mapped (in state RSM_STATE_ACTIVE).


3627         reply.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_REPLY;
3628         reply.rsmipc_hdr.rsmipc_cookie = req->rsmipc_hdr.rsmipc_cookie;
3629 
3630         (void) rsmipc_send(src, NULL, &reply);
3631 
3632         DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
3633             "rsm_intr_segconnect done\n"));
3634 }
3635 
3636 
3637 /*
3638  * When an exported segment is unpublished the exporter sends an ipc
3639  * message (RSMIPC_MSG_DISCONNECT) to all importers.  The recv ipc dispatcher
3640  * calls this function.  The import list is scanned; segments which match the
3641  * exported segment id are unloaded and disconnected.
3642  *
3643  * Will also be called from rsm_rebind with disconnect_flag FALSE.
3644  *
3645  */
3646 static void
3647 rsm_force_unload(rsm_node_id_t src_nodeid,
3648     rsm_memseg_id_t ex_segid,
3649     boolean_t disconnect_flag)
3650 
3651 {
3652         rsmresource_t   *p = NULL;
3653         rsmhash_table_t *rhash = &rsm_import_segs;
3654         uint_t          index;
3655         DBG_DEFINE(category,
3656             RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
3657 
3658         DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_force_unload enter\n"));
3659 
3660         index = rsmhash(ex_segid);
3661 
3662         rw_enter(&rhash->rsmhash_rw, RW_READER);
3663 
3664         p = rsmhash_getbkt(rhash, index);
3665 
3666         for (; p; p = p->rsmrc_next) {
3667                 rsmseg_t *seg = (rsmseg_t *)p;
3668                 if ((seg->s_segid == ex_segid) && (seg->s_node == src_nodeid)) {
3669                         /*
3670                          * In order to make rsmseg_unload and rsm_force_unload


6745 
6746         if (shared_cookie != NULL) {
6747                 /*
6748                  *  This is the last importer so inform the exporting node
6749                  *  so this import can be deleted from the list of importers.
6750                  */
6751                 request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_NOTIMPORTING;
6752                 request.rsmipc_key = seg->s_segid;
6753                 request.rsmipc_segment_cookie = shared_cookie;
6754                 rsmseglock_release(seg);
6755                 (void) rsmipc_send(seg->s_node, &request, RSM_NO_REPLY);
6756         } else {
6757                 rsmseglock_release(seg);
6758         }
6759 
6760         DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_disconnect done\n"));
6761 
6762         return (DDI_SUCCESS);
6763 }
6764 
6765 /*ARGSUSED*/
6766 static int
6767 rsm_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
6768     struct pollhead **phpp)
6769 {
6770         minor_t         rnum;
6771         rsmresource_t   *res;
6772         rsmseg_t        *seg;
6773         DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_DDI);
6774 
6775         DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_chpoll enter\n"));
6776 
6777         /* find minor, no lock */
6778         rnum = getminor(dev);
6779         res = rsmresource_lookup(rnum, RSM_NOLOCK);
6780 
6781         /* poll is supported only for export/import segments */
6782         if ((res == NULL) || (res == RSMRC_RESERVED) ||
6783             (res->rsmrc_type == RSM_RESOURCE_BAR)) {
6784                 return (ENXIO);
6785         }
6786 
6787         *reventsp = 0;
6788 
6789         /*
6790          * An exported segment must be in state RSM_STATE_EXPORT; an
6791          * imported segment must be in state RSM_STATE_ACTIVE.
6792          */
6793         seg = (rsmseg_t *)res;
6794 
6795         if (seg->s_pollevent) {
6796                 *reventsp = POLLRDNORM;
6797         } else if (!anyyet) {




6798                 /* cannot take segment lock here */
6799                 *phpp = &seg->s_poll;
6800                 seg->s_pollflag |= RSM_SEGMENT_POLL;
6801         }
6802         DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_chpoll done\n"));
6803         return (0);
6804 }
6805 
6806 
6807 
6808 /* ************************* IOCTL Commands ********************* */
6809 
6810 static rsmseg_t *
6811 rsmresource_seg(rsmresource_t *res, minor_t rnum, cred_t *credp,
6812     rsm_resource_type_t type)
6813 {
6814         /* get segment from resource handle */
6815         rsmseg_t *seg;
6816         DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_IOCTL);
6817 




   6  * You may not use this file except in compliance with the License.
   7  *
   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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright 2012 Milan Jurik. All rights reserved.
  25  * Copyright (c) 2016 by Delphix. All rights reserved.
  26  * Copyright 2017 Joyent, Inc.
  27  */
  28 
  29 
  30 /*
  31  * Overview of the RSM Kernel Agent:
  32  * ---------------------------------
  33  *
  34  * rsm.c constitutes the implementation of the RSM kernel agent. The RSM
  35  * kernel agent is a pseudo device driver which makes use of the RSMPI
  36  * interface on behalf of the RSMAPI user library.
  37  *
  38  * The kernel agent functionality can be categorized into the following
  39  * components:
  40  * 1. Driver Infrastructure
  41  * 2. Export/Import Segment Management
  42  * 3. Internal resource allocation/deallocation
  43  *
  44  * The driver infrastructure includes the basic module loading entry points
  45  * like _init, _info, _fini to load, unload and report information about
  46  * the driver module. The driver infrastructure also includes the


2403                                 rsmka_release_adapter(adapter);
2404                                 e = RSMERR_BAD_ADDR;
2405                         }
2406                 }
2407 #endif
2408                 if (ddi_copyout((caddr_t)&msg->rnum,
2409                     (caddr_t)&((rsm_ioctlmsg_t *)dataptr)->rnum,
2410                     sizeof (minor_t), mode)) {
2411                         rsmka_release_adapter(adapter);
2412                         e = RSMERR_BAD_ADDR;
2413                 }
2414         }
2415 
2416         DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_bind done\n"));
2417 
2418         return (e);
2419 }
2420 
2421 static void
2422 rsm_remap_local_importers(rsm_node_id_t src_nodeid,
2423     rsm_memseg_id_t ex_segid, ddi_umem_cookie_t cookie)


2424 {
2425         rsmresource_t   *p = NULL;
2426         rsmhash_table_t *rhash = &rsm_import_segs;
2427         uint_t          index;
2428 
2429         DBG_PRINTF((RSM_KERNEL_AGENT | RSM_FUNC_ALL, RSM_DEBUG_VERBOSE,
2430             "rsm_remap_local_importers enter\n"));
2431 
2432         index = rsmhash(ex_segid);
2433 
2434         rw_enter(&rhash->rsmhash_rw, RW_READER);
2435 
2436         p = rsmhash_getbkt(rhash, index);
2437 
2438         for (; p; p = p->rsmrc_next) {
2439                 rsmseg_t *seg = (rsmseg_t *)p;
2440                 rsmseglock_acquire(seg);
2441                 /*
2442                  * Change the s_cookie value of only the local importers
2443                  * which have been mapped (in state RSM_STATE_ACTIVE).


3626         reply.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_REPLY;
3627         reply.rsmipc_hdr.rsmipc_cookie = req->rsmipc_hdr.rsmipc_cookie;
3628 
3629         (void) rsmipc_send(src, NULL, &reply);
3630 
3631         DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
3632             "rsm_intr_segconnect done\n"));
3633 }
3634 
3635 
3636 /*
3637  * When an exported segment is unpublished the exporter sends an ipc
3638  * message (RSMIPC_MSG_DISCONNECT) to all importers.  The recv ipc dispatcher
3639  * calls this function.  The import list is scanned; segments which match the
3640  * exported segment id are unloaded and disconnected.
3641  *
3642  * Will also be called from rsm_rebind with disconnect_flag FALSE.
3643  *
3644  */
3645 static void
3646 rsm_force_unload(rsm_node_id_t src_nodeid, rsm_memseg_id_t ex_segid,

3647     boolean_t disconnect_flag)

3648 {
3649         rsmresource_t   *p = NULL;
3650         rsmhash_table_t *rhash = &rsm_import_segs;
3651         uint_t          index;
3652         DBG_DEFINE(category,
3653             RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
3654 
3655         DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_force_unload enter\n"));
3656 
3657         index = rsmhash(ex_segid);
3658 
3659         rw_enter(&rhash->rsmhash_rw, RW_READER);
3660 
3661         p = rsmhash_getbkt(rhash, index);
3662 
3663         for (; p; p = p->rsmrc_next) {
3664                 rsmseg_t *seg = (rsmseg_t *)p;
3665                 if ((seg->s_segid == ex_segid) && (seg->s_node == src_nodeid)) {
3666                         /*
3667                          * In order to make rsmseg_unload and rsm_force_unload


6742 
6743         if (shared_cookie != NULL) {
6744                 /*
6745                  *  This is the last importer so inform the exporting node
6746                  *  so this import can be deleted from the list of importers.
6747                  */
6748                 request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_NOTIMPORTING;
6749                 request.rsmipc_key = seg->s_segid;
6750                 request.rsmipc_segment_cookie = shared_cookie;
6751                 rsmseglock_release(seg);
6752                 (void) rsmipc_send(seg->s_node, &request, RSM_NO_REPLY);
6753         } else {
6754                 rsmseglock_release(seg);
6755         }
6756 
6757         DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_disconnect done\n"));
6758 
6759         return (DDI_SUCCESS);
6760 }
6761 

6762 static int
6763 rsm_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
6764     struct pollhead **phpp)
6765 {
6766         minor_t         rnum;
6767         rsmresource_t   *res;
6768         rsmseg_t        *seg;
6769         DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_DDI);
6770 
6771         DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_chpoll enter\n"));
6772 
6773         /* find minor, no lock */
6774         rnum = getminor(dev);
6775         res = rsmresource_lookup(rnum, RSM_NOLOCK);
6776 
6777         /* poll is supported only for export/import segments */
6778         if ((res == NULL) || (res == RSMRC_RESERVED) ||
6779             (res->rsmrc_type == RSM_RESOURCE_BAR)) {
6780                 return (ENXIO);
6781         }
6782 


6783         /*
6784          * An exported segment must be in state RSM_STATE_EXPORT; an
6785          * imported segment must be in state RSM_STATE_ACTIVE.
6786          */
6787         seg = (rsmseg_t *)res;
6788 
6789         if (seg->s_pollevent) {
6790                 *reventsp = POLLRDNORM;
6791         } else {
6792                 *reventsp = 0;
6793         }
6794 
6795         if ((*reventsp == 0 && !anyyet) || (events & POLLET)) {
6796                 /* cannot take segment lock here */
6797                 *phpp = &seg->s_poll;
6798                 seg->s_pollflag |= RSM_SEGMENT_POLL;
6799         }
6800         DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_chpoll done\n"));
6801         return (0);
6802 }
6803 
6804 
6805 
6806 /* ************************* IOCTL Commands ********************* */
6807 
6808 static rsmseg_t *
6809 rsmresource_seg(rsmresource_t *res, minor_t rnum, cred_t *credp,
6810     rsm_resource_type_t type)
6811 {
6812         /* get segment from resource handle */
6813         rsmseg_t *seg;
6814         DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_IOCTL);
6815