diff options
author | Volker Lendecke <vl@samba.org> | 2012-01-10 17:07:29 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2012-01-12 23:59:22 +0100 |
commit | 6da246bae1b000cb3191e114e978510ccacb7e90 (patch) | |
tree | 05bb1518abf7c2723efc049e99dd0713a5642d10 | |
parent | 6f9442a705b7ca67c78137db537f556385aa8558 (diff) | |
download | samba-6da246bae1b000cb3191e114e978510ccacb7e90.tar.gz samba-6da246bae1b000cb3191e114e978510ccacb7e90.tar.bz2 samba-6da246bae1b000cb3191e114e978510ccacb7e90.zip |
s3: Fix nested get_share_mode_lock calls
This forces us to only do one real get_share_mode_lock call and
share the data between the nested get_share_mode_lock calls.
Signed-off-by: Jeremy Allison <jra@samba.org>
-rw-r--r-- | source3/locking/share_mode_lock.c | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c index 1fb96998d7..51f09ae2af 100644 --- a/source3/locking/share_mode_lock.c +++ b/source3/locking/share_mode_lock.c @@ -306,11 +306,10 @@ fail: return NULL; } -struct share_mode_lock *get_share_mode_lock_fresh(TALLOC_CTX *mem_ctx, - const struct file_id id, - const char *servicepath, - const struct smb_filename *smb_fname, - const struct timespec *old_write_time) +static struct share_mode_lock *get_share_mode_lock_internal( + TALLOC_CTX *mem_ctx, const struct file_id id, + const char *servicepath, const struct smb_filename *smb_fname, + const struct timespec *old_write_time) { struct share_mode_lock *lck; struct share_mode_data *d; @@ -353,6 +352,59 @@ struct share_mode_lock *get_share_mode_lock_fresh(TALLOC_CTX *mem_ctx, return lck; } +/* + * We can only ever have one share mode locked. Users of + * get_share_mode_lock never see this, it will be refcounted by + * talloc_reference. + */ +static struct share_mode_lock *the_lock; + +static int the_lock_destructor(struct share_mode_lock *l) +{ + the_lock = NULL; + return 0; +} + +struct share_mode_lock *get_share_mode_lock_fresh( + TALLOC_CTX *mem_ctx, + const struct file_id id, + const char *servicepath, + const struct smb_filename *smb_fname, + const struct timespec *old_write_time) +{ + TALLOC_CTX *frame = talloc_stackframe(); + + struct share_mode_lock *lck; + + if (the_lock == NULL) { + the_lock = get_share_mode_lock_internal( + frame, id, servicepath, smb_fname, old_write_time); + if (the_lock == NULL) { + goto fail; + } + talloc_set_destructor(the_lock, the_lock_destructor); + } + if (!file_id_equal(&the_lock->data->id, &id)) { + DEBUG(1, ("Can not lock two share modes simultaneously\n")); + goto fail; + } + lck = talloc(mem_ctx, struct share_mode_lock); + if (lck == NULL) { + DEBUG(1, ("talloc failed\n")); + goto fail; + } + if (talloc_reference(lck, the_lock) == NULL) { + DEBUG(1, ("talloc_reference failed\n")); + goto fail; + } + lck->data = the_lock->data; + TALLOC_FREE(frame); + return lck; +fail: + TALLOC_FREE(frame); + return NULL; +} + struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, const struct file_id id) { |