@@ -32,35 +32,30 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
32
32
struct exfat_chain * p_dir , int entry , unsigned short * uniname )
33
33
{
34
34
int i ;
35
- struct exfat_dentry * ep ;
36
35
struct exfat_entry_set_cache * es ;
37
36
38
- es = exfat_get_dentry_set (sb , p_dir , entry , ES_ALL_ENTRIES , & ep );
37
+ es = exfat_get_dentry_set (sb , p_dir , entry , ES_ALL_ENTRIES );
39
38
if (!es )
40
39
return ;
41
40
42
- if (es -> num_entries < 3 )
43
- goto free_es ;
44
-
45
- ep += 2 ;
46
-
47
41
/*
48
42
* First entry : file entry
49
43
* Second entry : stream-extension entry
50
44
* Third entry : first file-name entry
51
45
* So, the index of first file-name dentry should start from 2.
52
46
*/
53
- for (i = 2 ; i < es -> num_entries ; i ++ , ep ++ ) {
47
+ for (i = 2 ; i < es -> num_entries ; i ++ ) {
48
+ struct exfat_dentry * ep = exfat_get_dentry_cached (es , i );
49
+
54
50
/* end of name entry */
55
51
if (exfat_get_entry_type (ep ) != TYPE_EXTEND )
56
- goto free_es ;
52
+ break ;
57
53
58
54
exfat_extract_uni_name (ep , uniname );
59
55
uniname += EXFAT_FILE_NAME_LEN ;
60
56
}
61
57
62
- free_es :
63
- kfree (es );
58
+ exfat_free_dentry_set (es , false);
64
59
}
65
60
66
61
/* read a directory entry from the opened directory */
@@ -590,62 +585,33 @@ int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir,
590
585
return 0 ;
591
586
}
592
587
593
- int exfat_update_dir_chksum_with_entry_set (struct super_block * sb ,
594
- struct exfat_entry_set_cache * es , int sync )
588
+ void exfat_update_dir_chksum_with_entry_set (struct exfat_entry_set_cache * es )
595
589
{
596
- struct exfat_sb_info * sbi = EXFAT_SB (sb );
597
- struct buffer_head * bh ;
598
- sector_t sec = es -> sector ;
599
- unsigned int off = es -> offset ;
600
- int chksum_type = CS_DIR_ENTRY , i , num_entries = es -> num_entries ;
601
- unsigned int buf_off = (off - es -> offset );
602
- unsigned int remaining_byte_in_sector , copy_entries , clu ;
590
+ int chksum_type = CS_DIR_ENTRY , i ;
603
591
unsigned short chksum = 0 ;
592
+ struct exfat_dentry * ep ;
604
593
605
- for (i = 0 ; i < num_entries ; i ++ ) {
606
- chksum = exfat_calc_chksum_2byte (& es -> entries [i ], DENTRY_SIZE ,
607
- chksum , chksum_type );
594
+ for (i = 0 ; i < es -> num_entries ; i ++ ) {
595
+ ep = exfat_get_dentry_cached (es , i );
596
+ chksum = exfat_calc_chksum_2byte (ep , DENTRY_SIZE , chksum ,
597
+ chksum_type );
608
598
chksum_type = CS_DEFAULT ;
609
599
}
600
+ ep = exfat_get_dentry_cached (es , 0 );
601
+ ep -> dentry .file .checksum = cpu_to_le16 (chksum );
602
+ es -> modified = true;
603
+ }
610
604
611
- es -> entries [0 ].dentry .file .checksum = cpu_to_le16 (chksum );
605
+ void exfat_free_dentry_set (struct exfat_entry_set_cache * es , int sync )
606
+ {
607
+ int i ;
612
608
613
- while (num_entries ) {
614
- /* write per sector base */
615
- remaining_byte_in_sector = (1 << sb -> s_blocksize_bits ) - off ;
616
- copy_entries = min_t (int ,
617
- EXFAT_B_TO_DEN (remaining_byte_in_sector ),
618
- num_entries );
619
- bh = sb_bread (sb , sec );
620
- if (!bh )
621
- goto err_out ;
622
- memcpy (bh -> b_data + off ,
623
- (unsigned char * )& es -> entries [0 ] + buf_off ,
624
- EXFAT_DEN_TO_B (copy_entries ));
625
- exfat_update_bh (sb , bh , sync );
626
- brelse (bh );
627
- num_entries -= copy_entries ;
628
-
629
- if (num_entries ) {
630
- /* get next sector */
631
- if (exfat_is_last_sector_in_cluster (sbi , sec )) {
632
- clu = exfat_sector_to_cluster (sbi , sec );
633
- if (es -> alloc_flag == ALLOC_NO_FAT_CHAIN )
634
- clu ++ ;
635
- else if (exfat_get_next_cluster (sb , & clu ))
636
- goto err_out ;
637
- sec = exfat_cluster_to_sector (sbi , clu );
638
- } else {
639
- sec ++ ;
640
- }
641
- off = 0 ;
642
- buf_off += EXFAT_DEN_TO_B (copy_entries );
643
- }
609
+ for (i = 0 ; i < es -> num_bh ; i ++ ) {
610
+ if (es -> modified )
611
+ exfat_update_bh (es -> sb , es -> bh [i ], sync );
612
+ brelse (es -> bh [i ]);
644
613
}
645
-
646
- return 0 ;
647
- err_out :
648
- return - EIO ;
614
+ kfree (es );
649
615
}
650
616
651
617
static int exfat_walk_fat_chain (struct super_block * sb ,
@@ -820,34 +786,40 @@ static bool exfat_validate_entry(unsigned int type,
820
786
}
821
787
}
822
788
789
+ struct exfat_dentry * exfat_get_dentry_cached (
790
+ struct exfat_entry_set_cache * es , int num )
791
+ {
792
+ int off = es -> start_off + num * DENTRY_SIZE ;
793
+ struct buffer_head * bh = es -> bh [EXFAT_B_TO_BLK (off , es -> sb )];
794
+ char * p = bh -> b_data + EXFAT_BLK_OFFSET (off , es -> sb );
795
+
796
+ return (struct exfat_dentry * )p ;
797
+ }
798
+
823
799
/*
824
800
* Returns a set of dentries for a file or dir.
825
801
*
826
- * Note that this is a copy (dump) of dentries so that user should
827
- * call write_entry_set () to apply changes made in this entry set
828
- * to the real device.
802
+ * Note It provides a direct pointer to bh->data via exfat_get_dentry_cached().
803
+ * User should call exfat_get_dentry_set () after setting 'modified' to apply
804
+ * changes made in this entry set to the real device.
829
805
*
830
806
* in:
831
807
* sb+p_dir+entry: indicates a file/dir
832
808
* type: specifies how many dentries should be included.
833
- * out:
834
- * file_ep: will point the first dentry(= file dentry) on success
835
809
* return:
836
810
* pointer of entry set on success,
837
811
* NULL on failure.
838
812
*/
839
813
struct exfat_entry_set_cache * exfat_get_dentry_set (struct super_block * sb ,
840
- struct exfat_chain * p_dir , int entry , unsigned int type ,
841
- struct exfat_dentry * * file_ep )
814
+ struct exfat_chain * p_dir , int entry , unsigned int type )
842
815
{
843
- int ret ;
816
+ int ret , i , num_bh ;
844
817
unsigned int off , byte_offset , clu = 0 ;
845
- unsigned int entry_type ;
846
818
sector_t sec ;
847
819
struct exfat_sb_info * sbi = EXFAT_SB (sb );
848
820
struct exfat_entry_set_cache * es ;
849
- struct exfat_dentry * ep , * pos ;
850
- unsigned char num_entries ;
821
+ struct exfat_dentry * ep ;
822
+ int num_entries ;
851
823
enum exfat_validate_dentry_mode mode = ES_MODE_STARTED ;
852
824
struct buffer_head * bh ;
853
825
@@ -861,84 +833,65 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
861
833
if (ret )
862
834
return NULL ;
863
835
836
+ es = kzalloc (sizeof (* es ), GFP_KERNEL );
837
+ if (!es )
838
+ return NULL ;
839
+ es -> sb = sb ;
840
+ es -> modified = false;
841
+
864
842
/* byte offset in cluster */
865
843
byte_offset = EXFAT_CLU_OFFSET (byte_offset , sbi );
866
844
867
845
/* byte offset in sector */
868
846
off = EXFAT_BLK_OFFSET (byte_offset , sb );
847
+ es -> start_off = off ;
869
848
870
849
/* sector offset in cluster */
871
850
sec = EXFAT_B_TO_BLK (byte_offset , sb );
872
851
sec += exfat_cluster_to_sector (sbi , clu );
873
852
874
853
bh = sb_bread (sb , sec );
875
854
if (!bh )
876
- return NULL ;
877
-
878
- ep = (struct exfat_dentry * )(bh -> b_data + off );
879
- entry_type = exfat_get_entry_type (ep );
855
+ goto free_es ;
856
+ es -> bh [es -> num_bh ++ ] = bh ;
880
857
881
- if (entry_type != TYPE_FILE && entry_type != TYPE_DIR )
882
- goto release_bh ;
858
+ ep = exfat_get_dentry_cached (es , 0 );
859
+ if (!exfat_validate_entry (exfat_get_entry_type (ep ), & mode ))
860
+ goto free_es ;
883
861
884
862
num_entries = type == ES_ALL_ENTRIES ?
885
863
ep -> dentry .file .num_ext + 1 : type ;
886
- es = kmalloc (struct_size (es , entries , num_entries ), GFP_KERNEL );
887
- if (!es )
888
- goto release_bh ;
889
-
890
864
es -> num_entries = num_entries ;
891
- es -> sector = sec ;
892
- es -> offset = off ;
893
- es -> alloc_flag = p_dir -> flags ;
894
-
895
- pos = & es -> entries [0 ];
896
-
897
- while (num_entries ) {
898
- if (!exfat_validate_entry (exfat_get_entry_type (ep ), & mode ))
899
- goto free_es ;
900
865
901
- /* copy dentry */
902
- memcpy (pos , ep , sizeof (struct exfat_dentry ));
903
-
904
- if (-- num_entries == 0 )
905
- break ;
906
-
907
- if (((off + DENTRY_SIZE ) & (sb -> s_blocksize - 1 )) <
908
- (off & (sb -> s_blocksize - 1 ))) {
909
- /* get the next sector */
910
- if (exfat_is_last_sector_in_cluster (sbi , sec )) {
911
- if (es -> alloc_flag == ALLOC_NO_FAT_CHAIN )
912
- clu ++ ;
913
- else if (exfat_get_next_cluster (sb , & clu ))
914
- goto free_es ;
915
- sec = exfat_cluster_to_sector (sbi , clu );
916
- } else {
917
- sec ++ ;
918
- }
919
-
920
- brelse (bh );
921
- bh = sb_bread (sb , sec );
922
- if (!bh )
866
+ num_bh = EXFAT_B_TO_BLK_ROUND_UP (off + num_entries * DENTRY_SIZE , sb );
867
+ for (i = 1 ; i < num_bh ; i ++ ) {
868
+ /* get the next sector */
869
+ if (exfat_is_last_sector_in_cluster (sbi , sec )) {
870
+ if (p_dir -> flags == ALLOC_NO_FAT_CHAIN )
871
+ clu ++ ;
872
+ else if (exfat_get_next_cluster (sb , & clu ))
923
873
goto free_es ;
924
- off = 0 ;
925
- ep = (struct exfat_dentry * )bh -> b_data ;
874
+ sec = exfat_cluster_to_sector (sbi , clu );
926
875
} else {
927
- ep ++ ;
928
- off += DENTRY_SIZE ;
876
+ sec ++ ;
929
877
}
930
- pos ++ ;
878
+
879
+ bh = sb_bread (sb , sec );
880
+ if (!bh )
881
+ goto free_es ;
882
+ es -> bh [es -> num_bh ++ ] = bh ;
931
883
}
932
884
933
- if (file_ep )
934
- * file_ep = & es -> entries [0 ];
935
- brelse (bh );
885
+ /* validiate cached dentries */
886
+ for (i = 1 ; i < num_entries ; i ++ ) {
887
+ ep = exfat_get_dentry_cached (es , i );
888
+ if (!exfat_validate_entry (exfat_get_entry_type (ep ), & mode ))
889
+ goto free_es ;
890
+ }
936
891
return es ;
937
892
938
893
free_es :
939
- kfree (es );
940
- release_bh :
941
- brelse (bh );
894
+ exfat_free_dentry_set (es , false);
942
895
return NULL ;
943
896
}
944
897
0 commit comments