Print this page
pbchk
pbchk
cleanup port_free_event_local() semantics


   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 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Copyright (c) 2018, Joyent, Inc.
  28  */
  29 
  30 /*
  31  * File Events Notification
  32  * ------------------------
  33  *
  34  * The File Events Notification facility provides file and directory change
  35  * notification. It is implemented as an event source(PORT_SOURCE_FILE)
  36  * under the Event Ports framework. Therefore the API is an extension to
  37  * the Event Ports API.
  38  *
  39  * It uses the FEM (File Events Monitoring) framework to intercept
  40  * operations on the files & directories and generate appropriate events.
  41  *
  42  * It provides event notification in accordance with what an application
  43  * can find out by stat`ing the file and comparing time stamps. The various
  44  * system calls that update the file's access, modification, and change
  45  * time stamps are documented in the man page section 2.
  46  *
  47  * It is non intrusive. That is, having an active file event watch on a file


 462 }
 463 
 464 /*
 465  * Remove a portfop_t from the port cache hash table and discard it.
 466  * It is called only when pfp is not on the vnode's list. Otherwise,
 467  * port_remove_fop() is called.
 468  */
 469 void
 470 port_pcache_remove_fop(portfop_cache_t *pfcp, portfop_t *pfp)
 471 {
 472         port_kevent_t   *pkevp;
 473 
 474 
 475         ASSERT(MUTEX_HELD(&pfcp->pfc_lock));
 476 
 477         pkevp = pfp->pfop_pev;
 478         pfp->pfop_pev = NULL;
 479 
 480         if (pkevp != NULL) {
 481                 (void) port_remove_done_event(pkevp);
 482                 port_free_event_local(pkevp, 0);
 483         }
 484 
 485         port_pcache_delete(pfcp, pfp);
 486 
 487         if (pfp->pfop_cname != NULL)
 488                 kmem_free(pfp->pfop_cname, pfp->pfop_clen + 1);
 489         kmem_free(pfp, sizeof (portfop_t));
 490         if (pfcp->pfc_objcount == 0)
 491                 cv_signal(&pfcp->pfc_lclosecv);
 492 }
 493 
 494 /*
 495  * if we have too many watches on the vnode, attempt to discard an
 496  * inactive one.
 497  */
 498 static void
 499 port_fop_trimpfplist(vnode_t *vp)
 500 {
 501         portfop_vp_t *pvp;
 502         portfop_t *pfp = NULL;


 713         portfop_t       *pfp = NULL;
 714         portfop_t       **bucket;
 715 
 716         ASSERT(MUTEX_HELD(&pfcp->pfc_lock));
 717         bucket = PORT_FOP_BUCKET(pfcp, obj);
 718         pfp = *bucket;
 719         while (pfp != NULL) {
 720                 if (pfp->pfop_object == obj && pfp->pfop_pid == pid)
 721                         break;
 722                 pfp = pfp->pfop_hashnext;
 723         }
 724         return (pfp);
 725 }
 726 
 727 /*
 728  * Given the file name, get the vnode and also the directory vnode
 729  * On return, the vnodes are held (VN_HOLD). The caller has to VN_RELE
 730  * the vnode(s).
 731  */
 732 int
 733 port_fop_getdvp(void *objptr, vnode_t **vp, vnode_t **dvp,
 734         char **cname, int *len, int follow)
 735 {
 736         int error = 0;
 737         struct pathname pn;
 738         char *fname;
 739 
 740         if (get_udatamodel() == DATAMODEL_NATIVE) {
 741                 fname = ((file_obj_t *)objptr)->fo_name;
 742 #ifdef  _SYSCALL32_IMPL
 743         } else {
 744                 fname = (caddr_t)(uintptr_t)((file_obj32_t *)objptr)->fo_name;
 745 #endif  /* _SYSCALL32_IMPL */
 746         }
 747 
 748         /*
 749          * lookuppn may fail with EINVAL, if dvp is  non-null(like when
 750          * looking for "."). So call again with dvp = NULL.
 751          */
 752         if ((error = pn_get(fname, UIO_USERSPACE, &pn)) != 0) {
 753                 return (error);
 754         }




   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 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Copyright 2020 Joyent, Inc.
  28  */
  29 
  30 /*
  31  * File Events Notification
  32  * ------------------------
  33  *
  34  * The File Events Notification facility provides file and directory change
  35  * notification. It is implemented as an event source(PORT_SOURCE_FILE)
  36  * under the Event Ports framework. Therefore the API is an extension to
  37  * the Event Ports API.
  38  *
  39  * It uses the FEM (File Events Monitoring) framework to intercept
  40  * operations on the files & directories and generate appropriate events.
  41  *
  42  * It provides event notification in accordance with what an application
  43  * can find out by stat`ing the file and comparing time stamps. The various
  44  * system calls that update the file's access, modification, and change
  45  * time stamps are documented in the man page section 2.
  46  *
  47  * It is non intrusive. That is, having an active file event watch on a file


 462 }
 463 
 464 /*
 465  * Remove a portfop_t from the port cache hash table and discard it.
 466  * It is called only when pfp is not on the vnode's list. Otherwise,
 467  * port_remove_fop() is called.
 468  */
 469 void
 470 port_pcache_remove_fop(portfop_cache_t *pfcp, portfop_t *pfp)
 471 {
 472         port_kevent_t   *pkevp;
 473 
 474 
 475         ASSERT(MUTEX_HELD(&pfcp->pfc_lock));
 476 
 477         pkevp = pfp->pfop_pev;
 478         pfp->pfop_pev = NULL;
 479 
 480         if (pkevp != NULL) {
 481                 (void) port_remove_done_event(pkevp);
 482                 port_free_event_local(pkevp, B_TRUE);
 483         }
 484 
 485         port_pcache_delete(pfcp, pfp);
 486 
 487         if (pfp->pfop_cname != NULL)
 488                 kmem_free(pfp->pfop_cname, pfp->pfop_clen + 1);
 489         kmem_free(pfp, sizeof (portfop_t));
 490         if (pfcp->pfc_objcount == 0)
 491                 cv_signal(&pfcp->pfc_lclosecv);
 492 }
 493 
 494 /*
 495  * if we have too many watches on the vnode, attempt to discard an
 496  * inactive one.
 497  */
 498 static void
 499 port_fop_trimpfplist(vnode_t *vp)
 500 {
 501         portfop_vp_t *pvp;
 502         portfop_t *pfp = NULL;


 713         portfop_t       *pfp = NULL;
 714         portfop_t       **bucket;
 715 
 716         ASSERT(MUTEX_HELD(&pfcp->pfc_lock));
 717         bucket = PORT_FOP_BUCKET(pfcp, obj);
 718         pfp = *bucket;
 719         while (pfp != NULL) {
 720                 if (pfp->pfop_object == obj && pfp->pfop_pid == pid)
 721                         break;
 722                 pfp = pfp->pfop_hashnext;
 723         }
 724         return (pfp);
 725 }
 726 
 727 /*
 728  * Given the file name, get the vnode and also the directory vnode
 729  * On return, the vnodes are held (VN_HOLD). The caller has to VN_RELE
 730  * the vnode(s).
 731  */
 732 int
 733 port_fop_getdvp(void *objptr, vnode_t **vp, vnode_t **dvp, char **cname,
 734     int *len, int follow)
 735 {
 736         int error = 0;
 737         struct pathname pn;
 738         char *fname;
 739 
 740         if (get_udatamodel() == DATAMODEL_NATIVE) {
 741                 fname = ((file_obj_t *)objptr)->fo_name;
 742 #ifdef  _SYSCALL32_IMPL
 743         } else {
 744                 fname = (caddr_t)(uintptr_t)((file_obj32_t *)objptr)->fo_name;
 745 #endif  /* _SYSCALL32_IMPL */
 746         }
 747 
 748         /*
 749          * lookuppn may fail with EINVAL, if dvp is  non-null(like when
 750          * looking for "."). So call again with dvp = NULL.
 751          */
 752         if ((error = pn_get(fname, UIO_USERSPACE, &pn)) != 0) {
 753                 return (error);
 754         }