162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2012 Red Hat.  All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef BTRFS_RCU_STRING_H
762306a36Sopenharmony_ci#define BTRFS_RCU_STRING_H
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistruct rcu_string {
1062306a36Sopenharmony_ci	struct rcu_head rcu;
1162306a36Sopenharmony_ci	char str[];
1262306a36Sopenharmony_ci};
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistatic inline struct rcu_string *rcu_string_strdup(const char *src, gfp_t mask)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	size_t len = strlen(src) + 1;
1762306a36Sopenharmony_ci	struct rcu_string *ret = kzalloc(sizeof(struct rcu_string) +
1862306a36Sopenharmony_ci					 (len * sizeof(char)), mask);
1962306a36Sopenharmony_ci	if (!ret)
2062306a36Sopenharmony_ci		return ret;
2162306a36Sopenharmony_ci	/* Warn if the source got unexpectedly truncated. */
2262306a36Sopenharmony_ci	if (WARN_ON(strscpy(ret->str, src, len) < 0)) {
2362306a36Sopenharmony_ci		kfree(ret);
2462306a36Sopenharmony_ci		return NULL;
2562306a36Sopenharmony_ci	}
2662306a36Sopenharmony_ci	return ret;
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic inline void rcu_string_free(struct rcu_string *str)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	if (str)
3262306a36Sopenharmony_ci		kfree_rcu(str, rcu);
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define printk_in_rcu(fmt, ...) do {	\
3662306a36Sopenharmony_ci	rcu_read_lock();		\
3762306a36Sopenharmony_ci	printk(fmt, __VA_ARGS__);	\
3862306a36Sopenharmony_ci	rcu_read_unlock();		\
3962306a36Sopenharmony_ci} while (0)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define printk_ratelimited_in_rcu(fmt, ...) do {	\
4262306a36Sopenharmony_ci	rcu_read_lock();				\
4362306a36Sopenharmony_ci	printk_ratelimited(fmt, __VA_ARGS__);		\
4462306a36Sopenharmony_ci	rcu_read_unlock();				\
4562306a36Sopenharmony_ci} while (0)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define rcu_str_deref(rcu_str) ({				\
4862306a36Sopenharmony_ci	struct rcu_string *__str = rcu_dereference(rcu_str);	\
4962306a36Sopenharmony_ci	__str->str;						\
5062306a36Sopenharmony_ci})
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#endif
53