Skip to content

Commit 35c1f13

Browse files
author
Kent Overstreet
committed
bcachefs: Redo bch2_dirent_init_name()
Redo (and simplify somewhat) how casefolded and non casefolded dirents are initialized, and export this to be used by fsck_rename_dirent(). Signed-off-by: Kent Overstreet <[email protected]>
1 parent 01d925f commit 35c1f13

File tree

2 files changed

+66
-70
lines changed

2 files changed

+66
-70
lines changed

fs/bcachefs/dirent.c

Lines changed: 60 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -231,67 +231,61 @@ void bch2_dirent_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c
231231
prt_printf(out, " type %s", bch2_d_type_str(d.v->d_type));
232232
}
233233

234-
static struct bkey_i_dirent *dirent_alloc_key(struct btree_trans *trans,
235-
subvol_inum dir,
236-
u8 type,
237-
int name_len, int cf_name_len,
238-
u64 dst)
234+
int bch2_dirent_init_name(struct bkey_i_dirent *dirent,
235+
const struct bch_hash_info *hash_info,
236+
const struct qstr *name,
237+
const struct qstr *cf_name)
239238
{
240-
struct bkey_i_dirent *dirent;
241-
unsigned u64s = BKEY_U64s + dirent_val_u64s(name_len, cf_name_len);
239+
EBUG_ON(hash_info->cf_encoding == NULL && cf_name);
240+
int cf_len = 0;
242241

243-
BUG_ON(u64s > U8_MAX);
244-
245-
dirent = bch2_trans_kmalloc(trans, u64s * sizeof(u64));
246-
if (IS_ERR(dirent))
247-
return dirent;
242+
if (name->len > BCH_NAME_MAX)
243+
return -ENAMETOOLONG;
248244

249-
bkey_dirent_init(&dirent->k_i);
250-
dirent->k.u64s = u64s;
245+
dirent->v.d_casefold = hash_info->cf_encoding != NULL;
251246

252-
if (type != DT_SUBVOL) {
253-
dirent->v.d_inum = cpu_to_le64(dst);
247+
if (!dirent->v.d_casefold) {
248+
memcpy(&dirent->v.d_name[0], name->name, name->len);
249+
memset(&dirent->v.d_name[name->len], 0,
250+
bkey_val_bytes(&dirent->k) -
251+
offsetof(struct bch_dirent, d_name) -
252+
name->len);
254253
} else {
255-
dirent->v.d_parent_subvol = cpu_to_le32(dir.subvol);
256-
dirent->v.d_child_subvol = cpu_to_le32(dst);
257-
}
254+
#ifdef CONFIG_UNICODE
255+
memcpy(&dirent->v.d_cf_name_block.d_names[0], name->name, name->len);
258256

259-
dirent->v.d_type = type;
260-
dirent->v.d_unused = 0;
261-
dirent->v.d_casefold = cf_name_len ? 1 : 0;
257+
char *cf_out = &dirent->v.d_cf_name_block.d_names[name->len];
262258

263-
return dirent;
264-
}
259+
if (cf_name) {
260+
cf_len = cf_name->len;
265261

266-
static void dirent_init_regular_name(struct bkey_i_dirent *dirent,
267-
const struct qstr *name)
268-
{
269-
EBUG_ON(dirent->v.d_casefold);
262+
memcpy(cf_out, cf_name->name, cf_name->len);
263+
} else {
264+
cf_len = utf8_casefold(hash_info->cf_encoding, name,
265+
cf_out,
266+
bkey_val_end(bkey_i_to_s(&dirent->k_i)) - (void *) cf_out);
267+
if (cf_len <= 0)
268+
return cf_len;
269+
}
270270

271-
memcpy(&dirent->v.d_name[0], name->name, name->len);
272-
memset(&dirent->v.d_name[name->len], 0,
273-
bkey_val_bytes(&dirent->k) -
274-
offsetof(struct bch_dirent, d_name) -
275-
name->len);
276-
}
271+
memset(&dirent->v.d_cf_name_block.d_names[name->len + cf_len], 0,
272+
bkey_val_bytes(&dirent->k) -
273+
offsetof(struct bch_dirent, d_cf_name_block.d_names) -
274+
name->len + cf_len);
277275

278-
static void dirent_init_casefolded_name(struct bkey_i_dirent *dirent,
279-
const struct qstr *name,
280-
const struct qstr *cf_name)
281-
{
282-
EBUG_ON(!dirent->v.d_casefold);
283-
EBUG_ON(!cf_name->len);
284-
285-
dirent->v.d_cf_name_block.d_name_len = cpu_to_le16(name->len);
286-
dirent->v.d_cf_name_block.d_cf_name_len = cpu_to_le16(cf_name->len);
287-
memcpy(&dirent->v.d_cf_name_block.d_names[0], name->name, name->len);
288-
memcpy(&dirent->v.d_cf_name_block.d_names[name->len], cf_name->name, cf_name->len);
289-
memset(&dirent->v.d_cf_name_block.d_names[name->len + cf_name->len], 0,
290-
bkey_val_bytes(&dirent->k) -
291-
offsetof(struct bch_dirent, d_cf_name_block.d_names) -
292-
name->len + cf_name->len);
293-
294-
EBUG_ON(bch2_dirent_get_casefold_name(dirent_i_to_s_c(dirent)).len != cf_name->len);
276+
dirent->v.d_cf_name_block.d_name_len = cpu_to_le16(name->len);
277+
dirent->v.d_cf_name_block.d_cf_name_len = cpu_to_le16(cf_len);
278+
279+
EBUG_ON(bch2_dirent_get_casefold_name(dirent_i_to_s_c(dirent)).len != cf_len);
280+
#else
281+
return -EOPNOTSUPP;
282+
#endif
283+
}
284+
285+
unsigned u64s = dirent_val_u64s(name->len, cf_len);
286+
BUG_ON(u64s > bkey_val_u64s(&dirent->k));
287+
set_bkey_val_u64s(&dirent->k, u64s);
288+
return 0;
295289
}
296290

