Author: jra
Date: 2006-07-19 21:20:44 +0000 (Wed, 19 Jul 2006)
New Revision: 17153

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=17153

Log:
Bring 3.0.23a up into line with the latest changes
in SAMBA_3_0. Fix kernel oplocks bug (efficiently).
Jerry - this needs merging for 3.0.23a.
Jeremy

Modified:
   branches/SAMBA_3_0_23/source/smbd/open.c


Changeset:
Modified: branches/SAMBA_3_0_23/source/smbd/open.c
===================================================================
--- branches/SAMBA_3_0_23/source/smbd/open.c    2006-07-19 21:03:03 UTC (rev 
17152)
+++ branches/SAMBA_3_0_23/source/smbd/open.c    2006-07-19 21:20:44 UTC (rev 
17153)
@@ -185,7 +185,8 @@
                        SMB_STRUCT_STAT *psbuf,
                        int flags,
                        mode_t unx_mode,
-                       uint32 access_mask)
+                       uint32 access_mask, /* client requested access mask. */
+                       uint32 open_access_mask) /* what we're actually using 
in the open. */
 {
        int accmode = (flags & O_ACCMODE);
        int local_flags = flags;
@@ -239,7 +240,7 @@
                local_flags = (flags & ~O_ACCMODE)|O_RDWR;
        }
 
