xref: /illumos-gate/usr/src/cmd/smbsrv/testoplock/tol_main.c (revision da90d5b8133e037164268f8957ab823e806a7bfb)
194047d49SGordon Ross /*
294047d49SGordon Ross  * This file and its contents are supplied under the terms of the
394047d49SGordon Ross  * Common Development and Distribution License ("CDDL"), version 1.0.
494047d49SGordon Ross  * You may only use this file in accordance with the terms of version
594047d49SGordon Ross  * 1.0 of the CDDL.
694047d49SGordon Ross  *
794047d49SGordon Ross  * A full copy of the text of the CDDL should have accompanied this
894047d49SGordon Ross  * source.  A copy of the CDDL is also available via the Internet at
994047d49SGordon Ross  * http://www.illumos.org/license/CDDL.
1094047d49SGordon Ross  */
1194047d49SGordon Ross 
1294047d49SGordon Ross /*
1394047d49SGordon Ross  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
14*da90d5b8SJohn Levon  * Copyright 2019 Joyent, Inc.
1594047d49SGordon Ross  */
1694047d49SGordon Ross 
1794047d49SGordon Ross /*
1894047d49SGordon Ross  * Test & debug program for oplocks
1994047d49SGordon Ross  *
2094047d49SGordon Ross  * This implements a simple command reader which accepts
2194047d49SGordon Ross  * commands to simulate oplock events, and prints the
2294047d49SGordon Ross  * state changes and actions that would happen after
2394047d49SGordon Ross  * each event.
2494047d49SGordon Ross  */
2594047d49SGordon Ross 
2694047d49SGordon Ross #include <sys/types.h>
2794047d49SGordon Ross #include <sys/debug.h>
2894047d49SGordon Ross #include <sys/stddef.h>
2994047d49SGordon Ross #include <stdio.h>
3094047d49SGordon Ross #include <stdlib.h>
3194047d49SGordon Ross #include <string.h>
3294047d49SGordon Ross #include <strings.h>
3394047d49SGordon Ross #include <unistd.h>
3494047d49SGordon Ross 
3594047d49SGordon Ross #include <smbsrv/smb_kproto.h>
3694047d49SGordon Ross #include <smbsrv/smb_oplock.h>
3794047d49SGordon Ross 
3894047d49SGordon Ross #define	OPLOCK_CACHE_RWH	(READ_CACHING | HANDLE_CACHING | WRITE_CACHING)
3994047d49SGordon Ross #define	OPLOCK_TYPE	(LEVEL_TWO_OPLOCK | LEVEL_ONE_OPLOCK |\
4094047d49SGordon Ross 			BATCH_OPLOCK | OPLOCK_LEVEL_GRANULAR)
4194047d49SGordon Ross 
4294047d49SGordon Ross #define	MAXFID 10
4394047d49SGordon Ross 
4494047d49SGordon Ross smb_node_t root_node, test_node;
4594047d49SGordon Ross smb_ofile_t  ofile_array[MAXFID];
4694047d49SGordon Ross smb_request_t test_sr;
4794047d49SGordon Ross uint32_t last_ind_break_level;
4894047d49SGordon Ross char cmdbuf[100];
4994047d49SGordon Ross 
5094047d49SGordon Ross extern const char *xlate_nt_status(uint32_t);
5194047d49SGordon Ross 
5294047d49SGordon Ross #define	BIT_DEF(name) { name, #name }
5394047d49SGordon Ross 
5494047d49SGordon Ross struct bit_defs {
5594047d49SGordon Ross 	uint32_t mask;
5694047d49SGordon Ross 	const char *name;
5794047d49SGordon Ross } state_bits[] = {
5894047d49SGordon Ross 	BIT_DEF(NO_OPLOCK),
5994047d49SGordon Ross 	BIT_DEF(BREAK_TO_NO_CACHING),
6094047d49SGordon Ross 	BIT_DEF(BREAK_TO_WRITE_CACHING),
6194047d49SGordon Ross 	BIT_DEF(BREAK_TO_HANDLE_CACHING),
6294047d49SGordon Ross 	BIT_DEF(BREAK_TO_READ_CACHING),
6394047d49SGordon Ross 	BIT_DEF(BREAK_TO_TWO_TO_NONE),
6494047d49SGordon Ross 	BIT_DEF(BREAK_TO_NONE),
6594047d49SGordon Ross 	BIT_DEF(BREAK_TO_TWO),
6694047d49SGordon Ross 	BIT_DEF(BATCH_OPLOCK),
6794047d49SGordon Ross 	BIT_DEF(LEVEL_ONE_OPLOCK),
6894047d49SGordon Ross 	BIT_DEF(LEVEL_TWO_OPLOCK),
6994047d49SGordon Ross 	BIT_DEF(MIXED_R_AND_RH),
7094047d49SGordon Ross 	BIT_DEF(EXCLUSIVE),
7194047d49SGordon Ross 	BIT_DEF(WRITE_CACHING),
7294047d49SGordon Ross 	BIT_DEF(HANDLE_CACHING),
7394047d49SGordon Ross 	BIT_DEF(READ_CACHING),
7494047d49SGordon Ross 	{ 0, NULL }
7594047d49SGordon Ross };
7694047d49SGordon Ross 
7794047d49SGordon Ross /*
7894047d49SGordon Ross  * Helper to print flags fields
7994047d49SGordon Ross  */
8094047d49SGordon Ross static void
8194047d49SGordon Ross print_bits32(char *label, struct bit_defs *bit, uint32_t state)
8294047d49SGordon Ross {
8394047d49SGordon Ross 	printf("%s0x%x (", label, state);
8494047d49SGordon Ross 	while (bit->mask != 0) {
8594047d49SGordon Ross 		if ((state & bit->mask) != 0)
8694047d49SGordon Ross 			printf(" %s", bit->name);
8794047d49SGordon Ross 		bit++;
8894047d49SGordon Ross 	}
8994047d49SGordon Ross 	printf(" )\n");
9094047d49SGordon Ross }
9194047d49SGordon Ross 
9294047d49SGordon Ross /*
9394047d49SGordon Ross  * Command language:
9494047d49SGordon Ross  *
9594047d49SGordon Ross  */
9694047d49SGordon Ross const char helpstr[] = "Commands:\n"
9794047d49SGordon Ross 	"help\t\tList commands\n"
9894047d49SGordon Ross 	"show\t\tShow OpLock state etc.\n"
9994047d49SGordon Ross 	"open FID\n"
10094047d49SGordon Ross 	"close FID\n"
10194047d49SGordon Ross 	"req FID [OplockLevel]\n"
10294047d49SGordon Ross 	"ack FID [OplockLevel]\n"
10394047d49SGordon Ross 	"brk-parent FID\n"
10494047d49SGordon Ross 	"brk-open [OverWrite]\n"
10594047d49SGordon Ross 	"brk-handle FID\n"
10694047d49SGordon Ross 	"brk-read FID\n"
10794047d49SGordon Ross 	"brk-write FID\n"
10894047d49SGordon Ross 	"brk-setinfo FID [InfoClass]\n"
10994047d49SGordon Ross 	"move FID1 FID2\n"
11094047d49SGordon Ross 	"waiters FID [count]\n";
11194047d49SGordon Ross 
11294047d49SGordon Ross /*
11394047d49SGordon Ross  * Command handlers
11494047d49SGordon Ross  */
11594047d49SGordon Ross 
11694047d49SGordon Ross static void
11794047d49SGordon Ross do_show(void)
11894047d49SGordon Ross {
11994047d49SGordon Ross 	smb_node_t *node = &test_node;
12094047d49SGordon Ross 	smb_oplock_t *ol = &node->n_oplock;
12194047d49SGordon Ross 	uint32_t state = ol->ol_state;
12294047d49SGordon Ross 	smb_ofile_t *f;
12394047d49SGordon Ross 
12494047d49SGordon Ross 	print_bits32(" ol_state=", state_bits, state);
12594047d49SGordon Ross 
12694047d49SGordon Ross 	if (ol->excl_open != NULL)
12794047d49SGordon Ross 		printf(" Excl=Y (FID=%d)", ol->excl_open->f_fid);
12894047d49SGordon Ross 	else
12994047d49SGordon Ross 		printf(" Excl=n");
13094047d49SGordon Ross 	printf(" cnt_II=%d cnt_R=%d cnt_RH=%d cnt_RHBQ=%d\n",
13194047d49SGordon Ross 	    ol->cnt_II, ol->cnt_R, ol->cnt_RH, ol->cnt_RHBQ);
13294047d49SGordon Ross 
13394047d49SGordon Ross 	printf(" ofile_cnt=%d\n", node->n_ofile_list.ll_count);
13494047d49SGordon Ross 	FOREACH_NODE_OFILE(node, f) {
13594047d49SGordon Ross 		smb_oplock_grant_t *og = &f->f_oplock;
13694047d49SGordon Ross 		printf("  fid=%d Lease=%s OgState=0x%x Brk=0x%x",
13794047d49SGordon Ross 		    f->f_fid,
13894047d49SGordon Ross 		    f->TargetOplockKey,	/* lease */
13994047d49SGordon Ross 		    f->f_oplock.og_state,
14094047d49SGordon Ross 		    f->f_oplock.og_breaking);
14194047d49SGordon Ross 		printf(" Excl=%s onlist: %s %s %s",
14294047d49SGordon Ross 		    (ol->excl_open == f) ? "Y" : "N",
14394047d49SGordon Ross 		    og->onlist_II ? "II" : "",
14494047d49SGordon Ross 		    og->onlist_R  ? "R" : "",
14594047d49SGordon Ross 		    og->onlist_RH ? "RH" : "");
14694047d49SGordon Ross 		if (og->onlist_RHBQ) {
14794047d49SGordon Ross 			printf(" RHBQ(to %s)",
14894047d49SGordon Ross 			    og->BreakingToRead ?
14994047d49SGordon Ross 			    "read" : "none");
15094047d49SGordon Ross 		}
15194047d49SGordon Ross 		printf("\n");
15294047d49SGordon Ross 	}
15394047d49SGordon Ross }
15494047d49SGordon Ross 
15594047d49SGordon Ross static void
15694047d49SGordon Ross do_open(int fid, char *arg2)
15794047d49SGordon Ross {
15894047d49SGordon Ross 	smb_node_t *node = &test_node;
15994047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
16094047d49SGordon Ross 
16194047d49SGordon Ross 	/*
16294047d49SGordon Ross 	 * Simulate an open (minimal init)
16394047d49SGordon Ross 	 */
16494047d49SGordon Ross 	if (ofile->f_refcnt) {
16594047d49SGordon Ross 		printf("open fid %d already opened\n");
16694047d49SGordon Ross 		return;
16794047d49SGordon Ross 	}
16894047d49SGordon Ross 
169*da90d5b8SJohn Levon 	if (arg2 != NULL) {
170*da90d5b8SJohn Levon 		(void) strlcpy((char *)ofile->TargetOplockKey, arg2,
17194047d49SGordon Ross 		    SMB_LEASE_KEY_SZ);
172*da90d5b8SJohn Levon 	}
17394047d49SGordon Ross 
17494047d49SGordon Ross 	ofile->f_refcnt++;
17594047d49SGordon Ross 	node->n_open_count++;
17694047d49SGordon Ross 	smb_llist_insert_tail(&node->n_ofile_list, ofile);
17794047d49SGordon Ross 	printf(" open %d OK\n", fid);
17894047d49SGordon Ross }
17994047d49SGordon Ross 
18094047d49SGordon Ross static void
18194047d49SGordon Ross do_close(int fid)
18294047d49SGordon Ross {
18394047d49SGordon Ross 	smb_node_t *node = &test_node;
18494047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
18594047d49SGordon Ross 
18694047d49SGordon Ross 	/*
18794047d49SGordon Ross 	 * Simulate an close
18894047d49SGordon Ross 	 */
18994047d49SGordon Ross 	if (ofile->f_refcnt <= 0) {
19094047d49SGordon Ross 		printf(" close fid %d already closed\n");
19194047d49SGordon Ross 		return;
19294047d49SGordon Ross 	}
19394047d49SGordon Ross 	smb_oplock_break_CLOSE(ofile->f_node, ofile);
19494047d49SGordon Ross 
19594047d49SGordon Ross 	smb_llist_remove(&node->n_ofile_list, ofile);
19694047d49SGordon Ross 	node->n_open_count--;
19794047d49SGordon Ross 	ofile->f_refcnt--;
19894047d49SGordon Ross 
19994047d49SGordon Ross 	bzero(ofile->TargetOplockKey, SMB_LEASE_KEY_SZ);
20094047d49SGordon Ross 
20194047d49SGordon Ross 	printf(" close OK\n");
20294047d49SGordon Ross }
20394047d49SGordon Ross 
20494047d49SGordon Ross static void
20594047d49SGordon Ross do_req(int fid, char *arg2)
20694047d49SGordon Ross {
20794047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
20894047d49SGordon Ross 	uint32_t oplock = BATCH_OPLOCK;
20994047d49SGordon Ross 	uint32_t status;
21094047d49SGordon Ross 
21194047d49SGordon Ross 	if (arg2 != NULL)
21294047d49SGordon Ross 		oplock = strtol(arg2, NULL, 16);
21394047d49SGordon Ross 
21494047d49SGordon Ross 	/*
21594047d49SGordon Ross 	 * Request an oplock
21694047d49SGordon Ross 	 */
21794047d49SGordon Ross 	status = smb_oplock_request(&test_sr, ofile, &oplock);
21894047d49SGordon Ross 	if (status == 0)
21994047d49SGordon Ross 		ofile->f_oplock.og_state = oplock;
22094047d49SGordon Ross 	printf(" req oplock fid=%d ret oplock=0x%x status=0x%x (%s)\n",
22194047d49SGordon Ross 	    fid, oplock, status, xlate_nt_status(status));
22294047d49SGordon Ross }
22394047d49SGordon Ross 
22494047d49SGordon Ross 
22594047d49SGordon Ross static void
22694047d49SGordon Ross do_ack(int fid, char *arg2)
22794047d49SGordon Ross {
22894047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
22994047d49SGordon Ross 	uint32_t oplock;
23094047d49SGordon Ross 	uint32_t status;
23194047d49SGordon Ross 
23294047d49SGordon Ross 	/* Default to level in last smb_oplock_ind_break() */
23394047d49SGordon Ross 	oplock = last_ind_break_level;
23494047d49SGordon Ross 	if (arg2 != NULL)
23594047d49SGordon Ross 		oplock = strtol(arg2, NULL, 16);
23694047d49SGordon Ross 
23794047d49SGordon Ross 	ofile->f_oplock.og_breaking = 0;
23894047d49SGordon Ross 	status = smb_oplock_ack_break(&test_sr, ofile, &oplock);
23994047d49SGordon Ross 	if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
24094047d49SGordon Ross 		printf(" ack: break fid=%d, break-in-progress\n", fid);
24194047d49SGordon Ross 		ofile->f_oplock.og_state = oplock;
24294047d49SGordon Ross 	}
24394047d49SGordon Ross 	if (status == 0)
24494047d49SGordon Ross 		ofile->f_oplock.og_state = oplock;
24594047d49SGordon Ross 
24694047d49SGordon Ross 	printf(" ack: break fid=%d, newstate=0x%x, status=0x%x (%s)\n",
24794047d49SGordon Ross 	    fid, oplock, status, xlate_nt_status(status));
24894047d49SGordon Ross }
24994047d49SGordon Ross 
25094047d49SGordon Ross static void
25194047d49SGordon Ross do_brk_parent(int fid)
25294047d49SGordon Ross {
25394047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
25494047d49SGordon Ross 	uint32_t status;
25594047d49SGordon Ross 
25694047d49SGordon Ross 	status = smb_oplock_break_PARENT(&test_node, ofile);
25794047d49SGordon Ross 	printf(" brk-parent %d ret status=0x%x (%s)\n",
25894047d49SGordon Ross 	    fid, status, xlate_nt_status(status));
25994047d49SGordon Ross }
26094047d49SGordon Ross 
26194047d49SGordon Ross static void
26294047d49SGordon Ross do_brk_open(int fid, char *arg2)
26394047d49SGordon Ross {
26494047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
26594047d49SGordon Ross 	uint32_t status;
26694047d49SGordon Ross 	int disp = FILE_OPEN;
26794047d49SGordon Ross 
26894047d49SGordon Ross 	if (arg2 != NULL)
26994047d49SGordon Ross 		disp = strtol(arg2, NULL, 16);
27094047d49SGordon Ross 
27194047d49SGordon Ross 	status = smb_oplock_break_OPEN(&test_node, ofile, 7, disp);
27294047d49SGordon Ross 	printf(" brk-open %d ret status=0x%x (%s)\n",
27394047d49SGordon Ross 	    fid, status, xlate_nt_status(status));
27494047d49SGordon Ross }
27594047d49SGordon Ross 
27694047d49SGordon Ross static void
27794047d49SGordon Ross do_brk_handle(int fid)
27894047d49SGordon Ross {
27994047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
28094047d49SGordon Ross 	uint32_t status;
28194047d49SGordon Ross 
28294047d49SGordon Ross 	status = smb_oplock_break_HANDLE(&test_node, ofile);
28394047d49SGordon Ross 	printf(" brk-handle %d ret status=0x%x (%s)\n",
28494047d49SGordon Ross 	    fid, status, xlate_nt_status(status));
28594047d49SGordon Ross 
28694047d49SGordon Ross }
28794047d49SGordon Ross 
28894047d49SGordon Ross static void
28994047d49SGordon Ross do_brk_read(int fid)
29094047d49SGordon Ross {
29194047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
29294047d49SGordon Ross 	uint32_t status;
29394047d49SGordon Ross 
29494047d49SGordon Ross 	status = smb_oplock_break_READ(ofile->f_node, ofile);
29594047d49SGordon Ross 	printf(" brk-read %d ret status=0x%x (%s)\n",
29694047d49SGordon Ross 	    fid, status, xlate_nt_status(status));
29794047d49SGordon Ross }
29894047d49SGordon Ross 
29994047d49SGordon Ross static void
30094047d49SGordon Ross do_brk_write(int fid)
30194047d49SGordon Ross {
30294047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
30394047d49SGordon Ross 	uint32_t status;
30494047d49SGordon Ross 
30594047d49SGordon Ross 	status = smb_oplock_break_WRITE(ofile->f_node, ofile);
30694047d49SGordon Ross 	printf(" brk-write %d ret status=0x%x (%s)\n",
30794047d49SGordon Ross 	    fid, status, xlate_nt_status(status));
30894047d49SGordon Ross }
30994047d49SGordon Ross 
31094047d49SGordon Ross static void
31194047d49SGordon Ross do_brk_setinfo(int fid, char *arg2)
31294047d49SGordon Ross {
31394047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
31494047d49SGordon Ross 	uint32_t status;
31594047d49SGordon Ross 	int infoclass = FileEndOfFileInformation; /* 20 */
31694047d49SGordon Ross 
31794047d49SGordon Ross 	if (arg2 != NULL)
31894047d49SGordon Ross 		infoclass = strtol(arg2, NULL, 16);
31994047d49SGordon Ross 
32094047d49SGordon Ross 	status = smb_oplock_break_SETINFO(
32194047d49SGordon Ross 	    &test_node, ofile, infoclass);
32294047d49SGordon Ross 	printf(" brk-setinfo %d ret status=0x%x (%s)\n",
32394047d49SGordon Ross 	    fid, status, xlate_nt_status(status));
32494047d49SGordon Ross 
32594047d49SGordon Ross }
32694047d49SGordon Ross 
32794047d49SGordon Ross /*
32894047d49SGordon Ross  * Move oplock to another FD, as specified,
32994047d49SGordon Ross  * or any other available open
33094047d49SGordon Ross  */
33194047d49SGordon Ross static void
33294047d49SGordon Ross do_move(int fid, char *arg2)
33394047d49SGordon Ross {
33494047d49SGordon Ross 	smb_ofile_t *ofile = &ofile_array[fid];
33594047d49SGordon Ross 	smb_ofile_t *of2;
33694047d49SGordon Ross 	int fid2;
33794047d49SGordon Ross 
33894047d49SGordon Ross 	if (arg2 == NULL) {
33994047d49SGordon Ross 		fprintf(stderr, "move: FID2 required\n");
34094047d49SGordon Ross 		return;
34194047d49SGordon Ross 	}
34294047d49SGordon Ross 	fid2 = atoi(arg2);
34394047d49SGordon Ross 	if (fid2 <= 0 || fid2 >= MAXFID) {
34494047d49SGordon Ross 		fprintf(stderr, "move: bad FID2 %d\n", fid2);
34594047d49SGordon Ross 		return;
34694047d49SGordon Ross 	}
34794047d49SGordon Ross 	of2 = &ofile_array[fid2];
34894047d49SGordon Ross 
34994047d49SGordon Ross 	smb_oplock_move(&test_node, ofile, of2);
35094047d49SGordon Ross 	printf(" move %d %d\n", fid, fid2);
35194047d49SGordon Ross }
35294047d49SGordon Ross 
35394047d49SGordon Ross /*
35494047d49SGordon Ross  * Set/clear oplock.waiters, which affects ack-break
35594047d49SGordon Ross  */
35694047d49SGordon Ross static void
35794047d49SGordon Ross do_waiters(int fid, char *arg2)
35894047d49SGordon Ross {
35994047d49SGordon Ross 	smb_node_t *node = &test_node;
36094047d49SGordon Ross 	smb_oplock_t *ol = &node->n_oplock;
36194047d49SGordon Ross 	int old, new = 0;
36294047d49SGordon Ross 
36394047d49SGordon Ross 	if (arg2 != NULL)
36494047d49SGordon Ross 		new = atoi(arg2);
36594047d49SGordon Ross 
36694047d49SGordon Ross 	old = ol->waiters;
36794047d49SGordon Ross 	ol->waiters = new;
36894047d49SGordon Ross 
36994047d49SGordon Ross 	printf(" waiters %d -> %d\n", old, new);
37094047d49SGordon Ross }
37194047d49SGordon Ross 
37294047d49SGordon Ross int
37394047d49SGordon Ross main(int argc, char *argv[])
37494047d49SGordon Ross {
37594047d49SGordon Ross 	smb_node_t *node = &test_node;
37694047d49SGordon Ross 	char *cmd;
37794047d49SGordon Ross 	char *arg1;
37894047d49SGordon Ross 	char *arg2;
37994047d49SGordon Ross 	char *savep;
38094047d49SGordon Ross 	char *sep = " \t\n";
38194047d49SGordon Ross 	char *prompt = NULL;
38294047d49SGordon Ross 	int fid;
38394047d49SGordon Ross 
38494047d49SGordon Ross 	if (isatty(0))
38594047d49SGordon Ross 		prompt = "> ";
38694047d49SGordon Ross 
38794047d49SGordon Ross 	smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t),
38894047d49SGordon Ross 	    offsetof(smb_ofile_t, f_node_lnd));
38994047d49SGordon Ross 
39094047d49SGordon Ross 	for (fid = 0; fid < MAXFID; fid++) {
39194047d49SGordon Ross 		smb_ofile_t *f = &ofile_array[fid];
39294047d49SGordon Ross 
39394047d49SGordon Ross 		f->f_magic = SMB_OFILE_MAGIC;
39494047d49SGordon Ross 		mutex_init(&f->f_mutex, NULL, MUTEX_DEFAULT, NULL);
39594047d49SGordon Ross 		f->f_fid = fid;
39694047d49SGordon Ross 		f->f_ftype = SMB_FTYPE_DISK;
39794047d49SGordon Ross 		f->f_node = &test_node;
39894047d49SGordon Ross 	}
39994047d49SGordon Ross 
40094047d49SGordon Ross 	for (;;) {
40194047d49SGordon Ross 		if (prompt) {
402*da90d5b8SJohn Levon 			(void) fputs(prompt, stdout);
40394047d49SGordon Ross 			fflush(stdout);
40494047d49SGordon Ross 		}
40594047d49SGordon Ross 
40694047d49SGordon Ross 		cmd = fgets(cmdbuf, sizeof (cmdbuf), stdin);
40794047d49SGordon Ross 		if (cmd == NULL)
40894047d49SGordon Ross 			break;
40994047d49SGordon Ross 		if (cmd[0] == '#')
41094047d49SGordon Ross 			continue;
41194047d49SGordon Ross 
41294047d49SGordon Ross 		if (prompt == NULL) {
41394047d49SGordon Ross 			/* Put commands in the output too. */
414*da90d5b8SJohn Levon 			(void) fputs(cmdbuf, stdout);
41594047d49SGordon Ross 		}
41694047d49SGordon Ross 		cmd = strtok_r(cmd, sep, &savep);
41794047d49SGordon Ross 		if (cmd == NULL)
41894047d49SGordon Ross 			continue;
41994047d49SGordon Ross 
42094047d49SGordon Ross 		/*
42194047d49SGordon Ross 		 * Commands with no args
42294047d49SGordon Ross 		 */
42394047d49SGordon Ross 		if (0 == strcmp(cmd, "help")) {
424*da90d5b8SJohn Levon 			(void) fputs(helpstr, stdout);
42594047d49SGordon Ross 			continue;
42694047d49SGordon Ross 		}
42794047d49SGordon Ross 
42894047d49SGordon Ross 		if (0 == strcmp(cmd, "show")) {
42994047d49SGordon Ross 			do_show();
43094047d49SGordon Ross 			continue;
43194047d49SGordon Ross 		}
43294047d49SGordon Ross 
43394047d49SGordon Ross 		/*
43494047d49SGordon Ross 		 * Commands with one arg (the FID)
43594047d49SGordon Ross 		 */
43694047d49SGordon Ross 		arg1 = strtok_r(NULL, sep, &savep);
43794047d49SGordon Ross 		if (arg1 == NULL) {
43894047d49SGordon Ross 			fprintf(stderr, "%s missing arg1\n", cmd);
43994047d49SGordon Ross 			continue;
44094047d49SGordon Ross 		}
44194047d49SGordon Ross 		fid = atoi(arg1);
44294047d49SGordon Ross 		if (fid <= 0 || fid >= MAXFID) {
44394047d49SGordon Ross 			fprintf(stderr, "%s bad FID %d\n", cmd, fid);
44494047d49SGordon Ross 			continue;
44594047d49SGordon Ross 		}
44694047d49SGordon Ross 
44794047d49SGordon Ross 		if (0 == strcmp(cmd, "close")) {
44894047d49SGordon Ross 			do_close(fid);
44994047d49SGordon Ross 			continue;
45094047d49SGordon Ross 		}
45194047d49SGordon Ross 		if (0 == strcmp(cmd, "brk-parent")) {
45294047d49SGordon Ross 			do_brk_parent(fid);
45394047d49SGordon Ross 			continue;
45494047d49SGordon Ross 		}
45594047d49SGordon Ross 		if (0 == strcmp(cmd, "brk-handle")) {
45694047d49SGordon Ross 			do_brk_handle(fid);
45794047d49SGordon Ross 			continue;
45894047d49SGordon Ross 		}
45994047d49SGordon Ross 		if (0 == strcmp(cmd, "brk-read")) {
46094047d49SGordon Ross 			do_brk_read(fid);
46194047d49SGordon Ross 			continue;
46294047d49SGordon Ross 		}
46394047d49SGordon Ross 		if (0 == strcmp(cmd, "brk-write")) {
46494047d49SGordon Ross 			do_brk_write(fid);
46594047d49SGordon Ross 			continue;
46694047d49SGordon Ross 		}
46794047d49SGordon Ross 
46894047d49SGordon Ross 		/*
46994047d49SGordon Ross 		 * Commands with an (optional) arg2.
47094047d49SGordon Ross 		 */
47194047d49SGordon Ross 		arg2 = strtok_r(NULL, sep, &savep);
47294047d49SGordon Ross 
47394047d49SGordon Ross 		if (0 == strcmp(cmd, "open")) {
47494047d49SGordon Ross 			do_open(fid, arg2);
47594047d49SGordon Ross 			continue;
47694047d49SGordon Ross 		}
47794047d49SGordon Ross 		if (0 == strcmp(cmd, "req")) {
47894047d49SGordon Ross 			do_req(fid, arg2);
47994047d49SGordon Ross 			continue;
48094047d49SGordon Ross 		}
48194047d49SGordon Ross 		if (0 == strcmp(cmd, "ack")) {
48294047d49SGordon Ross 			do_ack(fid, arg2);
48394047d49SGordon Ross 			continue;
48494047d49SGordon Ross 		}
48594047d49SGordon Ross 		if (0 == strcmp(cmd, "brk-open")) {
48694047d49SGordon Ross 			do_brk_open(fid, arg2);
48794047d49SGordon Ross 			continue;
48894047d49SGordon Ross 		}
48994047d49SGordon Ross 		if (0 == strcmp(cmd, "brk-setinfo")) {
49094047d49SGordon Ross 			do_brk_setinfo(fid, arg2);
49194047d49SGordon Ross 			continue;
49294047d49SGordon Ross 		}
49394047d49SGordon Ross 		if (0 == strcmp(cmd, "move")) {
49494047d49SGordon Ross 			do_move(fid, arg2);
49594047d49SGordon Ross 			continue;
49694047d49SGordon Ross 		}
49794047d49SGordon Ross 		if (0 == strcmp(cmd, "waiters")) {
49894047d49SGordon Ross 			do_waiters(fid, arg2);
49994047d49SGordon Ross 			continue;
50094047d49SGordon Ross 		}
50194047d49SGordon Ross 
50294047d49SGordon Ross 		fprintf(stderr, "%s unknown command. Try help\n", cmd);
50394047d49SGordon Ross 	}
50494047d49SGordon Ross 	return (0);
50594047d49SGordon Ross }
50694047d49SGordon Ross 
50794047d49SGordon Ross /*
50894047d49SGordon Ross  * A few functions called by the oplock code
50994047d49SGordon Ross  * Stubbed out, and/or just print a message.
51094047d49SGordon Ross  */
51194047d49SGordon Ross 
51294047d49SGordon Ross boolean_t
51394047d49SGordon Ross smb_node_is_file(smb_node_t *node)
51494047d49SGordon Ross {
51594047d49SGordon Ross 	return (B_TRUE);
51694047d49SGordon Ross }
51794047d49SGordon Ross 
51894047d49SGordon Ross boolean_t
51994047d49SGordon Ross smb_ofile_is_open(smb_ofile_t *ofile)
52094047d49SGordon Ross {
52194047d49SGordon Ross 	return (ofile->f_refcnt != 0);
52294047d49SGordon Ross }
52394047d49SGordon Ross 
52494047d49SGordon Ross int
52594047d49SGordon Ross smb_lock_range_access(
52694047d49SGordon Ross     smb_request_t	*sr,
52794047d49SGordon Ross     smb_node_t		*node,
52894047d49SGordon Ross     uint64_t		start,
52994047d49SGordon Ross     uint64_t		length,
53094047d49SGordon Ross     boolean_t		will_write)
53194047d49SGordon Ross {
53294047d49SGordon Ross 	return (0);
53394047d49SGordon Ross }
53494047d49SGordon Ross 
53594047d49SGordon Ross /*
53694047d49SGordon Ross  * Test code replacement for: smb_oplock_send_brk()
53794047d49SGordon Ross  */
53894047d49SGordon Ross static void
53994047d49SGordon Ross test_oplock_send_brk(smb_ofile_t *ofile,
54094047d49SGordon Ross     uint32_t NewLevel, boolean_t AckReq)
54194047d49SGordon Ross {
54294047d49SGordon Ross 	smb_oplock_grant_t *og = &ofile->f_oplock;
54394047d49SGordon Ross 
54494047d49SGordon Ross 	/* Skip building a message. */
54594047d49SGordon Ross 
54694047d49SGordon Ross 	if ((og->og_state & OPLOCK_LEVEL_GRANULAR) != 0)
54794047d49SGordon Ross 		NewLevel |= OPLOCK_LEVEL_GRANULAR;
54894047d49SGordon Ross 
54994047d49SGordon Ross 	/*
55094047d49SGordon Ross 	 * In a real server, we would send a break to the client,
55194047d49SGordon Ross 	 * and keep track (at the SMB level) whether this oplock
55294047d49SGordon Ross 	 * was obtained via a lease or an old-style oplock.
55394047d49SGordon Ross 	 */
55494047d49SGordon Ross 	if (AckReq) {
55594047d49SGordon Ross 		uint32_t BreakTo;
55694047d49SGordon Ross 
55794047d49SGordon Ross 		if ((og->og_state & OPLOCK_LEVEL_GRANULAR) != 0) {
55894047d49SGordon Ross 
55994047d49SGordon Ross 			BreakTo = (NewLevel & CACHE_RWH) << BREAK_SHIFT;
56094047d49SGordon Ross 			if (BreakTo == 0)
56194047d49SGordon Ross 				BreakTo = BREAK_TO_NO_CACHING;
56294047d49SGordon Ross 		} else {
56394047d49SGordon Ross 			if ((NewLevel & LEVEL_TWO_OPLOCK) != 0)
56494047d49SGordon Ross 				BreakTo = BREAK_TO_TWO;
56594047d49SGordon Ross 			else
56694047d49SGordon Ross 				BreakTo = BREAK_TO_NONE;
56794047d49SGordon Ross 		}
56894047d49SGordon Ross 		og->og_breaking = BreakTo;
56994047d49SGordon Ross 		last_ind_break_level = NewLevel;
57094047d49SGordon Ross 		/* Set og_state in  do_ack */
57194047d49SGordon Ross 	} else {
57294047d49SGordon Ross 		og->og_state = NewLevel;
57394047d49SGordon Ross 		/* Clear og_breaking in do_ack */
57494047d49SGordon Ross 	}
57594047d49SGordon Ross }
57694047d49SGordon Ross 
57794047d49SGordon Ross /*
57894047d49SGordon Ross  * Simplified version of what's in smb_srv_oplock.c
57994047d49SGordon Ross  */
58094047d49SGordon Ross void
58194047d49SGordon Ross smb_oplock_ind_break(smb_ofile_t *ofile, uint32_t NewLevel,
58294047d49SGordon Ross     boolean_t AckReq, uint32_t status)
58394047d49SGordon Ross {
58494047d49SGordon Ross 	smb_oplock_grant_t *og = &ofile->f_oplock;
58594047d49SGordon Ross 
58694047d49SGordon Ross 	printf("*smb_oplock_ind_break fid=%d NewLevel=0x%x,"
58794047d49SGordon Ross 	    " AckReq=%d, ComplStatus=0x%x (%s)\n",
58894047d49SGordon Ross 	    ofile->f_fid, NewLevel, AckReq,
58994047d49SGordon Ross 	    status, xlate_nt_status(status));
59094047d49SGordon Ross 
59194047d49SGordon Ross 	/*
59294047d49SGordon Ross 	 * Note that the CompletionStatus from the FS level
59394047d49SGordon Ross 	 * (smb_cmn_oplock.c) encodes what kind of action we
59494047d49SGordon Ross 	 * need to take at the SMB level.
59594047d49SGordon Ross 	 */
59694047d49SGordon Ross 	switch (status) {
59794047d49SGordon Ross 
59894047d49SGordon Ross 	case NT_STATUS_SUCCESS:
59994047d49SGordon Ross 	case NT_STATUS_CANNOT_GRANT_REQUESTED_OPLOCK:
60094047d49SGordon Ross 		test_oplock_send_brk(ofile, NewLevel, AckReq);
60194047d49SGordon Ross 		break;
60294047d49SGordon Ross 
60394047d49SGordon Ross 	case NT_STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE:
60494047d49SGordon Ross 	case NT_STATUS_OPLOCK_HANDLE_CLOSED:
60594047d49SGordon Ross 		og->og_state = OPLOCK_LEVEL_NONE;
60694047d49SGordon Ross 		break;
60794047d49SGordon Ross 
60894047d49SGordon Ross 	default:
60994047d49SGordon Ross 		/* Checked by caller. */
61094047d49SGordon Ross 		ASSERT(0);
61194047d49SGordon Ross 		break;
61294047d49SGordon Ross 	}
61394047d49SGordon Ross }
61494047d49SGordon Ross 
61594047d49SGordon Ross void
61694047d49SGordon Ross smb_oplock_ind_break_in_ack(smb_request_t *sr, smb_ofile_t *ofile,
61794047d49SGordon Ross     uint32_t NewLevel, boolean_t AckRequired)
61894047d49SGordon Ross {
61994047d49SGordon Ross 	ASSERT(sr == &test_sr);
62094047d49SGordon Ross 	smb_oplock_ind_break(ofile, NewLevel, AckRequired, STATUS_CANT_GRANT);
62194047d49SGordon Ross }
62294047d49SGordon Ross 
62394047d49SGordon Ross uint32_t
62494047d49SGordon Ross smb_oplock_wait_break(smb_node_t *node, int timeout)
62594047d49SGordon Ross {
62694047d49SGordon Ross 	printf("*smb_oplock_wait_break (state=0x%x)\n",
62794047d49SGordon Ross 	    node->n_oplock.ol_state);
62894047d49SGordon Ross 	return (0);
62994047d49SGordon Ross }
63094047d49SGordon Ross 
63194047d49SGordon Ross /*
63294047d49SGordon Ross  * There are a couple DTRACE_PROBE* in smb_cmn_oplock.c but we're
63394047d49SGordon Ross  * not linking with the user-level dtrace support, so just
63494047d49SGordon Ross  * stub these out.
63594047d49SGordon Ross  */
63694047d49SGordon Ross void
63794047d49SGordon Ross __dtrace_fksmb___probe1(char *n, unsigned long a)
63894047d49SGordon Ross {
63994047d49SGordon Ross }
64094047d49SGordon Ross void
64194047d49SGordon Ross __dtrace_fksmb___probe2(char *n, unsigned long a, unsigned long b)
64294047d49SGordon Ross {
64394047d49SGordon Ross }
644