From 196028ab7b578526179d4fcff42a5d73ba07ccbb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Jan 2009 14:02:18 +0100 Subject: s3:smbd: restructure kernel oplocks code This converts the irix oplocks code to use a fd event and removes the last special case for file descriptors for the main sys_select(). metze --- source3/smbd/oplock_irix.c | 118 ++++++++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 43 deletions(-) (limited to 'source3/smbd/oplock_irix.c') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 496b0b72ea..0cfa960425 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -23,6 +23,14 @@ #if HAVE_KERNEL_OPLOCKS_IRIX +struct irix_oplocks_context { + struct kernel_oplocks *ctx; + int write_fd; + int read_fd; + struct fd_event *read_fde; + bool pending; +}; + /**************************************************************************** Test to see if IRIX kernel oplocks work. ****************************************************************************/ @@ -100,22 +108,27 @@ static bool irix_oplocks_available(void) * oplock break protocol. ****************************************************************************/ -static files_struct *irix_oplock_receive_message(fd_set *fds) +static files_struct *irix_oplock_receive_message(struct kernel_oplocks *_ctx) { + struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data, + struct irix_oplocks_context); oplock_stat_t os; char dummy; struct file_id fileid; files_struct *fsp; - /* Ensure we only get one call per select fd set. */ - FD_CLR(oplock_pipe_read, fds); + /* + * TODO: is it correct to assume we only get one + * oplock break, for each byte we read from the pipe? + */ + ctx->pending = false; /* * Read one byte of zero to clear the * kernel break notify message. */ - if(read(oplock_pipe_read, &dummy, 1) != 1) { + if(read(ctx->read_fd, &dummy, 1) != 1) { DEBUG(0,("irix_oplock_receive_message: read of kernel " "notification failed. Error was %s.\n", strerror(errno) )); @@ -128,7 +141,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) * request outstanding. */ - if(sys_fcntl_ptr(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { + if(sys_fcntl_ptr(ctx->read_fd, F_OPLKSTAT, &os) < 0) { DEBUG(0,("irix_oplock_receive_message: fcntl of kernel " "notification failed. Error was %s.\n", strerror(errno) )); @@ -170,9 +183,13 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) Attempt to set an kernel oplock on a file. ****************************************************************************/ -static bool irix_set_kernel_oplock(files_struct *fsp, int oplock_type) +static bool irix_set_kernel_oplock(struct kernel_oplocks *_ctx, + files_struct *fsp, int oplock_type) { - if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, oplock_pipe_write) == -1) { + struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data, + struct irix_oplocks_context); + + if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, ctx->write_fd) == -1) { if(errno != EAGAIN) { DEBUG(0,("irix_set_kernel_oplock: Unable to get " "kernel oplock on file %s, file_id %s " @@ -204,7 +221,8 @@ static bool irix_set_kernel_oplock(files_struct *fsp, int oplock_type) Release a kernel oplock on a file. ****************************************************************************/ -static void irix_release_kernel_oplock(files_struct *fsp) +static void irix_release_kernel_oplock(struct kernel_oplocks *_ctx, + files_struct *fsp) { if (DEBUGLVL(10)) { /* @@ -234,63 +252,77 @@ static void irix_release_kernel_oplock(files_struct *fsp) } } -/**************************************************************************** - See if there is a message waiting in this fd set. - Note that fds MAY BE NULL ! If so we must do our own select. -****************************************************************************/ - -static bool irix_oplock_msg_waiting(fd_set *fds) +static bool irix_oplock_msg_waiting(struct kernel_oplocks *_ctx) { - int selrtn; - fd_set myfds; - struct timeval to; - - if (oplock_pipe_read == -1) - return False; - - if (fds) { - return FD_ISSET(oplock_pipe_read, fds); - } - - /* Do a zero-time select. We just need to find out if there - * are any outstanding messages. We use sys_select_intr as - * we need to ignore any signals. */ + struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data, + struct irix_oplocks_context); + return ctx->pending; +} - FD_ZERO(&myfds); - FD_SET(oplock_pipe_read, &myfds); +static void irix_oplocks_read_fde_handler(struct event_context *ev, + struct fd_event *fde, + uint16_t flags, + void *private_data) +{ + struct irix_oplocks_context *ctx = talloc_get_type(private_data, + struct irix_oplocks_context); - to = timeval_set(0, 0); - selrtn = sys_select_intr(oplock_pipe_read+1,&myfds,NULL,NULL,&to); - return (selrtn == 1) ? True : False; + ctx->pending = true; + process_kernel_oplocks(smbd_messaging_context()); + ctx->pending = false; } /**************************************************************************** Setup kernel oplocks. ****************************************************************************/ -struct kernel_oplocks *irix_init_kernel_oplocks(void) +static const struct kernel_oplocks_ops irix_koplocks = { + .receive_message = irix_oplock_receive_message, + .set_oplock = irix_set_kernel_oplock, + .release_oplock = irix_release_kernel_oplock, + .msg_waiting = irix_oplock_msg_waiting +}; + +struct kernel_oplocks *irix_init_kernel_oplocks(TALLOC_CTX *mem_ctx) { + struct kernel_oplocks *_ctx; + struct irix_oplocks_context *ctx; int pfd[2]; if (!irix_oplocks_available()) return NULL; + _ctx = talloc_zero(mem_ctx, struct kernel_oplocks); + if (!_ctx) { + return NULL; + } + + ctx = talloc_zero(_ctx, struct irix_oplocks_context); + if (!ctx) { + talloc_free(_ctx); + return NULL; + } + _ctx->ops = &irix_koplocks; + _ctx->private_data = ctx; + ctx->ctx = _ctx; + if(pipe(pfd) != 0) { + talloc_free(_ctx); DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. " "Error was %s\n", strerror(errno) )); return False; } - oplock_pipe_read = pfd[0]; - oplock_pipe_write = pfd[1]; - - irix_koplocks.receive_message = irix_oplock_receive_message; - irix_koplocks.set_oplock = irix_set_kernel_oplock; - irix_koplocks.release_oplock = irix_release_kernel_oplock; - irix_koplocks.msg_waiting = irix_oplock_msg_waiting; - irix_koplocks.notification_fd = oplock_pipe_read; + ctx->read_fd = pfd[0]; + ctx->write_fd = pfd[1]; - return &irix_koplocks; + ctx->read_fde = event_add_fd(smbd_event_context(), + ctx, + ctx->read_fd, + EVENT_FD_READ, + irix_oplocks_read_fde_handler, + ctx); + return _ctx; } #else void oplock_irix_dummy(void); -- cgit