s3/smbd: fix schedule_async_open() timer
authorRalph Boehme <slow@samba.org>
Tue, 7 Mar 2017 14:33:55 +0000 (15:33 +0100)
committerJeremy Allison <jra@samba.org>
Fri, 10 Mar 2017 02:28:25 +0000 (03:28 +0100)
schedule_async_open() was calling defer_open with sharemode lock = NULL,
as a result there was never an active 20 s timeout.

This has been broken since the commits in

$ git log --reverse -p -10 8283fd0e0090ed12b0b12d5acb550642d621b026

Just roll our own deferred record instead of calling defer_open() and
also set up timer that, as a last resort, catches stuck opens and just
exits for now.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/open.c

index d845ec2a03b0286720a1ae6d1c92a85ac46ee42f..ef0250e36bb733ae4259466a19c065e7e3761000 100644 (file)
@@ -45,6 +45,13 @@ struct deferred_open_record {
         bool delayed_for_oplocks;
        bool async_open;
         struct file_id id;
+
+       /*
+        * Timer for async opens, needed because they don't use a watch on
+        * a locking.tdb record. This is currently only used for real async
+        * opens and just terminates smbd if the async open times out.
+        */
+       struct tevent_timer *te;
 };
 
 /****************************************************************************
@@ -2236,19 +2243,44 @@ static void schedule_defer_open(struct share_mode_lock *lck,
  Reschedule an open call that went asynchronous.
 ****************************************************************************/
 
+static void schedule_async_open_timer(struct tevent_context *ev,
+                                     struct tevent_timer *te,
+                                     struct timeval current_time,
+                                     void *private_data)
+{
+       exit_server("async open timeout");
+}
+
 static void schedule_async_open(struct timeval request_time,
                                struct smb_request *req)
 {
-       struct timeval timeout;
-
-       timeout = timeval_set(20, 0);
+       struct deferred_open_record *open_rec = NULL;
+       struct timeval timeout = timeval_set(20, 0);
+       bool ok;
 
        if (request_timed_out(request_time, timeout)) {
                return;
        }
 
-       defer_open(NULL, request_time, timeout, req,
-                  false, true, (struct file_id){0});
+       open_rec = deferred_open_record_create(false, true, (struct file_id){0});
+       if (open_rec == NULL) {
+               exit_server("deferred_open_record_create failed");
+       }
+
+       ok = push_deferred_open_message_smb(req, request_time, timeout,
+                                           (struct file_id){0}, open_rec);
+       if (!ok) {
+               exit_server("push_deferred_open_message_smb failed");
+       }
+
+       open_rec->te = tevent_add_timer(req->sconn->ev_ctx,
+                                       req,
+                                       timeval_current_ofs(20, 0),
+                                       schedule_async_open_timer,
+                                       open_rec);
+       if (open_rec->te == NULL) {
+               exit_server("tevent_add_timer failed");
+       }
 }
 
 /****************************************************************************