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 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 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 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 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 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