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;
};
#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:

View File

@ -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);