scoutfs: add SK_ helpers for printing keys

Add some percpu string buffers so that we can pass formatted strings as
arguments when printing keys.  The percpu struct uses a different buffer
for each argument.  We wrap the whole print call in a wrapper that
disables and enables preemption.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2017-06-06 14:48:09 -07:00
parent a050152254
commit 1485b02554
2 changed files with 82 additions and 2 deletions
+53 -2
View File
@@ -116,9 +116,8 @@ void scoutfs_key_dec(struct scoutfs_key_buf *key)
*
* XXX nonprintable characters in the trace?
*/
int scoutfs_key_str(char *buf, struct scoutfs_key_buf *key)
int scoutfs_key_str_size(char *buf, struct scoutfs_key_buf *key, size_t size)
{
size_t size = buf ? INT_MAX : 0;
int len;
u8 type;
@@ -170,3 +169,55 @@ int scoutfs_key_str(char *buf, struct scoutfs_key_buf *key)
return snprintf_null(buf, size, "[truncated type %u len %u]",
type, key->key_len);
}
/*
* A null buf can be set to find the length of the formatted string.
*/
int scoutfs_key_str(char *buf, struct scoutfs_key_buf *key)
{
return scoutfs_key_str_size(buf, key, buf ? INT_MAX : 0);
}
#define MAX_STR_COUNT 10
struct key_strings {
bool started;
int next_str;
char strings[MAX_STR_COUNT][SK_STR_BYTES];
};
static DEFINE_PER_CPU(struct key_strings, percpu_key_strings);
void scoutfs_key_start_percpu(void)
{
struct key_strings *ks = this_cpu_ptr(&percpu_key_strings);
BUG_ON(ks->started);
ks->started = true;
get_cpu();
}
char *scoutfs_key_percpu_string(void)
{
struct key_strings *ks = this_cpu_ptr(&percpu_key_strings);
char *str;
BUG_ON(!ks->started);
str = ks->strings[ks->next_str++];
BUG_ON(ks->next_str >= MAX_STR_COUNT);
return str;
}
void scoutfs_key_finish_percpu(void)
{
struct key_strings *ks = this_cpu_ptr(&percpu_key_strings);
BUG_ON(!ks->started);
ks->next_str = 0;
ks->started = false;
put_cpu();
}
+29
View File
@@ -19,7 +19,36 @@ void scoutfs_key_inc_cur_len(struct scoutfs_key_buf *key);
void scoutfs_key_dec(struct scoutfs_key_buf *key);
void scoutfs_key_dec_cur_len(struct scoutfs_key_buf *key);
int scoutfs_key_str_size(char *buf, struct scoutfs_key_buf *key, size_t size);
int scoutfs_key_str(char *buf, struct scoutfs_key_buf *key);
void scoutfs_key_start_percpu(void);
char *scoutfs_key_percpu_string(void);
void scoutfs_key_finish_percpu(void);
#define SK_PCPU(statements) do { \
scoutfs_key_start_percpu(); \
{ statements; } \
scoutfs_key_finish_percpu(); \
} while (0)
/*
* The biggest keys are typically a little struct then a large name. The
* string representation will tend to be mostly the name, but some of the
* strict fields can blow up from say 8 bytes to 20 bytes. So we give
* a lot of padding for that.
*/
#define SK_STR_BYTES (100 + SCOUTFS_MAX_KEY_SIZE)
#define SK_FMT "%s"
#define SK_ARG(k) \
({ \
char *__str = scoutfs_key_percpu_string(); \
scoutfs_key_str_size(__str, k, SK_STR_BYTES); \
__str; \
})
#define SK_TRACE_PRINTK(args...) SK_PCPU(trace_printk(args))
#define SK_PRINTK(args...) SK_PCPU(printk(args))
/*
* Initialize a small key in a larger allocated buffer. This lets