source: rtems/testsuites/fstests/fsimfsgeneric01/init.c @ 2f68778

4.115
Last change on this file since 2f68778 was 2f68778, checked in by Sebastian Huber <sebastian.huber@…>, on 12/16/13 at 12:44:13

Filesystem: Add readv/writev handlers

The readv() and writev() support was implemented in terms of multiple
calls to the read and write handlers. This imposes a problem on device
files which use an IO vector as single request entity. For example a
low-level network device (e.g. BPF(4)) may use an IO vector to create
one frame from multiple protocol layers each with its own IO vector
entry.

  • Property mode set to 100644
File size: 9.8 KB
Line 
1/*
2 * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Obere Lagerstr. 30
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.com/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include "tmacros.h"
20
21#include <sys/stat.h>
22#include <sys/ioctl.h>
23#include <sys/uio.h>
24#include <fcntl.h>
25#include <unistd.h>
26#include <errno.h>
27
28#include <rtems/imfs.h>
29#include <rtems/malloc.h>
30#include <rtems/libcsupport.h>
31
32typedef enum {
33  TEST_NEW,
34  TEST_INITIALIZED,
35  TEST_FSTAT_OPEN,
36  TEST_OPEN,
37  TEST_READ,
38  TEST_WRITE,
39  TEST_IOCTL,
40  TEST_LSEEK,
41  TEST_FTRUNCATE,
42  TEST_FSYNC,
43  TEST_FDATASYNC,
44  TEST_FCNTL,
45  TEST_READV,
46  TEST_WRITEV,
47  TEST_CLOSED,
48  TEST_FSTAT_UNLINK,
49  TEST_REMOVED,
50  TEST_DESTROYED
51} test_state;
52
53static int handler_open(
54  rtems_libio_t *iop,
55  const char *path,
56  int oflag,
57  mode_t mode
58)
59{
60  test_state *state = IMFS_generic_get_context_by_iop(iop);
61
62  rtems_test_assert(*state == TEST_FSTAT_OPEN);
63  *state = TEST_OPEN;
64
65  return 0;
66}
67
68static int handler_close(
69  rtems_libio_t *iop
70)
71{
72  test_state *state = IMFS_generic_get_context_by_iop(iop);
73
74  rtems_test_assert(*state == TEST_WRITEV);
75  *state = TEST_CLOSED;
76
77  return 0;
78}
79
80static ssize_t handler_read(
81  rtems_libio_t *iop,
82  void *buffer,
83  size_t count
84)
85{
86  test_state *state = IMFS_generic_get_context_by_iop(iop);
87
88  rtems_test_assert(*state == TEST_OPEN);
89  *state = TEST_READ;
90
91  return 0;
92}
93
94static ssize_t handler_write(
95  rtems_libio_t *iop,
96  const void *buffer,
97  size_t count
98)
99{
100  test_state *state = IMFS_generic_get_context_by_iop(iop);
101
102  rtems_test_assert(*state == TEST_READ);
103  *state = TEST_WRITE;
104
105  return 0;
106}
107
108static int handler_ioctl(
109  rtems_libio_t *iop,
110  uint32_t request,
111  void *buffer
112)
113{
114  test_state *state = IMFS_generic_get_context_by_iop(iop);
115
116  rtems_test_assert(*state == TEST_WRITE);
117  *state = TEST_IOCTL;
118
119  return 0;
120}
121
122static off_t handler_lseek(
123  rtems_libio_t *iop,
124  off_t length,
125  int whence
126)
127{
128  test_state *state = IMFS_generic_get_context_by_iop(iop);
129
130  rtems_test_assert(*state == TEST_IOCTL);
131  *state = TEST_LSEEK;
132
133  return 0;
134}
135
136static int handler_fstat(
137  const rtems_filesystem_location_info_t *loc,
138  struct stat *buf
139)
140{
141  test_state *state = IMFS_generic_get_context_by_location(loc);
142
143  switch (*state) {
144    case TEST_INITIALIZED:
145      *state = TEST_FSTAT_OPEN;
146      break;
147    case TEST_CLOSED:
148      *state = TEST_FSTAT_UNLINK;
149      break;
150    default:
151      rtems_test_assert(0);
152      break;
153  }
154
155  return rtems_filesystem_default_fstat(loc, buf);
156}
157
158static int handler_ftruncate(
159  rtems_libio_t *iop,
160  off_t length
161)
162{
163  test_state *state = IMFS_generic_get_context_by_iop(iop);
164
165  rtems_test_assert(*state == TEST_LSEEK);
166  *state = TEST_FTRUNCATE;
167
168  return 0;
169}
170
171static int handler_fsync(
172  rtems_libio_t *iop
173)
174{
175  test_state *state = IMFS_generic_get_context_by_iop(iop);
176
177  rtems_test_assert(*state == TEST_FTRUNCATE);
178  *state = TEST_FSYNC;
179
180  return 0;
181}
182
183static int handler_fdatasync(
184  rtems_libio_t *iop
185)
186{
187  test_state *state = IMFS_generic_get_context_by_iop(iop);
188
189  rtems_test_assert(*state == TEST_FSYNC);
190  *state = TEST_FDATASYNC;
191
192  return 0;
193}
194
195static int handler_fcntl(
196  rtems_libio_t *iop,
197  int cmd
198)
199{
200  test_state *state = IMFS_generic_get_context_by_iop(iop);
201
202  rtems_test_assert(*state == TEST_FDATASYNC);
203  *state = TEST_FCNTL;
204
205  return 0;
206}
207
208static ssize_t handler_readv(
209  rtems_libio_t *iop,
210  const struct iovec *iov,
211  int iovcnt,
212  ssize_t total
213)
214{
215  test_state *state = IMFS_generic_get_context_by_iop(iop);
216
217  rtems_test_assert(*state == TEST_FCNTL);
218  *state = TEST_READV;
219
220  return 0;
221}
222
223static ssize_t handler_writev(
224  rtems_libio_t *iop,
225  const struct iovec *iov,
226  int iovcnt,
227  ssize_t total
228)
229{
230  test_state *state = IMFS_generic_get_context_by_iop(iop);
231
232  rtems_test_assert(*state == TEST_READV);
233  *state = TEST_WRITEV;
234
235  return 0;
236}
237
238static const rtems_filesystem_file_handlers_r node_handlers = {
239  .open_h = handler_open,
240  .close_h = handler_close,
241  .read_h = handler_read,
242  .write_h = handler_write,
243  .ioctl_h = handler_ioctl,
244  .lseek_h = handler_lseek,
245  .fstat_h = handler_fstat,
246  .ftruncate_h = handler_ftruncate,
247  .fsync_h = handler_fsync,
248  .fdatasync_h = handler_fdatasync,
249  .fcntl_h = handler_fcntl,
250  .readv_h = handler_readv,
251  .writev_h = handler_writev
252};
253
254static IMFS_jnode_t *node_initialize(
255  IMFS_jnode_t *node,
256  const IMFS_types_union *info
257)
258{
259  test_state *state = NULL;
260
261  node = IMFS_node_initialize_generic(node, info);
262  state = IMFS_generic_get_context_by_node(node);
263
264  rtems_test_assert(*state == TEST_NEW);
265  *state = TEST_INITIALIZED;
266
267  return node;
268}
269
270static IMFS_jnode_t *node_remove(IMFS_jnode_t *node)
271{
272  test_state *state = IMFS_generic_get_context_by_node(node);
273
274  rtems_test_assert(*state == TEST_FSTAT_UNLINK);
275  *state = TEST_REMOVED;
276
277  return node;
278}
279
280static IMFS_jnode_t *node_destroy(IMFS_jnode_t *node)
281{
282  test_state *state = IMFS_generic_get_context_by_node(node);
283
284  rtems_test_assert(*state == TEST_REMOVED);
285  *state = TEST_DESTROYED;
286
287  return node;
288}
289
290static const IMFS_node_control node_control = {
291  .imfs_type = IMFS_GENERIC,
292  .handlers = &node_handlers,
293  .node_initialize = node_initialize,
294  .node_remove = node_remove,
295  .node_destroy = node_destroy
296};
297
298static void test_imfs_make_generic_node(void)
299{
300  test_state state = TEST_NEW;
301  int rv = 0;
302  int fd = 0;
303  const char *path = "generic";
304  char buf [1];
305  ssize_t n = 0;
306  off_t off = 0;
307  struct iovec iov = {
308    .iov_base = &buf [0],
309    .iov_len = (int) sizeof(buf)
310  };
311
312  rv = IMFS_make_generic_node(
313    path,
314    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
315    &node_control,
316    &state
317  );
318  rtems_test_assert(rv == 0);
319
320  fd = open(path, O_RDWR);
321  rtems_test_assert(fd >= 0);
322
323  n = read(fd, buf, sizeof(buf));
324  rtems_test_assert(n == 0);
325
326  n = write(fd, buf, sizeof(buf));
327  rtems_test_assert(n == 0);
328
329  rv = ioctl(fd, 0);
330  rtems_test_assert(rv == 0);
331
332  off = lseek(fd, off, SEEK_SET);
333  rtems_test_assert(off == 0);
334
335  rv = ftruncate(fd, 0);
336  rtems_test_assert(rv == 0);
337
338  rv = fsync(fd);
339  rtems_test_assert(rv == 0);
340
341  rv = fdatasync(fd);
342  rtems_test_assert(rv == 0);
343
344  rv = fcntl(fd, F_GETFD);
345  rtems_test_assert(rv >= 0);
346
347  rv = readv(fd, &iov, 1);
348  rtems_test_assert(rv == 0);
349
350  rv = writev(fd, &iov, 1);
351  rtems_test_assert(rv == 0);
352
353  rv = close(fd);
354  rtems_test_assert(rv == 0);
355
356  rv = unlink(path);
357  rtems_test_assert(rv == 0);
358
359  rtems_test_assert(state == TEST_DESTROYED);
360}
361
362static IMFS_jnode_t *node_initialize_error(
363  IMFS_jnode_t *node,
364  const IMFS_types_union *info
365)
366{
367  errno = EIO;
368
369  return NULL;
370}
371
372static IMFS_jnode_t *node_remove_inhibited(IMFS_jnode_t *node)
373{
374  rtems_test_assert(false);
375
376  return node;
377}
378
379static IMFS_jnode_t *node_destroy_inhibited(IMFS_jnode_t *node)
380{
381  rtems_test_assert(false);
382
383  return node;
384}
385
386static const IMFS_node_control node_invalid_control = {
387  .imfs_type = IMFS_DIRECTORY,
388  .handlers = &node_handlers,
389  .node_initialize = node_initialize_error,
390  .node_remove = node_remove_inhibited,
391  .node_destroy = node_destroy_inhibited
392};
393
394static const IMFS_node_control node_initialization_error_control = {
395  .imfs_type = IMFS_GENERIC,
396  .handlers = &node_handlers,
397  .node_initialize = node_initialize_error,
398  .node_remove = node_remove_inhibited,
399  .node_destroy = node_destroy_inhibited
400};
401
402static void test_imfs_make_generic_node_errors(void)
403{
404  int rv = 0;
405  const char *path = "generic";
406  rtems_chain_control *chain = &rtems_filesystem_mount_table;
407  rtems_filesystem_mount_table_entry_t *mt_entry =
408    (rtems_filesystem_mount_table_entry_t *) rtems_chain_first(chain);
409  const char *type = mt_entry->type;
410  void *opaque = NULL;
411  rtems_resource_snapshot before;
412
413  rtems_resource_snapshot_take(&before);
414
415  errno = 0;
416  rv = IMFS_make_generic_node(
417    path,
418    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
419    &node_invalid_control,
420    NULL
421  );
422  rtems_test_assert(rv == -1);
423  rtems_test_assert(errno == EINVAL);
424  rtems_test_assert(rtems_resource_snapshot_check(&before));
425
426  errno = 0;
427  rv = IMFS_make_generic_node(
428    path,
429    S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO,
430    &node_control,
431    NULL
432  );
433  rtems_test_assert(rv == -1);
434  rtems_test_assert(errno == EINVAL);
435  rtems_test_assert(rtems_resource_snapshot_check(&before));
436
437  errno = 0;
438  mt_entry->type = "XXX";
439  rv = IMFS_make_generic_node(
440    path,
441    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
442    &node_control,
443    NULL
444  );
445  mt_entry->type = type;
446  rtems_test_assert(rv == -1);
447  rtems_test_assert(errno == ENOTSUP);
448  rtems_test_assert(rtems_resource_snapshot_check(&before));
449
450  errno = 0;
451  opaque = rtems_heap_greedy_allocate(NULL, 0);
452  rv = IMFS_make_generic_node(
453    path,
454    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
455    &node_control,
456    NULL
457  );
458  rtems_heap_greedy_free(opaque);
459  rtems_test_assert(rv == -1);
460  rtems_test_assert(errno == ENOMEM);
461  rtems_test_assert(rtems_resource_snapshot_check(&before));
462
463  errno = 0;
464  rv = IMFS_make_generic_node(
465    path,
466    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
467    &node_initialization_error_control,
468    NULL
469  );
470  rtems_test_assert(rv == -1);
471  rtems_test_assert(errno == EIO);
472  rtems_test_assert(rtems_resource_snapshot_check(&before));
473}
474
475static void Init(rtems_task_argument arg)
476{
477  printf("\n\n*** TEST FSIMFSGENERIC 1 ***\n");
478
479  test_imfs_make_generic_node();
480  test_imfs_make_generic_node_errors();
481
482  printf("*** END OF TEST FSIMFSGENERIC 1 ***\n");
483
484  rtems_test_exit(0);
485}
486
487#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
488#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
489
490#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4
491
492#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
493
494#define CONFIGURE_MAXIMUM_TASKS 1
495
496#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
497
498#define CONFIGURE_INIT
499
500#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.