diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/chgpasswd.c | 6 | ||||
-rw-r--r-- | source3/smbd/open.c | 24 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 46 | ||||
-rw-r--r-- | source3/smbd/reply.c | 2 | ||||
-rw-r--r-- | source3/smbd/server.c | 12 |
5 files changed, 50 insertions, 40 deletions
diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 4dc6d29e3c..4131bc9297 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -343,6 +343,12 @@ static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequenc } else { /* CHILD */ + /* + * Lose any oplock capabilities. + */ + set_process_capability(KERNEL_OPLOCK_CAPABILITY, False); + set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False); + /* make sure it doesn't freeze */ alarm(20); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 64f28ddfe2..2b2f0f0524 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -535,18 +535,30 @@ static void open_file(files_struct *fsp,connection_struct *conn, conn->num_files_open)); } +} +/**************************************************************************** + If it's a read-only file, and we were compiled with mmap enabled, + try and mmap the file. This is split out from open_file() above + as mmap'ing the file can cause the kernel reference count to + be incremented, which can cause kernel oplocks to be refused. + Splitting this call off allows the kernel oplock to be granted, then + the file mmap'ed. +****************************************************************************/ + +static void mmap_open_file(files_struct *fsp) +{ #if WITH_MMAP /* mmap it if read-only */ if (!fsp->can_write) { - fsp->mmap_size = file_size(fname); + fsp->mmap_size = file_size(fsp->fsp_name); if (fsp->mmap_size < MAX_MMAP_SIZE) { fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { DEBUG(3,("Failed to mmap() %s - %s\n", - fname,strerror(errno))); + fsp->fsp_name,strerror(errno))); fsp->mmap_ptr = NULL; } } @@ -554,7 +566,6 @@ static void open_file(files_struct *fsp,connection_struct *conn, #endif } - /**************************************************************************** C. Hoch 11/22/95 Helper for open_file_shared. @@ -938,6 +949,13 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if ((flags2&O_TRUNC) && file_existed) truncate_unless_locked(fsp,conn,token,&share_locked); + + /* + * Attempt to mmap a read only file. + * Moved until after a kernel oplock may + * be granted due to reference count issues. JRA. + */ + mmap_open_file(fsp); } if (share_locked && lp_share_modes(SNUM(conn))) diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index b418e7cd54..27d802c151 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -240,39 +240,9 @@ BOOL set_file_oplock(files_struct *fsp) { #if defined(HAVE_KERNEL_OPLOCKS) if(lp_kernel_oplocks()) { -#if 0 /* for now. */ - extern struct current_user current_user; -#endif - int saved_errno; - int fcntl_ret; -#if 0 /* for now. */ - /* - * Go back to being root. - */ - - unbecome_user(); -#endif - - fcntl_ret = fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write); - saved_errno = errno; - -#if 0 /* for now. */ - /* - * Go back to being the correct user. - */ - if(!become_user(fsp->conn, current_user.vuid)) - { - DEBUG( 0, ( "set_file_oplock: unable to re-become user!" ) ); - DEBUGADD( 0, ( "Shutting down server\n" ) ); - close_sockets(); - close(oplock_sock); - exit_server("unable to re-become user"); - } -#endif - - if(fcntl_ret < 0) { - if(saved_errno != EAGAIN) { + if(fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write) < 0 ) { + if(errno != EAGAIN) { DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ inode = %.0f. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, @@ -284,6 +254,10 @@ inode = %.0f. Another process had the file open.\n", } return False; } + + DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", + fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode)); + } #endif /* HAVE_KERNEL_OPLOCKS */ @@ -305,7 +279,8 @@ inode = %.0f. Another process had the file open.\n", static void release_file_oplock(files_struct *fsp) { #if defined(HAVE_KERNEL_OPLOCKS) - if(fsp->granted_oplock && lp_kernel_oplocks()) + + if(lp_kernel_oplocks()) { if( DEBUGLVL( 10 )) { @@ -320,7 +295,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, } /* - * Remove the kernel oplock on this file. + * Remote the kernel oplock on this file. */ if(fcntl(fsp->fd_ptr->fd, F_OPLKACK, OP_REVOKE) < 0) @@ -1057,6 +1032,9 @@ void check_kernel_oplocks(void) int pfd[2]; pstring tmpname; + set_process_capability(KERNEL_OPLOCK_CAPABILITY,True); + set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,True); + slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", (unsigned int)getpid()); mktemp(tmpname); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 21fa2e9a79..63bbcbcdba 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3544,7 +3544,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, #endif uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); - SMB_OFF_T count, offset; + SMB_OFF_T count = 0, offset = 0; int32 lock_timeout = IVAL(inbuf,smb_vwv4); int i; char *data; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e1b5e42764..fb97cf8380 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -240,6 +240,14 @@ max can be %d\n", that client substitutions will be done correctly in the process. */ reset_globals_after_fork(); + + /* + * Ensure this child has kernel oplock + * capabilities, but not it's children. + */ + set_process_capability(KERNEL_OPLOCK_CAPABILITY, True); + set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False); + return True; } /* The parent doesn't need this socket */ @@ -661,8 +669,6 @@ static void usage(char *pname) DEBUG(3,( "loaded services\n")); - check_kernel_oplocks(); - if (!is_daemon && !is_a_socket(0)) { DEBUG(0,("standard input is not a socket, assuming -D option\n")); is_daemon = True; @@ -673,6 +679,8 @@ static void usage(char *pname) become_daemon(); } + check_kernel_oplocks(); + if (!directory_exist(lp_lockdir(), NULL)) { mkdir(lp_lockdir(), 0755); } |