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 /* 228934SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 26*10966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h> 276600Sas200622 #include <smbsrv/smb_fsops.h> 285331Samw #include <sys/sdt.h> 296600Sas200622 #include <sys/fcntl.h> 305331Samw #include <sys/vfs.h> 315331Samw #include <sys/vfs_opreg.h> 325331Samw #include <sys/vnode.h> 335331Samw #include <sys/fem.h> 345331Samw 356600Sas200622 extern caller_context_t smb_ct; 366600Sas200622 376600Sas200622 static boolean_t smb_fem_initialized = B_FALSE; 386600Sas200622 static fem_t *smb_fcn_ops = NULL; 396600Sas200622 static fem_t *smb_oplock_ops = NULL; 406600Sas200622 416600Sas200622 /* 426600Sas200622 * Declarations for FCN (file change notification) FEM monitors 436600Sas200622 */ 446600Sas200622 456600Sas200622 void smb_fem_fcn_install(smb_node_t *); 466600Sas200622 void smb_fem_fcn_uninstall(smb_node_t *); 476600Sas200622 486600Sas200622 static int smb_fem_fcn_create(femarg_t *, char *, vattr_t *, vcexcl_t, int, 495331Samw vnode_t **, cred_t *, int, caller_context_t *, vsecattr_t *); 506600Sas200622 static int smb_fem_fcn_remove(femarg_t *, char *, cred_t *, 515331Samw caller_context_t *, int); 526600Sas200622 static int smb_fem_fcn_rename(femarg_t *, char *, vnode_t *, char *, 535331Samw cred_t *, caller_context_t *, int); 546600Sas200622 static int smb_fem_fcn_mkdir(femarg_t *, char *, vattr_t *, vnode_t **, 555331Samw cred_t *, caller_context_t *, int, vsecattr_t *); 566600Sas200622 static int smb_fem_fcn_rmdir(femarg_t *, char *, vnode_t *, cred_t *, 575331Samw caller_context_t *, int); 586600Sas200622 static int smb_fem_fcn_link(femarg_t *, vnode_t *, char *, cred_t *, 595331Samw caller_context_t *, int); 606600Sas200622 static int smb_fem_fcn_symlink(femarg_t *, char *, vattr_t *, 615331Samw char *, cred_t *, caller_context_t *, int); 625331Samw 635331Samw static const fs_operation_def_t smb_fcn_tmpl[] = { 645331Samw VOPNAME_CREATE, { .femop_create = smb_fem_fcn_create }, 655331Samw VOPNAME_REMOVE, {.femop_remove = smb_fem_fcn_remove}, 665331Samw VOPNAME_RENAME, {.femop_rename = smb_fem_fcn_rename}, 675331Samw VOPNAME_MKDIR, {.femop_mkdir = smb_fem_fcn_mkdir}, 685331Samw VOPNAME_RMDIR, {.femop_rmdir = smb_fem_fcn_rmdir}, 695331Samw VOPNAME_LINK, {.femop_link = smb_fem_fcn_link}, 705331Samw VOPNAME_SYMLINK, {.femop_symlink = smb_fem_fcn_symlink}, 715331Samw NULL, NULL 725331Samw }; 735331Samw 746600Sas200622 /* 756600Sas200622 * Declarations for oplock FEM monitors 766600Sas200622 */ 776600Sas200622 786600Sas200622 int smb_fem_oplock_install(smb_node_t *); 796600Sas200622 void smb_fem_oplock_uninstall(smb_node_t *); 806600Sas200622 816600Sas200622 static int smb_fem_oplock_open(femarg_t *, int, cred_t *, 826600Sas200622 struct caller_context *); 836600Sas200622 static int smb_fem_oplock_read(femarg_t *, uio_t *, int, cred_t *, 846600Sas200622 struct caller_context *); 856600Sas200622 static int smb_fem_oplock_write(femarg_t *, uio_t *, int, cred_t *, 866600Sas200622 struct caller_context *); 876600Sas200622 static int smb_fem_oplock_setattr(femarg_t *, vattr_t *, int, cred_t *, 886600Sas200622 caller_context_t *); 896600Sas200622 static int smb_fem_oplock_rwlock(femarg_t *, int, caller_context_t *); 906600Sas200622 static int smb_fem_oplock_space(femarg_t *, int, flock64_t *, int, 916600Sas200622 offset_t, cred_t *, caller_context_t *); 926600Sas200622 static int smb_fem_oplock_setsecattr(femarg_t *, vsecattr_t *, int, cred_t *, 936600Sas200622 caller_context_t *); 946600Sas200622 static int smb_fem_oplock_vnevent(femarg_t *, vnevent_t, vnode_t *, char *, 956600Sas200622 caller_context_t *); 966600Sas200622 976600Sas200622 static const fs_operation_def_t smb_oplock_tmpl[] = { 986600Sas200622 VOPNAME_OPEN, { .femop_open = smb_fem_oplock_open }, 996600Sas200622 VOPNAME_READ, { .femop_read = smb_fem_oplock_read }, 1006600Sas200622 VOPNAME_WRITE, { .femop_write = smb_fem_oplock_write }, 1016600Sas200622 VOPNAME_SETATTR, { .femop_setattr = smb_fem_oplock_setattr }, 1026600Sas200622 VOPNAME_RWLOCK, { .femop_rwlock = smb_fem_oplock_rwlock }, 1036600Sas200622 VOPNAME_SPACE, { .femop_space = smb_fem_oplock_space }, 1046600Sas200622 VOPNAME_SETSECATTR, { .femop_setsecattr = smb_fem_oplock_setsecattr }, 1056600Sas200622 VOPNAME_VNEVENT, { .femop_vnevent = smb_fem_oplock_vnevent }, 1066600Sas200622 NULL, NULL 1076600Sas200622 }; 1086600Sas200622 1098934SJose.Borrego@Sun.COM static int smb_fem_oplock_break(femarg_t *, caller_context_t *); 1108934SJose.Borrego@Sun.COM 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 1296600Sas200622 rc = fem_create("smb_oplock_ops", smb_oplock_tmpl, 1306600Sas200622 &smb_oplock_ops); 1316600Sas200622 1326600Sas200622 if (rc) { 1336600Sas200622 fem_free(smb_fcn_ops); 1346600Sas200622 smb_fcn_ops = NULL; 1356600Sas200622 return (rc); 1366600Sas200622 } 1376600Sas200622 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); 1566600Sas200622 fem_free(smb_oplock_ops); 1576139Sjb150015 smb_fcn_ops = NULL; 1586600Sas200622 smb_oplock_ops = NULL; 1596139Sjb150015 smb_fem_initialized = B_FALSE; 1605331Samw } 1615331Samw 1625331Samw void 1635331Samw smb_fem_fcn_install(smb_node_t *node) 1645331Samw { 1656600Sas200622 (void) fem_install(node->vp, smb_fcn_ops, (void *)node, OPARGUNIQ, 1666600Sas200622 (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 1756600Sas200622 int 1766600Sas200622 smb_fem_oplock_install(smb_node_t *node) 1776600Sas200622 { 1786600Sas200622 return (fem_install(node->vp, smb_oplock_ops, (void *)node, OPARGUNIQ, 1796600Sas200622 (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release)); 1806600Sas200622 } 1816600Sas200622 1826600Sas200622 void 1836600Sas200622 smb_fem_oplock_uninstall(smb_node_t *node) 1846600Sas200622 { 1856600Sas200622 (void) fem_uninstall(node->vp, smb_oplock_ops, (void *)node); 1866600Sas200622 } 1876600Sas200622 1886600Sas200622 /* 1896600Sas200622 * FEM FCN monitors 1906600Sas200622 * 1916600Sas200622 * The FCN monitors intercept the respective VOP_* call regardless 1926600Sas200622 * of whether the call originates from CIFS, NFS, or a local process. 1936600Sas200622 */ 1946600Sas200622 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 2066600Sas200622 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 2466600Sas200622 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 2696600Sas200622 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 2946600Sas200622 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 3206600Sas200622 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 3446600Sas200622 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 3686600Sas200622 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 } 3926600Sas200622 3936600Sas200622 /* 3946600Sas200622 * FEM oplock monitors 3956600Sas200622 * 3966600Sas200622 * The monitors below are not intended to intercept CIFS calls. 3976600Sas200622 * CIFS higher-level routines will break oplocks as needed prior 3986600Sas200622 * to getting to the VFS layer. 3996600Sas200622 */ 4006600Sas200622 static int 4016600Sas200622 smb_fem_oplock_open( 4028934SJose.Borrego@Sun.COM femarg_t *arg, 4038934SJose.Borrego@Sun.COM int mode, 4048934SJose.Borrego@Sun.COM cred_t *cr, 4058934SJose.Borrego@Sun.COM caller_context_t *ct) 4066600Sas200622 { 4078934SJose.Borrego@Sun.COM int rc; 4086600Sas200622 4098934SJose.Borrego@Sun.COM rc = smb_fem_oplock_break(arg, ct); 4108934SJose.Borrego@Sun.COM if (rc == 0) 4118934SJose.Borrego@Sun.COM rc = vnext_open(arg, mode, cr, ct); 4128934SJose.Borrego@Sun.COM return (rc); 4136600Sas200622 } 4146600Sas200622 4156600Sas200622 /* 4166600Sas200622 * Should normally be hit only via NFSv2/v3. All other accesses 4176600Sas200622 * (CIFS/NFS/local) should call VOP_OPEN first. 4186600Sas200622 */ 4196600Sas200622 4206600Sas200622 static int 4216600Sas200622 smb_fem_oplock_read( 4228934SJose.Borrego@Sun.COM femarg_t *arg, 4238934SJose.Borrego@Sun.COM uio_t *uiop, 4248934SJose.Borrego@Sun.COM int ioflag, 4258934SJose.Borrego@Sun.COM cred_t *cr, 4268934SJose.Borrego@Sun.COM caller_context_t *ct) 4276600Sas200622 { 4288934SJose.Borrego@Sun.COM int rc; 4296600Sas200622 4308934SJose.Borrego@Sun.COM rc = smb_fem_oplock_break(arg, ct); 4318934SJose.Borrego@Sun.COM if (rc == 0) 4328934SJose.Borrego@Sun.COM rc = vnext_read(arg, uiop, ioflag, cr, ct); 4338934SJose.Borrego@Sun.COM return (rc); 4346600Sas200622 } 4356600Sas200622 4366600Sas200622 /* 4376600Sas200622 * Should normally be hit only via NFSv2/v3. All other accesses 4386600Sas200622 * (CIFS/NFS/local) should call VOP_OPEN first. 4396600Sas200622 */ 4406600Sas200622 4416600Sas200622 static int 4426600Sas200622 smb_fem_oplock_write( 4438934SJose.Borrego@Sun.COM femarg_t *arg, 4448934SJose.Borrego@Sun.COM uio_t *uiop, 4458934SJose.Borrego@Sun.COM int ioflag, 4468934SJose.Borrego@Sun.COM cred_t *cr, 4478934SJose.Borrego@Sun.COM caller_context_t *ct) 4486600Sas200622 { 4498934SJose.Borrego@Sun.COM int rc; 4506600Sas200622 4518934SJose.Borrego@Sun.COM rc = smb_fem_oplock_break(arg, ct); 4528934SJose.Borrego@Sun.COM if (rc == 0) 4538934SJose.Borrego@Sun.COM rc = vnext_write(arg, uiop, ioflag, cr, ct); 4548934SJose.Borrego@Sun.COM return (rc); 4556600Sas200622 } 4566600Sas200622 4576600Sas200622 static int 4586600Sas200622 smb_fem_oplock_setattr( 4598934SJose.Borrego@Sun.COM femarg_t *arg, 4608934SJose.Borrego@Sun.COM vattr_t *vap, 4618934SJose.Borrego@Sun.COM int flags, 4628934SJose.Borrego@Sun.COM cred_t *cr, 4638934SJose.Borrego@Sun.COM caller_context_t *ct) 4646600Sas200622 { 4658934SJose.Borrego@Sun.COM int rc; 4666600Sas200622 4678934SJose.Borrego@Sun.COM rc = smb_fem_oplock_break(arg, ct); 4688934SJose.Borrego@Sun.COM if (rc == 0) 4698934SJose.Borrego@Sun.COM rc = vnext_setattr(arg, vap, flags, cr, ct); 4708934SJose.Borrego@Sun.COM return (rc); 4716600Sas200622 } 4726600Sas200622 4736600Sas200622 static int 4746600Sas200622 smb_fem_oplock_rwlock( 4758934SJose.Borrego@Sun.COM femarg_t *arg, 4768934SJose.Borrego@Sun.COM int write_lock, 4778934SJose.Borrego@Sun.COM caller_context_t *ct) 4786600Sas200622 { 4796600Sas200622 if (write_lock) { 4808934SJose.Borrego@Sun.COM int rc; 4818934SJose.Borrego@Sun.COM 4828934SJose.Borrego@Sun.COM rc = smb_fem_oplock_break(arg, ct); 4838934SJose.Borrego@Sun.COM if (rc != 0) 4848934SJose.Borrego@Sun.COM return (rc); 4856600Sas200622 } 4866600Sas200622 return (vnext_rwlock(arg, write_lock, ct)); 4876600Sas200622 } 4886600Sas200622 4896600Sas200622 static int 4906600Sas200622 smb_fem_oplock_space( 4918934SJose.Borrego@Sun.COM femarg_t *arg, 4928934SJose.Borrego@Sun.COM int cmd, 4938934SJose.Borrego@Sun.COM flock64_t *bfp, 4948934SJose.Borrego@Sun.COM int flag, 4958934SJose.Borrego@Sun.COM offset_t offset, 4968934SJose.Borrego@Sun.COM cred_t *cr, 4978934SJose.Borrego@Sun.COM caller_context_t *ct) 4986600Sas200622 { 4998934SJose.Borrego@Sun.COM int rc; 5006600Sas200622 5018934SJose.Borrego@Sun.COM rc = smb_fem_oplock_break(arg, ct); 5028934SJose.Borrego@Sun.COM if (rc == 0) 5038934SJose.Borrego@Sun.COM rc = vnext_space(arg, cmd, bfp, flag, offset, cr, ct); 5048934SJose.Borrego@Sun.COM return (rc); 5056600Sas200622 } 5066600Sas200622 5076600Sas200622 static int 5086600Sas200622 smb_fem_oplock_setsecattr( 5098934SJose.Borrego@Sun.COM femarg_t *arg, 5108934SJose.Borrego@Sun.COM vsecattr_t *vsap, 5118934SJose.Borrego@Sun.COM int flag, 5128934SJose.Borrego@Sun.COM cred_t *cr, 5138934SJose.Borrego@Sun.COM caller_context_t *ct) 5146600Sas200622 { 5158934SJose.Borrego@Sun.COM int rc; 5166600Sas200622 5178934SJose.Borrego@Sun.COM rc = smb_fem_oplock_break(arg, ct); 5188934SJose.Borrego@Sun.COM if (rc == 0) 5198934SJose.Borrego@Sun.COM rc = vnext_setsecattr(arg, vsap, flag, cr, ct); 5208934SJose.Borrego@Sun.COM return (rc); 5216600Sas200622 } 5226600Sas200622 5236600Sas200622 /* 5246600Sas200622 * smb_fem_oplock_vnevent() 5256600Sas200622 * 5266600Sas200622 * To intercept NFS and local renames and removes in order to break any 5276600Sas200622 * existing oplock prior to the operation. 5286600Sas200622 * 5296600Sas200622 * Note: Currently, this monitor is traversed only when an FS is mounted 5306600Sas200622 * non-nbmand. (When the FS is mounted nbmand, share reservation checking 5316600Sas200622 * will detect a share violation and return an error prior to the VOP layer 5326600Sas200622 * being reached.) Thus, for nbmand NFS and local renames and removes, 5336600Sas200622 * an existing oplock is never broken prior to share checking (contrary to 5346600Sas200622 * how it is with intra-CIFS remove and rename requests). 5356600Sas200622 */ 5366600Sas200622 5376600Sas200622 static int 5386600Sas200622 smb_fem_oplock_vnevent( 5398934SJose.Borrego@Sun.COM femarg_t *arg, 5408934SJose.Borrego@Sun.COM vnevent_t vnevent, 5418934SJose.Borrego@Sun.COM vnode_t *dvp, 5428934SJose.Borrego@Sun.COM char *name, 5438934SJose.Borrego@Sun.COM caller_context_t *ct) 5446600Sas200622 { 5458934SJose.Borrego@Sun.COM int rc; 5468934SJose.Borrego@Sun.COM 5476600Sas200622 switch (vnevent) { 5486600Sas200622 case VE_REMOVE: 5496600Sas200622 case VE_RENAME_DEST: 5506600Sas200622 case VE_RENAME_SRC: 5518934SJose.Borrego@Sun.COM rc = smb_fem_oplock_break(arg, ct); 5528934SJose.Borrego@Sun.COM if (rc != 0) 5538934SJose.Borrego@Sun.COM return (rc); 5546600Sas200622 break; 5556600Sas200622 5566600Sas200622 default: 5576600Sas200622 break; 5586600Sas200622 } 5596600Sas200622 return (vnext_vnevent(arg, vnevent, dvp, name, ct)); 5606600Sas200622 } 5618934SJose.Borrego@Sun.COM 5628934SJose.Borrego@Sun.COM static int 5638934SJose.Borrego@Sun.COM smb_fem_oplock_break(femarg_t *arg, caller_context_t *ct) 5648934SJose.Borrego@Sun.COM { 5658934SJose.Borrego@Sun.COM smb_node_t *node; 5668934SJose.Borrego@Sun.COM int rc; 5678934SJose.Borrego@Sun.COM 5688934SJose.Borrego@Sun.COM node = (smb_node_t *)((arg)->fa_fnode->fn_available); 5698934SJose.Borrego@Sun.COM SMB_NODE_VALID(node); 5708934SJose.Borrego@Sun.COM 5718934SJose.Borrego@Sun.COM if (ct == NULL) { 5729021Samw@Sun.COM (void) smb_oplock_break(node, NULL, B_FALSE); 5738934SJose.Borrego@Sun.COM return (0); 5748934SJose.Borrego@Sun.COM } 5758934SJose.Borrego@Sun.COM 5768934SJose.Borrego@Sun.COM if (ct->cc_caller_id == smb_ct.cc_caller_id) 5778934SJose.Borrego@Sun.COM return (0); 5788934SJose.Borrego@Sun.COM 5798934SJose.Borrego@Sun.COM if (ct->cc_flags & CC_DONTBLOCK) { 5809021Samw@Sun.COM if (smb_oplock_break(node, NULL, B_TRUE)) 5818934SJose.Borrego@Sun.COM return (0); 5828934SJose.Borrego@Sun.COM ct->cc_flags |= CC_WOULDBLOCK; 5838934SJose.Borrego@Sun.COM rc = EAGAIN; 5848934SJose.Borrego@Sun.COM } else { 5859021Samw@Sun.COM (void) smb_oplock_break(node, NULL, B_FALSE); 5868934SJose.Borrego@Sun.COM rc = 0; 5878934SJose.Borrego@Sun.COM } 5888934SJose.Borrego@Sun.COM return (rc); 5898934SJose.Borrego@Sun.COM } 590