1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright 2017 Cray Inc. All rights reserved.
9 * This file is part of Lustre, http://www.lustre.org/
11 * lustre/kunit/kinode.c
13 * Check that the inode number is the same whether the call to
14 * vfs_getattr is coming from a system call or from a kthread. When
15 * CONFIG_X86_X32 was set, the result used to be different for
16 * Lustre. In addition, a user can also check that the same inode
17 * number is also seen from the kernel and userspace.
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/completion.h>
26 #include <linux/kthread.h>
28 #include <linux/version.h>
30 /* Random ID passed by userspace, and printed in messages, used to
31 * separate different runs of that module. */
33 module_param(run_id, int, 0644);
34 MODULE_PARM_DESC(run_id, "run ID");
36 /* Name of the file to stat. */
37 static char fname[4096];
38 module_param_string(fname, fname, sizeof(fname), 0644);
39 MODULE_PARM_DESC(fname, "name of file to stat");
41 static DECLARE_COMPLETION(thr_start);
43 #define PREFIX "lustre_kinode_%u:"
45 static int stat_file(struct kstat *stbuf)
50 fd = filp_open(fname, O_RDONLY, 0);
52 pr_err(PREFIX " can't open file %s\n", run_id, fname);
56 #if defined(HAVE_USER_NAMESPACE_ARG) || defined(HAVE_INODEOPS_ENHANCED_GETATTR)
57 rc = vfs_getattr(&fd->f_path, stbuf, STATX_INO, AT_STATX_SYNC_AS_STAT);
58 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
59 rc = vfs_getattr(&fd->f_path, stbuf);
61 rc = vfs_getattr(fd->f_path.mnt, fd->f_path.dentry, stbuf);
64 pr_err(PREFIX " vfs_getattr failed: %d\n", run_id, rc);
68 pr_err(PREFIX " inode is %llu\n", run_id, stbuf->ino);
77 static int stat_thread(void *data)
79 struct kstat *stbuf = data;
82 /* Signal caller that thread has started. */
85 rc = stat_file(stbuf);
87 /* Wait for call to kthread_stop. */
88 set_current_state(TASK_INTERRUPTIBLE);
89 while (!kthread_should_stop()) {
91 set_current_state(TASK_INTERRUPTIBLE);
93 set_current_state(TASK_RUNNING);
98 static int __init kinode_init(void)
100 struct task_struct *thr;
105 #ifdef CONFIG_X86_X32
106 pr_err(PREFIX " CONFIG_X86_X32 is set\n", run_id);
108 pr_err(PREFIX " CONFIG_X86_X32 is not set\n", run_id);
111 if (strlen(fname) < 1) {
112 pr_err(PREFIX " invalid file name '%s'\n", run_id, fname);
116 rc = stat_file(&stbuf1);
118 pr_err(PREFIX " direct stat failed: %d\n", run_id, rc);
122 /* Run the same from a kthread. */
123 thr = kthread_run(stat_thread, &stbuf2, "kinode_%u", run_id);
125 pr_err(PREFIX " Cannot create kthread\n", run_id);
129 /* Wait for the thread to start, then wait for it to
131 wait_for_completion(&thr_start);
132 rc = kthread_stop(thr);
134 pr_err(PREFIX " indirect stat failed: %d\n", run_id, rc);
138 if (stbuf1.ino != stbuf2.ino)
139 pr_err(PREFIX " inode numbers are different: %llu %llu\n",
140 run_id, stbuf1.ino, stbuf2.ino);
142 /* below message is checked in sanity.sh test_129 */
143 pr_err(PREFIX " inode numbers are identical: %llu\n",
151 static void __exit kinode_exit(void)
155 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
156 MODULE_DESCRIPTION("Lustre inode stat test module");
157 MODULE_VERSION(LUSTRE_VERSION_STRING);
158 MODULE_LICENSE("GPL");
160 module_init(kinode_init);
161 module_exit(kinode_exit);