Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : SMB2 maxfid test
5 :
6 : Copyright (C) Christof Schmitt 2016
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "libcli/smb2/smb2.h"
24 : #include "libcli/smb2/smb2_calls.h"
25 :
26 : #include "torture/torture.h"
27 : #include "torture/smb2/proto.h"
28 :
29 1 : bool torture_smb2_maxfid(struct torture_context *tctx)
30 : {
31 1 : bool ret = true;
32 : NTSTATUS status;
33 1 : struct smb2_tree *tree = NULL;
34 1 : const char *dname = "smb2_maxfid";
35 : size_t i, maxfid;
36 1 : struct smb2_handle *handles, dir_handle = { };
37 : size_t max_handles;
38 :
39 : /*
40 : * We limited this to 65520 as socket_wrapper has a limit of
41 : * 65535 (0xfff0) open sockets.
42 : *
43 : * It could be increased by setting the following env variable:
44 : *
45 : * SOCKET_WRAPPER_MAX_SOCKETS=100000
46 : */
47 1 : max_handles = torture_setting_int(tctx, "maxopenfiles", 65520);
48 :
49 1 : if (!torture_smb2_connection(tctx, &tree)) {
50 0 : return false;
51 : }
52 :
53 1 : handles = talloc_array(tctx, struct smb2_handle, max_handles);
54 1 : if (handles == 0) {
55 0 : torture_fail(tctx, "Could not allocate handles array.\n");
56 : return false;
57 : }
58 :
59 1 : smb2_deltree(tree, dname);
60 :
61 1 : status = torture_smb2_testdir(tree, dname, &dir_handle);
62 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
63 : "torture_smb2_testdir failed");
64 1 : smb2_util_close(tree, dir_handle);
65 :
66 1 : torture_comment(tctx, "Creating subdirectories\n");
67 :
68 134 : for (i = 0; i < max_handles; i += 1000) {
69 : char *name;
70 66 : struct smb2_create create = { };
71 66 : struct smb2_close close = { };
72 :
73 66 : name = talloc_asprintf(tctx, "%s\\%zu", dname, i / 1000);
74 66 : torture_assert_goto(tctx, (name != NULL), ret, done,
75 : "no memory for directory name\n");
76 :
77 66 : create.in.desired_access = SEC_RIGHTS_DIR_ALL;
78 66 : create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
79 66 : create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
80 66 : create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
81 : NTCREATEX_SHARE_ACCESS_WRITE |
82 : NTCREATEX_SHARE_ACCESS_DELETE;
83 66 : create.in.create_disposition = NTCREATEX_DISP_CREATE;
84 66 : create.in.fname = name;
85 :
86 66 : status = smb2_create(tree, tctx, &create);
87 66 : talloc_free(name);
88 :
89 66 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
90 : "CREATE directory failed\n");
91 :
92 66 : close.in.file.handle = create.out.file.handle;
93 66 : status = smb2_close(tree, &close);
94 66 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
95 : "CLOSE directory failed\n");
96 : }
97 :
98 1 : torture_comment(tctx, "Testing maximum number of open files\n");
99 :
100 65521 : for (i = 0; i < max_handles; i++) {
101 : char *name;
102 65520 : struct smb2_create create = { };
103 :
104 65520 : name = talloc_asprintf(tctx, "%s\\%zu\\%zu", dname, i / 1000, i);
105 65520 : torture_assert_goto(tctx, (name != NULL), ret, done,
106 : "no memory for file name\n");
107 :
108 65520 : create.in.desired_access = SEC_RIGHTS_DIR_ALL;
109 65520 : create.in.create_options = 0;
110 65520 : create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
111 65520 : create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
112 : NTCREATEX_SHARE_ACCESS_WRITE |
113 : NTCREATEX_SHARE_ACCESS_DELETE;
114 65520 : create.in.create_disposition = NTCREATEX_DISP_CREATE;
115 65520 : create.in.fname = name;
116 :
117 65520 : status = smb2_create(tree, tctx, &create);
118 65520 : if (!NT_STATUS_IS_OK(status)) {
119 0 : torture_comment(tctx, "create of %s failed: %s\n",
120 : name, nt_errstr(status));
121 0 : talloc_free(name);
122 0 : break;
123 : }
124 65520 : talloc_free(name);
125 :
126 65520 : handles[i] = create.out.file.handle;
127 : }
128 :
129 1 : maxfid = i;
130 1 : if (maxfid == max_handles) {
131 1 : torture_comment(tctx, "Reached test limit of %zu open files. "
132 : "Adjust to higher test with "
133 : "--option=torture:maxopenfiles=NNN\n", maxfid);
134 : }
135 :
136 1 : torture_comment(tctx, "Cleanup open files\n");
137 :
138 65521 : for (i = 0; i < maxfid; i++) {
139 65520 : status = smb2_util_close(tree, handles[i]);
140 65520 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
141 : "CLOSE failed\n");
142 : }
143 :
144 1 : done:
145 1 : smb2_deltree(tree, dname);
146 1 : talloc_free(handles);
147 :
148 1 : return ret;
149 : }
|