]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3: Fix an assert to trigger in close_remove_share_mode
authorStefan Metzmacher <metze@samba.org>
Fri, 1 Jun 2012 14:29:51 +0000 (16:29 +0200)
committerStefan Metzmacher <metze@samba.org>
Sun, 3 Jun 2012 15:23:28 +0000 (17:23 +0200)
In case we have a left-over entry in the share mode entry array,
the SMB_ASSERT(got_tokens) is likely to kick in. It happens when
we are about to delete a file with initial delete on close. We don't
have a delete on close token set in the locking.tdb record. We see
the fsp->initial_delete_on_close set, add the delete_on_close token
to lck. Then "delete_file" is being set to true. Then later on we
do the notify_deferred_opens. This walks the list, also checking
for share_mode_stale_pid. We have already deleted our own share
mode entry, share_mode_stale_pid() sees the left-over entry. It not
also deletes that one but also the delete on close token. This leads
to a different view of "delete_file" a.k.a. "got_tokens" further
down in close_remove_share_mode, leading the SMB_ASSERT to fire.

This patch attempts to fix the issue by keeping around our own share
mode entry for almost the whole routine, preventing share_mode_stale_pid()
from removing the delete tokens.

Pair-Programmed-With: Volker Lendecke <vl@samba.org>

source3/smbd/close.c

index 9b7e7ac7f505596e9fe4ba49665c77df9fbfcc0c..158108484b759e5472935194d0a83268fc5b3eb5 100644 (file)
@@ -332,6 +332,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
                                        enum file_close_type close_type)
 {
        connection_struct *conn = fsp->conn;
+       struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
        bool delete_file = false;
        bool changed_user = false;
        struct share_mode_lock *lck = NULL;
@@ -386,12 +387,6 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
                }
        }
 
-       if (!del_share_mode(lck, fsp)) {
-               DEBUG(0, ("close_remove_share_mode: Could not delete share "
-                         "entry for file %s\n",
-                         fsp_str_dbg(fsp)));
-       }
-
        if (fsp->initial_delete_on_close &&
                        !is_delete_on_close_set(lck, fsp->name_hash)) {
                bool became_user = False;
@@ -432,6 +427,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
                            && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
                                continue;
                        }
+                       if (procid_equal(&self, &e->pid) &&
+                           (e->share_file_id == fsp->fh->gen_id)) {
+                               continue;
+                       }
                        if (share_mode_stale_pid(lck->data, i)) {
                                continue;
                        }
@@ -452,6 +451,13 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
        normal_close = (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE);
 
        if (!normal_close || !delete_file) {
+
+               if (!del_share_mode(lck, fsp)) {
+                       DEBUG(0, ("close_remove_share_mode: Could not delete "
+                                 "share entry for file %s\n",
+                                 fsp_str_dbg(fsp)));
+               }
+
                TALLOC_FREE(lck);
                return NT_STATUS_OK;
        }
@@ -571,6 +577,11 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
                pop_sec_ctx();
        }
 
+       if (!del_share_mode(lck, fsp)) {
+               DEBUG(0, ("close_remove_share_mode: Could not delete share "
+                         "entry for file %s\n", fsp_str_dbg(fsp)));
+       }
+
        TALLOC_FREE(lck);
 
        if (delete_file) {