Skip to content

Commit fb44d8b

Browse files
Hakon-BuggeSomasundaram Krishnasamy
authored andcommitted
Revert "net/rds: make copy_page_from_iter and copy_page_to_iter stay within page boundaries (WORKAROUND!)"
This reverts commit 8401073. This workaround is not needed when zero-order allocations are used together with the device's SGE capability. So, reverting this commit in order to apply the series from bug 27339270. Signed-off-by: Håkon Bugge <[email protected]> Reviewed-by: Wei Lin Guay <[email protected]> Orabug: 27339270 Signed-off-by: Somasundaram Krishnasamy <[email protected]>
1 parent b01acfe commit fb44d8b

File tree

2 files changed

+59
-61
lines changed

2 files changed

+59
-61
lines changed

net/rds/ib_recv.c

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -785,40 +785,40 @@ int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
785785
struct rds_ib_connection *ic = inc->i_conn->c_transport_data;
786786
struct rds_ib_incoming *ibinc;
787787
struct rds_page_frag *frag;
788-
size_t len, saved_len, to_copy, copied, offset, chunk;
788+
unsigned long to_copy;
789+
unsigned long frag_off = 0;
790+
int copied = 0;
791+
int ret;
792+
u32 len;
789793

790794
ibinc = container_of(inc, struct rds_ib_incoming, ii_inc);
791795
frag = list_entry(ibinc->ii_frags.next, struct rds_page_frag, f_item);
792-
793796
len = be32_to_cpu(inc->i_hdr.h_len);
794-
if (iov_iter_count(to) < len)
795-
len = iov_iter_count(to);
796-
797-
saved_len = len;
798797

799-
while (len > 0) {
800-
to_copy = len < ic->i_frag_sz ? len : ic->i_frag_sz;
798+
while (iov_iter_count(to) && copied < len) {
799+
if (frag_off == ic->i_frag_sz) {
800+
frag = list_entry(frag->f_item.next,
801+
struct rds_page_frag, f_item);
802+
frag_off = 0;
803+
}
804+
to_copy = min_t(unsigned long, iov_iter_count(to),
805+
ic->i_frag_sz - frag_off);
806+
to_copy = min_t(unsigned long, to_copy, len - copied);
801807

808+
/* XXX needs + offset for multiple recvs per page */
802809
rds_stats_add(s_copy_to_user, to_copy);
810+
ret = copy_page_to_iter(sg_page(&frag->f_sg),
811+
frag->f_sg.offset + frag_off,
812+
to_copy,
813+
to);
814+
if (ret != to_copy)
815+
return -EFAULT;
803816

804-
for (copied = 0; copied < to_copy; copied += chunk) {
805-
offset = frag->f_sg.offset + copied;
806-
chunk = offset < PAGE_SIZE ? PAGE_SIZE - offset : PAGE_SIZE;
807-
if (copied + chunk > to_copy)
808-
chunk = to_copy - copied;
809-
810-
if (copy_page_to_iter(sg_page(&frag->f_sg) + (offset >> PAGE_SHIFT),
811-
offset & ~PAGE_MASK,
812-
chunk, to) != chunk)
813-
return -EFAULT;
814-
}
815-
816-
frag = list_entry(frag->f_item.next,
817-
struct rds_page_frag, f_item);
818-
len -= copied;
817+
frag_off += to_copy;
818+
copied += to_copy;
819819
}
820820

821-
return saved_len;
821+
return copied;
822822
}
823823

824824
/* ic starts out kzalloc()ed */

net/rds/message.c

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,9 @@ struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents)
295295
int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from,
296296
gfp_t gfp, bool large_page)
297297
{
298+
unsigned long to_copy, nbytes;
299+
unsigned long sg_off;
298300
struct scatterlist *sg;
299-
size_t to_copy, copied, offset, chunk;
300301
int ret = 0;
301302

302303
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,
305306
* now allocate and copy in the data payload.
306307
*/
307308
sg = rm->data.op_sg;
309+
sg_off = 0; /* Dear gcc, sg->page will be null from kzalloc. */
308310

309311
while (iov_iter_count(from)) {
310312
if (!sg_page(sg)) {
@@ -316,69 +318,65 @@ int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from,
316318
if (ret)
317319
return ret;
318320
rm->data.op_nents++;
321+
sg_off = 0;
319322
}
320323

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);
324326

325327
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;
326332

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;
332334

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++;
340337
}
341338

342-
return 0;
339+
return ret;
343340
}
344341

345342
int rds_message_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
346343
{
347344
struct rds_message *rm;
348345
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;
350351

351352
rm = container_of(inc, struct rds_message, m_inc);
352353
len = be32_to_cpu(rm->m_inc.i_hdr.h_len);
353-
if (iov_iter_count(to) < len)
354-
len = iov_iter_count(to);
355354

356355
sg = rm->data.op_sg;
356+
vec_off = 0;
357+
copied = 0;
357358

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);
362363

363364
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;
364369

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;
370372

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++;
375376
}
376-
377-
sg++;
378-
len -= copied;
379377
}
380378

381-
return saved_len;
379+
return copied;
382380
}
383381

384382
/*

0 commit comments

Comments
 (0)