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 }
|