31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * CDDL HEADER START
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The contents of this file are subject to the terms of the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Common Development and Distribution License (the "License").
31ceb98b622e1a310256f4c4a1472beb92046db3praks * You may not use this file except in compliance with the License.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
31ceb98b622e1a310256f4c4a1472beb92046db3praks * or http://www.opensolaris.org/os/licensing.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * See the License for the specific language governing permissions
31ceb98b622e1a310256f4c4a1472beb92046db3praks * and limitations under the License.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * When distributing Covered Code, include this CDDL HEADER in each
31ceb98b622e1a310256f4c4a1472beb92046db3praks * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If applicable, add the following below this CDDL HEADER, with the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * fields enclosed by brackets "[]" replaced with your own identifying
31ceb98b622e1a310256f4c4a1472beb92046db3praks * information: Portions Copyright [yyyy] [name of copyright owner]
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * CDDL HEADER END
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
efaadbbfd41d2a35674006a9d58a2812beba0ea8Prakash Sangappa * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Use is subject to license terms.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill/*
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill * Copyright (c) 2013, Joyent, Inc. All rights reserved.
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill */
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * File Events Notification
31ceb98b622e1a310256f4c4a1472beb92046db3praks * ------------------------
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The File Events Notification facility provides file and directory change
31ceb98b622e1a310256f4c4a1472beb92046db3praks * notification. It is implemented as an event source(PORT_SOURCE_FILE)
31ceb98b622e1a310256f4c4a1472beb92046db3praks * under the Event Ports framework. Therefore the API is an extension to
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the Event Ports API.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * It uses the FEM (File Events Monitoring) framework to intercept
31ceb98b622e1a310256f4c4a1472beb92046db3praks * operations on the files & directories and generate appropriate events.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * It provides event notification in accordance with what an application
31ceb98b622e1a310256f4c4a1472beb92046db3praks * can find out by stat`ing the file and comparing time stamps. The various
31ceb98b622e1a310256f4c4a1472beb92046db3praks * system calls that update the file's access, modification, and change
31ceb98b622e1a310256f4c4a1472beb92046db3praks * time stamps are documented in the man page section 2.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * It is non intrusive. That is, having an active file event watch on a file
31ceb98b622e1a310256f4c4a1472beb92046db3praks * or directory will not prevent it from being removed or renamed or block an
31ceb98b622e1a310256f4c4a1472beb92046db3praks * unmount operation of the file system where the watched file or directory
31ceb98b622e1a310256f4c4a1472beb92046db3praks * resides.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Interface:
31ceb98b622e1a310256f4c4a1472beb92046db3praks * ----------
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The object for this event source is of type 'struct file_obj *'
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The file that needs to be monitored is specified in 'fo_name'.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The time stamps collected by a stat(2) call are passed in fo_atime,
31ceb98b622e1a310256f4c4a1472beb92046db3praks * fo_mtime, fo_ctime. At the time a file events watch is registered, the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * time stamps passed in are compared with the current time stamps of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file. If it has changed, relevant events are sent immediately. If the time
31ceb98b622e1a310256f4c4a1472beb92046db3praks * stamps are all '0', they will not be compared.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The events are delivered to an event port. A port is created using
31ceb98b622e1a310256f4c4a1472beb92046db3praks * port_create().
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * To register a file events watch on a file or directory.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * port_associate(int port, PORT_SOURCE_FILE, (uintptr_t)&fobj, events, user)
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * 'user' is the user pointer to be returned with the event.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * To de-register a file events watch,
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * port_dissociate(int port, PORT_SOURCE_FILE, (uintptr_t)&fobj)
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The events are collected using the port_get()/port_getn() interface. The
31ceb98b622e1a310256f4c4a1472beb92046db3praks * event source will be PORT_SOURCE_FILE.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * After an event is delivered, the file events watch gets de-activated. To
31ceb98b622e1a310256f4c4a1472beb92046db3praks * receive the next event, the process will have to re-register the watch and
31ceb98b622e1a310256f4c4a1472beb92046db3praks * activate it by calling port_associate() again. This behavior is intentional
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * and supports proper multi threaded programming when using file events
31ceb98b622e1a310256f4c4a1472beb92046db3praks * notification API.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Implementation overview:
31ceb98b622e1a310256f4c4a1472beb92046db3praks * ------------------------
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Each file events watch is represented by 'portfop_t' in the kernel. A
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * cache(in portfop_cache_t) of these portfop_t's are maintained per event
31ceb98b622e1a310256f4c4a1472beb92046db3praks * port by this source. The object here is the pointer to the file_obj
31ceb98b622e1a310256f4c4a1472beb92046db3praks * structure. The portfop_t's are hashed in using the object pointer. Therefore
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * it is possible to have multiple file events watches on a file by the same
31ceb98b622e1a310256f4c4a1472beb92046db3praks * process by using different object structure(file_obj_t) and hence can
31ceb98b622e1a310256f4c4a1472beb92046db3praks * receive multiple event notification for a file. These watches can be for
31ceb98b622e1a310256f4c4a1472beb92046db3praks * different event types.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The cached entries of these file objects are retained, even after delivering
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * an event, marking them inactive for performance reasons. The assumption
31ceb98b622e1a310256f4c4a1472beb92046db3praks * is that the process would come back and re-register the file to receive
31ceb98b622e1a310256f4c4a1472beb92046db3praks * further events. When there are more then 'port_fop_maxpfps' watches per file
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * it will attempt to free the oldest inactive watches.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * In case the event that is being delivered is an exception event, the cached
31ceb98b622e1a310256f4c4a1472beb92046db3praks * entries get removed. An exception event on a file or directory means its
31ceb98b622e1a310256f4c4a1472beb92046db3praks * identity got changed(rename to/from, delete, mounted over, file system
31ceb98b622e1a310256f4c4a1472beb92046db3praks * unmount).
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If the event port gets closed, all the associated file event watches will be
31ceb98b622e1a310256f4c4a1472beb92046db3praks * removed and discarded.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Data structures:
31ceb98b622e1a310256f4c4a1472beb92046db3praks * ----------------
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The list of file event watches per file are managed by the data structure
31ceb98b622e1a310256f4c4a1472beb92046db3praks * portfop_vp_t. The first time a file events watch is registered for a file,
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * a portfop_vp_t is installed on the vnode_t's member v_fopdata. This gets
31ceb98b622e1a310256f4c4a1472beb92046db3praks * removed and freed only when the vnode becomes inactive. The FEM hooks are
31ceb98b622e1a310256f4c4a1472beb92046db3praks * also installed when the first watch is registered on a file. The FEM hooks
31ceb98b622e1a310256f4c4a1472beb92046db3praks * get un-installed when all the watches are removed.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Each file events watch is represented by the structure portfop_t. They
31ceb98b622e1a310256f4c4a1472beb92046db3praks * get added to a list of portfop_t's on the vnode(portfop_vp_t). After
31ceb98b622e1a310256f4c4a1472beb92046db3praks * delivering an event, the portfop_t is marked inactive but retained. It is
31ceb98b622e1a310256f4c4a1472beb92046db3praks * moved to the end of the list. All the active portfop_t's are maintained at
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the beginning. In case of exception events, the portfop_t will be removed
31ceb98b622e1a310256f4c4a1472beb92046db3praks * and discarded.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * To intercept unmount operations, FSEM hooks are added to the file system
31ceb98b622e1a310256f4c4a1472beb92046db3praks * under which files are being watched. A hash table('portfop_vfs_hash_t') of
31ceb98b622e1a310256f4c4a1472beb92046db3praks * active file systems is maintained. Each file system that has active watches
31ceb98b622e1a310256f4c4a1472beb92046db3praks * is represented by 'portfop_vfs_t' and is added to the hash table.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The vnode's 'portfop_vp_t' structure is added to the list of files(vnodes)
31ceb98b622e1a310256f4c4a1472beb92046db3praks * being watched on the portfop_vfs_t structure.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * File system support:
31ceb98b622e1a310256f4c4a1472beb92046db3praks * -------------------
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * The file system implementation has to provide vnode event notifications
31ceb98b622e1a310256f4c4a1472beb92046db3praks * (vnevents) in order to support watching any files on that file system.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The vnode events(vnevents) are notifications provided by the file system
31ceb98b622e1a310256f4c4a1472beb92046db3praks * for name based file operations like rename, remove etc, which do not go
31ceb98b622e1a310256f4c4a1472beb92046db3praks * thru the VOP_** interfaces. If the file system does not implement vnode
31ceb98b622e1a310256f4c4a1472beb92046db3praks * notifications, watching for file events on such file systems is not
31ceb98b622e1a310256f4c4a1472beb92046db3praks * supported. The vnode event notifications support is determined by the call
31ceb98b622e1a310256f4c4a1472beb92046db3praks * vnevent_support(vp) (VOP_VNEVENT(vp, VE_SUPPORT)), which the file system
31ceb98b622e1a310256f4c4a1472beb92046db3praks * has to implement.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Locking order:
31ceb98b622e1a310256f4c4a1472beb92046db3praks * --------------
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * A file(vnode) can have file event watches registered by different processes.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * There is one portfop_t per watch registered. These are on the vnode's list
31ceb98b622e1a310256f4c4a1472beb92046db3praks * protected by the mutex 'pvp_mutex' in 'portfop_vp_t'. The portfop_t's are
31ceb98b622e1a310256f4c4a1472beb92046db3praks * also on the per port cache. The cache is protected by the pfc_lock of
31ceb98b622e1a310256f4c4a1472beb92046db3praks * portfop_cache_t. The lock order here is 'pfc_lock' -> 'pvp_mutex'.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/types.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/systm.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/stat.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/errno.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/kmem.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/sysmacros.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/debug.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/vnode.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/poll_impl.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/port_impl.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/fem.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/vfs_opreg.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks#include <sys/atomic.h>
84c5ce693a3660dc01d938cb3329b81631896a32praks#include <sys/mount.h>
84c5ce693a3660dc01d938cb3329b81631896a32praks#include <sys/mntent.h>
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * For special case support of mnttab (/etc/mnttab).
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraksextern struct vnode *vfs_mntdummyvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praksextern int mntfstype;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks#define PORTFOP_PVFSH(vfsp) (&portvfs_hash[PORTFOP_PVFSHASH(vfsp)])
31ceb98b622e1a310256f4c4a1472beb92046db3praksportfop_vfs_hash_t portvfs_hash[PORTFOP_PVFSHASH_SZ];
31ceb98b622e1a310256f4c4a1472beb92046db3praks
6b5ad791879c4fea5b397add82a50aaf0d392b91praks#define PORTFOP_NVP 20
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Inactive file event watches(portfop_t) are retained on the vnode's list
31ceb98b622e1a310256f4c4a1472beb92046db3praks * for performance reason. If the applications re-registers the file, the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * inactive entry is made active and moved up the list.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If there are greater then the following number of watches on a vnode,
31ceb98b622e1a310256f4c4a1472beb92046db3praks * it will attempt to discard an oldest inactive watch(pfp) at the time
073af7d9c45b5d0da4960c39a80af39504480d26praks * a new watch is being registered and when events get delivered. We
31ceb98b622e1a310256f4c4a1472beb92046db3praks * do this to avoid accumulating inactive watches on a file.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint port_fop_maxpfps = 20;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/* local functions */
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_callback(void *, int *, pid_t, int, void *);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void port_pcache_insert(portfop_cache_t *, portfop_t *);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void port_pcache_delete(portfop_cache_t *, portfop_t *);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void port_close_fop(void *arg, int port, pid_t pid, int lastclose);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * port fop functions that will be the fem hooks.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int port_fop_open(femarg_t *vf, int mode, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_read(femarg_t *vf, uio_t *uiop, int ioflag, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct caller_context *ct);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_write(femarg_t *vf, uio_t *uiop, int ioflag, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_map(femarg_t *vf, offset_t off, struct as *as,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caddr_t *addrp, size_t len, uchar_t prot, uchar_t maxport,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint_t flags, cred_t *cr, caller_context_t *ct);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_setattr(femarg_t *vf, vattr_t *vap, int flags, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_create(femarg_t *vf, char *name, vattr_t *vap,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vcexcl_t excl, int mode, vnode_t **vpp, cred_t *cr, int flag,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, vsecattr_t *vsecp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int port_fop_remove(femarg_t *vf, char *nm, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int flags);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int port_fop_link(femarg_t *vf, vnode_t *svp, char *tnm, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int flags);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_rename(femarg_t *vf, char *snm, vnode_t *tdvp, char *tnm,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cred_t *cr, caller_context_t *ct, int flags);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_mkdir(femarg_t *vf, char *dirname, vattr_t *vap,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vnode_t **vpp, cred_t *cr, caller_context_t *ct, int flags,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vsecattr_t *vsecp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int port_fop_rmdir(femarg_t *vf, char *nm, vnode_t *cdir, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int flags);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int port_fop_readdir(femarg_t *vf, uio_t *uiop, cred_t *cr, int *eofp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int flags);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_symlink(femarg_t *vf, char *linkname, vattr_t *vap,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *target, cred_t *cr, caller_context_t *ct, int flags);
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_setsecattr(femarg_t *vf, vsecattr_t *vsap, int flag,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cred_t *cr, caller_context_t *ct);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_vnevent(femarg_t *vf, vnevent_t vnevent, vnode_t *dvp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *cname, caller_context_t *ct);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int port_fop_unmount(fsemarg_t *vf, int flag, cred_t *cr);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Fem hooks.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksconst fs_operation_def_t port_vnodesrc_template[] = {
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_OPEN, { .femop_open = port_fop_open },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_READ, { .femop_read = port_fop_read },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_WRITE, { .femop_write = port_fop_write },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_MAP, { .femop_map = port_fop_map },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_SETATTR, { .femop_setattr = port_fop_setattr },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_CREATE, { .femop_create = port_fop_create },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_REMOVE, { .femop_remove = port_fop_remove },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_LINK, { .femop_link = port_fop_link },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_RENAME, { .femop_rename = port_fop_rename },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_MKDIR, { .femop_mkdir = port_fop_mkdir },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_RMDIR, { .femop_rmdir = port_fop_rmdir },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_READDIR, { .femop_readdir = port_fop_readdir },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_SYMLINK, { .femop_symlink = port_fop_symlink },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_SETSECATTR, { .femop_setsecattr = port_fop_setsecattr },
31ceb98b622e1a310256f4c4a1472beb92046db3praks VOPNAME_VNEVENT, { .femop_vnevent = port_fop_vnevent },
31ceb98b622e1a310256f4c4a1472beb92046db3praks NULL, NULL
31ceb98b622e1a310256f4c4a1472beb92046db3praks};
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Fsem - vfs ops hooks
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksconst fs_operation_def_t port_vfssrc_template[] = {
31ceb98b622e1a310256f4c4a1472beb92046db3praks VFSNAME_UNMOUNT, { .fsemop_unmount = port_fop_unmount },
31ceb98b622e1a310256f4c4a1472beb92046db3praks NULL, NULL
31ceb98b622e1a310256f4c4a1472beb92046db3praks};
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksfem_t *fop_femop;
31ceb98b622e1a310256f4c4a1472beb92046db3praksfsem_t *fop_fsemop;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic fem_t *
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_femop()
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks fem_t *femp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (fop_femop != NULL)
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (fop_femop);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (fem_create("portfop_fem",
31ceb98b622e1a310256f4c4a1472beb92046db3praks (const struct fs_operation_def *)port_vnodesrc_template,
31ceb98b622e1a310256f4c4a1472beb92046db3praks (fem_t **)&femp)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
75d94465dbafa487b716482dc36d5150a4ec9853Josef 'Jeff' Sipek if (atomic_cas_ptr(&fop_femop, NULL, femp) != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * some other thread beat us to it.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks fem_free(femp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (fop_femop);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic fsem_t *
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_fsemop()
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks fsem_t *fsemp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (fop_fsemop != NULL)
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (fop_fsemop);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (fsem_create("portfop_fsem", port_vfssrc_template, &fsemp)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
75d94465dbafa487b716482dc36d5150a4ec9853Josef 'Jeff' Sipek if (atomic_cas_ptr(&fop_fsemop, NULL, fsemp) != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * some other thread beat us to it.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks fsem_free(fsemp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (fop_fsemop);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * port_fop_callback()
31ceb98b622e1a310256f4c4a1472beb92046db3praks * - PORT_CALLBACK_DEFAULT
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The file event will be delivered to the application.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * - PORT_CALLBACK_DISSOCIATE
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The object will be dissociated from the port.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * - PORT_CALLBACK_CLOSE
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The object will be dissociated from the port because the port
31ceb98b622e1a310256f4c4a1472beb92046db3praks * is being closed.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks/* ARGSUSED */
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_callback(void *arg, int *events, pid_t pid, int flag, void *evp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *pfp = (portfop_t *)arg;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_kevent_t *pkevp = (port_kevent_t *)evp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int error = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks ASSERT((events != NULL));
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (flag == PORT_CALLBACK_DEFAULT) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (curproc->p_pid != pid) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (EACCES); /* deny delivery of events */
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks *events = pkevp->portkev_events;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_events = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags &= ~PORT_FOP_KEV_ONQ;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Inserts a portfop_t into the port sources cache's.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_pcache_insert(portfop_cache_t *pfcp, portfop_t *pfp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t **bucket;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks ASSERT(MUTEX_HELD(&pfcp->pfc_lock));
31ceb98b622e1a310256f4c4a1472beb92046db3praks bucket = PORT_FOP_BUCKET(pfcp, pfp->pfop_object);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_hashnext = *bucket;
31ceb98b622e1a310256f4c4a1472beb92046db3praks *bucket = pfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfcp->pfc_objcount++;
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Remove the pfp from the port source cache.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_pcache_delete(portfop_cache_t *pfcp, portfop_t *pfp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *lpdp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *cpdp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t **bucket;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks bucket = PORT_FOP_BUCKET(pfcp, pfp->pfop_object);
31ceb98b622e1a310256f4c4a1472beb92046db3praks cpdp = *bucket;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp == cpdp) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks *bucket = pfp->pfop_hashnext;
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks while (cpdp != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks lpdp = cpdp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks cpdp = cpdp->pfop_hashnext;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (cpdp == pfp) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /* portfop struct found */
31ceb98b622e1a310256f4c4a1472beb92046db3praks lpdp->pfop_hashnext = pfp->pfop_hashnext;
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfcp->pfc_objcount--;
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The vnode's(portfop_vp_t) pfp list management. The 'pvp_mutex' is held
31ceb98b622e1a310256f4c4a1472beb92046db3praks * when these routines are called.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The 'pvp_lpfop' member points to the oldest inactive entry on the list.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * It is used to discard the oldtest inactive pfp if the number of entries
31ceb98b622e1a310256f4c4a1472beb92046db3praks * exceed the limit.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_listinsert(portfop_vp_t *pvp, portfop_t *pfp, int where)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (where == 1) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_insert_head(&pvp->pvp_pfoplist, (void *)pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_insert_tail(&pvp->pvp_pfoplist, (void *)pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pvp->pvp_lpfop == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_lpfop = pfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_cnt++;
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_listinsert_head(portfop_vp_t *pvp, portfop_t *pfp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listinsert(pvp, pfp, 1);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_listinsert_tail(portfop_vp_t *pvp, portfop_t *pfp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * We point lpfop to an inactive one, if it was initially pointing
31ceb98b622e1a310256f4c4a1472beb92046db3praks * to an active one. Insert to the tail is done only when a pfp goes
31ceb98b622e1a310256f4c4a1472beb92046db3praks * inactive.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pvp->pvp_lpfop && pvp->pvp_lpfop->pfop_flags & PORT_FOP_ACTIVE) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_lpfop = pfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listinsert(pvp, pfp, 0);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_listremove(portfop_vp_t *pvp, portfop_t *pfp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pvp->pvp_lpfop == pfp) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_lpfop = list_next(&pvp->pvp_pfoplist, (void *)pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_remove(&pvp->pvp_pfoplist, (void *)pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_cnt--;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pvp->pvp_cnt && pvp->pvp_lpfop == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_lpfop = list_head(&pvp->pvp_pfoplist);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_listmove(portfop_vp_t *pvp, list_t *tlist)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_move_tail(tlist, &pvp->pvp_pfoplist);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_lpfop = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_cnt = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Remove a portfop_t from the port cache hash table and discard it.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * It is called only when pfp is not on the vnode's list. Otherwise,
31ceb98b622e1a310256f4c4a1472beb92046db3praks * port_remove_fop() is called.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksvoid
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_pcache_remove_fop(portfop_cache_t *pfcp, portfop_t *pfp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_kevent_t *pkevp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks ASSERT(MUTEX_HELD(&pfcp->pfc_lock));
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp = pfp->pfop_pev;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_pev = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pkevp != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks (void) port_remove_done_event(pkevp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_free_event_local(pkevp, 0);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_pcache_delete(pfcp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_cname != NULL)
31ceb98b622e1a310256f4c4a1472beb92046db3praks kmem_free(pfp->pfop_cname, pfp->pfop_clen + 1);
31ceb98b622e1a310256f4c4a1472beb92046db3praks kmem_free(pfp, sizeof (portfop_t));
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfcp->pfc_objcount == 0)
31ceb98b622e1a310256f4c4a1472beb92046db3praks cv_signal(&pfcp->pfc_lclosecv);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * if we have too many watches on the vnode, attempt to discard an
31ceb98b622e1a310256f4c4a1472beb92046db3praks * inactive one.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_trimpfplist(vnode_t *vp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vp_t *pvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *pfp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_cache_t *pfcp;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks vnode_t *tdvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Due to a reference the vnode cannot disappear, v_fopdata should
31ceb98b622e1a310256f4c4a1472beb92046db3praks * not change.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((pvp = vp->v_fopdata) != NULL &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_cnt > port_fop_maxpfps) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp = pvp->pvp_lpfop;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfcp = pfp->pfop_pcache;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * only if we can get the cache lock, we need to
31ceb98b622e1a310256f4c4a1472beb92046db3praks * do this due to reverse lock order and some thread
31ceb98b622e1a310256f4c4a1472beb92046db3praks * that may be trying to reactivate this entry.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (mutex_tryenter(&pfcp->pfc_lock)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp && !(pfp->pfop_flags & PORT_FOP_ACTIVE) &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks !(pfp->pfop_flags & PORT_FOP_KEV_ONQ)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listremove(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags |= PORT_FOP_REMOVING;
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * discard pfp if any.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp != NULL) {
6b5ad791879c4fea5b397add82a50aaf0d392b91praks tdvp = pfp->pfop_dvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_pcache_remove_fop(pfcp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pfcp->pfc_lock);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (tdvp != NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(tdvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
6b5ad791879c4fea5b397add82a50aaf0d392b91praks/*
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * This routine returns 1, if the vnode can be rele'ed by the caller.
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * The caller has to VN_RELE the vnode with out holding any
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * locks.
6b5ad791879c4fea5b397add82a50aaf0d392b91praks */
6b5ad791879c4fea5b397add82a50aaf0d392b91praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_femuninstall(vnode_t *vp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vp_t *pvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vfs_t *vfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vfs_t *pvfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vfs_hash_t *pvfsh;
31ceb98b622e1a310256f4c4a1472beb92046db3praks kmutex_t *mtx;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks int ret = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * if list is empty, uninstall fem.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp = vp->v_fopdata;
31ceb98b622e1a310256f4c4a1472beb92046db3praks ASSERT(MUTEX_HELD(&pvp->pvp_mutex));
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * make sure the list is empty.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!list_head(&pvp->pvp_pfoplist)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * we could possibly uninstall the fem hooks when
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the vnode becomes inactive and the v_fopdata is
073af7d9c45b5d0da4960c39a80af39504480d26praks * free. But the hooks get triggered unnecessarily
31ceb98b622e1a310256f4c4a1472beb92046db3praks * even though there are no active watches. So, we
31ceb98b622e1a310256f4c4a1472beb92046db3praks * uninstall it here.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks (void) fem_uninstall(vp, (fem_t *)pvp->pvp_femp, vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_femp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * If we successfully uninstalled fem, no process is watching
073af7d9c45b5d0da4960c39a80af39504480d26praks * this vnode, Remove it from the vfs's list of watched vnodes.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsp = pvp->pvp_pvfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vfsp = vp->v_vfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsh = PORTFOP_PVFSH(vfsp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks mtx = &pvfsh->pvfshash_mutex;
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(mtx);
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If unmount is in progress, that thread will remove and
31ceb98b622e1a310256f4c4a1472beb92046db3praks * release the vnode from the vfs's list, just leave.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!pvfsp->pvfs_unmount) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_remove(&pvfsp->pvfs_pvplist, pvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(mtx);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks ret = 1;
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(mtx);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
e1054916dcccb673a033fb9878063866d615ae62Robert Mustacchi mutex_exit(&pvp->pvp_mutex);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks return (ret);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Remove pfp from the vnode's watch list and the cache and discard it.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If it is the last pfp on the vnode's list, the fem hooks get uninstalled.
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * Returns 1 if pfp removed successfully.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The *active is set to indicate if the pfp was still active(no events had
31ceb98b622e1a310256f4c4a1472beb92046db3praks * been posted, or the posted event had not been collected yet and it was
31ceb98b622e1a310256f4c4a1472beb92046db3praks * able to remove it from the port's queue).
6b5ad791879c4fea5b397add82a50aaf0d392b91praks *
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * vpp and dvpp will point to the vnode and directory vnode which the caller
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * is required to VN_RELE without holding any locks.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_remove_fop(portfop_t *pfp, portfop_cache_t *pfcp, int cleanup,
6b5ad791879c4fea5b397add82a50aaf0d392b91praks int *active, vnode_t **vpp, vnode_t **dvpp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vp_t *pvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int tactive = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks ASSERT(MUTEX_HELD(&pfcp->pfc_lock));
31ceb98b622e1a310256f4c4a1472beb92046db3praks vp = pfp->pfop_vp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp = vp->v_fopdata;
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * if not cleanup, remove it only if the pfp is still active and
31ceb98b622e1a310256f4c4a1472beb92046db3praks * is not being removed by some other thread.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!cleanup && (!(pfp->pfop_flags & PORT_FOP_ACTIVE) ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags & PORT_FOP_REMOVING)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (0);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * mark it inactive.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_flags & PORT_FOP_ACTIVE) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags &= ~PORT_FOP_ACTIVE;
31ceb98b622e1a310256f4c4a1472beb92046db3praks tactive = 1;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Check if the pfp is still on the vnode's list. This can
31ceb98b622e1a310256f4c4a1472beb92046db3praks * happen if port_fop_excep() is in the process of removing it.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * In case of cleanup, just mark this pfp as inactive so that no
31ceb98b622e1a310256f4c4a1472beb92046db3praks * new events (VNEVENT) will be delivered, and remove it from the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * event queue if it was already queued. Since the cache lock is
31ceb98b622e1a310256f4c4a1472beb92046db3praks * held, the pfp will not disappear, even though it is being
31ceb98b622e1a310256f4c4a1472beb92046db3praks * removed.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_flags & PORT_FOP_REMOVING) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!tactive && port_remove_done_event(pfp->pfop_pev)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags &= ~PORT_FOP_KEV_ONQ;
31ceb98b622e1a310256f4c4a1472beb92046db3praks tactive = 1;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (active) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks *active = tactive;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (1);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * if we find an event on the queue and removed it, then this
31ceb98b622e1a310256f4c4a1472beb92046db3praks * association is considered active.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!tactive && port_remove_done_event(pfp->pfop_pev)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags &= ~PORT_FOP_KEV_ONQ;
31ceb98b622e1a310256f4c4a1472beb92046db3praks tactive = 1;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (active) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks *active = tactive;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp = (portfop_vp_t *)vp->v_fopdata;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * remove pfp from the vnode's list
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listremove(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If no more associations on the vnode, uninstall fem hooks.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The pvp mutex will be released in this routine.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (port_fop_femuninstall(vp))
6b5ad791879c4fea5b397add82a50aaf0d392b91praks *vpp = vp;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks *dvpp = pfp->pfop_dvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_pcache_remove_fop(pfcp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (1);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * This routine returns a pointer to a cached portfop entry, or NULL if it
31ceb98b622e1a310256f4c4a1472beb92046db3praks * does not find it in the hash table. The object pointer is used as index.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The entries are hashed by the object's address. We need to match the pid
31ceb98b622e1a310256f4c4a1472beb92046db3praks * as the evet port can be shared between processes. The file events
31ceb98b622e1a310256f4c4a1472beb92046db3praks * watches are per process only.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksportfop_t *
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_cache_lookup_fop(portfop_cache_t *pfcp, pid_t pid, uintptr_t obj)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *pfp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t **bucket;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks ASSERT(MUTEX_HELD(&pfcp->pfc_lock));
31ceb98b622e1a310256f4c4a1472beb92046db3praks bucket = PORT_FOP_BUCKET(pfcp, obj);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp = *bucket;
31ceb98b622e1a310256f4c4a1472beb92046db3praks while (pfp != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_object == obj && pfp->pfop_pid == pid)
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp = pfp->pfop_hashnext;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Given the file name, get the vnode and also the directory vnode
31ceb98b622e1a310256f4c4a1472beb92046db3praks * On return, the vnodes are held (VN_HOLD). The caller has to VN_RELE
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the vnode(s).
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_getdvp(void *objptr, vnode_t **vp, vnode_t **dvp,
31ceb98b622e1a310256f4c4a1472beb92046db3praks char **cname, int *len, int follow)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int error = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks struct pathname pn;
31ceb98b622e1a310256f4c4a1472beb92046db3praks char *fname;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (get_udatamodel() == DATAMODEL_NATIVE) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks fname = ((file_obj_t *)objptr)->fo_name;
31ceb98b622e1a310256f4c4a1472beb92046db3praks#ifdef _SYSCALL32_IMPL
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks fname = (caddr_t)(uintptr_t)((file_obj32_t *)objptr)->fo_name;
31ceb98b622e1a310256f4c4a1472beb92046db3praks#endif /* _SYSCALL32_IMPL */
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * lookuppn may fail with EINVAL, if dvp is non-null(like when
31ceb98b622e1a310256f4c4a1472beb92046db3praks * looking for "."). So call again with dvp = NULL.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((error = pn_get(fname, UIO_USERSPACE, &pn)) != 0) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks error = lookuppn(&pn, NULL, follow, dvp, vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (error == EINVAL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pn_free(&pn);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((error = pn_get(fname, UIO_USERSPACE, &pn)) != 0) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks error = lookuppn(&pn, NULL, follow, NULL, vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (dvp != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks *dvp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (error == 0 && cname != NULL && len != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pn_setlast(&pn);
31ceb98b622e1a310256f4c4a1472beb92046db3praks *len = pn.pn_pathlen;
31ceb98b622e1a310256f4c4a1472beb92046db3praks *cname = kmem_alloc(*len + 1, KM_SLEEP);
31ceb98b622e1a310256f4c4a1472beb92046db3praks (void) strcpy(*cname, pn.pn_path);
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (cname != NULL && len != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks *cname = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks *len = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pn_free(&pn);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_source_t *
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_getsrc(port_t *pp, int source)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_source_t *pse;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int lock = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * get the port source structure.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!MUTEX_HELD(&pp->port_queue.portq_source_mutex)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pp->port_queue.portq_source_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks lock = 1;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pse = pp->port_queue.portq_scache[PORT_SHASH(source)];
31ceb98b622e1a310256f4c4a1472beb92046db3praks for (; pse != NULL; pse = pse->portsrc_next) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pse->portsrc_source == source)
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (lock) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pp->port_queue.portq_source_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (pse);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
073af7d9c45b5d0da4960c39a80af39504480d26praks * Compare time stamps and generate an event if it has changed.
073af7d9c45b5d0da4960c39a80af39504480d26praks * Note that the port cache pointer will be valid due to a reference
073af7d9c45b5d0da4960c39a80af39504480d26praks * to the port. We need to grab the port cache lock and verify that
073af7d9c45b5d0da4960c39a80af39504480d26praks * the pfp is still the same before proceeding to deliver an event.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
073af7d9c45b5d0da4960c39a80af39504480d26praksport_check_timestamp(portfop_cache_t *pfcp, vnode_t *vp, vnode_t *dvp,
073af7d9c45b5d0da4960c39a80af39504480d26praks portfop_t *pfp, void *objptr, uintptr_t object)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks vattr_t vatt;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vp_t *pvp = vp->v_fopdata;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int events = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_kevent_t *pkevp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks file_obj_t *fobj;
073af7d9c45b5d0da4960c39a80af39504480d26praks portfop_t *tpfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * If time stamps are specified, get attributes and compare.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks vatt.va_mask = AT_ATIME|AT_MTIME|AT_CTIME;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (get_udatamodel() == DATAMODEL_NATIVE) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj = (file_obj_t *)objptr;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (fobj->fo_atime.tv_sec || fobj->fo_atime.tv_nsec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj->fo_mtime.tv_sec || fobj->fo_mtime.tv_nsec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj->fo_ctime.tv_sec || fobj->fo_ctime.tv_nsec) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (VOP_GETATTR(vp, &vatt, 0, CRED(), NULL)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks return;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * timestamp not specified, all 0's,
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks return;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks#ifdef _SYSCALL32_IMPL
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks file_obj32_t *fobj32;
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj32 = (file_obj32_t *)objptr;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (fobj32->fo_atime.tv_sec || fobj32->fo_atime.tv_nsec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj32->fo_mtime.tv_sec || fobj32->fo_mtime.tv_nsec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj32->fo_ctime.tv_sec || fobj32->fo_ctime.tv_nsec) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (VOP_GETATTR(vp, &vatt, 0, CRED(), NULL)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks return;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * timestamp not specified, all 0.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks return;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks#endif /* _SYSCALL32_IMPL */
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
073af7d9c45b5d0da4960c39a80af39504480d26praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * Now grab the cache lock and verify that we are still
073af7d9c45b5d0da4960c39a80af39504480d26praks * dealing with the same pfp and curthread is the one
073af7d9c45b5d0da4960c39a80af39504480d26praks * which registered it. We need to do this to avoid
073af7d9c45b5d0da4960c39a80af39504480d26praks * delivering redundant events.
073af7d9c45b5d0da4960c39a80af39504480d26praks */
073af7d9c45b5d0da4960c39a80af39504480d26praks mutex_enter(&pfcp->pfc_lock);
073af7d9c45b5d0da4960c39a80af39504480d26praks tpfp = port_cache_lookup_fop(pfcp, curproc->p_pid, object);
073af7d9c45b5d0da4960c39a80af39504480d26praks
073af7d9c45b5d0da4960c39a80af39504480d26praks if (tpfp == NULL || tpfp != pfp ||
073af7d9c45b5d0da4960c39a80af39504480d26praks pfp->pfop_vp != vp || pfp->pfop_dvp != dvp ||
073af7d9c45b5d0da4960c39a80af39504480d26praks pfp->pfop_callrid != curthread ||
073af7d9c45b5d0da4960c39a80af39504480d26praks !(pfp->pfop_flags & PORT_FOP_ACTIVE)) {
073af7d9c45b5d0da4960c39a80af39504480d26praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * Some other event was delivered, the file
073af7d9c45b5d0da4960c39a80af39504480d26praks * watch was removed or reassociated. Just
073af7d9c45b5d0da4960c39a80af39504480d26praks * ignore it and leave
073af7d9c45b5d0da4960c39a80af39504480d26praks */
073af7d9c45b5d0da4960c39a80af39504480d26praks mutex_exit(&pfcp->pfc_lock);
073af7d9c45b5d0da4960c39a80af39504480d26praks return;
073af7d9c45b5d0da4960c39a80af39504480d26praks }
073af7d9c45b5d0da4960c39a80af39504480d26praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * The pfp cannot disappear as the port cache lock is held.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * While the pvp_mutex is held, no events will get delivered.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_flags & PORT_FOP_ACTIVE &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks !(pfp->pfop_flags & PORT_FOP_REMOVING)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (get_udatamodel() == DATAMODEL_NATIVE) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj = (file_obj_t *)objptr;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_events & FILE_ACCESS &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (fobj->fo_atime.tv_sec || fobj->fo_atime.tv_nsec) &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (vatt.va_atime.tv_sec != fobj->fo_atime.tv_sec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks vatt.va_atime.tv_nsec != fobj->fo_atime.tv_nsec))
31ceb98b622e1a310256f4c4a1472beb92046db3praks events |= FILE_ACCESS;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_events & FILE_MODIFIED &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (fobj->fo_mtime.tv_sec || fobj->fo_mtime.tv_nsec) &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (vatt.va_mtime.tv_sec != fobj->fo_mtime.tv_sec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks vatt.va_mtime.tv_nsec != fobj->fo_mtime.tv_nsec))
31ceb98b622e1a310256f4c4a1472beb92046db3praks events |= FILE_MODIFIED;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_events & FILE_ATTRIB &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (fobj->fo_ctime.tv_sec || fobj->fo_ctime.tv_nsec) &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (vatt.va_ctime.tv_sec != fobj->fo_ctime.tv_sec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks vatt.va_ctime.tv_nsec != fobj->fo_ctime.tv_nsec))
31ceb98b622e1a310256f4c4a1472beb92046db3praks events |= FILE_ATTRIB;
31ceb98b622e1a310256f4c4a1472beb92046db3praks#ifdef _SYSCALL32_IMPL
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks file_obj32_t *fobj32;
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj32 = (file_obj32_t *)objptr;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_events & FILE_ACCESS &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (fobj32->fo_atime.tv_sec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj32->fo_atime.tv_nsec) &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (vatt.va_atime.tv_sec != fobj32->fo_atime.tv_sec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks vatt.va_atime.tv_nsec != fobj32->fo_atime.tv_nsec))
31ceb98b622e1a310256f4c4a1472beb92046db3praks events |= FILE_ACCESS;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_events & FILE_MODIFIED &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (fobj32->fo_mtime.tv_sec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj32->fo_mtime.tv_nsec) &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (vatt.va_mtime.tv_sec != fobj32->fo_mtime.tv_sec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks vatt.va_mtime.tv_nsec != fobj32->fo_mtime.tv_nsec))
31ceb98b622e1a310256f4c4a1472beb92046db3praks events |= FILE_MODIFIED;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_events & FILE_ATTRIB &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (fobj32->fo_ctime.tv_sec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks fobj32->fo_ctime.tv_nsec) &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (vatt.va_ctime.tv_sec != fobj32->fo_ctime.tv_sec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks vatt.va_ctime.tv_nsec != fobj32->fo_ctime.tv_nsec))
31ceb98b622e1a310256f4c4a1472beb92046db3praks events |= FILE_ATTRIB;
31ceb98b622e1a310256f4c4a1472beb92046db3praks#endif /* _SYSCALL32_IMPL */
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * No events to deliver
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (events == 0) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvp->pvp_mutex);
073af7d9c45b5d0da4960c39a80af39504480d26praks mutex_exit(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Deliver the event now.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp = pfp->pfop_pev;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags &= ~PORT_FOP_ACTIVE;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_events |= events;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Move it to the tail as active once are in the
073af7d9c45b5d0da4960c39a80af39504480d26praks * beginning of the list.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listremove(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listinsert_tail(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_send_event(pkevp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags |= PORT_FOP_KEV_ONQ;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvp->pvp_mutex);
073af7d9c45b5d0da4960c39a80af39504480d26praks mutex_exit(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Add the event source to the port and return the port source cache pointer.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_associate_source(portfop_cache_t **pfcpp, port_t *pp, int source)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_cache_t *pfcp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_source_t *pse;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int error;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * associate PORT_SOURCE_FILE source with the port, if it is
31ceb98b622e1a310256f4c4a1472beb92046db3praks * not associated yet. Note the PORT_SOURCE_FILE source is
31ceb98b622e1a310256f4c4a1472beb92046db3praks * associated once and will not be dissociated.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((pse = port_getsrc(pp, PORT_SOURCE_FILE)) == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (error = port_associate_ksource(pp->port_fd, source,
31ceb98b622e1a310256f4c4a1472beb92046db3praks &pse, port_close_fop, pp, NULL)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks *pfcpp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Get the portfop cache pointer.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((pfcp = pse->portsrc_data) == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * This is the first time that a file is being associated,
31ceb98b622e1a310256f4c4a1472beb92046db3praks * create the portfop cache.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfcp = kmem_zalloc(sizeof (portfop_cache_t), KM_SLEEP);
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pp->port_queue.portq_source_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pse->portsrc_data == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pse->portsrc_data = pfcp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pp->port_queue.portq_source_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * someone else created the port cache, free
31ceb98b622e1a310256f4c4a1472beb92046db3praks * what we just now allocated.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pp->port_queue.portq_source_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks kmem_free(pfcp, sizeof (portfop_cache_t));
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfcp = pse->portsrc_data;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks *pfcpp = pfcp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (0);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Add the given pvp on the file system's list of vnodes watched.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_pvfsadd(portfop_vp_t *pvp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int error = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = pvp->pvp_vp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vfs_hash_t *pvfsh;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vfs_t *pvfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks fsem_t *fsemp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsh = PORTFOP_PVFSH(vp->v_vfsp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pvfsh->pvfshash_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks for (pvfsp = pvfsh->pvfshash_pvfsp; pvfsp &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsp->pvfs != vp->v_vfsp; pvfsp = pvfsp->pvfs_next)
31ceb98b622e1a310256f4c4a1472beb92046db3praks ;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!pvfsp) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((fsemp = port_fop_fsemop()) != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((error = fsem_install(vp->v_vfsp, fsemp,
31ceb98b622e1a310256f4c4a1472beb92046db3praks vp->v_vfsp, OPUNIQ, NULL, NULL))) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvfsh->pvfshash_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvfsh->pvfshash_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (EINVAL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsp = kmem_zalloc(sizeof (portfop_vfs_t), KM_SLEEP);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsp->pvfs = vp->v_vfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_create(&(pvfsp->pvfs_pvplist), sizeof (portfop_vp_t),
31ceb98b622e1a310256f4c4a1472beb92046db3praks offsetof(portfop_vp_t, pvp_pvfsnode));
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsp->pvfs_fsemp = fsemp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsp->pvfs_next = pvfsh->pvfshash_pvfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsh->pvfshash_pvfsp = pvfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * check if an unmount is in progress.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!pvfsp->pvfs_unmount) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * insert the pvp on list.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_pvfsp = pvfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_insert_head(&pvfsp->pvfs_pvplist, (void *)pvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks error = EINVAL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvfsh->pvfshash_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Installs the portfop_vp_t data structure on the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * vnode. The 'pvp_femp == NULL' indicates it is not
31ceb98b622e1a310256f4c4a1472beb92046db3praks * active. The fem hooks have to be installed.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The portfop_vp_t is only freed when the vnode gets freed.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksvoid
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_install_fopdata(vnode_t *vp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vp_t *npvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks npvp = kmem_zalloc(sizeof (*npvp), KM_SLEEP);
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_init(&npvp->pvp_mutex, NULL, MUTEX_DEFAULT, NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_create(&npvp->pvp_pfoplist, sizeof (portfop_t),
31ceb98b622e1a310256f4c4a1472beb92046db3praks offsetof(portfop_t, pfop_node));
31ceb98b622e1a310256f4c4a1472beb92046db3praks npvp->pvp_vp = vp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If v_fopdata is not null, some other thread beat us to it.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
75d94465dbafa487b716482dc36d5150a4ec9853Josef 'Jeff' Sipek if (atomic_cas_ptr(&vp->v_fopdata, NULL, npvp) != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_destroy(&npvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_destroy(&npvp->pvp_pfoplist);
31ceb98b622e1a310256f4c4a1472beb92046db3praks kmem_free(npvp, sizeof (*npvp));
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Allocate and add a portfop_t to the per port cache. Also add the portfop_t
31ceb98b622e1a310256f4c4a1472beb92046db3praks * to the vnode's list. The association is identified by the object pointer
31ceb98b622e1a310256f4c4a1472beb92046db3praks * address and pid.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_pfp_setup(portfop_t **pfpp, port_t *pp, vnode_t *vp, portfop_cache_t *pfcp,
31ceb98b622e1a310256f4c4a1472beb92046db3praks uintptr_t object, int events, void *user, char *cname, int clen,
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *dvp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *pfp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_kevent_t *pkevp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks fem_t *femp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int error = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vp_t *pvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The port cache mutex is held.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks *pfpp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * At this point the fem monitor is installed.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Allocate a port event structure per vnode association.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (error = port_alloc_event_local(pp, PORT_SOURCE_FILE,
31ceb98b622e1a310256f4c4a1472beb92046db3praks PORT_ALLOC_CACHED, &pkevp)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp = kmem_zalloc(sizeof (portfop_t), KM_SLEEP);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_pev = pkevp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_vp = vp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_pid = curproc->p_pid;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_pcache = pfcp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_pp = pp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags |= PORT_FOP_ACTIVE;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_cname = cname;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_clen = clen;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_dvp = dvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_object = object;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_callback = port_fop_callback;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_arg = pfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_object = object;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_user = user;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_events = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_pcache_insert(pfcp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Register a new file events monitor for this file(vnode), if not
31ceb98b622e1a310256f4c4a1472beb92046db3praks * done already.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((pvp = vp->v_fopdata) == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_install_fopdata(vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp = vp->v_fopdata;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * if the vnode does not have the file events hooks, install it.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pvp->pvp_femp == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((femp = port_fop_femop()) != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!(error = fem_install(pfp->pfop_vp, femp,
31ceb98b622e1a310256f4c4a1472beb92046db3praks (void *)vp, OPUNIQ, NULL, NULL))) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_femp = femp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * add fsem_t hooks to the vfsp and add pvp to
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the list of vnodes for this vfs.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!(error = port_fop_pvfsadd(pvp))) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Hold a reference to the vnode since
31ceb98b622e1a310256f4c4a1472beb92046db3praks * we successfully installed the hooks.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks VN_HOLD(vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks (void) fem_uninstall(vp, femp, vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp->pvp_femp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks error = EINVAL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (error) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * pkevp will get freed here.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
073af7d9c45b5d0da4960c39a80af39504480d26praks pfp->pfop_cname = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_pcache_remove_fop(pfcp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * insert the pfp on the vnode's list. After this
31ceb98b622e1a310256f4c4a1472beb92046db3praks * events can get delivered.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_events = events;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listinsert_head(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvp->pvp_mutex);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks /*
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * Hold the directory vnode since we have a reference now.
6b5ad791879c4fea5b397add82a50aaf0d392b91praks */
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (dvp != NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_HOLD(dvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks *pfpp = pfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (0);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksvnode_t *
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_resolve_vp(vnode_t *vp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *rvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * special case /etc/mnttab(mntfs type). The mntfstype != 0
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * if mntfs got mounted.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks if (vfs_mntdummyvp && mntfstype != 0 &&
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks vp->v_vfsp->vfs_fstype == mntfstype) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks VN_RELE(vp);
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks vp = vfs_mntdummyvp;
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks VN_HOLD(vfs_mntdummyvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * This should take care of lofs mounted fs systems and nfs4
31ceb98b622e1a310256f4c4a1472beb92046db3praks * hardlinks.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((VOP_REALVP(vp, &rvp, NULL) == 0) && vp != rvp) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks VN_HOLD(rvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks VN_RELE(vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks vp = rvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Register a file events watch on the given file associated to the port *pp.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The association is identified by the object pointer and the pid.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The events argument contains the events to be monitored for.
6b5ad791879c4fea5b397add82a50aaf0d392b91praks *
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * The vnode will have a VN_HOLD once the fem hooks are installed.
6b5ad791879c4fea5b397add82a50aaf0d392b91praks *
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * Every reference(pfp) to the directory vnode will have a VN_HOLD to ensure
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * that the directory vnode pointer does not change.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_associate_fop(port_t *pp, int source, uintptr_t object, int events,
31ceb98b622e1a310256f4c4a1472beb92046db3praks void *user)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_cache_t *pfcp;
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill vnode_t *vp, *dvp, *oldvp = NULL, *olddvp = NULL, *orig;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *pfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int error = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks file_obj_t fobj;
31ceb98b622e1a310256f4c4a1472beb92046db3praks void *objptr;
31ceb98b622e1a310256f4c4a1472beb92046db3praks char *cname;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int clen;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int follow;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * check that events specified are valid.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((events & ~FILE_EVENTS_MASK) != 0)
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (EINVAL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (get_udatamodel() == DATAMODEL_NATIVE) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (copyin((void *)object, &fobj, sizeof (file_obj_t)))
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (EFAULT);
31ceb98b622e1a310256f4c4a1472beb92046db3praks objptr = (void *)&fobj;
31ceb98b622e1a310256f4c4a1472beb92046db3praks#ifdef _SYSCALL32_IMPL
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks file_obj32_t fobj32;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (copyin((void *)object, &fobj32, sizeof (file_obj32_t)))
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (EFAULT);
31ceb98b622e1a310256f4c4a1472beb92046db3praks objptr = (void *)&fobj32;
31ceb98b622e1a310256f4c4a1472beb92046db3praks#endif /* _SYSCALL32_IMPL */
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks vp = dvp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * find out if we need to follow symbolic links.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks follow = !(events & FILE_NOFOLLOW);
31ceb98b622e1a310256f4c4a1472beb92046db3praks events = events & ~FILE_NOFOLLOW;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * lookup and find the vnode and its directory vnode of the given
31ceb98b622e1a310256f4c4a1472beb92046db3praks * file.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((error = port_fop_getdvp(objptr, &vp, &dvp, &cname, &clen,
31ceb98b622e1a310256f4c4a1472beb92046db3praks follow)) != 0) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (dvp != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks dvp = port_resolve_vp(dvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Not found
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (vp == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks error = ENOENT;
31ceb98b622e1a310256f4c4a1472beb92046db3praks goto errout;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill vp = port_resolve_vp(orig = vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (vp != NULL && vnevent_support(vp, NULL)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks error = ENOTSUP;
31ceb98b622e1a310256f4c4a1472beb92046db3praks goto errout;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
efaadbbfd41d2a35674006a9d58a2812beba0ea8Prakash Sangappa /*
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill * If dvp belongs to a different filesystem just ignore it, as hard
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill * links cannot exist across filesystems. We make an exception for
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill * procfs, however, the magic of which we treat semantically as a hard
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill * link, allowing one to use /proc/[pid]/fd/[fd] for PORT_SOURCE_FILE
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill * and avoid spurious FILE_RENAME_FROM/FILE_RENAME_TO events.
efaadbbfd41d2a35674006a9d58a2812beba0ea8Prakash Sangappa */
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill if (dvp != NULL && dvp->v_vfsp != vp->v_vfsp &&
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill !(orig->v_type == VPROC && vp != NULL && vp->v_type != VPROC)) {
efaadbbfd41d2a35674006a9d58a2812beba0ea8Prakash Sangappa VN_RELE(dvp);
efaadbbfd41d2a35674006a9d58a2812beba0ea8Prakash Sangappa dvp = NULL;
efaadbbfd41d2a35674006a9d58a2812beba0ea8Prakash Sangappa }
efaadbbfd41d2a35674006a9d58a2812beba0ea8Prakash Sangappa
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Associate this source to the port and get the per port
31ceb98b622e1a310256f4c4a1472beb92046db3praks * fop cache pointer. If the source is already associated, it
31ceb98b622e1a310256f4c4a1472beb92046db3praks * will just return the cache pointer.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (error = port_fop_associate_source(&pfcp, pp, source)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks goto errout;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Check if there is an existing association of this file.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp = port_cache_lookup_fop(pfcp, curproc->p_pid, object);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * If it is not the same vnode, just discard it. VN_RELE needs to be
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * called with no locks held, therefore save vnode pointers and
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * vn_rele them later.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp != NULL && (pfp->pfop_vp != vp || pfp->pfop_dvp != dvp)) {
6b5ad791879c4fea5b397add82a50aaf0d392b91praks (void) port_remove_fop(pfp, pfcp, 1, NULL, &oldvp, &olddvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp == NULL) {
6b5ad791879c4fea5b397add82a50aaf0d392b91praks vnode_t *tvp, *tdvp;
073af7d9c45b5d0da4960c39a80af39504480d26praks portfop_t *tpfp;
073af7d9c45b5d0da4960c39a80af39504480d26praks int error;
073af7d9c45b5d0da4960c39a80af39504480d26praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Add a new association, save the file name and the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * directory vnode pointer.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (error = port_pfp_setup(&pfp, pp, vp, pfcp, object,
31ceb98b622e1a310256f4c4a1472beb92046db3praks events, user, cname, clen, dvp)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks goto errout;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
073af7d9c45b5d0da4960c39a80af39504480d26praks pfp->pfop_callrid = curthread;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * File name used, so make sure we don't free it.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks cname = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * We need to check if the file was removed after the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the lookup and before the fem hooks where added. If
31ceb98b622e1a310256f4c4a1472beb92046db3praks * so, return error. The vnode will still exist as we have
31ceb98b622e1a310256f4c4a1472beb92046db3praks * a hold on it.
073af7d9c45b5d0da4960c39a80af39504480d26praks *
073af7d9c45b5d0da4960c39a80af39504480d26praks * Drop the cache lock before calling port_fop_getdvp().
073af7d9c45b5d0da4960c39a80af39504480d26praks * port_fop_getdvp() may block either in the vfs layer
073af7d9c45b5d0da4960c39a80af39504480d26praks * or some filesystem. Therefore there is potential
073af7d9c45b5d0da4960c39a80af39504480d26praks * for deadlock if cache lock is held and if some other
073af7d9c45b5d0da4960c39a80af39504480d26praks * thread is attempting to deliver file events which would
073af7d9c45b5d0da4960c39a80af39504480d26praks * require getting the cache lock, while it may be holding
073af7d9c45b5d0da4960c39a80af39504480d26praks * the filesystem or vfs layer locks.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
073af7d9c45b5d0da4960c39a80af39504480d26praks mutex_exit(&pfcp->pfc_lock);
073af7d9c45b5d0da4960c39a80af39504480d26praks tvp = NULL;
073af7d9c45b5d0da4960c39a80af39504480d26praks if ((error = port_fop_getdvp(objptr, &tvp, NULL,
073af7d9c45b5d0da4960c39a80af39504480d26praks NULL, NULL, follow)) == 0) {
073af7d9c45b5d0da4960c39a80af39504480d26praks if (tvp != NULL) {
073af7d9c45b5d0da4960c39a80af39504480d26praks tvp = port_resolve_vp(tvp);
073af7d9c45b5d0da4960c39a80af39504480d26praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * This vnode pointer is just used
073af7d9c45b5d0da4960c39a80af39504480d26praks * for comparison, so rele it
073af7d9c45b5d0da4960c39a80af39504480d26praks */
073af7d9c45b5d0da4960c39a80af39504480d26praks VN_RELE(tvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
073af7d9c45b5d0da4960c39a80af39504480d26praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
073af7d9c45b5d0da4960c39a80af39504480d26praks if (error || tvp == NULL || tvp != vp) {
073af7d9c45b5d0da4960c39a80af39504480d26praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * Since we dropped the cache lock, make sure
073af7d9c45b5d0da4960c39a80af39504480d26praks * we are still dealing with the same pfp and this
073af7d9c45b5d0da4960c39a80af39504480d26praks * is the thread which registered it.
073af7d9c45b5d0da4960c39a80af39504480d26praks */
073af7d9c45b5d0da4960c39a80af39504480d26praks mutex_enter(&pfcp->pfc_lock);
073af7d9c45b5d0da4960c39a80af39504480d26praks tpfp = port_cache_lookup_fop(pfcp,
073af7d9c45b5d0da4960c39a80af39504480d26praks curproc->p_pid, object);
073af7d9c45b5d0da4960c39a80af39504480d26praks
073af7d9c45b5d0da4960c39a80af39504480d26praks error = 0;
073af7d9c45b5d0da4960c39a80af39504480d26praks if (tpfp == NULL || tpfp != pfp ||
073af7d9c45b5d0da4960c39a80af39504480d26praks pfp->pfop_vp != vp ||
073af7d9c45b5d0da4960c39a80af39504480d26praks pfp->pfop_dvp != dvp ||
073af7d9c45b5d0da4960c39a80af39504480d26praks pfp->pfop_callrid != curthread) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * Some other event was delivered, the file
073af7d9c45b5d0da4960c39a80af39504480d26praks * watch was removed or reassociated, just
073af7d9c45b5d0da4960c39a80af39504480d26praks * ignore it and leave
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
073af7d9c45b5d0da4960c39a80af39504480d26praks mutex_exit(&pfcp->pfc_lock);
073af7d9c45b5d0da4960c39a80af39504480d26praks goto errout;
073af7d9c45b5d0da4960c39a80af39504480d26praks }
073af7d9c45b5d0da4960c39a80af39504480d26praks
073af7d9c45b5d0da4960c39a80af39504480d26praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * remove the pfp and fem hooks, if pfp still
073af7d9c45b5d0da4960c39a80af39504480d26praks * active and it is not being removed from
073af7d9c45b5d0da4960c39a80af39504480d26praks * the vnode list. This is checked in
073af7d9c45b5d0da4960c39a80af39504480d26praks * port_remove_fop with the vnode lock held.
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * The vnode returned is VN_RELE'ed after dropping
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * the locks.
073af7d9c45b5d0da4960c39a80af39504480d26praks */
6b5ad791879c4fea5b397add82a50aaf0d392b91praks tdvp = tvp = NULL;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (port_remove_fop(pfp, pfcp, 0, NULL, &tvp, &tdvp)) {
073af7d9c45b5d0da4960c39a80af39504480d26praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * The pfp was removed, means no
073af7d9c45b5d0da4960c39a80af39504480d26praks * events where queued. Report the
073af7d9c45b5d0da4960c39a80af39504480d26praks * error now.
073af7d9c45b5d0da4960c39a80af39504480d26praks */
073af7d9c45b5d0da4960c39a80af39504480d26praks error = EINVAL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
073af7d9c45b5d0da4960c39a80af39504480d26praks mutex_exit(&pfcp->pfc_lock);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (tvp != NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(tvp);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (tdvp != NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(tdvp);
073af7d9c45b5d0da4960c39a80af39504480d26praks goto errout;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vp_t *pvp = vp->v_fopdata;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Re-association of the object.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * remove any queued up event.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (port_remove_done_event(pfp->pfop_pev)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags &= ~PORT_FOP_KEV_ONQ;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * set new events to watch.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_events = events;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If not active, mark it active even if it is being
31ceb98b622e1a310256f4c4a1472beb92046db3praks * removed. Then it can send an exception event.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Move it to the head, as the active ones are only
073af7d9c45b5d0da4960c39a80af39504480d26praks * in the beginning. If removing, the pfp will be on
31ceb98b622e1a310256f4c4a1472beb92046db3praks * a temporary list, no need to move it to the front
073af7d9c45b5d0da4960c39a80af39504480d26praks * all the entries will be processed. Some exception
073af7d9c45b5d0da4960c39a80af39504480d26praks * events will be delivered in port_fop_excep();
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!(pfp->pfop_flags & PORT_FOP_ACTIVE)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags |= PORT_FOP_ACTIVE;
073af7d9c45b5d0da4960c39a80af39504480d26praks if (!(pfp->pfop_flags & PORT_FOP_REMOVING)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp = (portfop_vp_t *)vp->v_fopdata;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listremove(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listinsert_head(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
073af7d9c45b5d0da4960c39a80af39504480d26praks pfp->pfop_callrid = curthread;
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvp->pvp_mutex);
073af7d9c45b5d0da4960c39a80af39504480d26praks mutex_exit(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * Compare time stamps and deliver events.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
073af7d9c45b5d0da4960c39a80af39504480d26praks if (vp->v_type != VFIFO) {
073af7d9c45b5d0da4960c39a80af39504480d26praks port_check_timestamp(pfcp, vp, dvp, pfp, objptr, object);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks error = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If we have too many watches on the vnode, discard an
31ceb98b622e1a310256f4c4a1472beb92046db3praks * inactive watch.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_trimpfplist(vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3prakserrout:
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Release the hold acquired due to the lookup operation.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (vp != NULL)
31ceb98b622e1a310256f4c4a1472beb92046db3praks VN_RELE(vp);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (dvp != NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(dvp);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (oldvp != NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(oldvp);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (olddvp != NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(olddvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * copied file name not used, free it.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (cname != NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks kmem_free(cname, clen + 1);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The port_dissociate_fop() function dissociates the file object
31ceb98b622e1a310256f4c4a1472beb92046db3praks * from the event port and removes any events that are already on the queue.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Only the owner of the association is allowed to dissociate the file from
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the port. Returns success (0) if it was found and removed. Otherwise
31ceb98b622e1a310256f4c4a1472beb92046db3praks * ENOENT.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_dissociate_fop(port_t *pp, uintptr_t object)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_cache_t *pfcp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *pfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_source_t *pse;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int active = 0;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks vnode_t *tvp = NULL, *tdvp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pse = port_getsrc(pp, PORT_SOURCE_FILE);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * if this source is not associated or if there is no
31ceb98b622e1a310256f4c4a1472beb92046db3praks * cache, nothing to do just return.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pse == NULL ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks (pfcp = (portfop_cache_t *)pse->portsrc_data) == NULL)
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (EINVAL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Check if this object is on the cache. Only the owner pid
31ceb98b622e1a310256f4c4a1472beb92046db3praks * is allowed to dissociate.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp = port_cache_lookup_fop(pfcp, curproc->p_pid, object);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (ENOENT);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If this was the last association, it will release
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the hold on the vnode. There is a race condition where
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the the pfp is being removed due to an exception event
31ceb98b622e1a310256f4c4a1472beb92046db3praks * in port_fop_sendevent()->port_fop_excep() and port_remove_fop().
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Since port source cache lock is held, port_fop_excep() cannot
073af7d9c45b5d0da4960c39a80af39504480d26praks * complete. The vnode itself will not disappear as long its pfps
31ceb98b622e1a310256f4c4a1472beb92046db3praks * have a reference.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
6b5ad791879c4fea5b397add82a50aaf0d392b91praks (void) port_remove_fop(pfp, pfcp, 1, &active, &tvp, &tdvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pfcp->pfc_lock);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (tvp != NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(tvp);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (tdvp != NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(tdvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (active ? 0 : ENOENT);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * port_close() calls this function to request the PORT_SOURCE_FILE source
31ceb98b622e1a310256f4c4a1472beb92046db3praks * to remove/free all resources allocated and associated with the port.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/* ARGSUSED */
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_close_fop(void *arg, int port, pid_t pid, int lastclose)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_t *pp = arg;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_cache_t *pfcp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t **hashtbl;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *pfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *pfpnext;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks int index, i;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_source_t *pse;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks vnode_t *tdvp = NULL;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks vnode_t *vpl[PORTFOP_NVP];
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pse = port_getsrc(pp, PORT_SOURCE_FILE);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * No source or no cache, nothing to do.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pse == NULL ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks (pfcp = (portfop_cache_t *)pse->portsrc_data) == NULL)
31ceb98b622e1a310256f4c4a1472beb92046db3praks return;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Scan the cache and free all allocated portfop_t and port_kevent_t
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * structures of this pid. Note, no new association for this pid will
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * be possible as the port is being closed.
6b5ad791879c4fea5b397add82a50aaf0d392b91praks *
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * The common case is that the port is not shared and all the entries
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * are of this pid and have to be freed. Since VN_RELE has to be
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * called outside the lock, we do it in batches.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks hashtbl = (portfop_t **)pfcp->pfc_hash;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks index = i = 0;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks bzero(vpl, sizeof (vpl));
6b5ad791879c4fea5b397add82a50aaf0d392b91praks mutex_enter(&pfcp->pfc_lock);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks while (index < PORTFOP_HASHSIZE) {
6b5ad791879c4fea5b397add82a50aaf0d392b91praks pfp = hashtbl[index];
6b5ad791879c4fea5b397add82a50aaf0d392b91praks while (pfp != NULL && i < (PORTFOP_NVP - 1)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfpnext = pfp->pfop_hashnext;
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pid == pfp->pfop_pid) {
6b5ad791879c4fea5b397add82a50aaf0d392b91praks (void) port_remove_fop(pfp, pfcp, 1, NULL,
6b5ad791879c4fea5b397add82a50aaf0d392b91praks &vpl[i], &tdvp);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (vpl[i] != NULL) {
6b5ad791879c4fea5b397add82a50aaf0d392b91praks i++;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks }
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (tdvp != NULL) {
6b5ad791879c4fea5b397add82a50aaf0d392b91praks vpl[i++] = tdvp;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks tdvp = NULL;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
6b5ad791879c4fea5b397add82a50aaf0d392b91praks pfp = pfpnext;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks }
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (pfp == NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks index++;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks /*
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * Now call VN_RELE if we have collected enough vnodes or
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * we have reached the end of the hash table.
6b5ad791879c4fea5b397add82a50aaf0d392b91praks */
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (i >= (PORTFOP_NVP - 1) ||
6b5ad791879c4fea5b397add82a50aaf0d392b91praks (i > 0 && index == PORTFOP_HASHSIZE)) {
6b5ad791879c4fea5b397add82a50aaf0d392b91praks mutex_exit(&pfcp->pfc_lock);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks while (i > 0) {
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(vpl[--i]);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks vpl[i] = NULL;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks }
6b5ad791879c4fea5b397add82a50aaf0d392b91praks mutex_enter(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Due to a race between port_close_fop() and port_fop()
31ceb98b622e1a310256f4c4a1472beb92046db3praks * trying to remove the pfp's from the port's cache, it is
31ceb98b622e1a310256f4c4a1472beb92046db3praks * possible that some pfp's are still in the process of being
31ceb98b622e1a310256f4c4a1472beb92046db3praks * freed so we wait.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks while (lastclose && pfcp->pfc_objcount) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks (void) cv_wait_sig(&pfcp->pfc_lclosecv, &pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * last close, free the cache.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (lastclose) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks ASSERT(pfcp->pfc_objcount == 0);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pse->portsrc_data = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks kmem_free(pfcp, sizeof (portfop_cache_t));
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Given the list of associations(watches), it will send exception events,
31ceb98b622e1a310256f4c4a1472beb92046db3praks * if still active, and discard them. The exception events are handled
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * separately because, the pfp needs to be removed from the port cache and
31ceb98b622e1a310256f4c4a1472beb92046db3praks * freed as the vnode's identity is changing or being removed. To remove
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the pfp from the port's cache, we need to hold the cache lock (pfc_lock).
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The lock order is pfc_lock -> pvp_mutex(vnode's) mutex and that is why
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the cache's lock cannot be acquired in port_fop_sendevent().
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic void
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_excep(list_t *tlist, int op)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *pfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_cache_t *pfcp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_t *pp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_kevent_t *pkevp;
6b5ad791879c4fea5b397add82a50aaf0d392b91praks vnode_t *tdvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int error = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks while (pfp = (portfop_t *)list_head(tlist)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks int removed = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * remove from the temp list. Since PORT_FOP_REMOVING is
31ceb98b622e1a310256f4c4a1472beb92046db3praks * set, no other thread should attempt to perform a
31ceb98b622e1a310256f4c4a1472beb92046db3praks * list_remove on this pfp.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_remove(tlist, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfcp = pfp->pfop_pcache;
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pfcp->pfc_lock);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Remove the event from the port queue if it was queued up.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * No need to clear the PORT_FOP_KEV_ONQ flag as this pfp is
31ceb98b622e1a310256f4c4a1472beb92046db3praks * no longer on the vnode's list.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((pfp->pfop_flags & PORT_FOP_KEV_ONQ)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks removed = port_remove_done_event(pfp->pfop_pev);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If still active or the event was queued up and
31ceb98b622e1a310256f4c4a1472beb92046db3praks * had not been collected yet, send an EXCEPTION event.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_flags & (PORT_FOP_ACTIVE) || removed) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pp = pfp->pfop_pp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Allocate a port_kevent_t non cached to send this
31ceb98b622e1a310256f4c4a1472beb92046db3praks * event since we will be de-registering.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The port_kevent_t cannot be pointing back to the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * pfp anymore.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags &= ~PORT_FOP_ACTIVE;
31ceb98b622e1a310256f4c4a1472beb92046db3praks error = port_alloc_event_local(pp, PORT_SOURCE_FILE,
31ceb98b622e1a310256f4c4a1472beb92046db3praks PORT_ALLOC_DEFAULT, &pkevp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!error) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_callback = port_fop_callback;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_arg = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_object =
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_pev->portkev_object;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_user =
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_pev->portkev_user;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Copy the pid of the watching process.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_pid =
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_pev->portkev_pid;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_events = op;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_send_event(pkevp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * At this point the pfp has been removed from the vnode's
31ceb98b622e1a310256f4c4a1472beb92046db3praks * list its cached port_kevent_t is not on the done queue.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Remove the pfp and free it from the cache.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
6b5ad791879c4fea5b397add82a50aaf0d392b91praks tdvp = pfp->pfop_dvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_pcache_remove_fop(pfcp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pfcp->pfc_lock);
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (tdvp != NULL)
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(tdvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Send the file events to all of the processes watching this
31ceb98b622e1a310256f4c4a1472beb92046db3praks * vnode. In case of hard links, the directory vnode pointer and
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the file name are compared. If the names match, then the specified
31ceb98b622e1a310256f4c4a1472beb92046db3praks * event is sent or else, the FILE_ATTRIB event is sent, This is the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * documented behavior.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksvoid
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_sendevent(vnode_t *vp, int events, vnode_t *dvp, char *cname)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_kevent_t *pkevp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_t *pfp, *npfp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vp_t *pvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_t tmplist;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int removeall = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvp = (portfop_vp_t *)vp->v_fopdata;
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Check if the list is empty.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * All entries have been removed by some other thread.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The vnode may be still active and we got called,
31ceb98b622e1a310256f4c4a1472beb92046db3praks * but some other thread is in the process of removing the hooks.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!list_head(&pvp->pvp_pfoplist)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((events & (FILE_EXCEPTION))) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If it is an event for which we are going to remove
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the watches so just move it a temporary list and
31ceb98b622e1a310256f4c4a1472beb92046db3praks * release this vnode.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_create(&tmplist, sizeof (portfop_t),
31ceb98b622e1a310256f4c4a1472beb92046db3praks offsetof(portfop_t, pfop_node));
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If it is an UNMOUNT, MOUNTEDOVER or no file name has been
31ceb98b622e1a310256f4c4a1472beb92046db3praks * passed for an exception event, all associations need to be
31ceb98b622e1a310256f4c4a1472beb92046db3praks * removed.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (dvp == NULL || cname == NULL) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks removeall = 1;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!removeall) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
073af7d9c45b5d0da4960c39a80af39504480d26praks * All the active ones are in the beginning of the list.
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill * Note that we process this list in reverse order to assure
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill * that events are delivered in the order that they were
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill * associated.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill for (pfp = (portfop_t *)list_tail(&pvp->pvp_pfoplist);
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill pfp && !(pfp->pfop_flags & PORT_FOP_ACTIVE); pfp = npfp) {
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill npfp = list_prev(&pvp->pvp_pfoplist, pfp);
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill }
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill for (; pfp != NULL; pfp = npfp) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks int levents = events;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill npfp = list_prev(&pvp->pvp_pfoplist, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Hard links case - If the file is being
31ceb98b622e1a310256f4c4a1472beb92046db3praks * removed/renamed, and the name matches
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the watched file, then it is an EXCEPTION
31ceb98b622e1a310256f4c4a1472beb92046db3praks * event or else it will be just a FILE_ATTRIB.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((events & (FILE_EXCEPTION))) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks ASSERT(dvp != NULL && cname != NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_dvp == NULL ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks (pfp->pfop_dvp == dvp &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (strcmp(cname, pfp->pfop_cname) == 0))) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * It is an exception event, move it
31ceb98b622e1a310256f4c4a1472beb92046db3praks * to temp list and process it later.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Note we don't set the pfp->pfop_vp
31ceb98b622e1a310256f4c4a1472beb92046db3praks * to NULL even thought it has been
31ceb98b622e1a310256f4c4a1472beb92046db3praks * removed from the vnode's list. This
31ceb98b622e1a310256f4c4a1472beb92046db3praks * pointer is referenced in
31ceb98b622e1a310256f4c4a1472beb92046db3praks * port_remove_fop(). The vnode it
073af7d9c45b5d0da4960c39a80af39504480d26praks * self cannot disappear until this
31ceb98b622e1a310256f4c4a1472beb92046db3praks * pfp gets removed and freed.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listremove(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_insert_tail(&tmplist, (void *)pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags |= PORT_FOP_REMOVING;
31ceb98b622e1a310256f4c4a1472beb92046db3praks continue;
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks levents = FILE_ATTRIB;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (pfp->pfop_events & levents) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * deactivate and move it to the tail.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If the pfp was active, it cannot be
31ceb98b622e1a310256f4c4a1472beb92046db3praks * on the port's done queue.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags &= ~PORT_FOP_ACTIVE;
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listremove(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listinsert_tail(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp = pfp->pfop_pev;
31ceb98b622e1a310256f4c4a1472beb92046db3praks pkevp->portkev_events |=
31ceb98b622e1a310256f4c4a1472beb92046db3praks (levents & pfp->pfop_events);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_send_event(pkevp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags |= PORT_FOP_KEV_ONQ;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((events & (FILE_EXCEPTION))) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (!removeall) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Check the inactive associations and remove them if
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the file name matches.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks for (; pfp; pfp = npfp) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks npfp = list_next(&pvp->pvp_pfoplist, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (dvp == NULL || cname == NULL ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_dvp == NULL ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks (pfp->pfop_dvp == dvp &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks (strcmp(cname, pfp->pfop_cname) == 0))) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listremove(pvp, pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_insert_tail(&tmplist, (void *)pfp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags |= PORT_FOP_REMOVING;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Can be optimized to avoid two pass over this list
31ceb98b622e1a310256f4c4a1472beb92046db3praks * by having a flag in the vnode's portfop_vp_t
31ceb98b622e1a310256f4c4a1472beb92046db3praks * structure to indicate that it is going away,
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Or keep the list short by reusing inactive watches.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_listmove(pvp, &tmplist);
31ceb98b622e1a310256f4c4a1472beb92046db3praks for (pfp = (portfop_t *)list_head(&tmplist);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp; pfp = list_next(&tmplist, pfp)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pfp->pfop_flags |= PORT_FOP_REMOVING;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Uninstall the fem hooks if there are no more associations.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * This will release the pvp mutex.
31ceb98b622e1a310256f4c4a1472beb92046db3praks *
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Even thought all entries may have been removed,
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the vnode itself cannot disappear as there will be a
31ceb98b622e1a310256f4c4a1472beb92046db3praks * hold on it due to this call to port_fop_sendevent. This is
31ceb98b622e1a310256f4c4a1472beb92046db3praks * important to syncronize with a port_dissociate_fop() call
31ceb98b622e1a310256f4c4a1472beb92046db3praks * that may be attempting to remove an object from the vnode's.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
6b5ad791879c4fea5b397add82a50aaf0d392b91praks if (port_fop_femuninstall(vp))
6b5ad791879c4fea5b397add82a50aaf0d392b91praks VN_RELE(vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Send exception events and discard the watch entries.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_excep(&tmplist, events);
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_destroy(&tmplist);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks } else {
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(&pvp->pvp_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * trim the list.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_trimpfplist(vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks * Given the file operation, map it to the event types and send.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksvoid
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop(vnode_t *vp, int op, int retval)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int event = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * deliver events only if the operation was successful.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (retval)
31ceb98b622e1a310256f4c4a1472beb92046db3praks return;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * These events occurring on the watched file.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (op & FOP_MODIFIED_MASK) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks event = FILE_MODIFIED;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (op & FOP_ACCESS_MASK) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks event |= FILE_ACCESS;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (op & FOP_ATTRIB_MASK) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks event |= FILE_ATTRIB;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill if (op & FOP_TRUNC_MASK) {
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill event |= FILE_TRUNC;
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill }
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (event) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_sendevent(vp, event, NULL, NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
84c5ce693a3660dc01d938cb3329b81631896a32praksstatic int port_forceunmount(vfs_t *vfsp)
84c5ce693a3660dc01d938cb3329b81631896a32praks{
84c5ce693a3660dc01d938cb3329b81631896a32praks char *fsname = vfssw[vfsp->vfs_fstype].vsw_name;
84c5ce693a3660dc01d938cb3329b81631896a32praks
84c5ce693a3660dc01d938cb3329b81631896a32praks if (fsname == NULL) {
84c5ce693a3660dc01d938cb3329b81631896a32praks return (0);
84c5ce693a3660dc01d938cb3329b81631896a32praks }
84c5ce693a3660dc01d938cb3329b81631896a32praks
84c5ce693a3660dc01d938cb3329b81631896a32praks if (strcmp(fsname, MNTTYPE_NFS) == 0) {
84c5ce693a3660dc01d938cb3329b81631896a32praks return (1);
84c5ce693a3660dc01d938cb3329b81631896a32praks }
84c5ce693a3660dc01d938cb3329b81631896a32praks
84c5ce693a3660dc01d938cb3329b81631896a32praks if (strcmp(fsname, MNTTYPE_NFS3) == 0) {
84c5ce693a3660dc01d938cb3329b81631896a32praks return (1);
84c5ce693a3660dc01d938cb3329b81631896a32praks }
84c5ce693a3660dc01d938cb3329b81631896a32praks
84c5ce693a3660dc01d938cb3329b81631896a32praks if (strcmp(fsname, MNTTYPE_NFS4) == 0) {
84c5ce693a3660dc01d938cb3329b81631896a32praks return (1);
84c5ce693a3660dc01d938cb3329b81631896a32praks }
84c5ce693a3660dc01d938cb3329b81631896a32praks return (0);
84c5ce693a3660dc01d938cb3329b81631896a32praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * ----- the unmount filesystem op(fsem) hook.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_unmount(fsemarg_t *vf, int flag, cred_t *cr)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks vfs_t *vfsp = (vfs_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks kmutex_t *mtx;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vfs_t *pvfsp, **ppvfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks portfop_vp_t *pvp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int error;
84c5ce693a3660dc01d938cb3329b81631896a32praks int fmfs;
84c5ce693a3660dc01d938cb3329b81631896a32praks
84c5ce693a3660dc01d938cb3329b81631896a32praks fmfs = port_forceunmount(vfsp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks mtx = &(portvfs_hash[PORTFOP_PVFSHASH(vfsp)].pvfshash_mutex);
31ceb98b622e1a310256f4c4a1472beb92046db3praks ppvfsp = &(portvfs_hash[PORTFOP_PVFSHASH(vfsp)].pvfshash_pvfsp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsp = NULL;
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(mtx);
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
6b5ad791879c4fea5b397add82a50aaf0d392b91praks * since this fsem hook is triggered, the vfsp has to be on
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the hash list.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks for (pvfsp = *ppvfsp; pvfsp->pvfs != vfsp; pvfsp = pvfsp->pvfs_next)
31ceb98b622e1a310256f4c4a1472beb92046db3praks ;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
84c5ce693a3660dc01d938cb3329b81631896a32praks /*
84c5ce693a3660dc01d938cb3329b81631896a32praks * For some of the filesystems, allow unmounts to proceed only if
84c5ce693a3660dc01d938cb3329b81631896a32praks * there are no files being watched or it is a forced unmount.
84c5ce693a3660dc01d938cb3329b81631896a32praks */
84c5ce693a3660dc01d938cb3329b81631896a32praks if (fmfs && !(flag & MS_FORCE) &&
84c5ce693a3660dc01d938cb3329b81631896a32praks !list_is_empty(&pvfsp->pvfs_pvplist)) {
84c5ce693a3660dc01d938cb3329b81631896a32praks mutex_exit(mtx);
84c5ce693a3660dc01d938cb3329b81631896a32praks return (EBUSY);
84c5ce693a3660dc01d938cb3329b81631896a32praks }
84c5ce693a3660dc01d938cb3329b81631896a32praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Indicate that the unmount is in process. Don't remove it yet.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The underlying filesystem unmount routine sets the VFS_UNMOUNTED
31ceb98b622e1a310256f4c4a1472beb92046db3praks * flag on the vfs_t structure. But we call the filesystem unmount
31ceb98b622e1a310256f4c4a1472beb92046db3praks * routine after removing all the file watches for this filesystem,
31ceb98b622e1a310256f4c4a1472beb92046db3praks * otherwise the unmount will fail due to active vnodes.
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Meanwhile setting pvfsp->unmount = 1 will prevent any thread
31ceb98b622e1a310256f4c4a1472beb92046db3praks * attempting to add a file watch.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsp->pvfs_unmount = 1;
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(mtx);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * uninstall the fsem hooks.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks (void) fsem_uninstall(vfsp, (fsem_t *)pvfsp->pvfs_fsemp, vfsp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks while (pvp = list_head(&pvfsp->pvfs_pvplist)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks list_remove(&pvfsp->pvfs_pvplist, pvp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * This should send an UNMOUNTED event to all the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * watched vnode of this filesystem and uninstall
31ceb98b622e1a310256f4c4a1472beb92046db3praks * the fem hooks. We release the hold on the vnode here
31ceb98b622e1a310256f4c4a1472beb92046db3praks * because port_fop_femuninstall() will not do it if
31ceb98b622e1a310256f4c4a1472beb92046db3praks * unmount is in process.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_sendevent(pvp->pvp_vp, UNMOUNTED, NULL, NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks VN_RELE(pvp->pvp_vp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks error = vfsnext_unmount(vf, flag, cr);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * we free the pvfsp after the unmount has been completed.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_enter(mtx);
31ceb98b622e1a310256f4c4a1472beb92046db3praks for (; *ppvfsp && (*ppvfsp)->pvfs != vfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks ppvfsp = &(*ppvfsp)->pvfs_next)
31ceb98b622e1a310256f4c4a1472beb92046db3praks ;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * remove and free it.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks ASSERT(list_head(&pvfsp->pvfs_pvplist) == NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (*ppvfsp) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks pvfsp = *ppvfsp;
31ceb98b622e1a310256f4c4a1472beb92046db3praks *ppvfsp = pvfsp->pvfs_next;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks mutex_exit(mtx);
31ceb98b622e1a310256f4c4a1472beb92046db3praks kmem_free(pvfsp, sizeof (portfop_vfs_t));
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (error);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * ------------------------------file op hooks--------------------------
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The O_TRUNC operation is caught with the VOP_SETATTR(AT_SIZE) call.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwport_fop_open(femarg_t *vf, int mode, cred_t *cr, caller_context_t *ct)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_open(vf, mode, cr, ct);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_OPEN, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_write(femarg_t *vf, struct uio *uiop, int ioflag, struct cred *cr,
31ceb98b622e1a310256f4c4a1472beb92046db3praks caller_context_t *ct)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks retval = vnext_write(vf, uiop, ioflag, cr, ct);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_WRITE, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_map(femarg_t *vf, offset_t off, struct as *as, caddr_t *addrp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw size_t len, uchar_t prot, uchar_t maxport, uint_t flags, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_map(vf, off, as, addrp, len, prot, maxport,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw flags, cr, ct);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_MAP, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksstatic int
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_read(femarg_t *vf, struct uio *uiop, int ioflag, struct cred *cr,
31ceb98b622e1a310256f4c4a1472beb92046db3praks caller_context_t *ct)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks retval = vnext_read(vf, uiop, ioflag, cr, ct);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_READ, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * AT_SIZE - is for the open(O_TRUNC) case.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_setattr(femarg_t *vf, vattr_t *vap, int flags, cred_t *cr,
31ceb98b622e1a310256f4c4a1472beb92046db3praks caller_context_t *ct)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks int events = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks retval = vnext_setattr(vf, vap, flags, cr, ct);
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill if (vap->va_mask & AT_SIZE) {
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill events |= FOP_FILE_TRUNC;
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill }
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (vap->va_mask & (AT_SIZE|AT_MTIME)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks events |= FOP_FILE_SETATTR_MTIME;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks if (vap->va_mask & AT_ATIME) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks events |= FOP_FILE_SETATTR_ATIME;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks events |= FOP_FILE_SETATTR_CTIME;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, events, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_create(femarg_t *vf, char *name, vattr_t *vap, vcexcl_t excl,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int mode, vnode_t **vpp, cred_t *cr, int flag,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, vsecattr_t *vsecp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval, got = 1;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vattr_t vatt, vatt1;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * If the file already exists, then there will be no change
31ceb98b622e1a310256f4c4a1472beb92046db3praks * to the directory. Therefore, we need to compare the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * modification time of the directory to determine if the
31ceb98b622e1a310256f4c4a1472beb92046db3praks * file was actually created.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks vatt.va_mask = AT_ATIME|AT_MTIME|AT_CTIME;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (VOP_GETATTR(vp, &vatt, 0, CRED(), ct)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks got = 0;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_create(vf, name, vap, excl, mode, vpp, cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw flag, ct, vsecp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks
df2381bfa5cf7dd654bcf30b2f5af53f34f3043apraks vatt1.va_mask = AT_ATIME|AT_MTIME|AT_CTIME;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (got && !VOP_GETATTR(vp, &vatt1, 0, CRED(), ct)) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks if ((vatt1.va_mtime.tv_sec > vatt.va_mtime.tv_sec ||
31ceb98b622e1a310256f4c4a1472beb92046db3praks (vatt1.va_mtime.tv_sec = vatt.va_mtime.tv_sec &&
31ceb98b622e1a310256f4c4a1472beb92046db3praks vatt1.va_mtime.tv_nsec > vatt.va_mtime.tv_nsec))) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks /*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * File was created.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_CREATE, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwport_fop_remove(femarg_t *vf, char *nm, cred_t *cr, caller_context_t *ct,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int flags)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_remove(vf, nm, cr, ct, flags);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_REMOVE, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwport_fop_link(femarg_t *vf, vnode_t *svp, char *tnm, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int flags)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_link(vf, svp, tnm, cr, ct, flags);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_LINK, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * Rename operation is allowed only when from and to directories are
31ceb98b622e1a310256f4c4a1472beb92046db3praks * on the same filesystem. This is checked in vn_rename().
31ceb98b622e1a310256f4c4a1472beb92046db3praks * The target directory is notified thru a VNEVENT by the filesystem
31ceb98b622e1a310256f4c4a1472beb92046db3praks * if the source dir != target dir.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwport_fop_rename(femarg_t *vf, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int flags)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_rename(vf, snm, tdvp, tnm, cr, ct, flags);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_RENAMESRC, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_mkdir(femarg_t *vf, char *dirname, vattr_t *vap, vnode_t **vpp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_mkdir(vf, dirname, vap, vpp, cr, ct, flags, vsecp);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_MKDIR, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwport_fop_rmdir(femarg_t *vf, char *nm, vnode_t *cdir, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int flags)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_rmdir(vf, nm, cdir, cr, ct, flags);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_RMDIR, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwport_fop_readdir(femarg_t *vf, uio_t *uiop, cred_t *cr, int *eofp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int flags)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_readdir(vf, uiop, cr, eofp, ct, flags);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_READDIR, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
31ceb98b622e1a310256f4c4a1472beb92046db3praksport_fop_symlink(femarg_t *vf, char *linkname, vattr_t *vap, char *target,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cred_t *cr, caller_context_t *ct, int flags)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_symlink(vf, linkname, vap, target, cr, ct, flags);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_SYMLINK, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * acl, facl call this.
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwport_fop_setsecattr(femarg_t *vf, vsecattr_t *vsap, int flags, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks int retval;
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = vnext_setsecattr(vf, vsap, flags, cr, ct);
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop(vp, FOP_FILE_SETSECATTR, retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks return (retval);
31ceb98b622e1a310256f4c4a1472beb92046db3praks}
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks/*
31ceb98b622e1a310256f4c4a1472beb92046db3praks * these are events on the watched file/directory
31ceb98b622e1a310256f4c4a1472beb92046db3praks */
31ceb98b622e1a310256f4c4a1472beb92046db3praksint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwport_fop_vnevent(femarg_t *vf, vnevent_t vnevent, vnode_t *dvp, char *name,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct)
31ceb98b622e1a310256f4c4a1472beb92046db3praks{
31ceb98b622e1a310256f4c4a1472beb92046db3praks vnode_t *vp = (vnode_t *)vf->fa_fnode->fn_available;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks switch (vnevent) {
31ceb98b622e1a310256f4c4a1472beb92046db3praks case VE_RENAME_SRC:
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_sendevent(vp, FILE_RENAME_FROM, dvp, name);
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks case VE_RENAME_DEST:
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_sendevent(vp, FILE_RENAME_TO, dvp, name);
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks case VE_REMOVE:
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_sendevent(vp, FILE_DELETE, dvp, name);
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks case VE_RMDIR:
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_sendevent(vp, FILE_DELETE, dvp, name);
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks case VE_CREATE:
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill port_fop_sendevent(vp,
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill FILE_MODIFIED|FILE_ATTRIB|FILE_TRUNC, NULL, NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks case VE_LINK:
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_sendevent(vp, FILE_ATTRIB, NULL, NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks case VE_RENAME_DEST_DIR:
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_sendevent(vp, FILE_MODIFIED|FILE_ATTRIB,
31ceb98b622e1a310256f4c4a1472beb92046db3praks NULL, NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks
31ceb98b622e1a310256f4c4a1472beb92046db3praks case VE_MOUNTEDOVER:
31ceb98b622e1a310256f4c4a1472beb92046db3praks port_fop_sendevent(vp, MOUNTEDOVER, NULL, NULL);
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill case VE_TRUNCATE:
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill port_fop_sendevent(vp, FILE_TRUNC, NULL, NULL);
72102e7461c97dc268d21d9dd8f02da45f174acdBryan Cantrill break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks default:
31ceb98b622e1a310256f4c4a1472beb92046db3praks break;
31ceb98b622e1a310256f4c4a1472beb92046db3praks }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (vnext_vnevent(vf, vnevent, dvp, name, ct));
31ceb98b622e1a310256f4c4a1472beb92046db3praks}