smb_fem.c revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <smbsrv/smb_incl.h>
#include <sys/sdt.h>
#include <sys/vfs.h>
#include <sys/vfs_opreg.h>
#include <sys/vnode.h>
#include <sys/fem.h>
fem_t *smb_fcn_ops = NULL;
int smb_fem_fcn_create(femarg_t *, char *, vattr_t *, vcexcl_t, int,
vnode_t **, cred_t *, int, caller_context_t *, vsecattr_t *);
int smb_fem_fcn_remove(femarg_t *, char *, cred_t *,
caller_context_t *, int);
int smb_fem_fcn_rename(femarg_t *, char *, vnode_t *, char *,
cred_t *, caller_context_t *, int);
int smb_fem_fcn_mkdir(femarg_t *, char *, vattr_t *, vnode_t **,
cred_t *, caller_context_t *, int, vsecattr_t *);
int smb_fem_fcn_rmdir(femarg_t *, char *, vnode_t *, cred_t *,
caller_context_t *, int);
int smb_fem_fcn_link(femarg_t *, vnode_t *, char *, cred_t *,
caller_context_t *, int);
int smb_fem_fcn_symlink(femarg_t *, char *, vattr_t *,
char *, cred_t *, caller_context_t *, int);
static const fs_operation_def_t smb_fcn_tmpl[] = {
VOPNAME_CREATE, { .femop_create = smb_fem_fcn_create },
VOPNAME_REMOVE, {.femop_remove = smb_fem_fcn_remove},
VOPNAME_RENAME, {.femop_rename = smb_fem_fcn_rename},
VOPNAME_MKDIR, {.femop_mkdir = smb_fem_fcn_mkdir},
VOPNAME_RMDIR, {.femop_rmdir = smb_fem_fcn_rmdir},
VOPNAME_LINK, {.femop_link = smb_fem_fcn_link},
VOPNAME_SYMLINK, {.femop_symlink = smb_fem_fcn_symlink},
NULL, NULL
};
int
smb_fem_init()
{
return (fem_create("smb_fcn_ops", smb_fcn_tmpl, &smb_fcn_ops));
}
void
smb_fem_shutdown()
{
if (smb_fcn_ops)
fem_free(smb_fcn_ops);
}
void
smb_fem_fcn_install(smb_node_t *node)
{
(void) fem_install(node->vp, smb_fcn_ops, (void *)node, OPARGUNIQ,
(fem_func_t)smb_node_ref, (fem_func_t)smb_node_release);
}
void
smb_fem_fcn_uninstall(smb_node_t *node)
{
(void) fem_uninstall(node->vp, smb_fcn_ops, (void *)node);
}
/*
* smb_fem_fcn_create()
*
* This monitor will catch only changes to VREG files and not to extended
* attribute files. This is fine because, for CIFS files, stream creates
* should not trigger any file change notification on the VDIR directory
* being monitored. Creates of any other kind of extended attribute in
* the directory will also not trigger any file change notification on the
* VDIR directory being monitored.
*/
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)
{
smb_node_t *dnode;
int error;
dnode = (smb_node_t *)arg->fa_fnode->fn_available;
ASSERT(dnode);
error = vnext_create(arg, name, vap, excl, mode, vpp, cr, flag,
ct, vsecp);
if (error == 0)
smb_process_node_notify_change_queue(dnode);
return (error);
}
/*
* smb_fem_fcn_remove()
*
* This monitor will catch only changes to VREG files and to not extended
* attribute files. This is fine because, for CIFS files, stream deletes
* should not trigger any file change notification on the VDIR directory
* being monitored. Deletes of any other kind of extended attribute in
* the directory will also not trigger any file change notification on the
* VDIR directory being monitored.
*/
int
smb_fem_fcn_remove(
femarg_t *arg,
char *name,
cred_t *cr,
caller_context_t *ct,
int flags)
{
smb_node_t *dnode;
int error;
dnode = (smb_node_t *)arg->fa_fnode->fn_available;
ASSERT(dnode);
error = vnext_remove(arg, name, cr, ct, flags);
if (error == 0)
smb_process_node_notify_change_queue(dnode);
return (error);
}
int
smb_fem_fcn_rename(
femarg_t *arg,
char *snm,
vnode_t *tdvp,
char *tnm,
cred_t *cr,
caller_context_t *ct,
int flags)
{
smb_node_t *dnode;
int error;
dnode = (smb_node_t *)arg->fa_fnode->fn_available;
ASSERT(dnode);
error = vnext_rename(arg, snm, tdvp, tnm, cr, ct, flags);
if (error == 0)
smb_process_node_notify_change_queue(dnode);
return (error);
}
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)
{
smb_node_t *dnode;
int error;
dnode = (smb_node_t *)arg->fa_fnode->fn_available;
ASSERT(dnode);
error = vnext_mkdir(arg, name, vap, vpp, cr, ct, flags, vsecp);
if (error == 0)
smb_process_node_notify_change_queue(dnode);
return (error);
}
int
smb_fem_fcn_rmdir(
femarg_t *arg,
char *name,
vnode_t *cdir,
cred_t *cr,
caller_context_t *ct,
int flags)
{
smb_node_t *dnode;
int error;
dnode = (smb_node_t *)arg->fa_fnode->fn_available;
ASSERT(dnode);
error = vnext_rmdir(arg, name, cdir, cr, ct, flags);
if (error == 0)
smb_process_node_notify_change_queue(dnode);
return (error);
}
int
smb_fem_fcn_link(
femarg_t *arg,
vnode_t *svp,
char *tnm,
cred_t *cr,
caller_context_t *ct,
int flags)
{
smb_node_t *dnode;
int error;
dnode = (smb_node_t *)arg->fa_fnode->fn_available;
ASSERT(dnode);
error = vnext_link(arg, svp, tnm, cr, ct, flags);
if (error == 0)
smb_process_node_notify_change_queue(dnode);
return (error);
}
int
smb_fem_fcn_symlink(
femarg_t *arg,
char *linkname,
vattr_t *vap,
char *target,
cred_t *cr,
caller_context_t *ct,
int flags)
{
smb_node_t *dnode;
int error;
dnode = (smb_node_t *)arg->fa_fnode->fn_available;
ASSERT(dnode);
error = vnext_symlink(arg, linkname, vap, target, cr, ct, flags);
if (error == 0)
smb_process_node_notify_change_queue(dnode);
return (error);
}