summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Danneman <steven.danneman@isilon.com>2009-05-14 23:14:03 +0000
committerTim Prouty <tprouty@samba.org>2009-09-24 11:31:35 -0700
commit60433b154dc345f8883b15d657e3f7d5c21fc6a1 (patch)
tree74c6b3bd612ae218e451d220f1d2cce9edf27072
parent74c0a7a1d34a75abec32cc46ab0b02b483160215 (diff)
downloadsamba-60433b154dc345f8883b15d657e3f7d5c21fc6a1.tar.gz
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.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c
index fa1f883c591..b9a2c30734c 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);
}