TODO source4/torture/smb2/durable_open.c
authorStefan Metzmacher <metze@samba.org>
Tue, 14 Aug 2018 13:16:21 +0000 (15:16 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 14 Aug 2018 17:06:03 +0000 (19:06 +0200)
source4/torture/smb2/durable_open.c

index 61412558b35c3b91f83fd6ce7d2339c438e4e1b1..0704fe4af8fdfcdb151c140e328a756680350da9 100644 (file)
@@ -2917,9 +2917,11 @@ static bool test_delay_writetime(struct torture_context *tctx,
                                 bool (*write_data_cb)(void *private_data),
                                 void *private_data)
 {
-       union smb_fileinfo finfo0, finfo1, finfoT;
+       union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfoT;
        struct timeval before_write;
        struct timeval after_write;
+       struct timeval before_last_write;
+       struct timeval after_last_write;
        struct timeval start;
        struct timeval end;
        double sec = used_delay / normal_delay;
@@ -2959,7 +2961,6 @@ static bool test_delay_writetime(struct torture_context *tctx,
        ok = write_data_cb(private_data);
        after_write = timeval_current();
        torture_assert(tctx, ok, "write_data_cb");
-       (void)(&before_write == &after_write);
 
        start = timeval_current();
        end = timeval_add(&start, max_delay * 2, 0);
@@ -2972,7 +2973,6 @@ static bool test_delay_writetime(struct torture_context *tctx,
                ok = get_basic_info_cb(private_data, &finfoT);
                after_get = timeval_current();
                torture_assert(tctx, ok, "get_basic_info_cb: finfoT");
-               (void)(&before_get == &after_get);
 
                if (finfoT.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
                        double delayS = timeval_elapsed2(&after_write, &before_get);
@@ -3014,50 +3014,81 @@ static bool test_delay_writetime(struct torture_context *tctx,
        ok = get_basic_info_cb(private_data, &finfoT);
        torture_assert(tctx, ok, "get_basic_info_cb: finfoT");
        COMPARE_ALL_TIMES_EQUAL(finfoT, finfo1);
-#if 0
+
+       torture_comment(tctx, "Do a write on the file handle\n");
+       before_write = timeval_current();
+       ok = write_data_cb(private_data);
+       after_write = timeval_current();
+       torture_assert(tctx, ok, "write_data_cb");
+
+       ZERO_STRUCT(finfo2);
+       before_last_write = before_write;
+       after_last_write = after_write;
        start = timeval_current();
-       end = timeval_add(&start, 7 * sec, 0);
+       end = timeval_add(&start, max_delay * 2, 0);
        while (!timeval_expired(&end)) {
-               union smb_fileinfo finfoT0;
-               union smb_fileinfo finfoT1;
+               struct timeval before_get;
+               struct timeval after_get;
 
-               ok = get_basic_info_cb(private_data, &finfoT0);
-               torture_assert(tctx, ok, "get_basic_info_cb: finfoT0");
+               smb_msleep(0.01 * msec);
 
-               torture_comment(tctx, "Do a write on the file handle\n");
-               ok = write_data_cb(private_data);
-               torture_assert_ntstatus_ok(tctx, status);
-
-               ok = get_basic_info_cb(private_data, &finfoT1);
-               torture_assert(tctx, ok, "get_basic_info_cb: finfoT1");
-               COMPARE_WRITE_TIME_EQUAL(finfoT1, finfoT0);
-
-               if (finfo.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
-                       double diff = timeval_elapsed(&start);
-                       if (diff < (used_delay / (double)1000000)) {
-                               torture_result(tctx, TORTURE_FAIL, __location__": Server updated write_time after %.2f seconds "
-                                               "(write time update delay == %.2f) (wrong!)\n",
-                                               diff, used_delay / (double)1000000);
-                               ret = false;
-                               break;
-                       }
-
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(correct)\n",
-                                       diff);
-                       changed = true;
+               torture_comment(tctx, "Wait for change\n");
+               before_get = timeval_current();
+               ok = get_basic_info_cb(private_data, &finfoT);
+               after_get = timeval_current();
+               torture_assert(tctx, ok, "get_basic_info_cb: finfoT");
+
+               if (finfoT.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
+                       double delayS = timeval_elapsed2(&after_write, &before_get);
+                       double delayL = timeval_elapsed2(&before_write, &after_get);
+
+                       torture_comment(tctx, "Server updated write_time after %.2f/%.2f seconds "
+                                       "(min delay == %.2f, max delay == %.2f)\n",
+                                       delayS, delayL, min_delay, max_delay);
+                       torture_assert(tctx, (delayL >= min_delay),
+                                      "Server updated write_time to early!");
+                       torture_assert(tctx, (delayS <= max_delay),
+                                      "Server didn't update write_time!");
+
+                       COMPARE_TIMES_AFTER_WRITE(finfoT, finfo1);
+                       before_write = before_last_write;
+                       after_write = after_last_write;
+                       finfo2 = finfoT;
                        break;
                }
-               ok = get_basic_info_cb(private_data, &finfo1);
-               torture_assert_ntstatus_ok(tctx, status);
 
-               COMPARE_WRITE_TIME_EQUAL(finfo1, finfoT);
-               smb_msleep(0.5 * msec);
+               COMPARE_ALL_TIMES_EQUAL(finfoT, finfo1);
+
+               torture_comment(tctx, "Write while waiting\n");
+               before_last_write = timeval_current();
+               ok = write_data_cb(private_data);
+               after_last_write = timeval_current();
+               torture_assert(tctx, ok, "write_data_cb");
+       }
+
+       // We may get one additional change...
+
+       ok = get_basic_info_cb(private_data, &finfo3);
+       torture_assert(tctx, ok, "get_basic_info_cb: finfo3");
+       COMPARE_ALL_TIMES_EQUAL(finfo3, finfo2);
+
+       /*
+        * Make sure the time doesn't change during the next 5 seconds
+        */
+       start = timeval_current();
+       end = timeval_add(&start, max_delay * 1.25, 0);
+       while (!timeval_expired(&end)) {
+               smb_msleep(1 * msec);
+               torture_comment(tctx, "Check for no additional change\n");
+               ok = get_basic_info_cb(private_data, &finfoT);
+               torture_assert(tctx, ok, "get_basic_info_cb: finfoT");
+               COMPARE_ALL_TIMES_EQUAL(finfoT, finfo3);
        }
-       changed = false;
-       GET_INFO_BOTH(finfo1, c2finfo1);
-       COMPARE_WRITE_TIME_GREATER(finfo1, finfo0);
-#endif
+
+       ok = get_basic_info_cb(private_data, &finfoT);
+       torture_assert(tctx, ok, "get_basic_info_cb: finfoT");
+       COMPARE_ALL_TIMES_EQUAL(finfoT, finfo3);
+
 done:
        return ret;
 }
@@ -3092,6 +3123,13 @@ static bool test_durable_open_delaywrite1_get_info(void *private_data,
 
        GET_INFO_FILE(state->tree2, t2finfo);
        GET_INFO_FILE(state->tree1, t1finfo);
+       if (t1finfo.basic_info.out.write_time != t2finfo.basic_info.out.write_time) {
+               /*
+                * There was a race, get it again on handle 2,
+                * but then they have to match.
+                */
+               GET_INFO_FILE(state->tree2, t2finfo);
+       }
        COMPARE_ALL_TIMES_EQUAL(t1finfo, t2finfo);
 
        finfo->basic_info.out = t1finfo.basic_info.out;
@@ -3133,20 +3171,16 @@ static bool test_durable_open_delaywrite1(struct torture_context *tctx,
        NTSTATUS status;
        TALLOC_CTX *mem_ctx = talloc_new(tctx);
        char fname[256];
-       struct smb2_handle _h;
-       struct smb2_handle *h = NULL;
+       struct smb2_handle _h1;
+       struct smb2_handle *h1 = NULL;
        struct smb2_handle _h2;
        struct smb2_handle *h2 = NULL;
-       struct smb2_create cr;
+       struct smb2_create cr1;
        struct smb2_create cr2;
-       union smb_fileinfo finfoCR, finfo0, finfo1, finfo2, finfo3, finfo4, finfoT, finfoCL;
-       union smb_fileinfo c2finfoCR, c2finfo0, c2finfo1, c2finfo2, c2finfo3, c2finfo4, c2finfoT, c2finfoCL;
-       struct smb2_close cl;
+       union smb_fileinfo c1finfoCR, c1finfo0, c1finfo1, c1finfo2, c1finfoCL;
+       union smb_fileinfo c2finfoCR, c2finfo0, c2finfo1, c2finfo2, c2finfo3, c2finfoCL;
+       struct smb2_close cl1;
        struct smb2_close cl2;
-       struct smb2_write wr;
-       ssize_t written;
-       struct timeval start;
-       struct timeval end;
        //double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        //double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 1000000);
        double normal_delay = 1000000;
@@ -3156,7 +3190,6 @@ static bool test_durable_open_delaywrite1(struct torture_context *tctx,
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
        bool ret = true;
-       bool changed = false;
        bool ok;
 
        /* Choose a random name in case the state is left a little funky. */
@@ -3165,132 +3198,23 @@ static bool test_durable_open_delaywrite1(struct torture_context *tctx,
 
        smb2_util_unlink(tree1, fname);
 
-       smb2_oplock_create_share(&cr, fname,
+       smb2_oplock_create_share(&cr1, fname,
                                 smb2_util_share_access(""),
                                 smb2_util_oplock_level("b"));
-       cr.in.durable_open = true;
+       cr1.in.durable_open = true;
 
-       status = smb2_create(tree1, mem_ctx, &cr);
+       status = smb2_create(tree1, mem_ctx, &cr1);
        CHECK_STATUS(status, NT_STATUS_OK);
-       _h = cr.out.file.handle;
-       h = &_h;
-       CHECK_CREATED(&cr, CREATED, FILE_ATTRIBUTE_ARCHIVE);
-       CHECK_VAL(cr.out.oplock_level, smb2_util_oplock_level("b"));
-       CHECK_VAL(cr.out.durable_open, true);
-       CHECK_VAL(cr.out.durable_open_v2, false);
-       CHECK_VAL(cr.out.persistent_open, false);
-       //CHECK_VAL(io.out.timeout, io.in.timeout);
-
-       //      struct {
-       //              NTTIME create_time;
-       //              NTTIME access_time;
-       //              NTTIME write_time;
-       //              NTTIME change_time;
-       //              uint32_t attrib;
-       //      } out;
-       //} basic_info;
-       ZERO_STRUCT(finfoCR);
-       finfoCR.basic_info.out.create_time = cr.out.create_time;
-       finfoCR.basic_info.out.access_time = cr.out.access_time;
-       finfoCR.basic_info.out.write_time = cr.out.write_time;
-       finfoCR.basic_info.out.change_time = cr.out.change_time;
-       finfoCR.basic_info.out.attrib = cr.out.file_attr;
-
-       ZERO_STRUCT(finfo0);
-       finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFORMATION;
-       finfo0.basic_info.in.file.handle = *h;
-       finfo1 = finfo0;
-       finfo2 = finfo0;
-       finfo3 = finfo0;
-       finfo4 = finfo0;
-       finfoT = finfo0;
+       _h1 = cr1.out.file.handle;
+       h1 = &_h1;
+       CHECK_CREATED(&cr1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+       CHECK_VAL(cr1.out.oplock_level, smb2_util_oplock_level("b"));
+       CHECK_VAL(cr1.out.durable_open, true);
+       CHECK_VAL(cr1.out.durable_open_v2, false);
+       CHECK_VAL(cr1.out.persistent_open, false);
 
-       /* get the initial times */
-       GET_INFO_FILE(tree1, finfo0);
-       COMPARE_WRITE_TIME_EQUAL(finfoCR, finfo0);
-
-                       ///* static body buffer 56 (0x38) bytes */
-                       //uint8_t  security_flags;      /* SMB2_SECURITY_* */
-                       //uint8_t  oplock_level;        /* SMB2_OPLOCK_LEVEL_* */
-                       //uint32_t impersonation_level; /* SMB2_IMPERSONATION_* */
-                       //uint64_t create_flags;
-                       //uint64_t reserved;
-                       //uint32_t desired_access;
-                       //uint32_t file_attributes;
-                       //uint32_t share_access; /* NTCREATEX_SHARE_ACCESS_* */
-                       //uint32_t create_disposition; /* NTCREATEX_DISP_* */
-                       //uint32_t create_options; /* NTCREATEX_OPTIONS_* */
-
-                       ///* uint16_t fname_ofs */
-                       ///* uint16_t fname_size */
-                       ///* uint32_t blob_ofs; */
-                       ///* uint32_t blob_size; */
-
-                       ///* dynamic body */
-                       //const char *fname;
-
-                       ///* now some optional parameters - encoded as tagged blobs */
-                       //struct smb_ea_list eas;
-                       //uint64_t alloc_size;
-                       //struct security_descriptor *sec_desc;
-                       //bool   durable_open;
-                       //struct smb2_handle *durable_handle;
-
-                       ///* data for durable handle v2 */
-                       //bool durable_open_v2;
-                       //struct GUID create_guid;
-                       //bool persistent_open;
-                       //uint32_t timeout;
-                       //struct smb2_handle *durable_handle_v2;
-
-                       //bool   query_maximal_access;
-                       //NTTIME timewarp;
-                       //bool   query_on_disk_id;
-                       //struct smb2_lease *lease_request;
-                       //struct smb2_lease *lease_request_v2;
-
-                       //struct GUID *app_instance_id;
-
-                       ///* and any additional blobs the caller wants */
-                       //struct smb2_create_blobs blobs;
-               //} in;
-               //struct {//
-                       //union smb_handle file;
-
-                       ///* static body buffer 88 (0x58) bytes */
-                       ///* uint16_t buffer_code;  0x59 = 0x58 + 1 */
-                       //uint8_t oplock_level;
-                       //uint8_t reserved;
-                       //uint32_t create_action;
-                       //NTTIME   create_time;
-                       //NTTIME   access_time;
-                       //NTTIME   write_time;
-                       //NTTIME   change_time;
-                       //uint64_t alloc_size;
-                       //uint64_t size;
-                       //uint32_t file_attr;
-                       //uint32_t reserved2;
-                       ///* struct smb2_handle handle;*/
-                       ///* uint32_t blob_ofs; */
-                       ///* uint32_t blob_size; */
-
-                       ///* optional return values matching tagged values in the call */
-                       //uint32_t maximal_access;
-                       //uint8_t on_disk_id[32];
-                       //struct smb2_lease lease_response;
-                       //struct smb2_lease lease_response_v2;
-                       //bool durable_open;
-
-                       ///* durable handle v2 */
-                       //bool durable_open_v2;
-                       //bool persistent_open;
-                       //uint32_t timeout;
-
-                       ///* tagged blobs in the reply */
-                       //struct smb2_create_blobs blobs;
-               //} out;
-       cr2 = cr;
-       cr2.in.desired_access = SEC_FILE_READ_ATTRIBUTE;//FILE_READ_ATTRIBUTES;
+       cr2 = cr1;
+       cr2.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
        cr2.in.durable_open = false;
        cr2.in.oplock_level = 0;
        cr2.in.create_disposition = NTCREATEX_DISP_OPEN;
@@ -3304,6 +3228,13 @@ static bool test_durable_open_delaywrite1(struct torture_context *tctx,
        CHECK_VAL(cr2.out.durable_open_v2, false);
        CHECK_VAL(cr2.out.persistent_open, false);
 
+       ZERO_STRUCT(c1finfoCR);
+       c1finfoCR.basic_info.out.create_time = cr1.out.create_time;
+       c1finfoCR.basic_info.out.access_time = cr1.out.access_time;
+       c1finfoCR.basic_info.out.write_time = cr1.out.write_time;
+       c1finfoCR.basic_info.out.change_time = cr1.out.change_time;
+       c1finfoCR.basic_info.out.attrib = cr1.out.file_attr;
+
        ZERO_STRUCT(c2finfoCR);
        c2finfoCR.basic_info.out.create_time = cr2.out.create_time;
        c2finfoCR.basic_info.out.access_time = cr2.out.access_time;
@@ -3311,153 +3242,50 @@ static bool test_durable_open_delaywrite1(struct torture_context *tctx,
        c2finfoCR.basic_info.out.change_time = cr2.out.change_time;
        c2finfoCR.basic_info.out.attrib = cr2.out.file_attr;
 
+       COMPARE_ALL_TIMES_EQUAL(c1finfoCR, c2finfoCR);
+
+       ZERO_STRUCT(c1finfo0);
+       c1finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFORMATION;
+       c1finfo0.basic_info.in.file.handle = *h1;
+       c1finfo1 = c1finfo0;
+       c1finfo2 = c1finfo0;
+
        ZERO_STRUCT(c2finfo0);
        c2finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFORMATION;
        c2finfo0.basic_info.in.file.handle = *h2;
        c2finfo1 = c2finfo0;
        c2finfo2 = c2finfo0;
        c2finfo3 = c2finfo0;
-       c2finfo4 = c2finfo0;
-       c2finfoT = c2finfo0;
 
-       /* get the initial times */
-       GET_INFO_FILE(tree2, c2finfo0);
-       COMPARE_WRITE_TIME_EQUAL(c2finfoCR, c2finfo0);
+       GET_INFO_BOTH(c1finfo0, c2finfo0);
+       COMPARE_ALL_TIMES_EQUAL(c1finfo0, c1finfoCR);
 
-       state.h1 = h;
+       state.h1 = h1;
        state.h2 = h2;
 
        ok = test_delay_writetime(tctx, used_delay, normal_delay,
-                       "some description",
+                       "run1",
                        test_durable_open_delaywrite1_get_info,
                        test_durable_open_delaywrite1_write_data,
                        &state);
-       torture_assert(tctx, ok, "test_delay_writetime");
-goto close_handles;
-goto done;
-       /*
-        * make sure the write time is updated 2 seconds later
-        * calcuated from the first write
-        * (but expect upto 5 seconds extra time for a busy server)
-        */
-       start = timeval_current();
-       end = timeval_add(&start, 7 * sec, 0);
-       while (!timeval_expired(&end)) {
-               /* do a write */
-               torture_comment(tctx, "Do a write on the file handle\n");
-               GET_INFO_BOTH(finfoT, c2finfoT);
-               ZERO_STRUCT(wr);
-               wr.in.file.handle = *h;
-               wr.in.offset      = 0;
-               wr.in.data        = data_blob_const("x", 1);
-               status = smb2_write(tree1, &wr);
-               CHECK_STATUS(status, NT_STATUS_OK);
-               written = wr.out.nwritten;
-               if (written != 1) {
-                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
-                       ret = false;
-                       goto done;
-               }
-               /* get the times after the write */
-               GET_INFO_BOTH(finfo1, c2finfo1);
-               if (changed) {
-                       COMPARE_WRITE_TIME_GREATER(finfo1, finfoT);
-               }
-
-               if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
-                       double diff = timeval_elapsed(&start);
-                       if (diff < (used_delay / (double)1000000)) {
-                               torture_result(tctx, TORTURE_FAIL, __location__": Server updated write_time after %.2f seconds "
-                                               "(write time update delay == %.2f) (wrong!)\n",
-                                               diff, used_delay / (double)1000000);
-                               ret = false;
-                               break;
-                       }
-
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(correct)\n",
-                                       diff);
-                       changed = true;
-                       break;
-               }
-               COMPARE_WRITE_TIME_EQUAL(finfo1, finfoT);
-               smb_msleep(0.5 * msec);
-       }
-
-       changed = false;
-       GET_INFO_BOTH(finfo1, c2finfo1);
-       COMPARE_WRITE_TIME_GREATER(finfo1, finfo0);
-
-       /* sure any further write doesn't update the write time */
-       start = timeval_current();
-       end = timeval_add(&start, 15 * sec, 0);
-       while (!timeval_expired(&end)) {
-               /* do a write */
-               torture_comment(tctx, "Do a write on the file handle\n");
-               ZERO_STRUCT(wr);
-               wr.in.file.handle = *h;
-               wr.in.offset      = 0;
-               wr.in.data        = data_blob_const("x", 1);
-               status = smb2_write(tree1, &wr);
-               CHECK_STATUS(status, NT_STATUS_OK);
-               written = wr.out.nwritten;
-               if (written != 1) {
-                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
-                       ret = false;
-                       goto done;
-               }
-               /* get the times after the write */
-               GET_INFO_BOTH(finfo2, c2finfo2);
-
-               if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
-                       double diff = timeval_elapsed(&start);
-                       torture_result(tctx, TORTURE_FAIL, __location__": Server updated write_time after %.2f seconds "
-                                       "(wrong!)\n",
-                                       diff);
-                       ret = false;
-                       //break;
-               }
-               smb_msleep(0.1 * msec);
-               //smb_msleep(1 * msec);
-       }
-
-       GET_INFO_BOTH(finfo2, c2finfo2);
-       //COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
-       COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
-       if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write_time (correct)\n");
-       }
+       torture_assert(tctx, ok, "test_delay_writetime(1)");
+       ok = test_delay_writetime(tctx, used_delay, normal_delay,
+                       "run2",
+                       test_durable_open_delaywrite1_get_info,
+                       test_durable_open_delaywrite1_write_data,
+                       &state);
+       torture_assert(tctx, ok, "test_delay_writetime(2)");
 
-       /* sure any further write doesn't update the write time */
-       start = timeval_current();
-       end = timeval_add(&start, 15 * sec, 0);
-       while (!timeval_expired(&end)) {
-               /* do a write */
-               torture_comment(tctx, "Check on both file handles\n");
-               GET_INFO_BOTH(finfo3, c2finfo3);
-
-               if (finfo3.basic_info.out.write_time > finfo2.basic_info.out.write_time) {
-                       double diff = timeval_elapsed(&start);
-                       torture_result(tctx, TORTURE_FAIL, __location__": Server updated write_time after %.2f seconds "
-                                       "(wrong!)\n",
-                                       diff);
-                       ret = false;
-                       break;
-               }
-               smb_msleep(0.1 * msec);
-               //smb_msleep(1 * msec);
-       }
-close_handles:
-       GET_INFO_BOTH(finfo3, c2finfo3);
-       //COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
+       GET_INFO_BOTH(c1finfo1, c2finfo1);
+       COMPARE_TIMES_AFTER_WRITE(c1finfo1, c1finfo0);
 
        /* sleep */
        torture_comment(tctx, "Sleep ...\n");
        smb_msleep(5 * msec);
        torture_comment(tctx, "... continue\n");
 
-       GET_INFO_BOTH(finfo4, c2finfo4);
-       COMPARE_WRITE_TIME_EQUAL(finfo4, finfo3);
+       GET_INFO_BOTH(c1finfo2, c2finfo2);
+       COMPARE_ALL_TIMES_EQUAL(c1finfo2, c1finfo1);
 
        /*
         * the close updates the write time to the time of the close
@@ -3465,23 +3293,22 @@ close_handles:
         */
        torture_comment(tctx, "Close the file handle\n");
 
-       ZERO_STRUCT(cl);
-       cl.in.file.handle = *h;
-       cl.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
-       status = smb2_close(tree1, &cl);
+       ZERO_STRUCT(cl1);
+       cl1.in.file.handle = *h1;
+       cl1.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
+       status = smb2_close(tree1, &cl1);
        CHECK_STATUS(status, NT_STATUS_OK);
-       h = NULL;
-       ZERO_STRUCT(finfoCL);
-       finfoCL.basic_info.out.create_time = cl.out.create_time;
-       finfoCL.basic_info.out.access_time = cl.out.access_time;
-       finfoCL.basic_info.out.write_time = cl.out.write_time;
-       finfoCL.basic_info.out.change_time = cl.out.change_time;
-       finfoCL.basic_info.out.attrib = cl.out.file_attr;
-       //COMPARE_WRITE_TIME_GREATER(finfoCL, finfo3);
-       //COMPARE_TIMES_AFTER_CLOSE(finfoCL, finfo3);
+       h1 = NULL;
+       ZERO_STRUCT(c1finfoCL);
+       c1finfoCL.basic_info.out.create_time = cl1.out.create_time;
+       c1finfoCL.basic_info.out.access_time = cl1.out.access_time;
+       c1finfoCL.basic_info.out.write_time = cl1.out.write_time;
+       c1finfoCL.basic_info.out.change_time = cl1.out.change_time;
+       c1finfoCL.basic_info.out.attrib = cl1.out.file_attr;
+       COMPARE_ALL_TIMES_EQUAL(c1finfoCL, c1finfo2);
 
        GET_INFO_FILE(tree2, c2finfo3);
-       COMPARE_ALL_TIMES_EQUAL(c2finfo3, finfoCL);
+       COMPARE_ALL_TIMES_EQUAL(c2finfo3, c1finfoCL);
 
        ZERO_STRUCT(cl2);
        cl2.in.file.handle = *h2;
@@ -3495,35 +3322,14 @@ close_handles:
        c2finfoCL.basic_info.out.write_time = cl2.out.write_time;
        c2finfoCL.basic_info.out.change_time = cl2.out.change_time;
        c2finfoCL.basic_info.out.attrib = cl2.out.file_attr;
-       COMPARE_ALL_TIMES_EQUAL(c2finfoCL, finfoCL);
-               //struct {
-               //      /* static body buffer 60 (0x3C) bytes */
-               //      /* uint16_t buffer_code;  0x3C */
-               //      uint16_t flags;
-               //      uint32_t _pad;
-               //      NTTIME   create_time;
-               //      NTTIME   access_time;
-               //      NTTIME   write_time;
-               //      NTTIME   change_time;
-               //      uint64_t alloc_size;
-               //      uint64_t size;
-               //      uint32_t file_attr;
-               //} out;
-
-       //if (pinfo4.basic_info.out.write_time > pinfo3.basic_info.out.write_time) {
-       //      torture_comment(tctx, "Server updated the write_time on close (correct)\n");
-       //}
-       ///* try a durable reconnect while the file is still open */
-       //ZERO_STRUCT(io);
-       //io.in.fname = "";
-       //io.in.durable_handle_v2 = h;
-       //io.in.create_guid = create_guid;
-       //status = smb2_create(tree1, mem_ctx, &io);
-       //CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+       COMPARE_ALL_TIMES_EQUAL(c2finfoCL, c1finfoCL);
 
 done:
-       if (h != NULL) {
-               smb2_util_close(tree1, *h);
+       if (h1 != NULL) {
+               smb2_util_close(tree1, *h1);
+       }
+       if (h2 != NULL) {
+               smb2_util_close(tree2, *h2);
        }
 
        smb2_util_unlink(tree1, fname);