@@ -558,7 +558,8 @@ static void remove_oldest_entry_locked(void)
558
558
}
559
559
560
560
/* Add a new DFS cache entry */
561
- static int add_cache_entry_locked (struct dfs_info3_param * refs , int numrefs )
561
+ static struct cache_entry * add_cache_entry_locked (struct dfs_info3_param * refs ,
562
+ int numrefs )
562
563
{
563
564
int rc ;
564
565
struct cache_entry * ce ;
@@ -573,11 +574,11 @@ static int add_cache_entry_locked(struct dfs_info3_param *refs, int numrefs)
573
574
574
575
rc = cache_entry_hash (refs [0 ].path_name , strlen (refs [0 ].path_name ), & hash );
575
576
if (rc )
576
- return rc ;
577
+ return ERR_PTR ( rc ) ;
577
578
578
579
ce = alloc_cache_entry (refs , numrefs );
579
580
if (IS_ERR (ce ))
580
- return PTR_ERR ( ce ) ;
581
+ return ce ;
581
582
582
583
spin_lock (& cache_ttl_lock );
583
584
if (!cache_ttl ) {
@@ -594,7 +595,7 @@ static int add_cache_entry_locked(struct dfs_info3_param *refs, int numrefs)
594
595
595
596
atomic_inc (& cache_count );
596
597
597
- return 0 ;
598
+ return ce ;
598
599
}
599
600
600
601
/* Check if two DFS paths are equal. @s1 and @s2 are expected to be in @cache_cp's charset */
@@ -767,8 +768,12 @@ static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, const
767
768
*
768
769
* For interlinks, cifs_mount() and expand_dfs_referral() are supposed to
769
770
* handle them properly.
771
+ *
772
+ * On success, return entry with acquired lock for reading, otherwise error ptr.
770
773
*/
771
- static int cache_refresh_path (const unsigned int xid , struct cifs_ses * ses , const char * path )
774
+ static struct cache_entry * cache_refresh_path (const unsigned int xid ,
775
+ struct cifs_ses * ses ,
776
+ const char * path )
772
777
{
773
778
struct dfs_info3_param * refs = NULL ;
774
779
struct cache_entry * ce ;
@@ -780,10 +785,9 @@ static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses, cons
780
785
down_read (& htable_rw_lock );
781
786
782
787
ce = lookup_cache_entry (path );
783
- if (!IS_ERR (ce ) && !cache_entry_expired (ce )) {
784
- up_read (& htable_rw_lock );
785
- return 0 ;
786
- }
788
+ if (!IS_ERR (ce ) && !cache_entry_expired (ce ))
789
+ return ce ;
790
+
787
791
/*
788
792
* Unlock shared access as we don't want to hold any locks while getting
789
793
* a new referral. The @ses used for performing the I/O could be
@@ -797,25 +801,35 @@ static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses, cons
797
801
* Request a new DFS referral in order to create or update a cache entry.
798
802
*/
799
803
rc = get_dfs_referral (xid , ses , path , & refs , & numrefs );
800
- if (rc )
804
+ if (rc ) {
805
+ ce = ERR_PTR (rc );
801
806
goto out ;
807
+ }
802
808
803
809
dump_refs (refs , numrefs );
804
810
805
811
down_write (& htable_rw_lock );
806
812
/* Re-check as another task might have it added or refreshed already */
807
813
ce = lookup_cache_entry (path );
808
814
if (!IS_ERR (ce )) {
809
- if (cache_entry_expired (ce ))
815
+ if (cache_entry_expired (ce )) {
810
816
rc = update_cache_entry_locked (ce , refs , numrefs );
817
+ if (rc )
818
+ ce = ERR_PTR (rc );
819
+ }
811
820
} else {
812
- rc = add_cache_entry_locked (refs , numrefs );
821
+ ce = add_cache_entry_locked (refs , numrefs );
813
822
}
814
823
815
- up_write (& htable_rw_lock );
824
+ if (IS_ERR (ce )) {
825
+ up_write (& htable_rw_lock );
826
+ goto out ;
827
+ }
828
+
829
+ downgrade_write (& htable_rw_lock );
816
830
out :
817
831
free_dfs_info_array (refs , numrefs );
818
- return rc ;
832
+ return ce ;
819
833
}
820
834
821
835
/*
@@ -935,15 +949,8 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nl
935
949
if (IS_ERR (npath ))
936
950
return PTR_ERR (npath );
937
951
938
- rc = cache_refresh_path (xid , ses , npath );
939
- if (rc )
940
- goto out_free_path ;
941
-
942
- down_read (& htable_rw_lock );
943
-
944
- ce = lookup_cache_entry (npath );
952
+ ce = cache_refresh_path (xid , ses , npath );
945
953
if (IS_ERR (ce )) {
946
- up_read (& htable_rw_lock );
947
954
rc = PTR_ERR (ce );
948
955
goto out_free_path ;
949
956
}
@@ -1039,10 +1046,13 @@ int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
1039
1046
1040
1047
cifs_dbg (FYI , "%s: update target hint - path: %s\n" , __func__ , npath );
1041
1048
1042
- rc = cache_refresh_path (xid , ses , npath );
1043
- if (rc )
1049
+ ce = cache_refresh_path (xid , ses , npath );
1050
+ if (IS_ERR (ce )) {
1051
+ rc = PTR_ERR (ce );
1044
1052
goto out_free_path ;
1053
+ }
1045
1054
1055
+ up_read (& htable_rw_lock );
1046
1056
down_write (& htable_rw_lock );
1047
1057
1048
1058
ce = lookup_cache_entry (npath );
0 commit comments