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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define DBGC_CLASS DBGC_LOCKING
#include "includes.h"
/* Current number of oplocks we have outstanding. */
static int32 exclusive_oplocks_open = 0;
static int32 level_II_oplocks_open = 0;
-BOOL global_client_failed_oplock_break = False;
+bool global_client_failed_oplock_break = False;
-extern struct timeval smb_last_time;
extern uint32 global_client_caps;
-extern int smb_read_error;
static struct kernel_oplocks *koplocks;
Return True if an oplock message is pending.
****************************************************************************/
-BOOL oplock_message_waiting(fd_set *fds)
+bool oplock_message_waiting(fd_set *fds)
{
if (koplocks && koplocks->msg_waiting(fds)) {
return True;
}
/****************************************************************************
- Read an oplock break message from either the oplock UDP fd or the
- kernel (if kernel oplocks are supported).
-
- If timeout is zero then *fds contains the file descriptors that
- are ready to be read and acted upon. If timeout is non-zero then
- *fds contains the file descriptors to be selected on for read.
- The timeout is in milliseconds
-
+ Find out if there are any kernel oplock messages waiting and process them
+ if so. pfds is the fd_set from the main select loop (which contains any
+ kernel oplock fd if that's what the system uses (IRIX). If may be NULL if
+ we're calling this in a shutting down state.
****************************************************************************/
-void process_kernel_oplocks(void)
+void process_kernel_oplocks(struct messaging_context *msg_ctx, fd_set *pfds)
{
- fd_set fds;
-
- FD_ZERO(&fds);
- smb_read_error = 0;
-
/*
* We need to check for kernel oplocks before going into the select
* here, as the EINTR generated by the linux kernel oplock may have
return;
}
- while (koplocks->msg_waiting(&fds)) {
+ while (koplocks->msg_waiting(pfds)) {
files_struct *fsp;
char msg[MSG_SMB_KERNEL_BREAK_SIZE];
- fsp = koplocks->receive_message(&fds);
+ fsp = koplocks->receive_message(pfds);
if (fsp == NULL) {
DEBUG(3, ("Kernel oplock message announced, but none "
}
/* Put the kernel break info into the message. */
- SDEV_T_VAL(msg,0,fsp->dev);
- SINO_T_VAL(msg,8,fsp->inode);
- SIVAL(msg,16,fsp->file_id);
+ push_file_id_16(msg, &fsp->file_id);
+ SIVAL(msg,16,fsp->fh->gen_id);
/* Don't need to be root here as we're only ever
sending to ourselves. */
- message_send_pid(pid_to_procid(sys_getpid()),
- MSG_SMB_KERNEL_BREAK,
- &msg, MSG_SMB_KERNEL_BREAK_SIZE, True);
+ messaging_send_buf(msg_ctx, procid_self(),
+ MSG_SMB_KERNEL_BREAK,
+ (uint8 *)&msg, MSG_SMB_KERNEL_BREAK_SIZE);
}
}
disabled (just sets flags). Returns True if oplock set.
****************************************************************************/
-BOOL set_file_oplock(files_struct *fsp, int oplock_type)
+bool set_file_oplock(files_struct *fsp, int oplock_type)
{
if (koplocks && !koplocks->set_oplock(fsp, oplock_type)) {
return False;
exclusive_oplocks_open++;
}
- DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f, file_id = %lu, \
-tv_sec = %x, tv_usec = %x\n",
- fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id,
- (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec ));
+ DEBUG(5,("set_file_oplock: granted oplock on file %s, %s/%lu, "
+ "tv_sec = %x, tv_usec = %x\n",
+ fsp->fsp_name, file_id_string_tos(&fsp->file_id),
+ fsp->fh->gen_id, (int)fsp->open_time.tv_sec,
+ (int)fsp->open_time.tv_usec ));
return True;
}
fsp->sent_oplock_break = NO_BREAK_SENT;
flush_write_cache(fsp, OPLOCK_RELEASE_FLUSH);
+
+ TALLOC_FREE(fsp->oplock_timeout);
}
/****************************************************************************
to none even if a "break-to-level II" was sent.
****************************************************************************/
-BOOL remove_oplock(files_struct *fsp)
+bool remove_oplock(files_struct *fsp)
{
- SMB_DEV_T dev = fsp->dev;
- SMB_INO_T inode = fsp->inode;
- BOOL ret;
+ bool ret;
struct share_mode_lock *lck;
/* Remove the oplock flag from the sharemode. */
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
+ lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+ NULL);
if (lck == NULL) {
DEBUG(0,("remove_oplock: failed to lock share entry for "
"file %s\n", fsp->fsp_name ));
ret = remove_share_oplock(lck, fsp);
if (!ret) {
DEBUG(0,("remove_oplock: failed to remove share oplock for "
- "file %s fnum %d, dev = %x, inode = %.0f\n",
- fsp->fsp_name, fsp->fnum, (unsigned int)dev,
- (double)inode));
+ "file %s fnum %d, %s\n",
+ fsp->fsp_name, fsp->fnum, file_id_string_tos(&fsp->file_id)));
}
release_file_oplock(fsp);
- talloc_free(lck);
+ TALLOC_FREE(lck);
return ret;
}
/*
* Deal with a reply when a break-to-level II was sent.
*/
-BOOL downgrade_oplock(files_struct *fsp)
+bool downgrade_oplock(files_struct *fsp)
{
- SMB_DEV_T dev = fsp->dev;
- SMB_INO_T inode = fsp->inode;
- BOOL ret;
+ bool ret;
struct share_mode_lock *lck;
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
+ lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+ NULL);
if (lck == NULL) {
DEBUG(0,("downgrade_oplock: failed to lock share entry for "
"file %s\n", fsp->fsp_name ));
ret = downgrade_share_oplock(lck, fsp);
if (!ret) {
DEBUG(0,("downgrade_oplock: failed to downgrade share oplock "
- "for file %s fnum %d, dev = %x, inode = %.0f\n",
- fsp->fsp_name, fsp->fnum, (unsigned int)dev,
- (double)inode));
+ "for file %s fnum %d, file_id %s\n",
+ fsp->fsp_name, fsp->fnum, file_id_string_tos(&fsp->file_id)));
}
downgrade_file_oplock(fsp);
- talloc_free(lck);
+ TALLOC_FREE(lck);
return ret;
}
/****************************************************************************
- Setup the listening set of file descriptors for an oplock break
- message either from the UDP socket or from the kernel. Returns the maximum
- fd used.
+ Return the fd (if any) used for receiving oplock notifications.
****************************************************************************/
-int setup_oplock_select_set( fd_set *fds)
+int oplock_notify_fd(void)
{
- int maxfd = 0;
-
- if (koplocks && koplocks->notification_fd != -1) {
- FD_SET(koplocks->notification_fd, fds);
- maxfd = MAX(maxfd, koplocks->notification_fd);
+ if (koplocks) {
+ return koplocks->notification_fd;
}
- return maxfd;
+ return -1;
}
/****************************************************************************
}
memset(result,'\0',smb_size);
- set_message(result,8,0,True);
+ srv_set_message(result,8,0,true);
SCVAL(result,smb_com,SMBlockingX);
SSVAL(result,smb_tid,fsp->conn->cnum);
SSVAL(result,smb_pid,0xFFFF);
static void wait_before_sending_break(void)
{
- struct timeval cur_tv;
- long wait_left = (long)lp_oplock_break_wait_time();
+ long wait_time = (long)lp_oplock_break_wait_time();
- if (wait_left == 0) {
- return;
- }
-
- GetTimeOfDay(&cur_tv);
-
- wait_left -= ((cur_tv.tv_sec - smb_last_time.tv_sec)*1000) +
- ((cur_tv.tv_usec - smb_last_time.tv_usec)/1000);
-
- if(wait_left > 0) {
- wait_left = MIN(wait_left, 1000);
- sys_usleep(wait_left * 1000);
+ if (wait_time) {
+ smb_msleep(wait_time);
}
}
Ensure that we have a valid oplock.
****************************************************************************/
-static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id)
+static files_struct *initial_break_processing(struct file_id id, unsigned long file_id)
{
files_struct *fsp = NULL;
if( DEBUGLVL( 3 ) ) {
- dbgtext( "initial_break_processing: called for dev = 0x%x, inode = %.0f file_id = %lu\n",
- (unsigned int)dev, (double)inode, file_id);
+ dbgtext( "initial_break_processing: called for %s/%u\n",
+ file_id_string_tos(&id), (int)file_id);
dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n",
exclusive_oplocks_open, level_II_oplocks_open );
}
* we have an oplock on it.
*/
- fsp = file_find_dif(dev, inode, file_id);
+ fsp = file_find_dif(id, file_id);
if(fsp == NULL) {
/* The file could have been closed in the meantime - return success. */
if( DEBUGLVL( 3 ) ) {
dbgtext( "initial_break_processing: cannot find open file with " );
- dbgtext( "dev = 0x%x, inode = %.0f file_id = %lu", (unsigned int)dev,
- (double)inode, file_id);
+ dbgtext( "file_id %s gen_id = %lu", file_id_string_tos(&id), file_id);
dbgtext( "allowing break to succeed.\n" );
}
return NULL;
if(fsp->oplock_type == NO_OPLOCK) {
if( DEBUGLVL( 3 ) ) {
dbgtext( "initial_break_processing: file %s ", fsp->fsp_name );
- dbgtext( "(dev = %x, inode = %.0f, file_id = %lu) has no oplock.\n",
- (unsigned int)dev, (double)inode, fsp->file_id );
+ dbgtext( "(file_id = %s gen_id = %lu) has no oplock.\n",
+ file_id_string_tos(&id), fsp->fh->gen_id );
dbgtext( "Allowing break to succeed regardless.\n" );
}
return NULL;
return fsp;
}
-static void oplock_timeout_handler(struct timed_event *te,
+static void oplock_timeout_handler(struct event_context *ctx,
+ struct timed_event *te,
const struct timeval *now,
void *private_data)
{
- files_struct *fsp = private_data;
+ files_struct *fsp = (files_struct *)private_data;
- DEBUG(0, ("Oplock break failed -- replying anyway\n"));
+ /* Remove the timed event handler. */
+ TALLOC_FREE(fsp->oplock_timeout);
+ DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", fsp->fsp_name));
global_client_failed_oplock_break = True;
remove_oplock(fsp);
reply_to_oplock_break_requests(fsp);
}
-static void process_oplock_break_message(int msg_type, struct process_id src,
- void *buf, size_t len)
+/*******************************************************************
+ Add a timeout handler waiting for the client reply.
+*******************************************************************/
+
+static void add_oplock_timeout_handler(files_struct *fsp)
+{
+ if (fsp->oplock_timeout != NULL) {
+ DEBUG(0, ("Logic problem -- have an oplock event hanging "
+ "around\n"));
+ }
+
+ fsp->oplock_timeout =
+ event_add_timed(smbd_event_context(), NULL,
+ timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
+ "oplock_timeout_handler",
+ oplock_timeout_handler, fsp);
+
+ if (fsp->oplock_timeout == NULL) {
+ DEBUG(0, ("Could not add oplock timeout handler\n"));
+ }
+}
+
+/*******************************************************************
+ This handles the case of a write triggering a break to none
+ message on a level2 oplock.
+ When we get this message we may be in any of three states :
+ NO_OPLOCK, LEVEL_II, FAKE_LEVEL2. We only send a message to
+ the client for LEVEL2.
+*******************************************************************/
+
+static void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id src,
+ DATA_BLOB *data)
{
struct share_mode_entry msg;
files_struct *fsp;
char *break_msg;
- BOOL break_to_level2 = False;
- BOOL sign_state;
+ bool sign_state;
- if (buf == NULL) {
+ if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
return;
}
- if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
- DEBUG(0, ("Got invalid msg len %d\n", (int)len));
+ if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
+ DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
return;
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, buf);
+ message_to_share_mode_entry(&msg, (char *)data->data);
- DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%d\n",
- (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode,
- (int)msg.share_file_id));
+ DEBUG(10, ("Got oplock async level 2 break message from pid %d: %s/%lu\n",
+ (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id));
- fsp = initial_break_processing(msg.dev, msg.inode,
- msg.share_file_id);
+ fsp = initial_break_processing(msg.id, msg.share_file_id);
if (fsp == NULL) {
- /* We hit race here. Break messages are sent, and before we
+ /* We hit a race here. Break messages are sent, and before we
+ * get to process this message, we have closed the file.
+ * No need to reply as this is an async message. */
+ DEBUG(3, ("process_oplock_async_level2_break_message: Did not find fsp, ignoring\n"));
+ return;
+ }
+
+ if (fsp->oplock_type == NO_OPLOCK) {
+ /* We already got a "break to none" message and we've handled it.
+ * just ignore. */
+ DEBUG(3, ("process_oplock_async_level2_break_message: already broken to none, ignoring.\n"));
+ return;
+ }
+
+ if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) {
+ /* Don't tell the client, just downgrade. */
+ DEBUG(3, ("process_oplock_async_level2_break_message: downgrading fake level 2 oplock.\n"));
+ remove_oplock(fsp);
+ return;
+ }
+
+ /* Ensure we're really at level2 state. */
+ SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK);
+
+ /* Now send a break to none message to our client. */
+
+ break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE);
+ if (break_msg == NULL) {
+ exit_server("Could not talloc break_msg\n");
+ }
+
+ /* Need to wait before sending a break message if we sent ourselves this message. */
+ if (procid_to_pid(&src) == sys_getpid()) {
+ wait_before_sending_break();
+ }
+
+ /* Save the server smb signing state. */
+ sign_state = srv_oplock_set_signing(False);
+
+ show_msg(break_msg);
+ if (!srv_send_smb(smbd_server_fd(),
+ break_msg,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("oplock_break: srv_send_smb failed.");
+ }
+
+ /* Restore the sign state to what it was. */
+ srv_oplock_set_signing(sign_state);
+
+ TALLOC_FREE(break_msg);
+
+ /* Async level2 request, don't send a reply, just remove the oplock. */
+ remove_oplock(fsp);
+}
+
+/*******************************************************************
+ This handles the generic oplock break message from another smbd.
+*******************************************************************/
+
+static void process_oplock_break_message(struct messaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id src,
+ DATA_BLOB *data)
+{
+ struct share_mode_entry msg;
+ files_struct *fsp;
+ char *break_msg;
+ bool break_to_level2 = False;
+ bool sign_state;
+
+ if (data->data == NULL) {
+ DEBUG(0, ("Got NULL buffer\n"));
+ return;
+ }
+
+ if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
+ DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
+ return;
+ }
+
+ /* De-linearize incoming message. */
+ message_to_share_mode_entry(&msg, (char *)data->data);
+
+ DEBUG(10, ("Got oplock break message from pid %d: %s/%lu\n",
+ (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id));
+
+ fsp = initial_break_processing(msg.id, msg.share_file_id);
+
+ if (fsp == NULL) {
+ /* a We hit race here. Break messages are sent, and before we
* get to process this message, we have closed the file. Reply
* with 'ok, oplock broken' */
DEBUG(3, ("Did not find fsp\n"));
- become_root();
/* We just send the same message back. */
- message_send_pid(src, MSG_SMB_BREAK_RESPONSE,
- buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
-
- unbecome_root();
+ messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE,
+ (uint8 *)data->data,
+ MSG_SMB_SHARE_MODE_ENTRY_SIZE);
return;
}
if (EXCLUSIVE_OPLOCK_TYPE(msg.op_type) &&
!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
- DEBUG(3, ("Already downgraded oplock on 0x%x/%.0f: %s\n",
- (unsigned int)fsp->dev, (double)fsp->inode,
+ DEBUG(3, ("Already downgraded oplock on %s: %s\n",
+ file_id_string_tos(&fsp->file_id),
fsp->fsp_name));
- become_root();
-
/* We just send the same message back. */
- message_send_pid(src, MSG_SMB_BREAK_RESPONSE,
- buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
-
- unbecome_root();
+ messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE,
+ (uint8 *)data->data,
+ MSG_SMB_SHARE_MODE_ENTRY_SIZE);
return;
}
- if ((msg_type == MSG_SMB_BREAK_REQUEST) &&
- (global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
+ if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
+ !(msg.op_type & FORCE_OPLOCK_BREAK_TO_NONE) &&
!koplocks && /* NOTE: we force levelII off for kernel oplocks -
* this will change when it is supported */
lp_level2_oplocks(SNUM(fsp->conn))) {
exit_server("Could not talloc break_msg\n");
}
- /* Need to wait before sending a break message to a file of our own */
+ /* Need to wait before sending a break message if we sent ourselves this message. */
if (procid_to_pid(&src) == sys_getpid()) {
wait_before_sending_break();
}
sign_state = srv_oplock_set_signing(False);
show_msg(break_msg);
- if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server("oplock_break: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ break_msg,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
/* Restore the sign state to what it was. */
srv_oplock_set_signing(sign_state);
- talloc_free(break_msg);
+ TALLOC_FREE(break_msg);
+
+ fsp->sent_oplock_break = break_to_level2 ? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
- if (msg_type == MSG_SMB_BREAK_REQUEST) {
- fsp->sent_oplock_break = break_to_level2 ?
- LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
- } else {
- /* Async level2 request, don't send a reply */
- fsp->sent_oplock_break = ASYNC_LEVEL_II_BREAK_SENT;
- }
msg.pid = src;
ADD_TO_ARRAY(NULL, struct share_mode_entry, msg,
&fsp->pending_break_messages,
&fsp->num_pending_break_messages);
- if (fsp->oplock_timeout != NULL) {
- DEBUG(0, ("Logic problem -- have an oplock event hanging "
- "around\n"));
- }
-
- fsp->oplock_timeout =
- add_timed_event(NULL,
- timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
- "oplock_timeout_handler",
- oplock_timeout_handler, fsp);
-
- if (fsp->oplock_timeout == NULL) {
- DEBUG(0, ("Could not add oplock timeout handler\n"));
- }
+ add_oplock_timeout_handler(fsp);
}
-static void process_kernel_oplock_break(int msg_type, struct process_id src,
- void *buf, size_t len)
+/*******************************************************************
+ This handles the kernel oplock break message.
+*******************************************************************/
+
+static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id src,
+ DATA_BLOB *data)
{
- SMB_DEV_T dev;
- SMB_INO_T inode;
+ struct file_id id;
unsigned long file_id;
files_struct *fsp;
char *break_msg;
- BOOL sign_state;
+ bool sign_state;
- if (buf == NULL) {
+ if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
return;
}
- if (len != MSG_SMB_KERNEL_BREAK_SIZE) {
- DEBUG(0, ("Got invalid msg len %d\n", (int)len));
+ if (data->length != MSG_SMB_KERNEL_BREAK_SIZE) {
+ DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
return;
}
/* Pull the data from the message. */
- dev = DEV_T_VAL(buf, 0);
- inode = INO_T_VAL(buf, 8);
- file_id = (unsigned long)IVAL(buf, 16);
+ pull_file_id_16((char *)data->data, &id);
+ file_id = (unsigned long)IVAL(data->data, 16);
- DEBUG(10, ("Got kernel oplock break message from pid %d: 0x%x/%.0f/%u\n",
- (int)procid_to_pid(&src), (unsigned int)dev, (double)inode,
+ DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n",
+ (int)procid_to_pid(&src), file_id_string_tos(&id),
(unsigned int)file_id));
- fsp = initial_break_processing(dev, inode, file_id);
+ fsp = initial_break_processing(id, file_id);
if (fsp == NULL) {
DEBUG(3, ("Got a kernel oplock break message for a file "
sign_state = srv_oplock_set_signing(False);
show_msg(break_msg);
- if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server("oplock_break: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ break_msg,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
/* Restore the sign state to what it was. */
srv_oplock_set_signing(sign_state);
- talloc_free(break_msg);
+ TALLOC_FREE(break_msg);
fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
+
+ add_oplock_timeout_handler(fsp);
}
void reply_to_oplock_break_requests(files_struct *fsp)
{
int i;
- become_root();
for (i=0; i<fsp->num_pending_break_messages; i++) {
struct share_mode_entry *e = &fsp->pending_break_messages[i];
char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
share_mode_entry_to_message(msg, e);
- message_send_pid(e->pid, MSG_SMB_BREAK_RESPONSE,
- msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
+ messaging_send_buf(smbd_messaging_context(), e->pid,
+ MSG_SMB_BREAK_RESPONSE,
+ (uint8 *)msg,
+ MSG_SMB_SHARE_MODE_ENTRY_SIZE);
}
- unbecome_root();
SAFE_FREE(fsp->pending_break_messages);
fsp->num_pending_break_messages = 0;
if (fsp->oplock_timeout != NULL) {
- talloc_free(fsp->oplock_timeout);
+ /* Remove the timed event handler. */
+ TALLOC_FREE(fsp->oplock_timeout);
fsp->oplock_timeout = NULL;
}
return;
}
-static void process_oplock_break_response(int msg_type, struct process_id src,
- void *buf, size_t len)
+static void process_oplock_break_response(struct messaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id src,
+ DATA_BLOB *data)
{
struct share_mode_entry msg;
- if (buf == NULL) {
+ if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
return;
}
- if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
- DEBUG(0, ("Got invalid msg len %u\n", (unsigned int)len));
+ if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
+ DEBUG(0, ("Got invalid msg len %u\n",
+ (unsigned int)data->length));
return;
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, buf);
+ message_to_share_mode_entry(&msg, (char *)data->data);
- DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%u mid %u\n",
- (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode,
- (unsigned int)msg.share_file_id, (unsigned int)msg.op_mid));
+ DEBUG(10, ("Got oplock break response from pid %d: %s/%lu mid %u\n",
+ (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id,
+ (unsigned int)msg.op_mid));
/* Here's the hack from open.c, store the mid in the 'port' field */
schedule_deferred_open_smb_message(msg.op_mid);
}
-static void process_open_retry_message(int msg_type, struct process_id src,
- void *buf, size_t len)
+static void process_open_retry_message(struct messaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id src,
+ DATA_BLOB *data)
{
struct share_mode_entry msg;
- if (buf == NULL) {
+ if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
return;
}
- if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
- DEBUG(0, ("Got invalid msg len %d\n", (int)len));
+ if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
+ DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
return;
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, buf);
+ message_to_share_mode_entry(&msg, (char *)data->data);
- DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f mid %u\n",
- (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode,
+ DEBUG(10, ("Got open retry msg from pid %d: %s mid %u\n",
+ (int)procid_to_pid(&src), file_id_string_tos(&msg.id),
(unsigned int)msg.op_mid));
schedule_deferred_open_smb_message(msg.op_mid);
if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
return;
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
+ lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+ NULL);
if (lck == NULL) {
DEBUG(0,("release_level_2_oplocks_on_change: failed to lock "
"share mode entry for file %s.\n", fsp->fsp_name ));
+ return;
}
DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n",
lck->num_share_modes ));
- if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) {
- /* See if someone else has already downgraded us, then we
- don't have to do anything */
- for (i=0; i<lck->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->share_modes[i];
-
- if (!is_valid_share_mode_entry(e)) {
- continue;
- }
-
- if ((e->op_type == NO_OPLOCK) &&
- (e->share_file_id == fsp->file_id) &&
- (e->dev == fsp->dev) &&
- (e->inode == fsp->inode) &&
- (procid_is_me(&e->pid))) {
- /* We're done */
- fsp->oplock_type = NO_OPLOCK;
- talloc_free(lck);
- return;
- }
- }
- }
-
for(i = 0; i < lck->num_share_modes; i++) {
struct share_mode_entry *share_entry = &lck->share_modes[i];
char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
* As there could have been multiple writes waiting at the
* lock_share_entry gate we may not be the first to
* enter. Hence the state of the op_types in the share mode
- * entries may be partly NO_OPLOCK and partly LEVEL_II
+ * entries may be partly NO_OPLOCK and partly LEVEL_II or FAKE_LEVEL_II
* oplock. It will do no harm to re-send break messages to
* those smbd's that are still waiting their turn to remove
* their LEVEL_II state, and also no harm to ignore existing
"share_entry[%i]->op_type == %d\n",
i, share_entry->op_type ));
- if ((share_entry->op_type == NO_OPLOCK) ||
- (share_entry->op_type == FAKE_LEVEL_II_OPLOCK)) {
+ if (share_entry->op_type == NO_OPLOCK) {
continue;
}
DEBUG(0,("release_level_2_oplocks_on_change: PANIC. "
"share mode entry %d is an exlusive "
"oplock !\n", i ));
- talloc_free(lck);
+ TALLOC_FREE(lck);
abort();
}
share_mode_entry_to_message(msg, share_entry);
- become_root();
- message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK,
- msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
- unbecome_root();
+ messaging_send_buf(smbd_messaging_context(), share_entry->pid,
+ MSG_SMB_ASYNC_LEVEL2_BREAK,
+ (uint8 *)msg,
+ MSG_SMB_SHARE_MODE_ENTRY_SIZE);
}
- remove_all_share_oplocks(lck, fsp);
- talloc_free(lck);
+ /* We let the message receivers handle removing the oplock state
+ in the share mode lock db. */
+
+ TALLOC_FREE(lck);
}
/****************************************************************************
Linearize a share mode entry struct to an internal oplock break message.
****************************************************************************/
-void share_mode_entry_to_message(char *msg, struct share_mode_entry *e)
+void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e)
{
SIVAL(msg,0,(uint32)e->pid.pid);
SSVAL(msg,4,e->op_mid);
SIVAL(msg,16,e->private_options);
SIVAL(msg,20,(uint32)e->time.tv_sec);
SIVAL(msg,24,(uint32)e->time.tv_usec);
- SDEV_T_VAL(msg,28,e->dev);
- SINO_T_VAL(msg,36,e->inode);
+ push_file_id_16(msg+28, &e->id);
SIVAL(msg,44,e->share_file_id);
+ SIVAL(msg,48,e->uid);
+ SSVAL(msg,52,e->flags);
+#ifdef CLUSTER_SUPPORT
+ SIVAL(msg,54,e->pid.vnn);
+#endif
}
/****************************************************************************
e->private_options = IVAL(msg,16);
e->time.tv_sec = (time_t)IVAL(msg,20);
e->time.tv_usec = (int)IVAL(msg,24);
- e->dev = DEV_T_VAL(msg,28);
- e->inode = INO_T_VAL(msg,36);
+ pull_file_id_16(msg+28, &e->id);
e->share_file_id = (unsigned long)IVAL(msg,44);
+ e->uid = (uint32)IVAL(msg,48);
+ e->flags = (uint16)SVAL(msg,52);
+#ifdef CLUSTER_SUPPORT
+ e->pid.vnn = IVAL(msg,54);
+#endif
}
/****************************************************************************
Setup oplocks for this process.
****************************************************************************/
-BOOL init_oplocks(void)
+bool init_oplocks(struct messaging_context *msg_ctx)
{
- DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n"));
-
- message_register(MSG_SMB_BREAK_REQUEST,
- process_oplock_break_message);
- message_register(MSG_SMB_ASYNC_LEVEL2_BREAK,
- process_oplock_break_message);
- message_register(MSG_SMB_BREAK_RESPONSE,
- process_oplock_break_response);
- message_register(MSG_SMB_KERNEL_BREAK,
- process_kernel_oplock_break);
- message_register(MSG_SMB_OPEN_RETRY,
- process_open_retry_message);
+ DEBUG(3,("init_oplocks: initializing messages.\n"));
+
+ messaging_register(msg_ctx, NULL, MSG_SMB_BREAK_REQUEST,
+ process_oplock_break_message);
+ messaging_register(msg_ctx, NULL, MSG_SMB_ASYNC_LEVEL2_BREAK,
+ process_oplock_async_level2_break_message);
+ messaging_register(msg_ctx, NULL, MSG_SMB_BREAK_RESPONSE,
+ process_oplock_break_response);
+ messaging_register(msg_ctx, NULL, MSG_SMB_KERNEL_BREAK,
+ process_kernel_oplock_break);
+ messaging_register(msg_ctx, NULL, MSG_SMB_OPEN_RETRY,
+ process_open_retry_message);
if (lp_kernel_oplocks()) {
#if HAVE_KERNEL_OPLOCKS_IRIX