-       if ((access_mask & 
(FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
+       if ((open_access_mask & 
(FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
            (!file_existed && (local_flags & O_CREAT)) ||
            ((local_flags & O_TRUNC) == O_TRUNC) ) {
 
@@ -1112,6 +1113,7 @@
        uint16 mid = get_current_mid();
        struct timeval request_time = timeval_zero();
        struct share_mode_lock *lck = NULL;
+       uint32 open_access_mask = access_mask;
        NTSTATUS status;
 
        if (conn->printer) {
@@ -1202,12 +1204,14 @@
                        /* If file exists replace/overwrite. If file doesn't
                         * exist create. */
                        flags2 |= (O_CREAT | O_TRUNC);
+                       open_access_mask |= FILE_WRITE_DATA; /* This will cause 
oplock breaks. */
                        break;
 
                case FILE_OVERWRITE_IF:
                        /* If file exists replace/overwrite. If file doesn't
                         * exist create. */
                        flags2 |= (O_CREAT | O_TRUNC);
+                       open_access_mask |= FILE_WRITE_DATA; /* This will cause 
oplock breaks. */
                        break;
 
                case FILE_OPEN:
@@ -1234,6 +1238,7 @@
                                return NULL;
                        }
                        flags2 |= O_TRUNC;
+                       open_access_mask |= FILE_WRITE_DATA; /* This will cause 
oplock breaks. */
                        break;
 
                case FILE_CREATE:
@@ -1286,7 +1291,10 @@
 
        /* This is a nasty hack - must fix... JRA. */
        if (access_mask == MAXIMUM_ALLOWED_ACCESS) {
-               access_mask = FILE_GENERIC_ALL;
+               open_access_mask = access_mask = FILE_GENERIC_ALL;
+               if (flags2 & O_TRUNC) {
+                       open_access_mask |= FILE_WRITE_DATA; /* This will cause 
oplock breaks. */
+               }
        }
 
        /*
@@ -1351,7 +1359,7 @@
        fsp->inode = psbuf->st_ino;
        fsp->share_access = share_access;
        fsp->fh->private_options = create_options;
-       fsp->access_mask = access_mask;
+       fsp->access_mask = open_access_mask; /* We change this to the requested 
access_mask after the open is done. */
        /* Ensure no SAMBA_PRIVATE bits can be set. */
        fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK);
 
@@ -1382,6 +1390,7 @@
                        return NULL;
                }
 
+               /* Use the client requested access mask here, not the one we 
open with. */
                status = open_mode_check(conn, fname, lck,
                                         access_mask, share_access,
                                         create_options, &file_existed);
@@ -1417,6 +1426,8 @@
                            (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
                             NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
                                files_struct *fsp_dup;
+
+                               /* Use the client requested access mask here, 
not the one we open with. */
                                fsp_dup = fcb_or_dos_open(conn, fname, dev,
                                                          inode, access_mask,
                                                          share_access,
@@ -1532,119 +1543,88 @@
                 (unsigned int)flags, (unsigned int)flags2,
                 (unsigned int)unx_mode));
 
-       /* Drop the lock before doing any real file access. Allows kernel
-          oplock breaks to be processed. Handle any races after the open
-          call when we re-acquire the lock. */
-
-       if (lck) {
-               TALLOC_FREE(lck);
-       }
-
        /*
         * open_file strips any O_TRUNC flags itself.
         */
 
        fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,
-                            access_mask);
+                               access_mask, open_access_mask);
 
        if (!fsp_open) {
+               if (lck != NULL) {
+                       TALLOC_FREE(lck);
+               }
                file_free(fsp);
                return NULL;
        }
 
-       /*
-        * Deal with the race condition where two smbd's detect the
-        * file doesn't exist and do the create at the same time. One
-        * of them will win and set a share mode, the other (ie. this
-        * one) should check if the requested share mode for this
-        * create is allowed.
-        */
+       if (!file_existed) {
 
-       /*
-        * Now the file exists and fsp is successfully opened,
-        * fsp->dev and fsp->inode are valid and should replace the
-        * dev=0,inode=0 from a non existent file. Spotted by
-        * Nadav Danieli <[EMAIL PROTECTED]>. JRA.
-        */
+               /*
+                * Deal with the race condition where two smbd's detect the
+                * file doesn't exist and do the create at the same time. One
+                * of them will win and set a share mode, the other (ie. this
+                * one) should check if the requested share mode for this
+                * create is allowed.
+                */
 
-       dev = fsp->dev;
-       inode = fsp->inode;
+               /*
+                * Now the file exists and fsp is successfully opened,
+                * fsp->dev and fsp->inode are valid and should replace the
+                * dev=0,inode=0 from a non existent file. Spotted by
+                * Nadav Danieli <[EMAIL PROTECTED]>. JRA.
+                */
 
-       lck = get_share_mode_lock(NULL, dev, inode,
-                               conn->connectpath,
-                               fname);
+               dev = fsp->dev;
+               inode = fsp->inode;
 
-       if (lck == NULL) {
-               DEBUG(0, ("open_file_ntcreate: Could not get share mode lock 
for %s\n", fname));
-               fd_close(conn, fsp);
-               file_free(fsp);
-               set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
-               return NULL;
-       }
+               lck = get_share_mode_lock(NULL, dev, inode,
+                                       conn->connectpath,
+                                       fname);
 
-       /*
-        * The share entry is again *locked*.....
-        */
-
-       /* First pass - send break only on batch oplocks. */
-       if (delay_for_oplocks(lck, fsp, 1, oplock_request)) {
-               schedule_defer_open(lck, request_time);
-               fd_close(conn, fsp);
-               file_free(fsp);
-               TALLOC_FREE(lck);
-               set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
-               return NULL;
-       }
-
-       status = open_mode_check(conn, fname, lck,
-                                access_mask, share_access,
-                                create_options, &file_existed);
-
-       if (NT_STATUS_IS_OK(status)) {
-               /* We might be going to allow this open. Check oplock status 
again. */
-               /* Second pass - send break for both batch or exclusive 
oplocks. */
-               if (delay_for_oplocks(lck, fsp, 2, oplock_request)) {
-                       schedule_defer_open(lck, request_time);
+               if (lck == NULL) {
+                       DEBUG(0, ("open_file_ntcreate: Could not get share mode 
lock for %s\n", fname));
                        fd_close(conn, fsp);
                        file_free(fsp);
-                       TALLOC_FREE(lck);
                        set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
                        return NULL;
                }
-       }
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
-               /* DELETE_PENDING is not deferred for a second */
-               fd_close(conn, fsp);
-               file_free(fsp);
-               TALLOC_FREE(lck);
-               set_saved_ntstatus(status);
-               return NULL;
-       }
+               status = open_mode_check(conn, fname, lck,
+                                        access_mask, share_access,
+                                        create_options, &file_existed);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               struct deferred_open_record state;
+               if (!NT_STATUS_IS_OK(status)) {
+                       struct deferred_open_record state;
 
-               fd_close(conn, fsp);
-               file_free(fsp);
+                       fd_close(conn, fsp);
+                       file_free(fsp);
 
-               state.delayed_for_oplocks = False;
-               state.dev = dev;
-               state.inode = inode;
+                       state.delayed_for_oplocks = False;
+                       state.dev = dev;
+                       state.inode = inode;
 
-               /* Do it all over again immediately. In the second
-                * round we will find that the file existed and handle
-                * the DELETE_PENDING and FCB cases correctly. No need
-                * to duplicate the code here. Essentially this is a
-                * "goto top of this function", but don't tell
-                * anybody... */
+                       /* Do it all over again immediately. In the second
+                        * round we will find that the file existed and handle
+                        * the DELETE_PENDING and FCB cases correctly. No need
+                        * to duplicate the code here. Essentially this is a
+                        * "goto top of this function", but don't tell
+                        * anybody... */
 
-               defer_open(lck, request_time, timeval_zero(),
-                          &state);
-               TALLOC_FREE(lck);
-               return NULL;
+                       defer_open(lck, request_time, timeval_zero(),
+                                  &state);
+                       TALLOC_FREE(lck);
+                       return NULL;
+               }
+
+               /*
+                * We exit this block with the share entry *locked*.....
+                */
+
        }
 
+       SMB_ASSERT(lck != NULL);
+
        /* note that we ignore failure for the following. It is
            basically a hack for NFS, and NFS will never set one of
            these only read them. Nobody but Samba can ever set a deny
@@ -1685,7 +1665,7 @@
 
        if (file_existed) {
                /* stat opens on existing files don't get oplocks. */
-               if (is_stat_open(fsp->access_mask)) {
+               if (is_stat_open(open_access_mask)) {
                        fsp->oplock_type = NO_OPLOCK;
                }
 
@@ -1828,7 +1808,7 @@
 
        /* note! we must use a non-zero desired access or we don't get
            a real file descriptor. Oh what a twisted web we weave. */
-       fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA);
+       fsp_open = 
open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA,FILE_WRITE_DATA);
 
        /* 
         * This is not a user visible file open.

Reply via email to