1. 08 10月, 2019 1 次提交
    • D
      xen-netfront: do not use ~0U as error return value for xennet_fill_frags() · a1afd826
      Dongli Zhang 提交于
      [ Upstream commit a761129e3625688310aecf26e1be9e98e85f8eb5 ]
      
      xennet_fill_frags() uses ~0U as return value when the sk_buff is not able
      to cache extra fragments. This is incorrect because the return type of
      xennet_fill_frags() is RING_IDX and 0xffffffff is an expected value for
      ring buffer index.
      
      In the situation when the rsp_cons is approaching 0xffffffff, the return
      value of xennet_fill_frags() may become 0xffffffff which xennet_poll() (the
      caller) would regard as error. As a result, queue->rx.rsp_cons is set
      incorrectly because it is updated only when there is error. If there is no
      error, xennet_poll() would be responsible to update queue->rx.rsp_cons.
      Finally, queue->rx.rsp_cons would point to the rx ring buffer entries whose
      queue->rx_skbs[i] and queue->grant_rx_ref[i] are already cleared to NULL.
      This leads to NULL pointer access in the next iteration to process rx ring
      buffer entries.
      
      The symptom is similar to the one fixed in
      commit 00b368502d18 ("xen-netfront: do not assume sk_buff_head list is
      empty in error handling").
      
      This patch changes the return type of xennet_fill_frags() to indicate
      whether it is successful or failed. The queue->rx.rsp_cons will be
      always updated inside this function.
      
      Fixes: ad4f15dc ("xen/netfront: don't bug in case of too many frags")
      Signed-off-by: NDongli Zhang <dongli.zhang@oracle.com>
      Reviewed-by: NJuergen Gross <jgross@suse.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      a1afd826
  2. 21 9月, 2019 1 次提交
    • D
      xen-netfront: do not assume sk_buff_head list is empty in error handling · 47288968
      Dongli Zhang 提交于
      [ Upstream commit 00b368502d18f790ab715e055869fd4bb7484a9b ]
      
      When skb_shinfo(skb) is not able to cache extra fragment (that is,
      skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS), xennet_fill_frags() assumes
      the sk_buff_head list is already empty. As a result, cons is increased only
      by 1 and returns to error handling path in xennet_poll().
      
      However, if the sk_buff_head list is not empty, queue->rx.rsp_cons may be
      set incorrectly. That is, queue->rx.rsp_cons would point to the rx ring
      buffer entries whose queue->rx_skbs[i] and queue->grant_rx_ref[i] are
      already cleared to NULL. This leads to NULL pointer access in the next
      iteration to process rx ring buffer entries.
      
      Below is how xennet_poll() does error handling. All remaining entries in
      tmpq are accounted to queue->rx.rsp_cons without assuming how many
      outstanding skbs are remained in the list.
      
       985 static int xennet_poll(struct napi_struct *napi, int budget)
      ... ...
      1032           if (unlikely(xennet_set_skb_gso(skb, gso))) {
      1033                   __skb_queue_head(&tmpq, skb);
      1034                   queue->rx.rsp_cons += skb_queue_len(&tmpq);
      1035                   goto err;
      1036           }
      
      It is better to always have the error handling in the same way.
      
      Fixes: ad4f15dc ("xen/netfront: don't bug in case of too many frags")
      Signed-off-by: NDongli Zhang <dongli.zhang@oracle.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      47288968
  3. 10 1月, 2019 1 次提交
  4. 13 9月, 2018 1 次提交
  5. 08 9月, 2018 1 次提交
  6. 15 8月, 2018 1 次提交
    • X
      xen-netfront: fix warn message as irq device name has '/' · 21f2706b
      Xiao Liang 提交于
      There is a call trace generated after commit 2d408c0d(
      xen-netfront: fix queue name setting). There is no 'device/vif/xx-q0-tx' file found
      under /proc/irq/xx/.
      
      This patch only picks up device type and id as its name.
      
      With the patch, now /proc/interrupts looks like below and the warning message gone:
       70:         21          0          0          0   xen-dyn    -event     vif0-q0-tx
       71:         15          0          0          0   xen-dyn    -event     vif0-q0-rx
       72:         14          0          0          0   xen-dyn    -event     vif0-q1-tx
       73:         33          0          0          0   xen-dyn    -event     vif0-q1-rx
       74:         12          0          0          0   xen-dyn    -event     vif0-q2-tx
       75:         24          0          0          0   xen-dyn    -event     vif0-q2-rx
       76:         19          0          0          0   xen-dyn    -event     vif0-q3-tx
       77:         21          0          0          0   xen-dyn    -event     vif0-q3-rx
      
      Below is call trace information without this patch:
      
      name 'device/vif/0-q0-tx'
      WARNING: CPU: 2 PID: 37 at fs/proc/generic.c:174 __xlate_proc_name+0x85/0xa0
      RIP: 0010:__xlate_proc_name+0x85/0xa0
      RSP: 0018:ffffb85c40473c18 EFLAGS: 00010286
      RAX: 0000000000000000 RBX: 0000000000000006 RCX: 0000000000000006
      RDX: 0000000000000007 RSI: 0000000000000096 RDI: ffff984c7f516930
      RBP: ffffb85c40473cb8 R08: 000000000000002c R09: 0000000000000229
      R10: 0000000000000000 R11: 0000000000000001 R12: ffffb85c40473c98
      R13: ffffb85c40473cb8 R14: ffffb85c40473c50 R15: 0000000000000000
      FS:  0000000000000000(0000) GS:ffff984c7f500000(0000) knlGS:0000000000000000
      CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      CR2: 00007f69b6899038 CR3: 000000001c20a006 CR4: 00000000001606e0
      Call Trace:
      __proc_create+0x45/0x230
      ? snprintf+0x49/0x60
      proc_mkdir_data+0x35/0x90
      register_handler_proc+0xef/0x110
      ? proc_register+0xfc/0x110
      ? proc_create_data+0x70/0xb0
      __setup_irq+0x39b/0x660
      ? request_threaded_irq+0xad/0x160
      request_threaded_irq+0xf5/0x160
      ? xennet_tx_buf_gc+0x1d0/0x1d0 [xen_netfront]
      bind_evtchn_to_irqhandler+0x3d/0x70
      ? xenbus_alloc_evtchn+0x41/0xa0
      netback_changed+0xa46/0xcda [xen_netfront]
      ? find_watch+0x40/0x40
      xenwatch_thread+0xc5/0x160
      ? finish_wait+0x80/0x80
      kthread+0x112/0x130
      ? kthread_create_worker_on_cpu+0x70/0x70
      ret_from_fork+0x35/0x40
      Code: 81 5c 00 48 85 c0 75 cc 5b 49 89 2e 31 c0 5d 4d 89 3c 24 41 5c 41 5d 41 5e 41 5f c3 4c 89 ee 48 c7 c7 40 4f 0e b4 e8 65 ea d8 ff <0f> 0b b8 fe ff ff ff 5b 5d 41 5c 41 5d 41 5e 41 5f c3 66 0f 1f
      ---[ end trace 650e5561b0caab3a ]---
      Signed-off-by: NXiao Liang <xiliang@redhat.com>
      Reviewed-by: NJuergen Gross <jgross@suse.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      21f2706b
  7. 12 8月, 2018 1 次提交
  8. 31 7月, 2018 1 次提交
    • X
      xen-netfront: wait xenbus state change when load module manually · 822fb18a
      Xiao Liang 提交于
      When loading module manually, after call xenbus_switch_state to initializes
      the state of the netfront device, the driver state did not change so fast
      that may lead no dev created in latest kernel. This patch adds wait to make
      sure xenbus knows the driver is not in closed/unknown state.
      
      Current state:
      [vm]# ethtool eth0
      Settings for eth0:
      	Link detected: yes
      [vm]# modprobe -r xen_netfront
      [vm]# modprobe  xen_netfront
      [vm]# ethtool eth0
      Settings for eth0:
      Cannot get device settings: No such device
      Cannot get wake-on-lan settings: No such device
      Cannot get message level: No such device
      Cannot get link status: No such device
      No data available
      
      With the patch installed.
      [vm]# ethtool eth0
      Settings for eth0:
      	Link detected: yes
      [vm]# modprobe -r xen_netfront
      [vm]# modprobe xen_netfront
      [vm]# ethtool eth0
      Settings for eth0:
      	Link detected: yes
      Signed-off-by: NXiao Liang <xiliang@redhat.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      822fb18a
  9. 23 7月, 2018 1 次提交
    • V
      xen-netfront: fix queue name setting · 2d408c0d
      Vitaly Kuznetsov 提交于
      Commit f599c64f ("xen-netfront: Fix race between device setup and
      open") changed the initialization order: xennet_create_queues() now
      happens before we do register_netdev() so using netdev->name in
      xennet_init_queue() is incorrect, we end up with the following in
      /proc/interrupts:
      
       60:        139          0   xen-dyn    -event     eth%d-q0-tx
       61:        265          0   xen-dyn    -event     eth%d-q0-rx
       62:        234          0   xen-dyn    -event     eth%d-q1-tx
       63:          1          0   xen-dyn    -event     eth%d-q1-rx
      
      and this looks ugly. Actually, using early netdev name (even when it's
      already set) is also not ideal: nowadays we tend to rename eth devices
      and queue name may end up not corresponding to the netdev name.
      
      Use nodename from xenbus device for queue naming: this can't change in VM's
      lifetime. Now /proc/interrupts looks like
      
       62:        202          0   xen-dyn    -event     device/vif/0-q0-tx
       63:        317          0   xen-dyn    -event     device/vif/0-q0-rx
       64:        262          0   xen-dyn    -event     device/vif/0-q1-tx
       65:         17          0   xen-dyn    -event     device/vif/0-q1-rx
      
      Fixes: f599c64f ("xen-netfront: Fix race between device setup and open")
      Signed-off-by: NVitaly Kuznetsov <vkuznets@redhat.com>
      Reviewed-by: NRoss Lagerwall <ross.lagerwall@citrix.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      2d408c0d
  10. 10 7月, 2018 1 次提交
  11. 22 6月, 2018 2 次提交
  12. 13 6月, 2018 1 次提交
    • J
      xen/netfront: raise max number of slots in xennet_get_responses() · 57f230ab
      Juergen Gross 提交于
      The max number of slots used in xennet_get_responses() is set to
      MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD).
      
      In old kernel-xen MAX_SKB_FRAGS was 18, while nowadays it is 17. This
      difference is resulting in frequent messages "too many slots" and a
      reduced network throughput for some workloads (factor 10 below that of
      a kernel-xen based guest).
      
      Replacing MAX_SKB_FRAGS by XEN_NETIF_NR_SLOTS_MIN for calculation of
      the max number of slots to use solves that problem (tests showed no
      more messages "too many slots" and throughput was as high as with the
      kernel-xen based guest system).
      
      Replace MAX_SKB_FRAGS-2 by XEN_NETIF_NR_SLOTS_MIN-1 in
      netfront_tx_slot_available() for making it clearer what is really being
      tested without actually modifying the tested value.
      Signed-off-by: NJuergen Gross <jgross@suse.com>
      Reviewed-by: NBoris Ostrovsky <boris.ostrovsky@oracle.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      57f230ab
  13. 14 5月, 2018 1 次提交
  14. 27 3月, 2018 1 次提交
  15. 01 3月, 2018 1 次提交
  16. 06 2月, 2018 1 次提交
    • R
      xen-netfront: Fix race between device setup and open · f599c64f
      Ross Lagerwall 提交于
      When a netfront device is set up it registers a netdev fairly early on,
      before it has set up the queues and is actually usable. A userspace tool
      like NetworkManager will immediately try to open it and access its state
      as soon as it appears. The bug can be reproduced by hotplugging VIFs
      until the VM runs out of grant refs. It registers the netdev but fails
      to set up any queues (since there are no more grant refs). In the
      meantime, NetworkManager opens the device and the kernel crashes trying
      to access the queues (of which there are none).
      
      Fix this in two ways:
      * For initial setup, register the netdev much later, after the queues
      are setup. This avoids the race entirely.
      * During a suspend/resume cycle, the frontend reconnects to the backend
      and the queues are recreated. It is possible (though highly unlikely) to
      race with something opening the device and accessing the queues after
      they have been destroyed but before they have been recreated. Extend the
      region covered by the rtnl semaphore to protect against this race. There
      is a possibility that we fail to recreate the queues so check for this
      in the open function.
      Signed-off-by: NRoss Lagerwall <ross.lagerwall@citrix.com>
      Reviewed-by: NBoris Ostrovsky <boris.ostrovsky@oracle.com>
      Signed-off-by: NJuergen Gross <jgross@suse.com>
      f599c64f
  17. 09 1月, 2018 1 次提交
  18. 28 11月, 2017 1 次提交
    • E
      xen-netfront: remove warning when unloading module · 5b5971df
      Eduardo Otubo 提交于
      v2:
       * Replace busy wait with wait_event()/wake_up_all()
       * Cannot garantee that at the time xennet_remove is called, the
         xen_netback state will not be XenbusStateClosed, so added a
         condition for that
       * There's a small chance for the xen_netback state is
         XenbusStateUnknown by the time the xen_netfront switches to Closed,
         so added a condition for that.
      
      When unloading module xen_netfront from guest, dmesg would output
      warning messages like below:
      
        [  105.236836] xen:grant_table: WARNING: g.e. 0x903 still in use!
        [  105.236839] deferring g.e. 0x903 (pfn 0x35805)
      
      This problem relies on netfront and netback being out of sync. By the time
      netfront revokes the g.e.'s netback didn't have enough time to free all of
      them, hence displaying the warnings on dmesg.
      
      The trick here is to make netfront to wait until netback frees all the g.e.'s
      and only then continue to cleanup for the module removal, and this is done by
      manipulating both device states.
      Signed-off-by: NEduardo Otubo <otubo@redhat.com>
      Acked-by: NJuergen Gross <jgross@suse.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      5b5971df
  19. 22 11月, 2017 1 次提交
    • K
      treewide: setup_timer() -> timer_setup() · e99e88a9
      Kees Cook 提交于
      This converts all remaining cases of the old setup_timer() API into using
      timer_setup(), where the callback argument is the structure already
      holding the struct timer_list. These should have no behavioral changes,
      since they just change which pointer is passed into the callback with
      the same available pointers after conversion. It handles the following
      examples, in addition to some other variations.
      
      Casting from unsigned long:
      
          void my_callback(unsigned long data)
          {
              struct something *ptr = (struct something *)data;
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, ptr);
      
      and forced object casts:
      
          void my_callback(struct something *ptr)
          {
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, (unsigned long)ptr);
      
      become:
      
          void my_callback(struct timer_list *t)
          {
              struct something *ptr = from_timer(ptr, t, my_timer);
          ...
          }
          ...
          timer_setup(&ptr->my_timer, my_callback, 0);
      
      Direct function assignments:
      
          void my_callback(unsigned long data)
          {
              struct something *ptr = (struct something *)data;
          ...
          }
          ...
          ptr->my_timer.function = my_callback;
      
      have a temporary cast added, along with converting the args:
      
          void my_callback(struct timer_list *t)
          {
              struct something *ptr = from_timer(ptr, t, my_timer);
          ...
          }
          ...
          ptr->my_timer.function = (TIMER_FUNC_TYPE)my_callback;
      
      And finally, callbacks without a data assignment:
      
          void my_callback(unsigned long data)
          {
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, 0);
      
      have their argument renamed to verify they're unused during conversion:
      
          void my_callback(struct timer_list *unused)
          {
          ...
          }
          ...
          timer_setup(&ptr->my_timer, my_callback, 0);
      
      The conversion is done with the following Coccinelle script:
      
      spatch --very-quiet --all-includes --include-headers \
      	-I ./arch/x86/include -I ./arch/x86/include/generated \
      	-I ./include -I ./arch/x86/include/uapi \
      	-I ./arch/x86/include/generated/uapi -I ./include/uapi \
      	-I ./include/generated/uapi --include ./include/linux/kconfig.h \
      	--dir . \
      	--cocci-file ~/src/data/timer_setup.cocci
      
      @fix_address_of@
      expression e;
      @@
      
       setup_timer(
      -&(e)
      +&e
       , ...)
      
      // Update any raw setup_timer() usages that have a NULL callback, but
      // would otherwise match change_timer_function_usage, since the latter
      // will update all function assignments done in the face of a NULL
      // function initialization in setup_timer().
      @change_timer_function_usage_NULL@
      expression _E;
      identifier _timer;
      type _cast_data;
      @@
      
      (
      -setup_timer(&_E->_timer, NULL, _E);
      +timer_setup(&_E->_timer, NULL, 0);
      |
      -setup_timer(&_E->_timer, NULL, (_cast_data)_E);
      +timer_setup(&_E->_timer, NULL, 0);
      |
      -setup_timer(&_E._timer, NULL, &_E);
      +timer_setup(&_E._timer, NULL, 0);
      |
      -setup_timer(&_E._timer, NULL, (_cast_data)&_E);
      +timer_setup(&_E._timer, NULL, 0);
      )
      
      @change_timer_function_usage@
      expression _E;
      identifier _timer;
      struct timer_list _stl;
      identifier _callback;
      type _cast_func, _cast_data;
      @@
      
      (
      -setup_timer(&_E->_timer, _callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, &_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, &_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)&_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)&_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, &_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, &_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
       _E->_timer@_stl.function = _callback;
      |
       _E->_timer@_stl.function = &_callback;
      |
       _E->_timer@_stl.function = (_cast_func)_callback;
      |
       _E->_timer@_stl.function = (_cast_func)&_callback;
      |
       _E._timer@_stl.function = _callback;
      |
       _E._timer@_stl.function = &_callback;
      |
       _E._timer@_stl.function = (_cast_func)_callback;
      |
       _E._timer@_stl.function = (_cast_func)&_callback;
      )
      
      // callback(unsigned long arg)
      @change_callback_handle_cast
       depends on change_timer_function_usage@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _origtype;
      identifier _origarg;
      type _handletype;
      identifier _handle;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *t
       )
       {
      (
      	... when != _origarg
      	_handletype *_handle =
      -(_handletype *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle =
      -(void *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle;
      	... when != _handle
      	_handle =
      -(_handletype *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle;
      	... when != _handle
      	_handle =
      -(void *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      )
       }
      
      // callback(unsigned long arg) without existing variable
      @change_callback_handle_cast_no_arg
       depends on change_timer_function_usage &&
                           !change_callback_handle_cast@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _origtype;
      identifier _origarg;
      type _handletype;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *t
       )
       {
      +	_handletype *_origarg = from_timer(_origarg, t, _timer);
      +
      	... when != _origarg
      -	(_handletype *)_origarg
      +	_origarg
      	... when != _origarg
       }
      
      // Avoid already converted callbacks.
      @match_callback_converted
       depends on change_timer_function_usage &&
                  !change_callback_handle_cast &&
      	    !change_callback_handle_cast_no_arg@
      identifier change_timer_function_usage._callback;
      identifier t;
      @@
      
       void _callback(struct timer_list *t)
       { ... }
      
      // callback(struct something *handle)
      @change_callback_handle_arg
       depends on change_timer_function_usage &&
      	    !match_callback_converted &&
                  !change_callback_handle_cast &&
                  !change_callback_handle_cast_no_arg@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _handletype;
      identifier _handle;
      @@
      
       void _callback(
      -_handletype *_handle
      +struct timer_list *t
       )
       {
      +	_handletype *_handle = from_timer(_handle, t, _timer);
      	...
       }
      
      // If change_callback_handle_arg ran on an empty function, remove
      // the added handler.
      @unchange_callback_handle_arg
       depends on change_timer_function_usage &&
      	    change_callback_handle_arg@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _handletype;
      identifier _handle;
      identifier t;
      @@
      
       void _callback(struct timer_list *t)
       {
      -	_handletype *_handle = from_timer(_handle, t, _timer);
       }
      
      // We only want to refactor the setup_timer() data argument if we've found
      // the matching callback. This undoes changes in change_timer_function_usage.
      @unchange_timer_function_usage
       depends on change_timer_function_usage &&
                  !change_callback_handle_cast &&
                  !change_callback_handle_cast_no_arg &&
      	    !change_callback_handle_arg@
      expression change_timer_function_usage._E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type change_timer_function_usage._cast_data;
      @@
      
      (
      -timer_setup(&_E->_timer, _callback, 0);
      +setup_timer(&_E->_timer, _callback, (_cast_data)_E);
      |
      -timer_setup(&_E._timer, _callback, 0);
      +setup_timer(&_E._timer, _callback, (_cast_data)&_E);
      )
      
      // If we fixed a callback from a .function assignment, fix the
      // assignment cast now.
      @change_timer_function_assignment
       depends on change_timer_function_usage &&
                  (change_callback_handle_cast ||
                   change_callback_handle_cast_no_arg ||
                   change_callback_handle_arg)@
      expression change_timer_function_usage._E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type _cast_func;
      typedef TIMER_FUNC_TYPE;
      @@
      
      (
       _E->_timer.function =
      -_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -(_cast_func)_callback;
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -(_cast_func)&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -&_callback;
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -(_cast_func)_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -(_cast_func)&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      )
      
      // Sometimes timer functions are called directly. Replace matched args.
      @change_timer_function_calls
       depends on change_timer_function_usage &&
                  (change_callback_handle_cast ||
                   change_callback_handle_cast_no_arg ||
                   change_callback_handle_arg)@
      expression _E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type _cast_data;
      @@
      
       _callback(
      (
      -(_cast_data)_E
      +&_E->_timer
      |
      -(_cast_data)&_E
      +&_E._timer
      |
      -_E
      +&_E->_timer
      )
       )
      
      // If a timer has been configured without a data argument, it can be
      // converted without regard to the callback argument, since it is unused.
      @match_timer_function_unused_data@
      expression _E;
      identifier _timer;
      identifier _callback;
      @@
      
      (
      -setup_timer(&_E->_timer, _callback, 0);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, 0L);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, 0UL);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0L);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0UL);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0L);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0UL);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0);
      +timer_setup(_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0L);
      +timer_setup(_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0UL);
      +timer_setup(_timer, _callback, 0);
      )
      
      @change_callback_unused_data
       depends on match_timer_function_unused_data@
      identifier match_timer_function_unused_data._callback;
      type _origtype;
      identifier _origarg;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *unused
       )
       {
      	... when != _origarg
       }
      Signed-off-by: NKees Cook <keescook@chromium.org>
      e99e88a9
  20. 17 10月, 2017 1 次提交
  21. 31 8月, 2017 1 次提交
  22. 12 5月, 2017 1 次提交
  23. 11 2月, 2017 1 次提交
  24. 10 2月, 2017 2 次提交
  25. 31 1月, 2017 1 次提交
  26. 30 1月, 2017 1 次提交
  27. 21 1月, 2017 1 次提交
    • V
      xen-netfront: Fix Rx stall during network stress and OOM · 90c311b0
      Vineeth Remanan Pillai 提交于
      During an OOM scenario, request slots could not be created as skb
      allocation fails. So the netback cannot pass in packets and netfront
      wrongly assumes that there is no more work to be done and it disables
      polling. This causes Rx to stall.
      
      The issue is with the retry logic which schedules the timer if the
      created slots are less than NET_RX_SLOTS_MIN. The count of new request
      slots to be pushed are calculated as a difference between new req_prod
      and rsp_cons which could be more than the actual slots, if there are
      unconsumed responses.
      
      The fix is to calculate the count of newly created slots as the
      difference between new req_prod and old req_prod.
      Signed-off-by: NVineeth Remanan Pillai <vineethp@amazon.com>
      Reviewed-by: NJuergen Gross <jgross@suse.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      90c311b0
  28. 09 1月, 2017 1 次提交
  29. 07 11月, 2016 1 次提交
  30. 03 11月, 2016 1 次提交
  31. 01 11月, 2016 1 次提交
  32. 21 10月, 2016 1 次提交
    • J
      net: use core MTU range checking in virt drivers · d0c2c997
      Jarod Wilson 提交于
      hyperv_net:
      - set min/max_mtu, per Haiyang, after rndis_filter_device_add
      
      virtio_net:
      - set min/max_mtu
      - remove virtnet_change_mtu
      
      vmxnet3:
      - set min/max_mtu
      
      xen-netback:
      - min_mtu = 0, max_mtu = 65517
      
      xen-netfront:
      - min_mtu = 0, max_mtu = 65535
      
      unisys/visor:
      - clean up defines a little to not clash with network core or add
        redundat definitions
      
      CC: netdev@vger.kernel.org
      CC: virtualization@lists.linux-foundation.org
      CC: "K. Y. Srinivasan" <kys@microsoft.com>
      CC: Haiyang Zhang <haiyangz@microsoft.com>
      CC: "Michael S. Tsirkin" <mst@redhat.com>
      CC: Shrikrishna Khare <skhare@vmware.com>
      CC: "VMware, Inc." <pv-drivers@vmware.com>
      CC: Wei Liu <wei.liu2@citrix.com>
      CC: Paul Durrant <paul.durrant@citrix.com>
      CC: David Kershner <david.kershner@unisys.com>
      Signed-off-by: NJarod Wilson <jarod@redhat.com>
      Reviewed-by: NHaiyang Zhang <haiyangz@microsoft.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      d0c2c997
  33. 20 9月, 2016 1 次提交
    • V
      xen-netfront: avoid packet loss when ethernet header crosses page boundary · fd07160b
      Vitaly Kuznetsov 提交于
      Small packet loss is reported on complex multi host network configurations
      including tunnels, NAT, ... My investigation led me to the following check
      in netback which drops packets:
      
              if (unlikely(txreq.size < ETH_HLEN)) {
                      netdev_err(queue->vif->dev,
                                 "Bad packet size: %d\n", txreq.size);
                      xenvif_tx_err(queue, &txreq, extra_count, idx);
                      break;
              }
      
      But this check itself is legitimate. SKBs consist of a linear part (which
      has to have the ethernet header) and (optionally) a number of frags.
      Netfront transmits the head of the linear part up to the page boundary
      as the first request and all the rest becomes frags so when we're
      reconstructing the SKB in netback we can't distinguish between original
      frags and the 'tail' of the linear part. The first SKB needs to be at
      least ETH_HLEN size. So in case we have an SKB with its linear part
      starting too close to the page boundary the packet is lost.
      
      I see two ways to fix the issue:
      - Change the 'wire' protocol between netfront and netback to start keeping
        the original SKB structure. We'll have to add a flag indicating the fact
        that the particular request is a part of the original linear part and not
        a frag. We'll need to know the length of the linear part to pre-allocate
        memory.
      - Avoid transmitting SKBs with linear parts starting too close to the page
        boundary. That seems preferable short-term and shouldn't bring
        significant performance degradation as such packets are rare. That's what
        this patch is trying to achieve with skb_copy().
      Signed-off-by: NVitaly Kuznetsov <vkuznets@redhat.com>
      Acked-by: NDavid Vrabel <david.vrabel@citrix.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      fd07160b
  34. 29 1月, 2016 1 次提交
  35. 23 10月, 2015 1 次提交
  36. 21 10月, 2015 1 次提交
  37. 21 9月, 2015 1 次提交
  38. 11 9月, 2015 1 次提交