@@ -2372,7 +2372,8 @@ void dentry_update_name_case(struct dentry *dentry, struct qstr *name)
2372
2372
}
2373
2373
EXPORT_SYMBOL (dentry_update_name_case );
2374
2374
2375
- static void switch_names (struct dentry * dentry , struct dentry * target )
2375
+ static void switch_names (struct dentry * dentry , struct dentry * target ,
2376
+ bool exchange )
2376
2377
{
2377
2378
if (dname_external (target )) {
2378
2379
if (dname_external (dentry )) {
@@ -2406,13 +2407,19 @@ static void switch_names(struct dentry *dentry, struct dentry *target)
2406
2407
*/
2407
2408
unsigned int i ;
2408
2409
BUILD_BUG_ON (!IS_ALIGNED (DNAME_INLINE_LEN , sizeof (long )));
2410
+ if (!exchange ) {
2411
+ memcpy (dentry -> d_iname , target -> d_name .name ,
2412
+ target -> d_name .len + 1 );
2413
+ dentry -> d_name .hash_len = target -> d_name .hash_len ;
2414
+ return ;
2415
+ }
2409
2416
for (i = 0 ; i < DNAME_INLINE_LEN / sizeof (long ); i ++ ) {
2410
2417
swap (((long * ) & dentry -> d_iname )[i ],
2411
2418
((long * ) & target -> d_iname )[i ]);
2412
2419
}
2413
2420
}
2414
2421
}
2415
- swap (dentry -> d_name .len , target -> d_name .len );
2422
+ swap (dentry -> d_name .hash_len , target -> d_name .hash_len );
2416
2423
}
2417
2424
2418
2425
static void dentry_lock_for_move (struct dentry * dentry , struct dentry * target )
@@ -2442,25 +2449,29 @@ static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target)
2442
2449
}
2443
2450
}
2444
2451
2445
- static void dentry_unlock_parents_for_move (struct dentry * dentry ,
2446
- struct dentry * target )
2452
+ static void dentry_unlock_for_move (struct dentry * dentry , struct dentry * target )
2447
2453
{
2448
2454
if (target -> d_parent != dentry -> d_parent )
2449
2455
spin_unlock (& dentry -> d_parent -> d_lock );
2450
2456
if (target -> d_parent != target )
2451
2457
spin_unlock (& target -> d_parent -> d_lock );
2458
+ spin_unlock (& target -> d_lock );
2459
+ spin_unlock (& dentry -> d_lock );
2452
2460
}
2453
2461
2454
2462
/*
2455
2463
* When switching names, the actual string doesn't strictly have to
2456
2464
* be preserved in the target - because we're dropping the target
2457
2465
* anyway. As such, we can just do a simple memcpy() to copy over
2458
- * the new name before we switch.
2459
- *
2460
- * Note that we have to be a lot more careful about getting the hash
2461
- * switched - we have to switch the hash value properly even if it
2462
- * then no longer matches the actual (corrupted) string of the target.
2463
- * The hash value has to match the hash queue that the dentry is on..
2466
+ * the new name before we switch, unless we are going to rehash
2467
+ * it. Note that if we *do* unhash the target, we are not allowed
2468
+ * to rehash it without giving it a new name/hash key - whether
2469
+ * we swap or overwrite the names here, resulting name won't match
2470
+ * the reality in filesystem; it's only there for d_path() purposes.
2471
+ * Note that all of this is happening under rename_lock, so the
2472
+ * any hash lookup seeing it in the middle of manipulations will
2473
+ * be discarded anyway. So we do not care what happens to the hash
2474
+ * key in that case.
2464
2475
*/
2465
2476
/*
2466
2477
* __d_move - move a dentry
@@ -2506,36 +2517,30 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
2506
2517
d_hash (dentry -> d_parent , dentry -> d_name .hash ));
2507
2518
}
2508
2519
2509
- list_del (& dentry -> d_u .d_child );
2510
- list_del (& target -> d_u .d_child );
2511
-
2512
2520
/* Switch the names.. */
2513
- switch_names (dentry , target );
2514
- swap (dentry -> d_name .hash , target -> d_name .hash );
2521
+ switch_names (dentry , target , exchange );
2515
2522
2516
- /* ... and switch the parents */
2523
+ /* ... and switch them in the tree */
2517
2524
if (IS_ROOT (dentry )) {
2525
+ /* splicing a tree */
2518
2526
dentry -> d_parent = target -> d_parent ;
2519
2527
target -> d_parent = target ;
2520
- INIT_LIST_HEAD (& target -> d_u .d_child );
2528
+ list_del_init (& target -> d_u .d_child );
2529
+ list_move (& dentry -> d_u .d_child , & dentry -> d_parent -> d_subdirs );
2521
2530
} else {
2531
+ /* swapping two dentries */
2522
2532
swap (dentry -> d_parent , target -> d_parent );
2523
-
2524
- /* And add them back to the (new) parent lists */
2525
- list_add (& target -> d_u .d_child , & target -> d_parent -> d_subdirs );
2533
+ list_move (& target -> d_u .d_child , & target -> d_parent -> d_subdirs );
2534
+ list_move (& dentry -> d_u .d_child , & dentry -> d_parent -> d_subdirs );
2535
+ if (exchange )
2536
+ fsnotify_d_move (target );
2537
+ fsnotify_d_move (dentry );
2526
2538
}
2527
2539
2528
- list_add (& dentry -> d_u .d_child , & dentry -> d_parent -> d_subdirs );
2529
-
2530
2540
write_seqcount_end (& target -> d_seq );
2531
2541
write_seqcount_end (& dentry -> d_seq );
2532
2542
2533
- dentry_unlock_parents_for_move (dentry , target );
2534
- if (exchange )
2535
- fsnotify_d_move (target );
2536
- spin_unlock (& target -> d_lock );
2537
- fsnotify_d_move (dentry );
2538
- spin_unlock (& dentry -> d_lock );
2543
+ dentry_unlock_for_move (dentry , target );
2539
2544
}
2540
2545
2541
2546
/*
@@ -2633,45 +2638,6 @@ static struct dentry *__d_unalias(struct inode *inode,
2633
2638
return ret ;
2634
2639
}
2635
2640
2636
- /*
2637
- * Prepare an anonymous dentry for life in the superblock's dentry tree as a
2638
- * named dentry in place of the dentry to be replaced.
2639
- * returns with anon->d_lock held!
2640
- */
2641
- static void __d_materialise_dentry (struct dentry * dentry , struct dentry * anon )
2642
- {
2643
- struct dentry * dparent ;
2644
-
2645
- dentry_lock_for_move (anon , dentry );
2646
-
2647
- write_seqcount_begin (& dentry -> d_seq );
2648
- write_seqcount_begin_nested (& anon -> d_seq , DENTRY_D_LOCK_NESTED );
2649
-
2650
- dparent = dentry -> d_parent ;
2651
-
2652
- switch_names (dentry , anon );
2653
- swap (dentry -> d_name .hash , anon -> d_name .hash );
2654
-
2655
- dentry -> d_parent = dentry ;
2656
- list_del_init (& dentry -> d_u .d_child );
2657
- anon -> d_parent = dparent ;
2658
- if (likely (!d_unhashed (anon ))) {
2659
- hlist_bl_lock (& anon -> d_sb -> s_anon );
2660
- __hlist_bl_del (& anon -> d_hash );
2661
- anon -> d_hash .pprev = NULL ;
2662
- hlist_bl_unlock (& anon -> d_sb -> s_anon );
2663
- }
2664
- list_move (& anon -> d_u .d_child , & dparent -> d_subdirs );
2665
-
2666
- write_seqcount_end (& dentry -> d_seq );
2667
- write_seqcount_end (& anon -> d_seq );
2668
-
2669
- dentry_unlock_parents_for_move (anon , dentry );
2670
- spin_unlock (& dentry -> d_lock );
2671
-
2672
- /* anon->d_lock still locked, returns locked */
2673
- }
2674
-
2675
2641
/**
2676
2642
* d_splice_alias - splice a disconnected dentry into the tree if one exists
2677
2643
* @inode: the inode which may have a disconnected dentry
@@ -2717,10 +2683,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
2717
2683
return ERR_PTR (- EIO );
2718
2684
}
2719
2685
write_seqlock (& rename_lock );
2720
- __d_materialise_dentry ( dentry , new );
2686
+ __d_move ( new , dentry , false );
2721
2687
write_sequnlock (& rename_lock );
2722
- _d_rehash (new );
2723
- spin_unlock (& new -> d_lock );
2724
2688
spin_unlock (& inode -> i_lock );
2725
2689
security_d_instantiate (new , inode );
2726
2690
iput (inode );
@@ -2780,7 +2744,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
2780
2744
} else if (IS_ROOT (alias )) {
2781
2745
/* Is this an anonymous mountpoint that we
2782
2746
* could splice into our tree? */
2783
- __d_materialise_dentry ( dentry , alias );
2747
+ __d_move ( alias , dentry , false );
2784
2748
write_sequnlock (& rename_lock );
2785
2749
goto found ;
2786
2750
} else {
@@ -2807,13 +2771,9 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
2807
2771
actual = __d_instantiate_unique (dentry , inode );
2808
2772
if (!actual )
2809
2773
actual = dentry ;
2810
- else
2811
- BUG_ON (!d_unhashed (actual ));
2812
2774
2813
- spin_lock ( & actual -> d_lock );
2775
+ d_rehash ( actual );
2814
2776
found :
2815
- _d_rehash (actual );
2816
- spin_unlock (& actual -> d_lock );
2817
2777
spin_unlock (& inode -> i_lock );
2818
2778
out_nolock :
2819
2779
if (actual == dentry ) {
0 commit comments