@@ -840,9 +840,109 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
840
840
return rc ;
841
841
}
842
842
843
+ static bool emit_cached_dirents (struct cached_dirents * cde ,
844
+ struct dir_context * ctx )
845
+ {
846
+ struct cached_dirent * dirent ;
847
+ int rc ;
848
+
849
+ list_for_each_entry (dirent , & cde -> entries , entry ) {
850
+ if (ctx -> pos >= dirent -> pos )
851
+ continue ;
852
+ ctx -> pos = dirent -> pos ;
853
+ rc = dir_emit (ctx , dirent -> name , dirent -> namelen ,
854
+ dirent -> fattr .cf_uniqueid ,
855
+ dirent -> fattr .cf_dtype );
856
+ if (!rc )
857
+ return rc ;
858
+ }
859
+ return true;
860
+ }
861
+
862
+ static void update_cached_dirents_count (struct cached_dirents * cde ,
863
+ struct dir_context * ctx )
864
+ {
865
+ if (cde -> ctx != ctx )
866
+ return ;
867
+ if (cde -> is_valid || cde -> is_failed )
868
+ return ;
869
+
870
+ cde -> pos ++ ;
871
+ }
872
+
873
+ static void finished_cached_dirents_count (struct cached_dirents * cde ,
874
+ struct dir_context * ctx )
875
+ {
876
+ if (cde -> ctx != ctx )
877
+ return ;
878
+ if (cde -> is_valid || cde -> is_failed )
879
+ return ;
880
+ if (ctx -> pos != cde -> pos )
881
+ return ;
882
+
883
+ cde -> is_valid = 1 ;
884
+ }
885
+
886
+ static void add_cached_dirent (struct cached_dirents * cde ,
887
+ struct dir_context * ctx ,
888
+ const char * name , int namelen ,
889
+ struct cifs_fattr * fattr )
890
+ {
891
+ struct cached_dirent * de ;
892
+
893
+ if (cde -> ctx != ctx )
894
+ return ;
895
+ if (cde -> is_valid || cde -> is_failed )
896
+ return ;
897
+ if (ctx -> pos != cde -> pos ) {
898
+ cde -> is_failed = 1 ;
899
+ return ;
900
+ }
901
+ de = kzalloc (sizeof (* de ), GFP_ATOMIC );
902
+ if (de == NULL ) {
903
+ cde -> is_failed = 1 ;
904
+ return ;
905
+ }
906
+ de -> namelen = namelen ;
907
+ de -> name = kstrndup (name , namelen , GFP_ATOMIC );
908
+ if (de -> name == NULL ) {
909
+ kfree (de );
910
+ cde -> is_failed = 1 ;
911
+ return ;
912
+ }
913
+ de -> pos = ctx -> pos ;
914
+
915
+ memcpy (& de -> fattr , fattr , sizeof (struct cifs_fattr ));
916
+
917
+ list_add_tail (& de -> entry , & cde -> entries );
918
+ }
919
+
920
+ static bool cifs_dir_emit (struct dir_context * ctx ,
921
+ const char * name , int namelen ,
922
+ struct cifs_fattr * fattr ,
923
+ struct cached_fid * cfid )
924
+ {
925
+ bool rc ;
926
+ ino_t ino = cifs_uniqueid_to_ino_t (fattr -> cf_uniqueid );
927
+
928
+ rc = dir_emit (ctx , name , namelen , ino , fattr -> cf_dtype );
929
+ if (!rc )
930
+ return rc ;
931
+
932
+ if (cfid ) {
933
+ mutex_lock (& cfid -> dirents .de_mutex );
934
+ add_cached_dirent (& cfid -> dirents , ctx , name , namelen ,
935
+ fattr );
936
+ mutex_unlock (& cfid -> dirents .de_mutex );
937
+ }
938
+
939
+ return rc ;
940
+ }
941
+
843
942
static int cifs_filldir (char * find_entry , struct file * file ,
844
- struct dir_context * ctx ,
845
- char * scratch_buf , unsigned int max_len )
943
+ struct dir_context * ctx ,
944
+ char * scratch_buf , unsigned int max_len ,
945
+ struct cached_fid * cfid )
846
946
{
847
947
struct cifsFileInfo * file_info = file -> private_data ;
848
948
struct super_block * sb = file_inode (file )-> i_sb ;
@@ -851,7 +951,6 @@ static int cifs_filldir(char *find_entry, struct file *file,
851
951
struct cifs_fattr fattr ;
852
952
struct qstr name ;
853
953
int rc = 0 ;
854
- ino_t ino ;
855
954
856
955
rc = cifs_fill_dirent (& de , find_entry , file_info -> srch_inf .info_level ,
857
956
file_info -> srch_inf .unicode );
@@ -931,8 +1030,8 @@ static int cifs_filldir(char *find_entry, struct file *file,
931
1030
932
1031
cifs_prime_dcache (file_dentry (file ), & name , & fattr );
933
1032
934
- ino = cifs_uniqueid_to_ino_t ( fattr . cf_uniqueid );
935
- return ! dir_emit ( ctx , name . name , name . len , ino , fattr . cf_dtype );
1033
+ return ! cifs_dir_emit ( ctx , name . name , name . len ,
1034
+ & fattr , cfid );
936
1035
}
937
1036
938
1037
@@ -941,15 +1040,18 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
941
1040
int rc = 0 ;
942
1041
unsigned int xid ;
943
1042
int i ;
1043
+ struct tcon_link * tlink = NULL ;
944
1044
struct cifs_tcon * tcon ;
945
- struct cifsFileInfo * cifsFile = NULL ;
1045
+ struct cifsFileInfo * cifsFile ;
946
1046
char * current_entry ;
947
1047
int num_to_fill = 0 ;
948
1048
char * tmp_buf = NULL ;
949
1049
char * end_of_smb ;
950
1050
unsigned int max_len ;
951
1051
const char * full_path ;
952
1052
void * page = alloc_dentry_path ();
1053
+ struct cached_fid * cfid = NULL ;
1054
+ struct cifs_sb_info * cifs_sb = CIFS_FILE_SB (file );
953
1055
954
1056
xid = get_xid ();
955
1057
@@ -959,6 +1061,56 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
959
1061
goto rddir2_exit ;
960
1062
}
961
1063
1064
+ if (file -> private_data == NULL ) {
1065
+ tlink = cifs_sb_tlink (cifs_sb );
1066
+ if (IS_ERR (tlink ))
1067
+ goto cache_not_found ;
1068
+ tcon = tlink_tcon (tlink );
1069
+ } else {
1070
+ cifsFile = file -> private_data ;
1071
+ tcon = tlink_tcon (cifsFile -> tlink );
1072
+ }
1073
+
1074
+ rc = open_cached_dir (xid , tcon , full_path , cifs_sb , & cfid );
1075
+ cifs_put_tlink (tlink );
1076
+ if (rc )
1077
+ goto cache_not_found ;
1078
+
1079
+ mutex_lock (& cfid -> dirents .de_mutex );
1080
+ /*
1081
+ * If this was reading from the start of the directory
1082
+ * we need to initialize scanning and storing the
1083
+ * directory content.
1084
+ */
1085
+ if (ctx -> pos == 0 && cfid -> dirents .ctx == NULL ) {
1086
+ cfid -> dirents .ctx = ctx ;
1087
+ cfid -> dirents .pos = 2 ;
1088
+ }
1089
+ /*
1090
+ * If we already have the entire directory cached then
1091
+ * we can just serve the cache.
1092
+ */
1093
+ if (cfid -> dirents .is_valid ) {
1094
+ if (!dir_emit_dots (file , ctx )) {
1095
+ mutex_unlock (& cfid -> dirents .de_mutex );
1096
+ goto rddir2_exit ;
1097
+ }
1098
+ emit_cached_dirents (& cfid -> dirents , ctx );
1099
+ mutex_unlock (& cfid -> dirents .de_mutex );
1100
+ goto rddir2_exit ;
1101
+ }
1102
+ mutex_unlock (& cfid -> dirents .de_mutex );
1103
+
1104
+ /* Drop the cache while calling initiate_cifs_search and
1105
+ * find_cifs_entry in case there will be reconnects during
1106
+ * query_directory.
1107
+ */
1108
+ if (cfid ) {
1109
+ close_cached_dir (cfid );
1110
+ cfid = NULL ;
1111
+ }
1112
+
1113
+ cache_not_found :
962
1114
/*
963
1115
* Ensure FindFirst doesn't fail before doing filldir() for '.' and
964
1116
* '..'. Otherwise we won't be able to notify VFS in case of failure.
@@ -977,7 +1129,6 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
977
1129
is in current search buffer?
978
1130
if it before then restart search
979
1131
if after then keep searching till find it */
980
-
981
1132
cifsFile = file -> private_data ;
982
1133
if (cifsFile -> srch_inf .endOfSearch ) {
983
1134
if (cifsFile -> srch_inf .emptyDir ) {
@@ -993,12 +1144,18 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
993
1144
tcon = tlink_tcon (cifsFile -> tlink );
994
1145
rc = find_cifs_entry (xid , tcon , ctx -> pos , file , full_path ,
995
1146
& current_entry , & num_to_fill );
1147
+ open_cached_dir (xid , tcon , full_path , cifs_sb , & cfid );
996
1148
if (rc ) {
997
1149
cifs_dbg (FYI , "fce error %d\n" , rc );
998
1150
goto rddir2_exit ;
999
1151
} else if (current_entry != NULL ) {
1000
1152
cifs_dbg (FYI , "entry %lld found\n" , ctx -> pos );
1001
1153
} else {
1154
+ if (cfid ) {
1155
+ mutex_lock (& cfid -> dirents .de_mutex );
1156
+ finished_cached_dirents_count (& cfid -> dirents , ctx );
1157
+ mutex_unlock (& cfid -> dirents .de_mutex );
1158
+ }
1002
1159
cifs_dbg (FYI , "Could not find entry\n" );
1003
1160
goto rddir2_exit ;
1004
1161
}
@@ -1028,14 +1185,20 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
1028
1185
*/
1029
1186
* tmp_buf = 0 ;
1030
1187
rc = cifs_filldir (current_entry , file , ctx ,
1031
- tmp_buf , max_len );
1188
+ tmp_buf , max_len , cfid );
1032
1189
if (rc ) {
1033
1190
if (rc > 0 )
1034
1191
rc = 0 ;
1035
1192
break ;
1036
1193
}
1037
1194
1038
1195
ctx -> pos ++ ;
1196
+ if (cfid ) {
1197
+ mutex_lock (& cfid -> dirents .de_mutex );
1198
+ update_cached_dirents_count (& cfid -> dirents , ctx );
1199
+ mutex_unlock (& cfid -> dirents .de_mutex );
1200
+ }
1201
+
1039
1202
if (ctx -> pos ==
1040
1203
cifsFile -> srch_inf .index_of_last_entry ) {
1041
1204
cifs_dbg (FYI , "last entry in buf at pos %lld %s\n" ,
@@ -1050,6 +1213,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
1050
1213
kfree (tmp_buf );
1051
1214
1052
1215
rddir2_exit :
1216
+ if (cfid )
1217
+ close_cached_dir (cfid );
1053
1218
free_dentry_path (page );
1054
1219
free_xid (xid );
1055
1220
return rc ;
0 commit comments