@@ -63,6 +63,17 @@ struct virtio_vsock {
6363
6464 u32 guest_cid ;
6565 bool seqpacket_allow ;
66+
67+ /* These fields are used only in tx path in function
68+ * 'virtio_transport_send_pkt_work()', so to save
69+ * stack space in it, place both of them here. Each
70+ * pointer from 'out_sgs' points to the corresponding
71+ * element in 'out_bufs' - this is initialized in
72+ * 'virtio_vsock_probe()'. Both fields are protected
73+ * by 'tx_lock'. +1 is needed for packet header.
74+ */
75+ struct scatterlist * out_sgs [MAX_SKB_FRAGS + 1 ];
76+ struct scatterlist out_bufs [MAX_SKB_FRAGS + 1 ];
6677};
6778
6879static u32 virtio_transport_get_local_cid (void )
@@ -100,8 +111,8 @@ virtio_transport_send_pkt_work(struct work_struct *work)
100111 vq = vsock -> vqs [VSOCK_VQ_TX ];
101112
102113 for (;;) {
103- struct scatterlist hdr , buf , * sgs [2 ];
104114 int ret , in_sg = 0 , out_sg = 0 ;
115+ struct scatterlist * * sgs ;
105116 struct sk_buff * skb ;
106117 bool reply ;
107118
@@ -111,12 +122,43 @@ virtio_transport_send_pkt_work(struct work_struct *work)
111122
112123 virtio_transport_deliver_tap_pkt (skb );
113124 reply = virtio_vsock_skb_reply (skb );
114-
115- sg_init_one (& hdr , virtio_vsock_hdr (skb ), sizeof (* virtio_vsock_hdr (skb )));
116- sgs [out_sg ++ ] = & hdr ;
117- if (skb -> len > 0 ) {
118- sg_init_one (& buf , skb -> data , skb -> len );
119- sgs [out_sg ++ ] = & buf ;
125+ sgs = vsock -> out_sgs ;
126+ sg_init_one (sgs [out_sg ], virtio_vsock_hdr (skb ),
127+ sizeof (* virtio_vsock_hdr (skb )));
128+ out_sg ++ ;
129+
130+ if (!skb_is_nonlinear (skb )) {
131+ if (skb -> len > 0 ) {
132+ sg_init_one (sgs [out_sg ], skb -> data , skb -> len );
133+ out_sg ++ ;
134+ }
135+ } else {
136+ struct skb_shared_info * si ;
137+ int i ;
138+
139+ /* If skb is nonlinear, then its buffer must contain
140+ * only header and nothing more. Data is stored in
141+ * the fragged part.
142+ */
143+ WARN_ON_ONCE (skb_headroom (skb ) != sizeof (* virtio_vsock_hdr (skb )));
144+
145+ si = skb_shinfo (skb );
146+
147+ for (i = 0 ; i < si -> nr_frags ; i ++ ) {
148+ skb_frag_t * skb_frag = & si -> frags [i ];
149+ void * va ;
150+
151+ /* We will use 'page_to_virt()' for the userspace page
152+ * here, because virtio or dma-mapping layers will call
153+ * 'virt_to_phys()' later to fill the buffer descriptor.
154+ * We don't touch memory at "virtual" address of this page.
155+ */
156+ va = page_to_virt (skb_frag -> bv_page );
157+ sg_init_one (sgs [out_sg ],
158+ va + skb_frag -> bv_offset ,
159+ skb_frag -> bv_len );
160+ out_sg ++ ;
161+ }
120162 }
121163
122164 ret = virtqueue_add_sgs (vq , sgs , out_sg , in_sg , skb , GFP_KERNEL );
@@ -621,6 +663,7 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
621663{
622664 struct virtio_vsock * vsock = NULL ;
623665 int ret ;
666+ int i ;
624667
625668 ret = mutex_lock_interruptible (& the_virtio_vsock_mutex );
626669 if (ret )
@@ -663,6 +706,9 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
663706 if (ret < 0 )
664707 goto out ;
665708
709+ for (i = 0 ; i < ARRAY_SIZE (vsock -> out_sgs ); i ++ )
710+ vsock -> out_sgs [i ] = & vsock -> out_bufs [i ];
711+
666712 rcu_assign_pointer (the_virtio_vsock , vsock );
667713
668714 mutex_unlock (& the_virtio_vsock_mutex );
0 commit comments