1*a90cf9f2SGordon Ross /*
2*a90cf9f2SGordon Ross * CDDL HEADER START
3*a90cf9f2SGordon Ross *
4*a90cf9f2SGordon Ross * The contents of this file are subject to the terms of the
5*a90cf9f2SGordon Ross * Common Development and Distribution License (the "License").
6*a90cf9f2SGordon Ross * You may not use this file except in compliance with the License.
7*a90cf9f2SGordon Ross *
8*a90cf9f2SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*a90cf9f2SGordon Ross * or http://www.opensolaris.org/os/licensing.
10*a90cf9f2SGordon Ross * See the License for the specific language governing permissions
11*a90cf9f2SGordon Ross * and limitations under the License.
12*a90cf9f2SGordon Ross *
13*a90cf9f2SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
14*a90cf9f2SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*a90cf9f2SGordon Ross * If applicable, add the following below this CDDL HEADER, with the
16*a90cf9f2SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
17*a90cf9f2SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
18*a90cf9f2SGordon Ross *
19*a90cf9f2SGordon Ross * CDDL HEADER END
20*a90cf9f2SGordon Ross */
21*a90cf9f2SGordon Ross
22*a90cf9f2SGordon Ross /*
23*a90cf9f2SGordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24*a90cf9f2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25*a90cf9f2SGordon Ross */
26*a90cf9f2SGordon Ross
27*a90cf9f2SGordon Ross /*
28*a90cf9f2SGordon Ross * File Change Notification (FCN)
29*a90cf9f2SGordon Ross * Common parts shared by SMB1 & SMB2
30*a90cf9f2SGordon Ross */
31*a90cf9f2SGordon Ross
32*a90cf9f2SGordon Ross /*
33*a90cf9f2SGordon Ross * This command notifies the client when the specified directory
34*a90cf9f2SGordon Ross * has changed, and optionally returns the names of files and
35*a90cf9f2SGordon Ross * directories that changed, and how they changed. The caller
36*a90cf9f2SGordon Ross * specifies a "Completion Filter" to select which kinds of
37*a90cf9f2SGordon Ross * changes they want to know about.
38*a90cf9f2SGordon Ross *
39*a90cf9f2SGordon Ross * When a change that's in the CompletionFilter is made to the directory,
40*a90cf9f2SGordon Ross * the command completes. The names of the files that have changed since
41*a90cf9f2SGordon Ross * the last time the command was issued are returned to the client.
42*a90cf9f2SGordon Ross * If too many files have changed since the last time the command was
43*a90cf9f2SGordon Ross * issued, then zero bytes are returned and an alternate status code
44*a90cf9f2SGordon Ross * is returned in the Status field of the response.
45*a90cf9f2SGordon Ross *
46*a90cf9f2SGordon Ross * The CompletionFilter is a mask created as the sum of any of the
47*a90cf9f2SGordon Ross * following flags:
48*a90cf9f2SGordon Ross *
49*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
50*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
51*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_NAME 0x00000003
52*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
53*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_SIZE 0x00000008
54*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
55*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
56*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_CREATION 0x00000040
57*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_EA 0x00000080
58*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_SECURITY 0x00000100
59*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
60*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
61*a90cf9f2SGordon Ross * FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
62*a90cf9f2SGordon Ross *
63*a90cf9f2SGordon Ross *
64*a90cf9f2SGordon Ross * The response contains FILE_NOTIFY_INFORMATION structures, as defined
65*a90cf9f2SGordon Ross * below. The NextEntryOffset field of the structure specifies the offset,
66*a90cf9f2SGordon Ross * in bytes, from the start of the current entry to the next entry in the
67*a90cf9f2SGordon Ross * list. If this is the last entry in the list, this field is zero. Each
68*a90cf9f2SGordon Ross * entry in the list must be longword aligned, so NextEntryOffset must be a
69*a90cf9f2SGordon Ross * multiple of four.
70*a90cf9f2SGordon Ross *
71*a90cf9f2SGordon Ross * typedef struct {
72*a90cf9f2SGordon Ross * ULONG NextEntryOffset;
73*a90cf9f2SGordon Ross * ULONG Action;
74*a90cf9f2SGordon Ross * ULONG FileNameLength;
75*a90cf9f2SGordon Ross * WCHAR FileName[1];
76*a90cf9f2SGordon Ross * } FILE_NOTIFY_INFORMATION;
77*a90cf9f2SGordon Ross *
78*a90cf9f2SGordon Ross * Where Action describes what happened to the file named FileName:
79*a90cf9f2SGordon Ross *
80*a90cf9f2SGordon Ross * FILE_ACTION_ADDED 0x00000001
81*a90cf9f2SGordon Ross * FILE_ACTION_REMOVED 0x00000002
82*a90cf9f2SGordon Ross * FILE_ACTION_MODIFIED 0x00000003
83*a90cf9f2SGordon Ross * FILE_ACTION_RENAMED_OLD_NAME 0x00000004
84*a90cf9f2SGordon Ross * FILE_ACTION_RENAMED_NEW_NAME 0x00000005
85*a90cf9f2SGordon Ross * FILE_ACTION_ADDED_STREAM 0x00000006
86*a90cf9f2SGordon Ross * FILE_ACTION_REMOVED_STREAM 0x00000007
87*a90cf9f2SGordon Ross * FILE_ACTION_MODIFIED_STREAM 0x00000008
88*a90cf9f2SGordon Ross */
89*a90cf9f2SGordon Ross
90*a90cf9f2SGordon Ross #include <smbsrv/smb_kproto.h>
91*a90cf9f2SGordon Ross #include <sys/sdt.h>
92*a90cf9f2SGordon Ross
93*a90cf9f2SGordon Ross static void smb_notify_sr(smb_request_t *, uint_t, const char *);
94*a90cf9f2SGordon Ross static uint32_t smb_notify_encode_action(struct smb_request *,
95*a90cf9f2SGordon Ross mbuf_chain_t *, uint32_t, char *);
96*a90cf9f2SGordon Ross
97*a90cf9f2SGordon Ross uint32_t
smb_notify_common(smb_request_t * sr,mbuf_chain_t * mbc,uint32_t CompletionFilter)98*a90cf9f2SGordon Ross smb_notify_common(smb_request_t *sr, mbuf_chain_t *mbc,
99*a90cf9f2SGordon Ross uint32_t CompletionFilter)
100*a90cf9f2SGordon Ross {
101*a90cf9f2SGordon Ross smb_notify_change_req_t *nc;
102*a90cf9f2SGordon Ross smb_node_t *node;
103*a90cf9f2SGordon Ross uint32_t status;
104*a90cf9f2SGordon Ross
105*a90cf9f2SGordon Ross if (sr->fid_ofile == NULL)
106*a90cf9f2SGordon Ross return (NT_STATUS_INVALID_HANDLE);
107*a90cf9f2SGordon Ross
108*a90cf9f2SGordon Ross node = sr->fid_ofile->f_node;
109*a90cf9f2SGordon Ross if (node == NULL || !smb_node_is_dir(node)) {
110*a90cf9f2SGordon Ross /*
111*a90cf9f2SGordon Ross * Notify change is only valid on directories.
112*a90cf9f2SGordon Ross */
113*a90cf9f2SGordon Ross return (NT_STATUS_INVALID_PARAMETER);
114*a90cf9f2SGordon Ross }
115*a90cf9f2SGordon Ross
116*a90cf9f2SGordon Ross /*
117*a90cf9f2SGordon Ross * Prepare to receive event data.
118*a90cf9f2SGordon Ross */
119*a90cf9f2SGordon Ross nc = &sr->sr_ncr;
120*a90cf9f2SGordon Ross nc->nc_flags = CompletionFilter;
121*a90cf9f2SGordon Ross ASSERT(nc->nc_action == 0);
122*a90cf9f2SGordon Ross ASSERT(nc->nc_fname == NULL);
123*a90cf9f2SGordon Ross nc->nc_fname = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
124*a90cf9f2SGordon Ross
125*a90cf9f2SGordon Ross /*
126*a90cf9f2SGordon Ross * Subscribe to events on this node.
127*a90cf9f2SGordon Ross */
128*a90cf9f2SGordon Ross smb_node_fcn_subscribe(node, sr);
129*a90cf9f2SGordon Ross
130*a90cf9f2SGordon Ross /*
131*a90cf9f2SGordon Ross * Wait for subscribed events to arrive.
132*a90cf9f2SGordon Ross * Expect SMB_REQ_STATE_EVENT_OCCURRED
133*a90cf9f2SGordon Ross * or SMB_REQ_STATE_CANCELED when signaled.
134*a90cf9f2SGordon Ross * Note it's possible (though rare) to already
135*a90cf9f2SGordon Ross * have SMB_REQ_STATE_CANCELED here.
136*a90cf9f2SGordon Ross */
137*a90cf9f2SGordon Ross mutex_enter(&sr->sr_mutex);
138*a90cf9f2SGordon Ross if (sr->sr_state == SMB_REQ_STATE_ACTIVE)
139*a90cf9f2SGordon Ross sr->sr_state = SMB_REQ_STATE_WAITING_EVENT;
140*a90cf9f2SGordon Ross while (sr->sr_state == SMB_REQ_STATE_WAITING_EVENT) {
141*a90cf9f2SGordon Ross cv_wait(&nc->nc_cv, &sr->sr_mutex);
142*a90cf9f2SGordon Ross }
143*a90cf9f2SGordon Ross if (sr->sr_state == SMB_REQ_STATE_EVENT_OCCURRED)
144*a90cf9f2SGordon Ross sr->sr_state = SMB_REQ_STATE_ACTIVE;
145*a90cf9f2SGordon Ross mutex_exit(&sr->sr_mutex);
146*a90cf9f2SGordon Ross
147*a90cf9f2SGordon Ross /*
148*a90cf9f2SGordon Ross * Unsubscribe from events on this node.
149*a90cf9f2SGordon Ross */
150*a90cf9f2SGordon Ross smb_node_fcn_unsubscribe(node, sr);
151*a90cf9f2SGordon Ross
152*a90cf9f2SGordon Ross /*
153*a90cf9f2SGordon Ross * Why did we wake up?
154*a90cf9f2SGordon Ross */
155*a90cf9f2SGordon Ross switch (sr->sr_state) {
156*a90cf9f2SGordon Ross case SMB_REQ_STATE_ACTIVE:
157*a90cf9f2SGordon Ross break;
158*a90cf9f2SGordon Ross case SMB_REQ_STATE_CANCELED:
159*a90cf9f2SGordon Ross status = NT_STATUS_CANCELLED;
160*a90cf9f2SGordon Ross goto out;
161*a90cf9f2SGordon Ross default:
162*a90cf9f2SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
163*a90cf9f2SGordon Ross goto out;
164*a90cf9f2SGordon Ross }
165*a90cf9f2SGordon Ross
166*a90cf9f2SGordon Ross /*
167*a90cf9f2SGordon Ross * We have SMB_REQ_STATE_ACTIVE.
168*a90cf9f2SGordon Ross *
169*a90cf9f2SGordon Ross * If we have event data, marshall it now, else just
170*a90cf9f2SGordon Ross * say "many things changed". Note that when we get
171*a90cf9f2SGordon Ross * action FILE_ACTION_SUBDIR_CHANGED, we don't have
172*a90cf9f2SGordon Ross * any event details and only know that some subdir
173*a90cf9f2SGordon Ross * changed, so just report "many things changed".
174*a90cf9f2SGordon Ross */
175*a90cf9f2SGordon Ross switch (nc->nc_action) {
176*a90cf9f2SGordon Ross
177*a90cf9f2SGordon Ross case FILE_ACTION_ADDED:
178*a90cf9f2SGordon Ross case FILE_ACTION_REMOVED:
179*a90cf9f2SGordon Ross case FILE_ACTION_MODIFIED:
180*a90cf9f2SGordon Ross case FILE_ACTION_RENAMED_OLD_NAME:
181*a90cf9f2SGordon Ross case FILE_ACTION_RENAMED_NEW_NAME:
182*a90cf9f2SGordon Ross case FILE_ACTION_ADDED_STREAM:
183*a90cf9f2SGordon Ross case FILE_ACTION_REMOVED_STREAM:
184*a90cf9f2SGordon Ross case FILE_ACTION_MODIFIED_STREAM:
185*a90cf9f2SGordon Ross /*
186*a90cf9f2SGordon Ross * Build the reply
187*a90cf9f2SGordon Ross */
188*a90cf9f2SGordon Ross status = smb_notify_encode_action(sr, mbc,
189*a90cf9f2SGordon Ross nc->nc_action, nc->nc_fname);
190*a90cf9f2SGordon Ross break;
191*a90cf9f2SGordon Ross
192*a90cf9f2SGordon Ross case FILE_ACTION_SUBDIR_CHANGED:
193*a90cf9f2SGordon Ross status = NT_STATUS_NOTIFY_ENUM_DIR;
194*a90cf9f2SGordon Ross break;
195*a90cf9f2SGordon Ross
196*a90cf9f2SGordon Ross case FILE_ACTION_DELETE_PENDING:
197*a90cf9f2SGordon Ross status = NT_STATUS_DELETE_PENDING;
198*a90cf9f2SGordon Ross break;
199*a90cf9f2SGordon Ross
200*a90cf9f2SGordon Ross default:
201*a90cf9f2SGordon Ross ASSERT(0);
202*a90cf9f2SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
203*a90cf9f2SGordon Ross break;
204*a90cf9f2SGordon Ross }
205*a90cf9f2SGordon Ross
206*a90cf9f2SGordon Ross out:
207*a90cf9f2SGordon Ross kmem_free(nc->nc_fname, MAXNAMELEN);
208*a90cf9f2SGordon Ross nc->nc_fname = NULL;
209*a90cf9f2SGordon Ross return (status);
210*a90cf9f2SGordon Ross }
211*a90cf9f2SGordon Ross
212*a90cf9f2SGordon Ross /*
213*a90cf9f2SGordon Ross * Encode a FILE_NOTIFY_INFORMATION struct.
214*a90cf9f2SGordon Ross *
215*a90cf9f2SGordon Ross * We only ever put one of these in a response, so this
216*a90cf9f2SGordon Ross * does not bother handling appending additional ones.
217*a90cf9f2SGordon Ross */
218*a90cf9f2SGordon Ross static uint32_t
smb_notify_encode_action(struct smb_request * sr,mbuf_chain_t * mbc,uint32_t action,char * fname)219*a90cf9f2SGordon Ross smb_notify_encode_action(struct smb_request *sr, mbuf_chain_t *mbc,
220*a90cf9f2SGordon Ross uint32_t action, char *fname)
221*a90cf9f2SGordon Ross {
222*a90cf9f2SGordon Ross uint32_t namelen;
223*a90cf9f2SGordon Ross
224*a90cf9f2SGordon Ross ASSERT(FILE_ACTION_ADDED <= action &&
225*a90cf9f2SGordon Ross action <= FILE_ACTION_MODIFIED_STREAM);
226*a90cf9f2SGordon Ross
227*a90cf9f2SGordon Ross if (fname == NULL)
228*a90cf9f2SGordon Ross return (NT_STATUS_INTERNAL_ERROR);
229*a90cf9f2SGordon Ross namelen = smb_wcequiv_strlen(fname);
230*a90cf9f2SGordon Ross if (namelen == 0)
231*a90cf9f2SGordon Ross return (NT_STATUS_INTERNAL_ERROR);
232*a90cf9f2SGordon Ross
233*a90cf9f2SGordon Ross if (smb_mbc_encodef(mbc, "%lllU", sr,
234*a90cf9f2SGordon Ross 0, /* NextEntryOffset */
235*a90cf9f2SGordon Ross action, namelen, fname))
236*a90cf9f2SGordon Ross return (NT_STATUS_NOTIFY_ENUM_DIR);
237*a90cf9f2SGordon Ross
238*a90cf9f2SGordon Ross return (0);
239*a90cf9f2SGordon Ross }
240*a90cf9f2SGordon Ross
241*a90cf9f2SGordon Ross /*
242*a90cf9f2SGordon Ross * smb_notify_file_closed
243*a90cf9f2SGordon Ross *
244*a90cf9f2SGordon Ross * Cancel any change-notify calls on this open file.
245*a90cf9f2SGordon Ross */
246*a90cf9f2SGordon Ross void
smb_notify_file_closed(struct smb_ofile * of)247*a90cf9f2SGordon Ross smb_notify_file_closed(struct smb_ofile *of)
248*a90cf9f2SGordon Ross {
249*a90cf9f2SGordon Ross smb_session_t *ses;
250*a90cf9f2SGordon Ross smb_request_t *sr;
251*a90cf9f2SGordon Ross smb_slist_t *list;
252*a90cf9f2SGordon Ross
253*a90cf9f2SGordon Ross SMB_OFILE_VALID(of);
254*a90cf9f2SGordon Ross ses = of->f_session;
255*a90cf9f2SGordon Ross SMB_SESSION_VALID(ses);
256*a90cf9f2SGordon Ross list = &ses->s_req_list;
257*a90cf9f2SGordon Ross
258*a90cf9f2SGordon Ross smb_slist_enter(list);
259*a90cf9f2SGordon Ross
260*a90cf9f2SGordon Ross sr = smb_slist_head(list);
261*a90cf9f2SGordon Ross while (sr) {
262*a90cf9f2SGordon Ross SMB_REQ_VALID(sr);
263*a90cf9f2SGordon Ross if (sr->sr_state == SMB_REQ_STATE_WAITING_EVENT &&
264*a90cf9f2SGordon Ross sr->fid_ofile == of) {
265*a90cf9f2SGordon Ross smb_request_cancel(sr);
266*a90cf9f2SGordon Ross }
267*a90cf9f2SGordon Ross sr = smb_slist_next(list, sr);
268*a90cf9f2SGordon Ross }
269*a90cf9f2SGordon Ross
270*a90cf9f2SGordon Ross smb_slist_exit(list);
271*a90cf9f2SGordon Ross }
272*a90cf9f2SGordon Ross
273*a90cf9f2SGordon Ross
274*a90cf9f2SGordon Ross /*
275*a90cf9f2SGordon Ross * smb_notify_event
276*a90cf9f2SGordon Ross *
277*a90cf9f2SGordon Ross * Post an event to the watchers on a given node.
278*a90cf9f2SGordon Ross *
279*a90cf9f2SGordon Ross * This makes one exception for RENAME, where we expect a
280*a90cf9f2SGordon Ross * pair of events for the {old,new} directory element names.
281*a90cf9f2SGordon Ross * This only delivers an event for the "new" name.
282*a90cf9f2SGordon Ross *
283*a90cf9f2SGordon Ross * The event delivery mechanism does not implement delivery of
284*a90cf9f2SGordon Ross * multiple events for one "NT Notify" call. One could do that,
285*a90cf9f2SGordon Ross * but modern clients don't actually use the event data. They
286*a90cf9f2SGordon Ross * set a max. received data size of zero, which means we discard
287*a90cf9f2SGordon Ross * the data and send the special "lots changed" error instead.
288*a90cf9f2SGordon Ross * Given that, there's not really any point in implementing the
289*a90cf9f2SGordon Ross * delivery of multiple events. In fact, we don't even need to
290*a90cf9f2SGordon Ross * implement single event delivery, but do so for completeness,
291*a90cf9f2SGordon Ross * for debug convenience, and to be nice to older clients that
292*a90cf9f2SGordon Ross * may actually want some event data instead of the error.
293*a90cf9f2SGordon Ross *
294*a90cf9f2SGordon Ross * Given that we only deliver a single event for an "NT Notify"
295*a90cf9f2SGordon Ross * caller, we want to deliver the "new" name event. (The "old"
296*a90cf9f2SGordon Ross * name event is less important, even ignored by some clients.)
297*a90cf9f2SGordon Ross * Since we know these are delivered in pairs, we can simply
298*a90cf9f2SGordon Ross * discard the "old" name event, knowing that the "new" name
299*a90cf9f2SGordon Ross * event will be delivered immediately afterwards.
300*a90cf9f2SGordon Ross *
301*a90cf9f2SGordon Ross * So, why do event sources post the "old name" event at all?
302*a90cf9f2SGordon Ross * (1) For debugging, so we see both {old,new} names here.
303*a90cf9f2SGordon Ross * (2) If in the future someone decides to implement the
304*a90cf9f2SGordon Ross * delivery of both {old,new} events, the changes can be
305*a90cf9f2SGordon Ross * mostly isolated to this file.
306*a90cf9f2SGordon Ross */
307*a90cf9f2SGordon Ross void
smb_notify_event(smb_node_t * node,uint_t action,const char * name)308*a90cf9f2SGordon Ross smb_notify_event(smb_node_t *node, uint_t action, const char *name)
309*a90cf9f2SGordon Ross {
310*a90cf9f2SGordon Ross smb_request_t *sr;
311*a90cf9f2SGordon Ross smb_node_fcn_t *fcn;
312*a90cf9f2SGordon Ross
313*a90cf9f2SGordon Ross SMB_NODE_VALID(node);
314*a90cf9f2SGordon Ross fcn = &node->n_fcn;
315*a90cf9f2SGordon Ross
316*a90cf9f2SGordon Ross if (action == FILE_ACTION_RENAMED_OLD_NAME)
317*a90cf9f2SGordon Ross return; /* see above */
318*a90cf9f2SGordon Ross
319*a90cf9f2SGordon Ross mutex_enter(&fcn->fcn_mutex);
320*a90cf9f2SGordon Ross
321*a90cf9f2SGordon Ross sr = list_head(&fcn->fcn_watchers);
322*a90cf9f2SGordon Ross while (sr) {
323*a90cf9f2SGordon Ross smb_notify_sr(sr, action, name);
324*a90cf9f2SGordon Ross sr = list_next(&fcn->fcn_watchers, sr);
325*a90cf9f2SGordon Ross }
326*a90cf9f2SGordon Ross
327*a90cf9f2SGordon Ross mutex_exit(&fcn->fcn_mutex);
328*a90cf9f2SGordon Ross }
329*a90cf9f2SGordon Ross
330*a90cf9f2SGordon Ross /*
331*a90cf9f2SGordon Ross * What completion filter (masks) apply to each of the
332*a90cf9f2SGordon Ross * FILE_ACTION_... events.
333*a90cf9f2SGordon Ross */
334*a90cf9f2SGordon Ross static const uint32_t
335*a90cf9f2SGordon Ross smb_notify_action_mask[] = {
336*a90cf9f2SGordon Ross 0, /* not used */
337*a90cf9f2SGordon Ross
338*a90cf9f2SGordon Ross /* FILE_ACTION_ADDED */
339*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_NAME |
340*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_LAST_WRITE,
341*a90cf9f2SGordon Ross
342*a90cf9f2SGordon Ross /* FILE_ACTION_REMOVED */
343*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_NAME |
344*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_LAST_WRITE,
345*a90cf9f2SGordon Ross
346*a90cf9f2SGordon Ross /* FILE_ACTION_MODIFIED */
347*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_ATTRIBUTES |
348*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_SIZE |
349*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_LAST_WRITE |
350*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_LAST_ACCESS |
351*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_CREATION |
352*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_EA |
353*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_SECURITY,
354*a90cf9f2SGordon Ross
355*a90cf9f2SGordon Ross /* FILE_ACTION_RENAMED_OLD_NAME */
356*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_NAME |
357*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_LAST_WRITE,
358*a90cf9f2SGordon Ross
359*a90cf9f2SGordon Ross /* FILE_ACTION_RENAMED_NEW_NAME */
360*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_NAME |
361*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_LAST_WRITE,
362*a90cf9f2SGordon Ross
363*a90cf9f2SGordon Ross /* FILE_ACTION_ADDED_STREAM */
364*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_STREAM_NAME,
365*a90cf9f2SGordon Ross
366*a90cf9f2SGordon Ross /* FILE_ACTION_REMOVED_STREAM */
367*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_STREAM_NAME,
368*a90cf9f2SGordon Ross
369*a90cf9f2SGordon Ross /* FILE_ACTION_MODIFIED_STREAM */
370*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_STREAM_SIZE |
371*a90cf9f2SGordon Ross FILE_NOTIFY_CHANGE_STREAM_WRITE,
372*a90cf9f2SGordon Ross
373*a90cf9f2SGordon Ross /* FILE_ACTION_SUBDIR_CHANGED */
374*a90cf9f2SGordon Ross NODE_FLAGS_WATCH_TREE,
375*a90cf9f2SGordon Ross
376*a90cf9f2SGordon Ross /* FILE_ACTION_DELETE_PENDING */
377*a90cf9f2SGordon Ross NODE_FLAGS_WATCH_TREE |
378*a90cf9f2SGordon Ross FILE_NOTIFY_VALID_MASK,
379*a90cf9f2SGordon Ross };
380*a90cf9f2SGordon Ross static const int smb_notify_action_nelm =
381*a90cf9f2SGordon Ross sizeof (smb_notify_action_mask) /
382*a90cf9f2SGordon Ross sizeof (smb_notify_action_mask[0]);
383*a90cf9f2SGordon Ross
384*a90cf9f2SGordon Ross /*
385*a90cf9f2SGordon Ross * smb_notify_sr
386*a90cf9f2SGordon Ross *
387*a90cf9f2SGordon Ross * Post an event to an smb request waiting on some node.
388*a90cf9f2SGordon Ross *
389*a90cf9f2SGordon Ross * Note that node->fcn.mutex is held. This implies a
390*a90cf9f2SGordon Ross * lock order: node->fcn.mutex, then sr_mutex
391*a90cf9f2SGordon Ross */
392*a90cf9f2SGordon Ross static void
smb_notify_sr(smb_request_t * sr,uint_t action,const char * name)393*a90cf9f2SGordon Ross smb_notify_sr(smb_request_t *sr, uint_t action, const char *name)
394*a90cf9f2SGordon Ross {
395*a90cf9f2SGordon Ross smb_notify_change_req_t *ncr;
396*a90cf9f2SGordon Ross uint32_t mask;
397*a90cf9f2SGordon Ross
398*a90cf9f2SGordon Ross SMB_REQ_VALID(sr);
399*a90cf9f2SGordon Ross ncr = &sr->sr_ncr;
400*a90cf9f2SGordon Ross
401*a90cf9f2SGordon Ross /*
402*a90cf9f2SGordon Ross * Compute the completion filter mask bits for which
403*a90cf9f2SGordon Ross * we will signal waiting notify requests.
404*a90cf9f2SGordon Ross */
405*a90cf9f2SGordon Ross VERIFY(action < smb_notify_action_nelm);
406*a90cf9f2SGordon Ross mask = smb_notify_action_mask[action];
407*a90cf9f2SGordon Ross
408*a90cf9f2SGordon Ross mutex_enter(&sr->sr_mutex);
409*a90cf9f2SGordon Ross if (sr->sr_state == SMB_REQ_STATE_WAITING_EVENT &&
410*a90cf9f2SGordon Ross (ncr->nc_flags & mask) != 0) {
411*a90cf9f2SGordon Ross sr->sr_state = SMB_REQ_STATE_EVENT_OCCURRED;
412*a90cf9f2SGordon Ross /*
413*a90cf9f2SGordon Ross * Save event data in the sr_ncr field so the
414*a90cf9f2SGordon Ross * reply handler can return it.
415*a90cf9f2SGordon Ross */
416*a90cf9f2SGordon Ross ncr->nc_action = action;
417*a90cf9f2SGordon Ross if (name != NULL)
418*a90cf9f2SGordon Ross (void) strlcpy(ncr->nc_fname, name, MAXNAMELEN);
419*a90cf9f2SGordon Ross cv_signal(&ncr->nc_cv);
420*a90cf9f2SGordon Ross }
421*a90cf9f2SGordon Ross mutex_exit(&sr->sr_mutex);
422*a90cf9f2SGordon Ross }
423