Update bcachefs sources to d4b7ef921a bcachefs: Refactoring

This commit is contained in:
Kent Overstreet 2017-11-04 18:32:07 -04:00
parent bf8c59996b
commit 8351bbc05b
41 changed files with 1537 additions and 1351 deletions

View File

@ -1 +1 @@
e82e65627960a46945b78a5e5e946b23b8f08972
0415b63b198ccf8bf5eee3af73accd60e94ad63a

View File

@ -75,7 +75,7 @@ deb: all
.PHONE: update-bcachefs-sources
update-bcachefs-sources:
git rm -rf libbcachefs
git rm -rf --ignore-unmatch libbcachefs
cp $(LINUX_DIR)/fs/bcachefs/*.[ch] libbcachefs/
cp $(LINUX_DIR)/include/trace/events/bcachefs.h include/trace/events/
echo `cd $(LINUX_DIR); git rev-parse HEAD` > .bcachefs_revision

View File

@ -130,14 +130,14 @@ static void create_dirent(struct bch_fs *c,
struct bch_hash_info parent_hash_info = bch2_hash_info_init(c, parent);
struct qstr qname = { { { .len = strlen(name), } }, .name = name };
int ret = bch2_dirent_create(c, parent->inum, &parent_hash_info,
int ret = bch2_dirent_create(c, parent->bi_inum, &parent_hash_info,
mode_to_type(mode), &qname,
inum, NULL, BCH_HASH_SET_MUST_CREATE);
if (ret)
die("error creating file: %s", strerror(-ret));
if (S_ISDIR(mode))
parent->i_nlink++;
parent->bi_nlink++;
}
static void create_link(struct bch_fs *c,
@ -149,7 +149,7 @@ static void create_link(struct bch_fs *c,
if (ret)
die("error looking up hardlink: %s", strerror(-ret));
inode.i_nlink++;
inode.bi_nlink++;
update_inode(c, &inode);
create_dirent(c, parent, name, inum, mode);
@ -171,7 +171,7 @@ static struct bch_inode_unpacked create_file(struct bch_fs *c,
if (ret)
die("error creating file: %s", strerror(-ret));
create_dirent(c, parent, name, new_inode.inum, mode);
create_dirent(c, parent, name, new_inode.bi_inum, mode);
return new_inode;
}
@ -207,9 +207,9 @@ static const struct xattr_handler *xattr_resolve_name(const char **name)
static void copy_times(struct bch_fs *c, struct bch_inode_unpacked *dst,
struct stat *src)
{
dst->i_atime = timespec_to_bch2_time(c, src->st_atim);
dst->i_mtime = timespec_to_bch2_time(c, src->st_mtim);
dst->i_ctime = timespec_to_bch2_time(c, src->st_ctim);
dst->bi_atime = timespec_to_bch2_time(c, src->st_atim);
dst->bi_mtime = timespec_to_bch2_time(c, src->st_mtim);
dst->bi_ctime = timespec_to_bch2_time(c, src->st_ctim);
}
static void copy_xattrs(struct bch_fs *c, struct bch_inode_unpacked *dst,
@ -236,7 +236,7 @@ static void copy_xattrs(struct bch_fs *c, struct bch_inode_unpacked *dst,
const struct xattr_handler *h = xattr_resolve_name(&attr);
int ret = __bch2_xattr_set(c, dst->inum, &hash_info, attr,
int ret = __bch2_xattr_set(c, dst->bi_inum, &hash_info, attr,
val, val_size, 0, h->flags, NULL);
if (ret < 0)
die("error creating xattr: %s", strerror(-ret));
@ -266,11 +266,11 @@ static void write_data(struct bch_fs *c,
die("error reserving space in new filesystem: %s", strerror(-ret));
bch2_write_op_init(&op, c, res, c->write_points,
POS(dst_inode->inum, dst_offset >> 9), NULL, 0);
POS(dst_inode->bi_inum, dst_offset >> 9), NULL, 0);
closure_call(&op.cl, bch2_write, NULL, &cl);
closure_sync(&cl);
dst_inode->i_sectors += len >> 9;
dst_inode->bi_sectors += len >> 9;
}
static char buf[1 << 20] __aligned(PAGE_SIZE);
@ -316,7 +316,7 @@ static void link_data(struct bch_fs *c, struct bch_inode_unpacked *dst,
length);
e = bkey_extent_init(&k.k);
e->k.p.inode = dst->inum;
e->k.p.inode = dst->bi_inum;
e->k.p.offset = logical + sectors;
e->k.size = sectors;
extent_ptr_append(e, (struct bch_extent_ptr) {
@ -340,7 +340,7 @@ static void link_data(struct bch_fs *c, struct bch_inode_unpacked *dst,
bch2_disk_reservation_put(c, &res);
dst->i_sectors += sectors;
dst->bi_sectors += sectors;
logical += sectors;
physical += sectors;
length -= sectors;
@ -453,7 +453,7 @@ static void copy_dir(struct copy_fs_state *s,
stat.st_mode, stat.st_rdev);
if (dst_inum)
*dst_inum = inode.inum;
*dst_inum = inode.bi_inum;
copy_times(c, &inode, &stat);
copy_xattrs(c, &inode, d->d_name);
@ -467,14 +467,14 @@ static void copy_dir(struct copy_fs_state *s,
close(fd);
break;
case DT_REG:
inode.i_size = stat.st_size;
inode.bi_size = stat.st_size;
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
copy_file(c, &inode, fd, child_path, &s->extents);
close(fd);
break;
case DT_LNK:
inode.i_size = stat.st_size;
inode.bi_size = stat.st_size;
copy_link(c, &inode, d->d_name);
break;
@ -555,7 +555,7 @@ static void reserve_old_fs_space(struct bch_fs *c,
dst = create_file(c, root_inode, "old_migrated_filesystem",
0, 0, S_IFREG|0400, 0);
dst.i_size = bucket_to_sector(ca, ca->mi.nbuckets) << 9;
dst.bi_size = bucket_to_sector(ca, ca->mi.nbuckets) << 9;
ranges_sort_merge(extents);

View File

@ -189,6 +189,8 @@ struct bch_sb *bch2_format(struct format_opts opts,
SET_BCH_SB_STR_HASH_TYPE(sb, BCH_STR_HASH_SIPHASH);
SET_BCH_SB_ENCODED_EXTENT_MAX_BITS(sb, ilog2(opts.encoded_extent_max));
SET_BCH_SB_POSIX_ACL(sb, 1);
struct timespec now;
if (clock_gettime(CLOCK_REALTIME, &now))
die("error getting current time: %m");

View File

@ -1,4 +1,4 @@
#ifndef NO_BCACHEFS_FS
#ifdef CONFIG_BCACHEFS_POSIX_ACL
#include "bcachefs.h"
@ -8,8 +8,9 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include "xattr.h"
#include "acl.h"
#include "fs.h"
#include "xattr.h"
/*
* Convert from filesystem to in-memory representation.
@ -134,9 +135,10 @@ fail:
return ERR_PTR(-EINVAL);
}
struct posix_acl *bch2_get_acl(struct inode *inode, int type)
struct posix_acl *bch2_get_acl(struct inode *vinode, int type)
{
struct bch_fs *c = inode->i_sb->s_fs_info;
struct bch_inode_info *inode = to_bch_ei(vinode);
struct bch_fs *c = inode->v.i_sb->s_fs_info;
int name_index;
char *value = NULL;
struct posix_acl *acl;
@ -169,14 +171,15 @@ struct posix_acl *bch2_get_acl(struct inode *inode, int type)
kfree(value);
if (!IS_ERR(acl))
set_cached_acl(inode, type, acl);
set_cached_acl(&inode->v, type, acl);
return acl;
}
int bch2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
int bch2_set_acl(struct inode *vinode, struct posix_acl *acl, int type)
{
struct bch_fs *c = inode->i_sb->s_fs_info;
struct bch_inode_info *inode = to_bch_ei(vinode);
struct bch_fs *c = inode->v.i_sb->s_fs_info;
int name_index;
void *value = NULL;
size_t size = 0;
@ -186,12 +189,13 @@ int bch2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
case ACL_TYPE_ACCESS:
name_index = BCH_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
ret = posix_acl_equiv_mode(acl, &inode->i_mode);
ret = posix_acl_equiv_mode(acl, &inode->v.i_mode);
if (ret < 0)
return ret;
else {
inode->i_ctime = current_fs_time(inode->i_sb);
mark_inode_dirty(inode);
inode->v.i_ctime =
current_fs_time(inode->v.i_sb);
mark_inode_dirty(&inode->v);
if (ret == 0)
acl = NULL;
}
@ -200,7 +204,7 @@ int bch2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
case ACL_TYPE_DEFAULT:
name_index = BCH_XATTR_INDEX_POSIX_ACL_DEFAULT;
if (!S_ISDIR(inode->i_mode))
if (!S_ISDIR(inode->v.i_mode))
return acl ? -EACCES : 0;
break;
@ -222,9 +226,9 @@ int bch2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
ret = -E2BIG;
if (!ret)
set_cached_acl(inode, type, acl);
set_cached_acl(&inode->v, type, acl);
return ret;
}
#endif /* NO_BCACHEFS_FS */
#endif /* CONFIG_BCACHEFS_POSIX_ACL */

View File

@ -1,7 +1,7 @@
#ifndef _BCACHEFS_ACL_H
#define _BCACHEFS_ACL_H
#ifndef NO_BCACHEFS_FS
#ifdef CONFIG_BCACHEFS_POSIX_ACL
#define BCH_ACL_VERSION 0x0001
@ -54,6 +54,13 @@ struct posix_acl;
extern struct posix_acl *bch2_get_acl(struct inode *, int);
extern int bch2_set_acl(struct inode *, struct posix_acl *, int);
#endif /* NO_BCACHEFS_FS */
#else
static inline int bch2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
return 0;
}
#endif /* CONFIG_BCACHEFS_POSIX_ACL */
#endif /* _BCACHEFS_ACL_H */

View File

