summaryrefslogtreecommitdiffstats
path: root/fs/bcachefs/alloc.h
blob: 739df233236c33c8330d36ede894bd9602be16f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#ifndef _BCACHEFS_ALLOC_H
#define _BCACHEFS_ALLOC_H

#include "bcachefs.h"
#include "alloc_types.h"

struct bkey;
struct bch_dev;
struct bch_fs;
struct bch_devs_List;

#define ALLOC_SCAN_BATCH(ca)		((ca)->mi.nbuckets >> 9)

const char *bch2_alloc_invalid(const struct bch_fs *, struct bkey_s_c);
int bch2_alloc_to_text(struct bch_fs *, char *, size_t, struct bkey_s_c);

#define bch2_bkey_alloc_ops (struct bkey_ops) {		\
	.key_invalid	= bch2_alloc_invalid,		\
	.val_to_text	= bch2_alloc_to_text,		\
}

struct dev_alloc_list {
	unsigned	nr;
	u8		devs[BCH_SB_MEMBERS_MAX];
};

struct dev_alloc_list bch2_wp_alloc_list(struct bch_fs *,
					 struct write_point *,
					 struct bch_devs_mask *);
void bch2_wp_rescale(struct bch_fs *, struct bch_dev *,
		     struct write_point *);

int bch2_alloc_read(struct bch_fs *, struct list_head *);
int bch2_alloc_replay_key(struct bch_fs *, struct bpos);

enum bucket_alloc_ret {
	ALLOC_SUCCESS		= 0,
	OPEN_BUCKETS_EMPTY	= -1,
	FREELIST_EMPTY		= -2,	/* Allocator thread not keeping up */
	NO_DEVICES		= -3,	/* -EROFS */
};

long bch2_bucket_alloc_new_fs(struct bch_dev *);

int bch2_bucket_alloc(struct bch_fs *, struct bch_dev *, enum alloc_reserve, bool,
		      struct closure *);

#define __writepoint_for_each_ptr(_wp, _ob, _i, _start)			\
	for ((_i) = (_start);						\
	     (_i) < (_wp)->nr_ptrs && ((_ob) = (_wp)->ptrs[_i], true);	\
	     (_i)++)

#define writepoint_for_each_ptr_all(_wp, _ob, _i)			\
	__writepoint_for_each_ptr(_wp, _ob, _i, 0)

#define writepoint_for_each_ptr(_wp, _ob, _i)				\
	__writepoint_for_each_ptr(_wp, _ob, _i, wp->first_ptr)

void __bch2_open_bucket_put(struct bch_fs *, struct open_bucket *);

static inline void bch2_open_bucket_put(struct bch_fs *c, struct open_bucket *ob)
{
	if (atomic_dec_and_test(&ob->pin))
		__bch2_open_bucket_put(c, ob);
}

static inline void bch2_open_bucket_put_refs(struct bch_fs *c, u8 *nr, u8 *refs)
{
	unsigned i;

	for (i = 0; i < *nr; i++)
		bch2_open_bucket_put(c, c->open_buckets + refs[i]);

	*nr = 0;
}

static inline void bch2_open_bucket_get(struct bch_fs *c,
					struct write_point *wp,
					u8 *nr, u8 *refs)
{
	struct open_bucket *ob;
	unsigned i;

	writepoint_for_each_ptr(wp, ob, i) {
		atomic_inc(&ob->pin);
		refs[(*nr)++] = ob - c->open_buckets;
	}
}

struct write_point *bch2_alloc_sectors_start(struct bch_fs *,
					     unsigned,
					     struct write_point_specifier,
					     struct bch_devs_list *,
					     unsigned, unsigned,
					     enum alloc_reserve,
					     unsigned,
					     struct closure *);

void bch2_alloc_sectors_append_ptrs(struct bch_fs *, struct write_point *,
				    struct bkey_i_extent *, unsigned);
void bch2_alloc_sectors_done(struct bch_fs *, struct write_point *);

static inline void bch2_wake_allocator(struct bch_dev *ca)
{
	struct task_struct *p;

	rcu_read_lock();
	p = rcu_dereference(ca->alloc_thread);
	if (p)
		wake_up_process(p);
	rcu_read_unlock();
}

static inline struct write_point_specifier writepoint_hashed(unsigned long v)
{
	return (struct write_point_specifier) { .v = v | 1 };
}

static inline struct write_point_specifier writepoint_ptr(struct write_point *wp)
{
	return (struct write_point_specifier) { .v = (unsigned long) wp };
}

void bch2_recalc_capacity(struct bch_fs *);

void bch2_dev_allocator_remove(struct bch_fs *, struct bch_dev *);
void bch2_dev_allocator_add(struct bch_fs *, struct bch_dev *);

void bch2_dev_allocator_stop(struct bch_dev *);
int bch2_dev_allocator_start(struct bch_dev *);

static inline void writepoint_init(struct write_point *wp,
				   enum bch_data_type type)
{
	mutex_init(&wp->lock);
	wp->type = type;
}

int bch2_alloc_write(struct bch_fs *);
int bch2_fs_allocator_start(struct bch_fs *);
void bch2_fs_allocator_init(struct bch_fs *);

#endif /* _BCACHEFS_ALLOC_H */