Whamcloud - gitweb
LU-17744 ldiskfs: mballoc stats fixes
[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
141         pr_info("No stack, save_stack_trace_tsk() could not be found\n");
142
143         return 0;
144 }
145 #endif
146
147 #ifndef HAVE_XARRAY_SUPPORT
148 struct kmem_cache *xarray_cachep;
149
150 static void xarray_node_ctor(void *arg)
151 {
152         struct xa_node *node = arg;
153
154         memset(node, 0, sizeof(*node));
155         INIT_LIST_HEAD(&node->private_list);
156 }
157 #endif
158
159 /*
160  * This is opencoding of vfree_atomic from Linux kernel added in 4.10 with
161  * minimum changes needed to work on older kernels too.
162  */
163
164 #ifndef llist_for_each_safe
165 #define llist_for_each_safe(pos, n, node)                       \
166         for ((pos) = (node); (pos) && ((n) = (pos)->next, true); (pos) = (n))
167 #endif
168
169 struct vfree_deferred {
170         struct llist_head list;
171         struct work_struct wq;
172 };
173 static DEFINE_PER_CPU(struct vfree_deferred, vfree_deferred);
174
175 static void free_work(struct work_struct *w)
176 {
177         struct vfree_deferred *p = container_of(w, struct vfree_deferred, wq);
178         struct llist_node *t, *llnode;
179
180         llist_for_each_safe(llnode, t, llist_del_all(&p->list))
181                 vfree((void *)llnode);
182 }
183
184 void libcfs_vfree_atomic(const void *addr)
185 {
186         struct vfree_deferred *p = raw_cpu_ptr(&vfree_deferred);
187
188         if (!addr)
189                 return;
190
191         if (llist_add((struct llist_node *)addr, &p->list))
192                 schedule_work(&p->wq);
193 }
194 EXPORT_SYMBOL(libcfs_vfree_atomic);
195
196 void __init init_libcfs_vfree_atomic(void)
197 {
198         int i;
199
200         for_each_possible_cpu(i) {
201                 struct vfree_deferred *p;
202
203                 p = &per_cpu(vfree_deferred, i);
204                 init_llist_head(&p->list);
205                 INIT_WORK(&p->wq, free_work);
206         }
207 }
208
209 int __init cfs_arch_init(void)
210 {
211         init_libcfs_vfree_atomic();
212
213 #ifndef HAVE_WAIT_VAR_EVENT
214         wait_bit_init();
215 #endif
216 #ifdef CONFIG_ARCH_STACKWALK
217         task_dump_stack_t =
218                 (void *)cfs_kallsyms_lookup_name("stack_trace_save_tsk");
219 #endif
220         cfs_apply_workqueue_attrs_t =
221                 (void *)cfs_kallsyms_lookup_name("apply_workqueue_attrs");
222 #ifndef HAVE_XARRAY_SUPPORT
223         xarray_cachep = kmem_cache_create("xarray_cache",
224                                           sizeof(struct xa_node), 0,
225                                           SLAB_PANIC | SLAB_RECLAIM_ACCOUNT,
226                                           xarray_node_ctor);
227 #endif
228         return llcrypt_init();
229 }
230
231 void __exit cfs_arch_exit(void)
232 {
233         /* exit_libcfs_vfree_atomic */
234         __flush_workqueue(system_wq);
235
236         llcrypt_exit();
237 }
238
239 int cfs_kernel_write(struct file *filp, const void *buf, size_t count,
240                      loff_t *pos)
241 {
242 #ifdef HAVE_NEW_KERNEL_WRITE
243         return kernel_write(filp, buf, count, pos);
244 #else
245         mm_segment_t __old_fs = get_fs();
246         int rc;
247
248         set_fs(KERNEL_DS);
249         rc = vfs_write(filp, (__force const char __user *)buf, count, pos);
250         set_fs(__old_fs);
251
252         return rc;
253 #endif
254 }
255 EXPORT_SYMBOL(cfs_kernel_write);
256
257 ssize_t cfs_kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
258 {
259 #ifdef HAVE_KERNEL_READ_LAST_POSP
260         return kernel_read(file, buf, count, pos);
261 #else
262         ssize_t size = kernel_read(file, *pos, buf, count);
263
264         if (size > 0)
265                 *pos += size;
266         return size;
267 #endif
268 }
269 EXPORT_SYMBOL(cfs_kernel_read);
270
271 #ifndef HAVE_KSET_FIND_OBJ
272 struct kobject *kset_find_obj(struct kset *kset, const char *name)
273 {
274         struct kobject *ret = NULL;
275         struct kobject *k;
276
277         spin_lock(&kset->list_lock);
278
279         list_for_each_entry(k, &kset->list, entry) {
280                 if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
281                         if (kref_get_unless_zero(&k->kref))
282                                 ret = k;
283                         break;
284                 }
285         }
286
287         spin_unlock(&kset->list_lock);
288         return ret;
289 }
290 EXPORT_SYMBOL_GPL(kset_find_obj);
291 #endif
292
293 #ifndef HAVE_MATCH_WILDCARD
294 /**
295  * match_wildcard: - parse if a string matches given wildcard pattern
296  * @pattern: wildcard pattern
297  * @str: the string to be parsed
298  *
299  * Description: Parse the string @str to check if matches wildcard
300  * pattern @pattern. The pattern may contain two type wildcardes:
301  *   '*' - matches zero or more characters
302  *   '?' - matches one character
303  * If it's matched, return true, else return false.
304  */
305 bool match_wildcard(const char *pattern, const char *str)
306 {
307         const char *s = str;
308         const char *p = pattern;
309         bool star = false;
310
311         while (*s) {
312                 switch (*p) {
313                 case '?':
314                         s++;
315                         p++;
316                         break;
317                 case '*':
318                         star = true;
319                         str = s;
320                         if (!*++p)
321                                 return true;
322                         pattern = p;
323                         break;
324                 default:
325                         if (*s == *p) {
326                                 s++;
327                                 p++;
328                         } else {
329                                 if (!star)
330                                         return false;
331                                 str++;
332                                 s = str;
333                                 p = pattern;
334                         }
335                         break;
336                 }
337         }
338
339         if (*p == '*')
340                 ++p;
341         return !*p;
342 }
343 EXPORT_SYMBOL(match_wildcard);
344 #endif /* !HAVE_MATCH_WILDCARD */
345
346 #ifndef HAVE_BITMAP_TO_ARR32
347 /**
348  * bitmap_to_arr32 - copy the contents of bitmap to a u32 array of bits
349  *      @buf: array of u32 (in host byte order), the dest bitmap
350  *      @bitmap: array of unsigned longs, the source bitmap
351  *      @nbits: number of bits in @bitmap
352  */
353 void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap, unsigned int nbits)
354 {
355         unsigned int i, halfwords;
356
357         halfwords = DIV_ROUND_UP(nbits, 32);
358         for (i = 0; i < halfwords; i++) {
359                 buf[i] = (u32) (bitmap[i/2] & UINT_MAX);
360                 if (++i < halfwords)
361                         buf[i] = (u32) (bitmap[i/2] >> 32);
362         }
363
364         /* Clear tail bits in last element of array beyond nbits. */
365         if (nbits % BITS_PER_LONG)
366                 buf[halfwords - 1] &= (u32) (UINT_MAX >> ((-nbits) & 31));
367 }
368 EXPORT_SYMBOL(bitmap_to_arr32);
369 #endif /* !HAVE_BITMAP_TO_ARR32 */
370
371 #ifndef HAVE_KSTRTOBOOL_FROM_USER
372 int kstrtobool_from_user(const char __user *s, size_t count, bool *res)
373 {
374         /* Longest string needed to differentiate, newline, terminator */
375         char buf[4];
376
377         count = min(count, sizeof(buf) - 1);
378         if (copy_from_user(buf, s, count))
379                 return -EFAULT;
380         buf[count] = '\0';
381         return strtobool(buf, res);
382 }
383 EXPORT_SYMBOL(kstrtobool_from_user);
384 #endif /* !HAVE_KSTRTOBOOL_FROM_USER */
385
386 #ifndef HAVE_NLA_STRDUP
387 char *nla_strdup(const struct nlattr *nla, gfp_t flags)
388 {
389         size_t srclen = nla_len(nla);
390         char *src = nla_data(nla), *dst;
391
392         if (srclen > 0 && src[srclen - 1] == '\0')
393                 srclen--;
394
395         dst = kmalloc(srclen + 1, flags);
396         if (dst != NULL) {
397                 memcpy(dst, src, srclen);
398                 dst[srclen] = '\0';
399         }
400         return dst;
401 }
402 EXPORT_SYMBOL(nla_strdup);
403 #endif /* !HAVE_NLA_STRDUP */