diff --git a/.bcachefs_revision b/.bcachefs_revision index e34b02c1..be8f2eb4 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -ae6e8a59d33008f46bb801850840dbd0a7608bbc +2834633e12dd6e8087f5f52742a3465a228998e5 diff --git a/libbcachefs/fs-ioctl.c b/libbcachefs/fs-ioctl.c index bfbe574d..2c1ecf77 100644 --- a/libbcachefs/fs-ioctl.c +++ b/libbcachefs/fs-ioctl.c @@ -40,14 +40,23 @@ static const unsigned bch_flags_to_xflags[] = { //[__BCH_INODE_PROJINHERIT] = FS_XFLAG_PROJINHERIT; }; -#define map_flags(_map, _in) \ -({ \ - unsigned _i, _out = 0; \ +#define set_flags(_map, _in, _out) \ +do { \ + unsigned _i; \ \ for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \ if ((_in) & (1 << _i)) \ (_out) |= _map[_i]; \ - (_out); \ + else \ + (_out) &= ~_map[_i]; \ +} while (0) + +#define map_flags(_map, _in) \ +({ \ + unsigned _out = 0; \ + \ + set_flags(_map, _in, _out); \ + _out; \ }) #define map_flags_rev(_map, _in) \ @@ -62,16 +71,12 @@ static const unsigned bch_flags_to_xflags[] = { (_out); \ }) -#define set_flags(_map, _in, _out) \ -do { \ - unsigned _i; \ +#define map_defined(_map) \ +({ \ + unsigned _in = ~0; \ \ - for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \ - if ((_in) & (1 << _i)) \ - (_out) |= _map[_i]; \ - else \ - (_out) &= ~_map[_i]; \ -} while (0) + map_flags_rev(_map, _in); \ +}) /* Set VFS inode flags from bcachefs inode: */ void bch2_inode_flags_to_vfs(struct bch_inode_info *inode) @@ -79,6 +84,11 @@ void bch2_inode_flags_to_vfs(struct bch_inode_info *inode) set_flags(bch_flags_to_vfs, inode->ei_inode.bi_flags, inode->v.i_flags); } +struct flags_set { + unsigned mask; + unsigned flags; +}; + static int bch2_inode_flags_set(struct bch_inode_info *inode, struct bch_inode_unpacked *bi, void *p) @@ -87,8 +97,9 @@ static int bch2_inode_flags_set(struct bch_inode_info *inode, * We're relying on btree locking here for exclusion with other ioctl * calls - use the flags in the btree (@bi), not inode->i_flags: */ - unsigned newflags = *((unsigned *) p); - unsigned oldflags = bi->bi_flags; + struct flags_set *s = p; + unsigned newflags = s->flags; + unsigned oldflags = bi->bi_flags & s->mask; if (((newflags ^ oldflags) & (BCH_INODE_APPEND|BCH_INODE_IMMUTABLE)) && !capable(CAP_LINUX_IMMUTABLE)) @@ -99,7 +110,8 @@ static int bch2_inode_flags_set(struct bch_inode_info *inode, (newflags & (BCH_INODE_NODUMP|BCH_INODE_NOATIME)) != newflags) return -EINVAL; - bi->bi_flags = newflags; + bi->bi_flags &= ~s->mask; + bi->bi_flags |= newflags; inode->v.i_ctime = current_time(&inode->v); return 0; } @@ -116,13 +128,14 @@ static int bch2_ioc_setflags(struct bch_fs *c, struct bch_inode_info *inode, void __user *arg) { - unsigned flags, uflags; + struct flags_set s = { .mask = map_defined(bch_flags_to_uflags) }; + unsigned uflags; int ret; if (get_user(uflags, (int __user *) arg)) return -EFAULT; - flags = map_flags_rev(bch_flags_to_uflags, uflags); + s.flags = map_flags_rev(bch_flags_to_uflags, uflags); if (uflags) return -EOPNOTSUPP; @@ -137,7 +150,7 @@ static int bch2_ioc_setflags(struct bch_fs *c, } mutex_lock(&inode->ei_update_lock); - ret = __bch2_write_inode(c, inode, bch2_inode_flags_set, &flags); + ret = __bch2_write_inode(c, inode, bch2_inode_flags_set, &s); if (!ret) bch2_inode_flags_to_vfs(inode); @@ -187,14 +200,14 @@ static int bch2_ioc_fssetxattr(struct bch_fs *c, struct bch_inode_info *inode, struct fsxattr __user *arg) { + struct flags_set s = { .mask = map_defined(bch_flags_to_xflags) }; struct fsxattr fa; - unsigned flags; int ret; if (copy_from_user(&fa, arg, sizeof(fa))) return -EFAULT; - flags = map_flags_rev(bch_flags_to_xflags, fa.fsx_xflags); + s.flags = map_flags_rev(bch_flags_to_xflags, fa.fsx_xflags); if (fa.fsx_xflags) return -EOPNOTSUPP; @@ -213,7 +226,7 @@ static int bch2_ioc_fssetxattr(struct bch_fs *c, if (ret) goto err_unlock; - ret = __bch2_write_inode(c, inode, bch2_inode_flags_set, &flags); + ret = __bch2_write_inode(c, inode, bch2_inode_flags_set, &s); if (!ret) bch2_inode_flags_to_vfs(inode); err_unlock: diff --git a/libbcachefs/fsck.c b/libbcachefs/fsck.c index ef09c131..ce14aa78 100644 --- a/libbcachefs/fsck.c +++ b/libbcachefs/fsck.c @@ -204,8 +204,8 @@ static int hash_check_key(const struct bch_hash_desc desc, "hash table key at wrong offset: %llu, " "hashed to %llu chain starts at %llu\n%s", k.k->p.offset, hashed, h->chain.pos.offset, - bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id), - buf, sizeof(buf), k))) { + (bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id), + buf, sizeof(buf), k), buf))) { ret = hash_redo_key(desc, h, c, k_iter, k, hashed); if (ret) { bch_err(c, "hash_redo_key err %i", ret); @@ -224,8 +224,8 @@ static int hash_check_key(const struct bch_hash_desc desc, if (fsck_err_on(k2.k->type == desc.key_type && !desc.cmp_bkey(k, k2), c, "duplicate hash table keys:\n%s", - bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id), - buf, sizeof(buf), k))) { + (bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id), + buf, sizeof(buf), k), buf))) { ret = bch2_hash_delete_at(desc, &h->info, &h->iter, NULL); if (ret) return ret; @@ -356,13 +356,13 @@ static int check_dirents(struct bch_fs *c) if (fsck_err_on(!w.have_inode, c, "dirent in nonexisting directory:\n%s", - bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, - buf, sizeof(buf), k)) || + (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, + buf, sizeof(buf), k), buf)) || fsck_err_on(!S_ISDIR(w.inode.bi_mode), c, "dirent in non directory inode type %u:\n%s", mode_to_type(w.inode.bi_mode), - bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, - buf, sizeof(buf), k))) { + (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, + buf, sizeof(buf), k), buf))) { ret = bch2_btree_delete_at(&iter, 0); if (ret) goto err; @@ -404,8 +404,8 @@ static int check_dirents(struct bch_fs *c) if (fsck_err_on(d_inum == d.k->p.inode, c, "dirent points to own directory:\n%s", - bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, - buf, sizeof(buf), k))) { + (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, + buf, sizeof(buf), k), buf))) { ret = remove_dirent(c, &iter, d); if (ret) goto err; @@ -421,8 +421,8 @@ static int check_dirents(struct bch_fs *c) if (fsck_err_on(!have_target, c, "dirent points to missing inode:\n%s", - bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, - buf, sizeof(buf), k))) { + (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, + buf, sizeof(buf), k), buf))) { ret = remove_dirent(c, &iter, d); if (ret) goto err; @@ -434,8 +434,8 @@ static int check_dirents(struct bch_fs *c) mode_to_type(target.bi_mode), c, "incorrect d_type: should be %u:\n%s", mode_to_type(target.bi_mode), - bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, - buf, sizeof(buf), k))) { + (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, + buf, sizeof(buf), k), buf))) { struct bkey_i_dirent *n; n = kmalloc(bkey_bytes(d.k), GFP_KERNEL);