2017-03-17 06:18:50 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
#ifndef _BCACHEFS_DISK_GROUPS_H
|
|
|
|
#define _BCACHEFS_DISK_GROUPS_H
|
|
|
|
|
2023-10-22 14:58:38 +00:00
|
|
|
#include "disk_groups_types.h"
|
|
|
|
|
2017-03-17 06:18:50 +00:00
|
|
|
extern const struct bch_sb_field_ops bch_sb_field_ops_disk_groups;
|
|
|
|
|
|
|
|
static inline unsigned disk_groups_nr(struct bch_sb_field_disk_groups *groups)
|
|
|
|
{
|
|
|
|
return groups
|
|
|
|
? (vstruct_end(&groups->field) -
|
|
|
|
(void *) &groups->entries[0]) / sizeof(struct bch_disk_group)
|
|
|
|
: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct target {
|
|
|
|
enum {
|
|
|
|
TARGET_NULL,
|
|
|
|
TARGET_DEV,
|
|
|
|
TARGET_GROUP,
|
|
|
|
} type;
|
|
|
|
union {
|
|
|
|
unsigned dev;
|
|
|
|
unsigned group;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
#define TARGET_DEV_START 1
|
|
|
|
#define TARGET_GROUP_START (256 + TARGET_DEV_START)
|
|
|
|
|
|
|
|
static inline u16 dev_to_target(unsigned dev)
|
|
|
|
{
|
|
|
|
return TARGET_DEV_START + dev;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline u16 group_to_target(unsigned group)
|
|
|
|
{
|
|
|
|
return TARGET_GROUP_START + group;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct target target_decode(unsigned target)
|
|
|
|
{
|
|
|
|
if (target >= TARGET_GROUP_START)
|
|
|
|
return (struct target) {
|
|
|
|
.type = TARGET_GROUP,
|
|
|
|
.group = target - TARGET_GROUP_START
|
|
|
|
};
|
|
|
|
|
|
|
|
if (target >= TARGET_DEV_START)
|
|
|
|
return (struct target) {
|
|
|
|
.type = TARGET_DEV,
|
|
|
|
.group = target - TARGET_DEV_START
|
|
|
|
};
|
|
|
|
|
|
|
|
return (struct target) { .type = TARGET_NULL };
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct bch_devs_mask *bch2_target_to_mask(struct bch_fs *, unsigned);
|
2018-11-01 19:13:19 +00:00
|
|
|
|
|
|
|
static inline struct bch_devs_mask target_rw_devs(struct bch_fs *c,
|
|
|
|
enum bch_data_type data_type,
|
|
|
|
u16 target)
|
|
|
|
{
|
|
|
|
struct bch_devs_mask devs = c->rw_devs[data_type];
|
|
|
|
const struct bch_devs_mask *t = bch2_target_to_mask(c, target);
|
|
|
|
|
|
|
|
if (t)
|
|
|
|
bitmap_and(devs.d, devs.d, t->d, BCH_SB_MEMBERS_MAX);
|
|
|
|
return devs;
|
|
|
|
}
|
|
|
|
|
bcachefs: don't spin in rebalance when background target is not usable
If a bcachefs filesystem is configured with a background device
(disk group), rebalance will relocate data to this device in the
background by checking extent keys for whether they currently reside
in the specified target. For keys that do not, rebalance performs a
read/write cycle to allow the write path to properly relocate data.
If the background target is not usable (read-only, for example),
however, the write path doesn't actually move data to another
device. Instead, rebalance spins indefinitely reading and rewriting
the same data over and over to the same device. If the background
target is made available again, the rebalance picks this up,
relocates the data, and eventually terminates.
To avoid this spinning behavior, update the rebalance background
target logic to not only check whether the extent is not in the
target, but whether the target is actually usable as well. If not,
then don't mark the key for rewrite.
Signed-off-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2023-05-30 18:51:12 +00:00
|
|
|
static inline bool bch2_target_accepts_data(struct bch_fs *c,
|
|
|
|
enum bch_data_type data_type,
|
|
|
|
u16 target)
|
|
|
|
{
|
|
|
|
struct bch_devs_mask rw_devs = target_rw_devs(c, data_type, target);
|
|
|
|
return !bitmap_empty(rw_devs.d, BCH_SB_MEMBERS_MAX);
|
|
|
|
}
|
|
|
|
|
2017-03-17 06:18:50 +00:00
|
|
|
bool bch2_dev_in_target(struct bch_fs *, unsigned, unsigned);
|
|
|
|
|
|
|
|
int bch2_disk_path_find(struct bch_sb_handle *, const char *);
|
2020-08-12 19:00:08 +00:00
|
|
|
|
|
|
|
/* Exported for userspace bcachefs-tools: */
|
2017-03-17 06:18:50 +00:00
|
|
|
int bch2_disk_path_find_or_create(struct bch_sb_handle *, const char *);
|
2020-08-12 19:00:08 +00:00
|
|
|
|
2023-10-22 15:12:14 +00:00
|
|
|
void bch2_disk_path_to_text(struct printbuf *, struct bch_fs *, unsigned);
|
|
|
|
void bch2_disk_path_to_text_sb(struct printbuf *, struct bch_sb *, unsigned);
|
|
|
|
|
2023-10-22 14:54:24 +00:00
|
|
|
void bch2_target_to_text(struct printbuf *out, struct bch_fs *, unsigned);
|
2022-02-20 10:00:45 +00:00
|
|
|
|
2023-07-13 01:48:32 +00:00
|
|
|
int bch2_opt_target_parse(struct bch_fs *, const char *, u64 *, struct printbuf *);
|
2022-03-05 17:01:16 +00:00
|
|
|
void bch2_opt_target_to_text(struct printbuf *, struct bch_fs *, struct bch_sb *, u64);
|
2017-03-17 06:18:50 +00:00
|
|
|
|
2023-07-13 01:48:32 +00:00
|
|
|
#define bch2_opt_target (struct bch_opt_fn) { \
|
|
|
|
.parse = bch2_opt_target_parse, \
|
|
|
|
.to_text = bch2_opt_target_to_text, \
|
|
|
|
}
|
|
|
|
|
2017-03-17 06:18:50 +00:00
|
|
|
int bch2_sb_disk_groups_to_cpu(struct bch_fs *);
|
|
|
|
|
2022-08-18 21:57:24 +00:00
|
|
|
int __bch2_dev_group_set(struct bch_fs *, struct bch_dev *, const char *);
|
2017-03-17 06:18:50 +00:00
|
|
|
int bch2_dev_group_set(struct bch_fs *, struct bch_dev *, const char *);
|
|
|
|
|
|
|
|
const char *bch2_sb_validate_disk_groups(struct bch_sb *,
|
|
|
|
struct bch_sb_field *);
|
|
|
|
|
2023-05-30 18:41:50 +00:00
|
|
|
void bch2_disk_groups_to_text(struct printbuf *, struct bch_fs *);
|
|
|
|
|
2017-03-17 06:18:50 +00:00
|
|
|
#endif /* _BCACHEFS_DISK_GROUPS_H */
|