297291
static struct bkey_i_dirent *dirent_create_key(struct btree_trans *trans,
@@ -302,31 +296,28 @@ static struct bkey_i_dirent *dirent_create_key(struct btree_trans *trans,
302296
const struct qstr *cf_name,
303297
u64 dst)
304298
{
305-
struct bkey_i_dirent *dirent;
306-
struct qstr _cf_name;
307-
308-
if (name->len > BCH_NAME_MAX)
309-
return ERR_PTR(-ENAMETOOLONG);
299+
struct bkey_i_dirent *dirent = bch2_trans_kmalloc(trans, BKEY_U64s_MAX * sizeof(u64));
300+
if (IS_ERR(dirent))
301+
return dirent;
310302

311-
if (hash_info->cf_encoding && !cf_name) {
312-
int ret = bch2_casefold(trans, hash_info, name, &_cf_name);
313-
if (ret)
314-
return ERR_PTR(ret);
303+
bkey_dirent_init(&dirent->k_i);
304+
dirent->k.u64s = BKEY_U64s_MAX;
315305

316-
cf_name = &_cf_name;
306+
if (type != DT_SUBVOL) {
307+
dirent->v.d_inum = cpu_to_le64(dst);
308+
} else {
309+
dirent->v.d_parent_subvol = cpu_to_le32(dir.subvol);
310+
dirent->v.d_child_subvol = cpu_to_le32(dst);
317311
}
318312

319-
dirent = dirent_alloc_key(trans, dir, type, name->len, cf_name ? cf_name->len : 0, dst);
320-
if (IS_ERR(dirent))
321-
return dirent;
313+
dirent->v.d_type = type;
314+
dirent->v.d_unused = 0;
322315

323-
if (cf_name)
324-
dirent_init_casefolded_name(dirent, name, cf_name);
325-
else
326-
dirent_init_regular_name(dirent, name);
316+
int ret = bch2_dirent_init_name(dirent, hash_info, name, cf_name);
317+
if (ret)
318+
return ERR_PTR(ret);
327319

328320
EBUG_ON(bch2_dirent_get_name(dirent_i_to_s_c(dirent)).len != name->len);
329-
330321
return dirent;
331322
}
332323

fs/bcachefs/dirent.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ static inline int bch2_maybe_casefold(struct btree_trans *trans,
3838
}
3939
}
4040

41-
struct qstr bch2_dirent_get_name(struct bkey_s_c_dirent d);
41+
struct qstr bch2_dirent_get_name(struct bkey_s_c_dirent);
4242

4343
static inline unsigned dirent_val_u64s(unsigned len, unsigned cf_len)
4444
{
@@ -59,6 +59,11 @@ static inline void dirent_copy_target(struct bkey_i_dirent *dst,
5959
dst->v.d_type = src.v->d_type;
6060
}
6161

62+
int bch2_dirent_init_name(struct bkey_i_dirent *,
63+
const struct bch_hash_info *,
64+
const struct qstr *,
65+
const struct qstr *);
66+
6267
int bch2_dirent_create_snapshot(struct btree_trans *, u32, u64, u32,
6368
const struct bch_hash_info *, u8,
6469
const struct qstr *, u64, u64 *,

0 commit comments

Comments
 (0)