2003-08-13 01:53:07 +00:00
/*
Unix SMB / CIFS implementation .
basic raw test suite for oplocks
Copyright ( C ) Andrew Tridgell 2003
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2006-01-03 13:41:17 +00:00
# include "torture/torture.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/security.h"
2005-12-28 15:38:36 +00:00
# include "libcli/raw/libcliraw.h"
2006-01-03 15:40:05 +00:00
# include "libcli/libcli.h"
2006-03-17 17:59:58 +00:00
# include "torture/util.h"
2006-04-10 04:51:52 +00:00
# include "lib/events/events.h"
2003-08-13 01:53:07 +00:00
# define CHECK_VAL(v, correct) do { \
if ( ( v ) ! = ( correct ) ) { \
2004-05-30 08:12:17 +00:00
printf ( " (%d) wrong value for %s got 0x%x - should be 0x%x \n " , \
2003-08-13 01:53:07 +00:00
__LINE__ , # v , ( int ) v , ( int ) correct ) ; \
ret = False ; \
} } while ( 0 )
# define CHECK_STATUS(status, correct) do { \
if ( ! NT_STATUS_EQUAL ( status , correct ) ) { \
printf ( " (%d) Incorrect status %s - should be %s \n " , \
__LINE__ , nt_errstr ( status ) , nt_errstr ( correct ) ) ; \
ret = False ; \
goto done ; \
} } while ( 0 )
static struct {
int fnum ;
2004-05-29 08:11:46 +00:00
uint8_t level ;
2003-08-13 01:53:07 +00:00
int count ;
2005-12-28 22:18:45 +00:00
int failures ;
2003-08-13 01:53:07 +00:00
} break_info ;
2006-04-10 04:51:52 +00:00
# define BASEDIR "\\test_notify"
2003-08-13 01:53:07 +00:00
/*
2006-04-11 04:40:11 +00:00
a handler function for oplock break requests . Ack it as a break to level II if possible
2003-08-13 01:53:07 +00:00
*/
2006-04-11 04:40:11 +00:00
static BOOL oplock_handler_ack_to_levelII ( struct smbcli_transport * transport , uint16_t tid ,
uint16_t fnum , uint8_t level , void * private )
2003-08-13 01:53:07 +00:00
{
2004-08-04 13:23:35 +00:00
struct smbcli_tree * tree = private ;
2003-08-13 01:53:07 +00:00
break_info . fnum = fnum ;
break_info . level = level ;
break_info . count + + ;
2006-04-11 04:40:11 +00:00
printf ( " Acking to level II in oplock handler \n " ) ;
2003-08-13 01:53:07 +00:00
2004-08-04 13:23:35 +00:00
return smbcli_oplock_ack ( tree , fnum , level ) ;
2003-08-13 01:53:07 +00:00
}
2006-04-11 04:40:11 +00:00
/*
a handler function for oplock break requests . Ack it as a break to none
*/
static BOOL oplock_handler_ack_to_none ( struct smbcli_transport * transport , uint16_t tid ,
uint16_t fnum , uint8_t level ,
void * private )
{
struct smbcli_tree * tree = private ;
break_info . fnum = fnum ;
break_info . level = level ;
break_info . count + + ;
printf ( " Acking to none in oplock handler \n " ) ;
return smbcli_oplock_ack ( tree , fnum , OPLOCK_BREAK_TO_NONE ) ;
}
2005-12-28 22:18:45 +00:00
static void oplock_handler_close_recv ( struct smbcli_request * req )
{
NTSTATUS status ;
status = smbcli_request_simple_recv ( req ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " close failed in oplock_handler_close \n " ) ;
break_info . failures + + ;
}
}
2003-08-13 01:53:07 +00:00
/*
a handler function for oplock break requests - close the file
*/
2006-04-11 04:40:11 +00:00
static BOOL oplock_handler_close ( struct smbcli_transport * transport , uint16_t tid ,
uint16_t fnum , uint8_t level , void * private )
2003-08-13 01:53:07 +00:00
{
union smb_close io ;
2004-08-04 13:23:35 +00:00
struct smbcli_tree * tree = private ;
2005-12-28 22:18:45 +00:00
struct smbcli_request * req ;
2003-08-13 01:53:07 +00:00
break_info . fnum = fnum ;
break_info . level = level ;
break_info . count + + ;
io . close . level = RAW_CLOSE_CLOSE ;
2006-03-12 22:48:25 +00:00
io . close . in . file . fnum = fnum ;
2003-08-13 01:53:07 +00:00
io . close . in . write_time = 0 ;
2005-12-28 22:18:45 +00:00
req = smb_raw_close_send ( tree , & io ) ;
if ( req = = NULL ) {
printf ( " failed to send close in oplock_handler_close \n " ) ;
2003-08-13 01:53:07 +00:00
return False ;
}
2005-12-28 22:18:45 +00:00
req - > async . fn = oplock_handler_close_recv ;
req - > async . private = NULL ;
2003-08-13 01:53:07 +00:00
return True ;
}
/*
test oplock ops
*/
2004-08-04 13:23:35 +00:00
static BOOL test_oplock ( struct smbcli_state * cli , TALLOC_CTX * mem_ctx )
2003-08-13 01:53:07 +00:00
{
2006-04-10 04:51:52 +00:00
const char * fname = BASEDIR " \\ test_oplock.dat " ;
2003-08-13 01:53:07 +00:00
NTSTATUS status ;
BOOL ret = True ;
union smb_open io ;
2006-03-10 20:49:20 +00:00
union smb_unlink unl ;
2003-08-13 01:53:07 +00:00
union smb_read rd ;
2004-08-03 06:50:58 +00:00
uint16_t fnum = 0 , fnum2 = 0 ;
2006-04-11 04:40:11 +00:00
char c = 0 ;
2003-08-13 01:53:07 +00:00
/* cleanup */
2004-08-04 13:23:35 +00:00
smbcli_unlink ( cli - > tree , fname ) ;
2003-08-13 01:53:07 +00:00
2006-04-11 04:40:11 +00:00
smbcli_oplock_handler ( cli - > transport , oplock_handler_ack_to_levelII , cli - > tree ) ;
2003-08-13 01:53:07 +00:00
/*
base ntcreatex parms
*/
io . generic . level = RAW_OPEN_NTCREATEX ;
io . ntcreatex . in . root_fid = 0 ;
2004-12-02 04:37:36 +00:00
io . ntcreatex . in . access_mask = SEC_RIGHTS_FILE_ALL ;
2003-08-13 01:53:07 +00:00
io . ntcreatex . in . alloc_size = 0 ;
io . ntcreatex . in . file_attr = FILE_ATTRIBUTE_NORMAL ;
io . ntcreatex . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
io . ntcreatex . in . open_disposition = NTCREATEX_DISP_OPEN_IF ;
io . ntcreatex . in . create_options = 0 ;
io . ntcreatex . in . impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS ;
io . ntcreatex . in . security_flags = 0 ;
io . ntcreatex . in . fname = fname ;
printf ( " open a file with a normal oplock \n " ) ;
ZERO_STRUCT ( break_info ) ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum = io . ntcreatex . out . file . fnum ;
2003-08-13 01:53:07 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , EXCLUSIVE_OPLOCK_RETURN ) ;
2006-04-10 06:06:26 +00:00
printf ( " a 2nd open should not cause a break \n " ) ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_SHARING_VIOLATION ) ;
CHECK_VAL ( break_info . count , 0 ) ;
CHECK_VAL ( break_info . failures , 0 ) ;
printf ( " unlink it - should also be no break \n " ) ;
2006-03-10 20:49:20 +00:00
unl . unlink . in . pattern = fname ;
unl . unlink . in . attrib = 0 ;
2003-08-13 01:53:07 +00:00
status = smb_raw_unlink ( cli - > tree , & unl ) ;
CHECK_STATUS ( status , NT_STATUS_SHARING_VIOLATION ) ;
CHECK_VAL ( break_info . count , 0 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2003-08-13 01:53:07 +00:00
2004-08-04 13:23:35 +00:00
smbcli_close ( cli - > tree , fnum ) ;
2003-08-13 01:53:07 +00:00
/*
with a batch oplock we get a break
*/
printf ( " open with batch oplock \n " ) ;
ZERO_STRUCT ( break_info ) ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum = io . ntcreatex . out . file . fnum ;
2003-08-13 01:53:07 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , BATCH_OPLOCK_RETURN ) ;
printf ( " unlink should generate a break \n " ) ;
2006-03-10 20:49:20 +00:00
unl . unlink . in . pattern = fname ;
unl . unlink . in . attrib = 0 ;
2003-08-13 01:53:07 +00:00
status = smb_raw_unlink ( cli - > tree , & unl ) ;
CHECK_STATUS ( status , NT_STATUS_SHARING_VIOLATION ) ;
2006-04-11 04:40:11 +00:00
CHECK_VAL ( break_info . count , 1 ) ;
2003-08-13 01:53:07 +00:00
CHECK_VAL ( break_info . fnum , fnum ) ;
2006-04-11 04:40:11 +00:00
CHECK_VAL ( break_info . level , OPLOCK_BREAK_TO_LEVEL_II ) ;
CHECK_VAL ( break_info . failures , 0 ) ;
printf ( " 2nd unlink should not generate a break \n " ) ;
ZERO_STRUCT ( break_info ) ;
status = smb_raw_unlink ( cli - > tree , & unl ) ;
CHECK_STATUS ( status , NT_STATUS_SHARING_VIOLATION ) ;
CHECK_VAL ( break_info . count , 0 ) ;
printf ( " writing should generate a self break to none \n " ) ;
smbcli_write ( cli - > tree , fnum , 0 , & c , 0 , 1 ) ;
msleep ( 100 ) ;
smbcli_write ( cli - > tree , fnum , 0 , & c , 1 , 1 ) ;
2003-08-13 01:53:07 +00:00
CHECK_VAL ( break_info . count , 1 ) ;
2006-04-11 04:40:11 +00:00
CHECK_VAL ( break_info . fnum , fnum ) ;
CHECK_VAL ( break_info . level , OPLOCK_BREAK_TO_NONE ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2003-08-13 01:53:07 +00:00
2004-08-04 13:23:35 +00:00
smbcli_close ( cli - > tree , fnum ) ;
2003-08-13 01:53:07 +00:00
2006-04-11 04:40:11 +00:00
printf ( " open with batch oplock \n " ) ;
ZERO_STRUCT ( break_info ) ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
fnum = io . ntcreatex . out . file . fnum ;
CHECK_VAL ( io . ntcreatex . out . oplock_level , BATCH_OPLOCK_RETURN ) ;
printf ( " unlink should generate a break, which we ack as break to none \n " ) ;
smbcli_oplock_handler ( cli - > transport , oplock_handler_ack_to_none , cli - > tree ) ;
unl . unlink . in . pattern = fname ;
unl . unlink . in . attrib = 0 ;
status = smb_raw_unlink ( cli - > tree , & unl ) ;
CHECK_STATUS ( status , NT_STATUS_SHARING_VIOLATION ) ;
CHECK_VAL ( break_info . count , 1 ) ;
CHECK_VAL ( break_info . fnum , fnum ) ;
CHECK_VAL ( break_info . level , OPLOCK_BREAK_TO_LEVEL_II ) ;
CHECK_VAL ( break_info . failures , 0 ) ;
printf ( " 2nd unlink should not generate a break \n " ) ;
ZERO_STRUCT ( break_info ) ;
status = smb_raw_unlink ( cli - > tree , & unl ) ;
CHECK_STATUS ( status , NT_STATUS_SHARING_VIOLATION ) ;
CHECK_VAL ( break_info . count , 0 ) ;
printf ( " writing should not generate a break \n " ) ;
smbcli_write ( cli - > tree , fnum , 0 , & c , 0 , 1 ) ;
msleep ( 100 ) ;
smbcli_write ( cli - > tree , fnum , 0 , & c , 1 , 1 ) ;
CHECK_VAL ( break_info . count , 0 ) ;
smbcli_close ( cli - > tree , fnum ) ;
2003-08-13 01:53:07 +00:00
printf ( " if we close on break then the unlink can succeed \n " ) ;
ZERO_STRUCT ( break_info ) ;
2004-08-04 13:23:35 +00:00
smbcli_oplock_handler ( cli - > transport , oplock_handler_close , cli - > tree ) ;
2003-08-13 01:53:07 +00:00
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum = io . ntcreatex . out . file . fnum ;
2003-08-13 01:53:07 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , BATCH_OPLOCK_RETURN ) ;
2006-03-10 20:49:20 +00:00
unl . unlink . in . pattern = fname ;
unl . unlink . in . attrib = 0 ;
2003-08-13 01:53:07 +00:00
ZERO_STRUCT ( break_info ) ;
status = smb_raw_unlink ( cli - > tree , & unl ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-04-11 04:40:11 +00:00
CHECK_VAL ( break_info . count , 1 ) ;
2003-08-13 01:53:07 +00:00
CHECK_VAL ( break_info . fnum , fnum ) ;
2004-05-30 08:12:17 +00:00
CHECK_VAL ( break_info . level , 1 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2003-08-13 01:53:07 +00:00
printf ( " a self read should not cause a break \n " ) ;
ZERO_STRUCT ( break_info ) ;
2004-08-04 13:23:35 +00:00
smbcli_close ( cli - > tree , fnum ) ;
2006-04-11 04:40:11 +00:00
smbcli_oplock_handler ( cli - > transport , oplock_handler_ack_to_levelII , cli - > tree ) ;
2003-08-13 01:53:07 +00:00
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum = io . ntcreatex . out . file . fnum ;
2003-08-13 01:53:07 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , BATCH_OPLOCK_RETURN ) ;
rd . read . level = RAW_READ_READ ;
2006-03-12 22:48:25 +00:00
rd . read . in . file . fnum = fnum ;
2003-08-13 01:53:07 +00:00
rd . read . in . count = 1 ;
rd . read . in . offset = 0 ;
rd . read . in . remaining = 0 ;
status = smb_raw_read ( cli - > tree , & rd ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
CHECK_VAL ( break_info . count , 0 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2003-08-13 01:53:07 +00:00
printf ( " a 2nd open should give a break \n " ) ;
ZERO_STRUCT ( break_info ) ;
2004-08-04 13:23:35 +00:00
smbcli_close ( cli - > tree , fnum ) ;
2006-04-11 04:40:11 +00:00
smbcli_oplock_handler ( cli - > transport , oplock_handler_ack_to_levelII , cli - > tree ) ;
2003-08-13 01:53:07 +00:00
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum = io . ntcreatex . out . file . fnum ;
2003-08-13 01:53:07 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , BATCH_OPLOCK_RETURN ) ;
ZERO_STRUCT ( break_info ) ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_SHARING_VIOLATION ) ;
CHECK_VAL ( break_info . count , 1 ) ;
CHECK_VAL ( break_info . fnum , fnum ) ;
2004-05-30 08:12:17 +00:00
CHECK_VAL ( break_info . level , 1 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2003-08-13 01:53:07 +00:00
2006-04-11 04:40:11 +00:00
printf ( " a 2nd open should give a break to level II if the first open allowed shared read \n " ) ;
ZERO_STRUCT ( break_info ) ;
smbcli_close ( cli - > tree , fnum ) ;
smbcli_oplock_handler ( cli - > transport , oplock_handler_ack_to_levelII , cli - > tree ) ;
io . ntcreatex . in . access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE ;
io . ntcreatex . in . share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
fnum = io . ntcreatex . out . file . fnum ;
CHECK_VAL ( io . ntcreatex . out . oplock_level , BATCH_OPLOCK_RETURN ) ;
ZERO_STRUCT ( break_info ) ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
CHECK_VAL ( io . ntcreatex . out . oplock_level , LEVEL_II_OPLOCK_RETURN ) ;
CHECK_VAL ( break_info . count , 1 ) ;
CHECK_VAL ( break_info . fnum , fnum ) ;
CHECK_VAL ( break_info . level , 1 ) ;
CHECK_VAL ( break_info . failures , 0 ) ;
ZERO_STRUCT ( break_info ) ;
printf ( " write should trigger a break to none on both \n " ) ;
smbcli_write ( cli - > tree , fnum , 0 , & c , 0 , 1 ) ;
msleep ( 100 ) ;
smbcli_write ( cli - > tree , fnum , 0 , & c , 1 , 1 ) ;
CHECK_VAL ( break_info . count , 2 ) ;
CHECK_VAL ( break_info . level , 0 ) ;
CHECK_VAL ( break_info . failures , 0 ) ;
smb_raw_exit ( cli - > session ) ;
2003-08-13 01:53:07 +00:00
printf ( " a 2nd open should get an oplock when we close instead of ack \n " ) ;
ZERO_STRUCT ( break_info ) ;
2004-08-04 13:23:35 +00:00
smbcli_close ( cli - > tree , fnum ) ;
smbcli_oplock_handler ( cli - > transport , oplock_handler_close , cli - > tree ) ;
2003-08-13 01:53:07 +00:00
2006-04-11 04:40:11 +00:00
io . ntcreatex . in . access_mask = SEC_RIGHTS_FILE_ALL ;
io . ntcreatex . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
2003-08-13 01:53:07 +00:00
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum2 = io . ntcreatex . out . file . fnum ;
2003-08-13 01:53:07 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , BATCH_OPLOCK_RETURN ) ;
ZERO_STRUCT ( break_info ) ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum = io . ntcreatex . out . file . fnum ;
2003-08-13 01:53:07 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , BATCH_OPLOCK_RETURN ) ;
CHECK_VAL ( break_info . count , 1 ) ;
CHECK_VAL ( break_info . fnum , fnum2 ) ;
2004-05-30 08:12:17 +00:00
CHECK_VAL ( break_info . level , 1 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2003-08-13 01:53:07 +00:00
2004-08-04 13:23:35 +00:00
smbcli_close ( cli - > tree , fnum ) ;
2004-05-25 00:05:51 +00:00
printf ( " open with batch oplock \n " ) ;
ZERO_STRUCT ( break_info ) ;
2006-04-11 04:40:11 +00:00
smbcli_oplock_handler ( cli - > transport , oplock_handler_ack_to_levelII , cli - > tree ) ;
2004-05-25 00:05:51 +00:00
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum = io . ntcreatex . out . file . fnum ;
2004-05-25 00:05:51 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , BATCH_OPLOCK_RETURN ) ;
ZERO_STRUCT ( break_info ) ;
printf ( " second open with attributes only shouldn't cause oplock break \n " ) ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
2004-11-30 04:33:27 +00:00
io . ntcreatex . in . access_mask = SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_ATTRIBUTE | SEC_STD_SYNCHRONIZE ;
2004-05-25 00:05:51 +00:00
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum2 = io . ntcreatex . out . file . fnum ;
2004-05-25 00:05:51 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , NO_OPLOCK_RETURN ) ;
CHECK_VAL ( break_info . count , 0 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2003-08-13 01:53:07 +00:00
2004-08-04 13:23:35 +00:00
smbcli_close ( cli - > tree , fnum ) ;
smbcli_close ( cli - > tree , fnum2 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
2004-05-30 08:12:17 +00:00
printf ( " open with attributes only can create file \n " ) ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
2004-11-30 04:33:27 +00:00
io . ntcreatex . in . access_mask = SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_ATTRIBUTE | SEC_STD_SYNCHRONIZE ;
2004-05-30 08:12:17 +00:00
io . ntcreatex . in . open_disposition = NTCREATEX_DISP_CREATE ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum = io . ntcreatex . out . file . fnum ;
2004-05-30 08:12:17 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , BATCH_OPLOCK_RETURN ) ;
printf ( " Subsequent normal open should break oplock on attribute only open to level II \n " ) ;
ZERO_STRUCT ( break_info ) ;
2006-04-11 04:40:11 +00:00
smbcli_oplock_handler ( cli - > transport , oplock_handler_ack_to_levelII , cli - > tree ) ;
2004-05-30 08:12:17 +00:00
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
2004-12-02 04:37:36 +00:00
io . ntcreatex . in . access_mask = SEC_RIGHTS_FILE_ALL ;
2004-05-30 08:12:17 +00:00
io . ntcreatex . in . open_disposition = NTCREATEX_DISP_OPEN ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum2 = io . ntcreatex . out . file . fnum ;
2004-05-30 08:12:17 +00:00
CHECK_VAL ( break_info . count , 1 ) ;
CHECK_VAL ( break_info . fnum , fnum ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2006-04-11 04:40:11 +00:00
CHECK_VAL ( break_info . level , OPLOCK_BREAK_TO_LEVEL_II ) ;
2004-05-30 08:12:17 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , LEVEL_II_OPLOCK_RETURN ) ;
2005-07-08 06:29:06 +00:00
smbcli_close ( cli - > tree , fnum2 ) ;
printf ( " third oplocked open should grant level2 without break \n " ) ;
ZERO_STRUCT ( break_info ) ;
2006-04-11 04:40:11 +00:00
smbcli_oplock_handler ( cli - > transport , oplock_handler_ack_to_levelII , cli - > tree ) ;
2005-07-08 06:29:06 +00:00
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
io . ntcreatex . in . access_mask = SEC_RIGHTS_FILE_ALL ;
io . ntcreatex . in . open_disposition = NTCREATEX_DISP_OPEN ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum2 = io . ntcreatex . out . file . fnum ;
2005-07-08 06:29:06 +00:00
CHECK_VAL ( break_info . count , 0 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2005-07-08 06:29:06 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , LEVEL_II_OPLOCK_RETURN ) ;
ZERO_STRUCT ( break_info ) ;
printf ( " write should trigger a break to none on both \n " ) ;
2006-04-11 04:40:11 +00:00
smbcli_write ( cli - > tree , fnum2 , 0 , & c , 0 , 1 ) ;
2005-07-08 06:29:06 +00:00
/* Now the oplock break request comes in. But right now we can't
* answer it . Do another write */
msleep ( 100 ) ;
2006-04-11 04:40:11 +00:00
smbcli_write ( cli - > tree , fnum2 , 0 , & c , 1 , 1 ) ;
2005-07-08 06:29:06 +00:00
CHECK_VAL ( break_info . count , 2 ) ;
CHECK_VAL ( break_info . level , 0 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2005-07-08 06:29:06 +00:00
smbcli_close ( cli - > tree , fnum ) ;
smbcli_close ( cli - > tree , fnum2 ) ;
ZERO_STRUCT ( break_info ) ;
2006-04-11 04:40:11 +00:00
smbcli_oplock_handler ( cli - > transport , oplock_handler_ack_to_levelII , cli - > tree ) ;
2005-07-08 06:29:06 +00:00
printf ( " Open with oplock after a on-oplock open should grant level2 \n " ) ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED ;
io . ntcreatex . in . access_mask = SEC_RIGHTS_FILE_ALL ;
io . ntcreatex . in . share_access = NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE |
NTCREATEX_SHARE_ACCESS_DELETE ;
io . ntcreatex . in . open_disposition = NTCREATEX_DISP_OPEN ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum = io . ntcreatex . out . file . fnum ;
2005-07-08 06:29:06 +00:00
CHECK_VAL ( break_info . count , 0 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2005-07-08 06:29:06 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , 0 ) ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
io . ntcreatex . in . access_mask = SEC_RIGHTS_FILE_ALL ;
io . ntcreatex . in . share_access = NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE |
NTCREATEX_SHARE_ACCESS_DELETE ;
io . ntcreatex . in . open_disposition = NTCREATEX_DISP_OPEN ;
status = smb_raw_open ( cli - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
2006-03-12 22:48:25 +00:00
fnum2 = io . ntcreatex . out . file . fnum ;
2005-07-08 06:29:06 +00:00
CHECK_VAL ( break_info . count , 0 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2005-07-08 06:29:06 +00:00
CHECK_VAL ( io . ntcreatex . out . oplock_level , LEVEL_II_OPLOCK_RETURN ) ;
printf ( " write should trigger a break to none \n " ) ;
{
union smb_write wr ;
wr . write . level = RAW_WRITE_WRITE ;
2006-03-12 22:48:25 +00:00
wr . write . in . file . fnum = fnum ;
2005-07-08 06:29:06 +00:00
wr . write . in . count = 1 ;
wr . write . in . offset = 0 ;
wr . write . in . remaining = 0 ;
2006-01-18 16:20:33 +00:00
wr . write . in . data = ( const uint8_t * ) " x " ;
2005-07-08 06:29:06 +00:00
status = smb_raw_write ( cli - > tree , & wr ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
}
/* Now the oplock break request comes in. But right now we can't
* answer it . Do another write */
msleep ( 100 ) ;
{
union smb_write wr ;
wr . write . level = RAW_WRITE_WRITE ;
2006-03-12 22:48:25 +00:00
wr . write . in . file . fnum = fnum ;
2005-07-08 06:29:06 +00:00
wr . write . in . count = 1 ;
wr . write . in . offset = 0 ;
wr . write . in . remaining = 0 ;
2006-01-18 16:20:33 +00:00
wr . write . in . data = ( const uint8_t * ) " x " ;
2005-07-08 06:29:06 +00:00
status = smb_raw_write ( cli - > tree , & wr ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
}
CHECK_VAL ( break_info . count , 1 ) ;
CHECK_VAL ( break_info . fnum , fnum2 ) ;
CHECK_VAL ( break_info . level , 0 ) ;
2005-12-28 22:18:45 +00:00
CHECK_VAL ( break_info . failures , 0 ) ;
2004-05-30 08:12:17 +00:00
2003-08-13 01:53:07 +00:00
done :
2004-08-04 13:23:35 +00:00
smbcli_close ( cli - > tree , fnum ) ;
smbcli_close ( cli - > tree , fnum2 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
2003-08-13 01:53:07 +00:00
return ret ;
}
/*
basic testing of oplocks
*/
2006-03-25 16:01:28 +00:00
BOOL torture_raw_oplock ( struct torture_context * torture )
2003-08-13 01:53:07 +00:00
{
2006-04-10 04:51:52 +00:00
struct smbcli_state * cli ;
2003-08-13 01:53:07 +00:00
BOOL ret = True ;
TALLOC_CTX * mem_ctx ;
2006-04-10 04:51:52 +00:00
if ( ! torture_open_connection ( & cli ) ) {
return False ;
}
if ( ! torture_setup_dir ( cli , BASEDIR ) ) {
2003-08-13 01:53:07 +00:00
return False ;
}
mem_ctx = talloc_init ( " torture_raw_oplock " ) ;
2006-04-10 04:51:52 +00:00
if ( ! test_oplock ( cli , mem_ctx ) ) {
ret = False ;
}
smb_raw_exit ( cli - > session ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
torture_close_connection ( cli ) ;
talloc_free ( mem_ctx ) ;
return ret ;
}
/*
stress testing of oplocks
*/
BOOL torture_bench_oplock ( struct torture_context * torture )
{
struct smbcli_state * * cli ;
BOOL ret = True ;
TALLOC_CTX * mem_ctx = talloc_new ( torture ) ;
extern int torture_nprocs ;
int i , count = 0 ;
int timelimit = lp_parm_int ( - 1 , " torture " , " timelimit " , 10 ) ;
union smb_open io ;
struct timeval tv ;
struct event_context * ev = event_context_find ( mem_ctx ) ;
cli = talloc_array ( mem_ctx , struct smbcli_state * , torture_nprocs ) ;
printf ( " Opening %d connections \n " , torture_nprocs ) ;
for ( i = 0 ; i < torture_nprocs ; i + + ) {
if ( ! torture_open_connection_ev ( & cli [ i ] , ev ) ) {
return False ;
}
talloc_steal ( mem_ctx , cli [ i ] ) ;
smbcli_oplock_handler ( cli [ i ] - > transport , oplock_handler_close ,
cli [ i ] - > tree ) ;
}
if ( ! torture_setup_dir ( cli [ 0 ] , BASEDIR ) ) {
2003-08-13 01:53:07 +00:00
ret = False ;
2006-04-10 04:51:52 +00:00
goto done ;
2003-08-13 01:53:07 +00:00
}
2006-04-10 04:51:52 +00:00
io . ntcreatex . level = RAW_OPEN_NTCREATEX ;
io . ntcreatex . in . root_fid = 0 ;
io . ntcreatex . in . access_mask = SEC_RIGHTS_FILE_ALL ;
io . ntcreatex . in . alloc_size = 0 ;
io . ntcreatex . in . file_attr = FILE_ATTRIBUTE_NORMAL ;
io . ntcreatex . in . share_access = NTCREATEX_SHARE_ACCESS_NONE ;
io . ntcreatex . in . open_disposition = NTCREATEX_DISP_OPEN_IF ;
io . ntcreatex . in . create_options = 0 ;
io . ntcreatex . in . impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS ;
io . ntcreatex . in . security_flags = 0 ;
io . ntcreatex . in . fname = BASEDIR " \\ test.dat " ;
io . ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED |
NTCREATEX_FLAGS_REQUEST_OPLOCK |
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK ;
tv = timeval_current ( ) ;
2006-04-10 05:12:49 +00:00
/*
we open the same file with SHARE_ACCESS_NONE from all the
connections in a round robin fashion . Each open causes an
oplock break on the previous connection , which is answered
by the oplock_handler_close ( ) to close the file .
This measures how fast we can pass on oplocks , and stresses
the oplock handling code
*/
2006-04-10 04:51:52 +00:00
printf ( " Running for %d seconds \n " , timelimit ) ;
while ( timeval_elapsed ( & tv ) < timelimit ) {
for ( i = 0 ; i < torture_nprocs ; i + + ) {
NTSTATUS status ;
status = smb_raw_open ( cli [ i ] - > tree , mem_ctx , & io ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
count + + ;
}
printf ( " %.2f ops/second \r " , count / timeval_elapsed ( & tv ) ) ;
}
printf ( " %.2f ops/second \n " , count / timeval_elapsed ( & tv ) ) ;
smb_raw_exit ( cli [ torture_nprocs - 1 ] - > session ) ;
done :
smb_raw_exit ( cli [ 0 ] - > session ) ;
smbcli_deltree ( cli [ 0 ] - > tree , BASEDIR ) ;
2005-01-27 07:08:20 +00:00
talloc_free ( mem_ctx ) ;
2003-08-13 01:53:07 +00:00
return ret ;
}