aboutsummaryrefslogtreecommitdiffstats
path: root/fs/orangefs/pvfs2-bufmap.c
diff options
context:
space:
mode:
authorMike Marshall <hubcap@omnibond.com>2015-09-04 10:31:16 -0400
committerMike Marshall <hubcap@omnibond.com>2015-10-03 11:44:00 -0400
commit4d1c44043b26e99dd70f379cdbe80c64f43fd123 (patch)
tree2e6f7e5c5bbbe931dcbccacdad5b1c476ec3b538 /fs/orangefs/pvfs2-bufmap.c
parent81b784b11ea65c5c591f4d963daed2111a1b4280 (diff)
Orangefs: use iov_iter interface
replace opencoded pvfs_bufmap_copy_to_kernel_iovec, pvfs_bufmap_copy_to_user_iovec, pvfs_bufmap_copy_iovec_from_kernel, and pvfs_bufmap_copy_iovec_from_user with pvfs_bufmap_copy_to_iovec and pvfs_bufmap_copy_from_iovec, which both use the iov_iter interface. Signed-off-by: Mike Marshall <hubcap@omnibond.com>
Diffstat (limited to 'fs/orangefs/pvfs2-bufmap.c')
-rw-r--r--fs/orangefs/pvfs2-bufmap.c474
1 files changed, 33 insertions, 441 deletions
diff --git a/fs/orangefs/pvfs2-bufmap.c b/fs/orangefs/pvfs2-bufmap.c
index a439163f8d7c..e01e220fd5d7 100644
--- a/fs/orangefs/pvfs2-bufmap.c
+++ b/fs/orangefs/pvfs2-bufmap.c
@@ -507,468 +507,60 @@ void readdir_index_put(struct pvfs2_bufmap *bufmap, int buffer_index)
507 pvfs2_bufmap_unref(bufmap); 507 pvfs2_bufmap_unref(bufmap);
508} 508}
509 509
510/* 510int pvfs_bufmap_copy_from_iovec(struct pvfs2_bufmap *bufmap,
511 * pvfs_bufmap_copy_iovec_from_user() 511 struct iov_iter *iter,
512 * 512 int buffer_index,
513 * copies data from several user space address's in an iovec 513 size_t size)
514 * to a mapped buffer
515 *
516 * Note that the mapped buffer is a series of pages and therefore
517 * the copies have to be split by PAGE_SIZE bytes at a time.
518 * Note that this routine checks that summation of iov_len
519 * across all the elements of iov is equal to size.
520 *
521 * returns 0 on success, -errno on failure
522 */
523int pvfs_bufmap_copy_iovec_from_user(struct pvfs2_bufmap *bufmap,
524 int buffer_index,
525 const struct iovec *iov,
526 unsigned long nr_segs,
527 size_t size)
528{ 514{
529 size_t ret = 0;
530 size_t amt_copied = 0;
531 size_t cur_copy_size = 0;
532 unsigned int to_page_offset = 0;
533 unsigned int to_page_index = 0;
534 void *to_kaddr = NULL;
535 void __user *from_addr = NULL;
536 struct iovec *copied_iovec = NULL;
537 struct pvfs_bufmap_desc *to; 515 struct pvfs_bufmap_desc *to;
538 unsigned int seg; 516 struct page *page;
539 char *tmp_printer = NULL; 517 size_t copied;
540 int tmp_int = 0; 518 int i;
541
542 gossip_debug(GOSSIP_BUFMAP_DEBUG,
543 "pvfs_bufmap_copy_iovec_from_user: index %d, "
544 "size %zd\n",
545 buffer_index,
546 size);
547
548 to = &bufmap->desc_array[buffer_index];
549
550 /*
551 * copy the passed in iovec so that we can change some of its fields
552 */
553 copied_iovec = kmalloc_array(nr_segs,
554 sizeof(*copied_iovec),
555 PVFS2_BUFMAP_GFP_FLAGS);
556 if (copied_iovec == NULL)
557 return -ENOMEM;
558
559 memcpy(copied_iovec, iov, nr_segs * sizeof(*copied_iovec));
560 /*
561 * Go through each segment in the iovec and make sure that
562 * the summation of iov_len matches the given size.
563 */
564 for (seg = 0, amt_copied = 0; seg < nr_segs; seg++)
565 amt_copied += copied_iovec[seg].iov_len;
566 if (amt_copied != size) {
567 gossip_err(
568 "pvfs2_bufmap_copy_iovec_from_user: computed total ("
569 "%zd) is not equal to (%zd)\n",
570 amt_copied,
571 size);
572 kfree(copied_iovec);
573 return -EINVAL;
574 }
575
576 to_page_index = 0;
577 to_page_offset = 0;
578 amt_copied = 0;
579 seg = 0;
580 /*
581 * Go through each segment in the iovec and copy its
582 * buffer into the mapped buffer one page at a time though
583 */
584 while (amt_copied < size) {
585 struct iovec *iv = &copied_iovec[seg];
586 int inc_to_page_index;
587
588 if (iv->iov_len < (PAGE_SIZE - to_page_offset)) {
589 cur_copy_size =
590 PVFS_util_min(iv->iov_len, size - amt_copied);
591 seg++;
592 from_addr = iv->iov_base;
593 inc_to_page_index = 0;
594 } else if (iv->iov_len == (PAGE_SIZE - to_page_offset)) {
595 cur_copy_size =
596 PVFS_util_min(iv->iov_len, size - amt_copied);
597 seg++;
598 from_addr = iv->iov_base;
599 inc_to_page_index = 1;
600 } else {
601 cur_copy_size =
602 PVFS_util_min(PAGE_SIZE - to_page_offset,
603 size - amt_copied);
604 from_addr = iv->iov_base;
605 iv->iov_base += cur_copy_size;
606 iv->iov_len -= cur_copy_size;
607 inc_to_page_index = 1;
608 }
609 to_kaddr = pvfs2_kmap(to->page_array[to_page_index]);
610 ret =
611 copy_from_user(to_kaddr + to_page_offset,
612 from_addr,
613 cur_copy_size);
614 if (!PageReserved(to->page_array[to_page_index]))
615 SetPageDirty(to->page_array[to_page_index]);
616
617 if (!tmp_printer) {
618 tmp_printer = (char *)(to_kaddr + to_page_offset);
619 tmp_int += tmp_printer[0];
620 gossip_debug(GOSSIP_BUFMAP_DEBUG,
621 "First character (integer value) in pvfs_bufmap_copy_from_user: %d\n",
622 tmp_int);
623 }
624
625 pvfs2_kunmap(to->page_array[to_page_index]);
626 if (ret) {
627 gossip_err("Failed to copy data from user space\n");
628 kfree(copied_iovec);
629 return -EFAULT;
630 }
631
632 amt_copied += cur_copy_size;
633 if (inc_to_page_index) {
634 to_page_offset = 0;
635 to_page_index++;
636 } else {
637 to_page_offset += cur_copy_size;
638 }
639 }
640 kfree(copied_iovec);
641 return 0;
642}
643
644/*
645 * pvfs_bufmap_copy_iovec_from_kernel()
646 *
647 * copies data from several kernel space address's in an iovec
648 * to a mapped buffer
649 *
650 * Note that the mapped buffer is a series of pages and therefore
651 * the copies have to be split by PAGE_SIZE bytes at a time.
652 * Note that this routine checks that summation of iov_len
653 * across all the elements of iov is equal to size.
654 *
655 * returns 0 on success, -errno on failure
656 */
657int pvfs_bufmap_copy_iovec_from_kernel(struct pvfs2_bufmap *bufmap,
658 int buffer_index, const struct iovec *iov,
659 unsigned long nr_segs, size_t size)
660{
661 size_t amt_copied = 0;
662 size_t cur_copy_size = 0;
663 int to_page_index = 0;
664 void *to_kaddr = NULL;
665 void *from_kaddr = NULL;
666 struct kvec *iv = NULL;
667 struct iovec *copied_iovec = NULL;
668 struct pvfs_bufmap_desc *to;
669 unsigned int seg;
670 unsigned to_page_offset = 0;
671 519
672 gossip_debug(GOSSIP_BUFMAP_DEBUG, 520 gossip_debug(GOSSIP_BUFMAP_DEBUG,
673 "pvfs_bufmap_copy_iovec_from_kernel: index %d, " 521 "%s: buffer_index:%d: size:%lu:\n",
674 "size %zd\n", 522 __func__, buffer_index, size);
675 buffer_index,
676 size);
677 523
678 to = &bufmap->desc_array[buffer_index]; 524 to = &bufmap->desc_array[buffer_index];
679 /*
680 * copy the passed in iovec so that we can change some of its fields
681 */
682 copied_iovec = kmalloc_array(nr_segs,
683 sizeof(*copied_iovec),
684 PVFS2_BUFMAP_GFP_FLAGS);
685 if (copied_iovec == NULL)
686 return -ENOMEM;
687
688 memcpy(copied_iovec, iov, nr_segs * sizeof(*copied_iovec));
689 /*
690 * Go through each segment in the iovec and make sure that
691 * the summation of iov_len matches the given size.
692 */
693 for (seg = 0, amt_copied = 0; seg < nr_segs; seg++)
694 amt_copied += copied_iovec[seg].iov_len;
695 if (amt_copied != size) {
696 gossip_err("pvfs2_bufmap_copy_iovec_from_kernel: computed total(%zd) is not equal to (%zd)\n",
697 amt_copied,
698 size);
699 kfree(copied_iovec);
700 return -EINVAL;
701 }
702 525
703 to_page_index = 0; 526 for (i = 0; size; i++) {
704 amt_copied = 0; 527 page = to->page_array[i];
705 seg = 0; 528 copied = copy_page_from_iter(page, 0, PAGE_SIZE, iter);
706 to_page_offset = 0; 529 size -= copied;
707 /* 530 if ((copied == 0) && (size))
708 * Go through each segment in the iovec and copy its 531 break;
709 * buffer into the mapped buffer one page at a time though
710 */
711 while (amt_copied < size) {
712 int inc_to_page_index;
713
714 iv = (struct kvec *) &copied_iovec[seg];
715
716 if (iv->iov_len < (PAGE_SIZE - to_page_offset)) {
717 cur_copy_size =
718 PVFS_util_min(iv->iov_len, size - amt_copied);
719 seg++;
720 from_kaddr = iv->iov_base;
721 inc_to_page_index = 0;
722 } else if (iv->iov_len == (PAGE_SIZE - to_page_offset)) {
723 cur_copy_size =
724 PVFS_util_min(iv->iov_len, size - amt_copied);
725 seg++;
726 from_kaddr = iv->iov_base;
727 inc_to_page_index = 1;
728 } else {
729 cur_copy_size =
730 PVFS_util_min(PAGE_SIZE - to_page_offset,
731 size - amt_copied);
732 from_kaddr = iv->iov_base;
733 iv->iov_base += cur_copy_size;
734 iv->iov_len -= cur_copy_size;
735 inc_to_page_index = 1;
736 }
737 to_kaddr = pvfs2_kmap(to->page_array[to_page_index]);
738 memcpy(to_kaddr + to_page_offset, from_kaddr, cur_copy_size);
739 if (!PageReserved(to->page_array[to_page_index]))
740 SetPageDirty(to->page_array[to_page_index]);
741 pvfs2_kunmap(to->page_array[to_page_index]);
742 amt_copied += cur_copy_size;
743 if (inc_to_page_index) {
744 to_page_offset = 0;
745 to_page_index++;
746 } else {
747 to_page_offset += cur_copy_size;
748 }
749 }
750 kfree(copied_iovec);
751 return 0;
752}
753
754/*
755 * pvfs_bufmap_copy_to_user_iovec()
756 *
757 * copies data to several user space address's in an iovec
758 * from a mapped buffer
759 *
760 * returns 0 on success, -errno on failure
761 */
762int pvfs_bufmap_copy_to_user_iovec(struct pvfs2_bufmap *bufmap,
763 int buffer_index, const struct iovec *iov,
764 unsigned long nr_segs, size_t size)
765{
766 size_t ret = 0;
767 size_t amt_copied = 0;
768 size_t cur_copy_size = 0;
769 int from_page_index = 0;
770 void *from_kaddr = NULL;
771 void __user *to_addr = NULL;
772 struct iovec *copied_iovec = NULL;
773 struct pvfs_bufmap_desc *from;
774 unsigned int seg;
775 unsigned from_page_offset = 0;
776 char *tmp_printer = NULL;
777 int tmp_int = 0;
778
779 gossip_debug(GOSSIP_BUFMAP_DEBUG,
780 "pvfs_bufmap_copy_to_user_iovec: index %d, size %zd\n",
781 buffer_index,
782 size);
783
784 from = &bufmap->desc_array[buffer_index];
785 /*
786 * copy the passed in iovec so that we can change some of its fields
787 */
788 copied_iovec = kmalloc_array(nr_segs,
789 sizeof(*copied_iovec),
790 PVFS2_BUFMAP_GFP_FLAGS);
791 if (copied_iovec == NULL)
792 return -ENOMEM;
793
794 memcpy(copied_iovec, iov, nr_segs * sizeof(*copied_iovec));
795 /*
796 * Go through each segment in the iovec and make sure that
797 * the summation of iov_len is greater than the given size.
798 */
799 for (seg = 0, amt_copied = 0; seg < nr_segs; seg++)
800 amt_copied += copied_iovec[seg].iov_len;
801 if (amt_copied < size) {
802 gossip_err("pvfs2_bufmap_copy_to_user_iovec: computed total (%zd) is less than (%zd)\n",
803 amt_copied,
804 size);
805 kfree(copied_iovec);
806 return -EINVAL;
807 } 532 }
808 533
809 from_page_index = 0; 534 return size ? -EFAULT : 0;
810 amt_copied = 0;
811 seg = 0;
812 from_page_offset = 0;
813 /*
814 * Go through each segment in the iovec and copy from the mapper buffer,
815 * but make sure that we do so one page at a time.
816 */
817 while (amt_copied < size) {
818 struct iovec *iv = &copied_iovec[seg];
819 int inc_from_page_index;
820
821 if (iv->iov_len < (PAGE_SIZE - from_page_offset)) {
822 cur_copy_size =
823 PVFS_util_min(iv->iov_len, size - amt_copied);
824 seg++;
825 to_addr = iv->iov_base;
826 inc_from_page_index = 0;
827 } else if (iv->iov_len == (PAGE_SIZE - from_page_offset)) {
828 cur_copy_size =
829 PVFS_util_min(iv->iov_len, size - amt_copied);
830 seg++;
831 to_addr = iv->iov_base;
832 inc_from_page_index = 1;
833 } else {
834 cur_copy_size =
835 PVFS_util_min(PAGE_SIZE - from_page_offset,
836 size - amt_copied);
837 to_addr = iv->iov_base;
838 iv->iov_base += cur_copy_size;
839 iv->iov_len -= cur_copy_size;
840 inc_from_page_index = 1;
841 }
842 from_kaddr = pvfs2_kmap(from->page_array[from_page_index]);
843 if (!tmp_printer) {
844 tmp_printer = (char *)(from_kaddr + from_page_offset);
845 tmp_int += tmp_printer[0];
846 gossip_debug(GOSSIP_BUFMAP_DEBUG,
847 "First character (integer value) in pvfs_bufmap_copy_to_user_iovec: %d\n",
848 tmp_int);
849 }
850 ret =
851 copy_to_user(to_addr,
852 from_kaddr + from_page_offset,
853 cur_copy_size);
854 pvfs2_kunmap(from->page_array[from_page_index]);
855 if (ret) {
856 gossip_err("Failed to copy data to user space\n");
857 kfree(copied_iovec);
858 return -EFAULT;
859 }
860 535
861 amt_copied += cur_copy_size;
862 if (inc_from_page_index) {
863 from_page_offset = 0;
864 from_page_index++;
865 } else {
866 from_page_offset += cur_copy_size;
867 }
868 }
869 kfree(copied_iovec);
870 return 0;
871} 536}
872 537
873/* 538/*
874 * pvfs_bufmap_copy_to_kernel_iovec() 539 * Iterate through the array of pages containing the bytes from
540 * a file being read.
875 * 541 *
876 * copies data to several kernel space address's in an iovec
877 * from a mapped buffer
878 *
879 * returns 0 on success, -errno on failure
880 */ 542 */
881int pvfs_bufmap_copy_to_kernel_iovec(struct pvfs2_bufmap *bufmap, 543int pvfs_bufmap_copy_to_iovec(struct pvfs2_bufmap *bufmap,
882 int buffer_index, const struct iovec *iov, 544 struct iov_iter *iter,
883 unsigned long nr_segs, size_t size) 545 int buffer_index)
884{ 546{
885 size_t amt_copied = 0;
886 size_t cur_copy_size = 0;
887 int from_page_index = 0;
888 void *from_kaddr = NULL;
889 void *to_kaddr = NULL;
890 struct kvec *iv;
891 struct iovec *copied_iovec = NULL;
892 struct pvfs_bufmap_desc *from; 547 struct pvfs_bufmap_desc *from;
893 unsigned int seg; 548 struct page *page;
894 unsigned int from_page_offset = 0; 549 int i;
550 size_t written;
895 551
896 gossip_debug(GOSSIP_BUFMAP_DEBUG, 552 gossip_debug(GOSSIP_BUFMAP_DEBUG,
897 "pvfs_bufmap_copy_to_kernel_iovec: index %d, size %zd\n", 553 "%s: buffer_index:%d: iov_iter_count(iter):%lu:\n",
898 buffer_index, 554 __func__, buffer_index, iov_iter_count(iter));
899 size);
900 555
901 from = &bufmap->desc_array[buffer_index]; 556 from = &bufmap->desc_array[buffer_index];
902 /*
903 * copy the passed in iovec so that we can change some of its fields
904 */
905 copied_iovec = kmalloc_array(nr_segs,
906 sizeof(*copied_iovec),
907 PVFS2_BUFMAP_GFP_FLAGS);
908 if (copied_iovec == NULL)
909 return -ENOMEM;
910 557
911 memcpy(copied_iovec, iov, nr_segs * sizeof(*copied_iovec)); 558 for (i = 0; iov_iter_count(iter); i++) {
912 /* 559 page = from->page_array[i];
913 * Go through each segment in the iovec and make sure that 560 written = copy_page_to_iter(page, 0, PAGE_SIZE, iter);
914 * the summation of iov_len is greater than the given size. 561 if ((written == 0) && (iov_iter_count(iter)))
915 */ 562 break;
916 for (seg = 0, amt_copied = 0; seg < nr_segs; seg++)
917 amt_copied += copied_iovec[seg].iov_len;
918
919 if (amt_copied < size) {
920 gossip_err("pvfs2_bufmap_copy_to_kernel_iovec: computed total (%zd) is less than (%zd)\n",
921 amt_copied,
922 size);
923 kfree(copied_iovec);
924 return -EINVAL;
925 } 563 }
926 564
927 from_page_index = 0; 565 return iov_iter_count(iter) ? -EFAULT : 0;
928 amt_copied = 0;
929 seg = 0;
930 from_page_offset = 0;
931 /*
932 * Go through each segment in the iovec and copy from the mapper buffer,
933 * but make sure that we do so one page at a time.
934 */
935 while (amt_copied < size) {
936 int inc_from_page_index;
937
938 iv = (struct kvec *) &copied_iovec[seg];
939
940 if (iv->iov_len < (PAGE_SIZE - from_page_offset)) {
941 cur_copy_size =
942 PVFS_util_min(iv->iov_len, size - amt_copied);
943 seg++;
944 to_kaddr = iv->iov_base;
945 inc_from_page_index = 0;
946 } else if (iv->iov_len == (PAGE_SIZE - from_page_offset)) {
947 cur_copy_size =
948 PVFS_util_min(iv->iov_len, size - amt_copied);
949 seg++;
950 to_kaddr = iv->iov_base;
951 inc_from_page_index = 1;
952 } else {
953 cur_copy_size =
954 PVFS_util_min(PAGE_SIZE - from_page_offset,
955 size - amt_copied);
956 to_kaddr = iv->iov_base;
957 iv->iov_base += cur_copy_size;
958 iv->iov_len -= cur_copy_size;
959 inc_from_page_index = 1;
960 }
961 from_kaddr = pvfs2_kmap(from->page_array[from_page_index]);
962 memcpy(to_kaddr, from_kaddr + from_page_offset, cur_copy_size);
963 pvfs2_kunmap(from->page_array[from_page_index]);
964 amt_copied += cur_copy_size;
965 if (inc_from_page_index) {
966 from_page_offset = 0;
967 from_page_index++;
968 } else {
969 from_page_offset += cur_copy_size;
970 }
971 }
972 kfree(copied_iovec);
973 return 0;
974} 566}