diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/smbd/open.c | 2 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 75 |
2 files changed, 59 insertions, 18 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bf3fbf7fec..70632a20eb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -665,7 +665,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); - opb_ret = request_oplock_break(share_entry, False); + opb_ret = request_oplock_break(share_entry); /* Now relock. */ lock_share_entry(conn, dev, inode); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 8d1b6911e7..a55d5443d5 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -944,12 +944,12 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, } /**************************************************************************** -Send an oplock break message to another smbd process. If the oplock is held -by the local smbd then call the oplock break function directly. -Note this function is always called with the share mode lock *NOT* held. + Send an oplock break message to another smbd process. If the oplock is held + by the local smbd then call the oplock break function directly. + This function is called with no share locks held. ****************************************************************************/ -BOOL request_oplock_break(share_mode_entry *share_entry, BOOL async) +BOOL request_oplock_break(share_mode_entry *share_entry) { char op_break_msg[OPLOCK_BREAK_MSG_LEN]; struct sockaddr_in addr_out; @@ -990,7 +990,7 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", /* We need to send a OPLOCK_BREAK_CMD message to the port in the share mode entry. */ if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - break_cmd_type = async ? ASYNC_LEVEL_II_OPLOCK_BREAK_CMD : LEVEL_II_OPLOCK_BREAK_CMD; + break_cmd_type = LEVEL_II_OPLOCK_BREAK_CMD; } else { break_cmd_type = OPLOCK_BREAK_CMD; } @@ -1008,7 +1008,7 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", addr_out.sin_family = AF_INET; if( DEBUGLVL( 3 ) ) { - dbgtext( "request_oplock_break: sending a %s oplock break message to ", async ? "asynchronous" : "synchronous" ); + dbgtext( "request_oplock_break: sending a synchronous oplock break message to " ); dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id ); @@ -1028,16 +1028,6 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", } /* - * If we just sent a message to a level II oplock share entry in async mode then - * we are done and may return. - */ - - if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type) && async) { - DEBUG(3,("request_oplock_break: sent async break message to level II entry.\n")); - return True; - } - - /* * Now we must await the oplock broken message coming back * from the target smbd process. Timeout if it fails to * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds. @@ -1150,6 +1140,57 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) } /**************************************************************************** + Send an asynchronous oplock break message to another smbd process. +****************************************************************************/ + +static BOOL request_remote_level2_async_oplock_break(share_mode_entry *share_entry) +{ + char op_break_msg[OPLOCK_BREAK_MSG_LEN]; + struct sockaddr_in addr_out; + pid_t pid = sys_getpid(); + SMB_DEV_T dev = share_entry->dev; + SMB_INO_T inode = share_entry->inode; + unsigned long file_id = share_entry->share_file_id; + + /* We need to send a ASYNC_LEVEL_II_OPLOCK_BREAK_CMD message to the port in the share mode entry. */ + + SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,ASYNC_LEVEL_II_OPLOCK_BREAK_CMD); + memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); + memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); + memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); + memcpy(op_break_msg+OPLOCK_BREAK_FILEID_OFFSET,(char *)&file_id,sizeof(file_id)); + + /* Set the address and port. */ + memset((char *)&addr_out,'\0',sizeof(addr_out)); + addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr_out.sin_port = htons( share_entry->op_port ); + addr_out.sin_family = AF_INET; + + if( DEBUGLVL( 3 ) ) { + dbgtext( "request_remote_level2_async_oplock_break: sending an asynchronous oplock break message to "); + dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id ); + } + + if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, + (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "request_remote_level2_async_oplock_break: failed when sending a oplock " ); + dbgtext( "break message to pid %d ", (int)share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id ); + dbgtext( "Error was %s\n", strerror(errno) ); + } + return False; + } + + DEBUG(3,("request_remote_level2_async_oplock_break: sent async break message to level II entry.\n")); + return True; +} + +/**************************************************************************** This function is called on any file modification or lock request. If a file is level 2 oplocked then it must tell all other level 2 holders to break to none. ****************************************************************************/ @@ -1234,7 +1275,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) */ DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock (async).\n")); - request_oplock_break(share_entry, True); + request_remote_level2_async_oplock_break(share_entry); } } |