@@ -970,7 +970,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
970
970
u64 off = * ki_pos ;
971
971
u64 len = iov_iter_count (to );
972
972
u64 i_size = i_size_read (inode );
973
- bool sparse = ceph_test_mount_opt (fsc , SPARSEREAD );
973
+ bool sparse = IS_ENCRYPTED ( inode ) || ceph_test_mount_opt (fsc , SPARSEREAD );
974
974
u64 objver = 0 ;
975
975
976
976
dout ("sync_read on inode %p %llx~%llx\n" , inode , * ki_pos , len );
@@ -1001,10 +1001,19 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
1001
1001
int idx ;
1002
1002
size_t left ;
1003
1003
struct ceph_osd_req_op * op ;
1004
+ u64 read_off = off ;
1005
+ u64 read_len = len ;
1006
+
1007
+ /* determine new offset/length if encrypted */
1008
+ ceph_fscrypt_adjust_off_and_len (inode , & read_off , & read_len );
1009
+
1010
+ dout ("sync_read orig %llu~%llu reading %llu~%llu" ,
1011
+ off , len , read_off , read_len );
1004
1012
1005
1013
req = ceph_osdc_new_request (osdc , & ci -> i_layout ,
1006
- ci -> i_vino , off , & len , 0 , 1 ,
1007
- sparse ? CEPH_OSD_OP_SPARSE_READ : CEPH_OSD_OP_READ ,
1014
+ ci -> i_vino , read_off , & read_len , 0 , 1 ,
1015
+ sparse ? CEPH_OSD_OP_SPARSE_READ :
1016
+ CEPH_OSD_OP_READ ,
1008
1017
CEPH_OSD_FLAG_READ ,
1009
1018
NULL , ci -> i_truncate_seq ,
1010
1019
ci -> i_truncate_size , false);
@@ -1013,18 +1022,22 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
1013
1022
break ;
1014
1023
}
1015
1024
1025
+ /* adjust len downward if the request truncated the len */
1026
+ if (off + len > read_off + read_len )
1027
+ len = read_off + read_len - off ;
1016
1028
more = len < iov_iter_count (to );
1017
1029
1018
- num_pages = calc_pages_for (off , len );
1019
- page_off = off & ~ PAGE_MASK ;
1030
+ num_pages = calc_pages_for (read_off , read_len );
1031
+ page_off = offset_in_page ( off ) ;
1020
1032
pages = ceph_alloc_page_vector (num_pages , GFP_KERNEL );
1021
1033
if (IS_ERR (pages )) {
1022
1034
ceph_osdc_put_request (req );
1023
1035
ret = PTR_ERR (pages );
1024
1036
break ;
1025
1037
}
1026
1038
1027
- osd_req_op_extent_osd_data_pages (req , 0 , pages , len , page_off ,
1039
+ osd_req_op_extent_osd_data_pages (req , 0 , pages , read_len ,
1040
+ offset_in_page (read_off ),
1028
1041
false, false);
1029
1042
1030
1043
op = & req -> r_ops [0 ];
@@ -1042,7 +1055,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
1042
1055
ceph_update_read_metrics (& fsc -> mdsc -> metric ,
1043
1056
req -> r_start_latency ,
1044
1057
req -> r_end_latency ,
1045
- len , ret );
1058
+ read_len , ret );
1046
1059
1047
1060
if (ret > 0 )
1048
1061
objver = req -> r_version ;
@@ -1057,8 +1070,35 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
1057
1070
else if (ret == - ENOENT )
1058
1071
ret = 0 ;
1059
1072
1073
+ if (ret > 0 && IS_ENCRYPTED (inode )) {
1074
+ int fret ;
1075
+
1076
+ fret = ceph_fscrypt_decrypt_extents (inode , pages ,
1077
+ read_off , op -> extent .sparse_ext ,
1078
+ op -> extent .sparse_ext_cnt );
1079
+ if (fret < 0 ) {
1080
+ ret = fret ;
1081
+ ceph_osdc_put_request (req );
1082
+ break ;
1083
+ }
1084
+
1085
+ /* account for any partial block at the beginning */
1086
+ fret -= (off - read_off );
1087
+
1088
+ /*
1089
+ * Short read after big offset adjustment?
1090
+ * Nothing is usable, just call it a zero
1091
+ * len read.
1092
+ */
1093
+ fret = max (fret , 0 );
1094
+
1095
+ /* account for partial block at the end */
1096
+ ret = min_t (ssize_t , fret , len );
1097
+ }
1098
+
1060
1099
ceph_osdc_put_request (req );
1061
1100
1101
+ /* Short read but not EOF? Zero out the remainder. */
1062
1102
if (ret >= 0 && ret < len && (off + ret < i_size )) {
1063
1103
int zlen = min (len - ret , i_size - off - ret );
1064
1104
int zoff = page_off + ret ;
@@ -1072,15 +1112,16 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
1072
1112
idx = 0 ;
1073
1113
left = ret > 0 ? ret : 0 ;
1074
1114
while (left > 0 ) {
1075
- size_t len , copied ;
1076
- page_off = off & ~ PAGE_MASK ;
1077
- len = min_t (size_t , left , PAGE_SIZE - page_off );
1115
+ size_t plen , copied ;
1116
+
1117
+ plen = min_t (size_t , left , PAGE_SIZE - page_off );
1078
1118
SetPageUptodate (pages [idx ]);
1079
1119
copied = copy_page_to_iter (pages [idx ++ ],
1080
- page_off , len , to );
1120
+ page_off , plen , to );
1081
1121
off += copied ;
1082
1122
left -= copied ;
1083
- if (copied < len ) {
1123
+ page_off = 0 ;
1124
+ if (copied < plen ) {
1084
1125
ret = - EFAULT ;
1085
1126
break ;
1086
1127
}
@@ -1097,20 +1138,21 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
1097
1138
break ;
1098
1139
}
1099
1140
1100
- if (off > * ki_pos ) {
1101
- if (off >= i_size ) {
1102
- * retry_op = CHECK_EOF ;
1103
- ret = i_size - * ki_pos ;
1104
- * ki_pos = i_size ;
1105
- } else {
1106
- ret = off - * ki_pos ;
1107
- * ki_pos = off ;
1141
+ if (ret > 0 ) {
1142
+ if (off > * ki_pos ) {
1143
+ if (off >= i_size ) {
1144
+ * retry_op = CHECK_EOF ;
1145
+ ret = i_size - * ki_pos ;
1146
+ * ki_pos = i_size ;
1147
+ } else {
1148
+ ret = off - * ki_pos ;
1149
+ * ki_pos = off ;
1150
+ }
1108
1151
}
1109
- }
1110
-
1111
- if (last_objver && ret > 0 )
1112
- * last_objver = objver ;
1113
1152
1153
+ if (last_objver )
1154
+ * last_objver = objver ;
1155
+ }
1114
1156
dout ("sync_read result %zd retry_op %d\n" , ret , * retry_op );
1115
1157
return ret ;
1116
1158
}
0 commit comments