@@ -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
297291static 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
0 commit comments