diff options
author | Mike Marshall <hubcap@omnibond.com> | 2015-09-04 10:31:16 -0400 |
---|---|---|
committer | Mike Marshall <hubcap@omnibond.com> | 2015-10-03 11:44:00 -0400 |
commit | 4d1c44043b26e99dd70f379cdbe80c64f43fd123 (patch) | |
tree | 2e6f7e5c5bbbe931dcbccacdad5b1c476ec3b538 /fs/orangefs/pvfs2-bufmap.c | |
parent | 81b784b11ea65c5c591f4d963daed2111a1b4280 (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.c | 474 |
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 | /* | 510 | int 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 | */ | ||
523 | int 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 | */ | ||
657 | int 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 | */ | ||
762 | int 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 | */ |
881 | int pvfs_bufmap_copy_to_kernel_iovec(struct pvfs2_bufmap *bufmap, | 543 | int 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 | } |