@@ -77,7 +77,6 @@ struct dio_submit {
77
77
unsigned blocks_available ; /* At block_in_file. changes */
78
78
int reap_counter ; /* rate limit reaping */
79
79
sector_t final_block_in_request ;/* doesn't change */
80
- unsigned first_block_in_page ; /* doesn't change, Used only once */
81
80
int boundary ; /* prev block is at a boundary */
82
81
get_block_t * get_block ; /* block mapping function */
83
82
dio_submit_t * submit_io ; /* IO submition function */
@@ -98,19 +97,14 @@ struct dio_submit {
98
97
sector_t cur_page_block ; /* Where it starts */
99
98
loff_t cur_page_fs_offset ; /* Offset in file */
100
99
101
- /*
102
- * Page fetching state. These variables belong to dio_refill_pages().
103
- */
104
- int curr_page ; /* changes */
105
- int total_pages ; /* doesn't change */
106
- unsigned long curr_user_address ;/* changes */
107
-
100
+ struct iov_iter * iter ;
108
101
/*
109
102
* Page queue. These variables belong to dio_refill_pages() and
110
103
* dio_get_page().
111
104
*/
112
105
unsigned head ; /* next page to process */
113
106
unsigned tail ; /* last valid page + 1 */
107
+ size_t from , to ;
114
108
};
115
109
116
110
/* dio_state communicated between submission path and end_io */
@@ -163,15 +157,10 @@ static inline unsigned dio_pages_present(struct dio_submit *sdio)
163
157
*/
164
158
static inline int dio_refill_pages (struct dio * dio , struct dio_submit * sdio )
165
159
{
166
- int ret ;
167
- int nr_pages ;
160
+ ssize_t ret ;
168
161
169
- nr_pages = min (sdio -> total_pages - sdio -> curr_page , DIO_PAGES );
170
- ret = get_user_pages_fast (
171
- sdio -> curr_user_address , /* Where from? */
172
- nr_pages , /* How many pages? */
173
- dio -> rw == READ , /* Write to memory? */
174
- & dio -> pages [0 ]); /* Put results here */
162
+ ret = iov_iter_get_pages (sdio -> iter , dio -> pages , DIO_PAGES * PAGE_SIZE ,
163
+ & sdio -> from );
175
164
176
165
if (ret < 0 && sdio -> blocks_available && (dio -> rw & WRITE )) {
177
166
struct page * page = ZERO_PAGE (0 );
@@ -186,18 +175,19 @@ static inline int dio_refill_pages(struct dio *dio, struct dio_submit *sdio)
186
175
dio -> pages [0 ] = page ;
187
176
sdio -> head = 0 ;
188
177
sdio -> tail = 1 ;
189
- ret = 0 ;
190
- goto out ;
178
+ sdio -> from = 0 ;
179
+ sdio -> to = PAGE_SIZE ;
180
+ return 0 ;
191
181
}
192
182
193
183
if (ret >= 0 ) {
194
- sdio -> curr_user_address += ret * PAGE_SIZE ;
195
- sdio -> curr_page += ret ;
184
+ iov_iter_advance ( sdio -> iter , ret ) ;
185
+ ret += sdio -> from ;
196
186
sdio -> head = 0 ;
197
- sdio -> tail = ret ;
198
- ret = 0 ;
187
+ sdio -> tail = (ret + PAGE_SIZE - 1 ) / PAGE_SIZE ;
188
+ sdio -> to = ((ret - 1 ) & (PAGE_SIZE - 1 )) + 1 ;
189
+ return 0 ;
199
190
}
200
- out :
201
191
return ret ;
202
192
}
203
193
@@ -208,8 +198,9 @@ static inline int dio_refill_pages(struct dio *dio, struct dio_submit *sdio)
208
198
* L1 cache.
209
199
*/
210
200
static inline struct page * dio_get_page (struct dio * dio ,
211
- struct dio_submit * sdio )
201
+ struct dio_submit * sdio , size_t * from , size_t * to )
212
202
{
203
+ int n ;
213
204
if (dio_pages_present (sdio ) == 0 ) {
214
205
int ret ;
215
206
@@ -218,7 +209,10 @@ static inline struct page *dio_get_page(struct dio *dio,
218
209
return ERR_PTR (ret );
219
210
BUG_ON (dio_pages_present (sdio ) == 0 );
220
211
}
221
- return dio -> pages [sdio -> head ++ ];
212
+ n = sdio -> head ++ ;
213
+ * from = n ? 0 : sdio -> from ;
214
+ * to = (n == sdio -> tail - 1 ) ? sdio -> to : PAGE_SIZE ;
215
+ return dio -> pages [n ];
222
216
}
223
217
224
218
/**
@@ -422,8 +416,8 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio)
422
416
*/
423
417
static inline void dio_cleanup (struct dio * dio , struct dio_submit * sdio )
424
418
{
425
- while (dio_pages_present ( sdio ) )
426
- page_cache_release (dio_get_page ( dio , sdio ) );
419
+ while (sdio -> head < sdio -> tail )
420
+ page_cache_release (dio -> pages [ sdio -> head ++ ] );
427
421
}
428
422
429
423
/*
@@ -912,23 +906,18 @@ static int do_direct_IO(struct dio *dio, struct dio_submit *sdio,
912
906
struct buffer_head * map_bh )
913
907
{
914
908
const unsigned blkbits = sdio -> blkbits ;
915
- const unsigned blocks_per_page = PAGE_SIZE >> blkbits ;
916
- struct page * page ;
917
- unsigned block_in_page ;
918
909
int ret = 0 ;
919
910
920
- /* The I/O can start at any block offset within the first page */
921
- block_in_page = sdio -> first_block_in_page ;
922
-
923
911
while (sdio -> block_in_file < sdio -> final_block_in_request ) {
924
- page = dio_get_page (dio , sdio );
912
+ struct page * page ;
913
+ size_t from , to ;
914
+ page = dio_get_page (dio , sdio , & from , & to );
925
915
if (IS_ERR (page )) {
926
916
ret = PTR_ERR (page );
927
917
goto out ;
928
918
}
929
919
930
- while (block_in_page < blocks_per_page ) {
931
- unsigned offset_in_page = block_in_page << blkbits ;
920
+ while (from < to ) {
932
921
unsigned this_chunk_bytes ; /* # of bytes mapped */
933
922
unsigned this_chunk_blocks ; /* # of blocks */
934
923
unsigned u ;
@@ -999,10 +988,9 @@ static int do_direct_IO(struct dio *dio, struct dio_submit *sdio,
999
988
page_cache_release (page );
1000
989
goto out ;
1001
990
}
1002
- zero_user (page , block_in_page << blkbits ,
1003
- 1 << blkbits );
991
+ zero_user (page , from , 1 << blkbits );
1004
992
sdio -> block_in_file ++ ;
1005
- block_in_page ++ ;
993
+ from += 1 << blkbits ;
1006
994
dio -> result += 1 << blkbits ;
1007
995
goto next_block ;
1008
996
}
@@ -1020,7 +1008,7 @@ static int do_direct_IO(struct dio *dio, struct dio_submit *sdio,
1020
1008
* can add to this page
1021
1009
*/
1022
1010
this_chunk_blocks = sdio -> blocks_available ;
1023
- u = (PAGE_SIZE - offset_in_page ) >> blkbits ;
1011
+ u = (to - from ) >> blkbits ;
1024
1012
if (this_chunk_blocks > u )
1025
1013
this_chunk_blocks = u ;
1026
1014
u = sdio -> final_block_in_request - sdio -> block_in_file ;
@@ -1032,7 +1020,7 @@ static int do_direct_IO(struct dio *dio, struct dio_submit *sdio,
1032
1020
if (this_chunk_blocks == sdio -> blocks_available )
1033
1021
sdio -> boundary = buffer_boundary (map_bh );
1034
1022
ret = submit_page_section (dio , sdio , page ,
1035
- offset_in_page ,
1023
+ from ,
1036
1024
this_chunk_bytes ,
1037
1025
sdio -> next_block_for_io ,
1038
1026
map_bh );
@@ -1043,9 +1031,9 @@ static int do_direct_IO(struct dio *dio, struct dio_submit *sdio,
1043
1031
sdio -> next_block_for_io += this_chunk_blocks ;
1044
1032
1045
1033
sdio -> block_in_file += this_chunk_blocks ;
1046
- block_in_page += this_chunk_blocks ;
1034
+ from += this_chunk_bytes ;
1035
+ dio -> result += this_chunk_bytes ;
1047
1036
sdio -> blocks_available -= this_chunk_blocks ;
1048
- dio -> result += this_chunk_blocks << blkbits ;
1049
1037
next_block :
1050
1038
BUG_ON (sdio -> block_in_file > sdio -> final_block_in_request );
1051
1039
if (sdio -> block_in_file == sdio -> final_block_in_request )
@@ -1054,7 +1042,6 @@ static int do_direct_IO(struct dio *dio, struct dio_submit *sdio,
1054
1042
1055
1043
/* Drop the ref which was taken in get_user_pages() */
1056
1044
page_cache_release (page );
1057
- block_in_page = 0 ;
1058
1045
}
1059
1046
out :
1060
1047
return ret ;
@@ -1122,7 +1109,6 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
1122
1109
struct dio * dio ;
1123
1110
struct dio_submit sdio = { 0 , };
1124
1111
unsigned long user_addr ;
1125
- size_t bytes ;
1126
1112
struct buffer_head map_bh = { 0 , };
1127
1113
struct blk_plug plug ;
1128
1114
unsigned long align = offset | iov_iter_alignment (iter );
@@ -1234,6 +1220,10 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
1234
1220
spin_lock_init (& dio -> bio_lock );
1235
1221
dio -> refcount = 1 ;
1236
1222
1223
+ sdio .iter = iter ;
1224
+ sdio .final_block_in_request =
1225
+ (offset + iov_iter_count (iter )) >> blkbits ;
1226
+
1237
1227
/*
1238
1228
* In case of non-aligned buffers, we may need 2 more
1239
1229
* pages since we need to zero out first and last block.
@@ -1250,34 +1240,9 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
1250
1240
1251
1241
blk_start_plug (& plug );
1252
1242
1253
- for (seg = 0 ; seg < iter -> nr_segs ; seg ++ ) {
1254
- user_addr = (unsigned long )iter -> iov [seg ].iov_base ;
1255
- sdio .size += bytes = iter -> iov [seg ].iov_len ;
1256
-
1257
- /* Index into the first page of the first block */
1258
- sdio .first_block_in_page = (user_addr & ~PAGE_MASK ) >> blkbits ;
1259
- sdio .final_block_in_request = sdio .block_in_file +
1260
- (bytes >> blkbits );
1261
- /* Page fetching state */
1262
- sdio .head = 0 ;
1263
- sdio .tail = 0 ;
1264
- sdio .curr_page = 0 ;
1265
-
1266
- sdio .total_pages = 0 ;
1267
- if (user_addr & (PAGE_SIZE - 1 )) {
1268
- sdio .total_pages ++ ;
1269
- bytes -= PAGE_SIZE - (user_addr & (PAGE_SIZE - 1 ));
1270
- }
1271
- sdio .total_pages += (bytes + PAGE_SIZE - 1 ) / PAGE_SIZE ;
1272
- sdio .curr_user_address = user_addr ;
1273
-
1274
- retval = do_direct_IO (dio , & sdio , & map_bh );
1275
-
1276
- if (retval ) {
1277
- dio_cleanup (dio , & sdio );
1278
- break ;
1279
- }
1280
- } /* end iovec loop */
1243
+ retval = do_direct_IO (dio , & sdio , & map_bh );
1244
+ if (retval )
1245
+ dio_cleanup (dio , & sdio );
1281
1246
1282
1247
if (retval == - ENOTBLK ) {
1283
1248
/*
0 commit comments