mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-02 00:00:03 +03:00
Update bcachefs sources to 9d554fa16d bcachefs: Add .to_text() methods for all superblock sections
This commit is contained in:
parent
f850624092
commit
c06026ac54
@ -1 +1 @@
|
||||
7d0925084b6927ad8c631bde92fb1c41cc6270c2
|
||||
9d554fa16def4f6310d2df74092c5568419e69e3
|
||||
|
@ -794,7 +794,8 @@ static int push_invalidated_bucket(struct bch_fs *c, struct bch_dev *ca, u64 b)
|
||||
|
||||
static void discard_one_bucket(struct bch_fs *c, struct bch_dev *ca, u64 b)
|
||||
{
|
||||
if (ca->mi.discard &&
|
||||
if (!c->opts.nochanges &&
|
||||
ca->mi.discard &&
|
||||
blk_queue_discard(bdev_get_queue(ca->disk_sb.bdev)))
|
||||
blkdev_issue_discard(ca->disk_sb.bdev, bucket_to_sector(ca, b),
|
||||
ca->mi.bucket_size, GFP_NOFS, 0);
|
||||
|
@ -122,9 +122,9 @@ void bch2_dirent_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
{
|
||||
struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
|
||||
|
||||
bch_scnmemcpy(out, d.v->d_name,
|
||||
bch2_dirent_name_bytes(d));
|
||||
pr_buf(out, " -> %llu type %s",
|
||||
pr_buf(out, "%.*s -> %llu type %s",
|
||||
bch2_dirent_name_bytes(d),
|
||||
d.v->d_name,
|
||||
d.v->d_type != DT_SUBVOL
|
||||
? le64_to_cpu(d.v->d_inum)
|
||||
: le32_to_cpu(d.v->d_child_subvol),
|
||||
|
@ -76,8 +76,9 @@ static int bch2_sb_disk_groups_validate(struct bch_sb *sb,
|
||||
for (g = sorted; g + 1 < sorted + nr_groups; g++)
|
||||
if (!BCH_GROUP_DELETED(g) &&
|
||||
!group_cmp(&g[0], &g[1])) {
|
||||
pr_buf(err, "duplicate label %llu.", BCH_GROUP_PARENT(g));
|
||||
bch_scnmemcpy(err, g->label, strnlen(g->label, sizeof(g->label)));
|
||||
pr_buf(err, "duplicate label %llu.%.*s",
|
||||
BCH_GROUP_PARENT(g),
|
||||
(int) sizeof(g->label), g->label);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -342,12 +343,10 @@ int bch2_disk_path_find_or_create(struct bch_sb_handle *sb, const char *name)
|
||||
return v;
|
||||
}
|
||||
|
||||
void bch2_disk_path_to_text(struct printbuf *out,
|
||||
struct bch_sb_handle *sb,
|
||||
unsigned v)
|
||||
void bch2_disk_path_to_text(struct printbuf *out, struct bch_sb *sb, unsigned v)
|
||||
{
|
||||
struct bch_sb_field_disk_groups *groups =
|
||||
bch2_sb_get_disk_groups(sb->sb);
|
||||
bch2_sb_get_disk_groups(sb);
|
||||
struct bch_disk_group *g;
|
||||
unsigned nr = 0;
|
||||
u16 path[32];
|
||||
@ -376,15 +375,13 @@ void bch2_disk_path_to_text(struct printbuf *out,
|
||||
v = path[--nr];
|
||||
g = groups->entries + v;
|
||||
|
||||
bch_scnmemcpy(out, g->label,
|
||||
strnlen(g->label, sizeof(g->label)));
|
||||
|
||||
pr_buf(out, "%.*s", (int) sizeof(g->label), g->label);
|
||||
if (nr)
|
||||
pr_buf(out, ".");
|
||||
}
|
||||
return;
|
||||
inval:
|
||||
pr_buf(out, "invalid group %u", v);
|
||||
pr_buf(out, "invalid label %u", v);
|
||||
}
|
||||
|
||||
int bch2_dev_group_set(struct bch_fs *c, struct bch_dev *ca, const char *name)
|
||||
@ -448,6 +445,36 @@ int bch2_opt_target_parse(struct bch_fs *c, const char *buf, u64 *v)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void bch2_sb_target_to_text(struct printbuf *out, struct bch_sb *sb, u64 v)
|
||||
{
|
||||
struct target t = target_decode(v);
|
||||
|
||||
switch (t.type) {
|
||||
case TARGET_NULL:
|
||||
pr_buf(out, "none");
|
||||
break;
|
||||
case TARGET_DEV: {
|
||||
struct bch_sb_field_members *mi = bch2_sb_get_members(sb);
|
||||
struct bch_member *m = mi->members + t.dev;
|
||||
|
||||
if (bch2_dev_exists(sb, mi, t.dev)) {
|
||||
pr_buf(out, "Device ");
|
||||
pr_uuid(out, m->uuid.b);
|
||||
pr_buf(out, " (%u)", t.dev);
|
||||
} else {
|
||||
pr_buf(out, "Bad device %u", t.dev);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TARGET_GROUP:
|
||||
bch2_disk_path_to_text(out, sb, t.group);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
void bch2_opt_target_to_text(struct printbuf *out, struct bch_fs *c, u64 v)
|
||||
{
|
||||
struct target t = target_decode(v);
|
||||
@ -481,7 +508,7 @@ void bch2_opt_target_to_text(struct printbuf *out, struct bch_fs *c, u64 v)
|
||||
}
|
||||
case TARGET_GROUP:
|
||||
mutex_lock(&c->sb_lock);
|
||||
bch2_disk_path_to_text(out, &c->disk_sb, t.group);
|
||||
bch2_disk_path_to_text(out, c->disk_sb.sb, t.group);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
break;
|
||||
default:
|
||||
|
@ -75,8 +75,9 @@ int bch2_disk_path_find(struct bch_sb_handle *, const char *);
|
||||
/* Exported for userspace bcachefs-tools: */
|
||||
int bch2_disk_path_find_or_create(struct bch_sb_handle *, const char *);
|
||||
|
||||
void bch2_disk_path_to_text(struct printbuf *, struct bch_sb_handle *,
|
||||
unsigned);
|
||||
void bch2_disk_path_to_text(struct printbuf *, struct bch_sb *, unsigned);
|
||||
|
||||
void bch2_sb_target_to_text(struct printbuf *, struct bch_sb *, u64);
|
||||
|
||||
int bch2_opt_target_parse(struct bch_fs *, const char *, u64 *);
|
||||
void bch2_opt_target_to_text(struct printbuf *, struct bch_fs *, u64);
|
||||
|
@ -954,15 +954,19 @@ void bch2_bkey_ptrs_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
switch (__extent_entry_type(entry)) {
|
||||
case BCH_EXTENT_ENTRY_ptr:
|
||||
ptr = entry_to_ptr(entry);
|
||||
ca = ptr->dev < c->sb.nr_devices && c->devs[ptr->dev]
|
||||
? bch_dev_bkey_exists(c, ptr->dev)
|
||||
: NULL;
|
||||
|
||||
pr_buf(out, "ptr: %u:%llu gen %u%s%s", ptr->dev,
|
||||
pr_buf(out, "ptr: %u:%llu gen %u%s", ptr->dev,
|
||||
(u64) ptr->offset, ptr->gen,
|
||||
ptr->cached ? " cached" : "",
|
||||
ca && ptr_stale(ca, ptr)
|
||||
? " stale" : "");
|
||||
ptr->cached ? " cached" : "");
|
||||
|
||||
if (c) {
|
||||
ca = ptr->dev < c->sb.nr_devices && c->devs[ptr->dev]
|
||||
? bch_dev_bkey_exists(c, ptr->dev)
|
||||
: NULL;
|
||||
|
||||
if (ca && ptr_stale(ca, ptr))
|
||||
pr_buf(out, " stale");
|
||||
}
|
||||
break;
|
||||
case BCH_EXTENT_ENTRY_crc32:
|
||||
case BCH_EXTENT_ENTRY_crc64:
|
||||
|
@ -303,7 +303,7 @@ static void journal_entry_btree_keys_to_text(struct printbuf *out, struct bch_fs
|
||||
|
||||
vstruct_for_each(entry, k) {
|
||||
if (!first) {
|
||||
printbuf_newline(out);
|
||||
pr_newline(out);
|
||||
pr_buf(out, "%s: ", bch2_jset_entry_types[entry->type]);
|
||||
}
|
||||
pr_buf(out, "btree=%s l=%u ", bch2_btree_ids[entry->btree_id], entry->level);
|
||||
@ -596,7 +596,7 @@ static void journal_entry_log_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct jset_entry_log *l = container_of(entry, struct jset_entry_log, entry);
|
||||
unsigned bytes = vstruct_bytes(entry) - offsetof(struct jset_entry_log, d);
|
||||
|
||||
bch_scnmemcpy(out, l->d, strnlen(l->d, bytes));
|
||||
pr_buf(out, "%.*s", bytes, l->d);
|
||||
}
|
||||
|
||||
struct jset_entry_ops {
|
||||
|
@ -286,7 +286,8 @@ void bch2_journal_do_discards(struct journal *j)
|
||||
struct journal_device *ja = &ca->journal;
|
||||
|
||||
while (should_discard_bucket(j, ja)) {
|
||||
if (ca->mi.discard &&
|
||||
if (!c->opts.nochanges &&
|
||||
ca->mi.discard &&
|
||||
blk_queue_discard(bdev_get_queue(ca->disk_sb.bdev)))
|
||||
blkdev_issue_discard(ca->disk_sb.bdev,
|
||||
bucket_to_sector(ca,
|
||||
|
@ -235,6 +235,7 @@ static void bch2_sb_journal_seq_blacklist_to_text(struct printbuf *out,
|
||||
le64_to_cpu(i->start),
|
||||
le64_to_cpu(i->end));
|
||||
}
|
||||
pr_newline(out);
|
||||
}
|
||||
|
||||
const struct bch_sb_field_ops bch_sb_field_ops_journal_seq_blacklist = {
|
||||
|
@ -6,7 +6,18 @@
|
||||
#include "subvolume.h"
|
||||
#include "super-io.h"
|
||||
|
||||
static int bch2_sb_validate_quota(struct bch_sb *sb, struct bch_sb_field *f,
|
||||
static const char * const bch2_quota_types[] = {
|
||||
"user",
|
||||
"group",
|
||||
"project",
|
||||
};
|
||||
|
||||
static const char * const bch2_quota_counters[] = {
|
||||
"space",
|
||||
"inodes",
|
||||
};
|
||||
|
||||
static int bch2_sb_quota_validate(struct bch_sb *sb, struct bch_sb_field *f,
|
||||
struct printbuf *err)
|
||||
{
|
||||
struct bch_sb_field_quota *q = field_to_type(f, quota);
|
||||
@ -14,13 +25,36 @@ static int bch2_sb_validate_quota(struct bch_sb *sb, struct bch_sb_field *f,
|
||||
if (vstruct_bytes(&q->field) < sizeof(*q)) {
|
||||
pr_buf(err, "wrong size (got %llu should be %zu)",
|
||||
vstruct_bytes(&q->field), sizeof(*q));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bch2_sb_quota_to_text(struct printbuf *out, struct bch_sb *sb,
|
||||
struct bch_sb_field *f)
|
||||
{
|
||||
struct bch_sb_field_quota *q = field_to_type(f, quota);
|
||||
unsigned qtyp, counter;
|
||||
|
||||
for (qtyp = 0; qtyp < ARRAY_SIZE(q->q); qtyp++) {
|
||||
pr_buf(out, "%s: flags %llx",
|
||||
bch2_quota_types[qtyp],
|
||||
le64_to_cpu(q->q[qtyp].flags));
|
||||
|
||||
for (counter = 0; counter < Q_COUNTERS; counter++)
|
||||
pr_buf(out, " %s timelimit %u warnlimit %u",
|
||||
bch2_quota_counters[counter],
|
||||
le32_to_cpu(q->q[qtyp].c[counter].timelimit),
|
||||
le32_to_cpu(q->q[qtyp].c[counter].warnlimit));
|
||||
|
||||
pr_newline(out);
|
||||
}
|
||||
}
|
||||
|
||||
const struct bch_sb_field_ops bch_sb_field_ops_quota = {
|
||||
.validate = bch2_sb_validate_quota,
|
||||
.validate = bch2_sb_quota_validate,
|
||||
.to_text = bch2_sb_quota_to_text,
|
||||
};
|
||||
|
||||
const char *bch2_quota_invalid(const struct bch_fs *c, struct bkey_s_c k)
|
||||
@ -34,11 +68,6 @@ const char *bch2_quota_invalid(const struct bch_fs *c, struct bkey_s_c k)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char * const bch2_quota_counters[] = {
|
||||
"space",
|
||||
"inodes",
|
||||
};
|
||||
|
||||
void bch2_quota_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct bkey_s_c k)
|
||||
{
|
||||
|
@ -803,7 +803,7 @@ static struct bch_sb_field_clean *read_superblock_clean(struct bch_fs *c)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = bch2_sb_clean_validate(c, clean, READ);
|
||||
ret = bch2_sb_clean_validate_late(c, clean, READ);
|
||||
if (ret) {
|
||||
mutex_unlock(&c->sb_lock);
|
||||
return ERR_PTR(ret);
|
||||
|
@ -36,6 +36,22 @@ static void bch2_cpu_replicas_sort(struct bch_replicas_cpu *r)
|
||||
eytzinger0_sort(r->entries, r->nr, r->entry_size, memcmp, NULL);
|
||||
}
|
||||
|
||||
void bch2_replicas_entry_v0_to_text(struct printbuf *out,
|
||||
struct bch_replicas_entry_v0 *e)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (e->data_type < BCH_DATA_NR)
|
||||
pr_buf(out, "%s", bch2_data_types[e->data_type]);
|
||||
else
|
||||
pr_buf(out, "(invalid data type %u)", e->data_type);
|
||||
|
||||
pr_buf(out, ": %u [", e->nr_devs);
|
||||
for (i = 0; i < e->nr_devs; i++)
|
||||
pr_buf(out, i ? " %u" : "%u", e->devs[i]);
|
||||
pr_buf(out, "]");
|
||||
}
|
||||
|
||||
void bch2_replicas_entry_to_text(struct printbuf *out,
|
||||
struct bch_replicas_entry *e)
|
||||
{
|
||||
@ -860,7 +876,7 @@ static int bch2_cpu_replicas_validate(struct bch_replicas_cpu *cpu_r,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bch2_sb_validate_replicas(struct bch_sb *sb, struct bch_sb_field *f,
|
||||
static int bch2_sb_replicas_validate(struct bch_sb *sb, struct bch_sb_field *f,
|
||||
struct printbuf *err)
|
||||
{
|
||||
struct bch_sb_field_replicas *sb_r = field_to_type(f, replicas);
|
||||
@ -890,14 +906,15 @@ static void bch2_sb_replicas_to_text(struct printbuf *out,
|
||||
|
||||
bch2_replicas_entry_to_text(out, e);
|
||||
}
|
||||
pr_newline(out);
|
||||
}
|
||||
|
||||
const struct bch_sb_field_ops bch_sb_field_ops_replicas = {
|
||||
.validate = bch2_sb_validate_replicas,
|
||||
.validate = bch2_sb_replicas_validate,
|
||||
.to_text = bch2_sb_replicas_to_text,
|
||||
};
|
||||
|
||||
static int bch2_sb_validate_replicas_v0(struct bch_sb *sb, struct bch_sb_field *f,
|
||||
static int bch2_sb_replicas_v0_validate(struct bch_sb *sb, struct bch_sb_field *f,
|
||||
struct printbuf *err)
|
||||
{
|
||||
struct bch_sb_field_replicas_v0 *sb_r = field_to_type(f, replicas_v0);
|
||||
@ -912,8 +929,27 @@ static int bch2_sb_validate_replicas_v0(struct bch_sb *sb, struct bch_sb_field *
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bch2_sb_replicas_v0_to_text(struct printbuf *out,
|
||||
struct bch_sb *sb,
|
||||
struct bch_sb_field *f)
|
||||
{
|
||||
struct bch_sb_field_replicas_v0 *sb_r = field_to_type(f, replicas_v0);
|
||||
struct bch_replicas_entry_v0 *e;
|
||||
bool first = true;
|
||||
|
||||
for_each_replicas_entry(sb_r, e) {
|
||||
if (!first)
|
||||
pr_buf(out, " ");
|
||||
first = false;
|
||||
|
||||
bch2_replicas_entry_v0_to_text(out, e);
|
||||
}
|
||||
pr_newline(out);
|
||||
}
|
||||
|
||||
const struct bch_sb_field_ops bch_sb_field_ops_replicas_v0 = {
|
||||
.validate = bch2_sb_validate_replicas_v0,
|
||||
.validate = bch2_sb_replicas_v0_validate,
|
||||
.to_text = bch2_sb_replicas_v0_to_text,
|
||||
};
|
||||
|
||||
/* Query replicas: */
|
||||
@ -970,19 +1006,42 @@ bool bch2_have_enough_devs(struct bch_fs *c, struct bch_devs_mask devs,
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned bch2_sb_dev_has_data(struct bch_sb *sb, unsigned dev)
|
||||
{
|
||||
struct bch_sb_field_replicas *replicas;
|
||||
struct bch_sb_field_replicas_v0 *replicas_v0;
|
||||
unsigned i, data_has = 0;
|
||||
|
||||
replicas = bch2_sb_get_replicas(sb);
|
||||
replicas_v0 = bch2_sb_get_replicas_v0(sb);
|
||||
|
||||
if (replicas) {
|
||||
struct bch_replicas_entry *r;
|
||||
|
||||
for_each_replicas_entry(replicas, r)
|
||||
for (i = 0; i < r->nr_devs; i++)
|
||||
if (r->devs[i] == dev)
|
||||
data_has |= 1 << r->data_type;
|
||||
} else if (replicas_v0) {
|
||||
struct bch_replicas_entry_v0 *r;
|
||||
|
||||
for_each_replicas_entry_v0(replicas_v0, r)
|
||||
for (i = 0; i < r->nr_devs; i++)
|
||||
if (r->devs[i] == dev)
|
||||
data_has |= 1 << r->data_type;
|
||||
}
|
||||
|
||||
|
||||
return data_has;
|
||||
}
|
||||
|
||||
unsigned bch2_dev_has_data(struct bch_fs *c, struct bch_dev *ca)
|
||||
{
|
||||
struct bch_replicas_entry *e;
|
||||
unsigned i, ret = 0;
|
||||
unsigned ret;
|
||||
|
||||
percpu_down_read(&c->mark_lock);
|
||||
|
||||
for_each_cpu_replicas_entry(&c->replicas, e)
|
||||
for (i = 0; i < e->nr_devs; i++)
|
||||
if (e->devs[i] == ca->dev_idx)
|
||||
ret |= 1 << e->data_type;
|
||||
|
||||
percpu_up_read(&c->mark_lock);
|
||||
mutex_lock(&c->sb_lock);
|
||||
ret = bch2_sb_dev_has_data(c->disk_sb.sb, ca->dev_idx);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ static inline void bch2_replicas_entry_cached(struct bch_replicas_entry *e,
|
||||
bool bch2_have_enough_devs(struct bch_fs *, struct bch_devs_mask,
|
||||
unsigned, bool);
|
||||
|
||||
unsigned bch2_sb_dev_has_data(struct bch_sb *, unsigned);
|
||||
unsigned bch2_dev_has_data(struct bch_fs *, struct bch_dev *);
|
||||
|
||||
int bch2_replicas_gc_end(struct bch_fs *, int);
|
||||
|
@ -918,7 +918,7 @@ static int u64_cmp(const void *_l, const void *_r)
|
||||
return l < r ? -1 : l > r ? 1 : 0;
|
||||
}
|
||||
|
||||
static int bch2_sb_validate_journal(struct bch_sb *sb,
|
||||
static int bch2_sb_journal_validate(struct bch_sb *sb,
|
||||
struct bch_sb_field *f,
|
||||
struct printbuf *err)
|
||||
{
|
||||
@ -971,13 +971,26 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bch2_sb_journal_to_text(struct printbuf *out, struct bch_sb *sb,
|
||||
struct bch_sb_field *f)
|
||||
{
|
||||
struct bch_sb_field_journal *journal = field_to_type(f, journal);
|
||||
unsigned i, nr = bch2_nr_journal_buckets(journal);
|
||||
|
||||
pr_buf(out, "Buckets: ");
|
||||
for (i = 0; i < nr; i++)
|
||||
pr_buf(out, " %llu", le64_to_cpu(journal->buckets[i]));
|
||||
pr_newline(out);
|
||||
}
|
||||
|
||||
static const struct bch_sb_field_ops bch_sb_field_ops_journal = {
|
||||
.validate = bch2_sb_validate_journal,
|
||||
.validate = bch2_sb_journal_validate,
|
||||
.to_text = bch2_sb_journal_to_text,
|
||||
};
|
||||
|
||||
/* BCH_SB_FIELD_members: */
|
||||
|
||||
static int bch2_sb_validate_members(struct bch_sb *sb,
|
||||
static int bch2_sb_members_validate(struct bch_sb *sb,
|
||||
struct bch_sb_field *f,
|
||||
struct printbuf *err)
|
||||
{
|
||||
@ -1027,13 +1040,105 @@ static int bch2_sb_validate_members(struct bch_sb *sb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bch2_sb_members_to_text(struct printbuf *out, struct bch_sb *sb,
|
||||
struct bch_sb_field *f)
|
||||
{
|
||||
struct bch_sb_field_members *mi = field_to_type(f, members);
|
||||
struct bch_sb_field_disk_groups *gi = bch2_sb_get_disk_groups(sb);
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < sb->nr_devices; i++) {
|
||||
struct bch_member *m = mi->members + i;
|
||||
unsigned data_have = bch2_sb_dev_has_data(sb, i);
|
||||
u64 bucket_size = le16_to_cpu(m->bucket_size);
|
||||
u64 device_size = le64_to_cpu(m->nbuckets) * bucket_size;
|
||||
|
||||
if (!bch2_member_exists(m))
|
||||
continue;
|
||||
|
||||
pr_buf(out, "Device: %u", i);
|
||||
pr_newline(out);
|
||||
|
||||
printbuf_indent_push(out, 2);
|
||||
|
||||
pr_buf(out, "UUID: ");
|
||||
pr_uuid(out, m->uuid.b);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Size: ");
|
||||
pr_units(out, device_size, device_size << 9);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Bucket size: ");
|
||||
pr_units(out, bucket_size, bucket_size << 9);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "First bucket: %u",
|
||||
le16_to_cpu(m->first_bucket));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Buckets: %llu",
|
||||
le64_to_cpu(m->nbuckets));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Last mount: ");
|
||||
if (m->last_mount)
|
||||
pr_time(out, le64_to_cpu(m->last_mount));
|
||||
else
|
||||
pr_buf(out, "(never)");
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "State: %s",
|
||||
BCH_MEMBER_STATE(m) < BCH_MEMBER_STATE_NR
|
||||
? bch2_member_states[BCH_MEMBER_STATE(m)]
|
||||
: "unknown");
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Group: ");
|
||||
if (BCH_MEMBER_GROUP(m)) {
|
||||
unsigned idx = BCH_MEMBER_GROUP(m) - 1;
|
||||
|
||||
if (idx < disk_groups_nr(gi))
|
||||
pr_buf(out, "%s (%u)",
|
||||
gi->entries[idx].label, idx);
|
||||
else
|
||||
pr_buf(out, "(bad disk labels section)");
|
||||
} else {
|
||||
pr_buf(out, "(none)");
|
||||
}
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Data allowed: ");
|
||||
if (BCH_MEMBER_DATA_ALLOWED(m))
|
||||
bch2_flags_to_text(out, bch2_data_types,
|
||||
BCH_MEMBER_DATA_ALLOWED(m));
|
||||
else
|
||||
pr_buf(out, "(none)");
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Has data: ");
|
||||
if (data_have)
|
||||
bch2_flags_to_text(out, bch2_data_types, data_have);
|
||||
else
|
||||
pr_buf(out, "(none)");
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Discard: %llu",
|
||||
BCH_MEMBER_DISCARD(m));
|
||||
pr_newline(out);
|
||||
|
||||
printbuf_indent_pop(out, 2);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct bch_sb_field_ops bch_sb_field_ops_members = {
|
||||
.validate = bch2_sb_validate_members,
|
||||
.validate = bch2_sb_members_validate,
|
||||
.to_text = bch2_sb_members_to_text,
|
||||
};
|
||||
|
||||
/* BCH_SB_FIELD_crypt: */
|
||||
|
||||
static int bch2_sb_validate_crypt(struct bch_sb *sb,
|
||||
static int bch2_sb_crypt_validate(struct bch_sb *sb,
|
||||
struct bch_sb_field *f,
|
||||
struct printbuf *err)
|
||||
{
|
||||
@ -1053,13 +1158,29 @@ static int bch2_sb_validate_crypt(struct bch_sb *sb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bch2_sb_crypt_to_text(struct printbuf *out, struct bch_sb *sb,
|
||||
struct bch_sb_field *f)
|
||||
{
|
||||
struct bch_sb_field_crypt *crypt = field_to_type(f, crypt);
|
||||
|
||||
pr_buf(out, "KFD: %llu", BCH_CRYPT_KDF_TYPE(crypt));
|
||||
pr_newline(out);
|
||||
pr_buf(out, "scrypt n: %llu", BCH_KDF_SCRYPT_N(crypt));
|
||||
pr_newline(out);
|
||||
pr_buf(out, "scrypt r: %llu", BCH_KDF_SCRYPT_R(crypt));
|
||||
pr_newline(out);
|
||||
pr_buf(out, "scrypt p: %llu", BCH_KDF_SCRYPT_P(crypt));
|
||||
pr_newline(out);
|
||||
}
|
||||
|
||||
static const struct bch_sb_field_ops bch_sb_field_ops_crypt = {
|
||||
.validate = bch2_sb_validate_crypt,
|
||||
.validate = bch2_sb_crypt_validate,
|
||||
.to_text = bch2_sb_crypt_to_text,
|
||||
};
|
||||
|
||||
/* BCH_SB_FIELD_clean: */
|
||||
|
||||
int bch2_sb_clean_validate(struct bch_fs *c, struct bch_sb_field_clean *clean, int write)
|
||||
int bch2_sb_clean_validate_late(struct bch_fs *c, struct bch_sb_field_clean *clean, int write)
|
||||
{
|
||||
struct jset_entry *entry;
|
||||
int ret;
|
||||
@ -1248,7 +1369,7 @@ void bch2_fs_mark_clean(struct bch_fs *c)
|
||||
* this should be in the write path, and we should be validating every
|
||||
* superblock section:
|
||||
*/
|
||||
ret = bch2_sb_clean_validate(c, sb_clean, WRITE);
|
||||
ret = bch2_sb_clean_validate_late(c, sb_clean, WRITE);
|
||||
if (ret) {
|
||||
bch_err(c, "error writing marking filesystem clean: validate error");
|
||||
goto out;
|
||||
@ -1259,7 +1380,7 @@ out:
|
||||
mutex_unlock(&c->sb_lock);
|
||||
}
|
||||
|
||||
static int bch2_sb_validate_clean(struct bch_sb *sb,
|
||||
static int bch2_sb_clean_validate(struct bch_sb *sb,
|
||||
struct bch_sb_field *f,
|
||||
struct printbuf *err)
|
||||
{
|
||||
@ -1274,8 +1395,32 @@ static int bch2_sb_validate_clean(struct bch_sb *sb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bch2_sb_clean_to_text(struct printbuf *out, struct bch_sb *sb,
|
||||
struct bch_sb_field *f)
|
||||
{
|
||||
struct bch_sb_field_clean *clean = field_to_type(f, clean);
|
||||
struct jset_entry *entry;
|
||||
|
||||
pr_buf(out, "flags: %x", le32_to_cpu(clean->flags));
|
||||
pr_newline(out);
|
||||
pr_buf(out, "journal_seq: %llu", le64_to_cpu(clean->journal_seq));
|
||||
pr_newline(out);
|
||||
|
||||
for (entry = clean->start;
|
||||
entry != vstruct_end(&clean->field);
|
||||
entry = vstruct_next(entry)) {
|
||||
if (entry->type == BCH_JSET_ENTRY_btree_keys &&
|
||||
!entry->u64s)
|
||||
continue;
|
||||
|
||||
bch2_journal_entry_to_text(out, NULL, entry);
|
||||
pr_newline(out);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct bch_sb_field_ops bch_sb_field_ops_clean = {
|
||||
.validate = bch2_sb_validate_clean,
|
||||
.validate = bch2_sb_clean_validate,
|
||||
.to_text = bch2_sb_clean_to_text,
|
||||
};
|
||||
|
||||
static const struct bch_sb_field_ops *bch2_sb_field_ops[] = {
|
||||
@ -1299,7 +1444,7 @@ static int bch2_sb_field_validate(struct bch_sb *sb, struct bch_sb_field *f,
|
||||
|
||||
ret = bch2_sb_field_ops[type]->validate(sb, f, &err);
|
||||
if (ret) {
|
||||
pr_buf(&err, "\n");
|
||||
pr_newline(&err);
|
||||
bch2_sb_field_to_text(&err, sb, f);
|
||||
*orig_err = err;
|
||||
}
|
||||
@ -1320,7 +1465,202 @@ void bch2_sb_field_to_text(struct printbuf *out, struct bch_sb *sb,
|
||||
pr_buf(out, "(unknown field %u)", type);
|
||||
|
||||
pr_buf(out, " (size %llu):", vstruct_bytes(f));
|
||||
pr_newline(out);
|
||||
|
||||
if (ops && ops->to_text)
|
||||
if (ops && ops->to_text) {
|
||||
printbuf_indent_push(out, 2);
|
||||
bch2_sb_field_ops[type]->to_text(out, sb, f);
|
||||
printbuf_indent_pop(out, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void bch2_sb_layout_to_text(struct printbuf *out, struct bch_sb_layout *l)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
pr_buf(out, "Type: %u", l->layout_type);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Superblock max size: ");
|
||||
pr_units(out,
|
||||
1 << l->sb_max_size_bits,
|
||||
512 << l->sb_max_size_bits);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Nr superblocks: %u", l->nr_superblocks);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Offsets: ");
|
||||
for (i = 0; i < l->nr_superblocks; i++) {
|
||||
if (i)
|
||||
pr_buf(out, ", ");
|
||||
pr_buf(out, "%llu", le64_to_cpu(l->sb_offset[i]));
|
||||
}
|
||||
pr_newline(out);
|
||||
}
|
||||
|
||||
void bch2_sb_to_text(struct printbuf *out, struct bch_sb *sb,
|
||||
bool print_layout, unsigned fields)
|
||||
{
|
||||
struct bch_sb_field_members *mi;
|
||||
struct bch_sb_field *f;
|
||||
u64 fields_have = 0;
|
||||
unsigned nr_devices = 0;
|
||||
|
||||
mi = bch2_sb_get_members(sb);
|
||||
if (mi) {
|
||||
struct bch_member *m;
|
||||
|
||||
for (m = mi->members;
|
||||
m < mi->members + sb->nr_devices;
|
||||
m++)
|
||||
nr_devices += bch2_member_exists(m);
|
||||
}
|
||||
|
||||
pr_buf(out, "External UUID: ");
|
||||
pr_uuid(out, sb->user_uuid.b);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Internal UUID: ");
|
||||
pr_uuid(out, sb->uuid.b);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Device index: %u", sb->dev_idx);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Label: ");
|
||||
pr_buf(out, "%.*s", (int) sizeof(sb->label), sb->label);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Version: %u", le16_to_cpu(sb->version));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Oldest version on disk: %u", le16_to_cpu(sb->version_min));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Created: ");
|
||||
if (sb->time_base_lo)
|
||||
pr_time(out, le64_to_cpu(sb->time_base_lo) / NSEC_PER_SEC);
|
||||
else
|
||||
pr_buf(out, "(not set)");
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Squence number: %llu", le64_to_cpu(sb->seq));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Block_size: ");
|
||||
pr_units(out, le16_to_cpu(sb->block_size),
|
||||
(u32) le16_to_cpu(sb->block_size) << 9);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Btree node size: ");
|
||||
pr_units(out, BCH_SB_BTREE_NODE_SIZE(sb),
|
||||
BCH_SB_BTREE_NODE_SIZE(sb) << 9);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Error action: %s",
|
||||
BCH_SB_ERROR_ACTION(sb) < BCH_ON_ERROR_NR
|
||||
? bch2_error_actions[BCH_SB_ERROR_ACTION(sb)]
|
||||
: "unknown");
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Clean: %llu", BCH_SB_CLEAN(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Features: ");
|
||||
bch2_flags_to_text(out, bch2_sb_features,
|
||||
le64_to_cpu(sb->features[0]));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Compat features: ");
|
||||
bch2_flags_to_text(out, bch2_sb_compat,
|
||||
le64_to_cpu(sb->compat[0]));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Metadata replicas: %llu", BCH_SB_META_REPLICAS_WANT(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Data replicas: %llu", BCH_SB_DATA_REPLICAS_WANT(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Metadata checksum type: %s (%llu)",
|
||||
BCH_SB_META_CSUM_TYPE(sb) < BCH_CSUM_OPT_NR
|
||||
? bch2_csum_opts[BCH_SB_META_CSUM_TYPE(sb)]
|
||||
: "unknown",
|
||||
BCH_SB_META_CSUM_TYPE(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Data checksum type: %s (%llu)",
|
||||
BCH_SB_DATA_CSUM_TYPE(sb) < BCH_CSUM_OPT_NR
|
||||
? bch2_csum_opts[BCH_SB_DATA_CSUM_TYPE(sb)]
|
||||
: "unknown",
|
||||
BCH_SB_DATA_CSUM_TYPE(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Compression type: %s (%llu)",
|
||||
BCH_SB_COMPRESSION_TYPE(sb) < BCH_COMPRESSION_OPT_NR
|
||||
? bch2_compression_opts[BCH_SB_COMPRESSION_TYPE(sb)]
|
||||
: "unknown",
|
||||
BCH_SB_COMPRESSION_TYPE(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Foreground write target: ");
|
||||
bch2_sb_target_to_text(out, sb, BCH_SB_FOREGROUND_TARGET(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Background write target: ");
|
||||
bch2_sb_target_to_text(out, sb, BCH_SB_BACKGROUND_TARGET(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Promote target: ");
|
||||
bch2_sb_target_to_text(out, sb, BCH_SB_PROMOTE_TARGET(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Metadata target: ");
|
||||
bch2_sb_target_to_text(out, sb, BCH_SB_METADATA_TARGET(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "String hash type: %s (%llu)",
|
||||
BCH_SB_STR_HASH_TYPE(sb) < BCH_STR_HASH_NR
|
||||
? bch2_str_hash_types[BCH_SB_STR_HASH_TYPE(sb)]
|
||||
: "unknown",
|
||||
BCH_SB_STR_HASH_TYPE(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "32 bit inodes: %llu", BCH_SB_INODE_32BIT(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "GC reserve percentage: %llu%%", BCH_SB_GC_RESERVE(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Root reserve percentage: %llu%%", BCH_SB_ROOT_RESERVE(sb));
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Devices: %u live, %u total",
|
||||
nr_devices, sb->nr_devices);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Sections: ");
|
||||
vstruct_for_each(sb, f)
|
||||
fields_have |= 1 << le32_to_cpu(f->type);
|
||||
bch2_flags_to_text(out, bch2_sb_fields, fields_have);
|
||||
pr_newline(out);
|
||||
|
||||
pr_buf(out, "Superblock size: %llu", vstruct_bytes(sb));
|
||||
pr_newline(out);
|
||||
|
||||
if (print_layout) {
|
||||
pr_newline(out);
|
||||
pr_buf(out, "layout:");
|
||||
pr_newline(out);
|
||||
printbuf_indent_push(out, 2);
|
||||
bch2_sb_layout_to_text(out, &sb->layout);
|
||||
printbuf_indent_pop(out, 2);
|
||||
}
|
||||
|
||||
vstruct_for_each(sb, f)
|
||||
if (fields & (1 << le32_to_cpu(f->type))) {
|
||||
pr_newline(out);
|
||||
bch2_sb_field_to_text(out, sb, f);
|
||||
}
|
||||
}
|
||||
|
@ -121,12 +121,14 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
|
||||
void bch2_journal_super_entries_add_common(struct bch_fs *,
|
||||
struct jset_entry **, u64);
|
||||
|
||||
int bch2_sb_clean_validate(struct bch_fs *, struct bch_sb_field_clean *, int);
|
||||
int bch2_sb_clean_validate_late(struct bch_fs *, struct bch_sb_field_clean *, int);
|
||||
|
||||
int bch2_fs_mark_dirty(struct bch_fs *);
|
||||
void bch2_fs_mark_clean(struct bch_fs *);
|
||||
|
||||
void bch2_sb_field_to_text(struct printbuf *, struct bch_sb *,
|
||||
struct bch_sb_field *);
|
||||
void bch2_sb_layout_to_text(struct printbuf *, struct bch_sb_layout *);
|
||||
void bch2_sb_to_text(struct printbuf *, struct bch_sb *, bool, unsigned);
|
||||
|
||||
#endif /* _BCACHEFS_SUPER_IO_H */
|
||||
|
@ -825,7 +825,7 @@ SHOW(bch2_dev)
|
||||
if (attr == &sysfs_label) {
|
||||
if (ca->mi.group) {
|
||||
mutex_lock(&c->sb_lock);
|
||||
bch2_disk_path_to_text(&out, &c->disk_sb,
|
||||
bch2_disk_path_to_text(&out, c->disk_sb.sb,
|
||||
ca->mi.group - 1);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
}
|
||||
|
@ -120,6 +120,27 @@ void bch2_hprint(struct printbuf *buf, s64 v)
|
||||
pr_buf(buf, "%c", si_units[u]);
|
||||
}
|
||||
|
||||
void bch2_pr_units(struct printbuf *out, s64 raw, s64 bytes)
|
||||
{
|
||||
if (raw < 0) {
|
||||
pr_buf(out, "-");
|
||||
raw = -raw;
|
||||
bytes = -bytes;
|
||||
}
|
||||
|
||||
switch (out->units) {
|
||||
case PRINTBUF_UNITS_RAW:
|
||||
pr_buf(out, "%llu", raw);
|
||||
break;
|
||||
case PRINTBUF_UNITS_BYTES:
|
||||
pr_buf(out, "%llu", bytes);
|
||||
break;
|
||||
case PRINTBUF_UNITS_HUMAN_READABLE:
|
||||
bch2_hprint(out, bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bch2_string_opt_to_text(struct printbuf *out,
|
||||
const char * const list[],
|
||||
size_t selected)
|
||||
@ -579,19 +600,6 @@ void memcpy_from_bio(void *dst, struct bio *src, struct bvec_iter src_iter)
|
||||
}
|
||||
}
|
||||
|
||||
void bch_scnmemcpy(struct printbuf *out,
|
||||
const char *src, size_t len)
|
||||
{
|
||||
size_t n = printbuf_remaining(out);
|
||||
|
||||
if (n) {
|
||||
n = min(n - 1, len);
|
||||
memcpy(out->pos, src, n);
|
||||
out->pos += n;
|
||||
*out->pos = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#include "eytzinger.h"
|
||||
|
||||
static int alignment_ok(const void *base, size_t align)
|
||||
|
@ -235,10 +235,17 @@ do { \
|
||||
#define ANYSINT_MAX(t) \
|
||||
((((t) 1 << (sizeof(t) * 8 - 2)) - (t) 1) * (t) 2 + (t) 1)
|
||||
|
||||
enum printbuf_units {
|
||||
PRINTBUF_UNITS_RAW,
|
||||
PRINTBUF_UNITS_BYTES,
|
||||
PRINTBUF_UNITS_HUMAN_READABLE,
|
||||
};
|
||||
|
||||
struct printbuf {
|
||||
char *pos;
|
||||
char *end;
|
||||
unsigned indent;
|
||||
char *pos;
|
||||
char *end;
|
||||
unsigned indent;
|
||||
enum printbuf_units units;
|
||||
};
|
||||
|
||||
static inline size_t printbuf_remaining(struct printbuf *buf)
|
||||
@ -272,7 +279,7 @@ static inline void printbuf_indent_pop(struct printbuf *buf, unsigned spaces)
|
||||
buf->indent -= spaces;
|
||||
}
|
||||
|
||||
static inline void printbuf_newline(struct printbuf *buf)
|
||||
static inline void pr_newline(struct printbuf *buf)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
@ -281,7 +288,45 @@ static inline void printbuf_newline(struct printbuf *buf)
|
||||
pr_buf(buf, " ");
|
||||
}
|
||||
|
||||
void bch_scnmemcpy(struct printbuf *, const char *, size_t);
|
||||
void bch2_pr_units(struct printbuf *, s64, s64);
|
||||
#define pr_units(...) bch2_pr_units(__VA_ARGS__)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
static inline void pr_time(struct printbuf *out, u64 time)
|
||||
{
|
||||
pr_buf(out, "%llu", time);
|
||||
}
|
||||
#else
|
||||
#include <time.h>
|
||||
static inline void pr_time(struct printbuf *out, u64 _time)
|
||||
{
|
||||
char time_str[64];
|
||||
time_t time = _time;
|
||||
struct tm *tm = localtime(&time);
|
||||
size_t err = strftime(time_str, sizeof(time_str), "%c", tm);
|
||||
if (!err)
|
||||
pr_buf(out, "(formatting error)");
|
||||
else
|
||||
pr_buf(out, "%s", time_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL__
|
||||
static inline void uuid_unparse_lower(u8 *uuid, char *out)
|
||||
{
|
||||
sprintf(out, "%plU", uuid);
|
||||
}
|
||||
#else
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
static inline void pr_uuid(struct printbuf *out, u8 *uuid)
|
||||
{
|
||||
char uuid_str[40];
|
||||
|
||||
uuid_unparse_lower(uuid, uuid_str);
|
||||
pr_buf(out, uuid_str);
|
||||
}
|
||||
|
||||
int bch2_strtoint_h(const char *, int *);
|
||||
int bch2_strtouint_h(const char *, unsigned int *);
|
||||
@ -768,13 +813,4 @@ static inline int u8_cmp(u8 l, u8 r)
|
||||
return cmp_int(l, r);
|
||||
}
|
||||
|
||||
#ifdef __KERNEL__
|
||||
static inline void uuid_unparse_lower(u8 *uuid, char *out)
|
||||
{
|
||||
sprintf(out, "%plU", uuid);
|
||||
}
|
||||
#else
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
#endif /* _BCACHEFS_UTIL_H */
|
||||
|
@ -111,11 +111,11 @@ void bch2_xattr_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
else
|
||||
pr_buf(out, "(unknown type %u)", xattr.v->x_type);
|
||||
|
||||
bch_scnmemcpy(out, xattr.v->x_name,
|
||||
xattr.v->x_name_len);
|
||||
pr_buf(out, ":");
|
||||
bch_scnmemcpy(out, xattr_val(xattr.v),
|
||||
le16_to_cpu(xattr.v->x_val_len));
|
||||
pr_buf(out, "%.*s:%.*s",
|
||||
xattr.v->x_name_len,
|
||||
xattr.v->x_name,
|
||||
le16_to_cpu(xattr.v->x_val_len),
|
||||
(char *) xattr_val(xattr.v));
|
||||
}
|
||||
|
||||
static int bch2_xattr_get_trans(struct btree_trans *trans, struct bch_inode_info *inode,
|
||||
|
Loading…
Reference in New Issue
Block a user