diff options
author | Stefan Metzmacher <metze@samba.org> | 2012-06-01 16:29:51 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2012-06-03 17:23:28 +0200 |
commit | d792f59aeb4e74ea14d3c5979addd31b78b1a2d9 (patch) | |
tree | 0247314c86f9dcce7e1fe0541c2f974c167293ad | |
parent | b9e11bd63ee6e1f1aac8d3b8a61ef0a4734cdd98 (diff) | |
download | samba-d792f59aeb4e74ea14d3c5979addd31b78b1a2d9.tar.gz samba-d792f59aeb4e74ea14d3c5979addd31b78b1a2d9.tar.bz2 samba-d792f59aeb4e74ea14d3c5979addd31b78b1a2d9.zip |
s3: Fix an assert to trigger in close_remove_share_mode
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>
-rw-r--r-- | source3/smbd/close.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 9b7e7ac7f5..158108484b 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -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) { |