bcachefs: Introduce bch2_dirent_get_name

A nice cleanup that avoids a bunch of open-coding name/string usage
around dirent usage.

Will be used by casefolding impl in future commits.

Signed-off-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c
index 065ea59..a87c4e5 100644
--- a/fs/bcachefs/dirent.c
+++ b/fs/bcachefs/dirent.c
@@ -13,7 +13,7 @@
 
 #include <linux/dcache.h>
 
-unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent d)
+static unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent d)
 {
 	unsigned len = bkey_val_bytes(d.k) -
 		offsetof(struct bch_dirent, d_name);
@@ -21,6 +21,11 @@ unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent d)
 	return strnlen(d.v->d_name, len);
 }
 
+struct qstr bch2_dirent_get_name(struct bkey_s_c_dirent d)
+{
+	return (struct qstr) QSTR_INIT(d.v->d_name, bch2_dirent_name_bytes(d));
+}
+
 static u64 bch2_dirent_hash(const struct bch_hash_info *info,
 			    const struct qstr *name)
 {
@@ -41,7 +46,7 @@ static u64 dirent_hash_key(const struct bch_hash_info *info, const void *key)
 static u64 dirent_hash_bkey(const struct bch_hash_info *info, struct bkey_s_c k)
 {
 	struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
-	struct qstr name = QSTR_INIT(d.v->d_name, bch2_dirent_name_bytes(d));
+	struct qstr name = bch2_dirent_get_name(d);
 
 	return bch2_dirent_hash(info, &name);
 }
@@ -49,20 +54,20 @@ static u64 dirent_hash_bkey(const struct bch_hash_info *info, struct bkey_s_c k)
 static bool dirent_cmp_key(struct bkey_s_c _l, const void *_r)
 {
 	struct bkey_s_c_dirent l = bkey_s_c_to_dirent(_l);
-	int len = bch2_dirent_name_bytes(l);
-	const struct qstr *r = _r;
+	const struct qstr l_name = bch2_dirent_get_name(l);
+	const struct qstr *r_name = _r;
 
-	return len - r->len ?: memcmp(l.v->d_name, r->name, len);
+	return l_name.len - r_name->len ?: memcmp(l_name.name, r_name->name, l_name.len);
 }
 
 static bool dirent_cmp_bkey(struct bkey_s_c _l, struct bkey_s_c _r)
 {
 	struct bkey_s_c_dirent l = bkey_s_c_to_dirent(_l);
 	struct bkey_s_c_dirent r = bkey_s_c_to_dirent(_r);
-	int l_len = bch2_dirent_name_bytes(l);
-	int r_len = bch2_dirent_name_bytes(r);
+	const struct qstr l_name = bch2_dirent_get_name(l);
+	const struct qstr r_name = bch2_dirent_get_name(r);
 
-	return l_len - r_len ?: memcmp(l.v->d_name, r.v->d_name, l_len);
+	return l_name.len - r_name.len ?: memcmp(l_name.name, r_name.name, l_name.len);
 }
 
 static bool dirent_is_visible(subvol_inum inum, struct bkey_s_c k)
@@ -89,37 +94,36 @@ int bch2_dirent_invalid(const struct bch_fs *c, struct bkey_s_c k,
 			struct printbuf *err)
 {
 	struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
-	unsigned len;
+	struct qstr d_name = bch2_dirent_get_name(d);
 
-	len = bch2_dirent_name_bytes(d);
-	if (!len) {
+	if (!d_name.len) {
 		prt_printf(err, "empty name");
 		return -BCH_ERR_invalid_bkey;
 	}
 
-	if (bkey_val_u64s(k.k) > dirent_val_u64s(len)) {
+	if (bkey_val_u64s(k.k) > dirent_val_u64s(d_name.len)) {
 		prt_printf(err, "value too big (%zu > %u)",
-		       bkey_val_u64s(k.k), dirent_val_u64s(len));
+		       bkey_val_u64s(k.k), dirent_val_u64s(d_name.len));
 		return -BCH_ERR_invalid_bkey;
 	}
 
-	if (len > BCH_NAME_MAX) {
+	if (d_name.len > BCH_NAME_MAX) {
 		prt_printf(err, "dirent name too big (%u > %u)",
-		       len, BCH_NAME_MAX);
+		       d_name.len, BCH_NAME_MAX);
 		return -BCH_ERR_invalid_bkey;
 	}
 
-	if (len == 1 && !memcmp(d.v->d_name, ".", 1)) {
+	if (d_name.len == 1 && !memcmp(d_name.name, ".", 1)) {
 		prt_printf(err, "invalid name");
 		return -BCH_ERR_invalid_bkey;
 	}
 
-	if (len == 2 && !memcmp(d.v->d_name, "..", 2)) {
+	if (d_name.len == 2 && !memcmp(d_name.name, "..", 2)) {
 		prt_printf(err, "invalid name");
 		return -BCH_ERR_invalid_bkey;
 	}
 
-	if (memchr(d.v->d_name, '/', len)) {
+	if (memchr(d_name.name, '/', d_name.len)) {
 		prt_printf(err, "invalid name");
 		return -BCH_ERR_invalid_bkey;
 	}
@@ -137,10 +141,11 @@ void bch2_dirent_to_text(struct printbuf *out, struct bch_fs *c,
 			 struct bkey_s_c k)
 {
 	struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
+	struct qstr d_name = bch2_dirent_get_name(d);
 
 	prt_printf(out, "%.*s -> %llu type %s",
-	       bch2_dirent_name_bytes(d),
-	       d.v->d_name,
+	       d_name.len,
+	       d_name.name,
 	       d.v->d_type != DT_SUBVOL
 	       ? le64_to_cpu(d.v->d_inum)
 	       : le32_to_cpu(d.v->d_child_subvol),
@@ -507,6 +512,7 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
 	subvol_inum target;
 	u32 snapshot;
 	struct bkey_buf sk;
+	struct qstr name;
 	int ret;
 
 	bch2_bkey_buf_init(&sk);
@@ -537,9 +543,11 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
 		dirent = bkey_i_to_s_c_dirent(sk.k);
 		bch2_trans_unlock(&trans);
 
+		name = bch2_dirent_get_name(dirent);
+
 		ctx->pos = dirent.k->p.offset;
-		if (!dir_emit(ctx, dirent.v->d_name,
-			      bch2_dirent_name_bytes(dirent),
+		if (!dir_emit(ctx, name.name,
+			      name.len,
 			      target.inum,
 			      vfs_d_type(dirent.v->d_type)))
 			break;
diff --git a/fs/bcachefs/dirent.h b/fs/bcachefs/dirent.h
index b42f4a1..e9fa1df 100644
--- a/fs/bcachefs/dirent.h
+++ b/fs/bcachefs/dirent.h
@@ -24,7 +24,7 @@ struct bch_fs;
 struct bch_hash_info;
 struct bch_inode_info;
 
-unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent);
+struct qstr bch2_dirent_get_name(struct bkey_s_c_dirent d);
 
 static inline unsigned dirent_val_u64s(unsigned len)
 {
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 113518e..0e1b317 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -1237,7 +1237,8 @@ static int bch2_get_name(struct dentry *parent, char *name, struct dentry *child
 	struct bch_inode_unpacked inode_u;
 	subvol_inum target;
 	u32 snapshot;
-	unsigned name_len;
+	struct qstr dirent_name;
+	unsigned name_len = 0;
 	int ret;
 
 	if (!S_ISDIR(dir->v.i_mode))
@@ -1314,9 +1315,10 @@ static int bch2_get_name(struct dentry *parent, char *name, struct dentry *child
 	ret = -ENOENT;
 	goto err;
 found:
-	name_len = min_t(unsigned, bch2_dirent_name_bytes(d), NAME_MAX);
+	dirent_name = bch2_dirent_get_name(d);
 
-	memcpy(name, d.v->d_name, name_len);
+	name_len = min_t(unsigned, dirent_name.len, NAME_MAX);
+	memcpy(name, dirent_name.name, name_len);
 	name[name_len] = '\0';
 err:
 	if (bch2_err_matches(ret, BCH_ERR_transaction_restart))