summaryrefslogtreecommitdiff
path: root/usr/src/cmd/smbsrv/testoplock/tol_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/smbsrv/testoplock/tol_main.c')
-rw-r--r--usr/src/cmd/smbsrv/testoplock/tol_main.c123
1 files changed, 79 insertions, 44 deletions
diff --git a/usr/src/cmd/smbsrv/testoplock/tol_main.c b/usr/src/cmd/smbsrv/testoplock/tol_main.c
index 7691edbca3..8cc81a4343 100644
--- a/usr/src/cmd/smbsrv/testoplock/tol_main.c
+++ b/usr/src/cmd/smbsrv/testoplock/tol_main.c
@@ -36,6 +36,8 @@
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_oplock.h>
+extern const char *xlate_nt_status(uint32_t);
+
#define OPLOCK_CACHE_RWH (READ_CACHING | HANDLE_CACHING | WRITE_CACHING)
#define OPLOCK_TYPE (LEVEL_TWO_OPLOCK | LEVEL_ONE_OPLOCK |\
BATCH_OPLOCK | OPLOCK_LEVEL_GRANULAR)
@@ -48,7 +50,7 @@ smb_request_t test_sr;
uint32_t last_ind_break_level;
char cmdbuf[100];
-extern const char *xlate_nt_status(uint32_t);
+static void run_ind_break_in_ack(smb_ofile_t *);
#define BIT_DEF(name) { name, #name }
@@ -134,16 +136,20 @@ do_show(void)
printf(" ofile_cnt=%d\n", node->n_ofile_list.ll_count);
FOREACH_NODE_OFILE(node, f) {
smb_oplock_grant_t *og = &f->f_oplock;
- printf(" fid=%d Lease=%s OgState=0x%x Brk=0x%x",
+ printf(" fid=%d Lease=%s State=0x%x",
f->f_fid,
f->TargetOplockKey, /* lease */
- f->f_oplock.og_state,
- f->f_oplock.og_breaking);
- printf(" Excl=%s onlist: %s %s %s",
- (ol->excl_open == f) ? "Y" : "N",
- og->onlist_II ? "II" : "",
- og->onlist_R ? "R" : "",
- og->onlist_RH ? "RH" : "");
+ og->og_state);
+ if (og->og_breaking)
+ printf(" BreakTo=0x%x", og->og_breakto);
+ printf(" Excl=%s onlist:",
+ (ol->excl_open == f) ? "Y" : "N");
+ if (og->onlist_II)
+ printf(" II");
+ if (og->onlist_R)
+ printf(" R");
+ if (og->onlist_RH)
+ printf(" RH");
if (og->onlist_RHBQ) {
printf(" RHBQ(to %s)",
og->BreakingToRead ?
@@ -224,8 +230,13 @@ do_req(int fid, char *arg2)
* Request an oplock
*/
status = smb_oplock_request(&test_sr, ofile, &oplock);
- if (status == 0)
+ if (status == 0 ||
+ status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
ofile->f_oplock.og_state = oplock;
+ /* When no break pending, breakto=state */
+ ofile->f_oplock.og_breakto = oplock;
+ ofile->f_oplock.og_breaking = B_FALSE;
+ }
printf(" req oplock fid=%d ret oplock=0x%x status=0x%x (%s)\n",
fid, oplock, status, xlate_nt_status(status));
}
@@ -249,18 +260,22 @@ do_ack(int fid, char *arg2)
ofile->f_oplock.og_breaking = 0;
status = smb_oplock_ack_break(&test_sr, ofile, &oplock);
- if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_SUCCESS)
+ if (status == 0)
ofile->f_oplock.og_state = oplock;
mutex_exit(&node->n_oplock.ol_mutex);
smb_llist_exit(&node->n_ofile_list);
if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
+ /* should not get this status */
printf(" ack: break fid=%d, break-in-progress\n", fid);
+ ASSERT(0);
}
printf(" ack: break fid=%d, newstate=0x%x, status=0x%x (%s)\n",
fid, oplock, status, xlate_nt_status(status));
+
+ run_ind_break_in_ack(ofile);
}
static void
@@ -335,8 +350,8 @@ do_brk_setinfo(int fid, char *arg2)
status = smb_oplock_break_SETINFO(
&test_node, ofile, infoclass);
- printf(" brk-setinfo %d ret status=0x%x (%s)\n",
- fid, status, xlate_nt_status(status));
+ printf(" brk-setinfo %d 0x%x ret status=0x%x (%s)\n",
+ fid, infoclass, status, xlate_nt_status(status));
}
@@ -559,47 +574,35 @@ smb_lock_range_access(
/*
* Test code replacement for combination of:
* smb_oplock_hdl_update()
- * smb_oplock_send_brk()
+ * smb_oplock_send_break()
+ *
+ * In a real server, we would send a break to the client,
+ * and keep track (at the SMB level) whether this oplock
+ * was obtained via a lease or an old-style oplock.
*/
static void
-test_oplock_send_brk(smb_ofile_t *ofile,
+test_oplock_send_break(smb_ofile_t *ofile,
uint32_t NewLevel, boolean_t AckReq)
{
smb_oplock_grant_t *og = &ofile->f_oplock;
+ uint32_t OldLevel;
/* Skip building a message. */
if ((og->og_state & OPLOCK_LEVEL_GRANULAR) != 0)
NewLevel |= OPLOCK_LEVEL_GRANULAR;
- /*
- * In a real server, we would send a break to the client,
- * and keep track (at the SMB level) whether this oplock
- * was obtained via a lease or an old-style oplock.
- *
- * This part like: smb_oplock_hdl_update()
- */
- if (AckReq) {
- uint32_t BreakTo;
-
- if ((og->og_state & OPLOCK_LEVEL_GRANULAR) != 0) {
-
- BreakTo = (NewLevel & CACHE_RWH) << BREAK_SHIFT;
- if (BreakTo == 0)
- BreakTo = BREAK_TO_NO_CACHING;
- // ls_breaking = BreakTo;
- } else {
- if ((NewLevel & LEVEL_TWO_OPLOCK) != 0)
- BreakTo = BREAK_TO_TWO;
- else
- BreakTo = BREAK_TO_NONE;
- }
- og->og_breaking = BreakTo;
- /* Set og_state in do_ack */
- } else {
+ OldLevel = og->og_state;
+ og->og_breakto = NewLevel;
+ og->og_breaking = B_TRUE;
+
+ printf("*smb_oplock_send_break fid=%d "
+ "NewLevel=0x%x, OldLevel=0x%x, AckReq=%d)\n",
+ ofile->f_fid, NewLevel, OldLevel, AckReq);
+
+ if (!AckReq) {
og->og_state = NewLevel;
- // If lease: ls_breaking = ...
- /* Clear og_breaking in do_ack */
+ og->og_breaking = B_FALSE;
}
/* Next, smb_oplock_send_break() would send a break. */
@@ -629,12 +632,14 @@ smb_oplock_ind_break(smb_ofile_t *ofile, uint32_t NewLevel,
case NT_STATUS_SUCCESS:
case NT_STATUS_CANNOT_GRANT_REQUESTED_OPLOCK:
- test_oplock_send_brk(ofile, NewLevel, AckReq);
+ test_oplock_send_break(ofile, NewLevel, AckReq);
break;
case NT_STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE:
case NT_STATUS_OPLOCK_HANDLE_CLOSED:
og->og_state = OPLOCK_LEVEL_NONE;
+ og->og_breakto = OPLOCK_LEVEL_NONE;
+ og->og_breaking = B_FALSE;
break;
default:
@@ -643,12 +648,42 @@ smb_oplock_ind_break(smb_ofile_t *ofile, uint32_t NewLevel,
}
}
+/* Arrange for break_in_ack to run after ack completes. */
+static uint32_t break_in_ack_NewLevel;
+static boolean_t break_in_ack_AckReq;
+static boolean_t break_in_ack_called;
+
void
smb_oplock_ind_break_in_ack(smb_request_t *sr, smb_ofile_t *ofile,
uint32_t NewLevel, boolean_t AckRequired)
{
ASSERT(sr == &test_sr);
- smb_oplock_ind_break(ofile, NewLevel, AckRequired, STATUS_CANT_GRANT);
+
+ /* Process these after ack */
+ ASSERT(!break_in_ack_called);
+ break_in_ack_called = B_TRUE;
+ break_in_ack_NewLevel = NewLevel;
+ break_in_ack_AckReq = AckRequired;
+}
+
+static void
+run_ind_break_in_ack(smb_ofile_t *ofile)
+{
+ uint32_t NewLevel;
+ boolean_t AckReq;
+
+ /* Process these after ack */
+ if (!break_in_ack_called)
+ return;
+ break_in_ack_called = B_FALSE;
+ NewLevel = break_in_ack_NewLevel;
+ AckReq = break_in_ack_AckReq;
+
+ printf("*smb_oplock_ind_break_in_ack fid=%d NewLevel=0x%x,"
+ " AckReq=%d\n",
+ ofile->f_fid, NewLevel, AckReq);
+
+ test_oplock_send_break(ofile, NewLevel, AckReq);
}
uint32_t