Whamcloud - gitweb
LU-6142 mdd: Fix style issues for mdd_device.c
[fs/lustre-release.git] / lustre / kunit / kinode.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /*
4  * Copyright 2017 Cray Inc. All rights reserved.
5  *
6  */
7
8 /*
9  * This file is part of Lustre, http://www.lustre.org/
10  *
11  * lustre/kunit/kinode.c
12  *
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.
18  *
19  * Author: Frank Zago
20  *
21  */
22
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/completion.h>
26 #include <linux/kthread.h>
27 #include <linux/fs.h>
28 #include <linux/version.h>
29
30 /* Random ID passed by userspace, and printed in messages, used to
31  * separate different runs of that module. */
32 static int run_id;
33 module_param(run_id, int, 0644);
34 MODULE_PARM_DESC(run_id, "run ID");
35
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");
40
41 static DECLARE_COMPLETION(thr_start);
42
43 #define PREFIX "lustre_kinode_%u:"
44
45 static int stat_file(struct kstat *stbuf)
46 {
47         struct file *fd;
48         int rc;
49
50         fd = filp_open(fname, O_RDONLY, 0);
51         if (IS_ERR(fd)) {
52                 pr_err(PREFIX " can't open file %s\n", run_id, fname);
53                 return -EIO;
54         }
55
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);
60 #else
61         rc = vfs_getattr(fd->f_path.mnt, fd->f_path.dentry, stbuf);
62 #endif
63         if (rc != 0) {
64                 pr_err(PREFIX " vfs_getattr failed: %d\n", run_id, rc);
65                 goto out;
66         }
67
68         pr_err(PREFIX " inode is %llu\n", run_id, stbuf->ino);
69         rc = 0;
70
71 out:
72         filp_close(fd, NULL);
73
74         return rc;
75 }
76
77 static int stat_thread(void *data)
78 {
79         struct kstat *stbuf = data;
80         int rc;
81
82         /* Signal caller that thread has started. */
83         complete(&thr_start);
84
85         rc = stat_file(stbuf);
86
87         /* Wait for call to kthread_stop. */
88         set_current_state(TASK_INTERRUPTIBLE);
89         while (!kthread_should_stop()) {
90                 schedule();
91                 set_current_state(TASK_INTERRUPTIBLE);
92         }
93         set_current_state(TASK_RUNNING);
94
95         return rc;
96 }
97
98 static int __init kinode_init(void)
99 {
100         struct task_struct *thr;
101         struct kstat stbuf1;
102         struct kstat stbuf2;
103         int rc;
104
105 #ifdef CONFIG_X86_X32
106         pr_err(PREFIX " CONFIG_X86_X32 is set\n", run_id);
107 #else
108         pr_err(PREFIX " CONFIG_X86_X32 is not set\n", run_id);
109 #endif
110
111         if (strlen(fname) < 1) {
112                 pr_err(PREFIX " invalid file name '%s'\n", run_id, fname);
113                 goto out;
114         }
115
116         rc = stat_file(&stbuf1);
117         if (rc) {
118                 pr_err(PREFIX " direct stat failed: %d\n", run_id, rc);
119                 goto out;
120         }
121
122         /* Run the same from a kthread. */
123         thr = kthread_run(stat_thread, &stbuf2, "kinode_%u", run_id);
124         if (IS_ERR(thr)) {
125                 pr_err(PREFIX " Cannot create kthread\n", run_id);
126                 goto out;
127         }
128
129         /* Wait for the thread to start, then wait for it to
130          * terminate. */
131         wait_for_completion(&thr_start);
132         rc = kthread_stop(thr);
133         if (rc) {
134                 pr_err(PREFIX " indirect stat failed: %d\n", run_id, rc);
135                 goto out;
136         }
137
138         if (stbuf1.ino != stbuf2.ino)
139                 pr_err(PREFIX " inode numbers are different: %llu %llu\n",
140                        run_id, stbuf1.ino, stbuf2.ino);
141         else
142                 /* below message is checked in sanity.sh test_129 */
143                 pr_err(PREFIX " inode numbers are identical: %llu\n",
144                        run_id, stbuf1.ino);
145
146 out:
147         /* Don't load. */
148         return -EINVAL;
149 }
150
151 static void __exit kinode_exit(void)
152 {
153 }
154
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");
159
160 module_init(kinode_init);
161 module_exit(kinode_exit);