@@ -752,19 +752,32 @@ struct pfn_reader_user {
752
752
* neither
753
753
*/
754
754
int locked ;
755
+
756
+ /* The following are only valid if file != NULL. */
757
+ struct file * file ;
758
+ struct folio * * ufolios ;
759
+ size_t ufolios_len ;
760
+ unsigned long ufolios_offset ;
761
+ struct folio * * ufolios_next ;
755
762
};
756
763
757
764
static void pfn_reader_user_init (struct pfn_reader_user * user ,
758
765
struct iopt_pages * pages )
759
766
{
760
767
user -> upages = NULL ;
768
+ user -> upages_len = 0 ;
761
769
user -> upages_start = 0 ;
762
770
user -> upages_end = 0 ;
763
771
user -> locked = -1 ;
764
-
765
772
user -> gup_flags = FOLL_LONGTERM ;
766
773
if (pages -> writable )
767
774
user -> gup_flags |= FOLL_WRITE ;
775
+
776
+ user -> file = (pages -> type == IOPT_ADDRESS_FILE ) ? pages -> file : NULL ;
777
+ user -> ufolios = NULL ;
778
+ user -> ufolios_len = 0 ;
779
+ user -> ufolios_next = NULL ;
780
+ user -> ufolios_offset = 0 ;
768
781
}
769
782
770
783
static void pfn_reader_user_destroy (struct pfn_reader_user * user ,
@@ -773,13 +786,67 @@ static void pfn_reader_user_destroy(struct pfn_reader_user *user,
773
786
if (user -> locked != -1 ) {
774
787
if (user -> locked )
775
788
mmap_read_unlock (pages -> source_mm );
776
- if (pages -> source_mm != current -> mm )
789
+ if (! user -> file && pages -> source_mm != current -> mm )
777
790
mmput (pages -> source_mm );
778
791
user -> locked = -1 ;
779
792
}
780
793
781
794
kfree (user -> upages );
782
795
user -> upages = NULL ;
796
+ kfree (user -> ufolios );
797
+ user -> ufolios = NULL ;
798
+ }
799
+
800
+ static long pin_memfd_pages (struct pfn_reader_user * user , unsigned long start ,
801
+ unsigned long npages )
802
+ {
803
+ unsigned long i ;
804
+ unsigned long offset ;
805
+ unsigned long npages_out = 0 ;
806
+ struct page * * upages = user -> upages ;
807
+ unsigned long end = start + (npages << PAGE_SHIFT ) - 1 ;
808
+ long nfolios = user -> ufolios_len / sizeof (* user -> ufolios );
809
+
810
+ /*
811
+ * todo: memfd_pin_folios should return the last pinned offset so
812
+ * we can compute npages pinned, and avoid looping over folios here
813
+ * if upages == NULL.
814
+ */
815
+ nfolios = memfd_pin_folios (user -> file , start , end , user -> ufolios ,
816
+ nfolios , & offset );
817
+ if (nfolios <= 0 )
818
+ return nfolios ;
819
+
820
+ offset >>= PAGE_SHIFT ;
821
+ user -> ufolios_next = user -> ufolios ;
822
+ user -> ufolios_offset = offset ;
823
+
824
+ for (i = 0 ; i < nfolios ; i ++ ) {
825
+ struct folio * folio = user -> ufolios [i ];
826
+ unsigned long nr = folio_nr_pages (folio );
827
+ unsigned long npin = min (nr - offset , npages );
828
+
829
+ npages -= npin ;
830
+ npages_out += npin ;
831
+
832
+ if (upages ) {
833
+ if (npin == 1 ) {
834
+ * upages ++ = folio_page (folio , offset );
835
+ } else {
836
+ int rc = folio_add_pins (folio , npin - 1 );
837
+
838
+ if (rc )
839
+ return rc ;
840
+
841
+ while (npin -- )
842
+ * upages ++ = folio_page (folio , offset ++ );
843
+ }
844
+ }
845
+
846
+ offset = 0 ;
847
+ }
848
+
849
+ return npages_out ;
783
850
}
784
851
785
852
static int pfn_reader_user_pin (struct pfn_reader_user * user ,
@@ -788,48 +855,60 @@ static int pfn_reader_user_pin(struct pfn_reader_user *user,
788
855
unsigned long last_index )
789
856
{
790
857
bool remote_mm = pages -> source_mm != current -> mm ;
791
- unsigned long npages ;
858
+ unsigned long npages = last_index - start_index + 1 ;
859
+ unsigned long start ;
860
+ unsigned long unum ;
792
861
uintptr_t uptr ;
793
862
long rc ;
794
863
795
864
if (IS_ENABLED (CONFIG_IOMMUFD_TEST ) &&
796
865
WARN_ON (last_index < start_index ))
797
866
return - EINVAL ;
798
867
799
- if (!user -> upages ) {
868
+ if (!user -> file && ! user -> upages ) {
800
869
/* All undone in pfn_reader_destroy() */
801
- user -> upages_len =
802
- (last_index - start_index + 1 ) * sizeof (* user -> upages );
870
+ user -> upages_len = npages * sizeof (* user -> upages );
803
871
user -> upages = temp_kmalloc (& user -> upages_len , NULL , 0 );
804
872
if (!user -> upages )
805
873
return - ENOMEM ;
806
874
}
807
875
876
+ if (user -> file && !user -> ufolios ) {
877
+ user -> ufolios_len = npages * sizeof (* user -> ufolios );
878
+ user -> ufolios = temp_kmalloc (& user -> ufolios_len , NULL , 0 );
879
+ if (!user -> ufolios )
880
+ return - ENOMEM ;
881
+ }
882
+
808
883
if (user -> locked == -1 ) {
809
884
/*
810
885
* The majority of usages will run the map task within the mm
811
886
* providing the pages, so we can optimize into
812
887
* get_user_pages_fast()
813
888
*/
814
- if (remote_mm ) {
889
+ if (! user -> file && remote_mm ) {
815
890
if (!mmget_not_zero (pages -> source_mm ))
816
891
return - EFAULT ;
817
892
}
818
893
user -> locked = 0 ;
819
894
}
820
895
821
- npages = min_t ( unsigned long , last_index - start_index + 1 ,
822
- user -> upages_len / sizeof (* user -> upages ) );
823
-
896
+ unum = user -> file ? user -> ufolios_len / sizeof ( * user -> ufolios ) :
897
+ user -> upages_len / sizeof (* user -> upages );
898
+ npages = min_t ( unsigned long , npages , unum );
824
899
825
900
if (iommufd_should_fail ())
826
901
return - EFAULT ;
827
902
828
- uptr = (uintptr_t )(pages -> uptr + start_index * PAGE_SIZE );
829
- if (!remote_mm )
903
+ if (user -> file ) {
904
+ start = pages -> start + (start_index * PAGE_SIZE );
905
+ rc = pin_memfd_pages (user , start , npages );
906
+ } else if (!remote_mm ) {
907
+ uptr = (uintptr_t )(pages -> uptr + start_index * PAGE_SIZE );
830
908
rc = pin_user_pages_fast (uptr , npages , user -> gup_flags ,
831
909
user -> upages );
832
- else {
910
+ } else {
911
+ uptr = (uintptr_t )(pages -> uptr + start_index * PAGE_SIZE );
833
912
if (!user -> locked ) {
834
913
mmap_read_lock (pages -> source_mm );
835
914
user -> locked = 1 ;
@@ -887,7 +966,8 @@ static int update_mm_locked_vm(struct iopt_pages *pages, unsigned long npages,
887
966
mmap_read_unlock (pages -> source_mm );
888
967
user -> locked = 0 ;
889
968
/* If we had the lock then we also have a get */
890
- } else if ((!user || !user -> upages ) &&
969
+
970
+ } else if ((!user || (!user -> upages && !user -> ufolios )) &&
891
971
pages -> source_mm != current -> mm ) {
892
972
if (!mmget_not_zero (pages -> source_mm ))
893
973
return - EINVAL ;
@@ -1068,8 +1148,15 @@ static int pfn_reader_fill_span(struct pfn_reader *pfns)
1068
1148
1069
1149
npages = user -> upages_end - start_index ;
1070
1150
start_index -= user -> upages_start ;
1071
- batch_from_pages (& pfns -> batch , user -> upages + start_index , npages );
1072
- return 0 ;
1151
+ rc = 0 ;
1152
+
1153
+ if (!user -> file )
1154
+ batch_from_pages (& pfns -> batch , user -> upages + start_index ,
1155
+ npages );
1156
+ else
1157
+ rc = batch_from_folios (& pfns -> batch , & user -> ufolios_next ,
1158
+ & user -> ufolios_offset , npages );
1159
+ return rc ;
1073
1160
}
1074
1161
1075
1162
static bool pfn_reader_done (struct pfn_reader * pfns )
@@ -1151,7 +1238,14 @@ static void pfn_reader_release_pins(struct pfn_reader *pfns)
1151
1238
unsigned long start_index = pfns -> batch_end_index -
1152
1239
user -> upages_start ;
1153
1240
1154
- unpin_user_pages (user -> upages + start_index , npages );
1241
+ if (!user -> file ) {
1242
+ unpin_user_pages (user -> upages + start_index , npages );
1243
+ } else {
1244
+ long n = user -> ufolios_len / sizeof (* user -> ufolios );
1245
+
1246
+ unpin_folios (user -> ufolios_next ,
1247
+ user -> ufolios + n - user -> ufolios_next );
1248
+ }
1155
1249
iopt_pages_sub_npinned (pages , npages );
1156
1250
user -> upages_end = pfns -> batch_end_index ;
1157
1251
}
0 commit comments