proto.h: Updated.
authorJeremy Allison <jra@samba.org>
Fri, 3 Oct 1997 03:15:24 +0000 (03:15 +0000)
committerJeremy Allison <jra@samba.org>
Fri, 3 Oct 1997 03:15:24 +0000 (03:15 +0000)
server.c: Updated after netbench observation. Oplocks must be
broken *before* share modes are checked, not after. Netbench seems
to be working now.
smb.h: Added offsets for oplock break time fields.
trans2.c: Upped debug messages.
util.c: Upped debug messages.
Jeremy (jallison@whistle.com)

source/include/proto.h
source/include/smb.h
source/lib/util.c
source/smbd/server.c
source/smbd/trans2.c

index 51433333c5084804db3ed85fb98c5bb5467950e9..35d43afe0ca5ce42573cebd99a7d20cb9ed38f26 100644 (file)
@@ -722,7 +722,7 @@ int find_service(char *service);
 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line);
 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line);
 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line);
-BOOL oplock_break(uint32 dev, uint32 inode);
+BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval);
 BOOL request_oplock_break(min_share_mode_entry *share_entry, 
                           uint32 dev, uint32 inode);
 BOOL snum_used(int snum);
index 509c1e1cf155deec9c402d964d5340d115264f69..66da2099c778722f755371da92a3ab5eeeb427e0 100644 (file)
@@ -1049,17 +1049,19 @@ extern int unix_ERR_code;
  * 
  * Form of this is :
  *
- *  0     2       6        10
- *  +----+--------+--------+--------+
- *  | cmd| pid    | dev    | inode  |
- *  +----+--------+--------+--------+
+ *  0     2       6        10       14      18       22
+ *  +----+--------+--------+--------+-------+--------+
+ *  | cmd| pid    | dev    | inode  | sec   |  usec  |
+ *  +----+--------+--------+--------+-------+--------+
  */
 
 #define OPLOCK_BREAK_CMD 0x1
 #define OPLOCK_BREAK_PID_OFFSET 2
 #define OPLOCK_BREAK_DEV_OFFSET 6
 #define OPLOCK_BREAK_INODE_OFFSET 10
-#define OPLOCK_BREAK_MSG_LEN 14
+#define OPLOCK_BREAK_SEC_OFFSET 14
+#define OPLOCK_BREAK_USEC_OFFSET 18
+#define OPLOCK_BREAK_MSG_LEN 22
 
 
 #define CMD_REPLY 0x8000
index e65e708139c7f9f24eb398c1a0dee6e753e3bdc4..3317efb80411e8578639d46d6e5d7a4dee93626f 100644 (file)
@@ -2860,7 +2860,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
 
   if (strequal(p1,"*")) return(True);
 
-  DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
+  DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
 
   if (trans2) {
     fstrcpy(ebase,p1);
@@ -2888,7 +2888,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
   matched = do_match(sbase,ebase,case_sig) && 
     (trans2 || do_match(sext,eext,case_sig));
 
-  DEBUG(5,("mask_match returning %d\n", matched));
+  DEBUG(8,("mask_match returning %d\n", matched));
 
   return matched;
 }
index 19cc5b9abb8a61606d23ebf4cac970b98f18115c..d7620a5804eb184d4969f253a5da721bc4cf6859 100644 (file)
@@ -1404,7 +1404,8 @@ static int access_table(int new_deny,int old_deny,int old_mode,
   if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
 
   if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
-    if (old_deny == new_deny && share_pid == getpid()) 
+    int pid = getpid();
+    if (old_deny == new_deny && share_pid == pid) 
        return(AALL);    
 
     if (old_mode == 0) return(AREAD);
@@ -1487,16 +1488,12 @@ BOOL check_file_sharing(int cnum,char *fname)
       {
         min_share_mode_entry *share_entry = &old_shares[i];
 
-        /* someone else has a share lock on it, check to see 
-           if we can too */
-        if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid))
-          goto free_and_exit;
-
 #ifdef USE_OPLOCKS
         /* 
-         * The share modes would give us access. Check if someone
-         * has an oplock on this file. If so we must break it before
-         * continuing. 
+         * Break oplocks before checking share modes. See comment in
+         * open_file_shared for details. 
+         * Check if someone has an oplock on this file. If so we must 
+         * break it before continuing. 
          */
         if(share_entry->op_type & BATCH_OPLOCK)
         {
@@ -1518,6 +1515,12 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
           break;
         }
 #endif /* USE_OPLOCKS */
