xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_fem.c (revision 6600:4e63bcd27ae9)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
226139Sjb150015  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
275331Samw 
285331Samw #include <smbsrv/smb_incl.h>
29*6600Sas200622 #include <smbsrv/smb_fsops.h>
305331Samw #include <sys/sdt.h>
31*6600Sas200622 #include <sys/fcntl.h>
325331Samw #include <sys/vfs.h>
335331Samw #include <sys/vfs_opreg.h>
345331Samw #include <sys/vnode.h>
355331Samw #include <sys/fem.h>
365331Samw 
37*6600Sas200622 extern caller_context_t	smb_ct;
38*6600Sas200622 
39*6600Sas200622 static boolean_t	smb_fem_initialized = B_FALSE;
40*6600Sas200622 static fem_t		*smb_fcn_ops = NULL;
41*6600Sas200622 static fem_t		*smb_oplock_ops = NULL;
42*6600Sas200622 
43*6600Sas200622 /*
44*6600Sas200622  * Declarations for FCN (file change notification) FEM monitors
45*6600Sas200622  */
46*6600Sas200622 
47*6600Sas200622 void smb_fem_fcn_install(smb_node_t *);
48*6600Sas200622 void smb_fem_fcn_uninstall(smb_node_t *);
49*6600Sas200622 
50*6600Sas200622 static int smb_fem_fcn_create(femarg_t *, char *, vattr_t *, vcexcl_t, int,
515331Samw     vnode_t **, cred_t *, int, caller_context_t *, vsecattr_t *);
52*6600Sas200622 static int smb_fem_fcn_remove(femarg_t *, char *, cred_t *,
535331Samw     caller_context_t *, int);
54*6600Sas200622 static int smb_fem_fcn_rename(femarg_t *, char *, vnode_t *, char *,
555331Samw     cred_t *, caller_context_t *, int);
56*6600Sas200622 static int smb_fem_fcn_mkdir(femarg_t *, char *, vattr_t *, vnode_t **,
575331Samw     cred_t *, caller_context_t *, int, vsecattr_t *);
58*6600Sas200622 static int smb_fem_fcn_rmdir(femarg_t *, char *, vnode_t *, cred_t *,
595331Samw     caller_context_t *, int);
60*6600Sas200622 static int smb_fem_fcn_link(femarg_t *, vnode_t *, char *, cred_t *,
615331Samw     caller_context_t *, int);
62*6600Sas200622 static int smb_fem_fcn_symlink(femarg_t *, char *, vattr_t *,
635331Samw     char *, cred_t *, caller_context_t *, int);
645331Samw 
655331Samw static const fs_operation_def_t smb_fcn_tmpl[] = {
665331Samw 	VOPNAME_CREATE, { .femop_create = smb_fem_fcn_create },
675331Samw 	VOPNAME_REMOVE, {.femop_remove = smb_fem_fcn_remove},
685331Samw 	VOPNAME_RENAME, {.femop_rename = smb_fem_fcn_rename},
695331Samw 	VOPNAME_MKDIR, {.femop_mkdir = smb_fem_fcn_mkdir},
705331Samw 	VOPNAME_RMDIR, {.femop_rmdir = smb_fem_fcn_rmdir},
715331Samw 	VOPNAME_LINK, {.femop_link = smb_fem_fcn_link},
725331Samw 	VOPNAME_SYMLINK, {.femop_symlink = smb_fem_fcn_symlink},
735331Samw 	NULL, NULL
745331Samw };
755331Samw 
76*6600Sas200622 /*
77*6600Sas200622  * Declarations for oplock FEM monitors
78*6600Sas200622  */
79*6600Sas200622 
80*6600Sas200622 int smb_fem_oplock_install(smb_node_t *);
81*6600Sas200622 void smb_fem_oplock_uninstall(smb_node_t *);
82*6600Sas200622 
83*6600Sas200622 static int smb_fem_oplock_open(femarg_t *, int, cred_t *,
84*6600Sas200622     struct caller_context *);
85*6600Sas200622 static int smb_fem_oplock_read(femarg_t *, uio_t *, int, cred_t *,
86*6600Sas200622     struct caller_context *);
87*6600Sas200622 static int smb_fem_oplock_write(femarg_t *, uio_t *, int, cred_t *,
88*6600Sas200622     struct caller_context *);
89*6600Sas200622 static int smb_fem_oplock_setattr(femarg_t *, vattr_t *, int, cred_t *,
90*6600Sas200622     caller_context_t *);
91*6600Sas200622 static int smb_fem_oplock_rwlock(femarg_t *, int, caller_context_t *);
92*6600Sas200622 static int smb_fem_oplock_space(femarg_t *, int, flock64_t *, int,
93*6600Sas200622     offset_t, cred_t *, caller_context_t *);
94*6600Sas200622 static int smb_fem_oplock_setsecattr(femarg_t *, vsecattr_t *, int, cred_t *,
95*6600Sas200622     caller_context_t *);
96*6600Sas200622 static int smb_fem_oplock_vnevent(femarg_t *, vnevent_t, vnode_t *, char *,
97*6600Sas200622     caller_context_t *);
98*6600Sas200622 
99*6600Sas200622 static const fs_operation_def_t smb_oplock_tmpl[] = {
100*6600Sas200622 	VOPNAME_OPEN,	{ .femop_open = smb_fem_oplock_open },
101*6600Sas200622 	VOPNAME_READ,	{ .femop_read = smb_fem_oplock_read },
102*6600Sas200622 	VOPNAME_WRITE,	{ .femop_write = smb_fem_oplock_write },
103*6600Sas200622 	VOPNAME_SETATTR, { .femop_setattr = smb_fem_oplock_setattr },
104*6600Sas200622 	VOPNAME_RWLOCK, { .femop_rwlock = smb_fem_oplock_rwlock },
105*6600Sas200622 	VOPNAME_SPACE,	{ .femop_space = smb_fem_oplock_space },
106*6600Sas200622 	VOPNAME_SETSECATTR, { .femop_setsecattr = smb_fem_oplock_setsecattr },
107*6600Sas200622 	VOPNAME_VNEVENT, { .femop_vnevent = smb_fem_oplock_vnevent },
108*6600Sas200622 	NULL, NULL
109*6600Sas200622 };
110*6600Sas200622 
1116139Sjb150015 /*
1126139Sjb150015  * smb_fem_init
1136139Sjb150015  *
1146139Sjb150015  * This function is not multi-thread safe. The caller must make sure only one
1156139Sjb150015  * thread makes the call.
1166139Sjb150015  */
1175331Samw int
1186139Sjb150015 smb_fem_init(void)
1195331Samw {
1206139Sjb150015 	int	rc = 0;
1216139Sjb150015 
1226139Sjb150015 	if (smb_fem_initialized)
1236139Sjb150015 		return (0);
1246139Sjb150015 
1256139Sjb150015 	rc = fem_create("smb_fcn_ops", smb_fcn_tmpl, &smb_fcn_ops);
1266139Sjb150015 	if (rc)
1276139Sjb150015 		return (rc);
1286139Sjb150015 
129*6600Sas200622 	rc = fem_create("smb_oplock_ops", smb_oplock_tmpl,
130*6600Sas200622 	    &smb_oplock_ops);
131*6600Sas200622 
132*6600Sas200622 	if (rc) {
133*6600Sas200622 		fem_free(smb_fcn_ops);
134*6600Sas200622 		smb_fcn_ops = NULL;
135*6600Sas200622 		return (rc);
136*6600Sas200622 	}
137*6600Sas200622 
1386139Sjb150015 	smb_fem_initialized = B_TRUE;
1396139Sjb150015 
1406139Sjb150015 	return (0);
1415331Samw }
1425331Samw 
1436139Sjb150015 /*
1446139Sjb150015  * smb_fem_fini
1456139Sjb150015  *
1466139Sjb150015  * This function is not multi-thread safe. The caller must make sure only one
1476139Sjb150015  * thread makes the call.
1486139Sjb150015  */
1495331Samw void
1506139Sjb150015 smb_fem_fini(void)
1515331Samw {
1526139Sjb150015 	if (!smb_fem_initialized)
1536139Sjb150015 		return;
1546139Sjb150015 
1556139Sjb150015 	fem_free(smb_fcn_ops);
156*6600Sas200622 	fem_free(smb_oplock_ops);
1576139Sjb150015 	smb_fcn_ops = NULL;
158*6600Sas200622 	smb_oplock_ops = NULL;
1596139Sjb150015 	smb_fem_initialized = B_FALSE;
1605331Samw }
1615331Samw 
1625331Samw void
1635331Samw smb_fem_fcn_install(smb_node_t *node)
1645331Samw {
165*6600Sas200622 	(void) fem_install(node->vp, smb_fcn_ops, (void *)node, OPARGUNIQ,
166*6600Sas200622 	    (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release);
1675331Samw }
1685331Samw 
1695331Samw void
1705331Samw smb_fem_fcn_uninstall(smb_node_t *node)
1715331Samw {
1725331Samw 	(void) fem_uninstall(node->vp, smb_fcn_ops, (void *)node);
1735331Samw }
1745331Samw 
175*6600Sas200622 int
176*6600Sas200622 smb_fem_oplock_install(smb_node_t *node)
177*6600Sas200622 {
178*6600Sas200622 	return (fem_install(node->vp, smb_oplock_ops, (void *)node, OPARGUNIQ,
179*6600Sas200622 	    (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release));
180*6600Sas200622 }
181*6600Sas200622 
182*6600Sas200622 void
183*6600Sas200622 smb_fem_oplock_uninstall(smb_node_t *node)
184*6600Sas200622 {
185*6600Sas200622 	(void) fem_uninstall(node->vp, smb_oplock_ops, (void *)node);
186*6600Sas200622 }
187*6600Sas200622 
188*6600Sas200622 /*
189*6600Sas200622  * FEM FCN monitors
190*6600Sas200622  *
191*6600Sas200622  * The FCN monitors intercept the respective VOP_* call regardless
192*6600Sas200622  * of whether the call originates from CIFS, NFS, or a local process.
193*6600Sas200622  */
194*6600Sas200622 
1955331Samw /*
1965331Samw  * smb_fem_fcn_create()
1975331Samw  *
1985331Samw  * This monitor will catch only changes to VREG files and not to extended
1995331Samw  * attribute files.  This is fine because, for CIFS files, stream creates
2005331Samw  * should not trigger any file change notification on the VDIR directory
2015331Samw  * being monitored.  Creates of any other kind of extended attribute in
2025331Samw  * the directory will also not trigger any file change notification on the
2035331Samw  * VDIR directory being monitored.
2045331Samw  */
2055331Samw 
206*6600Sas200622 static int
2075331Samw smb_fem_fcn_create(
2085331Samw     femarg_t *arg,
2095331Samw     char *name,
2105331Samw     vattr_t *vap,
2115331Samw     vcexcl_t excl,
2125331Samw     int mode,
2135331Samw     vnode_t **vpp,
2145331Samw     cred_t *cr,
2155331Samw     int flag,
2165331Samw     caller_context_t *ct,
2175331Samw     vsecattr_t *vsecp)
2185331Samw {
2195331Samw 	smb_node_t *dnode;
2205331Samw 	int error;
2215331Samw 
2225331Samw 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
2235331Samw 
2245331Samw 	ASSERT(dnode);
2255331Samw 
2265331Samw 	error = vnext_create(arg, name, vap, excl, mode, vpp, cr, flag,
2275331Samw 	    ct, vsecp);
2285331Samw 
2295331Samw 	if (error == 0)
2305331Samw 		smb_process_node_notify_change_queue(dnode);
2315331Samw 
2325331Samw 	return (error);
2335331Samw }
2345331Samw 
2355331Samw /*
2365331Samw  * smb_fem_fcn_remove()
2375331Samw  *
2385331Samw  * This monitor will catch only changes to VREG files and to not extended
2395331Samw  * attribute files.  This is fine because, for CIFS files, stream deletes
2405331Samw  * should not trigger any file change notification on the VDIR directory
2415331Samw  * being monitored.  Deletes of any other kind of extended attribute in
2425331Samw  * the directory will also not trigger any file change notification on the
2435331Samw  * VDIR directory being monitored.
2445331Samw  */
2455331Samw 
246*6600Sas200622 static int
2475331Samw smb_fem_fcn_remove(
2485331Samw     femarg_t *arg,
2495331Samw     char *name,
2505331Samw     cred_t *cr,
2515331Samw     caller_context_t *ct,
2525331Samw     int flags)
2535331Samw {
2545331Samw 	smb_node_t *dnode;
2555331Samw 	int error;
2565331Samw 
2575331Samw 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
2585331Samw 
2595331Samw 	ASSERT(dnode);
2605331Samw 
2615331Samw 	error = vnext_remove(arg, name, cr, ct, flags);
2625331Samw 
2635331Samw 	if (error == 0)
2645331Samw 		smb_process_node_notify_change_queue(dnode);
2655331Samw 
2665331Samw 	return (error);
2675331Samw }
2685331Samw 
269*6600Sas200622 static int
2705331Samw smb_fem_fcn_rename(
2715331Samw     femarg_t *arg,
2725331Samw     char *snm,
2735331Samw     vnode_t *tdvp,
2745331Samw     char *tnm,
2755331Samw     cred_t *cr,
2765331Samw     caller_context_t *ct,
2775331Samw     int flags)
2785331Samw {
2795331Samw 	smb_node_t *dnode;
2805331Samw 	int error;
2815331Samw 
2825331Samw 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
2835331Samw 
2845331Samw 	ASSERT(dnode);
2855331Samw 
2865331Samw 	error = vnext_rename(arg, snm, tdvp, tnm, cr, ct, flags);
2875331Samw 
2885331Samw 	if (error == 0)
2895331Samw 		smb_process_node_notify_change_queue(dnode);
2905331Samw 
2915331Samw 	return (error);
2925331Samw }
2935331Samw 
294*6600Sas200622 static int
2955331Samw smb_fem_fcn_mkdir(
2965331Samw     femarg_t *arg,
2975331Samw     char *name,
2985331Samw     vattr_t *vap,
2995331Samw     vnode_t **vpp,
3005331Samw     cred_t *cr,
3015331Samw     caller_context_t *ct,
3025331Samw     int flags,
3035331Samw     vsecattr_t *vsecp)
3045331Samw {
3055331Samw 	smb_node_t *dnode;
3065331Samw 	int error;
3075331Samw 
3085331Samw 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
3095331Samw 
3105331Samw 	ASSERT(dnode);
3115331Samw 
3125331Samw 	error = vnext_mkdir(arg, name, vap, vpp, cr, ct, flags, vsecp);
3135331Samw 
3145331Samw 	if (error == 0)
3155331Samw 		smb_process_node_notify_change_queue(dnode);
3165331Samw 
3175331Samw 	return (error);
3185331Samw }
3195331Samw 
320*6600Sas200622 static int
3215331Samw smb_fem_fcn_rmdir(
3225331Samw     femarg_t *arg,
3235331Samw     char *name,
3245331Samw     vnode_t *cdir,
3255331Samw     cred_t *cr,
3265331Samw     caller_context_t *ct,
3275331Samw     int flags)
3285331Samw {
3295331Samw 	smb_node_t *dnode;
3305331Samw 	int error;
3315331Samw 
3325331Samw 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
3335331Samw 
3345331Samw 	ASSERT(dnode);
3355331Samw 
3365331Samw 	error = vnext_rmdir(arg, name, cdir, cr, ct, flags);
3375331Samw 
3385331Samw 	if (error == 0)
3395331Samw 		smb_process_node_notify_change_queue(dnode);
3405331Samw 
3415331Samw 	return (error);
3425331Samw }
3435331Samw 
344*6600Sas200622 static int
3455331Samw smb_fem_fcn_link(
3465331Samw     femarg_t *arg,
3475331Samw     vnode_t *svp,
3485331Samw     char *tnm,
3495331Samw     cred_t *cr,
3505331Samw     caller_context_t *ct,
3515331Samw     int flags)
3525331Samw {
3535331Samw 	smb_node_t *dnode;
3545331Samw 	int error;
3555331Samw 
3565331Samw 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
3575331Samw 
3585331Samw 	ASSERT(dnode);
3595331Samw 
3605331Samw 	error = vnext_link(arg, svp, tnm, cr, ct, flags);
3615331Samw 
3625331Samw 	if (error == 0)
3635331Samw 		smb_process_node_notify_change_queue(dnode);
3645331Samw 
3655331Samw 	return (error);
3665331Samw }
3675331Samw 
368*6600Sas200622 static int
3695331Samw smb_fem_fcn_symlink(
3705331Samw     femarg_t *arg,
3715331Samw     char *linkname,
3725331Samw     vattr_t *vap,
3735331Samw     char *target,
3745331Samw     cred_t *cr,
3755331Samw     caller_context_t *ct,
3765331Samw     int flags)
3775331Samw {
3785331Samw 	smb_node_t *dnode;
3795331Samw 	int error;
3805331Samw 
3815331Samw 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
3825331Samw 
3835331Samw 	ASSERT(dnode);
3845331Samw 
3855331Samw 	error = vnext_symlink(arg, linkname, vap, target, cr, ct, flags);
3865331Samw 
3875331Samw 	if (error == 0)
3885331Samw 		smb_process_node_notify_change_queue(dnode);
3895331Samw 
3905331Samw 	return (error);
3915331Samw }
392*6600Sas200622 
393*6600Sas200622 /*
394*6600Sas200622  * FEM oplock monitors
395*6600Sas200622  *
396*6600Sas200622  * The monitors below are not intended to intercept CIFS calls.
397*6600Sas200622  * CIFS higher-level routines will break oplocks as needed prior
398*6600Sas200622  * to getting to the VFS layer.
399*6600Sas200622  */
400*6600Sas200622 
401*6600Sas200622 #define	SMB_FEM_OPLOCK_BREAK(arg) \
402*6600Sas200622 	smb_oplock_break((smb_node_t *)((arg)->fa_fnode->fn_available));
403*6600Sas200622 
404*6600Sas200622 static int
405*6600Sas200622 smb_fem_oplock_open(
406*6600Sas200622 	femarg_t *arg,
407*6600Sas200622 	int mode,
408*6600Sas200622 	cred_t *cr,
409*6600Sas200622 	struct caller_context *ct)
410*6600Sas200622 {
411*6600Sas200622 	if (ct == NULL || ct->cc_caller_id != smb_ct.cc_caller_id)
412*6600Sas200622 		SMB_FEM_OPLOCK_BREAK(arg);
413*6600Sas200622 
414*6600Sas200622 	return (vnext_open(arg, mode, cr, ct));
415*6600Sas200622 }
416*6600Sas200622 
417*6600Sas200622 /*
418*6600Sas200622  * Should normally be hit only via NFSv2/v3.  All other accesses
419*6600Sas200622  * (CIFS/NFS/local) should call VOP_OPEN first.
420*6600Sas200622  */
421*6600Sas200622 
422*6600Sas200622 static int
423*6600Sas200622 smb_fem_oplock_read(
424*6600Sas200622 	femarg_t *arg,
425*6600Sas200622 	uio_t *uiop,
426*6600Sas200622 	int ioflag,
427*6600Sas200622 	cred_t *cr,
428*6600Sas200622 	struct caller_context *ct)
429*6600Sas200622 {
430*6600Sas200622 	if (ct == NULL || ct->cc_caller_id != smb_ct.cc_caller_id)
431*6600Sas200622 		SMB_FEM_OPLOCK_BREAK(arg);
432*6600Sas200622 
433*6600Sas200622 	return (vnext_read(arg, uiop, ioflag, cr, ct));
434*6600Sas200622 }
435*6600Sas200622 
436*6600Sas200622 /*
437*6600Sas200622  * Should normally be hit only via NFSv2/v3.  All other accesses
438*6600Sas200622  * (CIFS/NFS/local) should call VOP_OPEN first.
439*6600Sas200622  */
440*6600Sas200622 
441*6600Sas200622 static int
442*6600Sas200622 smb_fem_oplock_write(
443*6600Sas200622 	femarg_t *arg,
444*6600Sas200622 	uio_t *uiop,
445*6600Sas200622 	int ioflag,
446*6600Sas200622 	cred_t *cr,
447*6600Sas200622 	struct caller_context *ct)
448*6600Sas200622 {
449*6600Sas200622 	if (ct == NULL || ct->cc_caller_id != smb_ct.cc_caller_id)
450*6600Sas200622 		SMB_FEM_OPLOCK_BREAK(arg);
451*6600Sas200622 
452*6600Sas200622 	return (vnext_write(arg, uiop, ioflag, cr, ct));
453*6600Sas200622 }
454*6600Sas200622 
455*6600Sas200622 static int
456*6600Sas200622 smb_fem_oplock_setattr(
457*6600Sas200622 	femarg_t *arg,
458*6600Sas200622 	vattr_t *vap,
459*6600Sas200622 	int flags,
460*6600Sas200622 	cred_t *cr,
461*6600Sas200622 	caller_context_t *ct)
462*6600Sas200622 {
463*6600Sas200622 	if (ct == NULL || ct->cc_caller_id != smb_ct.cc_caller_id)
464*6600Sas200622 		SMB_FEM_OPLOCK_BREAK(arg);
465*6600Sas200622 
466*6600Sas200622 	return (vnext_setattr(arg, vap, flags, cr, ct));
467*6600Sas200622 }
468*6600Sas200622 
469*6600Sas200622 static int
470*6600Sas200622 smb_fem_oplock_rwlock(
471*6600Sas200622 	femarg_t *arg,
472*6600Sas200622 	int write_lock,
473*6600Sas200622 	caller_context_t *ct)
474*6600Sas200622 {
475*6600Sas200622 	if (write_lock) {
476*6600Sas200622 		if (ct == NULL || ct->cc_caller_id != smb_ct.cc_caller_id)
477*6600Sas200622 			SMB_FEM_OPLOCK_BREAK(arg);
478*6600Sas200622 	}
479*6600Sas200622 
480*6600Sas200622 	return (vnext_rwlock(arg, write_lock, ct));
481*6600Sas200622 }
482*6600Sas200622 
483*6600Sas200622 static int
484*6600Sas200622 smb_fem_oplock_space(
485*6600Sas200622 	femarg_t *arg,
486*6600Sas200622 	int cmd,
487*6600Sas200622 	flock64_t *bfp,
488*6600Sas200622 	int flag,
489*6600Sas200622 	offset_t offset,
490*6600Sas200622 	cred_t *cr,
491*6600Sas200622 	caller_context_t *ct)
492*6600Sas200622 {
493*6600Sas200622 	if (ct == NULL || ct->cc_caller_id != smb_ct.cc_caller_id)
494*6600Sas200622 		SMB_FEM_OPLOCK_BREAK(arg);
495*6600Sas200622 
496*6600Sas200622 	return (vnext_space(arg, cmd, bfp, flag, offset, cr, ct));
497*6600Sas200622 }
498*6600Sas200622 
499*6600Sas200622 static int
500*6600Sas200622 smb_fem_oplock_setsecattr(
501*6600Sas200622 	femarg_t *arg,
502*6600Sas200622 	vsecattr_t *vsap,
503*6600Sas200622 	int flag,
504*6600Sas200622 	cred_t *cr,
505*6600Sas200622 	caller_context_t *ct)
506*6600Sas200622 {
507*6600Sas200622 	if (ct == NULL || ct->cc_caller_id != smb_ct.cc_caller_id)
508*6600Sas200622 		SMB_FEM_OPLOCK_BREAK(arg);
509*6600Sas200622 
510*6600Sas200622 	return (vnext_setsecattr(arg, vsap, flag, cr, ct));
511*6600Sas200622 }
512*6600Sas200622 
513*6600Sas200622 /*
514*6600Sas200622  * smb_fem_oplock_vnevent()
515*6600Sas200622  *
516*6600Sas200622  * To intercept NFS and local renames and removes in order to break any
517*6600Sas200622  * existing oplock prior to the operation.
518*6600Sas200622  *
519*6600Sas200622  * Note: Currently, this monitor is traversed only when an FS is mounted
520*6600Sas200622  * non-nbmand.  (When the FS is mounted nbmand, share reservation checking
521*6600Sas200622  * will detect a share violation and return an error prior to the VOP layer
522*6600Sas200622  * being reached.)  Thus, for nbmand NFS and local renames and removes,
523*6600Sas200622  * an existing oplock is never broken prior to share checking (contrary to
524*6600Sas200622  * how it is with intra-CIFS remove and rename requests).
525*6600Sas200622  */
526*6600Sas200622 
527*6600Sas200622 static int
528*6600Sas200622 smb_fem_oplock_vnevent(
529*6600Sas200622 	femarg_t *arg,
530*6600Sas200622 	vnevent_t vnevent,
531*6600Sas200622 	vnode_t *dvp,
532*6600Sas200622 	char *name,
533*6600Sas200622 	caller_context_t *ct)
534*6600Sas200622 {
535*6600Sas200622 	switch (vnevent) {
536*6600Sas200622 	case VE_REMOVE:
537*6600Sas200622 	case VE_RENAME_DEST:
538*6600Sas200622 	case VE_RENAME_SRC:
539*6600Sas200622 
540*6600Sas200622 		SMB_FEM_OPLOCK_BREAK(arg);
541*6600Sas200622 		break;
542*6600Sas200622 
543*6600Sas200622 	default:
544*6600Sas200622 		break;
545*6600Sas200622 	}
546*6600Sas200622 	return (vnext_vnevent(arg, vnevent, dvp, name, ct));
547*6600Sas200622 }
548