]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/dirent.c
Update bcachefs sources to 940d6ca657 bcachefs: acl code improvements
[bcachefs-tools-debian] / libbcachefs / dirent.c
1
2 #include "bcachefs.h"
3 #include "bkey_methods.h"
4 #include "btree_update.h"
5 #include "extents.h"
6 #include "dirent.h"
7 #include "fs.h"
8 #include "keylist.h"
9 #include "str_hash.h"
10
11 #include <linux/dcache.h>
12
13 unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent d)
14 {
15         unsigned len = bkey_val_bytes(d.k) -
16                 offsetof(struct bch_dirent, d_name);
17
18         while (len && !d.v->d_name[len - 1])
19                 --len;
20
21         return len;
22 }
23
24 static unsigned dirent_val_u64s(unsigned len)
25 {
26         return DIV_ROUND_UP(offsetof(struct bch_dirent, d_name) + len,
27                             sizeof(u64));
28 }
29
30 static u64 bch2_dirent_hash(const struct bch_hash_info *info,
31                             const struct qstr *name)
32 {
33         struct bch_str_hash_ctx ctx;
34
35         bch2_str_hash_init(&ctx, info);
36         bch2_str_hash_update(&ctx, info, name->name, name->len);
37
38         /* [0,2) reserved for dots */
39         return max_t(u64, bch2_str_hash_end(&ctx, info), 2);
40 }
41
42 static u64 dirent_hash_key(const struct bch_hash_info *info, const void *key)
43 {
44         return bch2_dirent_hash(info, key);
45 }
46
47 static u64 dirent_hash_bkey(const struct bch_hash_info *info, struct bkey_s_c k)
48 {
49         struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
50         struct qstr name = QSTR_INIT(d.v->d_name, bch2_dirent_name_bytes(d));
51
52         return bch2_dirent_hash(info, &name);
53 }
54
55 static bool dirent_cmp_key(struct bkey_s_c _l, const void *_r)
56 {
57         struct bkey_s_c_dirent l = bkey_s_c_to_dirent(_l);
58         int len = bch2_dirent_name_bytes(l);
59         const struct qstr *r = _r;
60
61         return len - r->len ?: memcmp(l.v->d_name, r->name, len);
62 }
63
64 static bool dirent_cmp_bkey(struct bkey_s_c _l, struct bkey_s_c _r)
65 {
66         struct bkey_s_c_dirent l = bkey_s_c_to_dirent(_l);
67         struct bkey_s_c_dirent r = bkey_s_c_to_dirent(_r);
68         int l_len = bch2_dirent_name_bytes(l);
69         int r_len = bch2_dirent_name_bytes(r);
70
71         return l_len - r_len ?: memcmp(l.v->d_name, r.v->d_name, l_len);
72 }
73
74 const struct bch_hash_desc bch2_dirent_hash_desc = {
75         .btree_id       = BTREE_ID_DIRENTS,
76         .key_type       = BCH_DIRENT,
77         .whiteout_type  = BCH_DIRENT_WHITEOUT,
78         .hash_key       = dirent_hash_key,
79         .hash_bkey      = dirent_hash_bkey,
80         .cmp_key        = dirent_cmp_key,
81         .cmp_bkey       = dirent_cmp_bkey,
82 };
83
84 const char *bch2_dirent_invalid(const struct bch_fs *c, struct bkey_s_c k)
85 {
86         struct bkey_s_c_dirent d;
87         unsigned len;
88
89         switch (k.k->type) {
90         case BCH_DIRENT:
91                 if (bkey_val_bytes(k.k) < sizeof(struct bch_dirent))
92                         return "value too small";
93
94                 d = bkey_s_c_to_dirent(k);
95                 len = bch2_dirent_name_bytes(d);
96
97                 if (!len)
98                         return "empty name";
99
100                 /*
101                  * older versions of bcachefs were buggy and creating dirent
102                  * keys that were bigger than necessary:
103                  */
104                 if (bkey_val_u64s(k.k) > dirent_val_u64s(len + 7))
105                         return "value too big";
106
107                 if (len > BCH_NAME_MAX)
108                         return "dirent name too big";
109
110                 if (memchr(d.v->d_name, '/', len))
111                         return "dirent name has invalid characters";
112
113                 return NULL;
114         case BCH_DIRENT_WHITEOUT:
115                 return bkey_val_bytes(k.k) != 0
116                         ? "value size should be zero"
117                         : NULL;
118
119         default:
120                 return "invalid type";
121         }
122 }
123
124 void bch2_dirent_to_text(struct bch_fs *c, char *buf,
125                          size_t size, struct bkey_s_c k)
126 {
127         struct bkey_s_c_dirent d;
128         size_t n = 0;
129
130         switch (k.k->type) {
131         case BCH_DIRENT:
132                 d = bkey_s_c_to_dirent(k);
133
134                 n += bch_scnmemcpy(buf + n, size - n, d.v->d_name,
135                                    bch2_dirent_name_bytes(d));
136                 n += scnprintf(buf + n, size - n, " -> %llu", d.v->d_inum);
137                 break;
138         case BCH_DIRENT_WHITEOUT:
139                 scnprintf(buf, size, "whiteout");
140                 break;
141         }
142 }
143
144 static struct bkey_i_dirent *dirent_create_key(u8 type,
145                                 const struct qstr *name, u64 dst)
146 {
147         struct bkey_i_dirent *dirent;
148         unsigned u64s = BKEY_U64s + dirent_val_u64s(name->len);
149
150         if (name->len > BCH_NAME_MAX)
151                 return ERR_PTR(-ENAMETOOLONG);
152
153         BUG_ON(u64s > U8_MAX);
154
155         dirent = kmalloc(u64s * sizeof(u64), GFP_NOFS);
156         if (!dirent)
157                 return ERR_PTR(-ENOMEM);
158
159         bkey_dirent_init(&dirent->k_i);
160         dirent->k.u64s = u64s;
161         dirent->v.d_inum = cpu_to_le64(dst);
162         dirent->v.d_type = type;
163
164         memcpy(dirent->v.d_name, name->name, name->len);
165         memset(dirent->v.d_name + name->len, 0,
166                bkey_val_bytes(&dirent->k) -
167                offsetof(struct bch_dirent, d_name) -
168                name->len);
169
170         EBUG_ON(bch2_dirent_name_bytes(dirent_i_to_s_c(dirent)) != name->len);
171
172         return dirent;
173 }
174
175 int bch2_dirent_create(struct bch_fs *c, u64 dir_inum,
176                        const struct bch_hash_info *hash_info,
177                        u8 type, const struct qstr *name, u64 dst_inum,
178                        u64 *journal_seq, int flags)
179 {
180         struct bkey_i_dirent *dirent;
181         int ret;
182
183         dirent = dirent_create_key(type, name, dst_inum);
184         if (IS_ERR(dirent))
185                 return PTR_ERR(dirent);
186
187         ret = bch2_hash_set(bch2_dirent_hash_desc, hash_info, c, dir_inum,
188                            journal_seq, &dirent->k_i, flags);
189         kfree(dirent);
190
191         return ret;
192 }
193
194 static void dirent_copy_target(struct bkey_i_dirent *dst,
195                                struct bkey_s_c_dirent src)
196 {
197         dst->v.d_inum = src.v->d_inum;
198         dst->v.d_type = src.v->d_type;
199 }
200
201 static struct bpos bch2_dirent_pos(struct bch_inode_info *inode,
202                                    const struct qstr *name)
203 {
204         return POS(inode->v.i_ino, bch2_dirent_hash(&inode->ei_str_hash, name));
205 }
206
207 int bch2_dirent_rename(struct bch_fs *c,
208                 struct bch_inode_info *src_dir, const struct qstr *src_name,
209                 struct bch_inode_info *dst_dir, const struct qstr *dst_name,
210                 u64 *journal_seq, enum bch_rename_mode mode)
211 {
212         struct btree_iter src_iter, dst_iter, whiteout_iter;
213         struct bkey_s_c old_src, old_dst;
214         struct bkey delete;
215         struct bkey_i_dirent *new_src = NULL, *new_dst = NULL;
216         struct bpos src_pos = bch2_dirent_pos(src_dir, src_name);
217         struct bpos dst_pos = bch2_dirent_pos(dst_dir, dst_name);
218         bool need_whiteout;
219         int ret;
220
221         bch2_btree_iter_init(&src_iter, c, BTREE_ID_DIRENTS, src_pos,
222                              BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
223         bch2_btree_iter_init(&dst_iter, c, BTREE_ID_DIRENTS, dst_pos,
224                              BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
225         bch2_btree_iter_link(&src_iter, &dst_iter);
226
227         bch2_btree_iter_init(&whiteout_iter, c, BTREE_ID_DIRENTS, src_pos,
228                              BTREE_ITER_SLOTS);
229         bch2_btree_iter_link(&src_iter, &whiteout_iter);
230
231         if (mode == BCH_RENAME_EXCHANGE) {
232                 new_src = dirent_create_key(0, src_name, 0);
233                 if (IS_ERR(new_src)) {
234                         ret = PTR_ERR(new_src);
235                         goto err;
236                 }
237         } else {
238                 new_src = (void *) &delete;
239         }
240
241         new_dst = dirent_create_key(0, dst_name, 0);
242         if (IS_ERR(new_dst)) {
243                 ret = PTR_ERR(new_dst);
244                 goto err;
245         }
246 retry:
247         /*
248          * Note that on -EINTR/dropped locks we're not restarting the lookup
249          * from the original hashed position (like we do when creating dirents,
250          * in bch_hash_set) -  we never move existing dirents to different slot:
251          */
252         old_src = bch2_hash_lookup_at(bch2_dirent_hash_desc,
253                                      &src_dir->ei_str_hash,
254                                      &src_iter, src_name);
255         if ((ret = btree_iter_err(old_src)))
256                 goto err;
257
258         ret = bch2_hash_needs_whiteout(bch2_dirent_hash_desc,
259                                 &src_dir->ei_str_hash,
260                                 &whiteout_iter, &src_iter);
261         if (ret < 0)
262                 goto err;
263         need_whiteout = ret;
264
265         /*
266          * Note that in BCH_RENAME mode, we're _not_ checking if
267          * the target already exists - we're relying on the VFS
268          * to do that check for us for correctness:
269          */
270         old_dst = mode == BCH_RENAME
271                 ? bch2_hash_hole_at(bch2_dirent_hash_desc, &dst_iter)
272                 : bch2_hash_lookup_at(bch2_dirent_hash_desc,
273                                      &dst_dir->ei_str_hash,
274                                      &dst_iter, dst_name);
275         if ((ret = btree_iter_err(old_dst)))
276                 goto err;
277
278         switch (mode) {
279         case BCH_RENAME:
280                 bkey_init(&new_src->k);
281                 dirent_copy_target(new_dst, bkey_s_c_to_dirent(old_src));
282
283                 if (bkey_cmp(dst_pos, src_iter.pos) <= 0 &&
284                     bkey_cmp(src_iter.pos, dst_iter.pos) < 0) {
285                         /*
286                          * If we couldn't insert new_dst at its hashed
287                          * position (dst_pos) due to a hash collision,
288                          * and we're going to be deleting in
289                          * between the hashed position and first empty
290                          * slot we found - just overwrite the pos we
291                          * were going to delete:
292                          *
293                          * Note: this is a correctness issue, in this
294                          * situation bch2_hash_needs_whiteout() could
295                          * return false when the whiteout would have
296                          * been needed if we inserted at the pos
297                          * __dirent_find_hole() found
298                          */
299                         new_dst->k.p = src_iter.pos;
300                         ret = bch2_btree_insert_at(c, NULL, NULL,
301                                         journal_seq,
302                                         BTREE_INSERT_ATOMIC,
303                                         BTREE_INSERT_ENTRY(&src_iter,
304                                                            &new_dst->k_i));
305                         goto err;
306                 }
307
308                 if (need_whiteout)
309                         new_src->k.type = BCH_DIRENT_WHITEOUT;
310                 break;
311         case BCH_RENAME_OVERWRITE:
312                 bkey_init(&new_src->k);
313                 dirent_copy_target(new_dst, bkey_s_c_to_dirent(old_src));
314
315                 if (bkey_cmp(dst_pos, src_iter.pos) <= 0 &&
316                     bkey_cmp(src_iter.pos, dst_iter.pos) < 0) {
317                         /*
318                          * Same case described above -
319                          * bch_hash_needs_whiteout could spuriously
320                          * return false, but we have to insert at
321                          * dst_iter.pos because we're overwriting
322                          * another dirent:
323                          */
324                         new_src->k.type = BCH_DIRENT_WHITEOUT;
325                 } else if (need_whiteout)
326                         new_src->k.type = BCH_DIRENT_WHITEOUT;
327                 break;
328         case BCH_RENAME_EXCHANGE:
329                 dirent_copy_target(new_src, bkey_s_c_to_dirent(old_dst));
330                 dirent_copy_target(new_dst, bkey_s_c_to_dirent(old_src));
331                 break;
332         }
333
334         new_src->k.p = src_iter.pos;
335         new_dst->k.p = dst_iter.pos;
336         ret = bch2_btree_insert_at(c, NULL, NULL, journal_seq,
337                         BTREE_INSERT_ATOMIC,
338                         BTREE_INSERT_ENTRY(&src_iter, &new_src->k_i),
339                         BTREE_INSERT_ENTRY(&dst_iter, &new_dst->k_i));
340 err:
341         if (ret == -EINTR)
342                 goto retry;
343
344         bch2_btree_iter_unlock(&whiteout_iter);
345         bch2_btree_iter_unlock(&dst_iter);
346         bch2_btree_iter_unlock(&src_iter);
347
348         if (new_src != (void *) &delete)
349                 kfree(new_src);
350         kfree(new_dst);
351         return ret;
352 }
353
354 int bch2_dirent_delete(struct bch_fs *c, u64 dir_inum,
355                        const struct bch_hash_info *hash_info,
356                        const struct qstr *name,
357                        u64 *journal_seq)
358 {
359         return bch2_hash_delete(bch2_dirent_hash_desc, hash_info,
360                                c, dir_inum, journal_seq, name);
361 }
362
363 u64 bch2_dirent_lookup(struct bch_fs *c, u64 dir_inum,
364                        const struct bch_hash_info *hash_info,
365                        const struct qstr *name)
366 {
367         struct btree_iter iter;
368         struct bkey_s_c k;
369         u64 inum;
370
371         k = bch2_hash_lookup(bch2_dirent_hash_desc, hash_info, c,
372                             dir_inum, &iter, name);
373         if (IS_ERR(k.k)) {
374                 bch2_btree_iter_unlock(&iter);
375                 return 0;
376         }
377
378         inum = le64_to_cpu(bkey_s_c_to_dirent(k).v->d_inum);
379         bch2_btree_iter_unlock(&iter);
380
381         return inum;
382 }
383
384 int bch2_empty_dir(struct bch_fs *c, u64 dir_inum)
385 {
386         struct btree_iter iter;
387         struct bkey_s_c k;
388         int ret = 0;
389
390         for_each_btree_key(&iter, c, BTREE_ID_DIRENTS, POS(dir_inum, 0), 0, k) {
391                 if (k.k->p.inode > dir_inum)
392                         break;
393
394                 if (k.k->type == BCH_DIRENT) {
395                         ret = -ENOTEMPTY;
396                         break;
397                 }
398         }
399         bch2_btree_iter_unlock(&iter);
400
401         return ret;
402 }
403
404 int bch2_readdir(struct bch_fs *c, struct file *file,
405                  struct dir_context *ctx)
406 {
407         struct bch_inode_info *inode = file_bch_inode(file);
408         struct btree_iter iter;
409         struct bkey_s_c k;
410         struct bkey_s_c_dirent dirent;
411         unsigned len;
412
413         if (!dir_emit_dots(file, ctx))
414                 return 0;
415
416         for_each_btree_key(&iter, c, BTREE_ID_DIRENTS,
417                            POS(inode->v.i_ino, ctx->pos), 0, k) {
418                 if (k.k->type != BCH_DIRENT)
419                         continue;
420
421                 dirent = bkey_s_c_to_dirent(k);
422
423                 if (bkey_cmp(k.k->p, POS(inode->v.i_ino, ctx->pos)) < 0)
424                         continue;
425
426                 if (k.k->p.inode > inode->v.i_ino)
427                         break;
428
429                 len = bch2_dirent_name_bytes(dirent);
430
431                 /*
432                  * XXX: dir_emit() can fault and block, while we're holding
433                  * locks
434                  */
435                 if (!dir_emit(ctx, dirent.v->d_name, len,
436                               le64_to_cpu(dirent.v->d_inum),
437                               dirent.v->d_type))
438                         break;
439
440                 ctx->pos = k.k->p.offset + 1;
441         }
442         bch2_btree_iter_unlock(&iter);
443
444         return 0;
445 }