X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libbcachefs%2Fxattr.c;h=725a6f3ef8ce877ccfbdd984a789d2a283235b7a;hb=2aed686c235a7d08adf601f147f823eb62e697a1;hp=b204b53bb9d6a3b970a9ca2156ee4f52088815be;hpb=ddb58076ef4fe4572ab8537785fc67052f47bf5b;p=bcachefs-tools-debian diff --git a/libbcachefs/xattr.c b/libbcachefs/xattr.c index b204b53..725a6f3 100644 --- a/libbcachefs/xattr.c +++ b/libbcachefs/xattr.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 #include "bcachefs.h" #include "bkey_methods.h" @@ -125,7 +126,7 @@ int bch2_xattr_get(struct bch_fs *c, struct bch_inode_info *inode, struct bkey_s_c_xattr xattr; int ret; - bch2_trans_init(&trans, c); + bch2_trans_init(&trans, c, 0, 0); iter = bch2_hash_lookup(&trans, bch2_xattr_hash_desc, &inode->ei_str_hash, inode->v.i_ino, @@ -197,55 +198,54 @@ int bch2_xattr_set(struct btree_trans *trans, u64 inum, return ret; } -static void __bch2_xattr_emit(const char *prefix, - const char *name, size_t name_len, - char **buffer, size_t *buffer_size, - ssize_t *ret) +struct xattr_buf { + char *buf; + size_t len; + size_t used; +}; + +static int __bch2_xattr_emit(const char *prefix, + const char *name, size_t name_len, + struct xattr_buf *buf) { const size_t prefix_len = strlen(prefix); const size_t total_len = prefix_len + name_len + 1; - if (*buffer) { - if (total_len > *buffer_size) { - *ret = -ERANGE; - return; - } + if (buf->buf) { + if (buf->used + total_len > buf->len) + return -ERANGE; - memcpy(*buffer, prefix, prefix_len); - memcpy(*buffer + prefix_len, + memcpy(buf->buf + buf->used, prefix, prefix_len); + memcpy(buf->buf + buf->used + prefix_len, name, name_len); - (*buffer)[prefix_len + name_len] = '\0'; - - *buffer += total_len; - *buffer_size -= total_len; + buf->buf[buf->used + prefix_len + name_len] = '\0'; } - *ret += total_len; + buf->used += total_len; + return 0; } -static void bch2_xattr_emit(struct dentry *dentry, +static int bch2_xattr_emit(struct dentry *dentry, const struct bch_xattr *xattr, - char **buffer, size_t *buffer_size, - ssize_t *ret) + struct xattr_buf *buf) { const struct xattr_handler *handler = bch2_xattr_type_to_handler(xattr->x_type); - if (handler && (!handler->list || handler->list(dentry))) - __bch2_xattr_emit(handler->prefix ?: handler->name, - xattr->x_name, xattr->x_name_len, - buffer, buffer_size, ret); + return handler && (!handler->list || handler->list(dentry)) + ? __bch2_xattr_emit(handler->prefix ?: handler->name, + xattr->x_name, xattr->x_name_len, buf) + : 0; } -static void bch2_xattr_list_bcachefs(struct bch_fs *c, - struct bch_inode_info *inode, - char **buffer, - size_t *buffer_size, - ssize_t *ret, - bool all) +static int bch2_xattr_list_bcachefs(struct bch_fs *c, + struct bch_inode_info *inode, + struct xattr_buf *buf, + bool all) { const char *prefix = all ? "bcachefs_effective." : "bcachefs."; unsigned id; + int ret = 0; u64 v; for (id = 0; id < Inode_opt_nr; id++) { @@ -257,25 +257,30 @@ static void bch2_xattr_list_bcachefs(struct bch_fs *c, !(inode->ei_inode.bi_fields_set & (1 << id))) continue; - __bch2_xattr_emit(prefix, - bch2_inode_opts[id], - strlen(bch2_inode_opts[id]), - buffer, buffer_size, ret); - if (*ret < 0) + ret = __bch2_xattr_emit(prefix, bch2_inode_opts[id], + strlen(bch2_inode_opts[id]), buf); + if (ret) break; } + + return ret; } ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) { struct bch_fs *c = dentry->d_sb->s_fs_info; struct bch_inode_info *inode = to_bch_ei(dentry->d_inode); - struct btree_iter iter; + struct btree_trans trans; + struct btree_iter *iter; struct bkey_s_c k; + struct xattr_buf buf = { .buf = buffer, .len = buffer_size }; u64 inum = dentry->d_inode->i_ino; - ssize_t ret = 0; + int ret; + + bch2_trans_init(&trans, c, 0, 0); - for_each_btree_key(&iter, c, BTREE_ID_XATTRS, POS(inum, 0), 0, k) { + for_each_btree_key(&trans, iter, BTREE_ID_XATTRS, + POS(inum, 0), 0, k, ret) { BUG_ON(k.k->p.inode < inum); if (k.k->p.inode > inum) @@ -284,27 +289,24 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) if (k.k->type != KEY_TYPE_xattr) continue; - bch2_xattr_emit(dentry, bkey_s_c_to_xattr(k).v, - &buffer, &buffer_size, &ret); - if (ret < 0) + ret = bch2_xattr_emit(dentry, bkey_s_c_to_xattr(k).v, &buf); + if (ret) break; } - bch2_btree_iter_unlock(&iter); + ret = bch2_trans_exit(&trans) ?: ret; - if (ret < 0) + if (ret) return ret; - bch2_xattr_list_bcachefs(c, inode, &buffer, - &buffer_size, &ret, false); - if (ret < 0) + ret = bch2_xattr_list_bcachefs(c, inode, &buf, false); + if (ret) return ret; - bch2_xattr_list_bcachefs(c, inode, &buffer, - &buffer_size, &ret, true); - if (ret < 0) + ret = bch2_xattr_list_bcachefs(c, inode, &buf, true); + if (ret) return ret; - return ret; + return buf.used; } static int bch2_xattr_get_handler(const struct xattr_handler *handler, @@ -325,7 +327,7 @@ 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; - return bch2_trans_do(c, &inode->ei_journal_seq, BTREE_INSERT_ATOMIC, + return bch2_trans_do(c, NULL, &inode->ei_journal_seq, 0, bch2_xattr_set(&trans, inode->v.i_ino, &inode->ei_str_hash, name, value, size, @@ -384,6 +386,9 @@ static int __bch2_xattr_bcachefs_get(const struct xattr_handler *handler, bch2_inode_opts_to_opts(bch2_inode_opts_get(&inode->ei_inode)); const struct bch_option *opt; int id, inode_opt_id; + char buf[512]; + struct printbuf out = PBUF(buf); + unsigned val_len; u64 v; id = bch2_opt_lookup(name); @@ -404,23 +409,16 @@ static int __bch2_xattr_bcachefs_get(const struct xattr_handler *handler, return -ENODATA; v = bch2_opt_get_by_id(&opts, id); + bch2_opt_to_text(&out, c, opt, v, 0); - if (!buffer) { - char buf[512]; - struct printbuf out = PBUF(buf); - - bch2_opt_to_text(&out, c, opt, v, 0); + val_len = out.pos - buf; - return out.pos - buf; - } else { - struct printbuf out = _PBUF(buffer, size); + if (buffer && val_len > size) + return -ERANGE; - bch2_opt_to_text(&out, c, opt, v, 0); - - return printbuf_remaining(&out) - ? (void *) out.pos - buffer - : -ERANGE; - } + if (buffer) + memcpy(buffer, buf, val_len); + return val_len; } static int bch2_xattr_bcachefs_get(const struct xattr_handler *handler,