Update bcachefs sources to 2834633e12 bcachefs: fix ioctls that set inode flags

This commit is contained in:
Kent Overstreet 2018-01-21 14:49:33 -05:00
parent fe2d5ef75f
commit 7c29c458db
3 changed files with 50 additions and 37 deletions

View File

@ -1 +1 @@
ae6e8a59d33008f46bb801850840dbd0a7608bbc 2834633e12dd6e8087f5f52742a3465a228998e5

View File

@ -40,14 +40,23 @@ static const unsigned bch_flags_to_xflags[] = {
//[__BCH_INODE_PROJINHERIT] = FS_XFLAG_PROJINHERIT; //[__BCH_INODE_PROJINHERIT] = FS_XFLAG_PROJINHERIT;
}; };
#define map_flags(_map, _in) \ #define set_flags(_map, _in, _out) \
({ \ do { \
unsigned _i, _out = 0; \ unsigned _i; \
\ \
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \ for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \
if ((_in) & (1 << _i)) \ if ((_in) & (1 << _i)) \
(_out) |= _map[_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) \ #define map_flags_rev(_map, _in) \
@ -62,16 +71,12 @@ static const unsigned bch_flags_to_xflags[] = {
(_out); \ (_out); \
}) })
#define set_flags(_map, _in, _out) \ #define map_defined(_map) \
do { \ ({ \
unsigned _i; \ unsigned _in = ~0; \
\ \
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \ map_flags_rev(_map, _in); \
if ((_in) & (1 << _i)) \ })
(_out) |= _map[_i]; \
else \
(_out) &= ~_map[_i]; \
} while (0)
/* Set VFS inode flags from bcachefs inode: */ /* Set VFS inode flags from bcachefs inode: */
void bch2_inode_flags_to_vfs(struct bch_inode_info *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); 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, static int bch2_inode_flags_set(struct bch_inode_info *inode,
struct bch_inode_unpacked *bi, struct bch_inode_unpacked *bi,
void *p) 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 * We're relying on btree locking here for exclusion with other ioctl
* calls - use the flags in the btree (@bi), not inode->i_flags: * calls - use the flags in the btree (@bi), not inode->i_flags:
*/ */
unsigned newflags = *((unsigned *) p); struct flags_set *s = p;
unsigned oldflags = bi->bi_flags; unsigned newflags = s->flags;
unsigned oldflags = bi->bi_flags & s->mask;
if (((newflags ^ oldflags) & (BCH_INODE_APPEND|BCH_INODE_IMMUTABLE)) && if (((newflags ^ oldflags) & (BCH_INODE_APPEND|BCH_INODE_IMMUTABLE)) &&
!capable(CAP_LINUX_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) (newflags & (BCH_INODE_NODUMP|BCH_INODE_NOATIME)) != newflags)
return -EINVAL; return -EINVAL;
bi->bi_flags = newflags; bi->bi_flags &= ~s->mask;
bi->bi_flags |= newflags;
inode->v.i_ctime = current_time(&inode->v); inode->v.i_ctime = current_time(&inode->v);
return 0; return 0;
} }
@ -116,13 +128,14 @@ static int bch2_ioc_setflags(struct bch_fs *c,
struct bch_inode_info *inode, struct bch_inode_info *inode,
void __user *arg) void __user *arg)
{ {
unsigned flags, uflags; struct flags_set s = { .mask = map_defined(bch_flags_to_uflags) };
unsigned uflags;
int ret; int ret;
if (get_user(uflags, (int __user *) arg)) if (get_user(uflags, (int __user *) arg))
return -EFAULT; return -EFAULT;
flags = map_flags_rev(bch_flags_to_uflags, uflags); s.flags = map_flags_rev(bch_flags_to_uflags, uflags);
if (uflags) if (uflags)
return -EOPNOTSUPP; return -EOPNOTSUPP;
@ -137,7 +150,7 @@ static int bch2_ioc_setflags(struct bch_fs *c,
} }
mutex_lock(&inode->ei_update_lock); 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) if (!ret)
bch2_inode_flags_to_vfs(inode); 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 bch_inode_info *inode,
struct fsxattr __user *arg) struct fsxattr __user *arg)
{ {
struct flags_set s = { .mask = map_defined(bch_flags_to_xflags) };
struct fsxattr fa; struct fsxattr fa;
unsigned flags;
int ret; int ret;
if (copy_from_user(&fa, arg, sizeof(fa))) if (copy_from_user(&fa, arg, sizeof(fa)))
return -EFAULT; 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) if (fa.fsx_xflags)
return -EOPNOTSUPP; return -EOPNOTSUPP;
@ -213,7 +226,7 @@ static int bch2_ioc_fssetxattr(struct bch_fs *c,
if (ret) if (ret)
goto err_unlock; 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) if (!ret)
bch2_inode_flags_to_vfs(inode); bch2_inode_flags_to_vfs(inode);
err_unlock: err_unlock:

View File

@ -204,8 +204,8 @@ static int hash_check_key(const struct bch_hash_desc desc,
"hash table key at wrong offset: %llu, " "hash table key at wrong offset: %llu, "
"hashed to %llu chain starts at %llu\n%s", "hashed to %llu chain starts at %llu\n%s",
k.k->p.offset, hashed, h->chain.pos.offset, k.k->p.offset, hashed, h->chain.pos.offset,
bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id), (bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id),
buf, sizeof(buf), k))) { buf, sizeof(buf), k), buf))) {
ret = hash_redo_key(desc, h, c, k_iter, k, hashed); ret = hash_redo_key(desc, h, c, k_iter, k, hashed);
if (ret) { if (ret) {
bch_err(c, "hash_redo_key err %i", 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 && if (fsck_err_on(k2.k->type == desc.key_type &&
!desc.cmp_bkey(k, k2), c, !desc.cmp_bkey(k, k2), c,
"duplicate hash table keys:\n%s", "duplicate hash table keys:\n%s",
bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id), (bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id),
buf, sizeof(buf), k))) { buf, sizeof(buf), k), buf))) {
ret = bch2_hash_delete_at(desc, &h->info, &h->iter, NULL); ret = bch2_hash_delete_at(desc, &h->info, &h->iter, NULL);
if (ret) if (ret)
return ret; return ret;
@ -356,13 +356,13 @@ static int check_dirents(struct bch_fs *c)
if (fsck_err_on(!w.have_inode, c, if (fsck_err_on(!w.have_inode, c,
"dirent in nonexisting directory:\n%s", "dirent in nonexisting directory:\n%s",
bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS,
buf, sizeof(buf), k)) || buf, sizeof(buf), k), buf)) ||
fsck_err_on(!S_ISDIR(w.inode.bi_mode), c, fsck_err_on(!S_ISDIR(w.inode.bi_mode), c,
"dirent in non directory inode type %u:\n%s", "dirent in non directory inode type %u:\n%s",
mode_to_type(w.inode.bi_mode), mode_to_type(w.inode.bi_mode),
bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS,
buf, sizeof(buf), k))) { buf, sizeof(buf), k), buf))) {
ret = bch2_btree_delete_at(&iter, 0); ret = bch2_btree_delete_at(&iter, 0);
if (ret) if (ret)
goto err; 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, if (fsck_err_on(d_inum == d.k->p.inode, c,
"dirent points to own directory:\n%s", "dirent points to own directory:\n%s",
bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS,
buf, sizeof(buf), k))) { buf, sizeof(buf), k), buf))) {
ret = remove_dirent(c, &iter, d); ret = remove_dirent(c, &iter, d);
if (ret) if (ret)
goto err; goto err;
@ -421,8 +421,8 @@ static int check_dirents(struct bch_fs *c)
if (fsck_err_on(!have_target, c, if (fsck_err_on(!have_target, c,
"dirent points to missing inode:\n%s", "dirent points to missing inode:\n%s",
bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS,
buf, sizeof(buf), k))) { buf, sizeof(buf), k), buf))) {
ret = remove_dirent(c, &iter, d); ret = remove_dirent(c, &iter, d);
if (ret) if (ret)
goto err; goto err;
@ -434,8 +434,8 @@ static int check_dirents(struct bch_fs *c)
mode_to_type(target.bi_mode), c, mode_to_type(target.bi_mode), c,
"incorrect d_type: should be %u:\n%s", "incorrect d_type: should be %u:\n%s",
mode_to_type(target.bi_mode), mode_to_type(target.bi_mode),
bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS,
buf, sizeof(buf), k))) { buf, sizeof(buf), k), buf))) {
struct bkey_i_dirent *n; struct bkey_i_dirent *n;
n = kmalloc(bkey_bytes(d.k), GFP_KERNEL); n = kmalloc(bkey_bytes(d.k), GFP_KERNEL);