xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_fem.c (revision 499fd601)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <smbsrv/smb_incl.h>
29 #include <sys/sdt.h>
30 #include <sys/vfs.h>
31 #include <sys/vfs_opreg.h>
32 #include <sys/vnode.h>
33 #include <sys/fem.h>
34 
35 fem_t *smb_fcn_ops = NULL;
36 
37 int smb_fem_fcn_create(femarg_t *, char *, vattr_t *, vcexcl_t, int,
38     vnode_t **, cred_t *, int, caller_context_t *, vsecattr_t *);
39 int smb_fem_fcn_remove(femarg_t *, char *, cred_t *,
40     caller_context_t *, int);
41 int smb_fem_fcn_rename(femarg_t *, char *, vnode_t *, char *,
42     cred_t *, caller_context_t *, int);
43 int smb_fem_fcn_mkdir(femarg_t *, char *, vattr_t *, vnode_t **,
44     cred_t *, caller_context_t *, int, vsecattr_t *);
45 int smb_fem_fcn_rmdir(femarg_t *, char *, vnode_t *, cred_t *,
46     caller_context_t *, int);
47 int smb_fem_fcn_link(femarg_t *, vnode_t *, char *, cred_t *,
48     caller_context_t *, int);
49 int smb_fem_fcn_symlink(femarg_t *, char *, vattr_t *,
50     char *, cred_t *, caller_context_t *, int);
51 
52 static const fs_operation_def_t smb_fcn_tmpl[] = {
53 	VOPNAME_CREATE, { .femop_create = smb_fem_fcn_create },
54 	VOPNAME_REMOVE, {.femop_remove = smb_fem_fcn_remove},
55 	VOPNAME_RENAME, {.femop_rename = smb_fem_fcn_rename},
56 	VOPNAME_MKDIR, {.femop_mkdir = smb_fem_fcn_mkdir},
57 	VOPNAME_RMDIR, {.femop_rmdir = smb_fem_fcn_rmdir},
58 	VOPNAME_LINK, {.femop_link = smb_fem_fcn_link},
59 	VOPNAME_SYMLINK, {.femop_symlink = smb_fem_fcn_symlink},
60 	NULL, NULL
61 };
62 
63 int
64 smb_fem_init()
65 {
66 	return (fem_create("smb_fcn_ops", smb_fcn_tmpl, &smb_fcn_ops));
67 }
68 
69 void
70 smb_fem_shutdown()
71 {
72 	if (smb_fcn_ops)
73 		fem_free(smb_fcn_ops);
74 }
75 
76 void
77 smb_fem_fcn_install(smb_node_t *node)
78 {
79 	(void) fem_install(node->vp, smb_fcn_ops, (void *)node, OPARGUNIQ,
80 	    (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release);
81 }
82 
83 void
84 smb_fem_fcn_uninstall(smb_node_t *node)
85 {
86 	(void) fem_uninstall(node->vp, smb_fcn_ops, (void *)node);
87 }
88 
89 /*
90  * smb_fem_fcn_create()
91  *
92  * This monitor will catch only changes to VREG files and not to extended
93  * attribute files.  This is fine because, for CIFS files, stream creates
94  * should not trigger any file change notification on the VDIR directory
95  * being monitored.  Creates of any other kind of extended attribute in
96  * the directory will also not trigger any file change notification on the
97  * VDIR directory being monitored.
98  */
99 
100 int
101 smb_fem_fcn_create(
102     femarg_t *arg,
103     char *name,
104     vattr_t *vap,
105     vcexcl_t excl,
106     int mode,
107     vnode_t **vpp,
108     cred_t *cr,
109     int flag,
110     caller_context_t *ct,
111     vsecattr_t *vsecp)
112 {
113 	smb_node_t *dnode;
114 	int error;
115 
116 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
117 
118 	ASSERT(dnode);
119 
120 	error = vnext_create(arg, name, vap, excl, mode, vpp, cr, flag,
121 	    ct, vsecp);
122 
123 	if (error == 0)
124 		smb_process_node_notify_change_queue(dnode);
125 
126 	return (error);
127 }
128 
129 /*
130  * smb_fem_fcn_remove()
131  *
132  * This monitor will catch only changes to VREG files and to not extended
133  * attribute files.  This is fine because, for CIFS files, stream deletes
134  * should not trigger any file change notification on the VDIR directory
135  * being monitored.  Deletes of any other kind of extended attribute in
136  * the directory will also not trigger any file change notification on the
137  * VDIR directory being monitored.
138  */
139 
140 int
141 smb_fem_fcn_remove(
142     femarg_t *arg,
143     char *name,
144     cred_t *cr,
145     caller_context_t *ct,
146     int flags)
147 {
148 	smb_node_t *dnode;
149 	int error;
150 
151 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
152 
153 	ASSERT(dnode);
154 
155 	error = vnext_remove(arg, name, cr, ct, flags);
156 
157 	if (error == 0)
158 		smb_process_node_notify_change_queue(dnode);
159 
160 	return (error);
161 }
162 
163 int
164 smb_fem_fcn_rename(
165     femarg_t *arg,
166     char *snm,
167     vnode_t *tdvp,
168     char *tnm,
169     cred_t *cr,
170     caller_context_t *ct,
171     int flags)
172 {
173 	smb_node_t *dnode;
174 	int error;
175 
176 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
177 
178 	ASSERT(dnode);
179 
180 	error = vnext_rename(arg, snm, tdvp, tnm, cr, ct, flags);
181 
182 	if (error == 0)
183 		smb_process_node_notify_change_queue(dnode);
184 
185 	return (error);
186 }
187 
188 int
189 smb_fem_fcn_mkdir(
190     femarg_t *arg,
191     char *name,
192     vattr_t *vap,
193     vnode_t **vpp,
194     cred_t *cr,
195     caller_context_t *ct,
196     int flags,
197     vsecattr_t *vsecp)
198 {
199 	smb_node_t *dnode;
200 	int error;
201 
202 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
203 
204 	ASSERT(dnode);
205 
206 	error = vnext_mkdir(arg, name, vap, vpp, cr, ct, flags, vsecp);
207 
208 	if (error == 0)
209 		smb_process_node_notify_change_queue(dnode);
210 
211 	return (error);
212 }
213 
214 int
215 smb_fem_fcn_rmdir(
216     femarg_t *arg,
217     char *name,
218     vnode_t *cdir,
219     cred_t *cr,
220     caller_context_t *ct,
221     int flags)
222 {
223 	smb_node_t *dnode;
224 	int error;
225 
226 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
227 
228 	ASSERT(dnode);
229 
230 	error = vnext_rmdir(arg, name, cdir, cr, ct, flags);
231 
232 	if (error == 0)
233 		smb_process_node_notify_change_queue(dnode);
234 
235 	return (error);
236 }
237 
238 int
239 smb_fem_fcn_link(
240     femarg_t *arg,
241     vnode_t *svp,
242     char *tnm,
243     cred_t *cr,
244     caller_context_t *ct,
245     int flags)
246 {
247 	smb_node_t *dnode;
248 	int error;
249 
250 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
251 
252 	ASSERT(dnode);
253 
254 	error = vnext_link(arg, svp, tnm, cr, ct, flags);
255 
256 	if (error == 0)
257 		smb_process_node_notify_change_queue(dnode);
258 
259 	return (error);
260 }
261 
262 int
263 smb_fem_fcn_symlink(
264     femarg_t *arg,
265     char *linkname,
266     vattr_t *vap,
267     char *target,
268     cred_t *cr,
269     caller_context_t *ct,
270     int flags)
271 {
272 	smb_node_t *dnode;
273 	int error;
274 
275 	dnode = (smb_node_t *)arg->fa_fnode->fn_available;
276 
277 	ASSERT(dnode);
278 
279 	error = vnext_symlink(arg, linkname, vap, target, cr, ct, flags);
280 
281 	if (error == 0)
282 		smb_process_node_notify_change_queue(dnode);
283 
284 	return (error);
285 }
286