~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/bcachefs/lru.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 
  3 #include "bcachefs.h"
  4 #include "alloc_background.h"
  5 #include "btree_iter.h"
  6 #include "btree_update.h"
  7 #include "btree_write_buffer.h"
  8 #include "error.h"
  9 #include "lru.h"
 10 #include "recovery.h"
 11 
 12 /* KEY_TYPE_lru is obsolete: */
 13 int bch2_lru_validate(struct bch_fs *c, struct bkey_s_c k,
 14                      enum bch_validate_flags flags)
 15 {
 16         int ret = 0;
 17 
 18         bkey_fsck_err_on(!lru_pos_time(k.k->p),
 19                          c, lru_entry_at_time_0,
 20                          "lru entry at time=0");
 21 fsck_err:
 22         return ret;
 23 }
 24 
 25 void bch2_lru_to_text(struct printbuf *out, struct bch_fs *c,
 26                       struct bkey_s_c k)
 27 {
 28         const struct bch_lru *lru = bkey_s_c_to_lru(k).v;
 29 
 30         prt_printf(out, "idx %llu", le64_to_cpu(lru->idx));
 31 }
 32 
 33 void bch2_lru_pos_to_text(struct printbuf *out, struct bpos lru)
 34 {
 35         prt_printf(out, "%llu:%llu -> %llu:%llu",
 36                    lru_pos_id(lru),
 37                    lru_pos_time(lru),
 38                    u64_to_bucket(lru.offset).inode,
 39                    u64_to_bucket(lru.offset).offset);
 40 }
 41 
 42 static int __bch2_lru_set(struct btree_trans *trans, u16 lru_id,
 43                           u64 dev_bucket, u64 time, bool set)
 44 {
 45         return time
 46                 ? bch2_btree_bit_mod_buffered(trans, BTREE_ID_lru,
 47                                               lru_pos(lru_id, dev_bucket, time), set)
 48                 : 0;
 49 }
 50 
 51 int bch2_lru_del(struct btree_trans *trans, u16 lru_id, u64 dev_bucket, u64 time)
 52 {
 53         return __bch2_lru_set(trans, lru_id, dev_bucket, time, KEY_TYPE_deleted);
 54 }
 55 
 56 int bch2_lru_set(struct btree_trans *trans, u16 lru_id, u64 dev_bucket, u64 time)
 57 {
 58         return __bch2_lru_set(trans, lru_id, dev_bucket, time, KEY_TYPE_set);
 59 }
 60 
 61 int bch2_lru_change(struct btree_trans *trans,
 62                     u16 lru_id, u64 dev_bucket,
 63                     u64 old_time, u64 new_time)
 64 {
 65         if (old_time == new_time)
 66                 return 0;
 67 
 68         return  bch2_lru_del(trans, lru_id, dev_bucket, old_time) ?:
 69                 bch2_lru_set(trans, lru_id, dev_bucket, new_time);
 70 }
 71 
 72 static const char * const bch2_lru_types[] = {
 73 #define x(n) #n,
 74         BCH_LRU_TYPES()
 75 #undef x
 76         NULL
 77 };
 78 
 79 int bch2_lru_check_set(struct btree_trans *trans,
 80                        u16 lru_id, u64 time,
 81                        struct bkey_s_c referring_k,
 82                        struct bkey_buf *last_flushed)
 83 {
 84         struct bch_fs *c = trans->c;
 85         struct printbuf buf = PRINTBUF;
 86         struct btree_iter lru_iter;
 87         struct bkey_s_c lru_k =
 88                 bch2_bkey_get_iter(trans, &lru_iter, BTREE_ID_lru,
 89                                    lru_pos(lru_id,
 90                                            bucket_to_u64(referring_k.k->p),
 91                                            time), 0);
 92         int ret = bkey_err(lru_k);
 93         if (ret)
 94                 return ret;
 95 
 96         if (lru_k.k->type != KEY_TYPE_set) {
 97                 ret = bch2_btree_write_buffer_maybe_flush(trans, referring_k, last_flushed);
 98                 if (ret)
 99                         goto err;
100 
101                 if (fsck_err(trans, alloc_key_to_missing_lru_entry,
102                              "missing %s lru entry\n"
103                              "  %s",
104                              bch2_lru_types[lru_type(lru_k)],
105                              (bch2_bkey_val_to_text(&buf, c, referring_k), buf.buf))) {
106                         ret = bch2_lru_set(trans, lru_id, bucket_to_u64(referring_k.k->p), time);
107                         if (ret)
108                                 goto err;
109                 }
110         }
111 err:
112 fsck_err:
113         bch2_trans_iter_exit(trans, &lru_iter);
114         printbuf_exit(&buf);
115         return ret;
116 }
117 
118 static int bch2_check_lru_key(struct btree_trans *trans,
119                               struct btree_iter *lru_iter,
120                               struct bkey_s_c lru_k,
121                               struct bpos *last_flushed_pos)
122 {
123         struct bch_fs *c = trans->c;
124         struct btree_iter iter;
125         struct bkey_s_c k;
126         struct bch_alloc_v4 a_convert;
127         const struct bch_alloc_v4 *a;
128         struct printbuf buf1 = PRINTBUF;
129         struct printbuf buf2 = PRINTBUF;
130         enum bch_lru_type type = lru_type(lru_k);
131         struct bpos alloc_pos = u64_to_bucket(lru_k.k->p.offset);
132         u64 idx;
133         int ret;
134 
135         if (fsck_err_on(!bch2_dev_bucket_exists(c, alloc_pos),
136                         trans, lru_entry_to_invalid_bucket,
137                         "lru key points to nonexistent device:bucket %llu:%llu",
138                         alloc_pos.inode, alloc_pos.offset))
139                 return bch2_btree_delete_at(trans, lru_iter, 0);
140 
141         k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_alloc, alloc_pos, 0);
142         ret = bkey_err(k);
143         if (ret)
144                 goto err;
145 
146         a = bch2_alloc_to_v4(k, &a_convert);
147 
148         switch (type) {
149         case BCH_LRU_read:
150                 idx = alloc_lru_idx_read(*a);
151                 break;
152         case BCH_LRU_fragmentation:
153                 idx = a->fragmentation_lru;
154                 break;
155         }
156 
157         if (lru_k.k->type != KEY_TYPE_set ||
158             lru_pos_time(lru_k.k->p) != idx) {
159                 if (!bpos_eq(*last_flushed_pos, lru_k.k->p)) {
160                         *last_flushed_pos = lru_k.k->p;
161                         ret = bch2_btree_write_buffer_flush_sync(trans) ?:
162                                 -BCH_ERR_transaction_restart_write_buffer_flush;
163                         goto out;
164                 }
165 
166                 if (fsck_err(trans, lru_entry_bad,
167                              "incorrect lru entry: lru %s time %llu\n"
168                              "  %s\n"
169                              "  for %s",
170                              bch2_lru_types[type],
171                              lru_pos_time(lru_k.k->p),
172                              (bch2_bkey_val_to_text(&buf1, c, lru_k), buf1.buf),
173                              (bch2_bkey_val_to_text(&buf2, c, k), buf2.buf)))
174                         ret = bch2_btree_delete_at(trans, lru_iter, 0);
175         }
176 out:
177 err:
178 fsck_err:
179         bch2_trans_iter_exit(trans, &iter);
180         printbuf_exit(&buf2);
181         printbuf_exit(&buf1);
182         return ret;
183 }
184 
185 int bch2_check_lrus(struct bch_fs *c)
186 {
187         struct bpos last_flushed_pos = POS_MIN;
188         int ret = bch2_trans_run(c,
189                 for_each_btree_key_commit(trans, iter,
190                                 BTREE_ID_lru, POS_MIN, BTREE_ITER_prefetch, k,
191                                 NULL, NULL, BCH_TRANS_COMMIT_no_enospc|BCH_TRANS_COMMIT_lazy_rw,
192                         bch2_check_lru_key(trans, &iter, k, &last_flushed_pos)));
193         bch_err_fn(c, ret);
194         return ret;
195 
196 }
197 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php