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 5 : bool torture_smb2_maxfid(struct torture_context *tctx)
30 : {
31 5 : bool ret = true;
32 0 : NTSTATUS status;
33 5 : struct smb2_tree *tree = NULL;
34 5 : const char *dname = "smb2_maxfid";
35 0 : size_t i, maxfid;
36 5 : struct smb2_handle *handles, dir_handle = { };
37 0 : 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 5 : max_handles = torture_setting_int(tctx, "maxopenfiles", 65520);
48 :
49 5 : if (!torture_smb2_connection(tctx, &tree)) {
50 0 : return false;
51 : }
52 :
53 5 : handles = talloc_array(tctx, struct smb2_handle, max_handles);
54 5 : if (handles == 0) {
55 0 : torture_fail(tctx, "Could not allocate handles array.\n");
56 : return false;
57 : }
58 :
59 5 : smb2_deltree(tree, dname);
60 :
61 5 : status = torture_smb2_testdir(tree, dname, &dir_handle);
62 5 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
63 : "torture_smb2_testdir failed");
64 5 : smb2_util_close(tree, dir_handle);
65 :
66 5 : torture_comment(tctx, "Creating subdirectories\n");
67 :
68 335 : for (i = 0; i < max_handles; i += 1000) {
69 0 : char *name;
70 330 : struct smb2_create create = { };
71 330 : struct smb2_close close = { };
72 :
73 330 : name = talloc_asprintf(tctx, "%s\\%zu", dname, i / 1000);
74 330 : torture_assert_goto(tctx, (name != NULL), ret, done,
75 : "no memory for directory name\n");
76 :
77 330 : create.in.desired_access = SEC_RIGHTS_DIR_ALL;
78 330 : create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
79 330 : create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
80 330 : create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
81 : NTCREATEX_SHARE_ACCESS_WRITE |
82 : NTCREATEX_SHARE_ACCESS_DELETE;
83 330 : create.in.create_disposition = NTCREATEX_DISP_CREATE;
84 330 : create.in.fname = name;
85 :
86 330 : status = smb2_create(tree, tctx, &create);
87 330 : talloc_free(name);
88 :
89 330 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
90 : "CREATE directory failed\n");
91 :
92 330 : close.in.file.handle = create.out.file.handle;
93 330 : status = smb2_close(tree, &close);
94 330 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
95 : "CLOSE directory failed\n");
96 : }
97 :
98 5 : torture_comment(tctx, "Testing maximum number of open files\n");
99 :
100 131155 : for (i = 0; i < max_handles; i++) {
101 0 : char *name;
102 131154 : struct smb2_create create = { };
103 :
104 131154 : name = talloc_asprintf(tctx, "%s\\%zu\\%zu", dname, i / 1000, i);
105 131154 : torture_assert_goto(tctx, (name != NULL), ret, done,
106 : "no memory for file name\n");
107 :
108 131154 : create.in.desired_access = SEC_RIGHTS_DIR_ALL;
109 131154 : create.in.create_options = 0;
110 131154 : create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
111 131154 : create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
112 : NTCREATEX_SHARE_ACCESS_WRITE |
113 : NTCREATEX_SHARE_ACCESS_DELETE;
114 131154 : create.in.create_disposition = NTCREATEX_DISP_CREATE;
115 131154 : create.in.fname = name;
116 :
117 131154 : status = smb2_create(tree, tctx, &create);
118 131154 : if (!NT_STATUS_IS_OK(status)) {
119 4 : torture_comment(tctx, "create of %s failed: %s\n",
120 : name, nt_errstr(status));
121 4 : talloc_free(name);
122 4 : break;
123 : }
124 131150 : talloc_free(name);
125 :
126 131150 : handles[i] = create.out.file.handle;
127 : }
128 :
129 5 : maxfid = i;
130 5 : 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 5 : torture_comment(tctx, "Cleanup open files\n");
137 :
138 131155 : for (i = 0; i < maxfid; i++) {
139 131150 : status = smb2_util_close(tree, handles[i]);
140 131150 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
141 : "CLOSE failed\n");
142 : }
143 :
144 5 : done:
145 5 : smb2_deltree(tree, dname);
146 5 : talloc_free(handles);
147 :
148 5 : return ret;
149 : }
|