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);
129 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
,
130 "Failed to vn_close test file: %s (%d)\n",
131 SPLAT_VNODE_TEST_FILE
, rc
);
135 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
, "Successfully vn_open'ed "
136 "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE
);
139 } /* splat_vnode_test1() */
142 splat_vnode_test2(struct file
*file
, void *arg
)
147 if ((rc
= vn_openat(SPLAT_VNODE_TEST_FILE_AT
, UIO_SYSSPACE
,
148 FREAD
, 0644, &vp
, 0, 0, rootdir
, 0))) {
149 splat_vprint(file
, SPLAT_VNODE_TEST2_NAME
,
150 "Failed to vn_openat test file: %s (%d)\n",
151 SPLAT_VNODE_TEST_FILE
, rc
);
155 rc
= VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
158 splat_vprint(file
, SPLAT_VNODE_TEST2_NAME
,
159 "Failed to vn_close test file: %s (%d)\n",
160 SPLAT_VNODE_TEST_FILE
, rc
);
164 splat_vprint(file
, SPLAT_VNODE_TEST2_NAME
, "Successfully vn_openat'ed "
165 "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE
);
168 } /* splat_vnode_test2() */
171 splat_vnode_test3(struct file
*file
, void *arg
)
174 char buf1
[32] = "SPL VNode Interface Test File\n";
178 if ((rc
= splat_vnode_unlink_all(file
, arg
, SPLAT_VNODE_TEST3_NAME
)))
181 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
,
182 FWRITE
| FREAD
| FCREAT
| FEXCL
,
184 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
185 "Failed to vn_open test file: %s (%d)\n",
186 SPLAT_VNODE_TEST_FILE_RW
, rc
);
190 rc
= vn_rdwr(UIO_WRITE
, vp
, buf1
, strlen(buf1
), 0,
191 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
193 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
194 "Failed vn_rdwr write of test file: %s (%d)\n",
195 SPLAT_VNODE_TEST_FILE_RW
, rc
);
199 rc
= vn_rdwr(UIO_READ
, vp
, buf2
, strlen(buf1
), 0,
200 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
202 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
203 "Failed vn_rdwr read of test file: %s (%d)\n",
204 SPLAT_VNODE_TEST_FILE_RW
, rc
);
208 if (strncmp(buf1
, buf2
, strlen(buf1
))) {
210 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
211 "Failed strncmp data written does not match "
212 "data read\nWrote: %sRead: %s\n", buf1
, buf2
);
217 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Wrote: %s", buf1
);
218 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Read: %s", buf2
);
219 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Successfully wrote and "
220 "read expected data pattern to test file: %s\n",
221 SPLAT_VNODE_TEST_FILE_RW
);
224 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
225 vn_remove(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
, RMFILE
);
228 } /* splat_vnode_test3() */
231 splat_vnode_test4(struct file
*file
, void *arg
)
234 char buf1
[32] = "SPL VNode Interface Test File\n";
238 if ((rc
= splat_vnode_unlink_all(file
, arg
, SPLAT_VNODE_TEST4_NAME
)))
241 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW1
, UIO_SYSSPACE
,
242 FWRITE
| FREAD
| FCREAT
| FEXCL
, 0644, &vp
, 0, 0))) {
243 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
244 "Failed to vn_open test file: %s (%d)\n",
245 SPLAT_VNODE_TEST_FILE_RW1
, rc
);
249 rc
= vn_rdwr(UIO_WRITE
, vp
, buf1
, strlen(buf1
), 0,
250 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
252 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
253 "Failed vn_rdwr write of test file: %s (%d)\n",
254 SPLAT_VNODE_TEST_FILE_RW1
, rc
);
258 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
260 rc
= vn_rename(SPLAT_VNODE_TEST_FILE_RW1
,SPLAT_VNODE_TEST_FILE_RW2
,0);
262 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Failed vn_rename "
264 SPLAT_VNODE_TEST_FILE_RW1
,
265 SPLAT_VNODE_TEST_FILE_RW2
, rc
);
269 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW2
, UIO_SYSSPACE
,
270 FREAD
| FEXCL
, 0644, &vp
, 0, 0))) {
271 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
272 "Failed to vn_open test file: %s (%d)\n",
273 SPLAT_VNODE_TEST_FILE_RW2
, rc
);
277 rc
= vn_rdwr(UIO_READ
, vp
, buf2
, strlen(buf1
), 0,
278 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
280 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
281 "Failed vn_rdwr read of test file: %s (%d)\n",
282 SPLAT_VNODE_TEST_FILE_RW2
, rc
);
286 if (strncmp(buf1
, buf2
, strlen(buf1
))) {
288 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
289 "Failed strncmp data written does not match "
290 "data read\nWrote: %sRead: %s\n", buf1
, buf2
);
295 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Wrote to %s: %s",
296 SPLAT_VNODE_TEST_FILE_RW1
, buf1
);
297 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Read from %s: %s",
298 SPLAT_VNODE_TEST_FILE_RW2
, buf2
);
299 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Successfully renamed "
300 "test file %s -> %s and verified data pattern\n",
301 SPLAT_VNODE_TEST_FILE_RW1
, SPLAT_VNODE_TEST_FILE_RW2
);
303 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
305 vn_remove(SPLAT_VNODE_TEST_FILE_RW1
, UIO_SYSSPACE
, RMFILE
);
306 vn_remove(SPLAT_VNODE_TEST_FILE_RW2
, UIO_SYSSPACE
, RMFILE
);
309 } /* splat_vnode_test4() */
312 splat_vnode_test5(struct file
*file
, void *arg
)
318 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE
, UIO_SYSSPACE
,
319 FREAD
, 0644, &vp
, 0, 0))) {
320 splat_vprint(file
, SPLAT_VNODE_TEST5_NAME
,
321 "Failed to vn_open test file: %s (%d)\n",
322 SPLAT_VNODE_TEST_FILE
, rc
);
326 rc
= VOP_GETATTR(vp
, &vap
, 0, 0, NULL
);
328 splat_vprint(file
, SPLAT_VNODE_TEST5_NAME
,
329 "Failed to vn_getattr test file: %s (%d)\n",
330 SPLAT_VNODE_TEST_FILE
, rc
);
334 if (vap
.va_type
!= VREG
) {
336 splat_vprint(file
, SPLAT_VNODE_TEST5_NAME
,
337 "Failed expected regular file type "
338 "(%d != VREG): %s (%d)\n", vap
.va_type
,
339 SPLAT_VNODE_TEST_FILE
, rc
);
343 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
, "Successfully "
344 "vn_getattr'ed test file: %s\n", SPLAT_VNODE_TEST_FILE
);
347 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
350 } /* splat_vnode_test5() */
353 splat_vnode_test6(struct file
*file
, void *arg
)
356 char buf
[32] = "SPL VNode Interface Test File\n";
359 if ((rc
= splat_vnode_unlink_all(file
, arg
, SPLAT_VNODE_TEST6_NAME
)))
362 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
,
363 FWRITE
| FCREAT
| FEXCL
, 0644, &vp
, 0, 0))) {
364 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
,
365 "Failed to vn_open test file: %s (%d)\n",
366 SPLAT_VNODE_TEST_FILE_RW
, rc
);
370 rc
= vn_rdwr(UIO_WRITE
, vp
, buf
, strlen(buf
), 0,
371 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
373 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
,
374 "Failed vn_rdwr write of test file: %s (%d)\n",
375 SPLAT_VNODE_TEST_FILE_RW
, rc
);
379 rc
= vn_fsync(vp
, 0, 0, 0);
381 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
,
382 "Failed vn_fsync of test file: %s (%d)\n",
383 SPLAT_VNODE_TEST_FILE_RW
, rc
);
388 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
, "Successfully "
389 "fsync'ed test file %s\n", SPLAT_VNODE_TEST_FILE_RW
);
391 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
392 vn_remove(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
, RMFILE
);
395 } /* splat_vnode_test6() */
397 /* Basically a slightly modified version of sys_close() */
402 struct files_struct
*files
= current
->files
;
403 #ifdef HAVE_FILES_FDTABLE
406 spin_lock(&files
->file_lock
);
407 fdt
= files_fdtable(files
);
409 if (fd
>= fdt
->max_fds
)
416 rcu_assign_pointer(fdt
->fd
[fd
], NULL
);
417 __clear_close_on_exec(fd
, fdt
);
419 spin_lock(&files
->file_lock
);
420 if (fd
>= files
->max_fds
)
427 files
->fd
[fd
] = NULL
;
428 FD_CLR(fd
, files
->close_on_exec
);
430 /* Dropping the lock here exposes a minor race but it allows me
431 * to use the existing kernel interfaces for this, and for a test
432 * case I think that's reasonable. */
433 spin_unlock(&files
->file_lock
);
438 spin_unlock(&files
->file_lock
);
440 } /* fd_uninstall() */
443 splat_vnode_test7(struct file
*file
, void *arg
)
445 char buf1
[32] = "SPL VNode Interface Test File\n";
451 if ((rc
= splat_vnode_unlink_all(file
, arg
, SPLAT_VNODE_TEST7_NAME
)))
454 /* Prep work needed to test getf/releasef */
455 fd
= get_unused_fd();
457 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
458 "Failed to get unused fd (%d)\n", fd
);
462 lfp
= filp_open(SPLAT_VNODE_TEST_FILE_RW
, O_RDWR
|O_CREAT
|O_EXCL
, 0644);
466 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
467 "Failed to filp_open: %s (%d)\n",
468 SPLAT_VNODE_TEST_FILE_RW
, rc
);
472 /* Pair up the new fd and lfp in the current context, this allows
473 * getf to lookup the file struct simply by the known open fd */
476 /* Actual getf()/releasef() test */
480 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
481 "Failed to getf fd %d: (%d)\n", fd
, rc
);
485 rc
= vn_rdwr(UIO_WRITE
, fp
->f_vnode
, buf1
, strlen(buf1
), 0,
486 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
488 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
489 "Failed vn_rdwr write of test file: %s (%d)\n",
490 SPLAT_VNODE_TEST_FILE_RW
, rc
);
494 rc
= vn_rdwr(UIO_READ
, fp
->f_vnode
, buf2
, strlen(buf1
), 0,
495 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
497 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
498 "Failed vn_rdwr read of test file: %s (%d)\n",
499 SPLAT_VNODE_TEST_FILE_RW
, rc
);
503 if (strncmp(buf1
, buf2
, strlen(buf1
))) {
505 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
506 "Failed strncmp data written does not match "
507 "data read\nWrote: %sRead: %s\n", buf1
, buf2
);
512 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Wrote: %s", buf1
);
513 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Read: %s", buf2
);
514 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Successfully wrote and "
515 "read expected data pattern to test file: %s\n",
516 SPLAT_VNODE_TEST_FILE_RW
);
521 vn_remove(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
, RMFILE
);
524 } /* splat_vnode_test7() */
527 splat_vnode_init(void)
529 splat_subsystem_t
*sub
;
531 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
535 memset(sub
, 0, sizeof(*sub
));
536 strncpy(sub
->desc
.name
, SPLAT_VNODE_NAME
, SPLAT_NAME_SIZE
);
537 strncpy(sub
->desc
.desc
, SPLAT_VNODE_DESC
, SPLAT_DESC_SIZE
);
538 INIT_LIST_HEAD(&sub
->subsystem_list
);
539 INIT_LIST_HEAD(&sub
->test_list
);
540 spin_lock_init(&sub
->test_lock
);
541 sub
->desc
.id
= SPLAT_SUBSYSTEM_VNODE
;
543 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST1_NAME
, SPLAT_VNODE_TEST1_DESC
,
544 SPLAT_VNODE_TEST1_ID
, splat_vnode_test1
);
545 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST2_NAME
, SPLAT_VNODE_TEST2_DESC
,
546 SPLAT_VNODE_TEST2_ID
, splat_vnode_test2
);
547 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST3_NAME
, SPLAT_VNODE_TEST3_DESC
,
548 SPLAT_VNODE_TEST3_ID
, splat_vnode_test3
);
549 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST4_NAME
, SPLAT_VNODE_TEST4_DESC
,
550 SPLAT_VNODE_TEST4_ID
, splat_vnode_test4
);
551 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST5_NAME
, SPLAT_VNODE_TEST5_DESC
,
552 SPLAT_VNODE_TEST5_ID
, splat_vnode_test5
);
553 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST6_NAME
, SPLAT_VNODE_TEST6_DESC
,
554 SPLAT_VNODE_TEST6_ID
, splat_vnode_test6
);
555 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST7_NAME
, SPLAT_VNODE_TEST7_DESC
,
556 SPLAT_VNODE_TEST7_ID
, splat_vnode_test7
);
559 } /* splat_vnode_init() */
562 splat_vnode_fini(splat_subsystem_t
*sub
)
566 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST7_ID
);
567 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST6_ID
);
568 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST5_ID
);
569 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST4_ID
);
570 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST3_ID
);
571 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST2_ID
);
572 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST1_ID
);
575 } /* splat_vnode_fini() */
580 return SPLAT_SUBSYSTEM_VNODE
;
581 } /* splat_vnode_id() */