]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcache/super.h
bcache in userspace; userspace fsck
[bcachefs-tools-debian] / libbcache / super.h
1 #ifndef _BCACHE_SUPER_H
2 #define _BCACHE_SUPER_H
3
4 #include "extents.h"
5
6 static inline size_t sector_to_bucket(const struct cache *ca, sector_t s)
7 {
8         return s >> ca->bucket_bits;
9 }
10
11 static inline sector_t bucket_to_sector(const struct cache *ca, size_t b)
12 {
13         return ((sector_t) b) << ca->bucket_bits;
14 }
15
16 static inline sector_t bucket_remainder(const struct cache *ca, sector_t s)
17 {
18         return s & (ca->mi.bucket_size - 1);
19 }
20
21 #define cache_member_info_get(_c)                                       \
22         (rcu_read_lock(), rcu_dereference((_c)->members))
23
24 #define cache_member_info_put() rcu_read_unlock()
25
26 static inline struct cache *bch_next_cache_rcu(struct cache_set *c,
27                                                unsigned *iter)
28 {
29         struct cache *ret = NULL;
30
31         while (*iter < c->sb.nr_in_set &&
32                !(ret = rcu_dereference(c->cache[*iter])))
33                 (*iter)++;
34
35         return ret;
36 }
37
38 #define for_each_cache_rcu(ca, c, iter)                                 \
39         for ((iter) = 0; ((ca) = bch_next_cache_rcu((c), &(iter))); (iter)++)
40
41 static inline struct cache *bch_get_next_cache(struct cache_set *c,
42                                                unsigned *iter)
43 {
44         struct cache *ret;
45
46         rcu_read_lock();
47         if ((ret = bch_next_cache_rcu(c, iter)))
48                 percpu_ref_get(&ret->ref);
49         rcu_read_unlock();
50
51         return ret;
52 }
53
54 /*
55  * If you break early, you must drop your ref on the current cache
56  */
57 #define for_each_cache(ca, c, iter)                                     \
58         for ((iter) = 0;                                                \
59              (ca = bch_get_next_cache(c, &(iter)));                     \
60              percpu_ref_put(&ca->ref), (iter)++)
61
62 void bch_check_mark_super_slowpath(struct cache_set *,
63                                    const struct bkey_i *, bool);
64
65 static inline bool bch_check_super_marked(struct cache_set *c,
66                                           const struct bkey_i *k, bool meta)
67 {
68         struct bkey_s_c_extent e = bkey_i_to_s_c_extent(k);
69         const struct bch_extent_ptr *ptr;
70         struct cache_member_cpu *mi = cache_member_info_get(c)->m;
71         bool ret = true;
72
73         extent_for_each_ptr(e, ptr)
74                 if (!(meta
75                       ? mi[ptr->dev].has_metadata
76                       : mi[ptr->dev].has_data) &&
77                     bch_extent_ptr_is_dirty(c, e, ptr)) {
78                         ret = false;
79                         break;
80                 }
81
82         cache_member_info_put();
83
84         return ret;
85 }
86
87 static inline void bch_check_mark_super(struct cache_set *c,
88                                         const struct bkey_i *k, bool meta)
89 {
90         if (bch_check_super_marked(c, k, meta))
91                 return;
92
93         bch_check_mark_super_slowpath(c, k, meta);
94 }
95
96 static inline bool bch_cache_may_remove(struct cache *ca)
97 {
98         struct cache_set *c = ca->set;
99         struct cache_group *tier = &c->cache_tiers[ca->mi.tier];
100
101         /*
102          * Right now, we can't remove the last device from a tier,
103          * - For tier 0, because all metadata lives in tier 0 and because
104          *   there is no way to have foreground writes go directly to tier 1.
105          * - For tier 1, because the code doesn't completely support an
106          *   empty tier 1.
107          */
108
109         /*
110          * Turning a device read-only removes it from the cache group,
111          * so there may only be one read-write device in a tier, and yet
112          * the device we are removing is in the same tier, so we have
113          * to check for identity.
114          * Removing the last RW device from a tier requires turning the
115          * whole cache set RO.
116          */
117
118         return tier->nr_devices != 1 ||
119                 rcu_access_pointer(tier->d[0].dev) != ca;
120 }
121
122 void free_super(struct bcache_superblock *);
123 int bch_super_realloc(struct bcache_superblock *, unsigned);
124 void bcache_write_super(struct cache_set *);
125 void __write_super(struct cache_set *, struct bcache_superblock *);
126
127 void bch_cache_set_release(struct kobject *);
128 void bch_cache_release(struct kobject *);
129
130 void bch_cache_set_unregister(struct cache_set *);
131 void bch_cache_set_stop(struct cache_set *);
132
133 const char *bch_register_one(const char *path);
134 const char *bch_register_cache_set(char * const *, unsigned,
135                                    struct cache_set_opts,
136                                    struct cache_set **);
137
138 bool bch_cache_set_read_only(struct cache_set *);
139 bool bch_cache_set_emergency_read_only(struct cache_set *);
140 void bch_cache_set_read_only_sync(struct cache_set *);
141 const char *bch_cache_set_read_write(struct cache_set *);
142
143 bool bch_cache_read_only(struct cache *);
144 const char *bch_cache_read_write(struct cache *);
145 bool bch_cache_remove(struct cache *, bool force);
146 int bch_cache_set_add_cache(struct cache_set *, const char *);
147
148 extern struct mutex bch_register_lock;
149 extern struct list_head bch_cache_sets;
150 extern struct idr bch_cache_set_minor;
151 extern struct workqueue_struct *bcache_io_wq;
152 extern struct crypto_shash *bch_sha1;
153
154 extern struct kobj_type bch_cache_set_ktype;
155 extern struct kobj_type bch_cache_set_internal_ktype;
156 extern struct kobj_type bch_cache_set_time_stats_ktype;
157 extern struct kobj_type bch_cache_set_opts_dir_ktype;
158 extern struct kobj_type bch_cache_ktype;
159
160 #endif /* _BCACHE_SUPER_H */