X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libbcachefs%2Fxattr.c;h=b5022a8b38c79bab1d9cf8b28ff9c7e94b32ede5;hb=934a84dfaf719af82dadbbe0e2480baff03c905b;hp=c2e9520a0457959f6b00ccfa7982dd7693e5172f;hpb=b797b087a9c47f95a70b4ed38c080af006280e16;p=bcachefs-tools-debian diff --git a/libbcachefs/xattr.c b/libbcachefs/xattr.c index c2e9520..b5022a8 100644 --- a/libbcachefs/xattr.c +++ b/libbcachefs/xattr.c @@ -69,32 +69,51 @@ const struct bch_hash_desc bch2_xattr_hash_desc = { .cmp_bkey = xattr_cmp_bkey, }; -const char *bch2_xattr_invalid(const struct bch_fs *c, struct bkey_s_c k) +int bch2_xattr_invalid(const struct bch_fs *c, struct bkey_s_c k, + int rw, struct printbuf *err) { const struct xattr_handler *handler; struct bkey_s_c_xattr xattr = bkey_s_c_to_xattr(k); - if (bkey_val_bytes(k.k) < sizeof(struct bch_xattr)) - return "value too small"; + if (bkey_val_bytes(k.k) < sizeof(struct bch_xattr)) { + prt_printf(err, "incorrect value size (%zu < %zu)", + bkey_val_bytes(k.k), sizeof(*xattr.v)); + return -BCH_ERR_invalid_bkey; + } if (bkey_val_u64s(k.k) < xattr_val_u64s(xattr.v->x_name_len, - le16_to_cpu(xattr.v->x_val_len))) - return "value too small"; + le16_to_cpu(xattr.v->x_val_len))) { + prt_printf(err, "value too small (%zu < %u)", + bkey_val_u64s(k.k), + xattr_val_u64s(xattr.v->x_name_len, + le16_to_cpu(xattr.v->x_val_len))); + return -BCH_ERR_invalid_bkey; + } + /* XXX why +4 ? */ if (bkey_val_u64s(k.k) > xattr_val_u64s(xattr.v->x_name_len, - le16_to_cpu(xattr.v->x_val_len) + 4)) - return "value too big"; + le16_to_cpu(xattr.v->x_val_len) + 4)) { + prt_printf(err, "value too big (%zu > %u)", + bkey_val_u64s(k.k), + xattr_val_u64s(xattr.v->x_name_len, + le16_to_cpu(xattr.v->x_val_len) + 4)); + return -BCH_ERR_invalid_bkey; + } handler = bch2_xattr_type_to_handler(xattr.v->x_type); - if (!handler) - return "invalid type"; + if (!handler) { + prt_printf(err, "invalid type (%u)", xattr.v->x_type); + return -BCH_ERR_invalid_bkey; + } - if (memchr(xattr.v->x_name, '\0', xattr.v->x_name_len)) - return "xattr name has invalid characters"; + if (memchr(xattr.v->x_name, '\0', xattr.v->x_name_len)) { + prt_printf(err, "xattr name has invalid characters"); + return -BCH_ERR_invalid_bkey; + } - return NULL; + return 0; } void bch2_xattr_to_text(struct printbuf *out, struct bch_fs *c, @@ -105,13 +124,13 @@ void bch2_xattr_to_text(struct printbuf *out, struct bch_fs *c, handler = bch2_xattr_type_to_handler(xattr.v->x_type); if (handler && handler->prefix) - pr_buf(out, "%s", handler->prefix); + prt_printf(out, "%s", handler->prefix); else if (handler) - pr_buf(out, "(type %u)", xattr.v->x_type); + prt_printf(out, "(type %u)", xattr.v->x_type); else - pr_buf(out, "(unknown type %u)", xattr.v->x_type); + prt_printf(out, "(unknown type %u)", xattr.v->x_type); - pr_buf(out, "%.*s:%.*s", + prt_printf(out, "%.*s:%.*s", xattr.v->x_name_len, xattr.v->x_name, le16_to_cpu(xattr.v->x_val_len), @@ -311,13 +330,9 @@ retry: if (ret) goto err; - for_each_btree_key_norestart(&trans, iter, BTREE_ID_xattrs, - SPOS(inum, offset, snapshot), 0, k, ret) { - BUG_ON(k.k->p.inode < inum); - - if (k.k->p.inode > inum) - break; - + for_each_btree_key_upto_norestart(&trans, iter, BTREE_ID_xattrs, + SPOS(inum, offset, snapshot), + POS(inum, U64_MAX), 0, k, ret) { if (k.k->type != KEY_TYPE_xattr) continue; @@ -329,23 +344,25 @@ retry: offset = iter.pos.offset; bch2_trans_iter_exit(&trans, &iter); err: - if (ret == -EINTR) + if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) goto retry; bch2_trans_exit(&trans); if (ret) - return ret; + goto out; ret = bch2_xattr_list_bcachefs(c, &inode->ei_inode, &buf, false); if (ret) - return ret; + goto out; ret = bch2_xattr_list_bcachefs(c, &inode->ei_inode, &buf, true); if (ret) - return ret; + goto out; return buf.used; +out: + return bch2_err_class(ret); } static int bch2_xattr_get_handler(const struct xattr_handler *handler, @@ -354,8 +371,10 @@ static int bch2_xattr_get_handler(const struct xattr_handler *handler, { struct bch_inode_info *inode = to_bch_ei(vinode); struct bch_fs *c = inode->v.i_sb->s_fs_info; + int ret; - return bch2_xattr_get(c, inode, name, buffer, size, handler->flags); + ret = bch2_xattr_get(c, inode, name, buffer, size, handler->flags); + return bch2_err_class(ret); } static int bch2_xattr_set_handler(const struct xattr_handler *handler, @@ -367,11 +386,13 @@ static int bch2_xattr_set_handler(const struct xattr_handler *handler, struct bch_inode_info *inode = to_bch_ei(vinode); struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode); + int ret; - return bch2_trans_do(c, NULL, NULL, 0, + ret = bch2_trans_do(c, NULL, NULL, 0, bch2_xattr_set(&trans, inode_inum(inode), &hash, name, value, size, handler->flags, flags)); + return bch2_err_class(ret); } static const struct xattr_handler bch_xattr_user_handler = { @@ -423,7 +444,7 @@ static int __bch2_xattr_bcachefs_get(const struct xattr_handler *handler, struct bch_inode_info *inode = to_bch_ei(vinode); struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_opts opts = - bch2_inode_opts_to_opts(bch2_inode_opts_get(&inode->ei_inode)); + bch2_inode_opts_to_opts(&inode->ei_inode); const struct bch_option *opt; int id, inode_opt_id; struct printbuf out = PRINTBUF; @@ -529,7 +550,7 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler, memcpy(buf, value, size); buf[size] = '\0'; - ret = bch2_opt_parse(c, NULL, opt, buf, &v); + ret = bch2_opt_parse(c, opt, buf, &v, NULL); kfree(buf); if (ret < 0)