]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/fs.c
Update bcachefs sources to f38382c574 bcachefs: Improve key marking interface
[bcachefs-tools-debian] / libbcachefs / fs.c
index ae875870b78ddf0b638f33a62d671a49d36e516b..a324278b6f43d1df3dcf0d67664c2b52d0458ec3 100644 (file)
@@ -47,30 +47,6 @@ static void journal_seq_copy(struct bch_inode_info *dst,
        } while ((v = cmpxchg(&dst->ei_journal_seq, old, journal_seq)) != old);
 }
 
-static inline int ptrcmp(void *l, void *r)
-{
-       return (l > r) - (l < r);
-}
-
-#define __bch2_lock_inodes(_lock, ...)                                 \
-do {                                                                   \
-       struct bch_inode_info *a[] = { NULL, __VA_ARGS__ };             \
-       unsigned i;                                                     \
-                                                                       \
-       bubble_sort(&a[1], ARRAY_SIZE(a) - 1 , ptrcmp);                 \
-                                                                       \
-       for (i = ARRAY_SIZE(a) - 1; a[i]; --i)                          \
-               if (a[i] != a[i - 1]) {                                 \
-                       if (_lock)                                      \
-                               mutex_lock_nested(&a[i]->ei_update_lock, i);\
-                       else                                            \
-                               mutex_unlock(&a[i]->ei_update_lock);    \
-               }                                                       \
-} while (0)
-
-#define bch2_lock_inodes(...)  __bch2_lock_inodes(true, __VA_ARGS__)
-#define bch2_unlock_inodes(...)        __bch2_lock_inodes(false, __VA_ARGS__)
-
 /*
  * I_SIZE_DIRTY requires special handling:
  *
@@ -119,7 +95,6 @@ void bch2_inode_update_after_write(struct bch_fs *c,
                inode->v.i_ctime = bch2_time_to_timespec(c, bi->bi_ctime);
 
        inode->ei_inode         = *bi;
-       inode->ei_qid           = bch_qid(bi);
 
        bch2_inode_flags_to_vfs(inode);
 }
@@ -130,22 +105,30 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans,
                                inode_set_fn set,
                                void *p)
 {
-       struct btree_iter *iter;
+       struct bch_fs *c = trans->c;
+       struct btree_iter *iter = NULL;
        struct bkey_inode_buf *inode_p;
        int ret;
 
        lockdep_assert_held(&inode->ei_update_lock);
 
-       iter = bch2_trans_get_iter(trans, BTREE_ID_INODES,
-                       POS(inode->v.i_ino, 0),
-                       BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
-       if (IS_ERR(iter))
-               return PTR_ERR(iter);
-
-       /* The btree node lock is our lock on the inode: */
-       ret = bch2_btree_iter_traverse(iter);
-       if (ret)
-               return ret;
+       if (c->opts.new_inode_updates) {
+       /* XXX: Don't do this with btree locks held */
+       if (!inode->ei_inode_update)
+               inode->ei_inode_update =
+                       bch2_deferred_update_alloc(c, BTREE_ID_INODES, 64);
+       } else {
+               iter = bch2_trans_get_iter(trans, BTREE_ID_INODES,
+                                          POS(inode->v.i_ino, 0),
+                                          BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
+               if (IS_ERR(iter))
+                       return PTR_ERR(iter);
+
+               /* The btree node lock is our lock on the inode: */
+               ret = bch2_btree_iter_traverse(iter);
+               if (ret)
+                       return ret;
+       }
 
        *inode_u = inode->ei_inode;
 
@@ -160,7 +143,15 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans,
                return PTR_ERR(inode_p);
 
        bch2_inode_pack(inode_p, inode_u);
-       bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, &inode_p->inode.k_i));
+
+       if (!inode->ei_inode_update)
+               bch2_trans_update(trans,
+                       BTREE_INSERT_ENTRY(iter, &inode_p->inode.k_i));
+       else
+               bch2_trans_update(trans,
+                       BTREE_INSERT_DEFERRED(inode->ei_inode_update,
+                                             &inode_p->inode.k_i));
+
        return 0;
 }
 
