]> git.proxmox.com Git - mirror_spl.git/blame - modules/splat/splat-vnode.c
OK, some pretty substantial rework here. I've merged the spl-file
[mirror_spl.git] / modules / splat / splat-vnode.c
CommitLineData
4b171585 1#include "splat-internal.h"
e4f1d29f 2#include <linux/rcupdate.h>
4b171585 3
4#define SPLAT_SUBSYSTEM_VNODE 0x0900
5#define SPLAT_VNODE_NAME "vnode"
6#define SPLAT_VNODE_DESC "Kernel Vnode Tests"
7
8#define SPLAT_VNODE_TEST1_ID 0x0901
9#define SPLAT_VNODE_TEST1_NAME "vn_open"
10#define SPLAT_VNODE_TEST1_DESC "Vn_open Test"
11
12#define SPLAT_VNODE_TEST2_ID 0x0902
13#define SPLAT_VNODE_TEST2_NAME "vn_openat"
14#define SPLAT_VNODE_TEST2_DESC "Vn_openat Test"
15
16#define SPLAT_VNODE_TEST3_ID 0x0903
17#define SPLAT_VNODE_TEST3_NAME "vn_rdwr"
18#define SPLAT_VNODE_TEST3_DESC "Vn_rdwrt Test"
19
20#define SPLAT_VNODE_TEST4_ID 0x0904
21#define SPLAT_VNODE_TEST4_NAME "vn_rename"
22#define SPLAT_VNODE_TEST4_DESC "Vn_rename Test"
23
24#define SPLAT_VNODE_TEST5_ID 0x0905
25#define SPLAT_VNODE_TEST5_NAME "vn_getattr"
26#define SPLAT_VNODE_TEST5_DESC "Vn_getattr Test"
27
28#define SPLAT_VNODE_TEST6_ID 0x0906
29#define SPLAT_VNODE_TEST6_NAME "vn_sync"
30#define SPLAT_VNODE_TEST6_DESC "Vn_sync Test"
31
e4f1d29f 32#define SPLAT_VNODE_TEST7_ID 0x0907
33#define SPLAT_VNODE_TEST7_NAME "getf"
34#define SPLAT_VNODE_TEST7_DESC "getf/releasef Test"
35
4b171585 36#define SPLAT_VNODE_TEST_FILE "/etc/fstab"
37#define SPLAT_VNODE_TEST_FILE_AT "etc/fstab"
38#define SPLAT_VNODE_TEST_FILE_RW "/tmp/spl.vnode.tmp"
39#define SPLAT_VNODE_TEST_FILE_RW1 "/tmp/spl.vnode.tmp.1"
40#define SPLAT_VNODE_TEST_FILE_RW2 "/tmp/spl.vnode.tmp.2"
41
42static int
43splat_vnode_test1(struct file *file, void *arg)
44{
45 vnode_t *vp;
46 int rc;
47
48 if ((rc = vn_open(SPLAT_VNODE_TEST_FILE, UIO_SYSSPACE,
49 FREAD, 0644, &vp, 0, 0))) {
50 splat_vprint(file, SPLAT_VNODE_TEST1_NAME,
51 "Failed to vn_open test file: %s (%d)\n",
52 SPLAT_VNODE_TEST_FILE, rc);
53 return rc;
54 }
55
56 rc = VOP_CLOSE(vp, 0, 0, 0, 0, 0);
57 VN_RELE(vp);
58
59 if (rc) {
60 splat_vprint(file, SPLAT_VNODE_TEST1_NAME,
61 "Failed to vn_close test file: %s (%d)\n",
62 SPLAT_VNODE_TEST_FILE, rc);
63 return rc;
64 }
65
66 splat_vprint(file, SPLAT_VNODE_TEST1_NAME, "Successfully vn_open'ed "
67 "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE);
68
69 return rc;
70} /* splat_vnode_test1() */
71
72static int
73splat_vnode_test2(struct file *file, void *arg)
74{
75 vnode_t *vp;
76 int rc;
77
78 if ((rc = vn_openat(SPLAT_VNODE_TEST_FILE_AT, UIO_SYSSPACE,
79 FREAD, 0644, &vp, 0, 0, rootdir, 0))) {
80 splat_vprint(file, SPLAT_VNODE_TEST2_NAME,
81 "Failed to vn_openat test file: %s (%d)\n",
82 SPLAT_VNODE_TEST_FILE, rc);
83 return rc;
84 }
85
86 rc = VOP_CLOSE(vp, 0, 0, 0, 0, 0);
87 VN_RELE(vp);
88
89 if (rc) {
90 splat_vprint(file, SPLAT_VNODE_TEST2_NAME,
91 "Failed to vn_close test file: %s (%d)\n",
92 SPLAT_VNODE_TEST_FILE, rc);
93 return rc;
94 }
95
96 splat_vprint(file, SPLAT_VNODE_TEST2_NAME, "Successfully vn_openat'ed "
97 "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE);
98
99 return rc;
100} /* splat_vnode_test2() */
101
102static int
103splat_vnode_test3(struct file *file, void *arg)
104{
105 vnode_t *vp;
106 char buf1[32] = "SPL VNode Interface Test File\n";
107 char buf2[32] = "";
108 int rc;
109
110 if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE,
111 FWRITE | FREAD | FCREAT | FEXCL,
112 0644, &vp, 0, 0))) {
113 splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
114 "Failed to vn_open test file: %s (%d)\n",
115 SPLAT_VNODE_TEST_FILE_RW, rc);
116 return rc;
117 }
118
119 rc = vn_rdwr(UIO_WRITE, vp, buf1, strlen(buf1), 0,
120 UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
121 if (rc < 0) {
122 splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
123 "Failed vn_rdwr write of test file: %s (%d)\n",
124 SPLAT_VNODE_TEST_FILE_RW, rc);
125 goto out;
126 }
127
128 rc = vn_rdwr(UIO_READ, vp, buf2, strlen(buf1), 0,
129 UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
130 if (rc < 0) {
131 splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
132 "Failed vn_rdwr read of test file: %s (%d)\n",
133 SPLAT_VNODE_TEST_FILE_RW, rc);
134 goto out;
135 }
136
137 if (strncmp(buf1, buf2, strlen(buf1))) {
e4f1d29f 138 rc = -EINVAL;
4b171585 139 splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
140 "Failed strncmp data written does not match "
141 "data read\nWrote: %sRead: %s\n", buf1, buf2);
142 goto out;
143 }
144
145 rc = 0;
146 splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Wrote: %s", buf1);
147 splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Read: %s", buf2);
148 splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Successfully wrote and "
149 "read expected data pattern to test file: %s\n",
150 SPLAT_VNODE_TEST_FILE_RW);
151
152out:
153 VOP_CLOSE(vp, 0, 0, 0, 0, 0);
154 VN_RELE(vp);
2f5d55aa 155 vn_remove(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE, RMFILE);
4b171585 156
157 return rc;
158} /* splat_vnode_test3() */
159
160static int
161splat_vnode_test4(struct file *file, void *arg)
162{
163 vnode_t *vp;
164 char buf1[32] = "SPL VNode Interface Test File\n";
165 char buf2[32] = "";
166 int rc;
167
168 if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW1, UIO_SYSSPACE,
169 FWRITE | FREAD | FCREAT | FEXCL, 0644, &vp, 0, 0))) {
170 splat_vprint(file, SPLAT_VNODE_TEST4_NAME,
171 "Failed to vn_open test file: %s (%d)\n",
172 SPLAT_VNODE_TEST_FILE_RW1, rc);
173 goto out;
174 }
175
176 rc = vn_rdwr(UIO_WRITE, vp, buf1, strlen(buf1), 0,
177 UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
178 if (rc < 0) {
179 splat_vprint(file, SPLAT_VNODE_TEST4_NAME,
180 "Failed vn_rdwr write of test file: %s (%d)\n",
181 SPLAT_VNODE_TEST_FILE_RW1, rc);
182 goto out2;
183 }
184
185 VOP_CLOSE(vp, 0, 0, 0, 0, 0);
186 VN_RELE(vp);
187
188 rc = vn_rename(SPLAT_VNODE_TEST_FILE_RW1,SPLAT_VNODE_TEST_FILE_RW2,0);
189 if (rc) {
190 splat_vprint(file, SPLAT_VNODE_TEST4_NAME, "Failed vn_rename "
191 "%s -> %s (%d)\n",
192 SPLAT_VNODE_TEST_FILE_RW1,
193 SPLAT_VNODE_TEST_FILE_RW2, rc);
194 goto out;
195 }
196
197 if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW2, UIO_SYSSPACE,
198 FREAD | FEXCL, 0644, &vp, 0, 0))) {
199 splat_vprint(file, SPLAT_VNODE_TEST4_NAME,
200 "Failed to vn_open test file: %s (%d)\n",
201 SPLAT_VNODE_TEST_FILE_RW2, rc);
202 goto out;
203 }
204
205 rc = vn_rdwr(UIO_READ, vp, buf2, strlen(buf1), 0,
206 UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
207 if (rc < 0) {
208 splat_vprint(file, SPLAT_VNODE_TEST4_NAME,
209 "Failed vn_rdwr read of test file: %s (%d)\n",
210 SPLAT_VNODE_TEST_FILE_RW2, rc);
211 goto out2;
212 }
213
214 if (strncmp(buf1, buf2, strlen(buf1))) {
215 rc = EINVAL;
216 splat_vprint(file, SPLAT_VNODE_TEST4_NAME,
217 "Failed strncmp data written does not match "
218 "data read\nWrote: %sRead: %s\n", buf1, buf2);
219 goto out2;
220 }
221
222 rc = 0;
223 splat_vprint(file, SPLAT_VNODE_TEST4_NAME, "Wrote to %s: %s",
224 SPLAT_VNODE_TEST_FILE_RW1, buf1);
225 splat_vprint(file, SPLAT_VNODE_TEST4_NAME, "Read from %s: %s",
226 SPLAT_VNODE_TEST_FILE_RW2, buf2);
227 splat_vprint(file, SPLAT_VNODE_TEST4_NAME, "Successfully renamed "
228 "test file %s -> %s and verified data pattern\n",
229 SPLAT_VNODE_TEST_FILE_RW1, SPLAT_VNODE_TEST_FILE_RW2);
230out2:
231 VOP_CLOSE(vp, 0, 0, 0, 0, 0);
232 VN_RELE(vp);
233out:
2f5d55aa 234 vn_remove(SPLAT_VNODE_TEST_FILE_RW1, UIO_SYSSPACE, RMFILE);
235 vn_remove(SPLAT_VNODE_TEST_FILE_RW2, UIO_SYSSPACE, RMFILE);
4b171585 236
237 return rc;
238} /* splat_vnode_test4() */
239
240static int
241splat_vnode_test5(struct file *file, void *arg)
242{
243 vnode_t *vp;
244 vattr_t vap;
245 int rc;
246
247 if ((rc = vn_open(SPLAT_VNODE_TEST_FILE, UIO_SYSSPACE,
248 FREAD, 0644, &vp, 0, 0))) {
249 splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
250 "Failed to vn_open test file: %s (%d)\n",
251 SPLAT_VNODE_TEST_FILE, rc);
252 return rc;
253 }
254
255 rc = VOP_GETATTR(vp, &vap, 0, 0, NULL);
256 if (rc) {
257 splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
258 "Failed to vn_getattr test file: %s (%d)\n",
259 SPLAT_VNODE_TEST_FILE, rc);
260 goto out;
261 }
262
263 if (vap.va_type != VREG) {
264 rc = -EINVAL;
265 splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
266 "Failed expected regular file type "
267 "(%d != VREG): %s (%d)\n", vap.va_type,
268 SPLAT_VNODE_TEST_FILE, rc);
269 goto out;
270 }
271
272 splat_vprint(file, SPLAT_VNODE_TEST1_NAME, "Successfully "
273 "vn_getattr'ed test file: %s\n", SPLAT_VNODE_TEST_FILE);
274
275out:
276 VOP_CLOSE(vp, 0, 0, 0, 0, 0);
277 VN_RELE(vp);
278
279 return rc;
280} /* splat_vnode_test5() */
281
282static int
283splat_vnode_test6(struct file *file, void *arg)
284{
285 vnode_t *vp;
286 char buf[32] = "SPL VNode Interface Test File\n";
287 int rc;
288
289 if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE,
290 FWRITE | FREAD | FCREAT | FEXCL, 0644, &vp, 0, 0))) {
291 splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
292 "Failed to vn_open test file: %s (%d)\n",
293 SPLAT_VNODE_TEST_FILE_RW, rc);
294 return rc;
295 }
296
297 rc = vn_rdwr(UIO_WRITE, vp, buf, strlen(buf), 0,
298 UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
299 if (rc < 0) {
300 splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
301 "Failed vn_rdwr write of test file: %s (%d)\n",
302 SPLAT_VNODE_TEST_FILE_RW, rc);
303 goto out;
304 }
305
306 rc = vn_fsync(vp, 0, 0, 0);
307 if (rc) {
308 splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
309 "Failed vn_fsync of test file: %s (%d)\n",
310 SPLAT_VNODE_TEST_FILE_RW, rc);
311 goto out;
312 }
313
314 rc = 0;
315 splat_vprint(file, SPLAT_VNODE_TEST6_NAME, "Successfully "
316 "fsync'ed test file %s\n", SPLAT_VNODE_TEST_FILE_RW);
317out:
318 VOP_CLOSE(vp, 0, 0, 0, 0, 0);
319 VN_RELE(vp);
2f5d55aa 320 vn_remove(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE, RMFILE);
4b171585 321
322 return rc;
e4f1d29f 323} /* splat_vnode_test6() */
324
325/* Basically a slightly modified version of sys_close() */
326static int
327fd_uninstall(int fd)
328{
329 struct file *fp;
330 struct files_struct *files = current->files;
331 struct fdtable *fdt;
332
333 spin_lock(&files->file_lock);
334 fdt = files_fdtable(files);
335
336 if (fd >= fdt->max_fds)
337 goto out_unlock;
338
339 fp = fdt->fd[fd];
340 if (!fp)
341 goto out_unlock;
342
343 rcu_assign_pointer(fdt->fd[fd], NULL);
344 FD_CLR(fd, fdt->close_on_exec);
345
346 /* Dropping the lock here exposes a minor race but it allows me
347 * to use the existing kernel interfaces for this, and for a test
348 * case I think that's reasonable. */
349 spin_unlock(&files->file_lock);
350 put_unused_fd(fd);
351
352out_unlock:
353 spin_unlock(&files->file_lock);
354 return -EBADF;
355} /* fd_uninstall() */
356
357static int
358splat_vnode_test7(struct file *file, void *arg)
359{
360 char buf1[32] = "SPL VNode Interface Test File\n";
361 char buf2[32] = "";
362 struct file *lfp;
363 file_t *fp;
364 int rc, fd;
365
366 /* Prep work needed to test getf/releasef */
367 fd = get_unused_fd();
368 if (fd < 0) {
369 splat_vprint(file, SPLAT_VNODE_TEST7_NAME,
370 "Failed to get unused fd (%d)\n", fd);
371 return fd;
372 }
373
374 lfp = filp_open(SPLAT_VNODE_TEST_FILE_RW, O_RDWR|O_CREAT|O_EXCL, 0644);
375 if (IS_ERR(lfp)) {
376 put_unused_fd(fd);
377 rc = PTR_ERR(lfp);
378 splat_vprint(file, SPLAT_VNODE_TEST7_NAME,
379 "Failed to filp_open: %s (%d)\n",
380 SPLAT_VNODE_TEST_FILE_RW, rc);
381 return rc;
382 }
383
384 /* Pair up the new fd and lfp in the current context, this allows
385 * getf to lookup the file struct simply by the known open fd */
386 fd_install(fd, lfp);
387
388 /* Actual getf()/releasef() test */
389 fp = vn_getf(fd);
390 if (fp == NULL) {
391 rc = -EINVAL;
392 splat_vprint(file, SPLAT_VNODE_TEST7_NAME,
393 "Failed to getf fd %d: (%d)\n", fd, rc);
394 goto out;
395 }
396
397 rc = vn_rdwr(UIO_WRITE, fp->f_vnode, buf1, strlen(buf1), 0,
398 UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
399 if (rc < 0) {
400 splat_vprint(file, SPLAT_VNODE_TEST7_NAME,
401 "Failed vn_rdwr write of test file: %s (%d)\n",
402 SPLAT_VNODE_TEST_FILE_RW, rc);
403 goto out;
404 }
405
406 rc = vn_rdwr(UIO_READ, fp->f_vnode, buf2, strlen(buf1), 0,
407 UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
408 if (rc < 0) {
409 splat_vprint(file, SPLAT_VNODE_TEST7_NAME,
410 "Failed vn_rdwr read of test file: %s (%d)\n",
411 SPLAT_VNODE_TEST_FILE_RW, rc);
412 goto out;
413 }
414
415 if (strncmp(buf1, buf2, strlen(buf1))) {
416 rc = -EINVAL;
417 splat_vprint(file, SPLAT_VNODE_TEST7_NAME,
418 "Failed strncmp data written does not match "
419 "data read\nWrote: %sRead: %s\n", buf1, buf2);
420 goto out;
421 }
422
423 rc = 0;
424 splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Wrote: %s", buf1);
425 splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Read: %s", buf2);
426 splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Successfully wrote and "
427 "read expected data pattern to test file: %s\n",
428 SPLAT_VNODE_TEST_FILE_RW);
429out:
430 vn_releasef(fd);
431 fd_uninstall(fd);
432 filp_close(lfp, 0);
433 vn_remove(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE, RMFILE);
434
435 return rc;
436} /* splat_vnode_test7() */
4b171585 437
438splat_subsystem_t *
439splat_vnode_init(void)
440{
441 splat_subsystem_t *sub;
442
443 sub = kmalloc(sizeof(*sub), GFP_KERNEL);
444 if (sub == NULL)
445 return NULL;
446
447 memset(sub, 0, sizeof(*sub));
448 strncpy(sub->desc.name, SPLAT_VNODE_NAME, SPLAT_NAME_SIZE);
449 strncpy(sub->desc.desc, SPLAT_VNODE_DESC, SPLAT_DESC_SIZE);
450 INIT_LIST_HEAD(&sub->subsystem_list);
451 INIT_LIST_HEAD(&sub->test_list);
452 spin_lock_init(&sub->test_lock);
453 sub->desc.id = SPLAT_SUBSYSTEM_VNODE;
454
455 SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST1_NAME, SPLAT_VNODE_TEST1_DESC,
456 SPLAT_VNODE_TEST1_ID, splat_vnode_test1);
457 SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST2_NAME, SPLAT_VNODE_TEST2_DESC,
458 SPLAT_VNODE_TEST2_ID, splat_vnode_test2);
459 SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST3_NAME, SPLAT_VNODE_TEST3_DESC,
460 SPLAT_VNODE_TEST3_ID, splat_vnode_test3);
461 SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST4_NAME, SPLAT_VNODE_TEST4_DESC,
462 SPLAT_VNODE_TEST4_ID, splat_vnode_test4);
463 SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST5_NAME, SPLAT_VNODE_TEST5_DESC,
464 SPLAT_VNODE_TEST5_ID, splat_vnode_test5);
465 SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST6_NAME, SPLAT_VNODE_TEST6_DESC,
466 SPLAT_VNODE_TEST6_ID, splat_vnode_test6);
e4f1d29f 467 SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST7_NAME, SPLAT_VNODE_TEST7_DESC,
468 SPLAT_VNODE_TEST7_ID, splat_vnode_test7);
4b171585 469
470 return sub;
471} /* splat_vnode_init() */
472
473void
474splat_vnode_fini(splat_subsystem_t *sub)
475{
476 ASSERT(sub);
477
e4f1d29f 478 SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST7_ID);
4b171585 479 SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST6_ID);
480 SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST5_ID);
481 SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST4_ID);
482 SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST3_ID);
483 SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST2_ID);
484 SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST1_ID);
485
486 kfree(sub);
487} /* splat_vnode_fini() */
488
489int
490splat_vnode_id(void)
491{
492 return SPLAT_SUBSYSTEM_VNODE;
493} /* splat_vnode_id() */