+
+        /* someone else has a share lock on it, check to see 
+           if we can too */
+        if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid))
+          goto free_and_exit;
+
       } /* end for */
 
       if(broke_oplock)
@@ -1727,22 +1730,13 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
         {
           min_share_mode_entry *share_entry = &old_shares[i];
 
-          /* someone else has a share lock on it, check to see 
-             if we can too */
-          if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False)
-          {
-            free((char *)old_shares);
-            unlock_share_entry(cnum, dev, inode, token);
-            errno = EACCES;
-            unix_ERR_class = ERRDOS;
-            unix_ERR_code = ERRbadshare;
-            return;
-          }
 #ifdef USE_OPLOCKS
           /* 
-           * The share modes would give us access. Check if someone
-           * has an oplock on this file. If so we must break it before
-           * continuing. 
+           * By observation of NetBench, oplocks are broken *before* share
+           * modes are checked. This allows a file to be closed by the client
+           * if the share mode would deny access and the client has an oplock. 
+           * Check if someone has an oplock on this file. If so we must break 
+           * it before continuing. 
            */
           if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
           {
@@ -1767,6 +1761,19 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
             break;
           }
 #endif /* USE_OPLOCKS */
+
+          /* someone else has a share lock on it, check to see 
+             if we can too */
+          if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False)
+          {
+            free((char *)old_shares);
+            unlock_share_entry(cnum, dev, inode, token);
+            errno = EACCES;
+            unix_ERR_class = ERRDOS;
+            unix_ERR_code = ERRbadshare;
+            return;
+          }
+
         } /* end for */
 
         if(broke_oplock)
@@ -2428,7 +2435,7 @@ static void process_smb(char *inbuf, char *outbuf)
                  static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
                  DEBUG(1,("%s Connection denied from %s\n",
                           timestring(),client_addr()));
-                 send_smb(Client,buf);
+                 send_smb(Client,(char *)buf);
                  exit_server("connection denied");
          }
   }
@@ -2535,8 +2542,12 @@ should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
         uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
         uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
         uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
+        struct timeval tval;
         struct sockaddr_in toaddr;
 
+        tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET);
+        tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET);
+
         DEBUG(5,("process_local_message: oplock break request from \
 pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
 
@@ -2549,7 +2560,7 @@ pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
 
         if(global_oplocks_open != 0)
         {
-          if(oplock_break(dev, inode) == False)
+          if(oplock_break(dev, inode, &tval) == False)
           {
             DEBUG(0,("process_local_message: oplock break failed - \
 not returning udp message.\n"));
@@ -2595,7 +2606,7 @@ pid %d, port %d, for file dev = %x, inode = %x\n", remotepid,
 /****************************************************************************
  Process an oplock break directly.
 ****************************************************************************/
-BOOL oplock_break(uint32 dev, uint32 inode)
+BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval)
 {
   extern int Client;
   static char *inbuf = NULL;
@@ -2633,7 +2644,9 @@ global_oplocks_open = %d\n", dev, inode, global_oplocks_open));
     if(OPEN_FNUM(fnum))
     {
       fsp = &Files[fnum];
-      if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode))
+      if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode) &&
+         (fsp->open_time.tv_sec == tval->tv_sec) && 
+         (fsp->open_time.tv_usec == tval->tv_usec))
         break;
     }
   }
@@ -2797,8 +2810,11 @@ BOOL request_oplock_break(min_share_mode_entry *share_entry,
 should be %d\n", pid, share_entry->op_port, oplock_port));
       return False;
     }
+
+    DEBUG(5,("request_oplock_break: breaking our own oplock\n"));
+
     /* Call oplock break direct. */
-    return oplock_break(dev, inode);
+    return oplock_break(dev, inode, &share_entry->time);
   }
 
   /* We need to send a OPLOCK_BREAK_CMD message to the
@@ -2808,6 +2824,8 @@ should be %d\n", pid, share_entry->op_port, oplock_port));
   SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid);
   SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev);
   SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode);
+  SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec);
+  SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec);
 
   /* set the address and port */
   bzero((char *)&addr_out,sizeof(addr_out));
index 8ab024ded28e2702e6bc7c25a2a2d188ce31b2e3..56f153f12fb6fe0146e98ccb869de14158b60ab7 100644 (file)
@@ -319,7 +319,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
 
       reskey = TellDir(Connections[cnum].dirptr);
 
-      DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
+      DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
               Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
       
       if (!dname)