Whamcloud - gitweb
LU-9859 libcfs: refactor libcfs initialization.
[fs/lustre-release.git] / libcfs / libcfs / linux / linux-prim.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2013, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  */
31
32 #define DEBUG_SUBSYSTEM S_LNET
33
34 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/fs.h>
37 #include <linux/sched.h>
38 #ifdef HAVE_SCHED_HEADERS
39 #include <linux/sched/mm.h>
40 #endif
41 #include <linux/slab.h>
42 #include <linux/uaccess.h>
43 #include <net/netlink.h>
44
45 #if defined(CONFIG_KGDB)
46 #include <asm/kgdb.h>
47 #endif
48
49 #include <lustre_compat.h>
50 #include <libcfs/crypto/llcrypt.h>
51 #include <libcfs/linux/linux-time.h>
52 #include <libcfs/linux/linux-wait.h>
53 #include <libcfs/linux/linux-misc.h>
54 #include <libcfs/linux/linux-mem.h>
55 #ifndef HAVE_XARRAY_SUPPORT
56 #include <libcfs/linux/xarray.h>
57 #endif
58
59 #ifndef HAVE_KTIME_GET_TS64
60 void ktime_get_ts64(struct timespec64 *ts)
61 {
62         struct timespec now;
63
64         ktime_get_ts(&now);
65         *ts = timespec_to_timespec64(now);
66 }
67 EXPORT_SYMBOL(ktime_get_ts64);
68 #endif /* HAVE_KTIME_GET_TS64 */
69
70 #ifndef HAVE_KTIME_GET_REAL_TS64
71 void ktime_get_real_ts64(struct timespec64 *ts)
72 {
73         struct timespec now;
74
75         getnstimeofday(&now);
76         *ts = timespec_to_timespec64(now);
77 }
78 EXPORT_SYMBOL(ktime_get_real_ts64);
79 #endif /* HAVE_KTIME_GET_REAL_TS64 */
80
81 #ifndef HAVE_KTIME_GET_REAL_SECONDS
82 /*
83  * Get the seconds portion of CLOCK_REALTIME (wall clock).
84  * This is the clock that can be altered by NTP and is
85  * independent of a reboot.
86  */
87 time64_t ktime_get_real_seconds(void)
88 {
89         return (time64_t)get_seconds();
90 }
91 EXPORT_SYMBOL(ktime_get_real_seconds);
92 #endif /* HAVE_KTIME_GET_REAL_SECONDS */
93
94 #ifndef HAVE_KTIME_GET_SECONDS
95 /*
96  * Get the seconds portion of CLOCK_MONOTONIC
97  * This clock is immutable and is reset across
98  * reboots. For older platforms this is a
99  * wrapper around get_seconds which is valid
100  * until 2038. By that time this will be gone
101  * one would hope.
102  */
103 time64_t ktime_get_seconds(void)
104 {
105         struct timespec64 now;
106
107         ktime_get_ts64(&now);
108         return now.tv_sec;
109 }
110 EXPORT_SYMBOL(ktime_get_seconds);
111 #endif /* HAVE_KTIME_GET_SECONDS */
112
113 static int (*cfs_apply_workqueue_attrs_t)(struct workqueue_struct *wq,
114                                           const struct workqueue_attrs *attrs);
115
116 int cfs_apply_workqueue_attrs(struct workqueue_struct *wq,
117                               const struct workqueue_attrs *attrs)
118 {
119         if (cfs_apply_workqueue_attrs_t)
120                 return cfs_apply_workqueue_attrs_t(wq, attrs);
121         return 0;
122 }
123 EXPORT_SYMBOL_GPL(cfs_apply_workqueue_attrs);
124
125 /* Linux v5.1-rc5 214d8ca6ee ("stacktrace: Provide common infrastructure")
126  * CONFIG_ARCH_STACKWALK indicates that save_stack_trace_tsk symbol is not
127  * exported. Use symbol_get() to find if save_stack_trace_tsk is available.
128  */
129 #ifdef CONFIG_ARCH_STACKWALK
130 static unsigned int (*task_dump_stack_t)(struct task_struct *task,
131                                          unsigned long *store,
132                                          unsigned int size,
133                                          unsigned int skipnr);
134
135 int cfs_stack_trace_save_tsk(struct task_struct *task, unsigned long *store,
136                              unsigned int size, unsigned int skipnr)
137 {
138         if (task_dump_stack_t)
139                 return task_dump_stack_t(task, store, size, skipnr);
140         return 0;
141 }
142 #endif
143
144 #ifndef HAVE_XARRAY_SUPPORT
145 struct kmem_cache *xarray_cachep;
146
147 static void xarray_node_ctor(void *arg)
148 {
149         struct xa_node *node = arg;
150
151         memset(node, 0, sizeof(*node));
152         INIT_LIST_HEAD(&node->private_list);
153 }
154 #endif
155
156 /*
157  * This is opencoding of vfree_atomic from Linux kernel added in 4.10 with
158  * minimum changes needed to work on older kernels too.
159  */
160
161 #ifndef llist_for_each_safe
162 #define llist_for_each_safe(pos, n, node)                       \
163         for ((pos) = (node); (pos) && ((n) = (pos)->next, true); (pos) = (n))
164 #endif
165
166 struct vfree_deferred {
167         struct llist_head list;
168         struct work_struct wq;
169 };
170 static DEFINE_PER_CPU(struct vfree_deferred, vfree_deferred);
171
172 static void free_work(struct work_struct *w)
173 {
174         struct vfree_deferred *p = container_of(w, struct vfree_deferred, wq);
175         struct llist_node *t, *llnode;
176
177         llist_for_each_safe(llnode, t, llist_del_all(&p->list))
178                 vfree((void *)llnode);
179 }
180
181 void libcfs_vfree_atomic(const void *addr)
182 {
183         struct vfree_deferred *p = raw_cpu_ptr(&vfree_deferred);
184
185         if (!addr)
186                 return;
187
188         if (llist_add((struct llist_node *)addr, &p->list))
189                 schedule_work(&p->wq);
190 }
191 EXPORT_SYMBOL(libcfs_vfree_atomic);
192
193 void __init init_libcfs_vfree_atomic(void)
194 {
195         int i;
196
197         for_each_possible_cpu(i) {
198                 struct vfree_deferred *p;
199
200                 p = &per_cpu(vfree_deferred, i);
201                 init_llist_head(&p->list);
202                 INIT_WORK(&p->wq, free_work);
203         }
204 }
205
206 int __init cfs_arch_init(void)
207 {
208         init_libcfs_vfree_atomic();
209
210 #ifndef HAVE_WAIT_VAR_EVENT
211         wait_bit_init();
212 #endif
213 #ifdef CONFIG_ARCH_STACKWALK
214         task_dump_stack_t =
215                 (void *)cfs_kallsyms_lookup_name("stack_trace_save_tsk");
216 #endif
217         cfs_apply_workqueue_attrs_t =
218                 (void *)cfs_kallsyms_lookup_name("apply_workqueue_attrs");
219 #ifndef HAVE_XARRAY_SUPPORT
220         xarray_cachep = kmem_cache_create("xarray_cache",
221                                           sizeof(struct xa_node), 0,
222                                           SLAB_PANIC | SLAB_RECLAIM_ACCOUNT,
223                                           xarray_node_ctor);
224 #endif
225         return llcrypt_init();
226 }
227
228 void __exit cfs_arch_exit(void)
229 {
230         /* exit_libcfs_vfree_atomic */
231         flush_scheduled_work();
232
233         llcrypt_exit();
234 }
235
236 int cfs_kernel_write(struct file *filp, const void *buf, size_t count,
237                      loff_t *pos)
238 {
239 #ifdef HAVE_NEW_KERNEL_WRITE
240         return kernel_write(filp, buf, count, pos);
241 #else
242         mm_segment_t __old_fs = get_fs();
243         int rc;
244
245         set_fs(KERNEL_DS);
246         rc = vfs_write(filp, (__force const char __user *)buf, count, pos);
247         set_fs(__old_fs);
248
249         return rc;
250 #endif
251 }
252 EXPORT_SYMBOL(cfs_kernel_write);
253
254 ssize_t cfs_kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
255 {
256 #ifdef HAVE_KERNEL_READ_LAST_POSP
257         return kernel_read(file, buf, count, pos);
258 #else
259         ssize_t size = kernel_read(file, *pos, buf, count);
260
261         if (size > 0)
262                 *pos += size;
263         return size;
264 #endif
265 }
266 EXPORT_SYMBOL(cfs_kernel_read);
267
268 #ifndef HAVE_KSET_FIND_OBJ
269 struct kobject *kset_find_obj(struct kset *kset, const char *name)
270 {
271         struct kobject *ret = NULL;
272         struct kobject *k;
273
274         spin_lock(&kset->list_lock);
275
276         list_for_each_entry(k, &kset->list, entry) {
277                 if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
278                         if (kref_get_unless_zero(&k->kref))
279                                 ret = k;
280                         break;
281                 }
282         }
283
284         spin_unlock(&kset->list_lock);
285         return ret;
286 }
287 EXPORT_SYMBOL_GPL(kset_find_obj);
288 #endif
289
290 #ifndef HAVE_MATCH_WILDCARD
291 /**
292  * match_wildcard: - parse if a string matches given wildcard pattern
293  * @pattern: wildcard pattern
294  * @str: the string to be parsed
295  *
296  * Description: Parse the string @str to check if matches wildcard
297  * pattern @pattern. The pattern may contain two type wildcardes:
298  *   '*' - matches zero or more characters
299  *   '?' - matches one character
300  * If it's matched, return true, else return false.
301  */
302 bool match_wildcard(const char *pattern, const char *str)
303 {
304         const char *s = str;
305         const char *p = pattern;
306         bool star = false;
307
308         while (*s) {
309                 switch (*p) {
310                 case '?':
311                         s++;
312                         p++;
313                         break;
314                 case '*':
315                         star = true;
316                         str = s;
317                         if (!*++p)
318                                 return true;
319                         pattern = p;
320                         break;
321                 default:
322                         if (*s == *p) {
323                                 s++;
324                                 p++;
325                         } else {
326                                 if (!star)
327                                         return false;
328                                 str++;
329                                 s = str;
330                                 p = pattern;
331                         }
332                         break;
333                 }
334         }
335
336         if (*p == '*')
337                 ++p;
338         return !*p;
339 }
340 EXPORT_SYMBOL(match_wildcard);
341 #endif /* !HAVE_MATCH_WILDCARD */
342
343 #ifndef HAVE_BITMAP_TO_ARR32
344 /**
345  * bitmap_to_arr32 - copy the contents of bitmap to a u32 array of bits
346  *      @buf: array of u32 (in host byte order), the dest bitmap
347  *      @bitmap: array of unsigned longs, the source bitmap
348  *      @nbits: number of bits in @bitmap
349  */
350 void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap, unsigned int nbits)
351 {
352         unsigned int i, halfwords;
353
354         halfwords = DIV_ROUND_UP(nbits, 32);
355         for (i = 0; i < halfwords; i++) {
356                 buf[i] = (u32) (bitmap[i/2] & UINT_MAX);
357                 if (++i < halfwords)
358                         buf[i] = (u32) (bitmap[i/2] >> 32);
359         }
360
361         /* Clear tail bits in last element of array beyond nbits. */
362         if (nbits % BITS_PER_LONG)
363                 buf[halfwords - 1] &= (u32) (UINT_MAX >> ((-nbits) & 31));
364 }
365 EXPORT_SYMBOL(bitmap_to_arr32);
366 #endif /* !HAVE_BITMAP_TO_ARR32 */
367
368 #ifndef HAVE_KSTRTOBOOL_FROM_USER
369 int kstrtobool_from_user(const char __user *s, size_t count, bool *res)
370 {
371         /* Longest string needed to differentiate, newline, terminator */
372         char buf[4];
373
374         count = min(count, sizeof(buf) - 1);
375         if (copy_from_user(buf, s, count))
376                 return -EFAULT;
377         buf[count] = '\0';
378         return strtobool(buf, res);
379 }
380 EXPORT_SYMBOL(kstrtobool_from_user);
381 #endif /* !HAVE_KSTRTOBOOL_FROM_USER */
382
383 #ifndef HAVE_NLA_STRDUP
384 char *nla_strdup(const struct nlattr *nla, gfp_t flags)
385 {
386         size_t srclen = nla_len(nla);
387         char *src = nla_data(nla), *dst;
388
389         if (srclen > 0 && src[srclen - 1] == '\0')
390                 srclen--;
391
392         dst = kmalloc(srclen + 1, flags);
393         if (dst != NULL) {
394                 memcpy(dst, src, srclen);
395                 dst[srclen] = '\0';
396         }
397         return dst;
398 }
399 EXPORT_SYMBOL(nla_strdup);
400 #endif /* !HAVE_NLA_STRDUP */