diff options
author | Steven Danneman <steven.danneman@isilon.com> | 2009-05-14 23:14:03 +0000 |
---|---|---|
committer | Tim Prouty <tprouty@samba.org> | 2009-09-24 11:31:35 -0700 |
commit | 60433b154dc345f8883b15d657e3f7d5c21fc6a1 (patch) | |
tree | 74c6b3bd612ae218e451d220f1d2cce9edf27072 | |
parent | 74c0a7a1d34a75abec32cc46ab0b02b483160215 (diff) | |
download | samba-60433b154dc345f8883b15d657e3f7d5c21fc6a1.tar.gz samba-60433b154dc345f8883b15d657e3f7d5c21fc6a1.tar.bz2 samba-60433b154dc345f8883b15d657e3f7d5c21fc6a1.zip |
s3 onefs: Fix 1 second share mode delay handling
When racing to the open and loosing we may get a share_mode violation.
In this case handle the 1-second delay via a defferred open properly.
This requires us to retrieve the share_mode_lock before deferring
open so we don't dereference a NULL pointer assuming we already had
the lck because we were the first opener.
-rw-r--r-- | source3/modules/onefs_open.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c index fa1f883c59..b9a2c30734 100644 --- a/source3/modules/onefs_open.c +++ b/source3/modules/onefs_open.c @@ -1095,9 +1095,39 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, state.id = id; state.failed = false; - if ((req != NULL) - && !request_timed_out(request_time, - timeout)) { + /* + * We hit the race that when we did the stat + * on the file it did not exist, and someone + * has created it in between the stat and the + * open_file() call. Retrieve the share_mode + * lock on the newly opened file so we can + * defer our request. + */ + if (lck == NULL) { + struct timespec old_write_time; + old_write_time = get_mtimespec(psbuf); + + lck = get_share_mode_lock(talloc_tos(), + id, conn->connectpath, fname, + &old_write_time); + if (lck == NULL) { + DEBUG(0, + ("onefs_open_file_ntcreate:" + " Could not get share " + "mode lock for %s\n", + fname)); + /* This will cause us to return + * immediately skipping the + * the 1 second delay, which + * isn't a big deal */ + status = NT_STATUS_SHARING_VIOLATION; + goto cleanup_destroy; + } + } + + if ((req != NULL) && + !request_timed_out(request_time, timeout)) + { defer_open(lck, request_time, timeout, req, &state); } |