summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/server.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 01d379ebb3..3a12513454 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -3695,6 +3695,31 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
return(cnum);
}
+/****************************************************************************
+ Attempt to break an oplock on a file (if oplocked).
+ Returns True if the file was closed as a result of
+ the oplock break, False otherwise.
+ Used as a last ditch attempt to free a space in the
+ file table when we have run out.
+****************************************************************************/
+
+static BOOL attempt_close_oplocked_file(files_struct *fp)
+{
+
+ DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fp->name));
+
+ if (fp->open && fp->granted_oplock && !fp->sent_oplock_break) {
+
+ /* Try and break the oplock. */
+ file_fd_struct *fsp = fp->fd_ptr;
+ if(oplock_break( fsp->dev, fsp->inode, &fp->open_time)) {
+ if(!fp->open) /* Did the oplock break close the file ? */
+ return True;
+ }
+ }
+
+ return False;
+}
/****************************************************************************
find first available file slot
@@ -3734,6 +3759,32 @@ int find_free_file(void )
return(i);
}
+ /*
+ * Before we give up, go through the open files
+ * and see if there are any files opened with a
+ * batch oplock. If so break the oplock and then
+ * re-use that entry (if it becomes closed).
+ * This may help as NT/95 clients tend to keep
+ * files batch oplocked for quite a long time
+ * after they have finished with them.
+ */
+ for (i=first_file;i<MAX_OPEN_FILES;i++) {
+ if(attempt_close_oplocked_file( &Files[i])) {
+ memset(&Files[i], 0, sizeof(Files[i]));
+ first_file = i+1;
+ Files[i].reserved = True;
+ return(i);
+ }
+ }
+
+ for (i=1;i<MAX_OPEN_FILES;i++) {
+ if(attempt_close_oplocked_file( &Files[i])) {
+ memset(&Files[i], 0, sizeof(Files[i]));
+ first_file = i+1;
+ Files[i].reserved = True;
+ return(i);
+ }
+ }
DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
return(-1);
@@ -5280,7 +5331,12 @@ static void usage(char *pname)
{
struct rlimit rlp;
getrlimit(RLIMIT_NOFILE, &rlp);
- rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
+ /*
+ * Set the fd limit to be MAX_OPEN_FILES + 10 to account for the
+ * extra fd we need to read directories, as well as the log files
+ * and standard handles etc.
+ */
+ rlp.rlim_cur = (MAX_OPEN_FILES+10>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES+10;
setrlimit(RLIMIT_NOFILE, &rlp);
getrlimit(RLIMIT_NOFILE, &rlp);
DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));