@@ -173,7 +164,7 @@ int __must_check bch2_write_inode(struct bch_fs *c,
        struct bch_inode_unpacked inode_u;
        int ret;
 
-       bch2_trans_init(&trans, c);
+       bch2_trans_init(&trans, c, 0, 0);
 retry:
        bch2_trans_begin(&trans);
 
@@ -197,7 +188,68 @@ retry:
        return ret < 0 ? ret : 0;
 }
 
-static struct inode *bch2_vfs_inode_get(struct bch_fs *c, u64 inum)
+int bch2_fs_quota_transfer(struct bch_fs *c,
+                          struct bch_inode_info *inode,
+                          struct bch_qid new_qid,
+                          unsigned qtypes,
+                          enum quota_acct_mode mode)
+{
+       unsigned i;
+       int ret;
+
+       qtypes &= enabled_qtypes(c);
+
+       for (i = 0; i < QTYP_NR; i++)
+               if (new_qid.q[i] == inode->ei_qid.q[i])
+                       qtypes &= ~(1U << i);
+
+       if (!qtypes)
+               return 0;
+
+       mutex_lock(&inode->ei_quota_lock);
+
+       ret = bch2_quota_transfer(c, qtypes, new_qid,
+                                 inode->ei_qid,
+                                 inode->v.i_blocks +
+                                 inode->ei_quota_reserved,
+                                 mode);
+       if (!ret)
+               for (i = 0; i < QTYP_NR; i++)
+                       if (qtypes & (1 << i))
+                               inode->ei_qid.q[i] = new_qid.q[i];
+
+       mutex_unlock(&inode->ei_quota_lock);
+
+       return ret;
+}
+
+int bch2_reinherit_attrs_fn(struct bch_inode_info *inode,
+                           struct bch_inode_unpacked *bi,
+                           void *p)
+{
+       struct bch_inode_info *dir = p;
+       u64 src, dst;
+       unsigned id;
+       int ret = 1;
+
+       for (id = 0; id < Inode_opt_nr; id++) {
+               if (bi->bi_fields_set & (1 << id))
+                       continue;
+
+               src = bch2_inode_opt_get(&dir->ei_inode, id);
+               dst = bch2_inode_opt_get(bi, id);
+
+               if (src == dst)
+                       continue;
+
+               bch2_inode_opt_set(bi, id, src);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+struct inode *bch2_vfs_inode_get(struct bch_fs *c, u64 inum)
 {
        struct bch_inode_unpacked inode_u;
        struct bch_inode_info *inode;
@@ -274,14 +326,13 @@ __bch2_create(struct bch_inode_info *dir, struct dentry *dentry,
        bch2_inode_init(c, &inode_u, 0, 0, 0, rdev, &dir->ei_inode);
        bch2_inode_init_owner(&inode_u, &dir->v, mode);
 
-       inode_u.bi_project = dir->ei_qid.q[QTYP_PRJ];
-
        hash_info = bch2_hash_info_init(c, &inode_u);
 
        if (tmpfile)
                inode_u.bi_flags |= BCH_INODE_UNLINKED;
 
-       ret = bch2_quota_acct(c, bch_qid(&inode_u), Q_INO, 1, BCH_QUOTA_PREALLOC);
+       ret = bch2_quota_acct(c, bch_qid(&inode_u), Q_INO, 1,
+                             KEY_TYPE_QUOTA_PREALLOC);
        if (ret)
                return ERR_PTR(ret);
 
@@ -304,7 +355,7 @@ __bch2_create(struct bch_inode_info *dir, struct dentry *dentry,
        if (!tmpfile)
                mutex_lock(&dir->ei_update_lock);
 
-       bch2_trans_init(&trans, c);
+       bch2_trans_init(&trans, c, 8, 1024);
 retry:
        bch2_trans_begin(&trans);
 
@@ -341,12 +392,10 @@ retry:
        if (unlikely(ret))
                goto err_trans;
 
-       atomic_long_inc(&c->nr_inodes);
-
        if (!tmpfile) {
                bch2_inode_update_after_write(c, dir, &dir_u,
                                              ATTR_MTIME|ATTR_CTIME);
-               journal_seq_copy(dir, inode->ei_journal_seq);
+               journal_seq_copy(dir, journal_seq);
                mutex_unlock(&dir->ei_update_lock);
        }
 
@@ -394,7 +443,7 @@ err_trans:
        make_bad_inode(&inode->v);
        iput(&inode->v);
 err:
-       bch2_quota_acct(c, bch_qid(&inode_u), Q_INO, -1, BCH_QUOTA_WARN);
+       bch2_quota_acct(c, bch_qid(&inode_u), Q_INO, -1, KEY_TYPE_QUOTA_WARN);
        inode = ERR_PTR(ret);
        goto out;
 }
@@ -458,7 +507,7 @@ static int __bch2_link(struct bch_fs *c,
        int ret;
 
        mutex_lock(&inode->ei_update_lock);
-       bch2_trans_init(&trans, c);
+       bch2_trans_init(&trans, c, 4, 1024);
 retry:
        bch2_trans_begin(&trans);
 
@@ -545,7 +594,7 @@ static int bch2_unlink(struct inode *vdir, struct dentry *dentry)
        int ret;
 
        bch2_lock_inodes(dir, inode);
-       bch2_trans_init(&trans, c);
+       bch2_trans_init(&trans, c, 4, 1024);
 retry:
        bch2_trans_begin(&trans);
 
@@ -666,6 +715,7 @@ static int inode_update_for_rename_fn(struct bch_inode_info *inode,
                                      void *p)
 {
        struct rename_info *info = p;
+       int ret;
 
        if (inode == info->src_dir) {
                bi->bi_nlink -= S_ISDIR(info->src_inode->v.i_mode);
@@ -680,6 +730,19 @@ static int inode_update_for_rename_fn(struct bch_inode_info *inode,
                        S_ISDIR(info->dst_inode->v.i_mode);
        }
 
+       if (inode == info->src_inode) {
+               ret = bch2_reinherit_attrs_fn(inode, bi, info->dst_dir);
+
+               BUG_ON(!ret && S_ISDIR(info->src_inode->v.i_mode));
+       }
+
+       if (inode == info->dst_inode &&
+           info->mode == BCH_RENAME_EXCHANGE) {
+               ret = bch2_reinherit_attrs_fn(inode, bi, info->src_dir);
+
+               BUG_ON(!ret && S_ISDIR(info->dst_inode->v.i_mode));
+       }
+
        if (inode == info->dst_inode &&
            info->mode == BCH_RENAME_OVERWRITE) {
                BUG_ON(bi->bi_nlink &&
@@ -738,12 +801,45 @@ static int bch2_rename2(struct inode *src_vdir, struct dentry *src_dentry,
                        return ret;
        }
 
+       bch2_trans_init(&trans, c, 8, 2048);
+
        bch2_lock_inodes(i.src_dir,
                         i.dst_dir,
                         i.src_inode,
                         i.dst_inode);
 
-       bch2_trans_init(&trans, c);
+       if (S_ISDIR(i.src_inode->v.i_mode) &&
+           inode_attrs_changing(i.dst_dir, i.src_inode)) {
+               ret = -EXDEV;
+               goto err;
+       }
+
+       if (i.mode == BCH_RENAME_EXCHANGE &&
+           S_ISDIR(i.dst_inode->v.i_mode) &&
+           inode_attrs_changing(i.src_dir, i.dst_inode)) {
+               ret = -EXDEV;
+               goto err;
+       }
+
+       if (inode_attr_changing(i.dst_dir, i.src_inode, Inode_opt_project)) {
+               ret = bch2_fs_quota_transfer(c, i.src_inode,
+                                            i.dst_dir->ei_qid,
+                                            1 << QTYP_PRJ,
+                                            KEY_TYPE_QUOTA_PREALLOC);
+               if (ret)
+                       goto err;
+       }
+
+       if (i.mode == BCH_RENAME_EXCHANGE &&
+           inode_attr_changing(i.src_dir, i.dst_inode, Inode_opt_project)) {
+               ret = bch2_fs_quota_transfer(c, i.dst_inode,
+                                            i.src_dir->ei_qid,
+                                            1 << QTYP_PRJ,
+                                            KEY_TYPE_QUOTA_PREALLOC);
+               if (ret)
+                       goto err;
+       }
+
 retry:
        bch2_trans_begin(&trans);
        i.now = bch2_current_time(c);
@@ -794,6 +890,17 @@ retry:
                                              ATTR_CTIME);
 err:
        bch2_trans_exit(&trans);
+
+       bch2_fs_quota_transfer(c, i.src_inode,
+                              bch_qid(&i.src_inode->ei_inode),
+                              1 << QTYP_PRJ,
+                              KEY_TYPE_QUOTA_NOCHECK);
+       if (i.dst_inode)
+               bch2_fs_quota_transfer(c, i.dst_inode,
+                                      bch_qid(&i.dst_inode->ei_inode),
+                                      1 << QTYP_PRJ,
+                                      KEY_TYPE_QUOTA_NOCHECK);
+
        bch2_unlock_inodes(i.src_dir,
                           i.dst_dir,
                           i.src_inode,
@@ -840,38 +947,28 @@ static int inode_update_for_setattr_fn(struct bch_inode_info *inode,
 static int bch2_setattr_nonsize(struct bch_inode_info *inode, struct iattr *iattr)
 {
        struct bch_fs *c = inode->v.i_sb->s_fs_info;
-       struct bch_qid qid = inode->ei_qid;
+       struct bch_qid qid;
        struct btree_trans trans;
        struct bch_inode_unpacked inode_u;
        struct posix_acl *acl = NULL;
-       unsigned qtypes = 0;
        int ret;
 
        mutex_lock(&inode->ei_update_lock);
 
-       if (c->opts.usrquota &&
-           (iattr->ia_valid & ATTR_UID) &&
-           !uid_eq(iattr->ia_uid, inode->v.i_uid)) {
-               qid.q[QTYP_USR] = from_kuid(&init_user_ns, iattr->ia_uid),
-               qtypes |= 1 << QTYP_USR;
-       }
+       qid = inode->ei_qid;
 
-       if (c->opts.grpquota &&
-           (iattr->ia_valid & ATTR_GID) &&
-           !gid_eq(iattr->ia_gid, inode->v.i_gid)) {
+       if (iattr->ia_valid & ATTR_UID)
+               qid.q[QTYP_USR] = from_kuid(&init_user_ns, iattr->ia_uid);
+
+       if (iattr->ia_valid & ATTR_GID)
                qid.q[QTYP_GRP] = from_kgid(&init_user_ns, iattr->ia_gid);
-               qtypes |= 1 << QTYP_GRP;
-       }
 
-       if (qtypes) {
-               ret = bch2_quota_transfer(c, qtypes, qid, inode->ei_qid,
-                                         inode->v.i_blocks +
-                                         inode->ei_quota_reserved);
-               if (ret)
-                       goto err;
-       }
+       ret = bch2_fs_quota_transfer(c, inode, qid, ~0,
+                                    KEY_TYPE_QUOTA_PREALLOC);
+       if (ret)
+               goto err;
 
-       bch2_trans_init(&trans, c);
+       bch2_trans_init(&trans, c, 0, 0);
 retry:
        bch2_trans_begin(&trans);
        kfree(acl);
@@ -973,33 +1070,33 @@ static int bch2_fill_extent(struct fiemap_extent_info *info,
 {
        if (bkey_extent_is_data(&k->k)) {
                struct bkey_s_c_extent e = bkey_i_to_s_c_extent(k);
-               const struct bch_extent_ptr *ptr;
-               struct bch_extent_crc_unpacked crc;
+               const union bch_extent_entry *entry;
+               struct extent_ptr_decoded p;
                int ret;
 
-               extent_for_each_ptr_crc(e, ptr, crc) {
+               extent_for_each_ptr_decode(e, p, entry) {
                        int flags2 = 0;
-                       u64 offset = ptr->offset;
+                       u64 offset = p.ptr.offset;
 
-                       if (crc.compression_type)
+                       if (p.crc.compression_type)
                                flags2 |= FIEMAP_EXTENT_ENCODED;
                        else
-                               offset += crc.offset;
+                               offset += p.crc.offset;
 
                        if ((offset & (PAGE_SECTORS - 1)) ||
                            (e.k->size & (PAGE_SECTORS - 1)))
                                flags2 |= FIEMAP_EXTENT_NOT_ALIGNED;
 
                        ret = fiemap_fill_next_extent(info,
-                                                     bkey_start_offset(e.k) << 9,
-                                                     offset << 9,
-                                                     e.k->size << 9, flags|flags2);
+                                               bkey_start_offset(e.k) << 9,
+                                               offset << 9,
+                                               e.k->size << 9, flags|flags2);
                        if (ret)
                                return ret;
                }
 
                return 0;
-       } else if (k->k.type == BCH_RESERVATION) {
+       } else if (k->k.type == KEY_TYPE_reservation) {
                return fiemap_fill_next_extent(info,
                                               bkey_start_offset(&k->k) << 9,
                                               0, k->k.size << 9,
@@ -1016,7 +1113,8 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
 {
        struct bch_fs *c = vinode->i_sb->s_fs_info;
        struct bch_inode_info *ei = to_bch_ei(vinode);
-       struct btree_iter iter;
+       struct btree_trans trans;
+       struct btree_iter *iter;
        struct bkey_s_c k;
        BKEY_PADDED(k) tmp;
        bool have_extent = false;
@@ -1025,10 +1123,12 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
        if (start + len < start)
                return -EINVAL;
 
-       for_each_btree_key(&iter, c, BTREE_ID_EXTENTS,
-                          POS(ei->v.i_ino, start >> 9), 0, k)
+       bch2_trans_init(&trans, c, 0, 0);
+
+       for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
+                          POS(ei->v.i_ino, start >> 9), 0, k, ret)
                if (bkey_extent_is_data(k.k) ||
-                   k.k->type == BCH_RESERVATION) {
+                   k.k->type == KEY_TYPE_reservation) {
                        if (bkey_cmp(bkey_start_pos(k.k),
                                     POS(ei->v.i_ino, (start + len) >> 9)) >= 0)
                                break;
@@ -1036,17 +1136,17 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
                        if (have_extent) {
                                ret = bch2_fill_extent(info, &tmp.k, 0);
                                if (ret)
-                                       goto out;
+                                       break;
                        }
 
                        bkey_reassemble(&tmp.k, k);
                        have_extent = true;
                }
 
-       if (have_extent)
+       if (!ret && have_extent)
                ret = bch2_fill_extent(info, &tmp.k, FIEMAP_EXTENT_LAST);
-out:
-       bch2_btree_iter_unlock(&iter);
+
+       ret = bch2_trans_exit(&trans) ?: ret;
        return ret < 0 ? ret : 0;
 }
 
@@ -1230,6 +1330,7 @@ static void bch2_vfs_inode_init(struct bch_fs *c,
        inode->ei_journal_seq   = 0;
        inode->ei_quota_reserved = 0;
        inode->ei_str_hash      = bch2_hash_info_init(c, bi);
+       inode->ei_qid           = bch_qid(bi);
 
        inode->v.i_mapping->a_ops = &bch_address_space_operations;
 
@@ -1264,6 +1365,7 @@ static struct inode *bch2_alloc_inode(struct super_block *sb)
        inode_init_once(&inode->v);
        mutex_init(&inode->ei_update_lock);
        mutex_init(&inode->ei_quota_lock);
+       inode->ei_inode_update = NULL;
        inode->ei_journal_seq = 0;
 
        return &inode->v;
@@ -1327,15 +1429,16 @@ static void bch2_evict_inode(struct inode *vinode)
 
        BUG_ON(!is_bad_inode(&inode->v) && inode->ei_quota_reserved);
 
+       if (inode->ei_inode_update)
+               bch2_deferred_update_free(c, inode->ei_inode_update);
+       inode->ei_inode_update = NULL;
+
        if (!inode->v.i_nlink && !is_bad_inode(&inode->v)) {
                bch2_quota_acct(c, inode->ei_qid, Q_SPC, -((s64) inode->v.i_blocks),
-                               BCH_QUOTA_WARN);
+                               KEY_TYPE_QUOTA_WARN);
                bch2_quota_acct(c, inode->ei_qid, Q_INO, -1,
-                               BCH_QUOTA_WARN);
+                               KEY_TYPE_QUOTA_WARN);
                bch2_inode_rm(c, inode->v.i_ino);
-
-               WARN_ONCE(atomic_long_dec_return(&c->nr_inodes) < 0,
-                         "nr_inodes < 0");
        }
 }
 
@@ -1343,18 +1446,16 @@ static int bch2_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *sb = dentry->d_sb;
        struct bch_fs *c = sb->s_fs_info;
-       struct bch_fs_usage usage = bch2_fs_usage_read(c);
-       u64 hidden_metadata = usage.buckets[BCH_DATA_SB] +
-               usage.buckets[BCH_DATA_JOURNAL];
+       struct bch_fs_usage_short usage = bch2_fs_usage_read_short(c);
        unsigned shift = sb->s_blocksize_bits - 9;
        u64 fsid;
 
        buf->f_type     = BCACHEFS_STATFS_MAGIC;
        buf->f_bsize    = sb->s_blocksize;
-       buf->f_blocks   = (c->capacity - hidden_metadata) >> shift;
-       buf->f_bfree    = (c->capacity - bch2_fs_sectors_used(c, usage)) >> shift;
+       buf->f_blocks   = usage.capacity >> shift;
+       buf->f_bfree    = (usage.capacity - usage.used) >> shift;
        buf->f_bavail   = buf->f_bfree;
-       buf->f_files    = atomic_long_read(&c->nr_inodes);
+       buf->f_files    = usage.nr_inodes;
        buf->f_ffree    = U64_MAX;
 
        fsid = le64_to_cpup((void *) c->sb.user_uuid.b) ^
@@ -1410,7 +1511,7 @@ static struct bch_fs *__bch2_open_as_blockdevs(const char *dev_name, char * cons
                 */
 
                c1 = bch2_path_to_fs(devs[0]);
-               if (!c1)
+               if (IS_ERR(c1))
                        return c;
 
                for (i = 1; i < nr_devs; i++) {
@@ -1432,7 +1533,7 @@ static struct bch_fs *__bch2_open_as_blockdevs(const char *dev_name, char * cons
 
        mutex_lock(&c->state_lock);
 
-       if (!bch2_fs_running(c)) {
+       if (!test_bit(BCH_FS_STARTED, &c->flags)) {
                mutex_unlock(&c->state_lock);
                closure_put(&c->cl);
                pr_err("err mounting %s: incomplete filesystem", dev_name);
@@ -1481,29 +1582,28 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data)
        struct bch_opts opts = bch2_opts_empty();
        int ret;
 
-       opt_set(opts, read_only, (*flags & MS_RDONLY) != 0);
+       opt_set(opts, read_only, (*flags & SB_RDONLY) != 0);
 
        ret = bch2_parse_mount_opts(&opts, data);
        if (ret)
                return ret;
 
        if (opts.read_only != c->opts.read_only) {
-               const char *err = NULL;
-
                mutex_lock(&c->state_lock);
 
                if (opts.read_only) {
                        bch2_fs_read_only(c);
 
-                       sb->s_flags |= MS_RDONLY;
+                       sb->s_flags |= SB_RDONLY;
                } else {
-                       err = bch2_fs_read_write(c);
-                       if (err) {
-                               bch_err(c, "error going rw: %s", err);
+                       ret = bch2_fs_read_write(c);
+                       if (ret) {
+                               bch_err(c, "error going rw: %i", ret);
+                               mutex_unlock(&c->state_lock);
                                return -EINVAL;
                        }
 
-                       sb->s_flags &= ~MS_RDONLY;
+                       sb->s_flags &= ~SB_RDONLY;
                }
 
                c->opts.read_only = opts.read_only;
@@ -1527,13 +1627,13 @@ static int bch2_show_options(struct seq_file *seq, struct dentry *root)
                const struct bch_option *opt = &bch2_opt_table[i];
                u64 v = bch2_opt_get_by_id(&c->opts, i);
 
-               if (opt->mode < OPT_MOUNT)
+               if (!(opt->mode & OPT_MOUNT))
                        continue;
 
                if (v == bch2_opt_get_by_id(&bch2_opts_default, i))
                        continue;
 
-               bch2_opt_to_text(c, buf, sizeof(buf), opt, v,
+               bch2_opt_to_text(&PBUF(buf), c, opt, v,
                                 OPT_SHOW_MOUNT_STYLE);
                seq_putc(seq, ',');
                seq_puts(seq, buf);
@@ -1581,7 +1681,7 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type,
        unsigned i;
        int ret;
 
-       opt_set(opts, read_only, (flags & MS_RDONLY) != 0);
+       opt_set(opts, read_only, (flags & SB_RDONLY) != 0);
 
        ret = bch2_parse_mount_opts(&opts, data);
        if (ret)
@@ -1591,7 +1691,7 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type,
        if (IS_ERR(c))
                return ERR_CAST(c);
 
-       sb = sget(fs_type, bch2_test_super, bch2_set_super, flags|MS_NOSEC, c);
+       sb = sget(fs_type, bch2_test_super, bch2_set_super, flags|SB_NOSEC, c);
        if (IS_ERR(sb)) {
                closure_put(&c->cl);
                return ERR_CAST(sb);
@@ -1602,7 +1702,7 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type,
        if (sb->s_root) {
                closure_put(&c->cl);
 
-               if ((flags ^ sb->s_flags) & MS_RDONLY) {
+               if ((flags ^ sb->s_flags) & SB_RDONLY) {
                        ret = -EBUSY;
                        goto err_put_super;
                }
@@ -1645,22 +1745,25 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type,
 
 #ifdef CONFIG_BCACHEFS_POSIX_ACL
        if (c->opts.acl)
-               sb->s_flags     |= MS_POSIXACL;
+               sb->s_flags     |= SB_POSIXACL;
 #endif
 
        vinode = bch2_vfs_inode_get(c, BCACHEFS_ROOT_INO);
        if (IS_ERR(vinode)) {
+               bch_err(c, "error mounting: error getting root inode %i",
+                       (int) PTR_ERR(vinode));
                ret = PTR_ERR(vinode);
                goto err_put_super;
        }
 
        sb->s_root = d_make_root(vinode);
        if (!sb->s_root) {
+               bch_err(c, "error mounting: error allocating root dentry");
                ret = -ENOMEM;
                goto err_put_super;
        }
 
-       sb->s_flags |= MS_ACTIVE;
+       sb->s_flags |= SB_ACTIVE;
 out:
        return dget(sb->s_root);