Restore key tracing

Now that the keys are a contiguous buffer we can format them for the
trace buffers with a much more straight forward type check around
per-key snprintfs.  We can get rid of all the weird kvec code that tried
to deal with keys that straddled vectors.

With that fixed we can uncomment out the tracing statements that were
waiting the key formatting.

I was testing with xattr keys so they're added as the code is updated.
The rest of the key types will be added seperately as they're used.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2017-02-15 13:10:27 -08:00
parent 607eff9b7c
commit 955d940c64
7 changed files with 88 additions and 167 deletions

View File

@@ -539,7 +539,7 @@ int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key_buf *key,
unsigned long flags;
int ret;
// trace_scoutfs_item_lookup(sb, key, val);
trace_scoutfs_item_lookup(sb, key, val);
end = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE);
if (!end) {
@@ -944,7 +944,7 @@ int scoutfs_item_insert_batch(struct super_block *sb, struct list_head *list,
unsigned long flags;
int ret;
// trace_scoutfs_item_insert_batch(sb, start, end);
trace_scoutfs_item_insert_batch(sb, start, end);
if (WARN_ON_ONCE(scoutfs_key_compare(start, end) > 0))
return -EINVAL;

View File

@@ -106,3 +106,70 @@ void scoutfs_key_dec(struct scoutfs_key_buf *key)
extend_zeros(key);
scoutfs_key_dec_cur_len(key);
}
/* return the bytes of the string including the null term */
#define snprintf_null(buf, size, fmt, args...) \
(snprintf((buf), (size), fmt, ##args) + 1)
/*
* Write the null-terminated string that describes the key to the
* buffer. The bytes copied (including the null) is returned. A null
* buffer can be used to find the string size without writing anything.
*
* XXX nonprintable characters in the trace?
*/
int scoutfs_key_str(char *buf, struct scoutfs_key_buf *key)
{
size_t size = buf ? INT_MAX : 0;
int len;
u8 type;
if (key->key_len == 0)
return snprintf_null(buf, size, "[0 len]");
type = *(u8 *)key->data;
switch(type) {
case SCOUTFS_INODE_KEY: {
struct scoutfs_inode_key *ikey = key->data;
if (key->key_len < sizeof(struct scoutfs_inode_key))
break;
return snprintf_null(buf, size, "ino.%llu",
be64_to_cpu(ikey->ino));
}
case SCOUTFS_XATTR_KEY: {
struct scoutfs_xattr_key *xkey = key->data;
len = (int)key->key_len - offsetof(struct scoutfs_xattr_key,
name[1]);
if (len <= 0)
break;
return snprintf_null(buf, size, "xat.%llu.%.*s",
be64_to_cpu(xkey->ino), len, xkey->name);
}
case SCOUTFS_DIRENT_KEY: {
struct scoutfs_dirent_key *dkey = key->data;
len = (int)key->key_len - offsetof(struct scoutfs_dirent_key,
name[1]);
if (len <= 0)
break;
return snprintf_null(buf, size, "dnt.%llu.%.*s",
be64_to_cpu(dkey->ino), len, dkey->name);
}
default:
return snprintf_null(buf, size, "[unknown type %u len %u]",
type, key->key_len);
}
return snprintf_null(buf, size, "[truncated type %u len %u]",
type, key->key_len);
}

View File

@@ -19,6 +19,8 @@ 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(char *buf, struct scoutfs_key_buf *key);
/*
* Initialize a small key in a larger allocated buffer. This lets
* callers, for example, search for a small key and get a larger key

View File

@@ -76,12 +76,6 @@ static size_t iter_contig(struct iter *iter)
return 0;
}
/* count of bytes remaining in the iteration */
static size_t iter_count(struct iter *iter)
{
return iter->count;
}
/*
* Return the result of memcmp between the min of the two total lengths.
* If their shorter lengths are equal than the shorter length is considered
@@ -296,145 +290,3 @@ void scoutfs_kvec_clone_less(struct kvec *dst, struct kvec *src)
scoutfs_kvec_memcmp(src, dst) < 0)
scoutfs_kvec_clone(dst, src);
}
/*
* Copy bytes from the kvec iterator into the dest buffer, zeroing the
* remainder of the buffer if there aren't enough bytes available in
* the iterator. If the tail bool is set then the kvec data is copied
* into the tail of the buffer and the head is zeroed.
*/
static bool iter_memcpy_zero(void *dst, struct iter *src, size_t len, bool tail)
{
size_t ctg;
size_t diff;
if (len == 0 || iter_count(src) == 0)
return false;
if (iter_count(src) < len) {
diff = len - iter_count(src);
if (tail) {
memset(dst, 0, diff);
dst += diff;
} else {
memset(dst + len - diff, 0, diff);
}
len = iter_count(src);
}
while ((ctg = min(len, iter_contig(src)))) {
memcpy(dst, iter_ptr(src), ctg);
iter_advance(src, ctg);
dst += ctg;
len -= ctg;
}
return true;
}
static int iter_puts_printable(char *dst, struct iter *src)
{
int len = iter_count(src);
size_t ctg;
int i;
while ((ctg = iter_contig(src))) {
memcpy(dst, iter_ptr(src), ctg);
iter_advance(src, ctg);
for (i = 0; i < ctg; i++) {
if (!isprint(dst[i]))
dst[i] = '_';
}
dst += ctg;
}
return len;
}
#define EMPTY_STR "''"
#define U64_U_BYTES 20
#define U64_D_BYTES 21
#define U64_X_BYTES 16
/*
* XXX figure out what to do about corrupt keys.
*/
unsigned scoutfs_kvec_key_strlen(struct kvec *key)
{
struct iter iter;
unsigned len = 0;
u8 type;
iter_init(&iter, key);
if (iter_count(&iter) == 0) {
len = sizeof(EMPTY_STR) - 1;
goto out;
}
iter_memcpy_zero(&type, &iter, sizeof(type), false);
len = 4; /* "typ." */
switch(type) {
case SCOUTFS_INODE_KEY:
len += U64_U_BYTES;
break;
case SCOUTFS_DIRENT_KEY:
len += U64_U_BYTES + (iter_count(&iter) - 8);
break;
case SCOUTFS_MAX_UNUSED_KEY:
break;
default:
/* hex of everything after the type */
len += (scoutfs_kvec_length(key) - 1) * 2;
break;
}
out:
return len + 1; /* null term */
}
void scoutfs_kvec_key_sprintf(char *buf, struct kvec *key)
{
struct iter iter;
__be64 be;
u8 type;
iter_init(&iter, key);
if (iter_contig(&iter) == 0) {
buf += sprintf(buf, EMPTY_STR);
goto done;
}
iter_memcpy_zero(&type, &iter, sizeof(type), false);
switch(type) {
case SCOUTFS_INODE_KEY:
buf += sprintf(buf, "ino.");
iter_memcpy_zero(&be, &iter, sizeof(be), false);
buf += sprintf(buf, "%llu", be64_to_cpu(be));
break;
case SCOUTFS_DIRENT_KEY:
buf += sprintf(buf, "den.");
iter_memcpy_zero(&be, &iter, sizeof(be), false);
buf += sprintf(buf, "%llu.", be64_to_cpu(be));
buf += iter_puts_printable(buf, &iter);
break;
case SCOUTFS_MAX_UNUSED_KEY:
buf += sprintf(buf, "max");
break;
default:
buf += sprintf(buf, "unk.");
while (iter_memcpy_zero(&be, &iter, sizeof(be), true))
buf += sprintf(buf, "%llx", be64_to_cpu(be));
break;
}
done:
*buf = '\0';
}

View File

@@ -66,8 +66,6 @@ int scoutfs_kvec_alloc_key(struct kvec *kvec);
void scoutfs_kvec_init_key(struct kvec *kvec);
void scoutfs_kvec_set_max_key(struct kvec *kvec);
void scoutfs_kvec_clone_less(struct kvec *dst, struct kvec *src);
unsigned scoutfs_kvec_key_strlen(struct kvec *key);
void scoutfs_kvec_key_sprintf(char *buf, struct kvec *key);
void scoutfs_kvec_be_inc(struct kvec *kvec);
void scoutfs_kvec_be_dec(struct kvec *kvec);

View File

@@ -194,7 +194,7 @@ int scoutfs_manifest_add(struct super_block *sb,
unsigned bytes;
int ret;
// trace_scoutfs_manifest_add(sb, first, last, segno, seq, level);
trace_scoutfs_manifest_add(sb, first, last, segno, seq, level);
key_bytes = first->key_len + last->key_len;
bytes = offsetof(struct scoutfs_manifest_entry, keys[key_bytes]);

View File

@@ -181,19 +181,19 @@ TRACE_EVENT(scoutfs_scan_orphans,
);
TRACE_EVENT(scoutfs_manifest_add,
TP_PROTO(struct super_block *sb, struct kvec *first,
struct kvec *last, u64 segno, u64 seq, u8 level),
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *first,
struct scoutfs_key_buf *last, u64 segno, u64 seq, u8 level),
TP_ARGS(sb, first, last, segno, seq, level),
TP_STRUCT__entry(
__dynamic_array(char, first, scoutfs_kvec_key_strlen(first))
__dynamic_array(char, last, scoutfs_kvec_key_strlen(last))
__dynamic_array(char, first, scoutfs_key_str(NULL, first))
__dynamic_array(char, last, scoutfs_key_str(NULL, last))
__field(u64, segno)
__field(u64, seq)
__field(u8, level)
),
TP_fast_assign(
scoutfs_kvec_key_sprintf(__get_dynamic_array(first), first);
scoutfs_kvec_key_sprintf(__get_dynamic_array(last), last);
scoutfs_key_str(__get_dynamic_array(first), first);
scoutfs_key_str(__get_dynamic_array(last), last);
__entry->segno = segno;
__entry->seq = seq;
__entry->level = level;
@@ -204,27 +204,29 @@ TRACE_EVENT(scoutfs_manifest_add,
);
TRACE_EVENT(scoutfs_item_lookup,
TP_PROTO(struct super_block *sb, struct kvec *key, struct kvec *val),
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key,
struct kvec *val),
TP_ARGS(sb, key, val),
TP_STRUCT__entry(
__dynamic_array(char, key, scoutfs_kvec_key_strlen(key))
__dynamic_array(char, key, scoutfs_key_str(NULL, key))
),
TP_fast_assign(
scoutfs_kvec_key_sprintf(__get_dynamic_array(key), key);
scoutfs_key_str(__get_dynamic_array(key), key);
),
TP_printk("key %s", __get_str(key))
);
TRACE_EVENT(scoutfs_item_insert_batch,
TP_PROTO(struct super_block *sb, struct kvec *start, struct kvec *end),
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end),
TP_ARGS(sb, start, end),
TP_STRUCT__entry(
__dynamic_array(char, start, scoutfs_kvec_key_strlen(start))
__dynamic_array(char, end, scoutfs_kvec_key_strlen(end))
__dynamic_array(char, start, scoutfs_key_str(NULL, start))
__dynamic_array(char, end, scoutfs_key_str(NULL, end))
),
TP_fast_assign(
scoutfs_kvec_key_sprintf(__get_dynamic_array(start), start);
scoutfs_kvec_key_sprintf(__get_dynamic_array(end), end);
scoutfs_key_str(__get_dynamic_array(start), start);
scoutfs_key_str(__get_dynamic_array(end), end);
),
TP_printk("start %s end %s", __get_str(start), __get_str(end))
);