18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2012 Red Hat.  All rights reserved.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#ifndef BTRFS_RCU_STRING_H
78c2ecf20Sopenharmony_ci#define BTRFS_RCU_STRING_H
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_cistruct rcu_string {
108c2ecf20Sopenharmony_ci	struct rcu_head rcu;
118c2ecf20Sopenharmony_ci	char str[];
128c2ecf20Sopenharmony_ci};
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic inline struct rcu_string *rcu_string_strdup(const char *src, gfp_t mask)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	size_t len = strlen(src) + 1;
178c2ecf20Sopenharmony_ci	struct rcu_string *ret = kzalloc(sizeof(struct rcu_string) +
188c2ecf20Sopenharmony_ci					 (len * sizeof(char)), mask);
198c2ecf20Sopenharmony_ci	if (!ret)
208c2ecf20Sopenharmony_ci		return ret;
218c2ecf20Sopenharmony_ci	/* Warn if the source got unexpectedly truncated. */
228c2ecf20Sopenharmony_ci	if (WARN_ON(strscpy(ret->str, src, len) < 0)) {
238c2ecf20Sopenharmony_ci		kfree(ret);
248c2ecf20Sopenharmony_ci		return NULL;
258c2ecf20Sopenharmony_ci	}
268c2ecf20Sopenharmony_ci	return ret;
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic inline void rcu_string_free(struct rcu_string *str)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	if (str)
328c2ecf20Sopenharmony_ci		kfree_rcu(str, rcu);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define printk_in_rcu(fmt, ...) do {	\
368c2ecf20Sopenharmony_ci	rcu_read_lock();		\
378c2ecf20Sopenharmony_ci	printk(fmt, __VA_ARGS__);	\
388c2ecf20Sopenharmony_ci	rcu_read_unlock();		\
398c2ecf20Sopenharmony_ci} while (0)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define printk_ratelimited_in_rcu(fmt, ...) do {	\
428c2ecf20Sopenharmony_ci	rcu_read_lock();				\
438c2ecf20Sopenharmony_ci	printk_ratelimited(fmt, __VA_ARGS__);		\
448c2ecf20Sopenharmony_ci	rcu_read_unlock();				\
458c2ecf20Sopenharmony_ci} while (0)
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define rcu_str_deref(rcu_str) ({				\
488c2ecf20Sopenharmony_ci	struct rcu_string *__str = rcu_dereference(rcu_str);	\
498c2ecf20Sopenharmony_ci	__str->str;						\
508c2ecf20Sopenharmony_ci})
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#endif
53