xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_ofile.c (revision 37b221f0ca7d390480c67caa3db64384a2b81406)
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 2018 Nexenta Systems, 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 
284 /* XXX: May need to actually assign GUIDs for these. */
285 /* Don't leak object addresses */
286 #define	SMB_OFILE_PERSISTID(of) \
287 	((uintptr_t)&smb_cache_ofile ^ (uintptr_t)(of))
288 
289 static boolean_t smb_ofile_is_open_locked(smb_ofile_t *);
290 static void smb_ofile_delete(void *arg);
291 static void smb_ofile_save_dh(void *arg);
292 
293 static int smb_ofile_netinfo_encode(smb_ofile_t *, uint8_t *, size_t,
294     uint32_t *);
295 static int smb_ofile_netinfo_init(smb_ofile_t *, smb_netfileinfo_t *);
296 static void smb_ofile_netinfo_fini(smb_netfileinfo_t *);
297 
298 /*
299  * smb_ofile_alloc
300  * Allocate an ofile and fill in it's "up" pointers, but
301  * do NOT link it into the tree's list of ofiles or the
302  * node's list of ofiles.  An ofile in this state is a
303  * "proposed" open passed to the oplock break code.
304  *
305  * If we don't get as far as smb_ofile_open with this OF,
306  * call smb_ofile_free() to free this object.
307  */
308 smb_ofile_t *
309 smb_ofile_alloc(
310     smb_request_t	*sr,
311     smb_arg_open_t	*op,
312     smb_node_t		*node, /* optional (may be NULL) */
313     uint16_t		ftype,
314     uint16_t		tree_fid,
315     uint32_t		uniqid)
316 {
317 	smb_tree_t	*tree = sr->tid_tree;
318 	smb_ofile_t	*of;
319 
320 	of = kmem_cache_alloc(smb_cache_ofile, KM_SLEEP);
321 	bzero(of, sizeof (smb_ofile_t));
322 	of->f_magic = SMB_OFILE_MAGIC;
323 
324 	mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL);
325 	list_create(&of->f_notify.nc_waiters, sizeof (smb_request_t),
326 	    offsetof(smb_request_t, sr_waiters));
327 
328 	of->f_state = SMB_OFILE_STATE_ALLOC;
329 	of->f_refcnt = 1;
330 	of->f_ftype = ftype;
331 	of->f_fid = tree_fid;
332 	/* of->f_persistid see smb2_create */
333 	of->f_uniqid = uniqid;
334 	of->f_opened_by_pid = sr->smb_pid;
335 	of->f_granted_access = op->desired_access;
336 	of->f_share_access = op->share_access;
337 	of->f_create_options = op->create_options;
338 	of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ?
339 	    smb_user_getprivcred(sr->uid_user) : sr->uid_user->u_cred;
340 	crhold(of->f_cr);
341 	of->f_server = tree->t_server;
342 	of->f_session = tree->t_session;
343 	(void) memset(of->f_lock_seq, -1, SMB_OFILE_LSEQ_MAX);
344 
345 	of->f_mode = smb_fsop_amask_to_omode(of->f_granted_access);
346 	if ((of->f_granted_access & FILE_DATA_ALL) == FILE_EXECUTE)
347 		of->f_flags |= SMB_OFLAGS_EXECONLY;
348 
349 	/*
350 	 * In case a lease is requested, copy the lease keys now so
351 	 * any oplock breaks during open don't break those on our
352 	 * other handles that might have the same lease.
353 	 */
354 	bcopy(op->lease_key, of->TargetOplockKey, SMB_LEASE_KEY_SZ);
355 	bcopy(op->parent_lease_key, of->ParentOplockKey, SMB_LEASE_KEY_SZ);
356 
357 	/*
358 	 * grab a ref for of->f_user and of->f_tree
359 	 * We know the user and tree must be "live" because
360 	 * this SR holds references to them.  The node ref. is
361 	 * held by our caller, until smb_ofile_open puts this
362 	 * ofile on the node ofile list with smb_node_add_ofile.
363 	 */
364 	smb_user_hold_internal(sr->uid_user);
365 	smb_tree_hold_internal(tree);
366 	of->f_user = sr->uid_user;
367 	of->f_tree = tree;
368 	of->f_node = node;
369 
370 	return (of);
371 }
372 
373 /*
374  * smb_ofile_open
375  *
376  * Complete an open on an ofile that was previously allocated by
377  * smb_ofile_alloc, by putting it on the tree ofile list and
378  * (if it's a file) the node ofile list.
379  */
380 void
381 smb_ofile_open(
382     smb_request_t	*sr,
383     smb_arg_open_t	*op,
384     smb_ofile_t		*of)
385 {
386 	smb_tree_t	*tree = sr->tid_tree;
387 	smb_node_t	*node = of->f_node;
388 
389 	ASSERT(of->f_state == SMB_OFILE_STATE_ALLOC);
390 	of->f_state = SMB_OFILE_STATE_OPEN;
391 
392 	switch (of->f_ftype) {
393 	case SMB_FTYPE_BYTE_PIPE:
394 	case SMB_FTYPE_MESG_PIPE:
395 		/* See smb_opipe_open. */
396 		of->f_pipe = op->pipe;
397 		smb_server_inc_pipes(of->f_server);
398 		break;
399 	case SMB_FTYPE_DISK:
400 	case SMB_FTYPE_PRINTER:
401 		/* Regular file, not a pipe */
402 		ASSERT(node != NULL);
403 
404 		smb_node_inc_open_ofiles(node);
405 		smb_node_add_ofile(node, of);
406 		smb_node_ref(node);
407 		smb_server_inc_files(of->f_server);
408 		break;
409 	default:
410 		ASSERT(0);
411 	}
412 	smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
413 	smb_llist_insert_tail(&tree->t_ofile_list, of);
414 	smb_llist_exit(&tree->t_ofile_list);
415 	atomic_inc_32(&tree->t_open_files);
416 	atomic_inc_32(&of->f_session->s_file_cnt);
417 
418 }
419 
420 /*
421  * smb_ofile_close
422  *
423  * Incoming states: (where from)
424  *   SMB_OFILE_STATE_OPEN  protocol close, smb_ofile_drop
425  *   SMB_OFILE_STATE_EXPIRED  called via smb2_dh_expire
426  *   SMB_OFILE_STATE_ORPHANED  smb2_dh_shutdown
427  */
428 void
429 smb_ofile_close(smb_ofile_t *of, int32_t mtime_sec)
430 {
431 	smb_attr_t *pa;
432 	timestruc_t now;
433 
434 	SMB_OFILE_VALID(of);
435 
436 	mutex_enter(&of->f_mutex);
437 	ASSERT(of->f_refcnt);
438 
439 	switch (of->f_state) {
440 	case SMB_OFILE_STATE_OPEN:
441 	case SMB_OFILE_STATE_ORPHANED:
442 	case SMB_OFILE_STATE_EXPIRED:
443 		of->f_state = SMB_OFILE_STATE_CLOSING;
444 		mutex_exit(&of->f_mutex);
445 		break;
446 	default:
447 		mutex_exit(&of->f_mutex);
448 		return;
449 	}
450 
451 	switch (of->f_ftype) {
452 	case SMB_FTYPE_BYTE_PIPE:
453 	case SMB_FTYPE_MESG_PIPE:
454 		smb_opipe_close(of);
455 		smb_server_dec_pipes(of->f_server);
456 		break;
457 
458 	case SMB_FTYPE_DISK:
459 		if (of->f_persistid != 0)
460 			smb_ofile_del_persistid(of);
461 		if (of->f_lease != NULL)
462 			smb2_lease_ofile_close(of);
463 		smb_oplock_break_CLOSE(of->f_node, of);
464 		/* FALLTHROUGH */
465 
466 	case SMB_FTYPE_PRINTER: /* or FTYPE_DISK */
467 		/*
468 		 * In here we make changes to of->f_pending_attr
469 		 * while not holding of->f_mutex.  This is OK
470 		 * because we've changed f_state to CLOSING,
471 		 * so no more threads will take this path.
472 		 */
473 		pa = &of->f_pending_attr;
474 		if (mtime_sec != 0) {
475 			pa->sa_vattr.va_mtime.tv_sec = mtime_sec;
476 			pa->sa_mask |= SMB_AT_MTIME;
477 		}
478 
479 		/*
480 		 * If we have ever modified data via this handle
481 		 * (write or truncate) and if the mtime was not
482 		 * set via this handle, update the mtime again
483 		 * during the close.  Windows expects this.
484 		 * [ MS-FSA 2.1.5.4 "Update Timestamps" ]
485 		 */
486 		if (of->f_written &&
487 		    (pa->sa_mask & SMB_AT_MTIME) == 0) {
488 			pa->sa_mask |= SMB_AT_MTIME;
489 			gethrestime(&now);
490 			pa->sa_vattr.va_mtime = now;
491 		}
492 
493 		if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) {
494 			/* We delete using the on-disk name. */
495 			uint32_t flags = SMB_CASE_SENSITIVE;
496 			(void) smb_node_set_delete_on_close(of->f_node,
497 			    of->f_cr, flags);
498 		}
499 		smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid);
500 		smb_node_destroy_lock_by_ofile(of->f_node, of);
501 
502 		if (smb_node_is_file(of->f_node)) {
503 			(void) smb_fsop_close(of->f_node, of->f_mode,
504 			    of->f_cr);
505 		} else {
506 			/*
507 			 * If there was an odir, close it.
508 			 */
509 			if (of->f_odir != NULL)
510 				smb_odir_close(of->f_odir);
511 			/*
512 			 * Cancel any notify change requests that
513 			 * might be watching this open file (dir),
514 			 * and unsubscribe it from node events.
515 			 *
516 			 * Can't hold f_mutex when calling smb_notify_ofile.
517 			 * Don't really need it when unsubscribing, but
518 			 * harmless, and consistent with subscribing.
519 			 */
520 			if (of->f_notify.nc_subscribed)
521 				smb_notify_ofile(of,
522 				    FILE_ACTION_HANDLE_CLOSED, NULL);
523 			mutex_enter(&of->f_mutex);
524 			if (of->f_notify.nc_subscribed) {
525 				of->f_notify.nc_subscribed = B_FALSE;
526 				smb_node_fcn_unsubscribe(of->f_node);
527 				of->f_notify.nc_filter = 0;
528 			}
529 			mutex_exit(&of->f_mutex);
530 		}
531 		if (smb_node_dec_open_ofiles(of->f_node) == 0) {
532 			/*
533 			 * Last close.  If we're not deleting
534 			 * the file, apply any pending attrs.
535 			 * Leave allocsz zero when no open files,
536 			 * just to avoid confusion, because it's
537 			 * only updated when there are opens.
538 			 * XXX: Just do this on _every_ close.
539 			 */
540 			mutex_enter(&of->f_node->n_mutex);
541 			if (of->f_node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
542 				smb_node_delete_on_close(of->f_node);
543 				pa->sa_mask = 0;
544 			}
545 			of->f_node->n_allocsz = 0;
546 			mutex_exit(&of->f_node->n_mutex);
547 		}
548 		if (pa->sa_mask != 0) {
549 			/*
550 			 * Commit any pending attributes from
551 			 * the ofile we're closing.  Note that
552 			 * we pass NULL as the ofile to setattr
553 			 * so it will write to the file system
554 			 * and not keep anything on the ofile.
555 			 */
556 			(void) smb_node_setattr(NULL, of->f_node,
557 			    of->f_cr, NULL, pa);
558 		}
559 
560 		smb_server_dec_files(of->f_server);
561 		break;
562 	}
563 
564 	/*
565 	 * Keep f_state == SMB_OFILE_STATE_CLOSING
566 	 * until the last ref. is dropped, in
567 	 * smb_ofile_release()
568 	 */
569 }
570 
571 /*
572  * "Destructor" function for smb_ofile_close_all, and
573  * smb_ofile_close_all_by_pid, called after the llist lock
574  * for tree list has been exited.  Our job is to either
575  * close this ofile, or (if durable) set state _SAVE_DH.
576  *
577  * The next interesting thing happens when the last ref.
578  * on this ofile calls smb_ofile_release(), where we
579  * eihter delete the ofile, or (if durable) leave it
580  * in the persistid hash table for possible reclaim.
581  *
582  * This is run via smb_llist_post (after smb_llist_exit)
583  * because smb_ofile_close can block, and we'd rather not
584  * block while holding the ofile list as reader.
585  */
586 static void
587 smb_ofile_drop(void *arg)
588 {
589 	smb_ofile_t	*of = arg;
590 
591 	SMB_OFILE_VALID(of);
592 
593 	mutex_enter(&of->f_mutex);
594 	switch (of->f_state) {
595 	case SMB_OFILE_STATE_OPEN:
596 		/* DH checks under mutex. */
597 		if (of->f_ftype == SMB_FTYPE_DISK &&
598 		    of->dh_vers != SMB2_NOT_DURABLE &&
599 		    smb_dh_should_save(of)) {
600 			/*
601 			 * Tell smb_ofile_release() to
602 			 * make this an _ORPHANED DH.
603 			 */
604 			of->f_state = SMB_OFILE_STATE_SAVE_DH;
605 			mutex_exit(&of->f_mutex);
606 			break;
607 		}
608 		/* OK close it. */
609 		mutex_exit(&of->f_mutex);
610 		smb_ofile_close(of, 0);
611 		break;
612 
613 	default:
614 		/* Something else closed it already. */
615 		mutex_exit(&of->f_mutex);
616 		break;
617 	}
618 
619 	/*
620 	 * Release the ref acquired during the traversal loop.
621 	 * Note that on the last ref, this ofile will be
622 	 * removed from the tree list etc.
623 	 * See: smb_llist_post, smb_ofile_delete
624 	 */
625 	smb_ofile_release(of);
626 }
627 
628 /*
629  * smb_ofile_close_all
630  *
631  *
632  */
633 void
634 smb_ofile_close_all(
635     smb_tree_t		*tree,
636     uint32_t		pid)
637 {
638 	smb_ofile_t	*of;
639 	smb_llist_t	*ll;
640 
641 	ASSERT(tree);
642 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
643 
644 	ll = &tree->t_ofile_list;
645 
646 	smb_llist_enter(ll, RW_READER);
647 	for (of = smb_llist_head(ll);
648 	    of != NULL;
649 	    of = smb_llist_next(ll, of)) {
650 		ASSERT(of->f_magic == SMB_OFILE_MAGIC);
651 		ASSERT(of->f_tree == tree);
652 		if (pid != 0 && of->f_opened_by_pid != pid)
653 			continue;
654 		if (smb_ofile_hold(of)) {
655 			smb_llist_post(ll, of, smb_ofile_drop);
656 		}
657 	}
658 
659 	/*
660 	 * Drop the lock and process the llist dtor queue.
661 	 * Calls smb_ofile_drop on ofiles that were open.
662 	 */
663 	smb_llist_exit(ll);
664 }
665 
666 /*
667  * If the enumeration request is for ofile data, handle it here.
668  * Otherwise, return.
669  *
670  * This function should be called with a hold on the ofile.
671  */
672 int
673 smb_ofile_enum(smb_ofile_t *of, smb_svcenum_t *svcenum)
674 {
675 	uint8_t *pb;
676 	uint_t nbytes;
677 	int rc;
678 
679 	ASSERT(of);
680 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
681 	ASSERT(of->f_refcnt);
682 
683 	if (svcenum->se_type != SMB_SVCENUM_TYPE_FILE)
684 		return (0);
685 
686 	if (svcenum->se_nskip > 0) {
687 		svcenum->se_nskip--;
688 		return (0);
689 	}
690 
691 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
692 		svcenum->se_nitems = svcenum->se_nlimit;
693 		return (0);
694 	}
695 
696 	pb = &svcenum->se_buf[svcenum->se_bused];
697 
698 	rc = smb_ofile_netinfo_encode(of, pb, svcenum->se_bavail,
699 	    &nbytes);
700 	if (rc == 0) {
701 		svcenum->se_bavail -= nbytes;
702 		svcenum->se_bused += nbytes;
703 		svcenum->se_nitems++;
704 	}
705 
706 	return (rc);
707 }
708 
709 /*
710  * Take a reference on an open file, in any of the states:
711  *   RECONNECT, SAVE_DH, OPEN, ORPHANED.
712  * Return TRUE if ref taken.  Used for oplock breaks.
713  *
714  * Note: When the oplock break code calls this, it holds the
715  * node ofile list lock and node oplock mutex.  When we see
716  * an ofile in states RECONNECT or SAVING, we know the ofile
717  * is gaining or losing it's tree, and that happens quickly,
718  * so we just wait for that work to finish.  However, the
719  * waiting for state transitions here means we have to be
720  * careful not to re-enter the node list lock or otherwise
721  * block on things that could cause a deadlock.  Waiting
722  * just on of->f_mutex here is OK.
723  */
724 boolean_t
725 smb_ofile_hold_olbrk(smb_ofile_t *of)
726 {
727 	boolean_t ret = B_FALSE;
728 
729 	ASSERT(of);
730 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
731 
732 	mutex_enter(&of->f_mutex);
733 
734 again:
735 	switch (of->f_state) {
736 	case SMB_OFILE_STATE_RECONNECT:
737 	case SMB_OFILE_STATE_SAVING:
738 		cv_wait(&of->f_cv, &of->f_mutex);
739 		goto again;
740 
741 	case SMB_OFILE_STATE_OPEN:
742 	case SMB_OFILE_STATE_ORPHANED:
743 	case SMB_OFILE_STATE_SAVE_DH:
744 		of->f_refcnt++;
745 		ret = B_TRUE;
746 		break;
747 
748 	default:
749 		break;
750 	}
751 	mutex_exit(&of->f_mutex);
752 
753 	return (ret);
754 }
755 
756 /*
757  * Take a reference on an open file.
758  */
759 boolean_t
760 smb_ofile_hold(smb_ofile_t *of)
761 {
762 	ASSERT(of);
763 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
764 
765 	mutex_enter(&of->f_mutex);
766 
767 	if (of->f_state != SMB_OFILE_STATE_OPEN) {
768 		mutex_exit(&of->f_mutex);
769 		return (B_FALSE);
770 	}
771 	of->f_refcnt++;
772 
773 	mutex_exit(&of->f_mutex);
774 	return (B_TRUE);
775 }
776 
777 /*
778  * Release a reference on a file.  If the reference count falls to
779  * zero and the file has been closed, post the object for deletion.
780  * Object deletion is deferred to avoid modifying a list while an
781  * iteration may be in progress.
782  *
783  * We're careful to avoid dropping f_session etc. until the last
784  * reference goes away.  The oplock break code depends on that
785  * not changing while it holds a ref. on an ofile.
786  */
787 void
788 smb_ofile_release(smb_ofile_t *of)
789 {
790 	smb_tree_t *tree = of->f_tree;
791 	boolean_t delete = B_FALSE;
792 
793 	SMB_OFILE_VALID(of);
794 
795 	mutex_enter(&of->f_mutex);
796 	ASSERT(of->f_refcnt > 0);
797 	of->f_refcnt--;
798 
799 	switch (of->f_state) {
800 	case SMB_OFILE_STATE_OPEN:
801 	case SMB_OFILE_STATE_ORPHANED:
802 	case SMB_OFILE_STATE_EXPIRED:
803 		break;
804 
805 	case SMB_OFILE_STATE_SAVE_DH:
806 		ASSERT(tree != NULL);
807 		if (of->f_refcnt == 0) {
808 			of->f_state = SMB_OFILE_STATE_SAVING;
809 			smb_llist_post(&tree->t_ofile_list, of,
810 			    smb_ofile_save_dh);
811 		}
812 		break;
813 
814 	case SMB_OFILE_STATE_CLOSING:
815 		/* Note, tree == NULL on _ORPHANED */
816 		if (of->f_refcnt == 0) {
817 			of->f_state = SMB_OFILE_STATE_CLOSED;
818 			if (tree == NULL) {
819 				/* Skip smb_llist_post */
820 				delete = B_TRUE;
821 				break;
822 			}
823 			smb_llist_post(&tree->t_ofile_list, of,
824 			    smb_ofile_delete);
825 		}
826 		break;
827 
828 	default:
829 		ASSERT(0);
830 		break;
831 	}
832 	mutex_exit(&of->f_mutex);
833 
834 	/*
835 	 * When we drop the last ref. on an expired DH, it's no longer
836 	 * in any tree, so skip the smb_llist_post and just call
837 	 * smb_ofile_delete directly.
838 	 */
839 	if (delete) {
840 		smb_ofile_delete(of);
841 	}
842 }
843 
844 /*
845  * smb_ofile_lookup_by_fid
846  *
847  * Find the open file whose fid matches the one specified in the request.
848  * If we can't find the fid or the shares (trees) don't match, we have a
849  * bad fid.
850  */
851 smb_ofile_t *
852 smb_ofile_lookup_by_fid(
853     smb_request_t	*sr,
854     uint16_t		fid)
855 {
856 	smb_tree_t	*tree = sr->tid_tree;
857 	smb_llist_t	*of_list;
858 	smb_ofile_t	*of;
859 
860 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
861 
862 	of_list = &tree->t_ofile_list;
863 
864 	smb_llist_enter(of_list, RW_READER);
865 	of = smb_llist_head(of_list);
866 	while (of) {
867 		ASSERT(of->f_magic == SMB_OFILE_MAGIC);
868 		ASSERT(of->f_tree == tree);
869 		if (of->f_fid == fid)
870 			break;
871 		of = smb_llist_next(of_list, of);
872 	}
873 	if (of == NULL)
874 		goto out;
875 
876 	/*
877 	 * Only allow use of a given FID with the same UID that
878 	 * was used to open it.  MS-CIFS 3.3.5.14
879 	 */
880 	if (of->f_user != sr->uid_user) {
881 		of = NULL;
882 		goto out;
883 	}
884 
885 	/* inline smb_ofile_hold() */
886 	mutex_enter(&of->f_mutex);
887 	if (of->f_state != SMB_OFILE_STATE_OPEN) {
888 		mutex_exit(&of->f_mutex);
889 		of = NULL;
890 		goto out;
891 	}
892 	of->f_refcnt++;
893 	mutex_exit(&of->f_mutex);
894 
895 out:
896 	smb_llist_exit(of_list);
897 	return (of);
898 }
899 
900 /*
901  * smb_ofile_lookup_by_uniqid
902  *
903  * Find the open file whose uniqid matches the one specified in the request.
904  */
905 smb_ofile_t *
906 smb_ofile_lookup_by_uniqid(smb_tree_t *tree, uint32_t uniqid)
907 {
908 	smb_llist_t	*of_list;
909 	smb_ofile_t	*of;
910 
911 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
912 
913 	of_list = &tree->t_ofile_list;
914 	smb_llist_enter(of_list, RW_READER);
915 	of = smb_llist_head(of_list);
916 
917 	while (of) {
918 		ASSERT(of->f_magic == SMB_OFILE_MAGIC);
919 		ASSERT(of->f_tree == tree);
920 
921 		if (of->f_uniqid == uniqid) {
922 			if (smb_ofile_hold(of)) {
923 				smb_llist_exit(of_list);
924 				return (of);
925 			}
926 		}
927 
928 		of = smb_llist_next(of_list, of);
929 	}
930 
931 	smb_llist_exit(of_list);
932 	return (NULL);
933 }
934 
935 static smb_ofile_t *
936 smb_ofile_hold_cb(smb_ofile_t *of)
937 {
938 	smb_ofile_t *ret = of;
939 
940 	mutex_enter(&of->f_mutex);
941 	if (of->f_state == SMB_OFILE_STATE_ORPHANED)
942 		/* inline smb_ofile_hold() */
943 		of->f_refcnt++;
944 	else
945 		ret = NULL;
946 
947 	mutex_exit(&of->f_mutex);
948 	return (ret);
949 }
950 
951 /*
952  * Lookup an ofile by persistent ID, and return ONLY if in state ORPHANED
953  * This is used by SMB2 create "reclaim".
954  */
955 smb_ofile_t *
956 smb_ofile_lookup_by_persistid(smb_request_t *sr, uint64_t persistid)
957 {
958 	smb_hash_t *hash;
959 	smb_bucket_t *bucket;
960 	smb_llist_t *ll;
961 	smb_ofile_t *of;
962 	uint_t idx;
963 
964 	hash = sr->sr_server->sv_persistid_ht;
965 	idx = smb_hash_uint64(hash, persistid);
966 	bucket = &hash->buckets[idx];
967 	ll = &bucket->b_list;
968 
969 	smb_llist_enter(ll, RW_READER);
970 	of = smb_llist_head(ll);
971 	while (of != NULL) {
972 		if (of->f_persistid == persistid)
973 			break;
974 		of = smb_llist_next(ll, of);
975 	}
976 	if (of != NULL)
977 		of = smb_ofile_hold_cb(of);
978 	smb_llist_exit(ll);
979 
980 	return (of);
981 }
982 
983 /*
984  * Create a (unique) persistent ID for a new ofile,
985  * and add this ofile to the persistid hash table.
986  */
987 void
988 smb_ofile_set_persistid(smb_ofile_t *of)
989 {
990 	smb_hash_t *hash = of->f_server->sv_persistid_ht;
991 	smb_bucket_t *bucket;
992 	smb_llist_t *ll;
993 	uint_t idx;
994 
995 	of->f_persistid = SMB_OFILE_PERSISTID(of);
996 
997 	idx = smb_hash_uint64(hash, of->f_persistid);
998 	bucket = &hash->buckets[idx];
999 	ll = &bucket->b_list;
1000 	smb_llist_enter(ll, RW_WRITER);
1001 	smb_llist_insert_tail(ll, of);
1002 	smb_llist_exit(ll);
1003 }
1004 
1005 void
1006 smb_ofile_del_persistid(smb_ofile_t *of)
1007 {
1008 	smb_hash_t *hash = of->f_server->sv_persistid_ht;
1009 	smb_bucket_t *bucket;
1010 	smb_llist_t *ll;
1011 	uint_t idx;
1012 
1013 	idx = smb_hash_uint64(hash, of->f_persistid);
1014 	bucket = &hash->buckets[idx];
1015 	ll = &bucket->b_list;
1016 	smb_llist_enter(ll, RW_WRITER);
1017 	smb_llist_remove(ll, of);
1018 	smb_llist_exit(ll);
1019 }
1020 
1021 /*
1022  * Disallow NetFileClose on certain ofiles to avoid side-effects.
1023  * Closing a tree root is not allowed: use NetSessionDel or NetShareDel.
1024  * Closing SRVSVC connections is not allowed because this NetFileClose
1025  * request may depend on this ofile.
1026  */
1027 boolean_t
1028 smb_ofile_disallow_fclose(smb_ofile_t *of)
1029 {
1030 	ASSERT(of);
1031 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1032 	ASSERT(of->f_refcnt);
1033 
1034 	switch (of->f_ftype) {
1035 	case SMB_FTYPE_DISK:
1036 		ASSERT(of->f_tree);
1037 		return (of->f_node == of->f_tree->t_snode);
1038 
1039 	case SMB_FTYPE_MESG_PIPE:
1040 		ASSERT(of->f_pipe);
1041 		if (smb_strcasecmp(of->f_pipe->p_name, "SRVSVC", 0) == 0)
1042 			return (B_TRUE);
1043 		break;
1044 	default:
1045 		break;
1046 	}
1047 
1048 	return (B_FALSE);
1049 }
1050 
1051 /*
1052  * smb_ofile_set_flags
1053  *
1054  * Return value:
1055  *
1056  *	Current flags value
1057  *
1058  */
1059 void
1060 smb_ofile_set_flags(
1061     smb_ofile_t		*of,
1062     uint32_t		flags)
1063 {
1064 	ASSERT(of);
1065 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1066 	ASSERT(of->f_refcnt);
1067 
1068 	mutex_enter(&of->f_mutex);
1069 	of->f_flags |= flags;
1070 	mutex_exit(&of->f_mutex);
1071 }
1072 
1073 /*
1074  * smb_ofile_seek
1075  *
1076  * Return value:
1077  *
1078  *	0		Success
1079  *	EINVAL		Unknown mode
1080  *	EOVERFLOW	offset too big
1081  *
1082  */
1083 int
1084 smb_ofile_seek(
1085     smb_ofile_t		*of,
1086     ushort_t		mode,
1087     int32_t		off,
1088     uint32_t		*retoff)
1089 {
1090 	u_offset_t	newoff = 0;
1091 	int		rc = 0;
1092 	smb_attr_t	attr;
1093 
1094 	ASSERT(of);
1095 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1096 	ASSERT(of->f_refcnt);
1097 
1098 	mutex_enter(&of->f_mutex);
1099 	switch (mode) {
1100 	case SMB_SEEK_SET:
1101 		if (off < 0)
1102 			newoff = 0;
1103 		else
1104 			newoff = (u_offset_t)off;
1105 		break;
1106 
1107 	case SMB_SEEK_CUR:
1108 		if (off < 0 && (-off) > of->f_seek_pos)
1109 			newoff = 0;
1110 		else
1111 			newoff = of->f_seek_pos + (u_offset_t)off;
1112 		break;
1113 
1114 	case SMB_SEEK_END:
1115 		bzero(&attr, sizeof (smb_attr_t));
1116 		attr.sa_mask |= SMB_AT_SIZE;
1117 		rc = smb_fsop_getattr(NULL, zone_kcred(), of->f_node, &attr);
1118 		if (rc != 0) {
1119 			mutex_exit(&of->f_mutex);
1120 			return (rc);
1121 		}
1122 		if (off < 0 && (-off) > attr.sa_vattr.va_size)
1123 			newoff = 0;
1124 		else
1125 			newoff = attr.sa_vattr.va_size + (u_offset_t)off;
1126 		break;
1127 
1128 	default:
1129 		mutex_exit(&of->f_mutex);
1130 		return (EINVAL);
1131 	}
1132 
1133 	/*
1134 	 * See comments at the beginning of smb_seek.c.
1135 	 * If the offset is greater than UINT_MAX, we will return an error.
1136 	 */
1137 
1138 	if (newoff > UINT_MAX) {
1139 		rc = EOVERFLOW;
1140 	} else {
1141 		of->f_seek_pos = newoff;
1142 		*retoff = (uint32_t)newoff;
1143 	}
1144 	mutex_exit(&of->f_mutex);
1145 	return (rc);
1146 }
1147 
1148 /*
1149  * smb_ofile_flush
1150  *
1151  * If writes on this file are not synchronous, flush it using the NFSv3
1152  * commit interface.
1153  *
1154  * XXX - todo: Flush named pipe should drain writes.
1155  */
1156 void
1157 smb_ofile_flush(struct smb_request *sr, struct smb_ofile *of)
1158 {
1159 	switch (of->f_ftype) {
1160 	case SMB_FTYPE_DISK:
1161 		if ((of->f_node->flags & NODE_FLAGS_WRITE_THROUGH) == 0)
1162 			(void) smb_fsop_commit(sr, of->f_cr, of->f_node);
1163 		break;
1164 	default:
1165 		break;
1166 	}
1167 }
1168 
1169 /*
1170  * smb_ofile_is_open
1171  */
1172 boolean_t
1173 smb_ofile_is_open(smb_ofile_t *of)
1174 {
1175 	boolean_t	rc;
1176 
1177 	SMB_OFILE_VALID(of);
1178 
1179 	mutex_enter(&of->f_mutex);
1180 	rc = smb_ofile_is_open_locked(of);
1181 	mutex_exit(&of->f_mutex);
1182 	return (rc);
1183 }
1184 
1185 /* *************************** Static Functions ***************************** */
1186 
1187 /*
1188  * Determine whether or not an ofile is open.
1189  * This function must be called with the mutex held.
1190  */
1191 static boolean_t
1192 smb_ofile_is_open_locked(smb_ofile_t *of)
1193 {
1194 	ASSERT(MUTEX_HELD(&of->f_mutex));
1195 
1196 	switch (of->f_state) {
1197 	case SMB_OFILE_STATE_OPEN:
1198 	case SMB_OFILE_STATE_SAVE_DH:
1199 	case SMB_OFILE_STATE_SAVING:
1200 	case SMB_OFILE_STATE_ORPHANED:
1201 	case SMB_OFILE_STATE_RECONNECT:
1202 		return (B_TRUE);
1203 
1204 	case SMB_OFILE_STATE_CLOSING:
1205 	case SMB_OFILE_STATE_CLOSED:
1206 	case SMB_OFILE_STATE_EXPIRED:
1207 		return (B_FALSE);
1208 
1209 	default:
1210 		ASSERT(0);
1211 		return (B_FALSE);
1212 	}
1213 }
1214 
1215 /*
1216  * smb_ofile_save_dh
1217  *
1218  * Called via smb_llist_post (after smb_llist_exit) when the last ref.
1219  * on this ofile has gone, and this ofile is a "durable handle" (DH)
1220  * that has state we've decided to save.
1221  *
1222  * This does parts of what smb_ofile_delete would do, including:
1223  * remove the ofile from the tree ofile list and related.
1224  *
1225  * We leave the ofile in state ORPHANED, ready for reconnect
1226  * or expiration via smb2_dh_expire (see smb_ofile_delete).
1227  */
1228 static void
1229 smb_ofile_save_dh(void *arg)
1230 {
1231 	smb_ofile_t	*of = (smb_ofile_t *)arg;
1232 	smb_tree_t	*tree = of->f_tree;
1233 
1234 	SMB_OFILE_VALID(of);
1235 	ASSERT(of->f_refcnt == 0);
1236 	ASSERT(of->f_ftype == SMB_FTYPE_DISK);
1237 	ASSERT(of->f_state == SMB_OFILE_STATE_SAVING);
1238 
1239 	atomic_dec_32(&of->f_session->s_file_cnt);
1240 	atomic_dec_32(&of->f_tree->t_open_files);
1241 	smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
1242 	smb_llist_remove(&tree->t_ofile_list, of);
1243 	smb_llist_exit(&tree->t_ofile_list);
1244 
1245 	/*
1246 	 * This ofile is no longer on t_ofile_list, however...
1247 	 *
1248 	 * This is called via smb_llist_post, which means it may run
1249 	 * BEFORE smb_ofile_release drops f_mutex (if another thread
1250 	 * flushes the delete queue before we do).  Synchronize.
1251 	 */
1252 	mutex_enter(&of->f_mutex);
1253 	DTRACE_PROBE1(ofile__exit, smb_ofile_t, of);
1254 	mutex_exit(&of->f_mutex);
1255 
1256 	/*
1257 	 * Keep f_notify state, lease, and
1258 	 * keep on node ofile list.
1259 	 * Keep of->f_cr until reclaim.
1260 	 */
1261 
1262 	ASSERT(of->f_fid != 0);
1263 	smb_idpool_free(&tree->t_fid_pool, of->f_fid);
1264 	of->f_fid = 0;
1265 	smb_tree_release(of->f_tree);
1266 	of->f_tree = NULL;
1267 	smb_user_release(of->f_user);
1268 	of->f_user = NULL;
1269 	of->f_session = NULL;
1270 
1271 	/*
1272 	 * Make it "orphaned" so it can now be reclaimed.
1273 	 * Note that smb_ofile_hold_olbrk() may have blocked
1274 	 * for state SMB_OFILE_STATE_SAVING, so wake it.
1275 	 */
1276 	mutex_enter(&of->f_mutex);
1277 	of->dh_expire_time = gethrtime() + of->dh_timeout_offset;
1278 	of->f_state = SMB_OFILE_STATE_ORPHANED;
1279 	cv_broadcast(&of->f_cv);
1280 	mutex_exit(&of->f_mutex);
1281 }
1282 
1283 /*
1284  * Delete an ofile.
1285  *
1286  * Approximately the inverse of smb_ofile_alloc()
1287  * Called via smb_llist_post (after smb_llist_exit)
1288  * when the last ref. on this ofile has gone.
1289  *
1290  * Normally,this removes the ofile from the tree list and
1291  * then frees resources held on the ofile.  However, when
1292  * we're expiring an orphaned durable handle, the linkage
1293  * into the tree lists etc. have already been destroyed.
1294  * This case is distinguished by of->f_tree == NULL.
1295  */
1296 static void
1297 smb_ofile_delete(void *arg)
1298 {
1299 	smb_ofile_t	*of = (smb_ofile_t *)arg;
1300 	smb_tree_t	*tree = of->f_tree;
1301 
1302 	SMB_OFILE_VALID(of);
1303 	ASSERT(of->f_refcnt == 0);
1304 	ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
1305 
1306 	if (tree != NULL) {
1307 		ASSERT(of->f_user != NULL);
1308 		ASSERT(of->f_session != NULL);
1309 		atomic_dec_32(&of->f_session->s_file_cnt);
1310 		atomic_dec_32(&of->f_tree->t_open_files);
1311 		smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
1312 		smb_llist_remove(&tree->t_ofile_list, of);
1313 		smb_llist_exit(&tree->t_ofile_list);
1314 	}
1315 
1316 	/*
1317 	 * Remove this ofile from the node's n_ofile_list so it
1318 	 * can't be found by list walkers like notify or oplock.
1319 	 * Keep the node ref. until later in this function so
1320 	 * of->f_node remains valid while we destroy the ofile.
1321 	 */
1322 	if (of->f_ftype == SMB_FTYPE_DISK ||
1323 	    of->f_ftype == SMB_FTYPE_PRINTER) {
1324 		ASSERT(of->f_node != NULL);
1325 		/*
1326 		 * Note smb_ofile_close did smb_node_dec_open_ofiles()
1327 		 */
1328 		smb_node_rem_ofile(of->f_node, of);
1329 	}
1330 
1331 	/*
1332 	 * This ofile is no longer on any lists, however...
1333 	 *
1334 	 * This is called via smb_llist_post, which means it may run
1335 	 * BEFORE smb_ofile_release drops f_mutex (if another thread
1336 	 * flushes the delete queue before we do).  Synchronize.
1337 	 */
1338 	mutex_enter(&of->f_mutex);
1339 	of->f_state = SMB_OFILE_STATE_ALLOC;
1340 	DTRACE_PROBE1(ofile__exit, smb_ofile_t, of);
1341 	mutex_exit(&of->f_mutex);
1342 
1343 	switch (of->f_ftype) {
1344 	case SMB_FTYPE_BYTE_PIPE:
1345 	case SMB_FTYPE_MESG_PIPE:
1346 		smb_opipe_dealloc(of->f_pipe);
1347 		of->f_pipe = NULL;
1348 		break;
1349 	case SMB_FTYPE_DISK:
1350 		ASSERT(of->f_notify.nc_subscribed == B_FALSE);
1351 		MBC_FLUSH(&of->f_notify.nc_buffer);
1352 		if (of->f_odir != NULL)
1353 			smb_odir_release(of->f_odir);
1354 		if (of->f_lease != NULL) {
1355 			smb2_lease_rele(of->f_lease);
1356 			of->f_lease = NULL;
1357 		}
1358 		/* FALLTHROUGH */
1359 	case SMB_FTYPE_PRINTER:
1360 		/*
1361 		 * Did smb_node_rem_ofile above.
1362 		 */
1363 		ASSERT(of->f_node != NULL);
1364 		smb_node_release(of->f_node);
1365 		break;
1366 	default:
1367 		ASSERT(!"f_ftype");
1368 		break;
1369 	}
1370 
1371 	smb_ofile_free(of);
1372 }
1373 
1374 void
1375 smb_ofile_free(smb_ofile_t *of)
1376 {
1377 	smb_tree_t	*tree = of->f_tree;
1378 
1379 	ASSERT(of->f_state == SMB_OFILE_STATE_ALLOC);
1380 
1381 	if (tree != NULL) {
1382 		if (of->f_fid != 0)
1383 			smb_idpool_free(&tree->t_fid_pool, of->f_fid);
1384 		smb_tree_release(of->f_tree);
1385 		smb_user_release(of->f_user);
1386 	}
1387 
1388 	if (of->f_cr != NULL)
1389 		crfree(of->f_cr);
1390 
1391 	of->f_magic = (uint32_t)~SMB_OFILE_MAGIC;
1392 	list_destroy(&of->f_notify.nc_waiters);
1393 	mutex_destroy(&of->f_mutex);
1394 	kmem_cache_free(smb_cache_ofile, of);
1395 }
1396 
1397 /*
1398  * smb_ofile_access
1399  *
1400  * This function will check to see if the access requested is granted.
1401  * Returns NT status codes.
1402  */
1403 uint32_t
1404 smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access)
1405 {
1406 
1407 	if ((of == NULL) || (cr == zone_kcred()))
1408 		return (NT_STATUS_SUCCESS);
1409 
1410 	/*
1411 	 * If the request is for something
1412 	 * I don't grant it is an error
1413 	 */
1414 	if (~(of->f_granted_access) & access) {
1415 		if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) &&
1416 		    (access & ACCESS_SYSTEM_SECURITY)) {
1417 			return (NT_STATUS_PRIVILEGE_NOT_HELD);
1418 		}
1419 		return (NT_STATUS_ACCESS_DENIED);
1420 	}
1421 
1422 	return (NT_STATUS_SUCCESS);
1423 }
1424 
1425 /*
1426  * smb_ofile_share_check
1427  *
1428  * Check if ofile was opened with share access NONE (0).
1429  * Returns: B_TRUE  - share access non-zero
1430  *          B_FALSE - share access NONE
1431  */
1432 boolean_t
1433 smb_ofile_share_check(smb_ofile_t *of)
1434 {
1435 	return (!SMB_DENY_ALL(of->f_share_access));
1436 }
1437 
1438 /*
1439  * check file sharing rules for current open request
1440  * against existing open instances of the same file
1441  *
1442  * Returns NT_STATUS_SHARING_VIOLATION if there is any
1443  * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
1444  */
1445 uint32_t
1446 smb_ofile_open_check(smb_ofile_t *of, uint32_t desired_access,
1447     uint32_t share_access)
1448 {
1449 	uint32_t ret;
1450 
1451 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1452 
1453 	mutex_enter(&of->f_mutex);
1454 
1455 	if (!smb_ofile_is_open_locked(of)) {
1456 		ret = NT_STATUS_INVALID_HANDLE;
1457 		goto out;
1458 	}
1459 
1460 	/* if it's just meta data */
1461 	if ((of->f_granted_access & FILE_DATA_ALL) == 0) {
1462 		ret = NT_STATUS_SUCCESS;
1463 		goto out;
1464 	}
1465 
1466 	/*
1467 	 * Check requested share access against the
1468 	 * open granted (desired) access
1469 	 */
1470 	if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) {
1471 		ret = NT_STATUS_SHARING_VIOLATION;
1472 		goto out;
1473 	}
1474 
1475 	if (SMB_DENY_READ(share_access) &&
1476 	    (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) {
1477 		ret = NT_STATUS_SHARING_VIOLATION;
1478 		goto out;
1479 	}
1480 
1481 	if (SMB_DENY_WRITE(share_access) &&
1482 	    (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
1483 		ret = NT_STATUS_SHARING_VIOLATION;
1484 		goto out;
1485 	}
1486 
1487 	/* check requested desired access against the open share access */
1488 	if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) {
1489 		ret = NT_STATUS_SHARING_VIOLATION;
1490 		goto out;
1491 	}
1492 
1493 	if (SMB_DENY_READ(of->f_share_access) &&
1494 	    (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) {
1495 		ret = NT_STATUS_SHARING_VIOLATION;
1496 		goto out;
1497 	}
1498 
1499 	if (SMB_DENY_WRITE(of->f_share_access) &&
1500 	    (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
1501 		ret = NT_STATUS_SHARING_VIOLATION;
1502 		goto out;
1503 	}
1504 
1505 	ret = NT_STATUS_SUCCESS;
1506 out:
1507 	mutex_exit(&of->f_mutex);
1508 	return (ret);
1509 }
1510 
1511 /*
1512  * smb_ofile_rename_check
1513  *
1514  * This does the work described in MS-FSA 2.1.5.1.2.2 (Algorithm
1515  * to Check Sharing Access to an Existing Stream or Directory),
1516  * where the "open in-progress" has DesiredAccess = DELETE and
1517  * SharingMode = SHARE_READ | SHARE_WRITE | SHARE_DELETE.
1518  */
1519 
1520 uint32_t
1521 smb_ofile_rename_check(smb_ofile_t *of)
1522 {
1523 	uint32_t ret;
1524 
1525 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1526 
1527 	mutex_enter(&of->f_mutex);
1528 
1529 	if (!smb_ofile_is_open_locked(of)) {
1530 		ret = NT_STATUS_INVALID_HANDLE;
1531 		goto out;
1532 	}
1533 
1534 	if ((of->f_granted_access & FILE_DATA_ALL) == 0) {
1535 		ret = NT_STATUS_SUCCESS;
1536 		goto out;
1537 	}
1538 
1539 	if ((of->f_share_access & FILE_SHARE_DELETE) == 0) {
1540 		ret = NT_STATUS_SHARING_VIOLATION;
1541 		goto out;
1542 	}
1543 
1544 	ret = NT_STATUS_SUCCESS;
1545 out:
1546 	mutex_exit(&of->f_mutex);
1547 	return (ret);
1548 }
1549 
1550 /*
1551  * smb_ofile_delete_check
1552  *
1553  * An open file can be deleted only if opened for
1554  * accessing meta data. Share modes aren't important
1555  * in this case.
1556  *
1557  * NOTE: there is another mechanism for deleting an
1558  * open file that NT clients usually use.
1559  * That's setting "Delete on close" flag for an open
1560  * file.  In this way the file will be deleted after
1561  * last close. This flag can be set by SmbTrans2SetFileInfo
1562  * with FILE_DISPOSITION_INFO information level.
1563  * For setting this flag, the file should be opened by
1564  * DELETE access in the FID that is passed in the Trans2
1565  * request.
1566  */
1567 
1568 uint32_t
1569 smb_ofile_delete_check(smb_ofile_t *of)
1570 {
1571 	uint32_t ret;
1572 
1573 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1574 
1575 	mutex_enter(&of->f_mutex);
1576 
1577 	if (!smb_ofile_is_open_locked(of)) {
1578 		ret = NT_STATUS_INVALID_HANDLE;
1579 		goto out;
1580 	}
1581 
1582 	if (of->f_granted_access &
1583 	    (FILE_READ_DATA | FILE_WRITE_DATA |
1584 	    FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) {
1585 		ret = NT_STATUS_SHARING_VIOLATION;
1586 		goto out;
1587 	}
1588 
1589 	ret = NT_STATUS_SUCCESS;
1590 out:
1591 	mutex_exit(&of->f_mutex);
1592 	return (ret);
1593 }
1594 
1595 cred_t *
1596 smb_ofile_getcred(smb_ofile_t *of)
1597 {
1598 	return (of->f_cr);
1599 }
1600 
1601 /*
1602  * smb_ofile_set_delete_on_close
1603  *
1604  * Set the DeleteOnClose flag on the smb file. When the file is closed,
1605  * the flag will be transferred to the smb node, which will commit the
1606  * delete operation and inhibit subsequent open requests.
1607  *
1608  * When DeleteOnClose is set on an smb_node, the common open code will
1609  * reject subsequent open requests for the file. Observation of Windows
1610  * 2000 indicates that subsequent opens should be allowed (assuming
1611  * there would be no sharing violation) until the file is closed using
1612  * the fid on which the DeleteOnClose was requested.
1613  */
1614 void
1615 smb_ofile_set_delete_on_close(smb_request_t *sr, smb_ofile_t *of)
1616 {
1617 	uint32_t	status;
1618 
1619 	/*
1620 	 * Break any oplock handle caching.
1621 	 */
1622 	status = smb_oplock_break_SETINFO(of->f_node, of,
1623 	    FileDispositionInformation);
1624 	if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
1625 		if (sr->session->dialect >= SMB_VERS_2_BASE)
1626 			(void) smb2sr_go_async(sr);
1627 		(void) smb_oplock_wait_break(of->f_node, 0);
1628 	}
1629 
1630 	mutex_enter(&of->f_mutex);
1631 	of->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE;
1632 	mutex_exit(&of->f_mutex);
1633 }
1634 
1635 /*
1636  * Encode open file information into a buffer; needed in user space to
1637  * support RPC requests.
1638  */
1639 static int
1640 smb_ofile_netinfo_encode(smb_ofile_t *of, uint8_t *buf, size_t buflen,
1641     uint32_t *nbytes)
1642 {
1643 	smb_netfileinfo_t	fi;
1644 	int			rc;
1645 
1646 	rc = smb_ofile_netinfo_init(of, &fi);
1647 	if (rc == 0) {
1648 		rc = smb_netfileinfo_encode(&fi, buf, buflen, nbytes);
1649 		smb_ofile_netinfo_fini(&fi);
1650 	}
1651 
1652 	return (rc);
1653 }
1654 
1655 static int
1656 smb_ofile_netinfo_init(smb_ofile_t *of, smb_netfileinfo_t *fi)
1657 {
1658 	smb_user_t	*user;
1659 	smb_tree_t	*tree;
1660 	smb_node_t	*node;
1661 	char		*path;
1662 	char		*buf;
1663 	int		rc;
1664 
1665 	ASSERT(of);
1666 	user = of->f_user;
1667 	tree = of->f_tree;
1668 	ASSERT(user);
1669 	ASSERT(tree);
1670 
1671 	buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1672 
1673 	switch (of->f_ftype) {
1674 	case SMB_FTYPE_DISK:
1675 		node = of->f_node;
1676 		ASSERT(node);
1677 
1678 		fi->fi_permissions = of->f_granted_access;
1679 		fi->fi_numlocks = smb_lock_get_lock_count(node, of);
1680 
1681 		path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1682 
1683 		if (node != tree->t_snode) {
1684 			rc = smb_node_getshrpath(node, tree, path, MAXPATHLEN);
1685 			if (rc != 0)
1686 				(void) strlcpy(path, node->od_name, MAXPATHLEN);
1687 		}
1688 
1689 		(void) snprintf(buf, MAXPATHLEN, "%s:%s", tree->t_sharename,
1690 		    path);
1691 		kmem_free(path, MAXPATHLEN);
1692 		break;
1693 
1694 	case SMB_FTYPE_MESG_PIPE:
1695 		ASSERT(of->f_pipe);
1696 
1697 		fi->fi_permissions = FILE_READ_DATA | FILE_WRITE_DATA |
1698 		    FILE_EXECUTE;
1699 		fi->fi_numlocks = 0;
1700 		(void) snprintf(buf, MAXPATHLEN, "\\PIPE\\%s",
1701 		    of->f_pipe->p_name);
1702 		break;
1703 
1704 	default:
1705 		kmem_free(buf, MAXPATHLEN);
1706 		return (-1);
1707 	}
1708 
1709 	fi->fi_fid = of->f_fid;
1710 	fi->fi_uniqid = of->f_uniqid;
1711 	fi->fi_pathlen = strlen(buf) + 1;
1712 	fi->fi_path = smb_mem_strdup(buf);
1713 	kmem_free(buf, MAXPATHLEN);
1714 
1715 	fi->fi_namelen = user->u_domain_len + user->u_name_len + 2;
1716 	fi->fi_username = kmem_alloc(fi->fi_namelen, KM_SLEEP);
1717 	(void) snprintf(fi->fi_username, fi->fi_namelen, "%s\\%s",
1718 	    user->u_domain, user->u_name);
1719 	return (0);
1720 }
1721 
1722 static void
1723 smb_ofile_netinfo_fini(smb_netfileinfo_t *fi)
1724 {
1725 	if (fi == NULL)
1726 		return;
1727 
1728 	if (fi->fi_path)
1729 		smb_mem_free(fi->fi_path);
1730 	if (fi->fi_username)
1731 		kmem_free(fi->fi_username, fi->fi_namelen);
1732 
1733 	bzero(fi, sizeof (smb_netfileinfo_t));
1734 }
1735 
1736 /*
1737  * A query of user and group quotas may span multiple requests.
1738  * f_quota_resume is used to determine where the query should
1739  * be resumed, in a subsequent request. f_quota_resume contains
1740  * the SID of the last quota entry returned to the client.
1741  */
1742 void
1743 smb_ofile_set_quota_resume(smb_ofile_t *ofile, char *resume)
1744 {
1745 	ASSERT(ofile);
1746 	mutex_enter(&ofile->f_mutex);
1747 	if (resume == NULL)
1748 		bzero(ofile->f_quota_resume, SMB_SID_STRSZ);
1749 	else
1750 		(void) strlcpy(ofile->f_quota_resume, resume, SMB_SID_STRSZ);
1751 	mutex_exit(&ofile->f_mutex);
1752 }
1753 
1754 void
1755 smb_ofile_get_quota_resume(smb_ofile_t *ofile, char *buf, int bufsize)
1756 {
1757 	ASSERT(ofile);
1758 	mutex_enter(&ofile->f_mutex);
1759 	(void) strlcpy(buf, ofile->f_quota_resume, bufsize);
1760 	mutex_exit(&ofile->f_mutex);
1761 }
1762