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