]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/xattr.c
Update bcachefs sources to 96b991466a bcachefs: Improve error message in fsck
[bcachefs-tools-debian] / libbcachefs / xattr.c
index 5ba52a3ff0b29719208008d780aa94d7c374f768..725a6f3ef8ce877ccfbdd984a789d2a283235b7a 100644 (file)
@@ -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,13 +257,13 @@ 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)
@@ -273,13 +273,14 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
        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);
+       bch2_trans_init(&trans, c, 0, 0);
 
        for_each_btree_key(&trans, iter, BTREE_ID_XATTRS,
-                          POS(inum, 0), 0, k) {
+                          POS(inum, 0), 0, k, ret) {
                BUG_ON(k.k->p.inode < inum);
 
                if (k.k->p.inode > inum)
@@ -288,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_trans_exit(&trans);
+       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,
@@ -329,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,
@@ -388,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);
@@ -408,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);
+       val_len = out.pos - buf;
 
-               bch2_opt_to_text(&out, c, opt, v, 0);
+       if (buffer && val_len > size)
+               return -ERANGE;
 
-               return out.pos - buf;
-       } else {
-               struct printbuf out = _PBUF(buffer, size);
-
-               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,