xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_ofile.c (revision 648766a76d4408cb08159179078fb2d5d2bb26cc)
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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2016 Syneto S.R.L. All rights reserved.
24  * Copyright (c) 2016 by Delphix. All rights reserved.
25  * Copyright 2020 Tintri by DDN, Inc. All rights reserved.
26  */
27 
28 /*
29  * General Structures Layout
30  * -------------------------
31  *
32  * This is a simplified diagram showing the relationship between most of the
33  * main structures.
34  *
35  * +-------------------+
36  * |     SMB_INFO      |
37  * +-------------------+
38  *          |
39  *          |
40  *          v
41  * +-------------------+       +-------------------+      +-------------------+
42  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
43  * +-------------------+       +-------------------+      +-------------------+
44  *   |          |
45  *   |          |
46  *   |          v
47  *   |  +-------------------+     +-------------------+   +-------------------+
48  *   |  |       USER        |<--->|       USER        |...|       USER        |
49  *   |  +-------------------+     +-------------------+   +-------------------+
50  *   |
51  *   |
52  *   v
53  * +-------------------+       +-------------------+      +-------------------+
54  * |       TREE        |<----->|       TREE        |......|       TREE        |
55  * +-------------------+       +-------------------+      +-------------------+
56  *      |         |
57  *      |         |
58  *      |         v
59  *      |     +-------+       +-------+      +-------+
60  *      |     | OFILE |<----->| OFILE |......| OFILE |
61  *      |     +-------+       +-------+      +-------+
62  *      |
63  *      |
64  *      v
65  *  +-------+       +------+      +------+
66  *  | ODIR  |<----->| ODIR |......| ODIR |
67  *  +-------+       +------+      +------+
68  *
69  *
70  * Ofile State Machine
71  * ------------------
72  *
73  *    +-------------------------+	 T0
74  *    |  SMB_OFILE_STATE_OPEN   |<--+-------- Creation/Allocation
75  *    +-------------------------+   |
76  *	    |		|	    | T5
77  *	    |		|	+---------------------------+
78  *	    |		|	| SMB_OFILE_STATE_RECONNECT |
79  *	    |		|	+---------------------------+
80  *	    |		|	    ^
81  *	    |		v	    |
82  *	    |   +---------------+   |
83  *	    |   | STATE_SAVE_DH |   |
84  *	    |   | STATE_SAVING  |   |
85  *	    |   +---------------+   |
86  *	    |		|	    | T4
87  *	    | T1	| T3	+--------------------------+
88  *	    |		+------>| SMB_OFILE_STATE_ORPHANED |
89  *	    v			+--------------------------+
90  *    +-------------------------+   |		|
91  *    | SMB_OFILE_STATE_CLOSING |<--+ T6	| T7
92  *    +-------------------------+		|
93  *	    |		^			v
94  *	    | T2	| T8	+-------------------------+
95  *	    |		+-------| SMB_OFILE_STATE_EXPIRED |
96  *	    v			+-------------------------+
97  *    +-------------------------+
98  *    | SMB_OFILE_STATE_CLOSED  |----------> Deletion/Free
99  *    +-------------------------+    T9
100  *
101  * SMB_OFILE_STATE_OPEN
102  *
103  *    While in this state:
104  *      - The ofile is queued in the list of ofiles of its tree.
105  *      - References will be given out if the ofile is looked up.
106  *
107  * SMB_OFILE_STATE_SAVE_DH
108  *
109  *    Similar to state _CLOSING, but instead of deleting the ofile,
110  *    it leaves the ofile in state _ORPHANED (for later reclaim).
111  *    Will move to _SAVING after last ref, then _ORPHANED.
112  *
113  *    While in this state:
114  *	- The ofile has been marked for preservation during a
115  *	  walk of the tree ofile list to close multiple files.
116  *	- References will not be given out if the ofile is looked up,
117  *	  except for oplock break processing.
118  *	- Still affects Sharing Violation rules
119  *
120  * SMB_OFILE_STATE_SAVING
121  *
122  *    Transient state used to keep oplock break processing out
123  *    while the ofile moves to state _ORPHANED.
124  *
125  *    While in this state:
126  *	- References will not be given out if the ofile is looked up,
127  *	  except for oplock break processing.
128  *	- Still affects Sharing Violation rules
129  *
130  * SMB_OFILE_STATE_CLOSING
131  *
132  *    Close has been requested.  Stay in this state until the last
133  *    ref. is gone, then move to state _CLOSED
134  *
135  *    While in this state:
136  *      - The ofile is queued in the list of ofiles of its tree.
137  *      - References will not be given out if the ofile is looked up.
138  *      - The file is closed and the locks held are being released.
139  *      - The resources associated with the ofile remain.
140  *
141  * SMB_OFILE_STATE_CLOSED
142  *
143  *    While in this state:
144  *      - The ofile is queued in the list of ofiles of its tree.
145  *      - References will not be given out if the ofile is looked up.
146  *      - The resources associated with the ofile remain.
147  *
148  * SMB_OFILE_STATE_ORPHANED
149  *
150  *    While in this state:
151  *      - The ofile is queued in the list of ofiles of its tree.
152  *      - Can be reclaimed by the original owner
153  *      - References will not be given out if the ofile is looked up.
154  *      - All the tree, user, and session "up" pointers are NULL!
155  *      - Will eventually be "expired" if not reclaimed
156  *      - Can be closed if its oplock is broken
157  *      - Still affects Sharing Violation rules
158  *
159  * SMB_OFILE_STATE_EXPIRED
160  *
161  *    While in this state:
162  *      - The ofile is queued in the list of ofiles of its tree.
163  *      - References will not be given out if the ofile is looked up.
164  *      - The ofile has not been reclaimed and will soon be closed,
165  *        due to, for example, the durable handle timer expiring, or its
166  *        oplock being broken.
167  *      - Cannot be reclaimed at this point
168  *
169  * SMB_OFILE_STATE_RECONNECT
170  *
171  *    Transient state used to keep oplock break processing out
172  *    while the ofile moves from state _ORPHANED to _OPEN.
173  *
174  *    While in this state:
175  *      - The ofile is being reclaimed; do not touch it.
176  *      - References will not be given out if the ofile is looked up.
177  *      - Still affects Sharing Violation rules
178  *	- see smb2_dh_reconnect() for which members need to be avoided
179  *
180  * Transition T0
181  *
182  *    This transition occurs in smb_ofile_open(). A new ofile is created and
183  *    added to the list of ofiles of a tree.
184  *
185  * Transition T1
186  *
187  *    This transition occurs in smb_ofile_close(). Note that this only happens
188  *    when we determine that an ofile should be closed in spite of its durable
189  *    handle properties.
190  *
191  * Transition T2
192  *
193  *    This transition occurs in smb_ofile_release(). The resources associated
194  *    with the ofile are freed as well as the ofile structure. For the
195  *    transition to occur, the ofile must be in the SMB_OFILE_STATE_CLOSED
196  *    state and the reference count be zero.
197  *
198  * Transition T3
199  *
200  *    This transition occurs in smb_ofile_orphan_dh(). It happens during an
201  *    smb2 logoff, or during a session disconnect when certain conditions are
202  *    met. The ofile and structures above it will be kept around until the ofile
203  *    either gets reclaimed, expires after f_timeout_offset nanoseconds, or its
204  *    oplock is broken.
205  *
206  * Transition T4
207  *
208  *    This transition occurs in smb2_dh_reconnect(). An smb2 create request
209  *    with a DURABLE_HANDLE_RECONNECT(_V2) create context has been
210  *    recieved from the original owner. If leases are supported or it's
211  *    RECONNECT_V2, reconnect is subject to additional conditions. The ofile
212  *    will be unwired from the old, disconnected session, tree, and user,
213  *    and wired up to its new context.
214  *
215  * Transition T5
216  *
217  *    This transition occurs in smb2_dh_reconnect(). The ofile has been
218  *    successfully reclaimed.
219  *
220  * Transition T6
221  *
222  *    This transition occurs in smb_ofile_close(). The ofile has been orphaned
223  *    while some thread was blocked, and that thread closes the ofile. Can only
224  *    happen when the ofile is orphaned due to an SMB2 LOGOFF request.
225  *
226  * Transition T7
227  *
228  *    This transition occurs in smb_session_durable_timers() and
229  *    smb_oplock_send_brk(). The ofile will soon be closed.
230  *    In the former case, f_timeout_offset nanoseconds have passed since
231  *    the ofile was orphaned. In the latter, an oplock break occured
232  *    on the ofile while it was orphaned.
233  *
234  * Transition T8
235  *
236  *    This transition occurs in smb_ofile_close().
237  *
238  * Transition T9
239  *
240  *    This transition occurs in smb_ofile_delete().
241  *
242  * Comments
243  * --------
244  *
245  *    The state machine of the ofile structures is controlled by 3 elements:
246  *      - The list of ofiles of the tree it belongs to.
247  *      - The mutex embedded in the structure itself.
248  *      - The reference count.
249  *
250  *    There's a mutex embedded in the ofile structure used to protect its fields
251  *    and there's a lock embedded in the list of ofiles of a tree. To
252  *    increment or to decrement the reference count the mutex must be entered.
253  *    To insert the ofile into the list of ofiles of the tree and to remove
254  *    the ofile from it, the lock must be entered in RW_WRITER mode.
255  *
256  *    Rules of access to a ofile structure:
257  *
258  *    1) In order to avoid deadlocks, when both (mutex and lock of the ofile
259  *       list) have to be entered, the lock must be entered first. Additionally,
260  *       f_mutex must not be held when removing the ofile from sv_persistid_ht.
261  *
262  *    2) All actions applied to an ofile require a reference count.
263  *
264  *    3) There are 2 ways of getting a reference count. One is when the ofile
265  *       is opened. The other one when the ofile is looked up. This translates
266  *       into 2 functions: smb_ofile_open() and smb_ofile_lookup_by_fid().
267  *
268  *    It should be noted that the reference count of an ofile registers the
269  *    number of references to the ofile in other structures (such as an smb
270  *    request). The reference count is not incremented in these 2 instances:
271  *
272  *    1) The ofile is open. An ofile is anchored by its state. If there's
273  *       no activity involving an ofile currently open, the reference count
274  *       of that ofile is zero.
275  *
276  *    2) The ofile is queued in the list of ofiles of its tree. The fact of
277  *       being queued in that list is NOT registered by incrementing the
278  *       reference count.
279  */
280 #include <smbsrv/smb2_kproto.h>
281 #include <smbsrv/smb_fsops.h>
282 #include <sys/time.h>
283 #include <sys/random.h>
284 
285 static boolean_t smb_ofile_is_open_locked(smb_ofile_t *);
286 static void smb_ofile_delete(void *arg);
287 static void smb_ofile_save_dh(void *arg);
288 
289 static int smb_ofile_netinfo_encode(smb_ofile_t *, uint8_t *, size_t,
290     uint32_t *);
291 static int smb_ofile_netinfo_init(smb_ofile_t *, smb_netfileinfo_t *);
292 static void smb_ofile_netinfo_fini(smb_netfileinfo_t *);
293 
294 /*
295  * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
296  * which is used to uniquely identify open instances for the
297  * VFS share reservation and POSIX locks.
298  */
299 static volatile uint32_t smb_fids = 0;
300 #define	SMB_UNIQ_FID()	atomic_inc_32_nv(&smb_fids)
301 
302 /*
303  * smb_ofile_alloc
304  * Allocate an ofile and fill in it's "up" pointers, but
305  * do NOT link it into the tree's list of ofiles or the
306  * node's list of ofiles.  An ofile in this state is a
307  * "proposed" open passed to the oplock break code.
308  *
309  * If we don't get as far as smb_ofile_open with this OF,
310  * call smb_ofile_free() to free this object.
311  *
312  * Note: The following sr members may be null during
313  * persistent handle import: session, uid_usr, tid_tree
314  */
315 smb_ofile_t *
316 smb_ofile_alloc(
317     smb_request_t	*sr,
318     smb_arg_open_t	*op,
319     smb_node_t		*node, /* optional (may be NULL) */
320     uint16_t		ftype,
321     uint16_t		tree_fid)
322 {
323 	smb_user_t	*user = sr->uid_user;	/* optional */
324 	smb_tree_t	*tree = sr->tid_tree;	/* optional */
325 	smb_ofile_t	*of;
326 
327 	of = kmem_cache_alloc(smb_cache_ofile, KM_SLEEP);
328 	bzero(of, sizeof (smb_ofile_t));
329 	of->f_magic = SMB_OFILE_MAGIC;
330 
331 	mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL);
332 	list_create(&of->f_notify.nc_waiters, sizeof (smb_request_t),
333 	    offsetof(smb_request_t, sr_waiters));
334 	mutex_init(&of->dh_nvlock, NULL, MUTEX_DEFAULT, NULL);
335 
336 	of->f_state = SMB_OFILE_STATE_ALLOC;
337 	of->f_refcnt = 1;
338 	of->f_ftype = ftype;
339 	of->f_fid = tree_fid;
340 	/* of->f_persistid see smb2_create */
341 	of->f_uniqid = SMB_UNIQ_FID();
342 	of->f_opened_by_pid = sr->smb_pid;
343 	of->f_granted_access = op->desired_access;
344 	of->f_share_access = op->share_access;
345 	of->f_create_options = op->create_options;
346 	if (user != NULL) {
347 		if ((op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) != 0)
348 			of->f_cr = smb_user_getprivcred(user);
349 		else
350 			of->f_cr = user->u_cred;
351 		crhold(of->f_cr);
352 	}
353 	of->f_server = sr->sr_server;
354 	of->f_session = sr->session;	/* may be NULL */
355 
356 	(void) memset(of->f_lock_seq, -1, SMB_OFILE_LSEQ_MAX);
357 
358 	of->f_mode = smb_fsop_amask_to_omode(of->f_granted_access);
359 	if ((of->f_granted_access & FILE_DATA_ALL) == FILE_EXECUTE)
360 		of->f_flags |= SMB_OFLAGS_EXECONLY;
361 
362 	/*
363 	 * In case a lease is requested, copy the lease keys now so
364 	 * any oplock breaks during open don't break those on our
365 	 * other handles that might have the same lease.
366 	 */
367 	bcopy(op->lease_key, of->TargetOplockKey, SMB_LEASE_KEY_SZ);
368 	bcopy(op->parent_lease_key, of->ParentOplockKey, SMB_LEASE_KEY_SZ);
369 
370 	/*
371 	 * grab a ref for of->f_user and of->f_tree
372 	 * We know the user and tree must be "live" because
373 	 * this SR holds references to them.  The node ref. is
374 	 * held by our caller, until smb_ofile_open puts this
375 	 * ofile on the node ofile list with smb_node_add_ofile.
376 	 */
377 	if (user != NULL) {
378 		smb_user_hold_internal(user);
379 		of->f_user = user;
380 	}
381 	if (tree != NULL) {
382 		smb_tree_hold_internal(tree);
383 		of->f_tree = tree;
384 	}
385 	of->f_node = node;	/* may be NULL */
386 
387 	return (of);
388 }
389 
390 /*
391  * smb_ofile_open
392  *
393  * Complete an open on an ofile that was previously allocated by
394  * smb_ofile_alloc, by putting it on the tree ofile list and
395  * (if it's a file) the node ofile list.
396  */
397 void
398 smb_ofile_open(
399     smb_request_t	*sr,
400     smb_arg_open_t	*op,
401     smb_ofile_t		*of)
402 {
403 	smb_tree_t	*tree = sr->tid_tree;
404 	smb_node_t	*node = of->f_node;
405 
406 	ASSERT(of->f_state == SMB_OFILE_STATE_ALLOC);
407 	of->f_state = SMB_OFILE_STATE_OPEN;
408 
409 	switch (of->f_ftype) {
410 	case SMB_FTYPE_BYTE_PIPE:
411 	case SMB_FTYPE_MESG_PIPE:
412 		/* See smb_opipe_open. */
413 		of->f_pipe = op->pipe;
414 		smb_server_inc_pipes(of->f_server);
415 		break;
416 	case SMB_FTYPE_DISK:
417 	case SMB_FTYPE_PRINTER:
418 		/* Regular file, not a pipe */
419 		ASSERT(node != NULL);
420 
421 		smb_node_inc_open_ofiles(node);
422 		smb_node_add_ofile(node, of);
423 		smb_node_ref(node);
424 		smb_server_inc_files(of->f_server);
425 		break;
426 	default:
427 		ASSERT(0);
428 	}
429 	smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
430 	smb_llist_insert_tail(&tree->t_ofile_list, of);
431 	smb_llist_exit(&tree->t_ofile_list);
432 	atomic_inc_32(&tree->t_open_files);
433 	atomic_inc_32(&of->f_session->s_file_cnt);
434 
435 }
436 
437 /*
438  * smb_ofile_close
439  *
440  * Incoming states: (where from)
441  *   SMB_OFILE_STATE_OPEN  protocol close, smb_ofile_drop
442  *   SMB_OFILE_STATE_EXPIRED  called via smb2_dh_expire
443  *   SMB_OFILE_STATE_ORPHANED  smb2_dh_shutdown
444  */
445 void
446 smb_ofile_close(smb_ofile_t *of, int32_t mtime_sec)
447 {
448 	smb_attr_t *pa;
449 
450 	SMB_OFILE_VALID(of);
451 
452 	mutex_enter(&of->f_mutex);
453 	ASSERT(of->f_refcnt);
454 
455 	switch (of->f_state) {
456 	case SMB_OFILE_STATE_OPEN:
457 	case SMB_OFILE_STATE_ORPHANED:
458 	case SMB_OFILE_STATE_EXPIRED:
459 		of->f_state = SMB_OFILE_STATE_CLOSING;
460 		mutex_exit(&of->f_mutex);
461 		break;
462 	default:
463 		mutex_exit(&of->f_mutex);
464 		return;
465 	}
466 
467 	/*
468 	 * Only one thread here (the one that that set f_state closing)
469 	 */
470 	switch (of->f_ftype) {
471 	case SMB_FTYPE_BYTE_PIPE:
472 	case SMB_FTYPE_MESG_PIPE:
473 		smb_opipe_close(of);
474 		smb_server_dec_pipes(of->f_server);
475 		break;
476 
477 	case SMB_FTYPE_DISK:
478 		if (of->dh_persist)
479 			smb2_dh_close_persistent(of);
480 		if (of->f_persistid != 0)
481 			smb_ofile_del_persistid(of);
482 		if (of->f_lease != NULL)
483 			smb2_lease_ofile_close(of);
484 		smb_oplock_break_CLOSE(of->f_node, of);
485 		/* FALLTHROUGH */
486 
487 	case SMB_FTYPE_PRINTER: /* or FTYPE_DISK */
488 		/*
489 		 * In here we make changes to of->f_pending_attr
490 		 * while not holding of->f_mutex.  This is OK
491 		 * because we've changed f_state to CLOSING,
492 		 * so no more threads will take this path.
493 		 */
494 		pa = &of->f_pending_attr;
495 		if (mtime_sec != 0) {
496 			pa->sa_vattr.va_mtime.tv_sec = mtime_sec;
497 			pa->sa_mask |= SMB_AT_MTIME;
498 		}
499 
500 		if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) {
501 			/* We delete using the on-disk name. */
502 			uint32_t flags = SMB_CASE_SENSITIVE;
503 			(void) smb_node_set_delete_on_close(of->f_node,
504 			    of->f_cr, flags);
505 		}
506 		smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid);
507 		smb_node_destroy_lock_by_ofile(of->f_node, of);
508 
509 		if (smb_node_is_file(of->f_node)) {
510 			(void) smb_fsop_close(of->f_node, of->f_mode,
511 			    of->f_cr);
512 		} else {
513 			/*
514 			 * If there was an odir, close it.
515 			 */
516 			if (of->f_odir != NULL)
517 				smb_odir_close(of->f_odir);
518 			/*
519 			 * Cancel any notify change requests that
520 			 * might be watching this open file (dir),
521 			 * and unsubscribe it from node events.
522 			 *
523 			 * Can't hold f_mutex when calling smb_notify_ofile.
524 			 * Don't really need it when unsubscribing, but
525 			 * harmless, and consistent with subscribing.
526 			 */
527 			if (of->f_notify.nc_subscribed)
528 				smb_notify_ofile(of,
529 				    FILE_ACTION_HANDLE_CLOSED, NULL);
530 			mutex_enter(&of->f_mutex);
531 			if (of->f_notify.nc_subscribed) {
532 				of->f_notify.nc_subscribed = B_FALSE;
533 				smb_node_fcn_unsubscribe(of->f_node);
534 				of->f_notify.nc_filter = 0;
535 			}
536 			mutex_exit(&of->f_mutex);
537 		}
538 		if (smb_node_dec_open_ofiles(of->f_node) == 0) {
539 			/*
540 			 * Last close.  If we're not deleting
541 			 * the file, apply any pending attrs.
542 			 * Leave allocsz zero when no open files,
543 			 * just to avoid confusion, because it's
544 			 * only updated when there are opens.
545 			 * XXX: Just do this on _every_ close.
546 			 */
547 			mutex_enter(&of->f_node->n_mutex);
548 			if (of->f_node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
549 				smb_node_delete_on_close(of->f_node);
550 				pa->sa_mask = 0;
551 			}
552 			of->f_node->n_allocsz = 0;
553 			mutex_exit(&of->f_node->n_mutex);
554 		}
555 		if (pa->sa_mask != 0) {
556 			/*
557 			 * Commit any pending attributes from
558 			 * the ofile we're closing.  Note that
559 			 * we pass NULL as the ofile to setattr
560 			 * so it will write to the file system
561 			 * and not keep anything on the ofile.
562 			 */
563 			(void) smb_node_setattr(NULL, of->f_node,
564 			    of->f_cr, NULL, pa);
565 		}
566 
567 		smb_server_dec_files(of->f_server);
568 		break;
569 	}
570 
571 	/*
572 	 * Keep f_state == SMB_OFILE_STATE_CLOSING
573 	 * until the last ref. is dropped, in
574 	 * smb_ofile_release()
575 	 */
576 }
577 
578 /*
579  * "Destructor" function for smb_ofile_close_all, and
580  * smb_ofile_close_all_by_pid, called after the llist lock
581  * for tree list has been exited.  Our job is to either
582  * close this ofile, or (if durable) set state _SAVE_DH.
583  *
584  * The next interesting thing happens when the last ref.
585  * on this ofile calls smb_ofile_release(), where we
586  * eihter delete the ofile, or (if durable) leave it
587  * in the persistid hash table for possible reclaim.
588  *
589  * This is run via smb_llist_post (after smb_llist_exit)
590  * because smb_ofile_close can block, and we'd rather not
591  * block while holding the ofile list as reader.
592  */
593 static void
594 smb_ofile_drop(void *arg)
595 {
596 	smb_ofile_t	*of = arg;
597 
598 	SMB_OFILE_VALID(of);
599 
600 	mutex_enter(&of->f_mutex);
601 	switch (of->f_state) {
602 	case SMB_OFILE_STATE_OPEN:
603 		/* DH checks under mutex. */
604 		if (of->f_ftype == SMB_FTYPE_DISK &&
605 		    of->dh_vers != SMB2_NOT_DURABLE &&
606 		    smb_dh_should_save(of)) {
607 			/*
608 			 * Tell smb_ofile_release() to
609 			 * make this an _ORPHANED DH.
610 			 */
611 			of->f_state = SMB_OFILE_STATE_SAVE_DH;
612 			mutex_exit(&of->f_mutex);
613 			break;
614 		}
615 		/* OK close it. */
616 		mutex_exit(&of->f_mutex);
617 		smb_ofile_close(of, 0);
618 		break;
619 
620 	default:
621 		/* Something else closed it already. */
622 		mutex_exit(&of->f_mutex);
623 		break;
624 	}
625 
626 	/*
627 	 * Release the ref acquired during the traversal loop.
628 	 * Note that on the last ref, this ofile will be
629 	 * removed from the tree list etc.
630 	 * See: smb_llist_post, smb_ofile_delete
631 	 */
632 	smb_ofile_release(of);
633 }
634 
635 /*
636  * smb_ofile_close_all
637  *
638  *
639  */
640 void
641 smb_ofile_close_all(
642     smb_tree_t		*tree,
643     uint32_t		pid)
644 {
645 	smb_ofile_t	*of;
646 	smb_llist_t	*ll;
647 
648 	ASSERT(tree);
649 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
650 
651 	ll = &tree->t_ofile_list;
652 
653 	smb_llist_enter(ll, RW_READER);
654 	for (of = smb_llist_head(ll);
655 	    of != NULL;
656 	    of = smb_llist_next(ll, of)) {
657 		ASSERT(of->f_magic == SMB_OFILE_MAGIC);
658 		ASSERT(of->f_tree == tree);
659 		if (pid != 0 && of->f_opened_by_pid != pid)
660 			continue;
661 		if (smb_ofile_hold(of)) {
662 			smb_llist_post(ll, of, smb_ofile_drop);
663 		}
664 	}
665 
666 	/*
667 	 * Drop the lock and process the llist dtor queue.
668 	 * Calls smb_ofile_drop on ofiles that were open.
669 	 */
670 	smb_llist_exit(ll);
671 }
672 
673 /*
674  * If the enumeration request is for ofile data, handle it here.
675  * Otherwise, return.
676  *
677  * This function should be called with a hold on the ofile.
678  */
679 int
680 smb_ofile_enum(smb_ofile_t *of, smb_svcenum_t *svcenum)
681 {
682 	uint8_t *pb;
683 	uint_t nbytes;
684 	int rc;
685 
686 	ASSERT(of);
687 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
688 	ASSERT(of->f_refcnt);
689 
690 	if (svcenum->se_type != SMB_SVCENUM_TYPE_FILE)
691 		return (0);
692 
693 	if (svcenum->se_nskip > 0) {
694 		svcenum->se_nskip--;
695 		return (0);
696 	}
697 
698 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
699 		svcenum->se_nitems = svcenum->se_nlimit;
700 		return (0);
701 	}
702 
703 	pb = &svcenum->se_buf[svcenum->se_bused];
704 
705 	rc = smb_ofile_netinfo_encode(of, pb, svcenum->se_bavail,
706 	    &nbytes);
707 	if (rc == 0) {
708 		svcenum->se_bavail -= nbytes;
709 		svcenum->se_bused += nbytes;
710 		svcenum->se_nitems++;
711 	}
712 
713 	return (rc);
714 }
715 
716 /*
717  * Take a reference on an open file, in any of the states:
718  *   RECONNECT, SAVE_DH, OPEN, ORPHANED.
719  * Return TRUE if ref taken.  Used for oplock breaks.
720  *
721  * Note: When the oplock break code calls this, it holds the
722  * node ofile list lock and node oplock mutex.  When we see
723  * an ofile in states RECONNECT or SAVING, we know the ofile
724  * is gaining or losing it's tree, and that happens quickly,
725  * so we just wait for that work to finish.  However, the
726  * waiting for state transitions here means we have to be
727  * careful not to re-enter the node list lock or otherwise
728  * block on things that could cause a deadlock.  Waiting
729  * just on of->f_mutex here is OK.
730  */
731 boolean_t
732 smb_ofile_hold_olbrk(smb_ofile_t *of)
733 {
734 	boolean_t ret = B_FALSE;
735 
736 	ASSERT(of);
737 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
738 
739 	mutex_enter(&of->f_mutex);
740 
741 again:
742 	switch (of->f_state) {
743 	case SMB_OFILE_STATE_RECONNECT:
744 	case SMB_OFILE_STATE_SAVING:
745 		cv_wait(&of->f_cv, &of->f_mutex);
746 		goto again;
747 
748 	case SMB_OFILE_STATE_OPEN:
749 	case SMB_OFILE_STATE_ORPHANED:
750 	case SMB_OFILE_STATE_SAVE_DH:
751 		of->f_refcnt++;
752 		ret = B_TRUE;
753 		break;
754 
755 	default:
756 		break;
757 	}
758 	mutex_exit(&of->f_mutex);
759 
760 	return (ret);
761 }
762 
763 /*
764  * Take a reference on an open file.
765  */
766 boolean_t
767 smb_ofile_hold(smb_ofile_t *of)
768 {
769 	ASSERT(of);
770 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
771 
772 	mutex_enter(&of->f_mutex);
773 
774 	if (of->f_state != SMB_OFILE_STATE_OPEN) {
775 		mutex_exit(&of->f_mutex);
776 		return (B_FALSE);
777 	}
778 	of->f_refcnt++;
779 
780 	mutex_exit(&of->f_mutex);
781 	return (B_TRUE);
782 }
783 
784 /*
785  * Release a reference on a file.  If the reference count falls to
786  * zero and the file has been closed, post the object for deletion.
787  * Object deletion is deferred to avoid modifying a list while an
788  * iteration may be in progress.
789  *
790  * We're careful to avoid dropping f_session etc. until the last
791  * reference goes away.  The oplock break code depends on that
792  * not changing while it holds a ref. on an ofile.
793  */
794 void
795 smb_ofile_release(smb_ofile_t *of)
796 {
797 	smb_tree_t *tree = of->f_tree;
798 	boolean_t delete = B_FALSE;
799 
800 	SMB_OFILE_VALID(of);
801 
802 	mutex_enter(&of->f_mutex);
803 	ASSERT(of->f_refcnt > 0);
804 	of->f_refcnt--;
805 
806 	switch (of->f_state) {
807 	case SMB_OFILE_STATE_OPEN:
808 	case SMB_OFILE_STATE_ORPHANED:
809 	case SMB_OFILE_STATE_EXPIRED:
810 		break;
811 
812 	case SMB_OFILE_STATE_SAVE_DH:
813 		ASSERT(tree != NULL);
814 		if (of->f_refcnt == 0) {
815 			of->f_state = SMB_OFILE_STATE_SAVING;
816 			smb_llist_post(&tree->t_ofile_list, of,
817 			    smb_ofile_save_dh);
818 		}
819 		break;
820 
821 	case SMB_OFILE_STATE_CLOSING:
822 		/* Note, tree == NULL on _ORPHANED */
823 		if (of->f_refcnt == 0) {
824 			of->f_state = SMB_OFILE_STATE_CLOSED;
825 			if (tree == NULL) {
826 				/* Skip smb_llist_post */
827 				delete = B_TRUE;
828 				break;
829 			}
830 			smb_llist_post(&tree->t_ofile_list, of,
831 			    smb_ofile_delete);
832 		}
833 		break;
834 
835 	default:
836 		ASSERT(0);
837 		break;
838 	}
839 	mutex_exit(&of->f_mutex);
840 
841 	/*
842 	 * When we drop the last ref. on an expired DH, it's no longer
843 	 * in any tree, so skip the smb_llist_post and just call
844 	 * smb_ofile_delete directly.
845 	 */
846 	if (delete) {
847 		smb_ofile_delete(of);
848 	}
849 }
850 
851 /*
852  * smb_ofile_lookup_by_fid
853  *
854  * Find the open file whose fid matches the one specified in the request.
855  * If we can't find the fid or the shares (trees) don't match, we have a
856  * bad fid.
857  */
858 smb_ofile_t *
859 smb_ofile_lookup_by_fid(
860     smb_request_t	*sr,
861     uint16_t		fid)
862 {
863 	smb_tree_t	*tree = sr->tid_tree;
864 	smb_llist_t	*of_list;
865 	smb_ofile_t	*of;
866 
867 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
868 
869 	of_list = &tree->t_ofile_list;
870 
871 	smb_llist_enter(of_list, RW_READER);
872 	of = smb_llist_head(of_list);
873 	while (of) {
874 		ASSERT(of->f_magic == SMB_OFILE_MAGIC);
875 		ASSERT(of->f_tree == tree);
876 		if (of->f_fid == fid)
877 			break;
878 		of = smb_llist_next(of_list, of);
879 	}
880 	if (of == NULL)
881 		goto out;
882 
883 	/*
884 	 * Only allow use of a given FID with the same UID that
885 	 * was used to open it.  MS-CIFS 3.3.5.14
886 	 */
887 	if (of->f_user != sr->uid_user) {
888 		of = NULL;
889 		goto out;
890 	}
891 
892 	/* inline smb_ofile_hold() */
893 	mutex_enter(&of->f_mutex);
894 	if (of->f_state != SMB_OFILE_STATE_OPEN) {
895 		mutex_exit(&of->f_mutex);
896 		of = NULL;
897 		goto out;
898 	}
899 	of->f_refcnt++;
900 	mutex_exit(&of->f_mutex);
901 
902 out:
903 	smb_llist_exit(of_list);
904 	return (of);
905 }
906 
907 /*
908  * smb_ofile_lookup_by_uniqid
909  *
910  * Find the open file whose uniqid matches the one specified in the request.
911  */
912 smb_ofile_t *
913 smb_ofile_lookup_by_uniqid(smb_tree_t *tree, uint32_t uniqid)
914 {
915 	smb_llist_t	*of_list;
916 	smb_ofile_t	*of;
917 
918 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
919 
920 	of_list = &tree->t_ofile_list;
921 	smb_llist_enter(of_list, RW_READER);
922 	of = smb_llist_head(of_list);
923 
924 	while (of) {
925 		ASSERT(of->f_magic == SMB_OFILE_MAGIC);
926 		ASSERT(of->f_tree == tree);
927 
928 		if (of->f_uniqid == uniqid) {
929 			if (smb_ofile_hold(of)) {
930 				smb_llist_exit(of_list);
931 				return (of);
932 			}
933 		}
934 
935 		of = smb_llist_next(of_list, of);
936 	}
937 
938 	smb_llist_exit(of_list);
939 	return (NULL);
940 }
941 
942 /*
943  * Durable ID (or persistent ID)
944  */
945 
946 static smb_ofile_t *
947 smb_ofile_hold_cb(smb_ofile_t *of)
948 {
949 	smb_ofile_t *ret = of;
950 
951 	mutex_enter(&of->f_mutex);
952 	if (of->f_state == SMB_OFILE_STATE_ORPHANED)
953 		/* inline smb_ofile_hold() */
954 		of->f_refcnt++;
955 	else
956 		ret = NULL;
957 
958 	mutex_exit(&of->f_mutex);
959 	return (ret);
960 }
961 
962 /*
963  * Lookup an ofile by persistent ID, and return ONLY if in state ORPHANED
964  * This is used by SMB2 create "reclaim".
965  */
966 smb_ofile_t *
967 smb_ofile_lookup_by_persistid(smb_request_t *sr, uint64_t persistid)
968 {
969 	smb_hash_t *hash;
970 	smb_bucket_t *bucket;
971 	smb_llist_t *ll;
972 	smb_ofile_t *of;
973 	uint_t idx;
974 
975 	if (persistid == 0)
976 		return (NULL);
977 
978 	hash = sr->sr_server->sv_persistid_ht;
979 	idx = smb_hash_uint64(hash, persistid);
980 	bucket = &hash->buckets[idx];
981 	ll = &bucket->b_list;
982 
983 	smb_llist_enter(ll, RW_READER);
984 	of = smb_llist_head(ll);
985 	while (of != NULL) {
986 		if (of->f_persistid == persistid)
987 			break;
988 		of = smb_llist_next(ll, of);
989 	}
990 	if (of != NULL)
991 		of = smb_ofile_hold_cb(of);
992 	smb_llist_exit(ll);
993 
994 	return (of);
995 }
996 
997 /*
998  * Create a (unique) durable/persistent ID for a new ofile,
999  * and add this ofile to the persistid hash table.  This ID
1000  * is referred to as the persistent ID in the protocol spec,
1001  * so that's what we call it too, though the persistence may
1002  * vary.  "Durable" handles are persistent across reconnects
1003  * but not server reboots.  Persistent handles are persistent
1004  * across server reboots too.
1005  *
1006  * Note that persistent IDs need to be unique for the lifetime of
1007  * any given ofile.  For normal (non-persistent) ofiles we can just
1008  * use a persistent ID derived from the ofile memory address, as
1009  * these don't ever live beyond the current OS boot lifetime.
1010  *
1011  * Persistent handles are re-imported after server restart, and
1012  * generally have a different memory address after import than
1013  * they had in the previous OS boot lifetime, so for these we
1014  * use a randomly assigned value that won't conflict with any
1015  * non-persistent (durable) handles.  Ensuring that a randomly
1016  * generated ID is unique requires a search of the ofiles in one
1017  * hash bucket, which we'd rather avoid for non-persistent opens.
1018  *
1019  * The solution used here is to divide the persistent ID space
1020  * in half (odd and even values) where durable opens use an ID
1021  * derived from the ofile address (which is always even), and
1022  * persistent opens use an ID generated randomly (always odd).
1023  *
1024  * smb_ofile_set_persistid_dh() sets a durable handle ID and
1025  * smb_ofile_set_persistid_ph() sets a persistent handle ID.
1026  */
1027 void
1028 smb_ofile_set_persistid_dh(smb_ofile_t *of)
1029 {
1030 	smb_hash_t *hash = of->f_server->sv_persistid_ht;
1031 	smb_bucket_t *bucket;
1032 	smb_llist_t *ll;
1033 	uint64_t persistid;
1034 	uint_t idx;
1035 
1036 	persistid = (uintptr_t)of;
1037 	/* Avoid showing object addresses */
1038 	persistid ^= ((uintptr_t)&smb_cache_ofile);
1039 	/* make sure it's even */
1040 	persistid &= ~((uint64_t)1);
1041 
1042 	idx = smb_hash_uint64(hash, persistid);
1043 	bucket = &hash->buckets[idx];
1044 	ll = &bucket->b_list;
1045 	smb_llist_enter(ll, RW_WRITER);
1046 	if (of->f_persistid == 0) {
1047 		of->f_persistid = persistid;
1048 		smb_llist_insert_tail(ll, of);
1049 	}
1050 	smb_llist_exit(ll);
1051 }
1052 
1053 void
1054 smb_ofile_set_persistid_ph(smb_ofile_t *of)
1055 {
1056 	uint64_t persistid;
1057 	int rc;
1058 
1059 top:
1060 	(void) random_get_pseudo_bytes((uint8_t *)&persistid,
1061 	    sizeof (persistid));
1062 	if (persistid == 0) {
1063 		cmn_err(CE_NOTE, "random gave all zeros!");
1064 		goto top;
1065 	}
1066 	/* make sure it's odd */
1067 	persistid |= (uint64_t)1;
1068 
1069 	/*
1070 	 * Try inserting with this persistent ID.
1071 	 */
1072 	rc = smb_ofile_insert_persistid(of, persistid);
1073 	if (rc == EEXIST)
1074 		goto top;
1075 	if (rc != 0) {
1076 		cmn_err(CE_NOTE, "set persistid rc=%d", rc);
1077 	}
1078 }
1079 
1080 /*
1081  * Insert an ofile into the persistid hash table.
1082  * If the persistent ID is in use, error.
1083  */
1084 int
1085 smb_ofile_insert_persistid(smb_ofile_t *new_of, uint64_t persistid)
1086 {
1087 	smb_hash_t *hash = new_of->f_server->sv_persistid_ht;
1088 	smb_bucket_t *bucket;
1089 	smb_llist_t *ll;
1090 	smb_ofile_t *of;
1091 	uint_t idx;
1092 
1093 	ASSERT(persistid != 0);
1094 
1095 	/*
1096 	 * Look to see if this key alreay exists.
1097 	 */
1098 	idx = smb_hash_uint64(hash, persistid);
1099 	bucket = &hash->buckets[idx];
1100 	ll = &bucket->b_list;
1101 
1102 	smb_llist_enter(ll, RW_WRITER);
1103 	of = smb_llist_head(ll);
1104 	while (of != NULL) {
1105 		if (of->f_persistid == persistid) {
1106 			/* already in use */
1107 			smb_llist_exit(ll);
1108 			return (EEXIST);
1109 		}
1110 		of = smb_llist_next(ll, of);
1111 	}
1112 
1113 	/* Not found, so OK to insert. */
1114 	if (new_of->f_persistid == 0) {
1115 		new_of->f_persistid = persistid;
1116 		smb_llist_insert_tail(ll, new_of);
1117 	}
1118 	smb_llist_exit(ll);
1119 
1120 	return (0);
1121 }
1122 
1123 void
1124 smb_ofile_del_persistid(smb_ofile_t *of)
1125 {
1126 	smb_hash_t *hash = of->f_server->sv_persistid_ht;
1127 	smb_bucket_t *bucket;
1128 	smb_llist_t *ll;
1129 	uint_t idx;
1130 
1131 	idx = smb_hash_uint64(hash, of->f_persistid);
1132 	bucket = &hash->buckets[idx];
1133 	ll = &bucket->b_list;
1134 	smb_llist_enter(ll, RW_WRITER);
1135 	if (of->f_persistid != 0) {
1136 		smb_llist_remove(ll, of);
1137 		of->f_persistid = 0;
1138 	}
1139 	smb_llist_exit(ll);
1140 }
1141 
1142 /*
1143  * Disallow NetFileClose on certain ofiles to avoid side-effects.
1144  * Closing a tree root is not allowed: use NetSessionDel or NetShareDel.
1145  * Closing SRVSVC connections is not allowed because this NetFileClose
1146  * request may depend on this ofile.
1147  */
1148 boolean_t
1149 smb_ofile_disallow_fclose(smb_ofile_t *of)
1150 {
1151 	ASSERT(of);
1152 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1153 	ASSERT(of->f_refcnt);
1154 
1155 	switch (of->f_ftype) {
1156 	case SMB_FTYPE_DISK:
1157 		ASSERT(of->f_tree);
1158 		return (of->f_node == of->f_tree->t_snode);
1159 
1160 	case SMB_FTYPE_MESG_PIPE:
1161 		ASSERT(of->f_pipe);
1162 		if (smb_strcasecmp(of->f_pipe->p_name, "SRVSVC", 0) == 0)
1163 			return (B_TRUE);
1164 		break;
1165 	default:
1166 		break;
1167 	}
1168 
1169 	return (B_FALSE);
1170 }
1171 
1172 /*
1173  * smb_ofile_set_flags
1174  *
1175  * Return value:
1176  *
1177  *	Current flags value
1178  *
1179  */
1180 void
1181 smb_ofile_set_flags(
1182     smb_ofile_t		*of,
1183     uint32_t		flags)
1184 {
1185 	ASSERT(of);
1186 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1187 	ASSERT(of->f_refcnt);
1188 
1189 	mutex_enter(&of->f_mutex);
1190 	of->f_flags |= flags;
1191 	mutex_exit(&of->f_mutex);
1192 }
1193 
1194 /*
1195  * smb_ofile_seek
1196  *
1197  * Return value:
1198  *
1199  *	0		Success
1200  *	EINVAL		Unknown mode
1201  *	EOVERFLOW	offset too big
1202  *
1203  */
1204 int
1205 smb_ofile_seek(
1206     smb_ofile_t		*of,
1207     ushort_t		mode,
1208     int32_t		off,
1209     uint32_t		*retoff)
1210 {
1211 	u_offset_t	newoff = 0;
1212 	int		rc = 0;
1213 	smb_attr_t	attr;
1214 
1215 	ASSERT(of);
1216 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1217 	ASSERT(of->f_refcnt);
1218 
1219 	mutex_enter(&of->f_mutex);
1220 	switch (mode) {
1221 	case SMB_SEEK_SET:
1222 		if (off < 0)
1223 			newoff = 0;
1224 		else
1225 			newoff = (u_offset_t)off;
1226 		break;
1227 
1228 	case SMB_SEEK_CUR:
1229 		if (off < 0 && (-off) > of->f_seek_pos)
1230 			newoff = 0;
1231 		else
1232 			newoff = of->f_seek_pos + (u_offset_t)off;
1233 		break;
1234 
1235 	case SMB_SEEK_END:
1236 		bzero(&attr, sizeof (smb_attr_t));
1237 		attr.sa_mask |= SMB_AT_SIZE;
1238 		rc = smb_fsop_getattr(NULL, zone_kcred(), of->f_node, &attr);
1239 		if (rc != 0) {
1240 			mutex_exit(&of->f_mutex);
1241 			return (rc);
1242 		}
1243 		if (off < 0 && (-off) > attr.sa_vattr.va_size)
1244 			newoff = 0;
1245 		else
1246 			newoff = attr.sa_vattr.va_size + (u_offset_t)off;
1247 		break;
1248 
1249 	default:
1250 		mutex_exit(&of->f_mutex);
1251 		return (EINVAL);
1252 	}
1253 
1254 	/*
1255 	 * See comments at the beginning of smb_seek.c.
1256 	 * If the offset is greater than UINT_MAX, we will return an error.
1257 	 */
1258 
1259 	if (newoff > UINT_MAX) {
1260 		rc = EOVERFLOW;
1261 	} else {
1262 		of->f_seek_pos = newoff;
1263 		*retoff = (uint32_t)newoff;
1264 	}
1265 	mutex_exit(&of->f_mutex);
1266 	return (rc);
1267 }
1268 
1269 /*
1270  * smb_ofile_flush
1271  *
1272  * If writes on this file are not synchronous, flush it using the NFSv3
1273  * commit interface.
1274  *
1275  * XXX - todo: Flush named pipe should drain writes.
1276  */
1277 void
1278 smb_ofile_flush(struct smb_request *sr, struct smb_ofile *of)
1279 {
1280 	switch (of->f_ftype) {
1281 	case SMB_FTYPE_DISK:
1282 		if ((of->f_node->flags & NODE_FLAGS_WRITE_THROUGH) == 0)
1283 			(void) smb_fsop_commit(sr, of->f_cr, of->f_node);
1284 		break;
1285 	default:
1286 		break;
1287 	}
1288 }
1289 
1290 /*
1291  * smb_ofile_is_open
1292  */
1293 boolean_t
1294 smb_ofile_is_open(smb_ofile_t *of)
1295 {
1296 	boolean_t	rc;
1297 
1298 	SMB_OFILE_VALID(of);
1299 
1300 	mutex_enter(&of->f_mutex);
1301 	rc = smb_ofile_is_open_locked(of);
1302 	mutex_exit(&of->f_mutex);
1303 	return (rc);
1304 }
1305 
1306 /* *************************** Static Functions ***************************** */
1307 
1308 /*
1309  * Determine whether or not an ofile is open.
1310  * This function must be called with the mutex held.
1311  */
1312 static boolean_t
1313 smb_ofile_is_open_locked(smb_ofile_t *of)
1314 {
1315 	ASSERT(MUTEX_HELD(&of->f_mutex));
1316 
1317 	switch (of->f_state) {
1318 	case SMB_OFILE_STATE_OPEN:
1319 	case SMB_OFILE_STATE_SAVE_DH:
1320 	case SMB_OFILE_STATE_SAVING:
1321 	case SMB_OFILE_STATE_ORPHANED:
1322 	case SMB_OFILE_STATE_RECONNECT:
1323 		return (B_TRUE);
1324 
1325 	case SMB_OFILE_STATE_CLOSING:
1326 	case SMB_OFILE_STATE_CLOSED:
1327 	case SMB_OFILE_STATE_EXPIRED:
1328 		return (B_FALSE);
1329 
1330 	default:
1331 		ASSERT(0);
1332 		return (B_FALSE);
1333 	}
1334 }
1335 
1336 /*
1337  * smb_ofile_save_dh
1338  *
1339  * Called via smb_llist_post (after smb_llist_exit) when the last ref.
1340  * on this ofile has gone, and this ofile is a "durable handle" (DH)
1341  * that has state we've decided to save.
1342  *
1343  * This does parts of what smb_ofile_delete would do, including:
1344  * remove the ofile from the tree ofile list and related.
1345  *
1346  * We leave the ofile in state ORPHANED, ready for reconnect
1347  * or expiration via smb2_dh_expire (see smb_ofile_delete).
1348  */
1349 static void
1350 smb_ofile_save_dh(void *arg)
1351 {
1352 	smb_ofile_t	*of = (smb_ofile_t *)arg;
1353 	smb_tree_t	*tree = of->f_tree;
1354 
1355 	SMB_OFILE_VALID(of);
1356 	ASSERT(of->f_refcnt == 0);
1357 	ASSERT(of->f_ftype == SMB_FTYPE_DISK);
1358 	ASSERT(of->f_state == SMB_OFILE_STATE_SAVING);
1359 
1360 	atomic_dec_32(&of->f_session->s_file_cnt);
1361 	atomic_dec_32(&of->f_tree->t_open_files);
1362 	smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
1363 	smb_llist_remove(&tree->t_ofile_list, of);
1364 	smb_llist_exit(&tree->t_ofile_list);
1365 
1366 	/*
1367 	 * This ofile is no longer on t_ofile_list, however...
1368 	 *
1369 	 * This is called via smb_llist_post, which means it may run
1370 	 * BEFORE smb_ofile_release drops f_mutex (if another thread
1371 	 * flushes the delete queue before we do).  Synchronize.
1372 	 */
1373 	mutex_enter(&of->f_mutex);
1374 	DTRACE_PROBE1(ofile__exit, smb_ofile_t, of);
1375 	mutex_exit(&of->f_mutex);
1376 
1377 	/*
1378 	 * Keep f_notify state, lease, and
1379 	 * keep on node ofile list.
1380 	 * Keep of->f_cr until reclaim.
1381 	 */
1382 
1383 	ASSERT(of->f_fid != 0);
1384 	smb_idpool_free(&tree->t_fid_pool, of->f_fid);
1385 	of->f_fid = 0;
1386 	smb_tree_release(of->f_tree);
1387 	of->f_tree = NULL;
1388 	smb_user_release(of->f_user);
1389 	of->f_user = NULL;
1390 	of->f_session = NULL;
1391 
1392 	/*
1393 	 * Make it "orphaned" so it can now be reclaimed.
1394 	 * Note that smb_ofile_hold_olbrk() may have blocked
1395 	 * for state SMB_OFILE_STATE_SAVING, so wake it.
1396 	 */
1397 	mutex_enter(&of->f_mutex);
1398 	of->dh_expire_time = gethrtime() + of->dh_timeout_offset;
1399 	of->f_state = SMB_OFILE_STATE_ORPHANED;
1400 	cv_broadcast(&of->f_cv);
1401 	mutex_exit(&of->f_mutex);
1402 }
1403 
1404 /*
1405  * Delete an ofile.
1406  *
1407  * Approximately the inverse of smb_ofile_alloc()
1408  * Called via smb_llist_post (after smb_llist_exit)
1409  * when the last ref. on this ofile has gone.
1410  *
1411  * Normally,this removes the ofile from the tree list and
1412  * then frees resources held on the ofile.  However, when
1413  * we're expiring an orphaned durable handle, the linkage
1414  * into the tree lists etc. have already been destroyed.
1415  * This case is distinguished by of->f_tree == NULL.
1416  */
1417 static void
1418 smb_ofile_delete(void *arg)
1419 {
1420 	smb_ofile_t	*of = (smb_ofile_t *)arg;
1421 	smb_tree_t	*tree = of->f_tree;
1422 
1423 	SMB_OFILE_VALID(of);
1424 	ASSERT(of->f_refcnt == 0);
1425 	ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
1426 
1427 	if (tree != NULL) {
1428 		ASSERT(of->f_user != NULL);
1429 		ASSERT(of->f_session != NULL);
1430 		atomic_dec_32(&of->f_session->s_file_cnt);
1431 		atomic_dec_32(&of->f_tree->t_open_files);
1432 		smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
1433 		smb_llist_remove(&tree->t_ofile_list, of);
1434 		smb_llist_exit(&tree->t_ofile_list);
1435 	}
1436 
1437 	/*
1438 	 * Remove this ofile from the node's n_ofile_list so it
1439 	 * can't be found by list walkers like notify or oplock.
1440 	 * Keep the node ref. until later in this function so
1441 	 * of->f_node remains valid while we destroy the ofile.
1442 	 */
1443 	if (of->f_ftype == SMB_FTYPE_DISK ||
1444 	    of->f_ftype == SMB_FTYPE_PRINTER) {
1445 		ASSERT(of->f_node != NULL);
1446 		/*
1447 		 * Note smb_ofile_close did smb_node_dec_open_ofiles()
1448 		 */
1449 		smb_node_rem_ofile(of->f_node, of);
1450 	}
1451 
1452 	/*
1453 	 * This ofile is no longer on any lists, however...
1454 	 *
1455 	 * This is called via smb_llist_post, which means it may run
1456 	 * BEFORE smb_ofile_release drops f_mutex (if another thread
1457 	 * flushes the delete queue before we do).  Synchronize.
1458 	 */
1459 	mutex_enter(&of->f_mutex);
1460 	of->f_state = SMB_OFILE_STATE_ALLOC;
1461 	DTRACE_PROBE1(ofile__exit, smb_ofile_t, of);
1462 	mutex_exit(&of->f_mutex);
1463 
1464 	switch (of->f_ftype) {
1465 	case SMB_FTYPE_BYTE_PIPE:
1466 	case SMB_FTYPE_MESG_PIPE:
1467 		smb_opipe_dealloc(of->f_pipe);
1468 		of->f_pipe = NULL;
1469 		break;
1470 	case SMB_FTYPE_DISK:
1471 		ASSERT(of->f_notify.nc_subscribed == B_FALSE);
1472 		MBC_FLUSH(&of->f_notify.nc_buffer);
1473 		if (of->f_odir != NULL)
1474 			smb_odir_release(of->f_odir);
1475 		if (of->f_lease != NULL) {
1476 			smb2_lease_rele(of->f_lease);
1477 			of->f_lease = NULL;
1478 		}
1479 		/* FALLTHROUGH */
1480 	case SMB_FTYPE_PRINTER:
1481 		/*
1482 		 * Did smb_node_rem_ofile above.
1483 		 */
1484 		ASSERT(of->f_node != NULL);
1485 		smb_node_release(of->f_node);
1486 		break;
1487 	default:
1488 		ASSERT(!"f_ftype");
1489 		break;
1490 	}
1491 
1492 	smb_ofile_free(of);
1493 }
1494 
1495 void
1496 smb_ofile_free(smb_ofile_t *of)
1497 {
1498 	smb_tree_t	*tree = of->f_tree;
1499 
1500 	ASSERT(of->f_state == SMB_OFILE_STATE_ALLOC);
1501 
1502 	/* Make sure it's not in the persistid hash. */
1503 	ASSERT(of->f_persistid == 0);
1504 
1505 	if (tree != NULL) {
1506 		if (of->f_fid != 0)
1507 			smb_idpool_free(&tree->t_fid_pool, of->f_fid);
1508 		smb_tree_release(of->f_tree);
1509 		smb_user_release(of->f_user);
1510 	}
1511 
1512 	if (of->f_cr != NULL)
1513 		crfree(of->f_cr);
1514 
1515 	of->f_magic = (uint32_t)~SMB_OFILE_MAGIC;
1516 	list_destroy(&of->f_notify.nc_waiters);
1517 	mutex_destroy(&of->dh_nvlock);
1518 	mutex_destroy(&of->f_mutex);
1519 	kmem_cache_free(smb_cache_ofile, of);
1520 }
1521 
1522 /*
1523  * smb_ofile_access
1524  *
1525  * This function will check to see if the access requested is granted.
1526  * Returns NT status codes.
1527  */
1528 uint32_t
1529 smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access)
1530 {
1531 
1532 	if ((of == NULL) || (cr == zone_kcred()))
1533 		return (NT_STATUS_SUCCESS);
1534 
1535 	/*
1536 	 * If the request is for something
1537 	 * I don't grant it is an error
1538 	 */
1539 	if (~(of->f_granted_access) & access) {
1540 		if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) &&
1541 		    (access & ACCESS_SYSTEM_SECURITY)) {
1542 			return (NT_STATUS_PRIVILEGE_NOT_HELD);
1543 		}
1544 		return (NT_STATUS_ACCESS_DENIED);
1545 	}
1546 
1547 	return (NT_STATUS_SUCCESS);
1548 }
1549 
1550 /*
1551  * smb_ofile_share_check
1552  *
1553  * Check if ofile was opened with share access NONE (0).
1554  * Returns: B_TRUE  - share access non-zero
1555  *          B_FALSE - share access NONE
1556  */
1557 boolean_t
1558 smb_ofile_share_check(smb_ofile_t *of)
1559 {
1560 	return (!SMB_DENY_ALL(of->f_share_access));
1561 }
1562 
1563 /*
1564  * check file sharing rules for current open request
1565  * against existing open instances of the same file
1566  *
1567  * Returns NT_STATUS_SHARING_VIOLATION if there is any
1568  * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
1569  */
1570 uint32_t
1571 smb_ofile_open_check(smb_ofile_t *of, uint32_t desired_access,
1572     uint32_t share_access)
1573 {
1574 	uint32_t ret;
1575 
1576 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1577 
1578 	mutex_enter(&of->f_mutex);
1579 
1580 	if (!smb_ofile_is_open_locked(of)) {
1581 		ret = NT_STATUS_INVALID_HANDLE;
1582 		goto out;
1583 	}
1584 
1585 	/* if it's just meta data */
1586 	if ((of->f_granted_access & FILE_DATA_ALL) == 0) {
1587 		ret = NT_STATUS_SUCCESS;
1588 		goto out;
1589 	}
1590 
1591 	/*
1592 	 * Check requested share access against the
1593 	 * open granted (desired) access
1594 	 */
1595 	if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) {
1596 		ret = NT_STATUS_SHARING_VIOLATION;
1597 		goto out;
1598 	}
1599 
1600 	if (SMB_DENY_READ(share_access) &&
1601 	    (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) {
1602 		ret = NT_STATUS_SHARING_VIOLATION;
1603 		goto out;
1604 	}
1605 
1606 	if (SMB_DENY_WRITE(share_access) &&
1607 	    (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
1608 		ret = NT_STATUS_SHARING_VIOLATION;
1609 		goto out;
1610 	}
1611 
1612 	/* check requested desired access against the open share access */
1613 	if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) {
1614 		ret = NT_STATUS_SHARING_VIOLATION;
1615 		goto out;
1616 	}
1617 
1618 	if (SMB_DENY_READ(of->f_share_access) &&
1619 	    (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) {
1620 		ret = NT_STATUS_SHARING_VIOLATION;
1621 		goto out;
1622 	}
1623 
1624 	if (SMB_DENY_WRITE(of->f_share_access) &&
1625 	    (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
1626 		ret = NT_STATUS_SHARING_VIOLATION;
1627 		goto out;
1628 	}
1629 
1630 	ret = NT_STATUS_SUCCESS;
1631 out:
1632 	mutex_exit(&of->f_mutex);
1633 	return (ret);
1634 }
1635 
1636 /*
1637  * smb_ofile_rename_check
1638  *
1639  * This does the work described in MS-FSA 2.1.5.1.2.2 (Algorithm
1640  * to Check Sharing Access to an Existing Stream or Directory),
1641  * where the "open in-progress" has DesiredAccess = DELETE and
1642  * SharingMode = SHARE_READ | SHARE_WRITE | SHARE_DELETE.
1643  */
1644 
1645 uint32_t
1646 smb_ofile_rename_check(smb_ofile_t *of)
1647 {
1648 	uint32_t ret;
1649 
1650 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1651 
1652 	mutex_enter(&of->f_mutex);
1653 
1654 	if (!smb_ofile_is_open_locked(of)) {
1655 		ret = NT_STATUS_INVALID_HANDLE;
1656 		goto out;
1657 	}
1658 
1659 	if ((of->f_granted_access & FILE_DATA_ALL) == 0) {
1660 		ret = NT_STATUS_SUCCESS;
1661 		goto out;
1662 	}
1663 
1664 	if ((of->f_share_access & FILE_SHARE_DELETE) == 0) {
1665 		ret = NT_STATUS_SHARING_VIOLATION;
1666 		goto out;
1667 	}
1668 
1669 	ret = NT_STATUS_SUCCESS;
1670 out:
1671 	mutex_exit(&of->f_mutex);
1672 	return (ret);
1673 }
1674 
1675 /*
1676  * smb_ofile_delete_check
1677  *
1678  * An open file can be deleted only if opened for
1679  * accessing meta data. Share modes aren't important
1680  * in this case.
1681  *
1682  * NOTE: there is another mechanism for deleting an
1683  * open file that NT clients usually use.
1684  * That's setting "Delete on close" flag for an open
1685  * file.  In this way the file will be deleted after
1686  * last close. This flag can be set by SmbTrans2SetFileInfo
1687  * with FILE_DISPOSITION_INFO information level.
1688  * For setting this flag, the file should be opened by
1689  * DELETE access in the FID that is passed in the Trans2
1690  * request.
1691  */
1692 
1693 uint32_t
1694 smb_ofile_delete_check(smb_ofile_t *of)
1695 {
1696 	uint32_t ret;
1697 
1698 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1699 
1700 	mutex_enter(&of->f_mutex);
1701 
1702 	if (!smb_ofile_is_open_locked(of)) {
1703 		ret = NT_STATUS_INVALID_HANDLE;
1704 		goto out;
1705 	}
1706 
1707 	if (of->f_granted_access &
1708 	    (FILE_READ_DATA | FILE_WRITE_DATA |
1709 	    FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) {
1710 		ret = NT_STATUS_SHARING_VIOLATION;
1711 		goto out;
1712 	}
1713 
1714 	ret = NT_STATUS_SUCCESS;
1715 out:
1716 	mutex_exit(&of->f_mutex);
1717 	return (ret);
1718 }
1719 
1720 cred_t *
1721 smb_ofile_getcred(smb_ofile_t *of)
1722 {
1723 	return (of->f_cr);
1724 }
1725 
1726 /*
1727  * smb_ofile_set_delete_on_close
1728  *
1729  * Set the DeleteOnClose flag on the smb file. When the file is closed,
1730  * the flag will be transferred to the smb node, which will commit the
1731  * delete operation and inhibit subsequent open requests.
1732  *
1733  * When DeleteOnClose is set on an smb_node, the common open code will
1734  * reject subsequent open requests for the file. Observation of Windows
1735  * 2000 indicates that subsequent opens should be allowed (assuming
1736  * there would be no sharing violation) until the file is closed using
1737  * the fid on which the DeleteOnClose was requested.
1738  */
1739 void
1740 smb_ofile_set_delete_on_close(smb_request_t *sr, smb_ofile_t *of)
1741 {
1742 	uint32_t	status;
1743 
1744 	/*
1745 	 * Break any oplock handle caching.
1746 	 */
1747 	status = smb_oplock_break_SETINFO(of->f_node, of,
1748 	    FileDispositionInformation);
1749 	if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
1750 		if (sr->session->dialect >= SMB_VERS_2_BASE)
1751 			(void) smb2sr_go_async(sr);
1752 		(void) smb_oplock_wait_break(of->f_node, 0);
1753 	}
1754 
1755 	mutex_enter(&of->f_mutex);
1756 	of->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE;
1757 	mutex_exit(&of->f_mutex);
1758 }
1759 
1760 /*
1761  * Encode open file information into a buffer; needed in user space to
1762  * support RPC requests.
1763  */
1764 static int
1765 smb_ofile_netinfo_encode(smb_ofile_t *of, uint8_t *buf, size_t buflen,
1766     uint32_t *nbytes)
1767 {
1768 	smb_netfileinfo_t	fi;
1769 	int			rc;
1770 
1771 	rc = smb_ofile_netinfo_init(of, &fi);
1772 	if (rc == 0) {
1773 		rc = smb_netfileinfo_encode(&fi, buf, buflen, nbytes);
1774 		smb_ofile_netinfo_fini(&fi);
1775 	}
1776 
1777 	return (rc);
1778 }
1779 
1780 static int
1781 smb_ofile_netinfo_init(smb_ofile_t *of, smb_netfileinfo_t *fi)
1782 {
1783 	smb_user_t	*user;
1784 	smb_tree_t	*tree;
1785 	smb_node_t	*node;
1786 	char		*path;
1787 	char		*buf;
1788 	int		rc;
1789 
1790 	ASSERT(of);
1791 	user = of->f_user;
1792 	tree = of->f_tree;
1793 	ASSERT(user);
1794 	ASSERT(tree);
1795 
1796 	buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1797 
1798 	switch (of->f_ftype) {
1799 	case SMB_FTYPE_DISK:
1800 		node = of->f_node;
1801 		ASSERT(node);
1802 
1803 		fi->fi_permissions = of->f_granted_access;
1804 		fi->fi_numlocks = smb_lock_get_lock_count(node, of);
1805 
1806 		path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1807 
1808 		if (node != tree->t_snode) {
1809 			rc = smb_node_getshrpath(node, tree, path, MAXPATHLEN);
1810 			if (rc != 0)
1811 				(void) strlcpy(path, node->od_name, MAXPATHLEN);
1812 		}
1813 
1814 		(void) snprintf(buf, MAXPATHLEN, "%s:%s", tree->t_sharename,
1815 		    path);
1816 		kmem_free(path, MAXPATHLEN);
1817 		break;
1818 
1819 	case SMB_FTYPE_MESG_PIPE:
1820 		ASSERT(of->f_pipe);
1821 
1822 		fi->fi_permissions = FILE_READ_DATA | FILE_WRITE_DATA |
1823 		    FILE_EXECUTE;
1824 		fi->fi_numlocks = 0;
1825 		(void) snprintf(buf, MAXPATHLEN, "\\PIPE\\%s",
1826 		    of->f_pipe->p_name);
1827 		break;
1828 
1829 	default:
1830 		kmem_free(buf, MAXPATHLEN);
1831 		return (-1);
1832 	}
1833 
1834 	fi->fi_fid = of->f_fid;
1835 	fi->fi_uniqid = of->f_uniqid;
1836 	fi->fi_pathlen = strlen(buf) + 1;
1837 	fi->fi_path = smb_mem_strdup(buf);
1838 	kmem_free(buf, MAXPATHLEN);
1839 
1840 	fi->fi_namelen = user->u_domain_len + user->u_name_len + 2;
1841 	fi->fi_username = kmem_alloc(fi->fi_namelen, KM_SLEEP);
1842 	(void) snprintf(fi->fi_username, fi->fi_namelen, "%s\\%s",
1843 	    user->u_domain, user->u_name);
1844 	return (0);
1845 }
1846 
1847 static void
1848 smb_ofile_netinfo_fini(smb_netfileinfo_t *fi)
1849 {
1850 	if (fi == NULL)
1851 		return;
1852 
1853 	if (fi->fi_path)
1854 		smb_mem_free(fi->fi_path);
1855 	if (fi->fi_username)
1856 		kmem_free(fi->fi_username, fi->fi_namelen);
1857 
1858 	bzero(fi, sizeof (smb_netfileinfo_t));
1859 }
1860 
1861 /*
1862  * A query of user and group quotas may span multiple requests.
1863  * f_quota_resume is used to determine where the query should
1864  * be resumed, in a subsequent request. f_quota_resume contains
1865  * the SID of the last quota entry returned to the client.
1866  */
1867 void
1868 smb_ofile_set_quota_resume(smb_ofile_t *ofile, char *resume)
1869 {
1870 	ASSERT(ofile);
1871 	mutex_enter(&ofile->f_mutex);
1872 	if (resume == NULL)
1873 		bzero(ofile->f_quota_resume, SMB_SID_STRSZ);
1874 	else
1875 		(void) strlcpy(ofile->f_quota_resume, resume, SMB_SID_STRSZ);
1876 	mutex_exit(&ofile->f_mutex);
1877 }
1878 
1879 void
1880 smb_ofile_get_quota_resume(smb_ofile_t *ofile, char *buf, int bufsize)
1881 {
1882 	ASSERT(ofile);
1883 	mutex_enter(&ofile->f_mutex);
1884 	(void) strlcpy(buf, ofile->f_quota_resume, bufsize);
1885 	mutex_exit(&ofile->f_mutex);
1886 }
1887