1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2012 Red Hat. All rights reserved. 4 */ 5 6 #ifndef BTRFS_RCU_STRING_H 7 #define BTRFS_RCU_STRING_H 8 9 #include <linux/types.h> 10 #include <linux/string.h> 11 #include <linux/slab.h> 12 #include <linux/rcupdate.h> 13 #include <linux/printk.h> 14 15 struct rcu_string { 16 struct rcu_head rcu; 17 char str[]; 18 }; 19 20 static inline struct rcu_string *rcu_string_strdup(const char *src, gfp_t mask) 21 { 22 size_t len = strlen(src) + 1; 23 struct rcu_string *ret = kzalloc(sizeof(struct rcu_string) + 24 (len * sizeof(char)), mask); 25 if (!ret) 26 return ret; 27 /* Warn if the source got unexpectedly truncated. */ 28 if (WARN_ON(strscpy(ret->str, src, len) < 0)) { 29 kfree(ret); 30 return NULL; 31 } 32 return ret; 33 } 34 35 static inline void rcu_string_free(struct rcu_string *str) 36 { 37 if (str) 38 kfree_rcu(str, rcu); 39 } 40 41 #define printk_in_rcu(fmt, ...) do { \ 42 rcu_read_lock(); \ 43 printk(fmt, __VA_ARGS__); \ 44 rcu_read_unlock(); \ 45 } while (0) 46 47 #define printk_ratelimited_in_rcu(fmt, ...) do { \ 48 rcu_read_lock(); \ 49 printk_ratelimited(fmt, __VA_ARGS__); \ 50 rcu_read_unlock(); \ 51 } while (0) 52 53 #define rcu_str_deref(rcu_str) ({ \ 54 struct rcu_string *__str = rcu_dereference(rcu_str); \ 55 __str->str; \ 56 }) 57 58 #endif 59