4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
24 * Copyright 2017 Cray Inc. All rights reserved.
28 /* Check that the inode number is the same whether the call to
29 * vfs_getattr is coming from a system call or from a kthread. When
30 * CONFIG_X86_X32 was set, the result used to be different for
31 * Lustre. In addition, a user can also check that the same inode
32 * number is also seen from the kernel and userspace. */
34 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/completion.h>
37 #include <linux/kthread.h>
39 #include <linux/version.h>
41 /* Random ID passed by userspace, and printed in messages, used to
42 * separate different runs of that module. */
44 module_param(run_id, int, 0644);
45 MODULE_PARM_DESC(run_id, "run ID");
47 /* Name of the file to stat. */
48 static char fname[4096];
49 module_param_string(fname, fname, sizeof(fname), 0644);
50 MODULE_PARM_DESC(fname, "name of file to stat");
52 static DECLARE_COMPLETION(thr_start);
54 #define PREFIX "lustre_kinode_%u:"
56 static int stat_file(struct kstat *stbuf)
61 fd = filp_open(fname, O_RDONLY, 0);
63 pr_err(PREFIX " can't open file %s\n", run_id, fname);
67 #ifdef HAVE_INODEOPS_ENHANCED_GETATTR
68 rc = vfs_getattr(&fd->f_path, stbuf, STATX_INO, AT_STATX_SYNC_AS_STAT);
69 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
70 rc = vfs_getattr(&fd->f_path, stbuf);
72 rc = vfs_getattr(fd->f_path.mnt, fd->f_path.dentry, stbuf);
75 pr_err(PREFIX " vfs_getattr failed: %d\n", run_id, rc);
79 pr_err(PREFIX " inode is %llu\n", run_id, stbuf->ino);
88 static int stat_thread(void *data)
90 struct kstat *stbuf = data;
93 /* Signal caller that thread has started. */
96 rc = stat_file(stbuf);
98 /* Wait for call to kthread_stop. */
99 set_current_state(TASK_INTERRUPTIBLE);
100 while (!kthread_should_stop()) {
102 set_current_state(TASK_INTERRUPTIBLE);
104 set_current_state(TASK_RUNNING);
109 static int __init kinode_init(void)
111 struct task_struct *thr;
116 #ifdef CONFIG_X86_X32
117 pr_err(PREFIX " CONFIG_X86_X32 is set\n", run_id);
119 pr_err(PREFIX " CONFIG_X86_X32 is not set\n", run_id);
122 if (strlen(fname) < 1) {
123 pr_err(PREFIX " invalid file name '%s'\n", run_id, fname);
127 rc = stat_file(&stbuf1);
129 pr_err(PREFIX " direct stat failed: %d\n", run_id, rc);
133 /* Run the same from a kthread. */
134 thr = kthread_run(stat_thread, &stbuf2, "kinode_%u", run_id);
136 pr_err(PREFIX " Cannot create kthread\n", run_id);
140 /* Wait for the thread to start, then wait for it to
142 wait_for_completion(&thr_start);
143 rc = kthread_stop(thr);
145 pr_err(PREFIX " indirect stat failed: %d\n", run_id, rc);
149 if (stbuf1.ino != stbuf2.ino)
150 pr_err(PREFIX " inode numbers are different: %llu %llu\n",
151 run_id, stbuf1.ino, stbuf2.ino);
153 pr_err(PREFIX " inode numbers are identical: %llu\n",
161 static void __exit kinode_exit(void)
165 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
166 MODULE_DESCRIPTION("Lustre inode stat test module");
167 MODULE_VERSION(LUSTRE_VERSION_STRING);
168 MODULE_LICENSE("GPL");
170 module_init(kinode_init);
171 module_exit(kinode_exit);