@@ -295,8 +295,9 @@ struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents)
295
295
int rds_message_copy_from_user (struct rds_message * rm , struct iov_iter * from ,
296
296
gfp_t gfp , bool large_page )
297
297
{
298
+ unsigned long to_copy , nbytes ;
299
+ unsigned long sg_off ;
298
300
struct scatterlist * sg ;
299
- size_t to_copy , copied , offset , chunk ;
300
301
int ret = 0 ;
301
302
302
303
rm -> m_inc .i_hdr .h_len = cpu_to_be32 (iov_iter_count (from ));
@@ -305,6 +306,7 @@ int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from,
305
306
* now allocate and copy in the data payload.
306
307
*/
307
308
sg = rm -> data .op_sg ;
309
+ sg_off = 0 ; /* Dear gcc, sg->page will be null from kzalloc. */
308
310
309
311
while (iov_iter_count (from )) {
310
312
if (!sg_page (sg )) {
@@ -316,69 +318,65 @@ int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from,
316
318
if (ret )
317
319
return ret ;
318
320
rm -> data .op_nents ++ ;
321
+ sg_off = 0 ;
319
322
}
320
323
321
- to_copy = iov_iter_count (from );
322
- if (to_copy > sg -> length )
323
- to_copy = sg -> length ;
324
+ to_copy = min_t (unsigned long , iov_iter_count (from ),
325
+ sg -> length - sg_off );
324
326
325
327
rds_stats_add (s_copy_from_user , to_copy );
328
+ nbytes = copy_page_from_iter (sg_page (sg ), sg -> offset + sg_off ,
329
+ to_copy , from );
330
+ if (nbytes != to_copy )
331
+ return - EFAULT ;
326
332
327
- for (copied = 0 ; copied < to_copy ; copied += chunk ) {
328
- offset = sg -> offset + copied ;
329
- chunk = offset < PAGE_SIZE ? PAGE_SIZE - offset : PAGE_SIZE ;
330
- if (copied + chunk > to_copy )
331
- chunk = to_copy - copied ;
333
+ sg_off += to_copy ;
332
334
333
- if (copy_page_from_iter (sg_page (sg ) + (offset >> PAGE_SHIFT ),
334
- offset & ~PAGE_MASK ,
335
- chunk , from ) != chunk )
336
- return - EFAULT ;
337
- }
338
-
339
- sg ++ ;
335
+ if (sg_off == sg -> length )
336
+ sg ++ ;
340
337
}
341
338
342
- return 0 ;
339
+ return ret ;
343
340
}
344
341
345
342
int rds_message_inc_copy_to_user (struct rds_incoming * inc , struct iov_iter * to )
346
343
{
347
344
struct rds_message * rm ;
348
345
struct scatterlist * sg ;
349
- size_t len , saved_len , to_copy , copied , offset , chunk ;
346
+ unsigned long to_copy ;
347
+ unsigned long vec_off ;
348
+ int copied ;
349
+ int ret ;
350
+ u32 len ;
350
351
351
352
rm = container_of (inc , struct rds_message , m_inc );
352
353
len = be32_to_cpu (rm -> m_inc .i_hdr .h_len );
353
- if (iov_iter_count (to ) < len )
354
- len = iov_iter_count (to );
355
354
356
355
sg = rm -> data .op_sg ;
356
+ vec_off = 0 ;
357
+ copied = 0 ;
357
358
358
- saved_len = len ;
359
-
360
- while ( len > 0 ) {
361
- to_copy = len < sg -> length ? len : sg -> length ;
359
+ while ( iov_iter_count ( to ) && copied < len ) {
360
+ to_copy = min_t ( unsigned long , iov_iter_count ( to ),
361
+ sg -> length - vec_off );
362
+ to_copy = min_t ( unsigned long , to_copy , len - copied ) ;
362
363
363
364
rds_stats_add (s_copy_to_user , to_copy );
365
+ ret = copy_page_to_iter (sg_page (sg ), sg -> offset + vec_off ,
366
+ to_copy , to );
367
+ if (ret != to_copy )
368
+ return - EFAULT ;
364
369
365
- for (copied = 0 ; copied < to_copy ; copied += chunk ) {
366
- offset = sg -> offset + copied ;
367
- chunk = offset < PAGE_SIZE ? PAGE_SIZE - offset : PAGE_SIZE ;
368
- if (copied + chunk > to_copy )
369
- chunk = to_copy - copied ;
370
+ vec_off += to_copy ;
371
+ copied += to_copy ;
370
372
371
- if (copy_page_to_iter (sg_page (sg ) + (offset >> PAGE_SHIFT ),
372
- offset & ~PAGE_MASK ,
373
- chunk , to ) != chunk )
374
- return - EFAULT ;
373
+ if (vec_off == sg -> length ) {
374
+ vec_off = 0 ;
375
+ sg ++ ;
375
376
}
376
-
377
- sg ++ ;
378
- len -= copied ;
379
377
}
380
378
381
- return saved_len ;
379
+ return copied ;
382
380
}
383
381
384
382
/*
0 commit comments