@@ -508,6 +508,72 @@ __be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes)
508
508
}
509
509
EXPORT_SYMBOL_GPL (xdr_reserve_space );
510
510
511
+ /**
512
+ * xdr_truncate_encode - truncate an encode buffer
513
+ * @xdr: pointer to xdr_stream
514
+ * @len: new length of buffer
515
+ *
516
+ * Truncates the xdr stream, so that xdr->buf->len == len,
517
+ * and xdr->p points at offset len from the start of the buffer, and
518
+ * head, tail, and page lengths are adjusted to correspond.
519
+ *
520
+ * If this means moving xdr->p to a different buffer, we assume that
521
+ * that the end pointer should be set to the end of the current page,
522
+ * except in the case of the head buffer when we assume the head
523
+ * buffer's current length represents the end of the available buffer.
524
+ *
525
+ * This is *not* safe to use on a buffer that already has inlined page
526
+ * cache pages (as in a zero-copy server read reply), except for the
527
+ * simple case of truncating from one position in the tail to another.
528
+ *
529
+ */
530
+ void xdr_truncate_encode (struct xdr_stream * xdr , size_t len )
531
+ {
532
+ struct xdr_buf * buf = xdr -> buf ;
533
+ struct kvec * head = buf -> head ;
534
+ struct kvec * tail = buf -> tail ;
535
+ int fraglen ;
536
+ int new , old ;
537
+
538
+ if (len > buf -> len ) {
539
+ WARN_ON_ONCE (1 );
540
+ return ;
541
+ }
542
+
543
+ fraglen = min_t (int , buf -> len - len , tail -> iov_len );
544
+ tail -> iov_len -= fraglen ;
545
+ buf -> len -= fraglen ;
546
+ if (tail -> iov_len && buf -> len == len ) {
547
+ xdr -> p = tail -> iov_base + tail -> iov_len ;
548
+ /* xdr->end, xdr->iov should be set already */
549
+ return ;
550
+ }
551
+ WARN_ON_ONCE (fraglen );
552
+ fraglen = min_t (int , buf -> len - len , buf -> page_len );
553
+ buf -> page_len -= fraglen ;
554
+ buf -> len -= fraglen ;
555
+
556
+ new = buf -> page_base + buf -> page_len ;
557
+ old = new + fraglen ;
558
+ xdr -> page_ptr -= (old >> PAGE_SHIFT ) - (new >> PAGE_SHIFT );
559
+
560
+ if (buf -> page_len && buf -> len == len ) {
561
+ xdr -> p = page_address (* xdr -> page_ptr );
562
+ xdr -> end = (void * )xdr -> p + PAGE_SIZE ;
563
+ xdr -> p = (void * )xdr -> p + (new % PAGE_SIZE );
564
+ /* xdr->iov should already be NULL */
565
+ return ;
566
+ }
567
+ if (fraglen )
568
+ xdr -> end = head -> iov_base + head -> iov_len ;
569
+ /* (otherwise assume xdr->end is already set) */
570
+ head -> iov_len = len ;
571
+ buf -> len = len ;
572
+ xdr -> p = head -> iov_base + head -> iov_len ;
573
+ xdr -> iov = buf -> head ;
574
+ }
575
+ EXPORT_SYMBOL (xdr_truncate_encode );
576
+
511
577
/**
512
578
* xdr_write_pages - Insert a list of pages into an XDR buffer for sending
513
579
* @xdr: pointer to xdr_stream
0 commit comments