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