1 /*****************************************************************************\
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://github.com/behlendorf/spl/>.
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * You should have received a copy of the GNU General Public License along
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting LAyer Tests (SPLAT) Vnode Tests.
25 \*****************************************************************************/
27 #include "splat-internal.h"
28 #include <linux/rcupdate.h>
30 #define SPLAT_VNODE_NAME "vnode"
31 #define SPLAT_VNODE_DESC "Kernel Vnode Tests"
33 #define SPLAT_VNODE_TEST1_ID 0x0901
34 #define SPLAT_VNODE_TEST1_NAME "vn_open"
35 #define SPLAT_VNODE_TEST1_DESC "Vn_open Test"
37 #define SPLAT_VNODE_TEST2_ID 0x0902
38 #define SPLAT_VNODE_TEST2_NAME "vn_openat"
39 #define SPLAT_VNODE_TEST2_DESC "Vn_openat Test"
41 #define SPLAT_VNODE_TEST3_ID 0x0903
42 #define SPLAT_VNODE_TEST3_NAME "vn_rdwr"
43 #define SPLAT_VNODE_TEST3_DESC "Vn_rdwrt Test"
45 #define SPLAT_VNODE_TEST4_ID 0x0904
46 #define SPLAT_VNODE_TEST4_NAME "vn_rename"
47 #define SPLAT_VNODE_TEST4_DESC "Vn_rename Test"
49 #define SPLAT_VNODE_TEST5_ID 0x0905
50 #define SPLAT_VNODE_TEST5_NAME "vn_getattr"
51 #define SPLAT_VNODE_TEST5_DESC "Vn_getattr Test"
53 #define SPLAT_VNODE_TEST6_ID 0x0906
54 #define SPLAT_VNODE_TEST6_NAME "vn_sync"
55 #define SPLAT_VNODE_TEST6_DESC "Vn_sync Test"
57 #define SPLAT_VNODE_TEST7_ID 0x0907
58 #define SPLAT_VNODE_TEST7_NAME "vn_getf"
59 #define SPLAT_VNODE_TEST7_DESC "vn_getf/vn_releasef Test"
61 #define SPLAT_VNODE_TEST_FILE "/etc/fstab"
62 #define SPLAT_VNODE_TEST_FILE_AT "etc/fstab"
63 #define SPLAT_VNODE_TEST_FILE_RW "/tmp/spl.vnode.tmp"
64 #define SPLAT_VNODE_TEST_FILE_RW1 "/tmp/spl.vnode.tmp.1"
65 #define SPLAT_VNODE_TEST_FILE_RW2 "/tmp/spl.vnode.tmp.2"
68 splat_vnode_user_cmd(struct file
*file
, void *arg
,
69 char *name
, char *cmd
)
71 char sh_path
[] = "/bin/sh";
72 char *argv
[] = { sh_path
,
76 char *envp
[] = { "HOME=/",
78 "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
82 rc
= call_usermodehelper(sh_path
, argv
, envp
, 1);
84 splat_vprint(file
, name
,
85 "Failed command: %s %s %s (%d)\n",
86 argv
[0], argv
[1], cmd
, rc
);
94 splat_vnode_unlink_all(struct file
*file
, void *arg
, char *name
)
96 char *cmds
[] = { "rm -f " SPLAT_VNODE_TEST_FILE_RW
,
97 "rm -f " SPLAT_VNODE_TEST_FILE_RW1
,
98 "rm -f " SPLAT_VNODE_TEST_FILE_RW2
,
102 while (cmds
[i
] != NULL
) {
103 if ((rc
= splat_vnode_user_cmd(file
, arg
, name
, cmds
[i
])))
113 splat_vnode_test1(struct file
*file
, void *arg
)
118 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE
, UIO_SYSSPACE
,
119 FREAD
, 0644, &vp
, 0, 0))) {
120 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
,
121 "Failed to vn_open test file: %s (%d)\n",
122 SPLAT_VNODE_TEST_FILE
, rc
);
126 rc
= VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
130 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
,
131 "Failed to vn_close test file: %s (%d)\n",
132 SPLAT_VNODE_TEST_FILE
, rc
);
136 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
, "Successfully vn_open'ed "
137 "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE
);
140 } /* splat_vnode_test1() */
143 splat_vnode_test2(struct file
*file
, void *arg
)
148 if ((rc
= vn_openat(SPLAT_VNODE_TEST_FILE_AT
, UIO_SYSSPACE
,
149 FREAD
, 0644, &vp
, 0, 0, rootdir
, 0))) {
150 splat_vprint(file
, SPLAT_VNODE_TEST2_NAME
,
151 "Failed to vn_openat test file: %s (%d)\n",
152 SPLAT_VNODE_TEST_FILE
, rc
);
156 rc
= VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
160 splat_vprint(file
, SPLAT_VNODE_TEST2_NAME
,
161 "Failed to vn_close test file: %s (%d)\n",
162 SPLAT_VNODE_TEST_FILE
, rc
);
166 splat_vprint(file
, SPLAT_VNODE_TEST2_NAME
, "Successfully vn_openat'ed "
167 "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE
);
170 } /* splat_vnode_test2() */
173 splat_vnode_test3(struct file
*file
, void *arg
)
176 char buf1
[32] = "SPL VNode Interface Test File\n";
180 if ((rc
= splat_vnode_unlink_all(file
, arg
, SPLAT_VNODE_TEST3_NAME
)))
183 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
,
184 FWRITE
| FREAD
| FCREAT
| FEXCL
,
186 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
187 "Failed to vn_open test file: %s (%d)\n",
188 SPLAT_VNODE_TEST_FILE_RW
, rc
);
192 rc
= vn_rdwr(UIO_WRITE
, vp
, buf1
, strlen(buf1
), 0,
193 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
195 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
196 "Failed vn_rdwr write of test file: %s (%d)\n",
197 SPLAT_VNODE_TEST_FILE_RW
, rc
);
201 rc
= vn_rdwr(UIO_READ
, vp
, buf2
, strlen(buf1
), 0,
202 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
204 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
205 "Failed vn_rdwr read of test file: %s (%d)\n",
206 SPLAT_VNODE_TEST_FILE_RW
, rc
);
210 if (strncmp(buf1
, buf2
, strlen(buf1
))) {
212 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
213 "Failed strncmp data written does not match "
214 "data read\nWrote: %sRead: %s\n", buf1
, buf2
);
219 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Wrote: %s", buf1
);
220 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Read: %s", buf2
);
221 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Successfully wrote and "
222 "read expected data pattern to test file: %s\n",
223 SPLAT_VNODE_TEST_FILE_RW
);
226 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
228 vn_remove(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
, RMFILE
);
231 } /* splat_vnode_test3() */
234 splat_vnode_test4(struct file
*file
, void *arg
)
237 char buf1
[32] = "SPL VNode Interface Test File\n";
241 if ((rc
= splat_vnode_unlink_all(file
, arg
, SPLAT_VNODE_TEST4_NAME
)))
244 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW1
, UIO_SYSSPACE
,
245 FWRITE
| FREAD
| FCREAT
| FEXCL
, 0644, &vp
, 0, 0))) {
246 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
247 "Failed to vn_open test file: %s (%d)\n",
248 SPLAT_VNODE_TEST_FILE_RW1
, rc
);
252 rc
= vn_rdwr(UIO_WRITE
, vp
, buf1
, strlen(buf1
), 0,
253 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
255 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
256 "Failed vn_rdwr write of test file: %s (%d)\n",
257 SPLAT_VNODE_TEST_FILE_RW1
, rc
);
261 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
264 rc
= vn_rename(SPLAT_VNODE_TEST_FILE_RW1
,SPLAT_VNODE_TEST_FILE_RW2
,0);
266 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Failed vn_rename "
268 SPLAT_VNODE_TEST_FILE_RW1
,
269 SPLAT_VNODE_TEST_FILE_RW2
, rc
);
273 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW2
, UIO_SYSSPACE
,
274 FREAD
| FEXCL
, 0644, &vp
, 0, 0))) {
275 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
276 "Failed to vn_open test file: %s (%d)\n",
277 SPLAT_VNODE_TEST_FILE_RW2
, rc
);
281 rc
= vn_rdwr(UIO_READ
, vp
, buf2
, strlen(buf1
), 0,
282 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
284 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
285 "Failed vn_rdwr read of test file: %s (%d)\n",
286 SPLAT_VNODE_TEST_FILE_RW2
, rc
);
290 if (strncmp(buf1
, buf2
, strlen(buf1
))) {
292 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
293 "Failed strncmp data written does not match "
294 "data read\nWrote: %sRead: %s\n", buf1
, buf2
);
299 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Wrote to %s: %s",
300 SPLAT_VNODE_TEST_FILE_RW1
, buf1
);
301 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Read from %s: %s",
302 SPLAT_VNODE_TEST_FILE_RW2
, buf2
);
303 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Successfully renamed "
304 "test file %s -> %s and verified data pattern\n",
305 SPLAT_VNODE_TEST_FILE_RW1
, SPLAT_VNODE_TEST_FILE_RW2
);
307 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
310 vn_remove(SPLAT_VNODE_TEST_FILE_RW1
, UIO_SYSSPACE
, RMFILE
);
311 vn_remove(SPLAT_VNODE_TEST_FILE_RW2
, UIO_SYSSPACE
, RMFILE
);
314 } /* splat_vnode_test4() */
317 splat_vnode_test5(struct file
*file
, void *arg
)
323 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE
, UIO_SYSSPACE
,
324 FREAD
, 0644, &vp
, 0, 0))) {
325 splat_vprint(file
, SPLAT_VNODE_TEST5_NAME
,
326 "Failed to vn_open test file: %s (%d)\n",
327 SPLAT_VNODE_TEST_FILE
, rc
);
331 rc
= VOP_GETATTR(vp
, &vap
, 0, 0, NULL
);
333 splat_vprint(file
, SPLAT_VNODE_TEST5_NAME
,
334 "Failed to vn_getattr test file: %s (%d)\n",
335 SPLAT_VNODE_TEST_FILE
, rc
);
339 if (vap
.va_type
!= VREG
) {
341 splat_vprint(file
, SPLAT_VNODE_TEST5_NAME
,
342 "Failed expected regular file type "
343 "(%d != VREG): %s (%d)\n", vap
.va_type
,
344 SPLAT_VNODE_TEST_FILE
, rc
);
348 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
, "Successfully "
349 "vn_getattr'ed test file: %s\n", SPLAT_VNODE_TEST_FILE
);
352 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
356 } /* splat_vnode_test5() */
359 splat_vnode_test6(struct file
*file
, void *arg
)
362 char buf
[32] = "SPL VNode Interface Test File\n";
365 if ((rc
= splat_vnode_unlink_all(file
, arg
, SPLAT_VNODE_TEST6_NAME
)))
368 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
,
369 FWRITE
| FCREAT
| FEXCL
, 0644, &vp
, 0, 0))) {
370 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
,
371 "Failed to vn_open test file: %s (%d)\n",
372 SPLAT_VNODE_TEST_FILE_RW
, rc
);
376 rc
= vn_rdwr(UIO_WRITE
, vp
, buf
, strlen(buf
), 0,
377 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
379 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
,
380 "Failed vn_rdwr write of test file: %s (%d)\n",
381 SPLAT_VNODE_TEST_FILE_RW
, rc
);
385 rc
= vn_fsync(vp
, 0, 0, 0);
387 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
,
388 "Failed vn_fsync of test file: %s (%d)\n",
389 SPLAT_VNODE_TEST_FILE_RW
, rc
);
394 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
, "Successfully "
395 "fsync'ed test file %s\n", SPLAT_VNODE_TEST_FILE_RW
);
397 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
399 vn_remove(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
, RMFILE
);
402 } /* splat_vnode_test6() */
404 /* Basically a slightly modified version of sys_close() */
409 struct files_struct
*files
= current
->files
;
410 #ifdef HAVE_FILES_FDTABLE
413 spin_lock(&files
->file_lock
);
414 fdt
= files_fdtable(files
);
416 if (fd
>= fdt
->max_fds
)
423 rcu_assign_pointer(fdt
->fd
[fd
], NULL
);
424 FD_CLR(fd
, fdt
->close_on_exec
);
426 spin_lock(&files
->file_lock
);
427 if (fd
>= files
->max_fds
)
434 files
->fd
[fd
] = NULL
;
435 FD_CLR(fd
, files
->close_on_exec
);
437 /* Dropping the lock here exposes a minor race but it allows me
438 * to use the existing kernel interfaces for this, and for a test
439 * case I think that's reasonable. */
440 spin_unlock(&files
->file_lock
);
445 spin_unlock(&files
->file_lock
);
447 } /* fd_uninstall() */
450 splat_vnode_test7(struct file
*file
, void *arg
)
452 char buf1
[32] = "SPL VNode Interface Test File\n";
458 if ((rc
= splat_vnode_unlink_all(file
, arg
, SPLAT_VNODE_TEST7_NAME
)))
461 /* Prep work needed to test getf/releasef */
462 fd
= get_unused_fd();
464 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
465 "Failed to get unused fd (%d)\n", fd
);
469 lfp
= filp_open(SPLAT_VNODE_TEST_FILE_RW
, O_RDWR
|O_CREAT
|O_EXCL
, 0644);
473 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
474 "Failed to filp_open: %s (%d)\n",
475 SPLAT_VNODE_TEST_FILE_RW
, rc
);
479 /* Pair up the new fd and lfp in the current context, this allows
480 * getf to lookup the file struct simply by the known open fd */
483 /* Actual getf()/releasef() test */
487 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
488 "Failed to getf fd %d: (%d)\n", fd
, rc
);
492 rc
= vn_rdwr(UIO_WRITE
, fp
->f_vnode
, buf1
, strlen(buf1
), 0,
493 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
495 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
496 "Failed vn_rdwr write of test file: %s (%d)\n",
497 SPLAT_VNODE_TEST_FILE_RW
, rc
);
501 rc
= vn_rdwr(UIO_READ
, fp
->f_vnode
, buf2
, strlen(buf1
), 0,
502 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
504 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
505 "Failed vn_rdwr read of test file: %s (%d)\n",
506 SPLAT_VNODE_TEST_FILE_RW
, rc
);
510 if (strncmp(buf1
, buf2
, strlen(buf1
))) {
512 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
513 "Failed strncmp data written does not match "
514 "data read\nWrote: %sRead: %s\n", buf1
, buf2
);
519 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Wrote: %s", buf1
);
520 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Read: %s", buf2
);
521 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Successfully wrote and "
522 "read expected data pattern to test file: %s\n",
523 SPLAT_VNODE_TEST_FILE_RW
);
528 vn_remove(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
, RMFILE
);
531 } /* splat_vnode_test7() */
534 splat_vnode_init(void)
536 splat_subsystem_t
*sub
;
538 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
542 memset(sub
, 0, sizeof(*sub
));
543 strncpy(sub
->desc
.name
, SPLAT_VNODE_NAME
, SPLAT_NAME_SIZE
);
544 strncpy(sub
->desc
.desc
, SPLAT_VNODE_DESC
, SPLAT_DESC_SIZE
);
545 INIT_LIST_HEAD(&sub
->subsystem_list
);
546 INIT_LIST_HEAD(&sub
->test_list
);
547 spin_lock_init(&sub
->test_lock
);
548 sub
->desc
.id
= SPLAT_SUBSYSTEM_VNODE
;
550 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST1_NAME
, SPLAT_VNODE_TEST1_DESC
,
551 SPLAT_VNODE_TEST1_ID
, splat_vnode_test1
);
552 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST2_NAME
, SPLAT_VNODE_TEST2_DESC
,
553 SPLAT_VNODE_TEST2_ID
, splat_vnode_test2
);
554 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST3_NAME
, SPLAT_VNODE_TEST3_DESC
,
555 SPLAT_VNODE_TEST3_ID
, splat_vnode_test3
);
556 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST4_NAME
, SPLAT_VNODE_TEST4_DESC
,
557 SPLAT_VNODE_TEST4_ID
, splat_vnode_test4
);
558 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST5_NAME
, SPLAT_VNODE_TEST5_DESC
,
559 SPLAT_VNODE_TEST5_ID
, splat_vnode_test5
);
560 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST6_NAME
, SPLAT_VNODE_TEST6_DESC
,
561 SPLAT_VNODE_TEST6_ID
, splat_vnode_test6
);
562 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST7_NAME
, SPLAT_VNODE_TEST7_DESC
,
563 SPLAT_VNODE_TEST7_ID
, splat_vnode_test7
);
566 } /* splat_vnode_init() */
569 splat_vnode_fini(splat_subsystem_t
*sub
)
573 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST7_ID
);
574 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST6_ID
);
575 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST5_ID
);
576 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST4_ID
);
577 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST3_ID
);
578 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST2_ID
);
579 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST1_ID
);
582 } /* splat_vnode_fini() */
587 return SPLAT_SUBSYSTEM_VNODE
;
588 } /* splat_vnode_id() */