smbtorture: Add smb2.maxfid
authorChristof Schmitt <cs@samba.org>
Mon, 11 Jul 2016 18:32:19 +0000 (11:32 -0700)
committerJeremy Allison <jra@samba.org>
Wed, 13 Jul 2016 01:00:15 +0000 (03:00 +0200)
This is the same as base.maxfid, but for the SMB2 protocol: Keep opening
file handles until an error is returned, print the number of file
handles opened and finally close the file handles again.

Signed-off-by: Christof Schmitt <cs@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source4/torture/smb2/maxfid.c [new file with mode: 0644]
source4/torture/smb2/smb2.c
source4/torture/smb2/wscript_build

diff --git a/source4/torture/smb2/maxfid.c b/source4/torture/smb2/maxfid.c
new file mode 100644 (file)
index 0000000..3de76ab
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   SMB2 maxfid test
+
+   Copyright (C) Christof Schmitt 2016
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+
+#include "torture/torture.h"
+#include "torture/smb2/proto.h"
+
+bool torture_smb2_maxfid(struct torture_context *tctx)
+{
+       bool ret = true;
+       NTSTATUS status;
+       struct smb2_tree *tree = NULL;
+       const char *dname = "smb2_maxfid";
+       int i, maxfid;
+       struct smb2_handle *handles,  dir_handle = { };
+       const size_t max_handles = 0x41000; /* Windows 8.1 allowed 0x40000 */
+
+       if (!torture_smb2_connection(tctx, &tree)) {
+               return false;
+       }
+
+       handles = talloc_array(tctx, struct smb2_handle, max_handles);
+       if (handles == 0) {
+               torture_fail(tctx, "Could not allocate handles array.\n");
+               return false;
+       }
+
+       smb2_deltree(tree, dname);
+
+       status = torture_smb2_testdir(tree, dname, &dir_handle);
+       torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                       "torture_smb2_testdir failed");
+       smb2_util_close(tree, dir_handle);
+
+       torture_comment(tctx, "Creating subdirectories\n");
+
+       for (i = 0; i < max_handles; i += 1000) {
+               char *name;
+               struct smb2_create create = { };
+               struct smb2_close close = { };
+
+               name = talloc_asprintf(tctx, "%s\\%d", dname, i / 1000);
+               torture_assert_goto(tctx, (name != NULL), ret, done,
+                                   "no memory for directory name\n");
+
+               create.in.desired_access = SEC_RIGHTS_DIR_ALL;
+               create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+               create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+               create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+                       NTCREATEX_SHARE_ACCESS_WRITE |
+                       NTCREATEX_SHARE_ACCESS_DELETE;
+               create.in.create_disposition = NTCREATEX_DISP_CREATE;
+               create.in.fname = name;
+
+               status = smb2_create(tree, tctx, &create);
+               talloc_free(name);
+
+               torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                               "CREATE directory failed\n");
+
+               close.in.file.handle = create.out.file.handle;
+               status = smb2_close(tree, &close);
+               torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                               "CLOSE directory failed\n");
+       }
+
+       torture_comment(tctx, "Testing maximum number of open files\n");
+
+       for (i = 0; i < max_handles; i++) {
+               char *name;
+               struct smb2_create create = { };
+
+               name = talloc_asprintf(tctx, "%s\\%d\\%d", dname, i / 1000, i);
+               torture_assert_goto(tctx, (name != NULL), ret, done,
+                                   "no memory for file name\n");
+
+               create.in.desired_access = SEC_RIGHTS_DIR_ALL;
+               create.in.create_options = 0;
+               create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+               create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+                       NTCREATEX_SHARE_ACCESS_WRITE |
+                       NTCREATEX_SHARE_ACCESS_DELETE;
+               create.in.create_disposition = NTCREATEX_DISP_CREATE;
+               create.in.fname = name;
+
+               status = smb2_create(tree, tctx, &create);
+               if (!NT_STATUS_IS_OK(status)) {
+                       torture_comment(tctx, "create of %s failed: %s\n",
+                                       name, nt_errstr(status));
+                       talloc_free(name);
+                       break;
+               }
+               talloc_free(name);
+
+               handles[i] = create.out.file.handle;
+       }
+
+       maxfid = i;
+       torture_comment(tctx, "Maximum number of open files: %d\n", maxfid);
+
+       torture_comment(tctx, "Cleanup open files\n");
+
+       for (i = 0; i < maxfid; i++) {
+               union smb_setfileinfo sfinfo = { };
+
+               sfinfo.disposition_info.in.delete_on_close = 1;
+               sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
+               sfinfo.generic.in.file.handle = handles[i];
+
+               status = smb2_setinfo_file(tree, &sfinfo);
+               torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                               "SETINFO failed\n");
+
+               status = smb2_util_close(tree, handles[i]);
+               torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                               "CLOSE failed\n");
+       }
+
+done:
+       smb2_deltree(tree, dname);
+       talloc_free(handles);
+
+       return ret;
+}
index be632cccca5ad5a7cfe25f8ea68e88d4f8124204..ca07992d6eb728c6a3e6f1a9b43b98596954cb30 100644 (file)
@@ -171,6 +171,7 @@ NTSTATUS torture_smb2_init(void)
        torture_suite_add_suite(suite, torture_smb2_session_init());
        torture_suite_add_suite(suite, torture_smb2_replay_init());
        torture_suite_add_simple_test(suite, "dosmode", torture_smb2_dosmode);
+       torture_suite_add_simple_test(suite, "maxfid", torture_smb2_maxfid);
 
        torture_suite_add_suite(suite, torture_smb2_doc_init());
 
index f404356fc3e2c75f61ec6250da9830d4a0b18954..e667f00a0c080a33d47247fd36e568092948ac43 100644 (file)
@@ -3,7 +3,7 @@
 bld.SAMBA_MODULE('TORTURE_SMB2',
        source='''connect.c scan.c util.c getinfo.c setinfo.c lock.c notify.c
        smb2.c durable_open.c durable_v2_open.c oplock.c dir.c lease.c create.c
-       acls.c read.c compound.c streams.c ioctl.c rename.c
+       acls.c read.c compound.c streams.c ioctl.c rename.c maxfid.c
        session.c delete-on-close.c replay.c notify_disabled.c dosmode.c''',
        subsystem='smbtorture',
        deps='LIBCLI_SMB2 POPT_CREDENTIALS torture NDR_IOCTL',