2 * This file is part of the SPL: Solaris Porting Layer.
4 * Copyright (c) 2008 Lawrence Livermore National Security, LLC.
5 * Produced at Lawrence Livermore National Laboratory
7 * Brian Behlendorf <behlendorf1@llnl.gov>,
8 * Herb Wartens <wartens2@llnl.gov>,
9 * Jim Garlick <garlick@llnl.gov>
12 * This is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "splat-internal.h"
28 #include <linux/rcupdate.h>
30 #define SPLAT_SUBSYSTEM_VNODE 0x0900
31 #define SPLAT_VNODE_NAME "vnode"
32 #define SPLAT_VNODE_DESC "Kernel Vnode Tests"
34 #define SPLAT_VNODE_TEST1_ID 0x0901
35 #define SPLAT_VNODE_TEST1_NAME "vn_open"
36 #define SPLAT_VNODE_TEST1_DESC "Vn_open Test"
38 #define SPLAT_VNODE_TEST2_ID 0x0902
39 #define SPLAT_VNODE_TEST2_NAME "vn_openat"
40 #define SPLAT_VNODE_TEST2_DESC "Vn_openat Test"
42 #define SPLAT_VNODE_TEST3_ID 0x0903
43 #define SPLAT_VNODE_TEST3_NAME "vn_rdwr"
44 #define SPLAT_VNODE_TEST3_DESC "Vn_rdwrt Test"
46 #define SPLAT_VNODE_TEST4_ID 0x0904
47 #define SPLAT_VNODE_TEST4_NAME "vn_rename"
48 #define SPLAT_VNODE_TEST4_DESC "Vn_rename Test"
50 #define SPLAT_VNODE_TEST5_ID 0x0905
51 #define SPLAT_VNODE_TEST5_NAME "vn_getattr"
52 #define SPLAT_VNODE_TEST5_DESC "Vn_getattr Test"
54 #define SPLAT_VNODE_TEST6_ID 0x0906
55 #define SPLAT_VNODE_TEST6_NAME "vn_sync"
56 #define SPLAT_VNODE_TEST6_DESC "Vn_sync Test"
58 #define SPLAT_VNODE_TEST7_ID 0x0907
59 #define SPLAT_VNODE_TEST7_NAME "vn_getf"
60 #define SPLAT_VNODE_TEST7_DESC "vn_getf/vn_releasef Test"
62 #define SPLAT_VNODE_TEST_FILE "/etc/fstab"
63 #define SPLAT_VNODE_TEST_FILE_AT "etc/fstab"
64 #define SPLAT_VNODE_TEST_FILE_RW "/tmp/spl.vnode.tmp"
65 #define SPLAT_VNODE_TEST_FILE_RW1 "/tmp/spl.vnode.tmp.1"
66 #define SPLAT_VNODE_TEST_FILE_RW2 "/tmp/spl.vnode.tmp.2"
69 splat_vnode_test1(struct file
*file
, void *arg
)
74 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE
, UIO_SYSSPACE
,
75 FREAD
, 0644, &vp
, 0, 0))) {
76 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
,
77 "Failed to vn_open test file: %s (%d)\n",
78 SPLAT_VNODE_TEST_FILE
, rc
);
82 rc
= VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
86 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
,
87 "Failed to vn_close test file: %s (%d)\n",
88 SPLAT_VNODE_TEST_FILE
, rc
);
92 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
, "Successfully vn_open'ed "
93 "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE
);
96 } /* splat_vnode_test1() */
99 splat_vnode_test2(struct file
*file
, void *arg
)
104 if ((rc
= vn_openat(SPLAT_VNODE_TEST_FILE_AT
, UIO_SYSSPACE
,
105 FREAD
, 0644, &vp
, 0, 0, rootdir
, 0))) {
106 splat_vprint(file
, SPLAT_VNODE_TEST2_NAME
,
107 "Failed to vn_openat test file: %s (%d)\n",
108 SPLAT_VNODE_TEST_FILE
, rc
);
112 rc
= VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
116 splat_vprint(file
, SPLAT_VNODE_TEST2_NAME
,
117 "Failed to vn_close test file: %s (%d)\n",
118 SPLAT_VNODE_TEST_FILE
, rc
);
122 splat_vprint(file
, SPLAT_VNODE_TEST2_NAME
, "Successfully vn_openat'ed "
123 "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE
);
126 } /* splat_vnode_test2() */
129 splat_vnode_test3(struct file
*file
, void *arg
)
132 char buf1
[32] = "SPL VNode Interface Test File\n";
136 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
,
137 FWRITE
| FREAD
| FCREAT
| FEXCL
,
139 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
140 "Failed to vn_open test file: %s (%d)\n",
141 SPLAT_VNODE_TEST_FILE_RW
, rc
);
145 rc
= vn_rdwr(UIO_WRITE
, vp
, buf1
, strlen(buf1
), 0,
146 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
148 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
149 "Failed vn_rdwr write of test file: %s (%d)\n",
150 SPLAT_VNODE_TEST_FILE_RW
, rc
);
154 rc
= vn_rdwr(UIO_READ
, vp
, buf2
, strlen(buf1
), 0,
155 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
157 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
158 "Failed vn_rdwr read of test file: %s (%d)\n",
159 SPLAT_VNODE_TEST_FILE_RW
, rc
);
163 if (strncmp(buf1
, buf2
, strlen(buf1
))) {
165 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
,
166 "Failed strncmp data written does not match "
167 "data read\nWrote: %sRead: %s\n", buf1
, buf2
);
172 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Wrote: %s", buf1
);
173 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Read: %s", buf2
);
174 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Successfully wrote and "
175 "read expected data pattern to test file: %s\n",
176 SPLAT_VNODE_TEST_FILE_RW
);
179 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
181 vn_remove(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
, RMFILE
);
184 } /* splat_vnode_test3() */
187 splat_vnode_test4(struct file
*file
, void *arg
)
190 char buf1
[32] = "SPL VNode Interface Test File\n";
194 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW1
, UIO_SYSSPACE
,
195 FWRITE
| FREAD
| FCREAT
| FEXCL
, 0644, &vp
, 0, 0))) {
196 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
197 "Failed to vn_open test file: %s (%d)\n",
198 SPLAT_VNODE_TEST_FILE_RW1
, rc
);
202 rc
= vn_rdwr(UIO_WRITE
, vp
, buf1
, strlen(buf1
), 0,
203 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
205 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
206 "Failed vn_rdwr write of test file: %s (%d)\n",
207 SPLAT_VNODE_TEST_FILE_RW1
, rc
);
211 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
214 rc
= vn_rename(SPLAT_VNODE_TEST_FILE_RW1
,SPLAT_VNODE_TEST_FILE_RW2
,0);
216 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Failed vn_rename "
218 SPLAT_VNODE_TEST_FILE_RW1
,
219 SPLAT_VNODE_TEST_FILE_RW2
, rc
);
223 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW2
, UIO_SYSSPACE
,
224 FREAD
| FEXCL
, 0644, &vp
, 0, 0))) {
225 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
226 "Failed to vn_open test file: %s (%d)\n",
227 SPLAT_VNODE_TEST_FILE_RW2
, rc
);
231 rc
= vn_rdwr(UIO_READ
, vp
, buf2
, strlen(buf1
), 0,
232 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
234 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
235 "Failed vn_rdwr read of test file: %s (%d)\n",
236 SPLAT_VNODE_TEST_FILE_RW2
, rc
);
240 if (strncmp(buf1
, buf2
, strlen(buf1
))) {
242 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
,
243 "Failed strncmp data written does not match "
244 "data read\nWrote: %sRead: %s\n", buf1
, buf2
);
249 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Wrote to %s: %s",
250 SPLAT_VNODE_TEST_FILE_RW1
, buf1
);
251 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Read from %s: %s",
252 SPLAT_VNODE_TEST_FILE_RW2
, buf2
);
253 splat_vprint(file
, SPLAT_VNODE_TEST4_NAME
, "Successfully renamed "
254 "test file %s -> %s and verified data pattern\n",
255 SPLAT_VNODE_TEST_FILE_RW1
, SPLAT_VNODE_TEST_FILE_RW2
);
257 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
260 vn_remove(SPLAT_VNODE_TEST_FILE_RW1
, UIO_SYSSPACE
, RMFILE
);
261 vn_remove(SPLAT_VNODE_TEST_FILE_RW2
, UIO_SYSSPACE
, RMFILE
);
264 } /* splat_vnode_test4() */
267 splat_vnode_test5(struct file
*file
, void *arg
)
273 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE
, UIO_SYSSPACE
,
274 FREAD
, 0644, &vp
, 0, 0))) {
275 splat_vprint(file
, SPLAT_VNODE_TEST5_NAME
,
276 "Failed to vn_open test file: %s (%d)\n",
277 SPLAT_VNODE_TEST_FILE
, rc
);
281 rc
= VOP_GETATTR(vp
, &vap
, 0, 0, NULL
);
283 splat_vprint(file
, SPLAT_VNODE_TEST5_NAME
,
284 "Failed to vn_getattr test file: %s (%d)\n",
285 SPLAT_VNODE_TEST_FILE
, rc
);
289 if (vap
.va_type
!= VREG
) {
291 splat_vprint(file
, SPLAT_VNODE_TEST5_NAME
,
292 "Failed expected regular file type "
293 "(%d != VREG): %s (%d)\n", vap
.va_type
,
294 SPLAT_VNODE_TEST_FILE
, rc
);
298 splat_vprint(file
, SPLAT_VNODE_TEST1_NAME
, "Successfully "
299 "vn_getattr'ed test file: %s\n", SPLAT_VNODE_TEST_FILE
);
302 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
306 } /* splat_vnode_test5() */
309 splat_vnode_test6(struct file
*file
, void *arg
)
312 char buf
[32] = "SPL VNode Interface Test File\n";
315 if ((rc
= vn_open(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
,
316 FWRITE
| FCREAT
| FEXCL
, 0644, &vp
, 0, 0))) {
317 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
,
318 "Failed to vn_open test file: %s (%d)\n",
319 SPLAT_VNODE_TEST_FILE_RW
, rc
);
323 rc
= vn_rdwr(UIO_WRITE
, vp
, buf
, strlen(buf
), 0,
324 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
326 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
,
327 "Failed vn_rdwr write of test file: %s (%d)\n",
328 SPLAT_VNODE_TEST_FILE_RW
, rc
);
332 rc
= vn_fsync(vp
, 0, 0, 0);
334 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
,
335 "Failed vn_fsync of test file: %s (%d)\n",
336 SPLAT_VNODE_TEST_FILE_RW
, rc
);
341 splat_vprint(file
, SPLAT_VNODE_TEST6_NAME
, "Successfully "
342 "fsync'ed test file %s\n", SPLAT_VNODE_TEST_FILE_RW
);
344 VOP_CLOSE(vp
, 0, 0, 0, 0, 0);
346 vn_remove(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
, RMFILE
);
349 } /* splat_vnode_test6() */
351 /* Basically a slightly modified version of sys_close() */
356 struct files_struct
*files
= current
->files
;
357 #ifdef HAVE_FILES_FDTABLE
360 spin_lock(&files
->file_lock
);
361 fdt
= files_fdtable(files
);
363 if (fd
>= fdt
->max_fds
)
370 rcu_assign_pointer(fdt
->fd
[fd
], NULL
);
371 FD_CLR(fd
, fdt
->close_on_exec
);
373 spin_lock(&files
->file_lock
);
374 if (fd
>= files
->max_fds
)
381 files
->fd
[fd
] = NULL
;
382 FD_CLR(fd
, files
->close_on_exec
);
384 /* Dropping the lock here exposes a minor race but it allows me
385 * to use the existing kernel interfaces for this, and for a test
386 * case I think that's reasonable. */
387 spin_unlock(&files
->file_lock
);
392 spin_unlock(&files
->file_lock
);
394 } /* fd_uninstall() */
397 splat_vnode_test7(struct file
*file
, void *arg
)
399 char buf1
[32] = "SPL VNode Interface Test File\n";
405 /* Prep work needed to test getf/releasef */
406 fd
= get_unused_fd();
408 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
409 "Failed to get unused fd (%d)\n", fd
);
413 lfp
= filp_open(SPLAT_VNODE_TEST_FILE_RW
, O_RDWR
|O_CREAT
|O_EXCL
, 0644);
417 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
418 "Failed to filp_open: %s (%d)\n",
419 SPLAT_VNODE_TEST_FILE_RW
, rc
);
423 /* Pair up the new fd and lfp in the current context, this allows
424 * getf to lookup the file struct simply by the known open fd */
427 /* Actual getf()/releasef() test */
431 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
432 "Failed to getf fd %d: (%d)\n", fd
, rc
);
436 rc
= vn_rdwr(UIO_WRITE
, fp
->f_vnode
, buf1
, strlen(buf1
), 0,
437 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
439 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
440 "Failed vn_rdwr write of test file: %s (%d)\n",
441 SPLAT_VNODE_TEST_FILE_RW
, rc
);
445 rc
= vn_rdwr(UIO_READ
, fp
->f_vnode
, buf2
, strlen(buf1
), 0,
446 UIO_SYSSPACE
, 0, RLIM64_INFINITY
, 0, NULL
);
448 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
449 "Failed vn_rdwr read of test file: %s (%d)\n",
450 SPLAT_VNODE_TEST_FILE_RW
, rc
);
454 if (strncmp(buf1
, buf2
, strlen(buf1
))) {
456 splat_vprint(file
, SPLAT_VNODE_TEST7_NAME
,
457 "Failed strncmp data written does not match "
458 "data read\nWrote: %sRead: %s\n", buf1
, buf2
);
463 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Wrote: %s", buf1
);
464 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Read: %s", buf2
);
465 splat_vprint(file
, SPLAT_VNODE_TEST3_NAME
, "Successfully wrote and "
466 "read expected data pattern to test file: %s\n",
467 SPLAT_VNODE_TEST_FILE_RW
);
472 vn_remove(SPLAT_VNODE_TEST_FILE_RW
, UIO_SYSSPACE
, RMFILE
);
475 } /* splat_vnode_test7() */
478 splat_vnode_init(void)
480 splat_subsystem_t
*sub
;
482 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
486 memset(sub
, 0, sizeof(*sub
));
487 strncpy(sub
->desc
.name
, SPLAT_VNODE_NAME
, SPLAT_NAME_SIZE
);
488 strncpy(sub
->desc
.desc
, SPLAT_VNODE_DESC
, SPLAT_DESC_SIZE
);
489 INIT_LIST_HEAD(&sub
->subsystem_list
);
490 INIT_LIST_HEAD(&sub
->test_list
);
491 spin_lock_init(&sub
->test_lock
);
492 sub
->desc
.id
= SPLAT_SUBSYSTEM_VNODE
;
494 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST1_NAME
, SPLAT_VNODE_TEST1_DESC
,
495 SPLAT_VNODE_TEST1_ID
, splat_vnode_test1
);
496 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST2_NAME
, SPLAT_VNODE_TEST2_DESC
,
497 SPLAT_VNODE_TEST2_ID
, splat_vnode_test2
);
498 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST3_NAME
, SPLAT_VNODE_TEST3_DESC
,
499 SPLAT_VNODE_TEST3_ID
, splat_vnode_test3
);
500 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST4_NAME
, SPLAT_VNODE_TEST4_DESC
,
501 SPLAT_VNODE_TEST4_ID
, splat_vnode_test4
);
502 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST5_NAME
, SPLAT_VNODE_TEST5_DESC
,
503 SPLAT_VNODE_TEST5_ID
, splat_vnode_test5
);
504 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST6_NAME
, SPLAT_VNODE_TEST6_DESC
,
505 SPLAT_VNODE_TEST6_ID
, splat_vnode_test6
);
506 SPLAT_TEST_INIT(sub
, SPLAT_VNODE_TEST7_NAME
, SPLAT_VNODE_TEST7_DESC
,
507 SPLAT_VNODE_TEST7_ID
, splat_vnode_test7
);
510 } /* splat_vnode_init() */
513 splat_vnode_fini(splat_subsystem_t
*sub
)
517 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST7_ID
);
518 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST6_ID
);
519 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST5_ID
);
520 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST4_ID
);
521 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST3_ID
);
522 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST2_ID
);
523 SPLAT_TEST_FINI(sub
, SPLAT_VNODE_TEST1_ID
);
526 } /* splat_vnode_fini() */
531 return SPLAT_SUBSYSTEM_VNODE
;
532 } /* splat_vnode_id() */