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 /*
22*12890SJoyce.McIntosh@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw */
245331Samw
2510966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
266600Sas200622 #include <smbsrv/smb_fsops.h>
275331Samw #include <sys/sdt.h>
286600Sas200622 #include <sys/fcntl.h>
295331Samw #include <sys/vfs.h>
305331Samw #include <sys/vfs_opreg.h>
315331Samw #include <sys/vnode.h>
325331Samw #include <sys/fem.h>
335331Samw
346600Sas200622 extern caller_context_t smb_ct;
356600Sas200622
366600Sas200622 static boolean_t smb_fem_initialized = B_FALSE;
376600Sas200622 static fem_t *smb_fcn_ops = NULL;
386600Sas200622 static fem_t *smb_oplock_ops = NULL;
396600Sas200622
406600Sas200622 /*
416600Sas200622 * Declarations for FCN (file change notification) FEM monitors
426600Sas200622 */
436600Sas200622
446600Sas200622 void smb_fem_fcn_install(smb_node_t *);
456600Sas200622 void smb_fem_fcn_uninstall(smb_node_t *);
466600Sas200622
476600Sas200622 static int smb_fem_fcn_create(femarg_t *, char *, vattr_t *, vcexcl_t, int,
485331Samw vnode_t **, cred_t *, int, caller_context_t *, vsecattr_t *);
496600Sas200622 static int smb_fem_fcn_remove(femarg_t *, char *, cred_t *,
505331Samw caller_context_t *, int);
516600Sas200622 static int smb_fem_fcn_rename(femarg_t *, char *, vnode_t *, char *,
525331Samw cred_t *, caller_context_t *, int);
536600Sas200622 static int smb_fem_fcn_mkdir(femarg_t *, char *, vattr_t *, vnode_t **,
545331Samw cred_t *, caller_context_t *, int, vsecattr_t *);
556600Sas200622 static int smb_fem_fcn_rmdir(femarg_t *, char *, vnode_t *, cred_t *,
565331Samw caller_context_t *, int);
576600Sas200622 static int smb_fem_fcn_link(femarg_t *, vnode_t *, char *, cred_t *,
585331Samw caller_context_t *, int);
596600Sas200622 static int smb_fem_fcn_symlink(femarg_t *, char *, vattr_t *,
605331Samw char *, cred_t *, caller_context_t *, int);
615331Samw
625331Samw static const fs_operation_def_t smb_fcn_tmpl[] = {
635331Samw VOPNAME_CREATE, { .femop_create = smb_fem_fcn_create },
645331Samw VOPNAME_REMOVE, {.femop_remove = smb_fem_fcn_remove},
655331Samw VOPNAME_RENAME, {.femop_rename = smb_fem_fcn_rename},
665331Samw VOPNAME_MKDIR, {.femop_mkdir = smb_fem_fcn_mkdir},
675331Samw VOPNAME_RMDIR, {.femop_rmdir = smb_fem_fcn_rmdir},
685331Samw VOPNAME_LINK, {.femop_link = smb_fem_fcn_link},
695331Samw VOPNAME_SYMLINK, {.femop_symlink = smb_fem_fcn_symlink},
705331Samw NULL, NULL
715331Samw };
725331Samw
736600Sas200622 /*
746600Sas200622 * Declarations for oplock FEM monitors
756600Sas200622 */
766600Sas200622
776600Sas200622 int smb_fem_oplock_install(smb_node_t *);
78*12890SJoyce.McIntosh@Sun.COM int smb_fem_oplock_uninstall(smb_node_t *);
796600Sas200622
806600Sas200622 static int smb_fem_oplock_open(femarg_t *, int, cred_t *,
816600Sas200622 struct caller_context *);
826600Sas200622 static int smb_fem_oplock_read(femarg_t *, uio_t *, int, cred_t *,
836600Sas200622 struct caller_context *);
846600Sas200622 static int smb_fem_oplock_write(femarg_t *, uio_t *, int, cred_t *,
856600Sas200622 struct caller_context *);
866600Sas200622 static int smb_fem_oplock_setattr(femarg_t *, vattr_t *, int, cred_t *,
876600Sas200622 caller_context_t *);
886600Sas200622 static int smb_fem_oplock_rwlock(femarg_t *, int, caller_context_t *);
896600Sas200622 static int smb_fem_oplock_space(femarg_t *, int, flock64_t *, int,
906600Sas200622 offset_t, cred_t *, caller_context_t *);
916600Sas200622 static int smb_fem_oplock_vnevent(femarg_t *, vnevent_t, vnode_t *, char *,
926600Sas200622 caller_context_t *);
936600Sas200622
946600Sas200622 static const fs_operation_def_t smb_oplock_tmpl[] = {
956600Sas200622 VOPNAME_OPEN, { .femop_open = smb_fem_oplock_open },
966600Sas200622 VOPNAME_READ, { .femop_read = smb_fem_oplock_read },
976600Sas200622 VOPNAME_WRITE, { .femop_write = smb_fem_oplock_write },
986600Sas200622 VOPNAME_SETATTR, { .femop_setattr = smb_fem_oplock_setattr },
996600Sas200622 VOPNAME_RWLOCK, { .femop_rwlock = smb_fem_oplock_rwlock },
1006600Sas200622 VOPNAME_SPACE, { .femop_space = smb_fem_oplock_space },
1016600Sas200622 VOPNAME_VNEVENT, { .femop_vnevent = smb_fem_oplock_vnevent },
1026600Sas200622 NULL, NULL
1036600Sas200622 };
1046600Sas200622
105*12890SJoyce.McIntosh@Sun.COM static int smb_fem_oplock_break(femarg_t *, caller_context_t *, uint32_t);
1068934SJose.Borrego@Sun.COM
1076139Sjb150015 /*
1086139Sjb150015 * smb_fem_init
1096139Sjb150015 *
1106139Sjb150015 * This function is not multi-thread safe. The caller must make sure only one
1116139Sjb150015 * thread makes the call.
1126139Sjb150015 */
1135331Samw int
smb_fem_init(void)1146139Sjb150015 smb_fem_init(void)
1155331Samw {
1166139Sjb150015 int rc = 0;
1176139Sjb150015
1186139Sjb150015 if (smb_fem_initialized)
1196139Sjb150015 return (0);
1206139Sjb150015
1216139Sjb150015 rc = fem_create("smb_fcn_ops", smb_fcn_tmpl, &smb_fcn_ops);
1226139Sjb150015 if (rc)
1236139Sjb150015 return (rc);
1246139Sjb150015
1256600Sas200622 rc = fem_create("smb_oplock_ops", smb_oplock_tmpl,
1266600Sas200622 &smb_oplock_ops);
1276600Sas200622
1286600Sas200622 if (rc) {
1296600Sas200622 fem_free(smb_fcn_ops);
1306600Sas200622 smb_fcn_ops = NULL;
1316600Sas200622 return (rc);
1326600Sas200622 }
1336600Sas200622
1346139Sjb150015 smb_fem_initialized = B_TRUE;
1356139Sjb150015
1366139Sjb150015 return (0);
1375331Samw }
1385331Samw
1396139Sjb150015 /*
1406139Sjb150015 * smb_fem_fini
1416139Sjb150015 *
1426139Sjb150015 * This function is not multi-thread safe. The caller must make sure only one
1436139Sjb150015 * thread makes the call.
1446139Sjb150015 */
1455331Samw void
smb_fem_fini(void)1466139Sjb150015 smb_fem_fini(void)
1475331Samw {
1486139Sjb150015 if (!smb_fem_initialized)
1496139Sjb150015 return;
1506139Sjb150015
1516139Sjb150015 fem_free(smb_fcn_ops);
1526600Sas200622 fem_free(smb_oplock_ops);
1536139Sjb150015 smb_fcn_ops = NULL;
1546600Sas200622 smb_oplock_ops = NULL;
1556139Sjb150015 smb_fem_initialized = B_FALSE;
1565331Samw }
1575331Samw
1585331Samw void
smb_fem_fcn_install(smb_node_t * node)1595331Samw smb_fem_fcn_install(smb_node_t *node)
1605331Samw {
1616600Sas200622 (void) fem_install(node->vp, smb_fcn_ops, (void *)node, OPARGUNIQ,
1626600Sas200622 (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release);
1635331Samw }
1645331Samw
1655331Samw void
smb_fem_fcn_uninstall(smb_node_t * node)1665331Samw smb_fem_fcn_uninstall(smb_node_t *node)
1675331Samw {
1685331Samw (void) fem_uninstall(node->vp, smb_fcn_ops, (void *)node);
1695331Samw }
1705331Samw
1716600Sas200622 int
smb_fem_oplock_install(smb_node_t * node)1726600Sas200622 smb_fem_oplock_install(smb_node_t *node)
1736600Sas200622 {
1746600Sas200622 return (fem_install(node->vp, smb_oplock_ops, (void *)node, OPARGUNIQ,
1756600Sas200622 (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release));
1766600Sas200622 }
1776600Sas200622
178*12890SJoyce.McIntosh@Sun.COM int
smb_fem_oplock_uninstall(smb_node_t * node)1796600Sas200622 smb_fem_oplock_uninstall(smb_node_t *node)
1806600Sas200622 {
181*12890SJoyce.McIntosh@Sun.COM return (fem_uninstall(node->vp, smb_oplock_ops, (void *)node));
1826600Sas200622 }
1836600Sas200622
1846600Sas200622 /*
1856600Sas200622 * FEM FCN monitors
1866600Sas200622 *
1876600Sas200622 * The FCN monitors intercept the respective VOP_* call regardless
1886600Sas200622 * of whether the call originates from CIFS, NFS, or a local process.
1896600Sas200622 */
1906600Sas200622
1915331Samw /*
1925331Samw * smb_fem_fcn_create()
1935331Samw *
1945331Samw * This monitor will catch only changes to VREG files and not to extended
1955331Samw * attribute files. This is fine because, for CIFS files, stream creates
1965331Samw * should not trigger any file change notification on the VDIR directory
1975331Samw * being monitored. Creates of any other kind of extended attribute in
1985331Samw * the directory will also not trigger any file change notification on the
1995331Samw * VDIR directory being monitored.
2005331Samw */
2015331Samw
2026600Sas200622 static int
smb_fem_fcn_create(femarg_t * arg,char * name,vattr_t * vap,vcexcl_t excl,int mode,vnode_t ** vpp,cred_t * cr,int flag,caller_context_t * ct,vsecattr_t * vsecp)2035331Samw smb_fem_fcn_create(
2045331Samw femarg_t *arg,
2055331Samw char *name,
2065331Samw vattr_t *vap,
2075331Samw vcexcl_t excl,
2085331Samw int mode,
2095331Samw vnode_t **vpp,
2105331Samw cred_t *cr,
2115331Samw int flag,
2125331Samw caller_context_t *ct,
2135331Samw vsecattr_t *vsecp)
2145331Samw {
2155331Samw smb_node_t *dnode;
2165331Samw int error;
2175331Samw
2185331Samw dnode = (smb_node_t *)arg->fa_fnode->fn_available;
2195331Samw
2205331Samw ASSERT(dnode);
2215331Samw
2225331Samw error = vnext_create(arg, name, vap, excl, mode, vpp, cr, flag,
2235331Samw ct, vsecp);
2245331Samw
2255331Samw if (error == 0)
22611963SAfshin.Ardakani@Sun.COM smb_node_notify_change(dnode);
2275331Samw
2285331Samw return (error);
2295331Samw }
2305331Samw
2315331Samw /*
2325331Samw * smb_fem_fcn_remove()
2335331Samw *
2345331Samw * This monitor will catch only changes to VREG files and to not extended
2355331Samw * attribute files. This is fine because, for CIFS files, stream deletes
2365331Samw * should not trigger any file change notification on the VDIR directory
2375331Samw * being monitored. Deletes of any other kind of extended attribute in
2385331Samw * the directory will also not trigger any file change notification on the
2395331Samw * VDIR directory being monitored.
2405331Samw */
2415331Samw
2426600Sas200622 static int
smb_fem_fcn_remove(femarg_t * arg,char * name,cred_t * cr,caller_context_t * ct,int flags)2435331Samw smb_fem_fcn_remove(
2445331Samw femarg_t *arg,
2455331Samw char *name,
2465331Samw cred_t *cr,
2475331Samw caller_context_t *ct,
2485331Samw int flags)
2495331Samw {
2505331Samw smb_node_t *dnode;
2515331Samw int error;
2525331Samw
2535331Samw dnode = (smb_node_t *)arg->fa_fnode->fn_available;
2545331Samw
2555331Samw ASSERT(dnode);
2565331Samw
2575331Samw error = vnext_remove(arg, name, cr, ct, flags);
2585331Samw
2595331Samw if (error == 0)
26011963SAfshin.Ardakani@Sun.COM smb_node_notify_change(dnode);
2615331Samw
2625331Samw return (error);
2635331Samw }
2645331Samw
2656600Sas200622 static int
smb_fem_fcn_rename(femarg_t * arg,char * snm,vnode_t * tdvp,char * tnm,cred_t * cr,caller_context_t * ct,int flags)2665331Samw smb_fem_fcn_rename(
2675331Samw femarg_t *arg,
2685331Samw char *snm,
2695331Samw vnode_t *tdvp,
2705331Samw char *tnm,
2715331Samw cred_t *cr,
2725331Samw caller_context_t *ct,
2735331Samw int flags)
2745331Samw {
2755331Samw smb_node_t *dnode;
2765331Samw int error;
2775331Samw
2785331Samw dnode = (smb_node_t *)arg->fa_fnode->fn_available;
2795331Samw
2805331Samw ASSERT(dnode);
2815331Samw
2825331Samw error = vnext_rename(arg, snm, tdvp, tnm, cr, ct, flags);
2835331Samw
2845331Samw if (error == 0)
28511963SAfshin.Ardakani@Sun.COM smb_node_notify_change(dnode);
2865331Samw
2875331Samw return (error);
2885331Samw }
2895331Samw
2906600Sas200622 static int
smb_fem_fcn_mkdir(femarg_t * arg,char * name,vattr_t * vap,vnode_t ** vpp,cred_t * cr,caller_context_t * ct,int flags,vsecattr_t * vsecp)2915331Samw smb_fem_fcn_mkdir(
2925331Samw femarg_t *arg,
2935331Samw char *name,
2945331Samw vattr_t *vap,
2955331Samw vnode_t **vpp,
2965331Samw cred_t *cr,
2975331Samw caller_context_t *ct,
2985331Samw int flags,
2995331Samw vsecattr_t *vsecp)
3005331Samw {
3015331Samw smb_node_t *dnode;
3025331Samw int error;
3035331Samw
3045331Samw dnode = (smb_node_t *)arg->fa_fnode->fn_available;
3055331Samw
3065331Samw ASSERT(dnode);
3075331Samw
3085331Samw error = vnext_mkdir(arg, name, vap, vpp, cr, ct, flags, vsecp);
3095331Samw
3105331Samw if (error == 0)
31111963SAfshin.Ardakani@Sun.COM smb_node_notify_change(dnode);
3125331Samw
3135331Samw return (error);
3145331Samw }
3155331Samw
3166600Sas200622 static int
smb_fem_fcn_rmdir(femarg_t * arg,char * name,vnode_t * cdir,cred_t * cr,caller_context_t * ct,int flags)3175331Samw smb_fem_fcn_rmdir(
3185331Samw femarg_t *arg,
3195331Samw char *name,
3205331Samw vnode_t *cdir,
3215331Samw cred_t *cr,
3225331Samw caller_context_t *ct,
3235331Samw int flags)
3245331Samw {
3255331Samw smb_node_t *dnode;
3265331Samw int error;
3275331Samw
3285331Samw dnode = (smb_node_t *)arg->fa_fnode->fn_available;
3295331Samw
3305331Samw ASSERT(dnode);
3315331Samw
3325331Samw error = vnext_rmdir(arg, name, cdir, cr, ct, flags);
3335331Samw
3345331Samw if (error == 0)
33511963SAfshin.Ardakani@Sun.COM smb_node_notify_change(dnode);
3365331Samw
3375331Samw return (error);
3385331Samw }
3395331Samw
3406600Sas200622 static int
smb_fem_fcn_link(femarg_t * arg,vnode_t * svp,char * tnm,cred_t * cr,caller_context_t * ct,int flags)3415331Samw smb_fem_fcn_link(
3425331Samw femarg_t *arg,
3435331Samw vnode_t *svp,
3445331Samw char *tnm,
3455331Samw cred_t *cr,
3465331Samw caller_context_t *ct,
3475331Samw int flags)
3485331Samw {
3495331Samw smb_node_t *dnode;
3505331Samw int error;
3515331Samw
3525331Samw dnode = (smb_node_t *)arg->fa_fnode->fn_available;
3535331Samw
3545331Samw ASSERT(dnode);
3555331Samw
3565331Samw error = vnext_link(arg, svp, tnm, cr, ct, flags);
3575331Samw
3585331Samw if (error == 0)
35911963SAfshin.Ardakani@Sun.COM smb_node_notify_change(dnode);
3605331Samw
3615331Samw return (error);
3625331Samw }
3635331Samw
3646600Sas200622 static int
smb_fem_fcn_symlink(femarg_t * arg,char * linkname,vattr_t * vap,char * target,cred_t * cr,caller_context_t * ct,int flags)3655331Samw smb_fem_fcn_symlink(
3665331Samw femarg_t *arg,
3675331Samw char *linkname,
3685331Samw vattr_t *vap,
3695331Samw char *target,
3705331Samw cred_t *cr,
3715331Samw caller_context_t *ct,
3725331Samw int flags)
3735331Samw {
3745331Samw smb_node_t *dnode;
3755331Samw int error;
3765331Samw
3775331Samw dnode = (smb_node_t *)arg->fa_fnode->fn_available;
3785331Samw
3795331Samw ASSERT(dnode);
3805331Samw
3815331Samw error = vnext_symlink(arg, linkname, vap, target, cr, ct, flags);
3825331Samw
3835331Samw if (error == 0)
38411963SAfshin.Ardakani@Sun.COM smb_node_notify_change(dnode);
3855331Samw
3865331Samw return (error);
3875331Samw }
3886600Sas200622
3896600Sas200622 /*
3906600Sas200622 * FEM oplock monitors
3916600Sas200622 *
3926600Sas200622 * The monitors below are not intended to intercept CIFS calls.
3936600Sas200622 * CIFS higher-level routines will break oplocks as needed prior
3946600Sas200622 * to getting to the VFS layer.
3956600Sas200622 */
3966600Sas200622 static int
smb_fem_oplock_open(femarg_t * arg,int mode,cred_t * cr,caller_context_t * ct)3976600Sas200622 smb_fem_oplock_open(
3988934SJose.Borrego@Sun.COM femarg_t *arg,
3998934SJose.Borrego@Sun.COM int mode,
4008934SJose.Borrego@Sun.COM cred_t *cr,
4018934SJose.Borrego@Sun.COM caller_context_t *ct)
4026600Sas200622 {
403*12890SJoyce.McIntosh@Sun.COM int rc;
404*12890SJoyce.McIntosh@Sun.COM uint32_t flags;
4056600Sas200622
406*12890SJoyce.McIntosh@Sun.COM if (mode & (FWRITE|FTRUNC))
407*12890SJoyce.McIntosh@Sun.COM flags = SMB_OPLOCK_BREAK_TO_NONE;
408*12890SJoyce.McIntosh@Sun.COM else
409*12890SJoyce.McIntosh@Sun.COM flags = SMB_OPLOCK_BREAK_TO_LEVEL_II;
410*12890SJoyce.McIntosh@Sun.COM
411*12890SJoyce.McIntosh@Sun.COM rc = smb_fem_oplock_break(arg, ct, flags);
4128934SJose.Borrego@Sun.COM if (rc == 0)
4138934SJose.Borrego@Sun.COM rc = vnext_open(arg, mode, cr, ct);
4148934SJose.Borrego@Sun.COM return (rc);
4156600Sas200622 }
4166600Sas200622
4176600Sas200622 /*
4186600Sas200622 * Should normally be hit only via NFSv2/v3. All other accesses
4196600Sas200622 * (CIFS/NFS/local) should call VOP_OPEN first.
4206600Sas200622 */
4216600Sas200622
4226600Sas200622 static int
smb_fem_oplock_read(femarg_t * arg,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)4236600Sas200622 smb_fem_oplock_read(
4248934SJose.Borrego@Sun.COM femarg_t *arg,
4258934SJose.Borrego@Sun.COM uio_t *uiop,
4268934SJose.Borrego@Sun.COM int ioflag,
4278934SJose.Borrego@Sun.COM cred_t *cr,
4288934SJose.Borrego@Sun.COM caller_context_t *ct)
4296600Sas200622 {
4308934SJose.Borrego@Sun.COM int rc;
4316600Sas200622
432*12890SJoyce.McIntosh@Sun.COM rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_LEVEL_II);
4338934SJose.Borrego@Sun.COM if (rc == 0)
4348934SJose.Borrego@Sun.COM rc = vnext_read(arg, uiop, ioflag, cr, ct);
4358934SJose.Borrego@Sun.COM return (rc);
4366600Sas200622 }
4376600Sas200622
4386600Sas200622 /*
4396600Sas200622 * Should normally be hit only via NFSv2/v3. All other accesses
4406600Sas200622 * (CIFS/NFS/local) should call VOP_OPEN first.
4416600Sas200622 */
4426600Sas200622
4436600Sas200622 static int
smb_fem_oplock_write(femarg_t * arg,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)4446600Sas200622 smb_fem_oplock_write(
4458934SJose.Borrego@Sun.COM femarg_t *arg,
4468934SJose.Borrego@Sun.COM uio_t *uiop,
4478934SJose.Borrego@Sun.COM int ioflag,
4488934SJose.Borrego@Sun.COM cred_t *cr,
4498934SJose.Borrego@Sun.COM caller_context_t *ct)
4506600Sas200622 {
4518934SJose.Borrego@Sun.COM int rc;
4526600Sas200622
453*12890SJoyce.McIntosh@Sun.COM rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
4548934SJose.Borrego@Sun.COM if (rc == 0)
4558934SJose.Borrego@Sun.COM rc = vnext_write(arg, uiop, ioflag, cr, ct);
4568934SJose.Borrego@Sun.COM return (rc);
4576600Sas200622 }
4586600Sas200622
4596600Sas200622 static int
smb_fem_oplock_setattr(femarg_t * arg,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)4606600Sas200622 smb_fem_oplock_setattr(
4618934SJose.Borrego@Sun.COM femarg_t *arg,
4628934SJose.Borrego@Sun.COM vattr_t *vap,
4638934SJose.Borrego@Sun.COM int flags,
4648934SJose.Borrego@Sun.COM cred_t *cr,
4658934SJose.Borrego@Sun.COM caller_context_t *ct)
4666600Sas200622 {
467*12890SJoyce.McIntosh@Sun.COM int rc = 0;
4686600Sas200622
469*12890SJoyce.McIntosh@Sun.COM if (vap->va_mask & AT_SIZE)
470*12890SJoyce.McIntosh@Sun.COM rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
4718934SJose.Borrego@Sun.COM if (rc == 0)
4728934SJose.Borrego@Sun.COM rc = vnext_setattr(arg, vap, flags, cr, ct);
4738934SJose.Borrego@Sun.COM return (rc);
4746600Sas200622 }
4756600Sas200622
4766600Sas200622 static int
smb_fem_oplock_rwlock(femarg_t * arg,int write_lock,caller_context_t * ct)4776600Sas200622 smb_fem_oplock_rwlock(
4788934SJose.Borrego@Sun.COM femarg_t *arg,
4798934SJose.Borrego@Sun.COM int write_lock,
4808934SJose.Borrego@Sun.COM caller_context_t *ct)
4816600Sas200622 {
482*12890SJoyce.McIntosh@Sun.COM int rc;
483*12890SJoyce.McIntosh@Sun.COM uint32_t flags;
4848934SJose.Borrego@Sun.COM
485*12890SJoyce.McIntosh@Sun.COM if (write_lock)
486*12890SJoyce.McIntosh@Sun.COM flags = SMB_OPLOCK_BREAK_TO_NONE;
487*12890SJoyce.McIntosh@Sun.COM else
488*12890SJoyce.McIntosh@Sun.COM flags = SMB_OPLOCK_BREAK_TO_LEVEL_II;
489*12890SJoyce.McIntosh@Sun.COM
490*12890SJoyce.McIntosh@Sun.COM rc = smb_fem_oplock_break(arg, ct, flags);
491*12890SJoyce.McIntosh@Sun.COM if (rc == 0)
492*12890SJoyce.McIntosh@Sun.COM rc = vnext_rwlock(arg, write_lock, ct);
493*12890SJoyce.McIntosh@Sun.COM
494*12890SJoyce.McIntosh@Sun.COM return (rc);
4956600Sas200622 }
4966600Sas200622
4976600Sas200622 static int
smb_fem_oplock_space(femarg_t * arg,int cmd,flock64_t * bfp,int flag,offset_t offset,cred_t * cr,caller_context_t * ct)4986600Sas200622 smb_fem_oplock_space(
4998934SJose.Borrego@Sun.COM femarg_t *arg,
5008934SJose.Borrego@Sun.COM int cmd,
5018934SJose.Borrego@Sun.COM flock64_t *bfp,
5028934SJose.Borrego@Sun.COM int flag,
5038934SJose.Borrego@Sun.COM offset_t offset,
5048934SJose.Borrego@Sun.COM cred_t *cr,
5058934SJose.Borrego@Sun.COM caller_context_t *ct)
5066600Sas200622 {
5078934SJose.Borrego@Sun.COM int rc;
5086600Sas200622
509*12890SJoyce.McIntosh@Sun.COM rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
5108934SJose.Borrego@Sun.COM if (rc == 0)
5118934SJose.Borrego@Sun.COM rc = vnext_space(arg, cmd, bfp, flag, offset, cr, ct);
5128934SJose.Borrego@Sun.COM return (rc);
5136600Sas200622 }
5146600Sas200622
5156600Sas200622 /*
5166600Sas200622 * smb_fem_oplock_vnevent()
5176600Sas200622 *
5186600Sas200622 * To intercept NFS and local renames and removes in order to break any
5196600Sas200622 * existing oplock prior to the operation.
5206600Sas200622 *
5216600Sas200622 * Note: Currently, this monitor is traversed only when an FS is mounted
5226600Sas200622 * non-nbmand. (When the FS is mounted nbmand, share reservation checking
5236600Sas200622 * will detect a share violation and return an error prior to the VOP layer
5246600Sas200622 * being reached.) Thus, for nbmand NFS and local renames and removes,
5256600Sas200622 * an existing oplock is never broken prior to share checking (contrary to
5266600Sas200622 * how it is with intra-CIFS remove and rename requests).
5276600Sas200622 */
5286600Sas200622
5296600Sas200622 static int
smb_fem_oplock_vnevent(femarg_t * arg,vnevent_t vnevent,vnode_t * dvp,char * name,caller_context_t * ct)5306600Sas200622 smb_fem_oplock_vnevent(
5318934SJose.Borrego@Sun.COM femarg_t *arg,
5328934SJose.Borrego@Sun.COM vnevent_t vnevent,
5338934SJose.Borrego@Sun.COM vnode_t *dvp,
5348934SJose.Borrego@Sun.COM char *name,
5358934SJose.Borrego@Sun.COM caller_context_t *ct)
5366600Sas200622 {
537*12890SJoyce.McIntosh@Sun.COM int rc;
538*12890SJoyce.McIntosh@Sun.COM uint32_t flags;
5398934SJose.Borrego@Sun.COM
5406600Sas200622 switch (vnevent) {
5416600Sas200622 case VE_REMOVE:
5426600Sas200622 case VE_RENAME_DEST:
543*12890SJoyce.McIntosh@Sun.COM flags = SMB_OPLOCK_BREAK_TO_NONE | SMB_OPLOCK_BREAK_BATCH;
544*12890SJoyce.McIntosh@Sun.COM rc = smb_fem_oplock_break(arg, ct, flags);
545*12890SJoyce.McIntosh@Sun.COM break;
5466600Sas200622 case VE_RENAME_SRC:
547*12890SJoyce.McIntosh@Sun.COM flags = SMB_OPLOCK_BREAK_TO_LEVEL_II | SMB_OPLOCK_BREAK_BATCH;
548*12890SJoyce.McIntosh@Sun.COM rc = smb_fem_oplock_break(arg, ct, flags);
5496600Sas200622 break;
5506600Sas200622 default:
551*12890SJoyce.McIntosh@Sun.COM rc = 0;
5526600Sas200622 break;
5536600Sas200622 }
554*12890SJoyce.McIntosh@Sun.COM
555*12890SJoyce.McIntosh@Sun.COM if (rc != 0)
556*12890SJoyce.McIntosh@Sun.COM return (rc);
557*12890SJoyce.McIntosh@Sun.COM
5586600Sas200622 return (vnext_vnevent(arg, vnevent, dvp, name, ct));
5596600Sas200622 }
5608934SJose.Borrego@Sun.COM
5618934SJose.Borrego@Sun.COM static int
smb_fem_oplock_break(femarg_t * arg,caller_context_t * ct,uint32_t flags)562*12890SJoyce.McIntosh@Sun.COM smb_fem_oplock_break(femarg_t *arg, caller_context_t *ct, uint32_t flags)
5638934SJose.Borrego@Sun.COM {
5648934SJose.Borrego@Sun.COM smb_node_t *node;
5658934SJose.Borrego@Sun.COM int rc;
5668934SJose.Borrego@Sun.COM
5678934SJose.Borrego@Sun.COM node = (smb_node_t *)((arg)->fa_fnode->fn_available);
5688934SJose.Borrego@Sun.COM SMB_NODE_VALID(node);
5698934SJose.Borrego@Sun.COM
570*12890SJoyce.McIntosh@Sun.COM if (ct && (ct->cc_caller_id == smb_ct.cc_caller_id))
5718934SJose.Borrego@Sun.COM return (0);
5728934SJose.Borrego@Sun.COM
573*12890SJoyce.McIntosh@Sun.COM if (ct && (ct->cc_flags & CC_DONTBLOCK)) {
574*12890SJoyce.McIntosh@Sun.COM flags |= SMB_OPLOCK_BREAK_NOWAIT;
575*12890SJoyce.McIntosh@Sun.COM rc = smb_oplock_break(NULL, node, flags);
576*12890SJoyce.McIntosh@Sun.COM if (rc == EAGAIN)
577*12890SJoyce.McIntosh@Sun.COM ct->cc_flags |= CC_WOULDBLOCK;
5788934SJose.Borrego@Sun.COM } else {
579*12890SJoyce.McIntosh@Sun.COM rc = smb_oplock_break(NULL, node, flags);
5808934SJose.Borrego@Sun.COM }
581*12890SJoyce.McIntosh@Sun.COM
5828934SJose.Borrego@Sun.COM return (rc);
5838934SJose.Borrego@Sun.COM }
584