@ -367,7 +367,7 @@ struct bch_dev {
uuid_le uuid;
char name[BDEVNAME_SIZE];
struct bcache_superblock disk_sb;
struct bch_sb_handle disk_sb;
int sb_write_error;
struct bch_devs_mask self;
@ -445,6 +445,7 @@ struct bch_dev {
* won't automatically reattach).
*/
enum {
BCH_FS_ALLOC_READ_DONE,
BCH_FS_INITIAL_GC_DONE,
BCH_FS_EMERGENCY_RO,
BCH_FS_WRITE_DISABLE_COMPLETE,
@ -517,14 +518,11 @@ struct bch_fs {
uuid_le uuid;
uuid_le user_uuid;
u16 block_size;
u16 btree_node_size;
u16 encoded_extent_max;
u8 nr_devices;
u8 clean;
u8 str_hash_type;
u8 encryption_type;
u64 time_base_lo;
@ -796,7 +794,7 @@ static inline unsigned bucket_bytes(const struct bch_dev *ca)
static inline unsigned block_bytes(const struct bch_fs *c)
{
return c->sb.block_size << 9;
return c->opts.block_size << 9;
}
#endif /* _BCACHEFS_H */

View File

@ -9,45 +9,29 @@
#include <asm/byteorder.h>
#include <linux/uuid.h>
#define LE32_BITMASK(name, type, field, offset, end) \
#define LE_BITMASK(_bits, name, type, field, offset, end) \
static const unsigned name##_OFFSET = offset; \
static const unsigned name##_BITS = (end - offset); \
static const __u64 name##_MAX = (1ULL << (end - offset)) - 1; \
static const __u##_bits name##_MAX = (1ULL << (end - offset)) - 1; \
\
static inline __u64 name(const type *k) \
{ \
return (__le32_to_cpu(k->field) >> offset) & \
return (__le##_bits##_to_cpu(k->field) >> offset) & \
~(~0ULL << (end - offset)); \
} \
\
static inline void SET_##name(type *k, __u64 v) \
{ \
__u64 new = __le32_to_cpu(k->field); \
__u##_bits new = __le##_bits##_to_cpu(k->field); \
\
new &= ~(~(~0ULL << (end - offset)) << offset); \
new |= (v & ~(~0ULL << (end - offset))) << offset; \
k->field = __cpu_to_le32(new); \
k->field = __cpu_to_le##_bits(new); \
}
#define LE64_BITMASK(name, type, field, offset, end) \
static const unsigned name##_OFFSET = offset; \
static const unsigned name##_BITS = (end - offset); \
static const __u64 name##_MAX = (1ULL << (end - offset)) - 1; \
\
static inline __u64 name(const type *k) \
{ \
return (__le64_to_cpu(k->field) >> offset) & \
~(~0ULL << (end - offset)); \
} \
\
static inline void SET_##name(type *k, __u64 v) \
{ \
__u64 new = __le64_to_cpu(k->field); \
\
new &= ~(~(~0ULL << (end - offset)) << offset); \
new |= (v & ~(~0ULL << (end - offset))) << offset; \
k->field = __cpu_to_le64(new); \
}
#define LE16_BITMASK(n, t, f, o, e) LE_BITMASK(16, n, t, f, o, e)
#define LE32_BITMASK(n, t, f, o, e) LE_BITMASK(32, n, t, f, o, e)
#define LE64_BITMASK(n, t, f, o, e) LE_BITMASK(64, n, t, f, o, e)
struct bkey_format {
__u8 key_u64s;
@ -592,9 +576,9 @@ enum bch_inode_types {
struct bch_inode {
struct bch_val v;
__le64 i_hash_seed;
__le32 i_flags;
__le16 i_mode;
__le64 bi_hash_seed;
__le32 bi_flags;
__le16 bi_mode;
__u8 fields[0];
} __attribute__((packed, aligned(8)));
BKEY_VAL_TYPE(inode, BCH_INODE_FS);
@ -602,24 +586,23 @@ BKEY_VAL_TYPE(inode, BCH_INODE_FS);
struct bch_inode_generation {
struct bch_val v;
__le32 i_generation;
__le32 bi_generation;
__le32 pad;
} __attribute__((packed, aligned(8)));
BKEY_VAL_TYPE(inode_generation, BCH_INODE_GENERATION);
#define BCH_INODE_FIELDS() \
BCH_INODE_FIELD(i_atime, 64) \
BCH_INODE_FIELD(i_ctime, 64) \
BCH_INODE_FIELD(i_mtime, 64) \
BCH_INODE_FIELD(i_otime, 64) \
BCH_INODE_FIELD(i_size, 64) \
BCH_INODE_FIELD(i_sectors, 64) \
BCH_INODE_FIELD(i_uid, 32) \
BCH_INODE_FIELD(i_gid, 32) \
BCH_INODE_FIELD(i_nlink, 32) \
BCH_INODE_FIELD(i_generation, 32) \
BCH_INODE_FIELD(i_dev, 32)
BCH_INODE_FIELD(bi_atime, 64) \
BCH_INODE_FIELD(bi_ctime, 64) \
BCH_INODE_FIELD(bi_mtime, 64) \
BCH_INODE_FIELD(bi_otime, 64) \
BCH_INODE_FIELD(bi_size, 64) \
BCH_INODE_FIELD(bi_sectors, 64) \
BCH_INODE_FIELD(bi_uid, 32) \
BCH_INODE_FIELD(bi_gid, 32) \
BCH_INODE_FIELD(bi_nlink, 32) \
BCH_INODE_FIELD(bi_generation, 32) \
BCH_INODE_FIELD(bi_dev, 32)
enum {
/*
@ -650,8 +633,8 @@ enum {
#define BCH_INODE_I_SECTORS_DIRTY (1 << __BCH_INODE_I_SECTORS_DIRTY)
#define BCH_INODE_HAS_XATTRS (1 << __BCH_INODE_HAS_XATTRS)
LE32_BITMASK(INODE_STR_HASH, struct bch_inode, i_flags, 20, 24);
LE32_BITMASK(INODE_NR_FIELDS, struct bch_inode, i_flags, 24, 32);
LE32_BITMASK(INODE_STR_HASH, struct bch_inode, bi_flags, 20, 24);
LE32_BITMASK(INODE_NR_FIELDS, struct bch_inode, bi_flags, 24, 32);
struct bch_inode_blockdev {
struct bch_val v;
@ -960,6 +943,8 @@ struct bch_sb {
* algorithm in use, if/when we get more than one
*/
LE16_BITMASK(BCH_SB_BLOCK_SIZE, struct bch_sb, block_size, 0, 16);
LE64_BITMASK(BCH_SB_INITIALIZED, struct bch_sb, flags[0], 0, 1);
LE64_BITMASK(BCH_SB_CLEAN, struct bch_sb, flags[0], 1, 2);
LE64_BITMASK(BCH_SB_CSUM_TYPE, struct bch_sb, flags[0], 2, 8);
@ -976,7 +961,7 @@ LE64_BITMASK(BCH_SB_DATA_CSUM_TYPE, struct bch_sb, flags[0], 44, 48);
LE64_BITMASK(BCH_SB_META_REPLICAS_WANT, struct bch_sb, flags[0], 48, 52);
LE64_BITMASK(BCH_SB_DATA_REPLICAS_WANT, struct bch_sb, flags[0], 52, 56);
/* 56-64 unused, was REPLICAS_HAVE */
LE64_BITMASK(BCH_SB_POSIX_ACL, struct bch_sb, flags[0], 56, 57);
LE64_BITMASK(BCH_SB_STR_HASH_TYPE, struct bch_sb, flags[1], 0, 4);
LE64_BITMASK(BCH_SB_COMPRESSION_TYPE, struct bch_sb, flags[1], 4, 8);

View File

@ -51,7 +51,7 @@ static inline bool btree_node_hashed(struct btree *b)
static inline size_t btree_bytes(struct bch_fs *c)
{
return c->sb.btree_node_size << 9;
return c->opts.btree_node_size << 9;
}
static inline size_t btree_max_u64s(struct bch_fs *c)
@ -71,7 +71,7 @@ static inline size_t btree_pages(struct bch_fs *c)
static inline unsigned btree_blocks(struct bch_fs *c)
{
return c->sb.btree_node_size >> c->block_bits;
return c->opts.btree_node_size >> c->block_bits;
}
#define BTREE_SPLIT_THRESHOLD(c) (btree_blocks(c) * 3 / 4)

View File

@ -116,7 +116,7 @@ static u8 bch2_btree_mark_key(struct bch_fs *c, enum bkey_type type,
{
switch (type) {
case BKEY_TYPE_BTREE:
bch2_gc_mark_key(c, k, c->sb.btree_node_size, true, flags);
bch2_gc_mark_key(c, k, c->opts.btree_node_size, true, flags);
return 0;
case BKEY_TYPE_EXTENTS:
bch2_gc_mark_key(c, k, k.k->size, false, flags);
@ -386,7 +386,7 @@ static void bch2_mark_pending_btree_node_frees(struct bch_fs *c)
for_each_pending_btree_node_free(c, as, d)
if (d->index_update_done)
__bch2_mark_key(c, bkey_i_to_s_c(&d->key),
c->sb.btree_node_size, true,
c->opts.btree_node_size, true,
&stats, 0,
BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE);
/*

View File

@ -916,7 +916,7 @@ static int validate_bset(struct bch_fs *c, struct btree *b,
return 0;
}
if (b->written + sectors > c->sb.btree_node_size) {
if (b->written + sectors > c->opts.btree_node_size) {
btree_node_error(c, b, "bset past end of btree node");
i->u64s = 0;
return 0;
@ -1034,7 +1034,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct btree *b)
if (bch2_meta_read_fault("btree"))
goto err;
while (b->written < c->sb.btree_node_size) {
while (b->written < c->opts.btree_node_size) {
unsigned sectors, whiteout_u64s = 0;
if (!b->written) {
@ -1528,7 +1528,7 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b,
BUG_ON(!list_empty(&b->write_blocked));
BUG_ON((b->will_make_reachable != NULL) != !b->written);
BUG_ON(b->written >= c->sb.btree_node_size);
BUG_ON(b->written >= c->opts.btree_node_size);
BUG_ON(bset_written(b, btree_bset_last(b)));
BUG_ON(le64_to_cpu(b->data->magic) != bset_magic(c));
BUG_ON(memcmp(&b->data->format, &b->format, sizeof(b->format)));
@ -1612,7 +1612,7 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b,
memset(data + bytes_to_write, 0,
(sectors_to_write << 9) - bytes_to_write);
BUG_ON(b->written + sectors_to_write > c->sb.btree_node_size);
BUG_ON(b->written + sectors_to_write > c->opts.btree_node_size);
BUG_ON(BSET_BIG_ENDIAN(i) != CPU_BIG_ENDIAN);
BUG_ON(i->seq != b->data->keys.seq);

View File

@ -181,7 +181,7 @@ found:
*/
replicas = bch2_extent_nr_dirty_ptrs(k);
if (replicas)
stats->s[replicas - 1].data[S_META] -= c->sb.btree_node_size;
stats->s[replicas - 1].data[S_META] -= c->opts.btree_node_size;
/*
* We're dropping @k from the btree, but it's still live until the
@ -208,7 +208,7 @@ found:
struct bch_fs_usage tmp = { 0 };
bch2_mark_key(c, bkey_i_to_s_c(&d->key),
-c->sb.btree_node_size, true, b
-c->opts.btree_node_size, true, b
? gc_pos_btree_node(b)
: gc_pos_btree_root(as->btree_id),
&tmp, 0);
@ -285,7 +285,7 @@ static void bch2_btree_node_free_ondisk(struct bch_fs *c,
BUG_ON(!pending->index_update_done);
bch2_mark_key(c, bkey_i_to_s_c(&pending->key),
-c->sb.btree_node_size, true,
-c->opts.btree_node_size, true,
gc_phase(GC_PHASE_PENDING_DELETE),
&stats, 0);
/*
@ -337,7 +337,7 @@ static struct btree *__bch2_btree_node_alloc(struct bch_fs *c,
retry:
/* alloc_sectors is weird, I suppose */
bkey_extent_init(&tmp.k);
tmp.k.k.size = c->sb.btree_node_size,
tmp.k.k.size = c->opts.btree_node_size,
ob = bch2_alloc_sectors(c, &c->btree_write_point,
bkey_i_to_extent(&tmp.k),
@ -347,7 +347,7 @@ retry:
if (IS_ERR(ob))
return ERR_CAST(ob);
if (tmp.k.k.size < c->sb.btree_node_size) {
if (tmp.k.k.size < c->opts.btree_node_size) {
bch2_open_bucket_put(c, ob);
goto retry;
}
@ -491,7 +491,7 @@ static struct btree_reserve *bch2_btree_reserve_get(struct bch_fs *c,
struct btree_reserve *reserve;
struct btree *b;
struct disk_reservation disk_res = { 0, 0 };
unsigned sectors = nr_nodes * c->sb.btree_node_size;
unsigned sectors = nr_nodes * c->opts.btree_node_size;
int ret, disk_res_flags = BCH_DISK_RESERVATION_GC_LOCK_HELD|
BCH_DISK_RESERVATION_METADATA;
@ -1035,7 +1035,7 @@ static void bch2_btree_set_root_inmem(struct btree_update *as, struct btree *b)
__bch2_btree_set_root_inmem(c, b);
bch2_mark_key(c, bkey_i_to_s_c(&b->key),
c->sb.btree_node_size, true,
c->opts.btree_node_size, true,
gc_pos_btree_root(b->btree_id),
&stats, 0);
@ -1120,7 +1120,7 @@ static void bch2_insert_fixup_btree_ptr(struct btree_update *as, struct btree *b
if (bkey_extent_is_data(&insert->k))
bch2_mark_key(c, bkey_i_to_s_c(insert),
c->sb.btree_node_size, true,
c->opts.btree_node_size, true,
gc_pos_btree_node(b), &stats, 0);
while ((k = bch2_btree_node_iter_peek_all(node_iter, b)) &&
@ -1901,7 +1901,7 @@ retry:
bch2_btree_node_lock_write(b, &iter);
bch2_mark_key(c, bkey_i_to_s_c(&new_key->k_i),
c->sb.btree_node_size, true,
c->opts.btree_node_size, true,
gc_pos_btree_root(b->btree_id),
&stats, 0);
bch2_btree_node_free_index(as, NULL,

View File

@ -263,7 +263,7 @@ static inline size_t bch_btree_keys_u64s_remaining(struct bch_fs *c,
unsigned used = bset_byte_offset(b, vstruct_end(i)) / sizeof(u64) +
b->whiteout_u64s +
b->uncompacted_whiteout_u64s;
unsigned total = c->sb.btree_node_size << 6;
unsigned total = c->opts.btree_node_size << 6;
EBUG_ON(used > total);

View File

@ -469,6 +469,7 @@ static void bch2_mark_pointer(struct bch_fs *c,
* checked the gen
*/
if (gen_after(new.gen, ptr->gen)) {
BUG_ON(!test_bit(BCH_FS_ALLOC_READ_DONE, &c->flags));
EBUG_ON(!ptr->cached &&
test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags));
return;

View File

@ -417,7 +417,7 @@ int bch2_request_key(struct bch_sb *sb, struct bch_key *key)
}
#endif
static int bch2_decrypt_sb_key(struct bch_fs *c,
int bch2_decrypt_sb_key(struct bch_fs *c,
struct bch_sb_field_crypt *crypt,
struct bch_key *key)
{

View File

@ -40,6 +40,9 @@ struct bch_csum bch2_checksum_bio(struct bch_fs *, unsigned,
void bch2_encrypt_bio(struct bch_fs *, unsigned,
struct nonce, struct bio *);
int bch2_decrypt_sb_key(struct bch_fs *, struct bch_sb_field_crypt *,
struct bch_key *);
int bch2_disable_encryption(struct bch_fs *);
int bch2_enable_encryption(struct bch_fs *, bool);

View File

@ -423,7 +423,7 @@ void bch2_bio_compress(struct bch_fs *c,
/* If it's only one block, don't bother trying to compress: */
if (*compression_type != BCH_COMPRESSION_NONE &&
bio_sectors(src) > c->sb.block_size &&
bio_sectors(src) > c->opts.block_size &&
!__bio_compress(c, dst, dst_len, src, src_len, compression_type))
goto out;

View File

@ -192,25 +192,23 @@ static void dirent_copy_target(struct bkey_i_dirent *dst,
dst->v.d_type = src.v->d_type;
}
static struct bpos bch2_dirent_pos(struct bch_inode_info *ei,
static struct bpos bch2_dirent_pos(struct bch_inode_info *inode,
const struct qstr *name)
{
return POS(ei->vfs_inode.i_ino, bch2_dirent_hash(&ei->str_hash, name));
return POS(inode->v.i_ino, bch2_dirent_hash(&inode->ei_str_hash, name));
}
int bch2_dirent_rename(struct bch_fs *c,
struct inode *src_dir, const struct qstr *src_name,
struct inode *dst_dir, const struct qstr *dst_name,
struct bch_inode_info *src_dir, const struct qstr *src_name,
struct bch_inode_info *dst_dir, const struct qstr *dst_name,
u64 *journal_seq, enum bch_rename_mode mode)
{
struct bch_inode_info *src_ei = to_bch_ei(src_dir);
struct bch_inode_info *dst_ei = to_bch_ei(dst_dir);
struct btree_iter src_iter, dst_iter, whiteout_iter;
struct bkey_s_c old_src, old_dst;
struct bkey delete;
struct bkey_i_dirent *new_src = NULL, *new_dst = NULL;
struct bpos src_pos = bch2_dirent_pos(src_ei, src_name);
struct bpos dst_pos = bch2_dirent_pos(dst_ei, dst_name);
struct bpos src_pos = bch2_dirent_pos(src_dir, src_name);
struct bpos dst_pos = bch2_dirent_pos(dst_dir, dst_name);
bool need_whiteout;
int ret = -ENOMEM;
@ -241,13 +239,13 @@ retry:
* in bch_hash_set) - we never move existing dirents to different slot:
*/
old_src = bch2_hash_lookup_at(bch2_dirent_hash_desc,
&src_ei->str_hash,
&src_dir->ei_str_hash,
&src_iter, src_name);
if ((ret = btree_iter_err(old_src)))
goto err;
ret = bch2_hash_needs_whiteout(bch2_dirent_hash_desc,
&src_ei->str_hash,
&src_dir->ei_str_hash,
&whiteout_iter, &src_iter);
if (ret < 0)
goto err;
@ -261,7 +259,7 @@ retry:
old_dst = mode == BCH_RENAME
? bch2_hash_hole_at(bch2_dirent_hash_desc, &dst_iter)
: bch2_hash_lookup_at(bch2_dirent_hash_desc,
&dst_ei->str_hash,
&dst_dir->ei_str_hash,
&dst_iter, dst_name);
if ((ret = btree_iter_err(old_dst)))
goto err;
@ -395,7 +393,7 @@ int bch2_empty_dir(struct bch_fs *c, u64 dir_inum)
int bch2_readdir(struct bch_fs *c, struct file *file,
struct dir_context *ctx)
{
struct inode *inode = file_inode(file);
struct bch_inode_info *inode = file_bch_inode(file);
struct btree_iter iter;
struct bkey_s_c k;
struct bkey_s_c_dirent dirent;
@ -404,29 +402,21 @@ int bch2_readdir(struct bch_fs *c, struct file *file,
if (!dir_emit_dots(file, ctx))
return 0;
pr_debug("listing for %lu from %llu", inode->i_ino, ctx->pos);
for_each_btree_key(&iter, c, BTREE_ID_DIRENTS,
POS(inode->i_ino, ctx->pos), 0, k) {
POS(inode->v.i_ino, ctx->pos), 0, k) {
if (k.k->type != BCH_DIRENT)
continue;
dirent = bkey_s_c_to_dirent(k);
pr_debug("saw %llu:%llu (%s) -> %llu",
k.k->p.inode, k.k->p.offset,
dirent.v->d_name, dirent.v->d_inum);
if (bkey_cmp(k.k->p, POS(inode->i_ino, ctx->pos)) < 0)
if (bkey_cmp(k.k->p, POS(inode->v.i_ino, ctx->pos)) < 0)
continue;
if (k.k->p.inode > inode->i_ino)
if (k.k->p.inode > inode->v.i_ino)
break;
len = bch2_dirent_name_bytes(dirent);
pr_debug("emitting %s", dirent.v->d_name);
/*
* XXX: dir_emit() can fault and block, while we're holding
* locks

View File

@ -11,6 +11,7 @@ struct file;
struct dir_context;
struct bch_fs;
struct bch_hash_info;
struct bch_inode_info;
unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent);
int bch2_dirent_create(struct bch_fs *c, u64, const struct bch_hash_info *,
@ -25,8 +26,8 @@ enum bch_rename_mode {
};
int bch2_dirent_rename(struct bch_fs *,
struct inode *, const struct qstr *,
struct inode *, const struct qstr *,
struct bch_inode_info *, const struct qstr *,
struct bch_inode_info *, const struct qstr *,
u64 *, enum bch_rename_mode);
u64 bch2_dirent_lookup(struct bch_fs *, u64, const struct bch_hash_info *,

View File

@ -575,7 +575,7 @@ static const char *bch2_btree_ptr_invalid(const struct bch_fs *c,
extent_for_each_ptr_crc(e, ptr, crc) {
reason = extent_ptr_invalid(c, e, ptr,
c->sb.btree_node_size,
c->opts.btree_node_size,
true);
if (reason)
return reason;
@ -610,6 +610,9 @@ static void btree_ptr_debugcheck(struct bch_fs *c, struct btree *b,
g = PTR_BUCKET(ca, ptr);
replicas++;
if (!test_bit(BCH_FS_ALLOC_READ_DONE, &c->flags))
continue;
err = "stale";
if (ptr_stale(ca, ptr))
goto err;

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@ ssize_t bch2_write_iter(struct kiocb *, struct iov_iter *);
int bch2_fsync(struct file *, loff_t, loff_t, int);
int bch2_truncate(struct inode *, struct iattr *);
int bch2_truncate(struct bch_inode_info *, struct iattr *);
long bch2_fallocate_dispatch(struct file *, int, loff_t, loff_t);
loff_t bch2_llseek(struct file *, loff_t, int);
@ -38,11 +38,11 @@ int bch2_migrate_page(struct address_space *, struct page *,
struct i_sectors_hook {
struct extent_insert_hook hook;
s64 sectors;
struct bch_inode_info *ei;
struct bch_inode_info *inode;
};
struct bchfs_write_op {
struct bch_inode_info *ei;
struct bch_inode_info *inode;
s64 sectors_added;
bool is_dio;
u64 new_i_size;

254
libbcachefs/fs-ioctl.c Normal file
View File

@ -0,0 +1,254 @@
#ifndef NO_BCACHEFS_FS
#include "bcachefs.h"
#include "chardev.h"
#include "fs.h"
#include "fs-ioctl.h"
#include <linux/compat.h>
#include <linux/mount.h>
#define FS_IOC_GOINGDOWN _IOR('X', 125, __u32)
/* Inode flags: */
/* bcachefs inode flags -> vfs inode flags: */
static const unsigned bch_flags_to_vfs[] = {
[__BCH_INODE_SYNC] = S_SYNC,
[__BCH_INODE_IMMUTABLE] = S_IMMUTABLE,
[__BCH_INODE_APPEND] = S_APPEND,
[__BCH_INODE_NOATIME] = S_NOATIME,
};
/* bcachefs inode flags -> FS_IOC_GETFLAGS: */
static const unsigned bch_flags_to_uflags[] = {
[__BCH_INODE_SYNC] = FS_SYNC_FL,
[__BCH_INODE_IMMUTABLE] = FS_IMMUTABLE_FL,
[__BCH_INODE_APPEND] = FS_APPEND_FL,
[__BCH_INODE_NODUMP] = FS_NODUMP_FL,
[__BCH_INODE_NOATIME] = FS_NOATIME_FL,
};
/* bcachefs inode flags -> FS_IOC_FSGETXATTR: */
static const unsigned bch_flags_to_xflags[] = {
[__BCH_INODE_SYNC] = FS_XFLAG_SYNC,
[__BCH_INODE_IMMUTABLE] = FS_XFLAG_IMMUTABLE,
[__BCH_INODE_APPEND] = FS_XFLAG_APPEND,
[__BCH_INODE_NODUMP] = FS_XFLAG_NODUMP,
[__BCH_INODE_NOATIME] = FS_XFLAG_NOATIME,
//[__BCH_INODE_PROJINHERIT] = FS_XFLAG_PROJINHERIT;
};
#define map_flags(_map, _in) \
({ \
unsigned _i, _out = 0; \
\
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \
if ((_in) & (1 << _i)) \
(_out) |= _map[_i]; \
(_out); \
})
#define map_flags_rev(_map, _in) \
({ \
unsigned _i, _out = 0; \
\
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \
if ((_in) & _map[_i]) { \
(_out) |= 1 << _i; \
(_in) &= ~_map[_i]; \
} \
(_out); \
})
#define set_flags(_map, _in, _out) \
do { \
unsigned _i; \
\
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \
if ((_in) & (1 << _i)) \
(_out) |= _map[_i]; \
else \
(_out) &= ~_map[_i]; \
} while (0)
/* Set VFS inode flags from bcachefs inode: */
void bch2_inode_flags_to_vfs(struct bch_inode_info *inode)
{
set_flags(bch_flags_to_vfs, inode->ei_flags, inode->v.i_flags);
}
static int bch2_inode_flags_set(struct bch_inode_info *inode,
struct bch_inode_unpacked *bi,
void *p)
{
/*
* 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;
if (((newflags ^ oldflags) & (BCH_INODE_APPEND|BCH_INODE_IMMUTABLE)) &&
!capable(CAP_LINUX_IMMUTABLE))
return -EPERM;
if (!S_ISREG(inode->v.i_mode) &&
!S_ISDIR(inode->v.i_mode) &&
(newflags & (BCH_INODE_NODUMP|BCH_INODE_NOATIME)) != newflags)
return -EINVAL;
bi->bi_flags = newflags;
inode->v.i_ctime = current_fs_time(inode->v.i_sb);
return 0;
}
static int bch2_ioc_getflags(struct bch_inode_info *inode, int __user *arg)
{
unsigned flags = map_flags(bch_flags_to_uflags, inode->ei_flags);
return put_user(flags, arg);
}
static int bch2_ioc_setflags(struct bch_fs *c,
struct file *file,
struct bch_inode_info *inode,
void __user *arg)
{
unsigned flags, uflags;
int ret;
if (get_user(uflags, (int __user *) arg))
return -EFAULT;
flags = map_flags_rev(bch_flags_to_uflags, uflags);
if (uflags)
return -EOPNOTSUPP;
ret = mnt_want_write_file(file);
if (ret)
return ret;
inode_lock(&inode->v);
if (!inode_owner_or_capable(&inode->v)) {
ret = -EACCES;
goto setflags_out;
}
mutex_lock(&inode->ei_update_lock);
ret = __bch2_write_inode(c, inode, bch2_inode_flags_set, &flags);
if (!ret)
bch2_inode_flags_to_vfs(inode);
mutex_unlock(&inode->ei_update_lock);
setflags_out:
inode_unlock(&inode->v);
mnt_drop_write_file(file);
return ret;
}
static int bch2_ioc_fsgetxattr(struct bch_inode_info *inode,
struct fsxattr __user *arg)
{
struct fsxattr fa = { 0 };
fa.fsx_xflags = map_flags(bch_flags_to_xflags, inode->ei_flags);
return copy_to_user(arg, &fa, sizeof(fa));
}
static int bch2_ioc_fssetxattr(struct bch_fs *c,
struct file *file,
struct bch_inode_info *inode,
struct fsxattr __user *arg)
{
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);
if (fa.fsx_xflags)
return -EOPNOTSUPP;
ret = mnt_want_write_file(file);
if (ret)
return ret;
inode_lock(&inode->v);
if (!inode_owner_or_capable(&inode->v)) {
ret = -EACCES;
goto err;
}
mutex_lock(&inode->ei_update_lock);
ret = __bch2_write_inode(c, inode, bch2_inode_flags_set, &flags);
if (!ret)
bch2_inode_flags_to_vfs(inode);
mutex_unlock(&inode->ei_update_lock);
err:
inode_unlock(&inode->v);
mnt_drop_write_file(file);
return ret;
}
long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
struct bch_inode_info *inode = file_bch_inode(file);
struct super_block *sb = inode->v.i_sb;
struct bch_fs *c = sb->s_fs_info;
switch (cmd) {
case FS_IOC_GETFLAGS:
return bch2_ioc_getflags(inode, (int __user *) arg);
case FS_IOC_SETFLAGS:
return bch2_ioc_setflags(c, file, inode, (int __user *) arg);
case FS_IOC_FSGETXATTR:
return bch2_ioc_fsgetxattr(inode, (void __user *) arg);
case FS_IOC_FSSETXATTR:
return bch2_ioc_fssetxattr(c, file, inode, (void __user *) arg);
case FS_IOC_GETVERSION:
return -ENOTTY;
case FS_IOC_SETVERSION:
return -ENOTTY;
case FS_IOC_GOINGDOWN:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
down_write(&sb->s_umount);
sb->s_flags |= MS_RDONLY;
bch2_fs_emergency_read_only(c);
up_write(&sb->s_umount);
return 0;
default:
return bch2_fs_ioctl(c, cmd, (void __user *) arg);
}
}
#ifdef CONFIG_COMPAT
long bch2_compat_fs_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
/* These are just misnamed, they actually get/put from/to user an int */
switch (cmd) {
case FS_IOC_GETFLAGS:
cmd = FS_IOC_GETFLAGS;
break;
case FS_IOC32_SETFLAGS:
cmd = FS_IOC_SETFLAGS;
break;
default:
return -ENOIOCTLCMD;
}
return bch2_fs_file_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
}
#endif
#endif /* NO_BCACHEFS_FS */

9
libbcachefs/fs-ioctl.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _BCACHEFS_FS_IOCTL_H
#define _BCACHEFS_FS_IOCTL_H
void bch2_inode_flags_to_vfs(struct bch_inode_info *);
long bch2_fs_file_ioctl(struct file *, unsigned, unsigned long);
long bch2_compat_fs_ioctl(struct file *, unsigned, unsigned long);
#endif /* _BCACHEFS_FS_IOCTL_H */

File diff suppressed because it is too large Load Diff

View File

@ -7,30 +7,35 @@
#include <linux/stat.h>
struct bch_inode_info {
struct inode vfs_inode;
struct inode v;
struct mutex update_lock;
u64 journal_seq;
struct mutex ei_update_lock;
u64 ei_journal_seq;
atomic_long_t i_size_dirty_count;
atomic_long_t ei_size_dirty_count;
/*
* these are updated whenever we update the inode in the btree - for
* e.g. fsync
*/
u64 i_size;
u32 i_flags;
u64 ei_size;
u32 ei_flags;
atomic_long_t i_sectors_dirty_count;
atomic64_t i_sectors;
atomic_long_t ei_sectors_dirty_count;
atomic64_t ei_sectors;
struct bch_hash_info str_hash;
struct bch_hash_info ei_str_hash;
unsigned long last_dirtied;
unsigned long ei_last_dirtied;
};
#define to_bch_ei(_inode) \
container_of(_inode, struct bch_inode_info, vfs_inode)
container_of_or_null(_inode, struct bch_inode_info, v)
static inline struct bch_inode_info *file_bch_inode(struct file *file)
{
return to_bch_ei(file_inode(file));
}
static inline u8 mode_to_type(umode_t mode)
{

View File

@ -67,7 +67,7 @@ static int reattach_inode(struct bch_fs *c,
snprintf(name_buf, sizeof(name_buf), "%llu", inum);
name = (struct qstr) QSTR(name_buf);
lostfound_inode->i_nlink++;
lostfound_inode->bi_nlink++;
bch2_inode_pack(&packed, lostfound_inode);
@ -80,7 +80,7 @@ static int reattach_inode(struct bch_fs *c,
return ret;
}
ret = bch2_dirent_create(c, lostfound_inode->inum,
ret = bch2_dirent_create(c, lostfound_inode->bi_inum,
&lostfound_hash_info,
DT_DIR, &name, inum, NULL,
BTREE_INSERT_NOFAIL);
@ -263,9 +263,9 @@ static int check_extents(struct bch_fs *c)
"extent type %u for missing inode %llu",
k.k->type, k.k->p.inode) ||
fsck_err_on(w.have_inode &&
!S_ISREG(w.inode.i_mode) && !S_ISLNK(w.inode.i_mode), c,
!S_ISREG(w.inode.bi_mode) && !S_ISLNK(w.inode.bi_mode), c,
"extent type %u for non regular file, inode %llu mode %o",
k.k->type, k.k->p.inode, w.inode.i_mode)) {
k.k->type, k.k->p.inode, w.inode.bi_mode)) {
ret = bch2_btree_delete_at(&iter, 0);
if (ret)
goto err;
@ -274,18 +274,18 @@ static int check_extents(struct bch_fs *c)
unfixable_fsck_err_on(w.first_this_inode &&
w.have_inode &&
!(w.inode.i_flags & BCH_INODE_I_SECTORS_DIRTY) &&
w.inode.i_sectors !=
!(w.inode.bi_flags & BCH_INODE_I_SECTORS_DIRTY) &&
w.inode.bi_sectors !=
(i_sectors = bch2_count_inode_sectors(c, w.cur_inum)),
c, "i_sectors wrong: got %llu, should be %llu",
w.inode.i_sectors, i_sectors);
w.inode.bi_sectors, i_sectors);
unfixable_fsck_err_on(w.have_inode &&
!(w.inode.i_flags & BCH_INODE_I_SIZE_DIRTY) &&
!(w.inode.bi_flags & BCH_INODE_I_SIZE_DIRTY) &&
k.k->type != BCH_RESERVATION &&
k.k->p.offset > round_up(w.inode.i_size, PAGE_SIZE) >> 9, c,
k.k->p.offset > round_up(w.inode.bi_size, PAGE_SIZE) >> 9, c,
"extent type %u offset %llu past end of inode %llu, i_size %llu",
k.k->type, k.k->p.offset, k.k->p.inode, w.inode.i_size);
k.k->type, k.k->p.offset, k.k->p.inode, w.inode.bi_size);
}
err:
fsck_err:
@ -324,9 +324,9 @@ static int check_dirents(struct bch_fs *c)
"dirent in nonexisting directory:\n%s",
bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS,
buf, sizeof(buf), k)) ||
fsck_err_on(!S_ISDIR(w.inode.i_mode), c,
fsck_err_on(!S_ISDIR(w.inode.bi_mode), c,
"dirent in non directory inode type %u:\n%s",
mode_to_type(w.inode.i_mode),
mode_to_type(w.inode.bi_mode),
bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS,
buf, sizeof(buf), k))) {
ret = bch2_btree_delete_at(&iter, 0);
@ -397,9 +397,9 @@ static int check_dirents(struct bch_fs *c)
if (fsck_err_on(have_target &&
d.v->d_type !=
mode_to_type(le16_to_cpu(target.i_mode)), c,
mode_to_type(le16_to_cpu(target.bi_mode)), c,
"incorrect d_type: should be %u:\n%s",
mode_to_type(le16_to_cpu(target.i_mode)),
mode_to_type(le16_to_cpu(target.bi_mode)),
bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS,
buf, sizeof(buf), k))) {
struct bkey_i_dirent *n;
@ -411,7 +411,7 @@ static int check_dirents(struct bch_fs *c)
}
bkey_reassemble(&n->k_i, d.s_c);
n->v.d_type = mode_to_type(le16_to_cpu(target.i_mode));
n->v.d_type = mode_to_type(le16_to_cpu(target.bi_mode));
ret = bch2_btree_insert_at(c, NULL, NULL, NULL,
BTREE_INSERT_NOFAIL,
@ -485,7 +485,7 @@ static int check_root(struct bch_fs *c, struct bch_inode_unpacked *root_inode)
if (fsck_err_on(ret, c, "root directory missing"))
goto create_root;
if (fsck_err_on(!S_ISDIR(root_inode->i_mode), c,
if (fsck_err_on(!S_ISDIR(root_inode->bi_mode), c,
"root inode not a directory"))
goto create_root;
@ -494,7 +494,7 @@ fsck_err:
return ret;
create_root:
bch2_inode_init(c, root_inode, 0, 0, S_IFDIR|S_IRWXU|S_IRUGO|S_IXUGO, 0);
root_inode->inum = BCACHEFS_ROOT_INO;
root_inode->bi_inum = BCACHEFS_ROOT_INO;
bch2_inode_pack(&packed, root_inode);
@ -528,7 +528,7 @@ static int check_lostfound(struct bch_fs *c,
if (fsck_err_on(ret, c, "lost+found missing"))
goto create_lostfound;
if (fsck_err_on(!S_ISDIR(lostfound_inode->i_mode), c,
if (fsck_err_on(!S_ISDIR(lostfound_inode->bi_mode), c,
"lost+found inode not a directory"))
goto create_lostfound;
@ -536,7 +536,7 @@ static int check_lostfound(struct bch_fs *c,
fsck_err:
return ret;
create_lostfound:
root_inode->i_nlink++;
root_inode->bi_nlink++;
bch2_inode_pack(&packed, root_inode);
@ -553,7 +553,7 @@ create_lostfound:
return ret;
ret = bch2_dirent_create(c, BCACHEFS_ROOT_INO, &root_hash_info, DT_DIR,
&lostfound, lostfound_inode->inum, NULL,
&lostfound, lostfound_inode->bi_inum, NULL,
BTREE_INSERT_NOFAIL);
if (ret)
return ret;
@ -711,7 +711,7 @@ up:
for_each_btree_key(&iter, c, BTREE_ID_INODES, POS_MIN, 0, k) {
if (k.k->type != BCH_INODE_FS ||
!S_ISDIR(le16_to_cpu(bkey_s_c_to_inode(k).v->i_mode)))
!S_ISDIR(le16_to_cpu(bkey_s_c_to_inode(k).v->bi_mode)))
continue;
if (fsck_err_on(!inode_bitmap_test(&dirs_done, k.k->p.inode), c,
@ -849,15 +849,15 @@ static int bch2_gc_do_inode(struct bch_fs *c,
inode.k->p.inode))
return ret;
i_nlink = u.i_nlink + nlink_bias(u.i_mode);
i_nlink = u.bi_nlink + nlink_bias(u.bi_mode);
fsck_err_on(i_nlink < link.count, c,
"inode %llu i_link too small (%u < %u, type %i)",
inode.k->p.inode, i_nlink,
link.count, mode_to_type(u.i_mode));
link.count, mode_to_type(u.bi_mode));
/* These should have been caught/fixed by earlier passes: */
if (S_ISDIR(u.i_mode)) {
if (S_ISDIR(u.bi_mode)) {
need_fsck_err_on(link.count > 1, c,
"directory %llu with multiple hardlinks: %u",
inode.k->p.inode, link.count);
@ -877,7 +877,7 @@ static int bch2_gc_do_inode(struct bch_fs *c,
"but found orphaned inode %llu",
inode.k->p.inode);
if (fsck_err_on(S_ISDIR(u.i_mode) &&
if (fsck_err_on(S_ISDIR(u.bi_mode) &&
bch2_empty_dir(c, inode.k->p.inode), c,
"non empty directory with link count 0, "
"inode nlink %u, dir links found %u",
@ -897,7 +897,7 @@ static int bch2_gc_do_inode(struct bch_fs *c,
return ret;
}
if (u.i_flags & BCH_INODE_I_SIZE_DIRTY) {
if (u.bi_flags & BCH_INODE_I_SIZE_DIRTY) {
fsck_err_on(c->sb.clean, c,
"filesystem marked clean, "
"but inode %llu has i_size dirty",
@ -911,7 +911,7 @@ static int bch2_gc_do_inode(struct bch_fs *c,
*/
ret = bch2_inode_truncate(c, inode.k->p.inode,
round_up(u.i_size, PAGE_SIZE) >> 9,
round_up(u.bi_size, PAGE_SIZE) >> 9,
NULL, NULL);
if (ret) {
bch_err(c, "error in fs gc: error %i "
@ -923,13 +923,13 @@ static int bch2_gc_do_inode(struct bch_fs *c,
* We truncated without our normal sector accounting hook, just
* make sure we recalculate it:
*/
u.i_flags |= BCH_INODE_I_SECTORS_DIRTY;
u.bi_flags |= BCH_INODE_I_SECTORS_DIRTY;
u.i_flags &= ~BCH_INODE_I_SIZE_DIRTY;
u.bi_flags &= ~BCH_INODE_I_SIZE_DIRTY;
do_update = true;
}
if (u.i_flags & BCH_INODE_I_SECTORS_DIRTY) {
if (u.bi_flags & BCH_INODE_I_SECTORS_DIRTY) {
s64 sectors;
fsck_err_on(c->sb.clean, c,
@ -948,8 +948,8 @@ static int bch2_gc_do_inode(struct bch_fs *c,
return sectors;
}
u.i_sectors = sectors;
u.i_flags &= ~BCH_INODE_I_SECTORS_DIRTY;
u.bi_sectors = sectors;
u.bi_flags &= ~BCH_INODE_I_SECTORS_DIRTY;
do_update = true;
}
@ -958,12 +958,12 @@ static int bch2_gc_do_inode(struct bch_fs *c,
"filesystem marked clean, "
"but inode %llu has wrong i_nlink "
"(type %u i_nlink %u, should be %u)",
inode.k->p.inode, mode_to_type(u.i_mode),
inode.k->p.inode, mode_to_type(u.bi_mode),
i_nlink, real_i_nlink);
bch_verbose(c, "setting inode %llu nlinks from %u to %u",
inode.k->p.inode, i_nlink, real_i_nlink);
u.i_nlink = real_i_nlink - nlink_bias(u.i_mode);;
u.bi_nlink = real_i_nlink - nlink_bias(u.bi_mode);
do_update = true;
}

View File

@ -2,6 +2,7 @@
#include "bcachefs.h"
#include "bkey_methods.h"
#include "btree_update.h"
#include "error.h"
#include "extents.h"
#include "inode.h"
#include "io.h"
@ -91,10 +92,10 @@ void bch2_inode_pack(struct bkey_inode_buf *packed,
unsigned nr_fields = 0, last_nonzero_fieldnr = 0;
bkey_inode_init(&packed->inode.k_i);
packed->inode.k.p.inode = inode->inum;
packed->inode.v.i_hash_seed = inode->i_hash_seed;
packed->inode.v.i_flags = cpu_to_le32(inode->i_flags);
packed->inode.v.i_mode = cpu_to_le16(inode->i_mode);
packed->inode.k.p.inode = inode->bi_inum;
packed->inode.v.bi_hash_seed = inode->bi_hash_seed;
packed->inode.v.bi_flags = cpu_to_le32(inode->bi_flags);
packed->inode.v.bi_mode = cpu_to_le16(inode->bi_mode);
#define BCH_INODE_FIELD(_name, _bits) \
out += inode_encode_field(out, end, 0, inode->_name); \
@ -124,9 +125,9 @@ void bch2_inode_pack(struct bkey_inode_buf *packed,
int ret = bch2_inode_unpack(inode_i_to_s_c(&packed->inode),
&unpacked);
BUG_ON(ret);
BUG_ON(unpacked.inum != inode->inum);
BUG_ON(unpacked.i_hash_seed != inode->i_hash_seed);
BUG_ON(unpacked.i_mode != inode->i_mode);
BUG_ON(unpacked.bi_inum != inode->bi_inum);
BUG_ON(unpacked.bi_hash_seed != inode->bi_hash_seed);
BUG_ON(unpacked.bi_mode != inode->bi_mode);
#define BCH_INODE_FIELD(_name, _bits) BUG_ON(unpacked._name != inode->_name);
BCH_INODE_FIELDS()
@ -143,10 +144,10 @@ int bch2_inode_unpack(struct bkey_s_c_inode inode,
unsigned fieldnr = 0, field_bits;
int ret;
unpacked->inum = inode.k->p.inode;
unpacked->i_hash_seed = inode.v->i_hash_seed;
unpacked->i_flags = le32_to_cpu(inode.v->i_flags);
unpacked->i_mode = le16_to_cpu(inode.v->i_mode);
unpacked->bi_inum = inode.k->p.inode;
unpacked->bi_hash_seed = inode.v->bi_hash_seed;
unpacked->bi_flags = le32_to_cpu(inode.v->bi_flags);
unpacked->bi_mode = le16_to_cpu(inode.v->bi_mode);
#define BCH_INODE_FIELD(_name, _bits) \
if (fieldnr++ == INODE_NR_FIELDS(inode.v)) { \
@ -231,7 +232,7 @@ static void bch2_inode_to_text(struct bch_fs *c, char *buf,
break;
}
scnprintf(buf, size, "i_size %llu", unpacked.i_size);
scnprintf(buf, size, "i_size %llu", unpacked.bi_size);
break;
}
}
@ -249,17 +250,17 @@ void bch2_inode_init(struct bch_fs *c, struct bch_inode_unpacked *inode_u,
memset(inode_u, 0, sizeof(*inode_u));
/* ick */
inode_u->i_flags |= c->sb.str_hash_type << INODE_STR_HASH_OFFSET;
get_random_bytes(&inode_u->i_hash_seed, sizeof(inode_u->i_hash_seed));
inode_u->bi_flags |= c->opts.str_hash << INODE_STR_HASH_OFFSET;
get_random_bytes(&inode_u->bi_hash_seed, sizeof(inode_u->bi_hash_seed));
inode_u->i_mode = mode;
inode_u->i_uid = uid;
inode_u->i_gid = gid;
inode_u->i_dev = rdev;
inode_u->i_atime = now;
inode_u->i_mtime = now;
inode_u->i_ctime = now;
inode_u->i_otime = now;
inode_u->bi_mode = mode;
inode_u->bi_uid = uid;
inode_u->bi_gid = gid;
inode_u->bi_dev = rdev;
inode_u->bi_atime = now;
inode_u->bi_mtime = now;
inode_u->bi_ctime = now;
inode_u->bi_otime = now;
}
int bch2_inode_create(struct bch_fs *c, struct bch_inode_unpacked *inode_u,
@ -287,7 +288,7 @@ again:
while (1) {
struct bkey_s_c k = bch2_btree_iter_peek_with_holes(&iter);
u32 i_generation = 0;
u32 bi_generation = 0;
ret = btree_iter_err(k);
if (ret) {
@ -308,11 +309,11 @@ again:
case BCH_INODE_GENERATION: {
struct bkey_s_c_inode_generation g =
bkey_s_c_to_inode_generation(k);
i_generation = le32_to_cpu(g.v->i_generation);
bi_generation = le32_to_cpu(g.v->bi_generation);
/* fallthrough: */
}
default:
inode_u->i_generation = i_generation;
inode_u->bi_generation = bi_generation;
bch2_inode_pack(&inode_p, inode_u);
inode_p.inode.k.p = k.k->p;
@ -326,7 +327,7 @@ again:
bch2_btree_iter_unlock(&iter);
if (!ret) {
inode_u->inum =
inode_u->bi_inum =
inode_p.inode.k.p.inode;
*hint = inode_p.inode.k.p.inode + 1;
}
@ -384,7 +385,7 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr)
* but there could be whiteouts (from hash collisions) that we should
* delete:
*
* XXX: the dirent could ideally would delete whitouts when they're no
* XXX: the dirent could ideally would delete whiteouts when they're no
* longer needed
*/
ret = bch2_btree_delete_range(c, BTREE_ID_DIRENTS,
@ -398,7 +399,7 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr)
BTREE_ITER_INTENT);
do {
struct bkey_s_c k = bch2_btree_iter_peek_with_holes(&iter);
u32 i_generation = 0;
u32 bi_generation = 0;
ret = btree_iter_err(k);
if (ret) {
@ -406,29 +407,33 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr)
return ret;
}
bch2_fs_inconsistent_on(k.k->type != BCH_INODE_FS, c,
"inode %llu not found when deleting",
inode_nr);
switch (k.k->type) {
case BCH_INODE_FS: {
struct bch_inode_unpacked inode_u;
if (!bch2_inode_unpack(bkey_s_c_to_inode(k), &inode_u))
i_generation = cpu_to_le32(inode_u.i_generation) + 1;
bi_generation = cpu_to_le32(inode_u.bi_generation) + 1;
break;
}
case BCH_INODE_GENERATION: {
struct bkey_s_c_inode_generation g =
bkey_s_c_to_inode_generation(k);
i_generation = le32_to_cpu(g.v->i_generation);
bi_generation = le32_to_cpu(g.v->bi_generation);
break;
}
}
if (!i_generation) {
if (!bi_generation) {
bkey_init(&delete.k);
delete.k.p.inode = inode_nr;
} else {
bkey_inode_generation_init(&delete.k_i);
delete.k.p.inode = inode_nr;
delete.v.i_generation = cpu_to_le32(i_generation);
delete.v.bi_generation = cpu_to_le32(bi_generation);
}
ret = bch2_btree_insert_at(c, NULL, NULL, NULL,
@ -504,17 +509,17 @@ void bch2_inode_pack_test(void)
{
struct bch_inode_unpacked *u, test_inodes[] = {
{
.i_atime = U64_MAX,
.i_ctime = U64_MAX,
.i_mtime = U64_MAX,
.i_otime = U64_MAX,
.i_size = U64_MAX,
.i_sectors = U64_MAX,
.i_uid = U32_MAX,
.i_gid = U32_MAX,
.i_nlink = U32_MAX,
.i_generation = U32_MAX,
.i_dev = U32_MAX,
.bi_atime = U64_MAX,
.bi_ctime = U64_MAX,
.bi_mtime = U64_MAX,
.bi_otime = U64_MAX,
.bi_size = U64_MAX,
.bi_sectors = U64_MAX,
.bi_uid = U32_MAX,
.bi_gid = U32_MAX,
.bi_nlink = U32_MAX,
.bi_generation = U32_MAX,
.bi_dev = U32_MAX,
},
};

View File

@ -6,10 +6,10 @@
extern const struct bkey_ops bch2_bkey_inode_ops;
struct bch_inode_unpacked {
u64 inum;
__le64 i_hash_seed;
u32 i_flags;
u16 i_mode;
u64 bi_inum;
__le64 bi_hash_seed;
u32 bi_flags;
u16 bi_mode;
#define BCH_INODE_FIELD(_name, _bits) u##_bits _name;
BCH_INODE_FIELDS()
@ -22,7 +22,7 @@ struct bkey_inode_buf {
#define BCH_INODE_FIELD(_name, _bits) + 8 + _bits / 8
u8 _pad[0 + BCH_INODE_FIELDS()];
#undef BCH_INODE_FIELD
};
} __attribute__((packed, aligned(8)));
void bch2_inode_pack(struct bkey_inode_buf *, const struct bch_inode_unpacked *);
int bch2_inode_unpack(struct bkey_s_c_inode, struct bch_inode_unpacked *);

View File

@ -700,11 +700,11 @@ reread: sectors_read = min_t(unsigned,
case JOURNAL_ENTRY_NONE:
if (!saw_bad)
return 0;
sectors = c->sb.block_size;
sectors = c->opts.block_size;
goto next_block;
case JOURNAL_ENTRY_BAD:
saw_bad = true;
sectors = c->sb.block_size;
sectors = c->opts.block_size;
goto next_block;
default:
return ret;
@ -1192,7 +1192,7 @@ static enum {
j->prev_buf_sectors =
vstruct_blocks_plus(buf->data, c->block_bits,
journal_entry_u64s_reserve(buf)) *
c->sb.block_size;
c->opts.block_size;
BUG_ON(j->prev_buf_sectors > j->cur_buf_sectors);

View File

@ -66,42 +66,24 @@ const char * const bch2_dev_state[] = {
NULL
};
const struct bch_option bch2_opt_table[] = {
#define OPT_BOOL() .type = BCH_OPT_BOOL
#define OPT_UINT(_min, _max) .type = BCH_OPT_UINT, .min = _min, .max = _max
#define OPT_STR(_choices) .type = BCH_OPT_STR, .choices = _choices
#define BCH_OPT(_name, _mode, _sb_opt, _bits, _type) \
[Opt_##_name] = { \
.name = #_name, \
.set_sb = SET_##_sb_opt, \
_type \
},
BCH_VISIBLE_OPTS()
#undef BCH_OPT
};
static int bch2_opt_lookup(const char *name)
void bch2_opts_apply(struct bch_opts *dst, struct bch_opts src)
{
const struct bch_option *i;
#define BCH_OPT(_name, ...) \
if (opt_defined(src, _name)) \
opt_set(*dst, _name, src._name);
for (i = bch2_opt_table;
i < bch2_opt_table + ARRAY_SIZE(bch2_opt_table);
i++)
if (!strcmp(name, i->name))
return i - bch2_opt_table;
return -1;
BCH_OPTS()
#undef BCH_OPT
}
static u64 bch2_opt_get(struct bch_opts *opts, enum bch_opt_id id)
u64 bch2_opt_get_by_id(const struct bch_opts *opts, enum bch_opt_id id)
{
switch (id) {
#define BCH_OPT(_name, ...) \
case Opt_##_name: \
return opts->_name; \
BCH_VISIBLE_OPTS()
BCH_OPTS()
#undef BCH_OPT
default:
@ -109,15 +91,15 @@ static u64 bch2_opt_get(struct bch_opts *opts, enum bch_opt_id id)
}
}
void bch2_opt_set(struct bch_opts *opts, enum bch_opt_id id, u64 v)
void bch2_opt_set_by_id(struct bch_opts *opts, enum bch_opt_id id, u64 v)
{
switch (id) {
#define BCH_OPT(_name, ...) \
case Opt_##_name: \
opts->_name = v; \
opt_set(*opts, _name, v); \
break;
BCH_VISIBLE_OPTS()
BCH_OPTS()
#undef BCH_OPT
default:
@ -129,13 +111,13 @@ void bch2_opt_set(struct bch_opts *opts, enum bch_opt_id id, u64 v)
* Initial options from superblock - here we don't want any options undefined,
* any options the superblock doesn't specify are set to 0:
*/
struct bch_opts bch2_sb_opts(struct bch_sb *sb)
struct bch_opts bch2_opts_from_sb(struct bch_sb *sb)
{
struct bch_opts opts = bch2_opts_empty();
#define BCH_OPT(_name, _mode, _sb_opt, ...) \
#define BCH_OPT(_name, _bits, _mode, _type, _sb_opt, _default) \
if (_sb_opt != NO_SB_OPT) \
opts._name = _sb_opt(sb);
opt_set(opts, _name, _sb_opt(sb));
BCH_OPTS()
#undef BCH_OPT
@ -143,9 +125,41 @@ struct bch_opts bch2_sb_opts(struct bch_sb *sb)
return opts;
}
static int parse_one_opt(enum bch_opt_id id, const char *val, u64 *res)
const struct bch_option bch2_opt_table[] = {
#define OPT_BOOL() .type = BCH_OPT_BOOL
#define OPT_UINT(_min, _max) .type = BCH_OPT_UINT, .min = _min, .max = _max
#define OPT_STR(_choices) .type = BCH_OPT_STR, .choices = _choices
#define BCH_OPT(_name, _bits, _mode, _type, _sb_opt, _default) \
[Opt_##_name] = { \
.attr = { \
.name = #_name, \
.mode = _mode == OPT_RUNTIME ? 0644 : 0444, \
}, \
.mode = _mode, \
.set_sb = SET_##_sb_opt, \
_type \
},
BCH_OPTS()
#undef BCH_OPT
};
static int bch2_opt_lookup(const char *name)
{
const struct bch_option *i;
for (i = bch2_opt_table;
i < bch2_opt_table + ARRAY_SIZE(bch2_opt_table);
i++)
if (!strcmp(name, i->attr.name))
return i - bch2_opt_table;
return -1;
}
int bch2_opt_parse(const struct bch_option *opt, const char *val, u64 *res)
{
const struct bch_option *opt = &bch2_opt_table[id];
ssize_t ret;
switch (opt->type) {
@ -190,11 +204,11 @@ int bch2_parse_mount_opts(struct bch_opts *opts, char *options)
if (val) {
id = bch2_opt_lookup(name);
if (id < 0)
continue;
goto bad_opt;
ret = parse_one_opt(id, val, &v);
ret = bch2_opt_parse(&bch2_opt_table[id], val, &v);
if (ret < 0)
return ret;
goto bad_val;
} else {
id = bch2_opt_lookup(name);
v = 1;
@ -205,47 +219,31 @@ int bch2_parse_mount_opts(struct bch_opts *opts, char *options)
v = 0;
}
if (id < 0 ||
bch2_opt_table[id].type != BCH_OPT_BOOL)
continue;
if (id < 0)
goto bad_opt;
if (bch2_opt_table[id].type != BCH_OPT_BOOL)
goto no_val;
}
bch2_opt_set(opts, id, v);
if (bch2_opt_table[id].mode < OPT_MOUNT)
goto bad_opt;
if (id == Opt_acl &&
!IS_ENABLED(CONFIG_BCACHEFS_POSIX_ACL))
goto bad_opt;
bch2_opt_set_by_id(opts, id, v);
}
return 0;
}
enum bch_opt_id bch2_parse_sysfs_opt(const char *name, const char *val,
u64 *res)
{
int id = bch2_opt_lookup(name);
int ret;
if (id < 0)
return -EINVAL;
ret = parse_one_opt(id, val, res);
if (ret < 0)
return ret;
return id;
}
ssize_t bch2_opt_show(struct bch_opts *opts, const char *name,
char *buf, size_t size)
{
int id = bch2_opt_lookup(name);
const struct bch_option *opt;
u64 v;
if (id < 0)
return -EINVAL;
v = bch2_opt_get(opts, id);
opt = &bch2_opt_table[id];
return opt->type == BCH_OPT_STR
? bch2_scnprint_string_list(buf, size, opt->choices, v)
: scnprintf(buf, size, "%lli", v);
bad_opt:
pr_err("Bad mount option %s", name);
return -1;
bad_val:
pr_err("Invalid value %s for mount option %s", val, name);
return -1;
no_val:
pr_err("Mount option %s requires a value", name);
return -1;
}

View File

@ -4,6 +4,7 @@
#include <linux/bug.h>
#include <linux/log2.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include "bcachefs_format.h"
extern const char * const bch2_error_actions[];
@ -30,18 +31,12 @@ extern const char * const bch2_dev_state[];
/* dummy option, for options that aren't stored in the superblock */
LE64_BITMASK(NO_SB_OPT, struct bch_sb, flags[0], 0, 0);
/**
* BCH_OPT(name, mode, sb_opt, type, ...)
*
* @name - name of mount option, sysfs attribute, and struct bch_opts
* member
*
* @mode - sysfs attr permissions
*
* @sb_option - name of corresponding superblock option
*
* @type - one of OPT_BOOL, OPT_UINT, OPT_STR
*/
enum opt_mode {
OPT_INTERNAL,
OPT_FORMAT,
OPT_MOUNT,
OPT_RUNTIME,
};
enum opt_type {
BCH_OPT_BOOL,
@ -49,82 +44,162 @@ enum opt_type {
BCH_OPT_STR,
};
#define BCH_VISIBLE_OPTS() \
BCH_OPT(errors, 0644, BCH_SB_ERROR_ACTION, \
s8, OPT_STR(bch2_error_actions)) \
BCH_OPT(metadata_replicas, 0444, BCH_SB_META_REPLICAS_WANT,\
s8, OPT_UINT(1, BCH_REPLICAS_MAX)) \
BCH_OPT(data_replicas, 0444, BCH_SB_DATA_REPLICAS_WANT,\
s8, OPT_UINT(1, BCH_REPLICAS_MAX)) \
BCH_OPT(metadata_replicas_required, 0444, BCH_SB_META_REPLICAS_REQ,\
s8, OPT_UINT(1, BCH_REPLICAS_MAX)) \
BCH_OPT(data_replicas_required, 0444, BCH_SB_DATA_REPLICAS_REQ,\
s8, OPT_UINT(1, BCH_REPLICAS_MAX)) \
BCH_OPT(degraded, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(metadata_checksum, 0644, BCH_SB_META_CSUM_TYPE, \
s8, OPT_STR(bch2_csum_types)) \
BCH_OPT(data_checksum, 0644, BCH_SB_DATA_CSUM_TYPE, \
s8, OPT_STR(bch2_csum_types)) \
BCH_OPT(compression, 0644, BCH_SB_COMPRESSION_TYPE,\
s8, OPT_STR(bch2_compression_types)) \
BCH_OPT(str_hash, 0644, BCH_SB_STR_HASH_TYPE, \
s8, OPT_STR(bch2_str_hash_types)) \
BCH_OPT(inodes_32bit, 0644, BCH_SB_INODE_32BIT, \
s8, OPT_BOOL()) \
BCH_OPT(gc_reserve_percent, 0444, BCH_SB_GC_RESERVE, \
s8, OPT_UINT(5, 21)) \
BCH_OPT(root_reserve_percent, 0444, BCH_SB_ROOT_RESERVE, \
s8, OPT_UINT(0, 100)) \
BCH_OPT(wide_macs, 0644, BCH_SB_128_BIT_MACS, \
s8, OPT_BOOL()) \
BCH_OPT(verbose_recovery, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(posix_acl, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(journal_flush_disabled, 0644, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(nofsck, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(fix_errors, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(nochanges, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(noreplay, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(norecovery, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(noexcl, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(sb, 0444, NO_SB_OPT, \
s64, OPT_UINT(0, S64_MAX)) \
/**
* BCH_OPT(name, type, in mem type, mode, sb_opt)
*
* @name - name of mount option, sysfs attribute, and struct bch_opts
* member
*
* @mode - when opt may be set
*
* @sb_option - name of corresponding superblock option
*
* @type - one of OPT_BOOL, OPT_UINT, OPT_STR
*/
/*
* XXX: add fields for
* - default value
* - helptext
*/
#define BCH_OPTS() \
BCH_OPT(read_only, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_OPT(nostart, 0444, NO_SB_OPT, \
s8, OPT_BOOL()) \
BCH_VISIBLE_OPTS()
BCH_OPT(block_size, u16, OPT_FORMAT, \
OPT_UINT(1, 128), \
BCH_SB_BLOCK_SIZE, 8) \
BCH_OPT(btree_node_size, u16, OPT_FORMAT, \
OPT_UINT(1, 128), \
BCH_SB_BTREE_NODE_SIZE, 512) \
BCH_OPT(errors, u8, OPT_RUNTIME, \
OPT_STR(bch2_error_actions), \
BCH_SB_ERROR_ACTION, BCH_ON_ERROR_RO) \
BCH_OPT(metadata_replicas, u8, OPT_MOUNT, \
OPT_UINT(1, BCH_REPLICAS_MAX), \
BCH_SB_META_REPLICAS_WANT, 1) \
BCH_OPT(data_replicas, u8, OPT_MOUNT, \
OPT_UINT(1, BCH_REPLICAS_MAX), \
BCH_SB_DATA_REPLICAS_WANT, 1) \
BCH_OPT(metadata_replicas_required, u8, OPT_MOUNT, \
OPT_UINT(1, BCH_REPLICAS_MAX), \
BCH_SB_META_REPLICAS_REQ, 1) \
BCH_OPT(data_replicas_required, u8, OPT_MOUNT, \
OPT_UINT(1, BCH_REPLICAS_MAX), \
BCH_SB_DATA_REPLICAS_REQ, 1) \
BCH_OPT(metadata_checksum, u8, OPT_RUNTIME, \
OPT_STR(bch2_csum_types), \
BCH_SB_META_CSUM_TYPE, BCH_CSUM_OPT_CRC32C) \
BCH_OPT(data_checksum, u8, OPT_RUNTIME, \
OPT_STR(bch2_csum_types), \
BCH_SB_DATA_CSUM_TYPE, BCH_CSUM_OPT_CRC32C) \
BCH_OPT(compression, u8, OPT_RUNTIME, \
OPT_STR(bch2_compression_types), \
BCH_SB_COMPRESSION_TYPE, BCH_COMPRESSION_OPT_NONE)\
BCH_OPT(str_hash, u8, OPT_RUNTIME, \
OPT_STR(bch2_str_hash_types), \
BCH_SB_STR_HASH_TYPE, BCH_STR_HASH_SIPHASH) \
BCH_OPT(inodes_32bit, u8, OPT_RUNTIME, \
OPT_BOOL(), \
BCH_SB_INODE_32BIT, false) \
BCH_OPT(gc_reserve_percent, u8, OPT_MOUNT, \
OPT_UINT(5, 21), \
BCH_SB_GC_RESERVE, 8) \
BCH_OPT(root_reserve_percent, u8, OPT_MOUNT, \
OPT_UINT(0, 100), \
BCH_SB_ROOT_RESERVE, 0) \
BCH_OPT(wide_macs, u8, OPT_RUNTIME, \
OPT_BOOL(), \
BCH_SB_128_BIT_MACS, false) \
BCH_OPT(acl, u8, OPT_MOUNT, \
OPT_BOOL(), \
BCH_SB_POSIX_ACL, true) \
BCH_OPT(degraded, u8, OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false) \
BCH_OPT(verbose_recovery, u8, OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false) \
BCH_OPT(journal_flush_disabled, u8, OPT_RUNTIME, \
OPT_BOOL(), \
NO_SB_OPT, false) \
BCH_OPT(nofsck, u8, OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false) \
BCH_OPT(fix_errors, u8, OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false) \
BCH_OPT(nochanges, u8, OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false) \
BCH_OPT(noreplay, u8, OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false) \
BCH_OPT(norecovery, u8, OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false) \
BCH_OPT(noexcl, u8, OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false) \
BCH_OPT(sb, u64, OPT_MOUNT, \
OPT_UINT(0, S64_MAX), \
NO_SB_OPT, BCH_SB_SECTOR) \
BCH_OPT(read_only, u8, OPT_INTERNAL, \
OPT_BOOL(), \
NO_SB_OPT, false) \
BCH_OPT(nostart, u8, OPT_INTERNAL, \
OPT_BOOL(), \
NO_SB_OPT, false)
struct bch_opts {
#define BCH_OPT(_name, _mode, _sb_opt, _bits, ...) \
_bits _name;
#define BCH_OPT(_name, _bits, ...) unsigned _name##_defined:1;
BCH_OPTS()
#undef BCH_OPT
#define BCH_OPT(_name, _bits, ...) _bits _name;
BCH_OPTS()
#undef BCH_OPT
};
static const struct bch_opts bch2_opts_default = {
#define BCH_OPT(_name, _bits, _mode, _type, _sb_opt, _default) \
._name##_defined = true, \
._name = _default, \
BCH_OPTS()
#undef BCH_OPT
};
enum bch_opt_id {
#define BCH_OPT(_name, ...) \
Opt_##_name,
#define opt_defined(_opts, _name) ((_opts)._name##_defined)
BCH_VISIBLE_OPTS()
#define opt_get(_opts, _name) \
(opt_defined(_opts, _name) ? _opts._name : bch2_opts_default._name)
#define opt_set(_opts, _name, _v) \
do { \
(_opts)._name##_defined = true; \
(_opts)._name = _v; \
} while (0)
static inline struct bch_opts bch2_opts_empty(void)
{
struct bch_opts opts;
memset(&opts, 0, sizeof(opts));
return opts;
}
void bch2_opts_apply(struct bch_opts *, struct bch_opts);
enum bch_opt_id {
#define BCH_OPT(_name, ...) Opt_##_name,
BCH_OPTS()
#undef BCH_OPT
bch2_opts_nr
};
struct bch_option {
const char *name;
struct attribute attr;
void (*set_sb)(struct bch_sb *, u64);
enum opt_mode mode;
enum opt_type type;
union {
@ -140,32 +215,12 @@ struct bch_option {
extern const struct bch_option bch2_opt_table[];
static inline struct bch_opts bch2_opts_empty(void)
{
struct bch_opts ret;
u64 bch2_opt_get_by_id(const struct bch_opts *, enum bch_opt_id);
void bch2_opt_set_by_id(struct bch_opts *, enum bch_opt_id, u64);
memset(&ret, 255, sizeof(ret));
return ret;
}
static inline void bch2_opts_apply(struct bch_opts *dst, struct bch_opts src)
{
#define BCH_OPT(_name, ...) \
if (src._name >= 0) \
dst->_name = src._name;
BCH_OPTS()
#undef BCH_OPT
}
#define opt_defined(_opt) ((_opt) >= 0)
void bch2_opt_set(struct bch_opts *, enum bch_opt_id, u64);
struct bch_opts bch2_sb_opts(struct bch_sb *);
struct bch_opts bch2_opts_from_sb(struct bch_sb *);
int bch2_opt_parse(const struct bch_option *, const char *, u64 *);
int bch2_parse_mount_opts(struct bch_opts *, char *);
enum bch_opt_id bch2_parse_sysfs_opt(const char *, const char *, u64 *);
ssize_t bch2_opt_show(struct bch_opts *, const char *, char *, size_t);
#endif /* _BCACHEFS_OPTS_H */

View File

@ -26,14 +26,14 @@ bch2_hash_info_init(struct bch_fs *c,
{
/* XXX ick */
struct bch_hash_info info = {
.type = (bi->i_flags >> INODE_STR_HASH_OFFSET) &
.type = (bi->bi_flags >> INODE_STR_HASH_OFFSET) &
~(~0U << INODE_STR_HASH_BITS)
};
switch (info.type) {
case BCH_STR_HASH_CRC32C:
case BCH_STR_HASH_CRC64:
info.crc_key = bi->i_hash_seed;
info.crc_key = bi->bi_hash_seed;
break;
case BCH_STR_HASH_SIPHASH: {
SHASH_DESC_ON_STACK(desc, c->sha256);
@ -42,8 +42,8 @@ bch2_hash_info_init(struct bch_fs *c,
desc->tfm = c->sha256;
desc->flags = 0;
crypto_shash_digest(desc, (void *) &bi->i_hash_seed,
sizeof(bi->i_hash_seed), digest);
crypto_shash_digest(desc, (void *) &bi->bi_hash_seed,
sizeof(bi->bi_hash_seed), digest);
memcpy(&info.siphash_key, digest, sizeof(info.siphash_key));
break;
}

View File

@ -32,7 +32,7 @@ struct bch_sb_field *bch2_sb_field_get(struct bch_sb *sb,
return NULL;
}
void bch2_free_super(struct bcache_superblock *sb)
void bch2_free_super(struct bch_sb_handle *sb)
{
if (sb->bio)
bio_put(sb->bio);
@ -43,7 +43,7 @@ void bch2_free_super(struct bcache_superblock *sb)
memset(sb, 0, sizeof(*sb));
}
static int __bch2_super_realloc(struct bcache_superblock *sb, unsigned order)
static int __bch2_super_realloc(struct bch_sb_handle *sb, unsigned order)
{
struct bch_sb *new_sb;
struct bio *bio;
@ -77,7 +77,7 @@ static int __bch2_super_realloc(struct bcache_superblock *sb, unsigned order)
return 0;
}
static int bch2_sb_realloc(struct bcache_superblock *sb, unsigned u64s)
static int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s)
{
u64 new_bytes = __vstruct_bytes(struct bch_sb, u64s);
u64 max_bytes = 512 << sb->sb->layout.sb_max_size_bits;
@ -145,7 +145,7 @@ static struct bch_sb_field *__bch2_sb_field_resize(struct bch_sb *sb,
return f;
}
struct bch_sb_field *bch2_sb_field_resize(struct bcache_superblock *sb,
struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *sb,
enum bch_sb_field_type type,
unsigned u64s)
{
@ -179,7 +179,7 @@ struct bch_sb_field *bch2_fs_sb_field_resize(struct bch_fs *c,
/* XXX: we're not checking that offline device have enough space */
for_each_online_member(ca, c, i) {
struct bcache_superblock *sb = &ca->disk_sb;
struct bch_sb_handle *sb = &ca->disk_sb;
if (bch2_sb_realloc(sb, le32_to_cpu(sb->sb->u64s) + d)) {
percpu_ref_put(&ca->ref);
@ -305,7 +305,7 @@ static const char *bch2_sb_validate_members(struct bch_sb *sb)
return NULL;
}
const char *bch2_sb_validate(struct bcache_superblock *disk_sb)
const char *bch2_sb_validate(struct bch_sb_handle *disk_sb)
{
struct bch_sb *sb = disk_sb->sb;
struct bch_sb_field *f;
@ -318,8 +318,10 @@ const char *bch2_sb_validate(struct bcache_superblock *disk_sb)
le64_to_cpu(sb->version) > BCH_SB_VERSION_MAX)
return"Unsupported superblock version";
if (le64_to_cpu(sb->version) < BCH_SB_VERSION_EXTENT_MAX)
if (le64_to_cpu(sb->version) < BCH_SB_VERSION_EXTENT_MAX) {
SET_BCH_SB_ENCODED_EXTENT_MAX_BITS(sb, 7);
SET_BCH_SB_POSIX_ACL(sb, 1);
}
block_size = le16_to_cpu(sb->block_size);
@ -462,11 +464,8 @@ static void bch2_sb_update(struct bch_fs *c)
c->sb.uuid = src->uuid;
c->sb.user_uuid = src->user_uuid;
c->sb.block_size = le16_to_cpu(src->block_size);
c->sb.btree_node_size = BCH_SB_BTREE_NODE_SIZE(src);
c->sb.nr_devices = src->nr_devices;
c->sb.clean = BCH_SB_CLEAN(src);
c->sb.str_hash_type = BCH_SB_STR_HASH_TYPE(src);
c->sb.encryption_type = BCH_SB_ENCRYPTION_TYPE(src);
c->sb.encoded_extent_max= 1 << BCH_SB_ENCODED_EXTENT_MAX_BITS(src);
c->sb.time_base_lo = le64_to_cpu(src->time_base_lo);
@ -557,7 +556,7 @@ int bch2_sb_from_fs(struct bch_fs *c, struct bch_dev *ca)
/* read superblock: */
static const char *read_one_super(struct bcache_superblock *sb, u64 offset)
static const char *read_one_super(struct bch_sb_handle *sb, u64 offset)
{
struct bch_csum csum;
size_t bytes;
@ -605,37 +604,37 @@ reread:
return NULL;
}
const char *bch2_read_super(struct bcache_superblock *sb,
const char *bch2_read_super(const char *path,
struct bch_opts opts,
const char *path)
struct bch_sb_handle *ret)
{
u64 offset = opt_defined(opts.sb) ? opts.sb : BCH_SB_SECTOR;
u64 offset = opt_get(opts, sb);
struct bch_sb_layout layout;
const char *err;
unsigned i;
memset(sb, 0, sizeof(*sb));
sb->mode = FMODE_READ;
memset(ret, 0, sizeof(*ret));
ret->mode = FMODE_READ;
if (!(opt_defined(opts.noexcl) && opts.noexcl))
sb->mode |= FMODE_EXCL;
if (!opt_get(opts, noexcl))
ret->mode |= FMODE_EXCL;
if (!(opt_defined(opts.nochanges) && opts.nochanges))
sb->mode |= FMODE_WRITE;
if (!opt_get(opts, nochanges))
ret->mode |= FMODE_WRITE;
err = bch2_blkdev_open(path, sb->mode, sb, &sb->bdev);
err = bch2_blkdev_open(path, ret->mode, ret, &ret->bdev);
if (err)
return err;
err = "cannot allocate memory";
if (__bch2_super_realloc(sb, 0))
if (__bch2_super_realloc(ret, 0))
goto err;
err = "dynamic fault";
if (bch2_fs_init_fault("read_super"))
goto err;
err = read_one_super(sb, offset);
err = read_one_super(ret, offset);
if (!err)
goto got_super;
@ -650,22 +649,22 @@ const char *bch2_read_super(struct bcache_superblock *sb,
* Error reading primary superblock - read location of backup
* superblocks:
*/
bio_reset(sb->bio);
sb->bio->bi_bdev = sb->bdev;
sb->bio->bi_iter.bi_sector = BCH_SB_LAYOUT_SECTOR;
sb->bio->bi_iter.bi_size = sizeof(struct bch_sb_layout);
bio_set_op_attrs(sb->bio, REQ_OP_READ, REQ_SYNC|REQ_META);
bio_reset(ret->bio);
ret->bio->bi_bdev = ret->bdev;
ret->bio->bi_iter.bi_sector = BCH_SB_LAYOUT_SECTOR;
ret->bio->bi_iter.bi_size = sizeof(struct bch_sb_layout);
bio_set_op_attrs(ret->bio, REQ_OP_READ, REQ_SYNC|REQ_META);
/*
* use sb buffer to read layout, since sb buffer is page aligned but
* layout won't be:
*/
bch2_bio_map(sb->bio, sb->sb);
bch2_bio_map(ret->bio, ret->sb);
err = "IO error";
if (submit_bio_wait(sb->bio))
if (submit_bio_wait(ret->bio))
goto err;
memcpy(&layout, sb->sb, sizeof(layout));
memcpy(&layout, ret->sb, sizeof(layout));
err = validate_sb_layout(&layout);
if (err)
goto err;
@ -676,26 +675,26 @@ const char *bch2_read_super(struct bcache_superblock *sb,
if (offset == BCH_SB_SECTOR)
continue;
err = read_one_super(sb, offset);
err = read_one_super(ret, offset);
if (!err)
goto got_super;
}
goto err;
got_super:
pr_debug("read sb version %llu, flags %llu, seq %llu, journal size %u",
le64_to_cpu(sb->sb->version),
le64_to_cpu(sb->sb->flags),
le64_to_cpu(sb->sb->seq),
le16_to_cpu(sb->sb->u64s));
le64_to_cpu(ret->sb->version),
le64_to_cpu(ret->sb->flags),
le64_to_cpu(ret->sb->seq),
le16_to_cpu(ret->sb->u64s));
err = "Superblock block size smaller than device block size";
if (le16_to_cpu(sb->sb->block_size) << 9 <
bdev_logical_block_size(sb->bdev))
if (le16_to_cpu(ret->sb->block_size) << 9 <
bdev_logical_block_size(ret->bdev))
goto err;
return NULL;
err:
bch2_free_super(sb);
bch2_free_super(ret);
return err;
}

View File

@ -9,7 +9,7 @@
#include <asm/byteorder.h>
struct bch_sb_field *bch2_sb_field_get(struct bch_sb *, enum bch_sb_field_type);
struct bch_sb_field *bch2_sb_field_resize(struct bcache_superblock *,
struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *,
enum bch_sb_field_type, unsigned);
struct bch_sb_field *bch2_fs_sb_field_resize(struct bch_fs *,
enum bch_sb_field_type, unsigned);
@ -26,7 +26,7 @@ bch2_sb_get_##_name(struct bch_sb *sb) \
} \
\
static inline struct bch_sb_field_##_name * \
bch2_sb_resize_##_name(struct bcache_superblock *sb, unsigned u64s) \
bch2_sb_resize_##_name(struct bch_sb_handle *sb, unsigned u64s) \
{ \
return field_to_type(bch2_sb_field_resize(sb, \
BCH_SB_FIELD_##_name, u64s), _name); \
@ -112,15 +112,15 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
int bch2_sb_to_fs(struct bch_fs *, struct bch_sb *);
int bch2_sb_from_fs(struct bch_fs *, struct bch_dev *);
void bch2_free_super(struct bcache_superblock *);
int bch2_super_realloc(struct bcache_superblock *, unsigned);
void bch2_free_super(struct bch_sb_handle *);
int bch2_super_realloc(struct bch_sb_handle *, unsigned);
const char *bch2_sb_validate_journal(struct bch_sb *,
struct bch_member_cpu);
const char *bch2_sb_validate(struct bcache_superblock *);
const char *bch2_sb_validate(struct bch_sb_handle *);
const char *bch2_read_super(struct bcache_superblock *,
struct bch_opts, const char *);
const char *bch2_read_super(const char *, struct bch_opts,
struct bch_sb_handle *);
void bch2_write_super(struct bch_fs *);
/* replicas: */

View File

@ -241,13 +241,12 @@ static void bch2_writes_disabled(struct percpu_ref *writes)
void bch2_fs_read_only(struct bch_fs *c)
{
mutex_lock(&c->state_lock);
if (c->state != BCH_FS_STARTING &&
c->state != BCH_FS_RW)
goto out;
return;
if (test_bit(BCH_FS_ERROR, &c->flags))
goto out;
return;
/*
* Block new foreground-end write operations from starting - any new
@ -296,8 +295,6 @@ void bch2_fs_read_only(struct bch_fs *c)
}
c->state = BCH_FS_RO;
out:
mutex_unlock(&c->state_lock);
}
static void bch2_fs_read_only_work(struct work_struct *work)
@ -305,7 +302,9 @@ static void bch2_fs_read_only_work(struct work_struct *work)
struct bch_fs *c =
container_of(work, struct bch_fs, read_only_work);
mutex_lock(&c->state_lock);
bch2_fs_read_only(c);
mutex_unlock(&c->state_lock);
}
static void bch2_fs_read_only_async(struct bch_fs *c)
@ -330,10 +329,9 @@ const char *bch2_fs_read_write(struct bch_fs *c)
const char *err = NULL;
unsigned i;
mutex_lock(&c->state_lock);
if (c->state != BCH_FS_STARTING &&
c->state != BCH_FS_RO)
goto out;
return NULL;
for_each_rw_member(ca, c, i)
bch2_dev_allocator_add(c, ca);
@ -367,13 +365,10 @@ const char *bch2_fs_read_write(struct bch_fs *c)
percpu_ref_reinit(&c->writes);
c->state = BCH_FS_RW;
err = NULL;
out:
mutex_unlock(&c->state_lock);
return err;
return NULL;
err:
__bch2_fs_read_only(c);
goto out;
return err;
}
/* Filesystem startup/shutdown: */
@ -452,7 +447,9 @@ static void bch2_fs_offline(struct bch_fs *c)
kobject_put(&c->opts_dir);
kobject_put(&c->internal);
mutex_lock(&c->state_lock);
__bch2_fs_read_only(c);
mutex_unlock(&c->state_lock);
}
static void bch2_fs_release(struct kobject *kobj)
@ -555,15 +552,16 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
goto err;
}
c->block_bits = ilog2(c->sb.block_size);
mutex_unlock(&c->sb_lock);
scnprintf(c->name, sizeof(c->name), "%pU", &c->sb.user_uuid);
bch2_opts_apply(&c->opts, bch2_sb_opts(sb));
c->opts = bch2_opts_default;
bch2_opts_apply(&c->opts, bch2_opts_from_sb(sb));
bch2_opts_apply(&c->opts, opts);
c->block_bits = ilog2(c->opts.block_size);
c->opts.nochanges |= c->opts.noreplay;
c->opts.read_only |= c->opts.nochanges;
@ -590,7 +588,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
bioset_init(&c->bio_write, 1, offsetof(struct bch_write_bio, bio)) ||
mempool_init_page_pool(&c->bio_bounce_pages,
max_t(unsigned,
c->sb.btree_node_size,
c->opts.btree_node_size,
c->sb.encoded_extent_max) /
PAGE_SECTORS, 0) ||
!(c->usage_percpu = alloc_percpu(struct bch_fs_usage)) ||
@ -657,7 +655,8 @@ static const char *__bch2_fs_online(struct bch_fs *c)
if (kobject_add(&c->kobj, NULL, "%pU", c->sb.user_uuid.b) ||
kobject_add(&c->internal, &c->kobj, "internal") ||
kobject_add(&c->opts_dir, &c->kobj, "options") ||
kobject_add(&c->time_stats, &c->kobj, "time_stats"))
kobject_add(&c->time_stats, &c->kobj, "time_stats") ||
bch2_opts_create_sysfs_files(&c->opts_dir))
return "error creating sysfs objects";
mutex_lock(&c->state_lock);
@ -699,6 +698,8 @@ static const char *__bch2_fs_start(struct bch_fs *c)
closure_init_stack(&cl);
mutex_lock(&c->state_lock);
BUG_ON(c->state != BCH_FS_STARTING);
mutex_lock(&c->sb_lock);
@ -742,6 +743,8 @@ static const char *__bch2_fs_start(struct bch_fs *c)
if (ret)
goto err;
set_bit(BCH_FS_ALLOC_READ_DONE, &c->flags);
bch_verbose(c, "starting mark and sweep:");
err = "error in recovery";
ret = bch2_initial_gc(c, &journal);
@ -796,6 +799,8 @@ static const char *__bch2_fs_start(struct bch_fs *c)
bch_notice(c, "initializing new filesystem");
set_bit(BCH_FS_ALLOC_READ_DONE, &c->flags);
ret = bch2_initial_gc(c, &journal);
if (ret)
goto err;
@ -831,7 +836,7 @@ static const char *__bch2_fs_start(struct bch_fs *c)
bch2_inode_init(c, &inode, 0, 0,
S_IFDIR|S_IRWXU|S_IRUGO|S_IXUGO, 0);
inode.inum = BCACHEFS_ROOT_INO;
inode.bi_inum = BCACHEFS_ROOT_INO;
bch2_inode_pack(&packed_inode, &inode);
@ -873,6 +878,7 @@ recovery_done:
err = NULL;
out:
mutex_unlock(&c->state_lock);
bch2_journal_entries_free(&journal);
return err;
err:
@ -922,7 +928,7 @@ static const char *bch2_dev_may_add(struct bch_sb *sb, struct bch_fs *c)
if (!sb_mi)
return "Invalid superblock: member info area missing";
if (le16_to_cpu(sb->block_size) != c->sb.block_size)
if (le16_to_cpu(sb->block_size) != c->opts.block_size)
return "mismatched block size";
if (le16_to_cpu(sb_mi->members[sb->dev_idx].bucket_size) <
@ -1129,7 +1135,7 @@ static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx)
btree_node_reserve_buckets =
DIV_ROUND_UP(BTREE_NODE_RESERVE,
ca->mi.bucket_size / c->sb.btree_node_size);
ca->mi.bucket_size / c->opts.btree_node_size);
if (percpu_ref_init(&ca->ref, bch2_dev_ref_release,
0, GFP_KERNEL) ||
@ -1176,7 +1182,7 @@ err:
return -ENOMEM;
}
static int __bch2_dev_online(struct bch_fs *c, struct bcache_superblock *sb)
static int __bch2_dev_online(struct bch_fs *c, struct bch_sb_handle *sb)
{
struct bch_dev *ca;
int ret;
@ -1462,7 +1468,7 @@ err:
/* Add new device to running filesystem: */
int bch2_dev_add(struct bch_fs *c, const char *path)
{
struct bcache_superblock sb;
struct bch_sb_handle sb;
const char *err;
struct bch_dev *ca = NULL;
struct bch_sb_field_members *mi, *dev_mi;
@ -1470,7 +1476,7 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
unsigned dev_idx, nr_devices, u64s;
int ret = -EINVAL;
err = bch2_read_super(&sb, bch2_opts_empty(), path);
err = bch2_read_super(path, bch2_opts_empty(), &sb);
if (err)
return -EINVAL;
@ -1572,14 +1578,14 @@ err:
/* Hot add existing device to running filesystem: */
int bch2_dev_online(struct bch_fs *c, const char *path)
{
struct bcache_superblock sb = { 0 };
struct bch_sb_handle sb = { 0 };
struct bch_dev *ca;
unsigned dev_idx;
const char *err;
mutex_lock(&c->state_lock);
err = bch2_read_super(&sb, bch2_opts_empty(), path);
err = bch2_read_super(path, bch2_opts_empty(), &sb);
if (err)
goto err;
@ -1673,7 +1679,7 @@ const char *bch2_fs_open(char * const *devices, unsigned nr_devices,
{
const char *err;
struct bch_fs *c = NULL;
struct bcache_superblock *sb;
struct bch_sb_handle *sb;
unsigned i, best_sb = 0;
if (!nr_devices)
@ -1688,7 +1694,7 @@ const char *bch2_fs_open(char * const *devices, unsigned nr_devices,
goto err;
for (i = 0; i < nr_devices; i++) {
err = bch2_read_super(&sb[i], opts, devices[i]);
err = bch2_read_super(devices[i], opts, &sb[i]);
if (err)
goto err;
@ -1757,7 +1763,7 @@ err:
goto out;
}
static const char *__bch2_fs_open_incremental(struct bcache_superblock *sb,
static const char *__bch2_fs_open_incremental(struct bch_sb_handle *sb,
struct bch_opts opts)
{
const char *err;
@ -1821,11 +1827,11 @@ err:
const char *bch2_fs_open_incremental(const char *path)
{
struct bcache_superblock sb;
struct bch_sb_handle sb;
struct bch_opts opts = bch2_opts_empty();
const char *err;
err = bch2_read_super(&sb, opts, path);
err = bch2_read_super(path, opts, &sb);
if (err)
return err;

View File

@ -1,7 +1,7 @@
#ifndef _BCACHEFS_SUPER_TYPES_H
#define _BCACHEFS_SUPER_TYPES_H
struct bcache_superblock {
struct bch_sb_handle {
struct bch_sb *sb;
struct block_device *bdev;
struct bio *bio;

View File

@ -194,14 +194,6 @@ read_attribute(data_replicas_have);
BCH_DEBUG_PARAMS()
#undef BCH_DEBUG_PARAM
#define BCH_OPT(_name, _mode, ...) \
static struct attribute sysfs_opt_##_name = { \
.name = #_name, .mode = _mode, \
};
BCH_VISIBLE_OPTS()
#undef BCH_OPT
#define BCH_TIME_STAT(name, frequency_units, duration_units) \
sysfs_time_stats_attribute(name, frequency_units, duration_units);
BCH_TIME_STATS()
@ -528,8 +520,13 @@ SHOW(bch2_fs_opts_dir)
{
char *out = buf, *end = buf + PAGE_SIZE;
struct bch_fs *c = container_of(kobj, struct bch_fs, opts_dir);
const struct bch_option *opt = container_of(attr, struct bch_option, attr);
int id = opt - bch2_opt_table;
u64 v = bch2_opt_get_by_id(&c->opts, id);
out += bch2_opt_show(&c->opts, attr->name, out, end - out);
out += opt->type == BCH_OPT_STR
? bch2_scnprint_string_list(out, end - out, opt->choices, v)
: scnprintf(out, end - out, "%lli", v);
out += scnprintf(out, end - out, "\n");
return out - buf;
@ -538,15 +535,13 @@ SHOW(bch2_fs_opts_dir)
STORE(bch2_fs_opts_dir)
{
struct bch_fs *c = container_of(kobj, struct bch_fs, opts_dir);
const struct bch_option *opt;
int id;
const struct bch_option *opt = container_of(attr, struct bch_option, attr);
int ret, id = opt - bch2_opt_table;
u64 v;
id = bch2_parse_sysfs_opt(attr->name, buf, &v);
if (id < 0)
return id;
opt = &bch2_opt_table[id];
ret = bch2_opt_parse(opt, buf, &v);
if (ret < 0)
return ret;
mutex_lock(&c->sb_lock);
@ -563,7 +558,7 @@ STORE(bch2_fs_opts_dir)
bch2_write_super(c);
}
bch2_opt_set(&c->opts, id, v);
bch2_opt_set_by_id(&c->opts, id, v);
mutex_unlock(&c->sb_lock);
@ -571,15 +566,26 @@ STORE(bch2_fs_opts_dir)
}
SYSFS_OPS(bch2_fs_opts_dir);
struct attribute *bch2_fs_opts_dir_files[] = {
#define BCH_OPT(_name, ...) \
&sysfs_opt_##_name,
struct attribute *bch2_fs_opts_dir_files[] = { NULL };
BCH_VISIBLE_OPTS()
#undef BCH_OPT
int bch2_opts_create_sysfs_files(struct kobject *kobj)
{
const struct bch_option *i;
int ret;
NULL
};
for (i = bch2_opt_table;
i < bch2_opt_table + bch2_opts_nr;
i++) {
if (i->mode == OPT_INTERNAL)
continue;
ret = sysfs_create_file(kobj, &i->attr);
if (ret)
return ret;
}
return 0;
}
/* time stats */

View File

@ -20,6 +20,8 @@ extern struct sysfs_ops bch2_fs_opts_dir_sysfs_ops;
extern struct sysfs_ops bch2_fs_time_stats_sysfs_ops;
extern struct sysfs_ops bch2_dev_sysfs_ops;
int bch2_opts_create_sysfs_files(struct kobject *);
#else
static struct attribute *bch2_fs_files[] = {};
@ -34,6 +36,8 @@ static const struct sysfs_ops bch2_fs_opts_dir_sysfs_ops;
static const struct sysfs_ops bch2_fs_time_stats_sysfs_ops;
static const struct sysfs_ops bch2_dev_sysfs_ops;
static inline int bch2_opts_create_sysfs_files(struct kobject *kobj) { return 0; }
#endif /* NO_BCACHEFS_SYSFS */
#endif /* _BCACHEFS_SYSFS_H_ */

View File

@ -162,17 +162,16 @@ const struct bkey_ops bch2_bkey_xattr_ops = {
.val_to_text = bch2_xattr_to_text,
};
int bch2_xattr_get(struct bch_fs *c, struct inode *inode,
int bch2_xattr_get(struct bch_fs *c, struct bch_inode_info *inode,
const char *name, void *buffer, size_t size, int type)
{
struct bch_inode_info *ei = to_bch_ei(inode);
struct btree_iter iter;
struct bkey_s_c k;
struct bkey_s_c_xattr xattr;
int ret;
k = bch2_hash_lookup(bch2_xattr_hash_desc, &ei->str_hash, c,
ei->vfs_inode.i_ino, &iter,
k = bch2_hash_lookup(bch2_xattr_hash_desc, &inode->ei_str_hash, c,
inode->v.i_ino, &iter,
&X_SEARCH(type, name, strlen(name)));
if (IS_ERR(k.k))
return bch2_btree_iter_unlock(&iter) ?: -ENODATA;
@ -236,15 +235,13 @@ int __bch2_xattr_set(struct bch_fs *c, u64 inum,
return ret;
}
int bch2_xattr_set(struct bch_fs *c, struct inode *inode,
int bch2_xattr_set(struct bch_fs *c, struct bch_inode_info *inode,
const char *name, const void *value, size_t size,
int flags, int type)
{
struct bch_inode_info *ei = to_bch_ei(inode);
return __bch2_xattr_set(c, inode->i_ino, &ei->str_hash,
return __bch2_xattr_set(c, inode->v.i_ino, &inode->ei_str_hash,
name, value, size, flags, type,
&ei->journal_seq);
&inode->ei_journal_seq);
}
static size_t bch2_xattr_emit(struct dentry *dentry,
@ -313,20 +310,22 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
}
static int bch2_xattr_get_handler(const struct xattr_handler *handler,
struct dentry *dentry, struct inode *inode,
struct dentry *dentry, struct inode *vinode,
const char *name, void *buffer, size_t size)
{
struct bch_fs *c = inode->i_sb->s_fs_info;
struct bch_inode_info *inode = to_bch_ei(vinode);
struct bch_fs *c = inode->v.i_sb->s_fs_info;
return bch2_xattr_get(c, inode, name, buffer, size, handler->flags);
}
static int bch2_xattr_set_handler(const struct xattr_handler *handler,
struct dentry *dentry, struct inode *inode,
struct dentry *dentry, struct inode *vinode,
const char *name, const void *value,
size_t size, int flags)
{
struct bch_fs *c = inode->i_sb->s_fs_info;
struct bch_inode_info *inode = to_bch_ei(vinode);
struct bch_fs *c = inode->v.i_sb->s_fs_info;
return bch2_xattr_set(c, inode, name, value, size, flags,
handler->flags);

View File

@ -9,12 +9,13 @@ extern const struct bkey_ops bch2_bkey_xattr_ops;
struct dentry;
struct xattr_handler;
struct bch_hash_info;
struct bch_inode_info;
int bch2_xattr_get(struct bch_fs *, struct inode *,
int bch2_xattr_get(struct bch_fs *, struct bch_inode_info *,
const char *, void *, size_t, int);
int __bch2_xattr_set(struct bch_fs *, u64, const struct bch_hash_info *,
const char *, const void *, size_t, int, int, u64 *);
int bch2_xattr_set(struct bch_fs *, struct inode *,
int bch2_xattr_set(struct bch_fs *, struct bch_inode_info *,
const char *, const void *, size_t, int, int);
ssize_t bch2_xattr_list(struct dentry *, char *, size_t);