Motr  M0
lut_main.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include <sys/ioctl.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h> /* exit */
28 #include <unistd.h> /* getuid, close, read, write, lseek */
29 
30 #include "lib/uuid.h" /* m0_kmod_uuid_file_set */
31 #include "motr/init.h" /* m0_init */
32 #include "module/instance.h" /* m0 */
33 #include "lib/arith.h" /* m0_is_po2 */
34 #include "lib/errno.h"
35 #include "lib/memory.h" /* m0_alloc_aligned */
36 
37 #include "net/lnet/lnet_core_types.h" /* M0_NET_LNET_NIDSTR_SIZE */
38 #include "net/lnet/lnet_ioctl.h" /* M0_LNET_DEV */
39 #include "net/lnet/ut/lnet_drv_ut.h" /* UT_PROC_NAME */
40 
41 const char lnet_xprt_dev[] = "/dev/" M0_LNET_DEV;
42 const char lnet_ut_proc[] = "/proc/" UT_PROC_NAME;
43 
44 enum {
48  UT_TM_UPVT = 0xdeadbeaf,
49 };
50 
56 #define LUT_PO2_SHIFT(n) \
57  (((n) <= 8) ? 3 : ((n) <= 16) ? 4 : ((n) <= 32) ? 5 : \
58  ((n) <= 64) ? 6 : ((n) <= 128) ? 7 : ((n) <= 256) ? 8 : \
59  ((n) <= 512) ? 9 : ((n) / 0))
60 #define LUT_ALLOC_PTR(ptr) \
61  ((ptr) = lut_mem_alloc(sizeof ((ptr)[0]), \
62  LUT_PO2_SHIFT(sizeof ((ptr)[0]))))
63 #define LUT_FREE_PTR(ptr) \
64  lut_mem_free((ptr), sizeof ((ptr)[0]), LUT_PO2_SHIFT(sizeof ((ptr)[0])))
65 
66 static void *lut_mem_alloc(size_t size, unsigned shift)
67 {
68  return m0_alloc_aligned(size, shift);
69 }
70 
71 static void lut_mem_free(void *data, size_t size, unsigned shift)
72 {
73  m0_free_aligned(data, size, shift);
74 }
75 
76 int test_dev_exists(void)
77 {
78  struct stat st;
79  int rc = stat(lnet_xprt_dev, &st);
80 
81  if (rc == 0) {
82  if (!S_ISCHR(st.st_mode))
83  rc = -1;
84  if (st.st_uid != 0)
85  rc = -1;
86  if ((st.st_mode & S_IRWXO) != 0)
87  rc = -1;
88  }
89  return rc;
90 }
91 
92 int test_open_close(void)
93 {
94  int f;
95  int rc;
96  int uid = getuid();
97  int gid = getgid();
98 
99  f = open(lnet_xprt_dev, O_RDWR|O_CLOEXEC);
100  if (f < 0) {
101  perror(lnet_xprt_dev);
102  return 1;
103  }
104  close(f);
105 
106  /* non-privileged user fails */
107  rc = setegid(FAIL_UID_GID);
108  M0_ASSERT(rc == 0);
109  rc = seteuid(FAIL_UID_GID);
110  M0_ASSERT(rc == 0);
111  f = open(lnet_xprt_dev, O_RDWR|O_CLOEXEC);
112  if (f >= 0) {
113  close(f);
114  rc = -1;
115  }
116  uid = seteuid(uid);
117  M0_ASSERT(uid == 0);
118  gid = setegid(gid);
119  M0_ASSERT(gid == 0);
120  return rc;
121 }
122 
124 {
125  int f;
126  int rc;
127  bool failed = false;
128  char buf[1];
129 
130  f = open(lnet_xprt_dev, O_RDWR|O_CLOEXEC);
131  if (f < 0) {
132  perror(lnet_xprt_dev);
133  return 1;
134  }
135 
136  rc = read(f, buf, sizeof buf);
137  if (rc >= 0 || errno != EINVAL)
138  failed = true;
139  rc = write(f, buf, sizeof buf);
140  if (rc >= 0 || errno != EINVAL)
141  failed = true;
142  close(f);
143  return failed ? 1 : 0;
144 }
145 
146 #define UT_LNET_INVALID \
147  _IOWR(M0_LNET_IOC_MAGIC, (M0_LNET_IOC_MAX_NR + 1), \
148  struct m0_lnet_dev_dom_init_params)
149 
151 {
153  int f;
154  int rc;
155  bool failed = false;
156 
157  M0_SET0(&p);
158 
159  f = open(lnet_xprt_dev, O_RDWR|O_CLOEXEC);
160  if (f < 0) {
161  perror(lnet_xprt_dev);
162  return 1;
163  }
164 
165  /* unsupported ioctl, detected and failed */
166  rc = ioctl(f, UT_LNET_INVALID, &p);
167  if (rc >= 0 || errno != ENOTTY)
168  failed = true;
169 
170  /* dom_init, but NULL arg, detected and failed */
171  rc = ioctl(f, M0_LNET_DOM_INIT, NULL);
172  if (rc >= 0 || errno != EFAULT)
173  failed = true;
174 
175  /* dom_init, but NULL payload, detected and failed */
176  rc = ioctl(f, M0_LNET_DOM_INIT, &p);
177  if (rc >= 0 || errno != EFAULT)
178  failed = true;
179 
180  close(f);
181  return failed ? 1 : 0;
182 }
183 
184 int test_dom_init(void)
185 {
187  struct nlx_core_domain *dom;
188  int f;
189  int rc;
190 
191  M0_SET0(&p);
193  M0_ASSERT(dom != NULL);
194  p.ddi_cd = dom;
195 
196  f = open(lnet_xprt_dev, O_RDWR|O_CLOEXEC);
197  if (f < 0) {
198  perror(lnet_xprt_dev);
199  return 1;
200  }
201 
202  rc = ioctl(f, M0_LNET_DOM_INIT, &p);
203  if (rc == 0) {
204  if (p.ddi_max_buffer_size < 2 ||
205  !m0_is_po2(p.ddi_max_buffer_size) ||
206  p.ddi_max_buffer_segment_size < 2 ||
207  !m0_is_po2(p.ddi_max_buffer_segment_size) ||
208  p.ddi_max_buffer_segments < 2 ||
209  !m0_is_po2(p.ddi_max_buffer_segments))
210  rc = 1;
211  }
212 
213  close(f);
214  LUT_FREE_PTR(dom);
215  return rc;
216 }
217 
218 int test_tms(bool force_cleanup)
219 {
220  struct m0_lnet_dev_dom_init_params pd;
221  struct nlx_core_domain *dom;
222  struct nlx_core_transfer_mc *tm[MULTI_TM_NR];
223  struct m0_lnet_dev_tm_start_params tsp;
224  struct m0_lnet_dev_tm_stop_params tpp;
225  int f;
226  int i;
227  int rc;
228 
229  M0_SET0(&pd);
231  M0_ASSERT(dom != NULL);
232  pd.ddi_cd = dom;
233 
234  for (i = 0; i < MULTI_TM_NR; ++i) {
235  LUT_ALLOC_PTR(tm[i]);
236  M0_ASSERT(tm[i] != NULL);
237  }
238 
239  f = open(lnet_xprt_dev, O_RDWR|O_CLOEXEC);
240  if (f < 0) {
241  rc = 1;
242  goto out;
243  }
244 
245  rc = ioctl(f, M0_LNET_DOM_INIT, &pd);
246  if (rc != 0)
247  goto out;
248 
249  for (i = 0; i < MULTI_TM_NR; ++i) {
250  tm[i]->ctm_upvt = (void *) UT_TM_UPVT;
251 
252  tsp.dts_ctm = tm[i];
253  rc = ioctl(f, M0_LNET_TM_START, &tsp);
254  if (rc != 0)
255  goto out;
256  if (tm[i]->ctm_upvt != (void *) UT_TM_UPVT) {
257  rc = 1;
258  goto out;
259  }
260  }
261 
262  if (!force_cleanup)
263  for (i = 0; i < MULTI_TM_NR; ++i) {
264  tpp.dts_ktm = tm[i]->ctm_kpvt;
265  rc = ioctl(f, M0_LNET_TM_STOP, &tpp);
266  if (rc != 0)
267  break;
268  }
269  out:
270  for (i = 0; i < MULTI_TM_NR; ++i)
271  LUT_FREE_PTR(tm[i]);
272  if (f >= 0)
273  close(f);
274  LUT_FREE_PTR(dom);
275  return rc;
276 }
277 
278 int test_duptm(void)
279 {
280  struct m0_lnet_dev_dom_init_params pd;
281  struct nlx_core_domain *dom;
282  struct nlx_core_transfer_mc *tm;
283  struct m0_lnet_dev_tm_start_params tsp;
284  struct m0_lnet_dev_tm_stop_params tpp;
285  int f;
286  int rc;
287 
288  M0_SET0(&pd);
290  M0_ASSERT(dom != NULL);
291  pd.ddi_cd = dom;
292 
293  LUT_ALLOC_PTR(tm);
294  M0_ASSERT(tm != NULL);
295 
296  f = open(lnet_xprt_dev, O_RDWR|O_CLOEXEC);
297  if (f < 0) {
298  rc = 1;
299  goto out;
300  }
301 
302  rc = ioctl(f, M0_LNET_DOM_INIT, &pd);
303  if (rc != 0)
304  goto out;
305 
306  tm->ctm_upvt = (void *) UT_TM_UPVT;
307  tsp.dts_ctm = tm;
308  rc = ioctl(f, M0_LNET_TM_START, &tsp);
309  if (rc != 0)
310  goto out;
311  if (tm->ctm_upvt != (void *) UT_TM_UPVT) {
312  rc = 1;
313  goto out;
314  }
315 
316  /* duplicate tm */
317  rc = ioctl(f, M0_LNET_TM_START, &tsp);
318  if (rc == 0 || errno != EBADR) {
319  rc = 1;
320  goto out;
321  } else
322  rc = 0;
323  tpp.dts_ktm = tm->ctm_kpvt;
324  rc = ioctl(f, M0_LNET_TM_STOP, &tpp);
325  out:
326  LUT_FREE_PTR(tm);
327  close(f);
328  LUT_FREE_PTR(dom);
329  return rc;
330 }
331 
332 int main(int argc, char *argv[])
333 {
334  static struct m0 instance;
335  int procf;
336  int i;
337  int rc;
338  char cmd[1];
339  off_t off = 0;
341 
342  m0_kmod_uuid_file_set("/sys/module/m0ut/parameters/node_uuid");
343 
344  rc = m0_init(&instance);
345  M0_ASSERT(rc == 0);
346 
348  for (i = 0; i < MAX_PROC_TRIES; ++i) {
349  procf = open(lnet_ut_proc, O_RDWR);
350  if (procf >= 0)
351  break;
352  M0_ASSERT(errno == ENOENT);
353  m0_nanosleep(delay, 0);
354  }
355  if (procf < 0) {
356  fprintf(stderr,
357  "%s: kernel UT did not create %s after %d sec\n",
358  __FILE__, lnet_ut_proc,
360  m0_fini();
361  exit(1);
362  }
363 
364  cmd[0] = UT_USER_READY;
365  rc = write(procf, cmd, 1);
366  M0_ASSERT(rc == 1);
367  while (1) {
368  off = lseek(procf, off, SEEK_SET);
369  if (off != 0)
370  break;
371  rc = read(procf, cmd, 1);
372  if (rc <= 0) {
373  fprintf(stderr, "%s: failed to read from procfs lnet UT"
374  " file '%s', rc = %d\n",
375  __FILE__, strerror(errno), rc);
376  break;
377  }
378  switch (*cmd) {
379  case UT_TEST_DEV:
380  rc = test_dev_exists();
381  break;
382  case UT_TEST_OPEN:
383  rc = test_open_close();
384  break;
385  case UT_TEST_RDWR:
386  rc = test_read_write();
387  break;
388  case UT_TEST_BADIOCTL:
390  break;
391  case UT_TEST_DOMINIT:
392  rc = test_dom_init();
393  break;
394  case UT_TEST_TMS:
395  rc = test_tms(false);
396  break;
397  case UT_TEST_DUPTM:
398  rc = test_duptm();
399  break;
400  case UT_TEST_TMCLEANUP:
401  rc = test_tms(true);
402  break;
403  case UT_TEST_DONE:
404  goto done;
405  default:
406  printf("**** UNKNOWN TEST %d\n", (int) *cmd);
407  break;
408  }
409  cmd[0] = (rc == 0) ? UT_USER_SUCCESS : UT_USER_FAIL;
410  rc = write(procf, cmd, 1);
411  M0_ASSERT(rc == 1);
412  }
413 done:
414  close(procf);
415  m0_fini();
416  return 0;
417 }
418 
419 /*
420  * Local variables:
421  * c-indentation-style: "K&R"
422  * c-basic-offset: 8
423  * tab-width: 8
424  * fill-column: 80
425  * scroll-step: 1
426  * End:
427  */
static struct m0_addb2_philter p
Definition: consumer.c:40
M0_INTERNAL int struct dentry struct kstat * stat
Definition: dir.c:1433
#define NULL
Definition: misc.h:38
void m0_fini(void)
Definition: init.c:318
int test_duptm(void)
Definition: lut_main.c:278
static FILE * f
Definition: adieu.c:79
uint64_t m0_time_t
Definition: time.h:37
#define M0_LNET_TM_STOP
Definition: lnet_ioctl.h:203
static bool m0_is_po2(uint64_t val)
Definition: arith.h:153
static int delay
Definition: dump.c:174
struct m0_bufvec data
Definition: di.c:40
M0_INTERNAL void m0_free_aligned(void *data, size_t size, unsigned shift)
Definition: memory.c:192
int test_read_write(void)
Definition: lut_main.c:123
#define LUT_FREE_PTR(ptr)
Definition: lut_main.c:63
int m0_init(struct m0 *instance)
Definition: init.c:310
#define M0_SET0(obj)
Definition: misc.h:64
m0_time_t m0_time(uint64_t secs, long ns)
Definition: time.c:41
Definition: sock.c:887
int test_invalid_ioctls(void)
Definition: lut_main.c:150
int main(int argc, char *argv[])
Definition: lut_main.c:332
int i
Definition: dir.c:1033
static void lut_mem_free(void *data, size_t size, unsigned shift)
Definition: lut_main.c:71
#define LUT_ALLOC_PTR(ptr)
Definition: lut_main.c:60
#define M0_ASSERT(cond)
int test_dev_exists(void)
Definition: lut_main.c:76
#define UT_PROC_NAME
Definition: lnet_drv_ut.h:50
struct nlx_core_transfer_mc * dts_ctm
Definition: lnet_ioctl.h:140
static struct m0_stob_domain * dom
Definition: storage.c:38
const char lnet_ut_proc[]
Definition: lut_main.c:42
Definition: instance.h:80
static void * lut_mem_alloc(size_t size, unsigned shift)
Definition: lut_main.c:66
#define M0_LNET_DEV
Definition: lnet_ioctl.h:164
int test_dom_init(void)
Definition: lut_main.c:184
#define M0_LNET_TM_START
Definition: lnet_ioctl.h:201
int test_tms(bool force_cleanup)
Definition: lut_main.c:218
int test_open_close(void)
Definition: lut_main.c:92
m0_bcount_t size
Definition: di.c:39
static struct m0 instance
Definition: main.c:78
#define M0_LNET_DOM_INIT
Definition: lnet_ioctl.h:170
void m0_kmod_uuid_file_set(const char *path)
Definition: uuuid.c:59
static unsigned done
Definition: storage.c:91
struct nlx_core_domain * ddi_cd
Definition: lnet_ioctl.h:41
const char lnet_xprt_dev[]
Definition: lut_main.c:41
#define out(...)
Definition: gen.c:41
M0_INTERNAL void * m0_alloc_aligned(size_t size, unsigned shift)
Definition: memory.c:168
int32_t rc
Definition: trigger_fop.h:47
#define UT_LNET_INVALID
Definition: lut_main.c:146
int m0_nanosleep(const m0_time_t req, m0_time_t *rem)
Definition: ktime.c:73