@@ -9845,30 +9845,18 @@ static int io_buffer_account_pin(struct io_ring_ctx *ctx, struct page **pages,
98459845 return ret ;
98469846}
98479847
9848- static int io_sqe_buffer_register (struct io_ring_ctx * ctx , struct iovec * iov ,
9849- struct io_mapped_ubuf * * pimu ,
9850- struct page * * last_hpage )
9848+ static struct page * * io_pin_pages (unsigned long ubuf , unsigned long len ,
9849+ int * npages )
98519850{
9852- struct io_mapped_ubuf * imu = NULL ;
9851+ unsigned long start , end , nr_pages ;
98539852 struct vm_area_struct * * vmas = NULL ;
98549853 struct page * * pages = NULL ;
9855- unsigned long off , start , end , ubuf ;
9856- size_t size ;
9857- int ret , pret , nr_pages , i ;
9858-
9859- if (!iov -> iov_base ) {
9860- * pimu = ctx -> dummy_ubuf ;
9861- return 0 ;
9862- }
9854+ int i , pret , ret = - ENOMEM ;
98639855
9864- ubuf = (unsigned long ) iov -> iov_base ;
9865- end = (ubuf + iov -> iov_len + PAGE_SIZE - 1 ) >> PAGE_SHIFT ;
9856+ end = (ubuf + len + PAGE_SIZE - 1 ) >> PAGE_SHIFT ;
98669857 start = ubuf >> PAGE_SHIFT ;
98679858 nr_pages = end - start ;
98689859
9869- * pimu = NULL ;
9870- ret = - ENOMEM ;
9871-
98729860 pages = kvmalloc_array (nr_pages , sizeof (struct page * ), GFP_KERNEL );
98739861 if (!pages )
98749862 goto done ;
@@ -9878,10 +9866,6 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
98789866 if (!vmas )
98799867 goto done ;
98809868
9881- imu = kvmalloc (struct_size (imu , bvec , nr_pages ), GFP_KERNEL );
9882- if (!imu )
9883- goto done ;
9884-
98859869 ret = 0 ;
98869870 mmap_read_lock (current -> mm );
98879871 pret = pin_user_pages (ubuf , nr_pages , FOLL_WRITE | FOLL_LONGTERM ,
@@ -9899,6 +9883,7 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
98999883 break ;
99009884 }
99019885 }
9886+ * npages = nr_pages ;
99029887 } else {
99039888 ret = pret < 0 ? pret : - EFAULT ;
99049889 }
@@ -9912,14 +9897,53 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
99129897 unpin_user_pages (pages , pret );
99139898 goto done ;
99149899 }
9900+ ret = 0 ;
9901+ done :
9902+ kvfree (vmas );
9903+ if (ret < 0 ) {
9904+ kvfree (pages );
9905+ pages = ERR_PTR (ret );
9906+ }
9907+ return pages ;
9908+ }
99159909
9916- ret = io_buffer_account_pin (ctx , pages , pret , imu , last_hpage );
9910+ static int io_sqe_buffer_register (struct io_ring_ctx * ctx , struct iovec * iov ,
9911+ struct io_mapped_ubuf * * pimu ,
9912+ struct page * * last_hpage )
9913+ {
9914+ struct io_mapped_ubuf * imu = NULL ;
9915+ struct page * * pages = NULL ;
9916+ unsigned long off ;
9917+ size_t size ;
9918+ int ret , nr_pages , i ;
9919+
9920+ if (!iov -> iov_base ) {
9921+ * pimu = ctx -> dummy_ubuf ;
9922+ return 0 ;
9923+ }
9924+
9925+ * pimu = NULL ;
9926+ ret = - ENOMEM ;
9927+
9928+ pages = io_pin_pages ((unsigned long ) iov -> iov_base , iov -> iov_len ,
9929+ & nr_pages );
9930+ if (IS_ERR (pages )) {
9931+ ret = PTR_ERR (pages );
9932+ pages = NULL ;
9933+ goto done ;
9934+ }
9935+
9936+ imu = kvmalloc (struct_size (imu , bvec , nr_pages ), GFP_KERNEL );
9937+ if (!imu )
9938+ goto done ;
9939+
9940+ ret = io_buffer_account_pin (ctx , pages , nr_pages , imu , last_hpage );
99179941 if (ret ) {
9918- unpin_user_pages (pages , pret );
9942+ unpin_user_pages (pages , nr_pages );
99199943 goto done ;
99209944 }
99219945
9922- off = ubuf & ~PAGE_MASK ;
9946+ off = ( unsigned long ) iov -> iov_base & ~PAGE_MASK ;
99239947 size = iov -> iov_len ;
99249948 for (i = 0 ; i < nr_pages ; i ++ ) {
99259949 size_t vec_len ;
@@ -9932,16 +9956,15 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
99329956 size -= vec_len ;
99339957 }
99349958 /* store original address for later verification */
9935- imu -> ubuf = ubuf ;
9936- imu -> ubuf_end = ubuf + iov -> iov_len ;
9959+ imu -> ubuf = ( unsigned long ) iov -> iov_base ;
9960+ imu -> ubuf_end = imu -> ubuf + iov -> iov_len ;
99379961 imu -> nr_bvecs = nr_pages ;
99389962 * pimu = imu ;
99399963 ret = 0 ;
99409964done :
99419965 if (ret )
99429966 kvfree (imu );
99439967 kvfree (pages );
9944- kvfree (vmas );
99459968 return ret ;
99469969}
99479970
0 commit comments