mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 17:57:38 -04:00
Merge tag 'net-next-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from Jakub Kicinski:
"Core & protocols:
- Continue Netlink conversions to per-namespace RTNL lock
(IPv4 routing, routing rules, routing next hops, ARP ioctls)
- Continue extending the use of netdev instance locks. As a driver
opt-in protect queue operations and (in due course) ethtool
operations with the instance lock and not RTNL lock.
- Support collecting TCP timestamps (data submitted, sent, acked) in
BPF, allowing for transparent (to the application) and lower
overhead tracking of TCP RPC performance.
- Tweak existing networking Rx zero-copy infra to support zero-copy
Rx via io_uring.
- Optimize MPTCP performance in single subflow mode by 29%.
- Enable GRO on packets which went thru XDP CPU redirect (were queued
for processing on a different CPU). Improving TCP stream
performance up to 2x.
- Improve performance of contended connect() by 200% by searching for
an available 4-tuple under RCU rather than a spin lock. Bring an
additional 229% improvement by tweaking hash distribution.
- Avoid unconditionally touching sk_tsflags on RX, improving
performance under UDP flood by as much as 10%.
- Avoid skb_clone() dance in ping_rcv() to improve performance under
ping flood.
- Avoid FIB lookup in netfilter if socket is available, 20% perf win.
- Rework network device creation (in-kernel) API to more clearly
identify network namespaces and their roles. There are up to 4
namespace roles but we used to have just 2 netns pointer arguments,
interpreted differently based on context.
- Use sysfs_break_active_protection() instead of trylock to avoid
deadlocks between unregistering objects and sysfs access.
- Add a new sysctl and sockopt for capping max retransmit timeout in
TCP.
- Support masking port and DSCP in routing rule matches.
- Support dumping IPv4 multicast addresses with RTM_GETMULTICAST.
- Support specifying at what time packet should be sent on AF_XDP
sockets.
- Expose TCP ULP diagnostic info (for TLS and MPTCP) to non-admin
users.
- Add Netlink YAML spec for WiFi (nl80211) and conntrack.
- Introduce EXPORT_IPV6_MOD() and EXPORT_IPV6_MOD_GPL() for symbols
which only need to be exported when IPv6 support is built as a
module.
- Age FDB entries based on Rx not Tx traffic in VxLAN, similar to
normal bridging.
- Allow users to specify source port range for GENEVE tunnels.
- netconsole: allow attaching kernel release, CPU ID and task name to
messages as metadata
Driver API:
- Continue rework / fixing of Energy Efficient Ethernet (EEE) across
the SW layers. Delegate the responsibilities to phylink where
possible. Improve its handling in phylib.
- Support symmetric OR-XOR RSS hashing algorithm.
- Support tracking and preserving IRQ affinity by NAPI itself.
- Support loopback mode speed selection for interface selftests.
Device drivers:
- Remove the IBM LCS driver for s390
- Remove the sb1000 cable modem driver
- Add support for SFP module access over SMBus
- Add MCTP transport driver for MCTP-over-USB
- Enable XDP metadata support in multiple drivers
- Ethernet high-speed NICs:
- Broadcom (bnxt):
- add PCIe TLP Processing Hints (TPH) support for new AMD
platforms
- support dumping RoCE queue state for debug
- opt into instance locking
- Intel (100G, ice, idpf):
- ice: rework MSI-X IRQ management and distribution
- ice: support for E830 devices
- iavf: add support for Rx timestamping
- iavf: opt into instance locking
- nVidia/Mellanox:
- mlx4: use page pool memory allocator for Rx
- mlx5: support for one PTP device per hardware clock
- mlx5: support for 200Gbps per-lane link modes
- mlx5: move IPSec policy check after decryption
- AMD/Solarflare:
- support FW flashing via devlink
- Cisco (enic):
- use page pool memory allocator for Rx
- enable 32, 64 byte CQEs
- get max rx/tx ring size from the device
- Meta (fbnic):
- support flow steering and RSS configuration
- report queue stats
- support TCP segmentation
- support IRQ coalescing
- support ring size configuration
- Marvell/Cavium:
- support AF_XDP
- Wangxun:
- support for PTP clock and timestamping
- Huawei (hibmcge):
- checksum offload
- add more statistics
- Ethernet virtual:
- VirtIO net:
- aggressively suppress Tx completions, improve perf by 96%
with 1 CPU and 55% with 2 CPUs
- expose NAPI to IRQ mapping and persist NAPI settings
- Google (gve):
- support XDP in DQO RDA Queue Format
- opt into instance locking
- Microsoft vNIC:
- support BIG TCP
- Ethernet NICs consumer, and embedded:
- Synopsys (stmmac):
- cleanup Tx and Tx clock setting and other link-focused
cleanups
- enable SGMII and 2500BASEX mode switching for Intel platforms
- support Sophgo SG2044
- Broadcom switches (b53):
- support for BCM53101
- TI:
- iep: add perout configuration support
- icssg: support XDP
- Cadence (macb):
- implement BQL
- Xilinx (axinet):
- support dynamic IRQ moderation and changing coalescing at
runtime
- implement BQL
- report standard stats
- MediaTek:
- support phylink managed EEE
- Intel:
- igc: don't restart the interface on every XDP program change
- RealTek (r8169):
- support reading registers of internal PHYs directly
- increase max jumbo packet size on RTL8125/RTL8126
- Airoha:
- support for RISC-V NPU packet processing unit
- enable scatter-gather and support MTU up to 9kB
- Tehuti (tn40xx):
- support cards with TN4010 MAC and an Aquantia AQR105 PHY
- Ethernet PHYs:
- support for TJA1102S, TJA1121
- dp83tg720: add randomized polling intervals for link detection
- dp83822: support changing the transmit amplitude voltage
- support for LEDs on 88q2xxx
- CAN:
- canxl: support Remote Request Substitution bit access
- flexcan: add S32G2/S32G3 SoC
- WiFi:
- remove cooked monitor support
- strict mode for better AP testing
- basic EPCS support
- OMI RX bandwidth reduction support
- batman-adv: add support for jumbo frames
- WiFi drivers:
- RealTek (rtw88):
- support RTL8814AE and RTL8814AU
- RealTek (rtw89):
- switch using wiphy_lock and wiphy_work
- add BB context to manipulate two PHY as preparation of MLO
- improve BT-coexistence mechanism to play A2DP smoothly
- Intel (iwlwifi):
- add new iwlmld sub-driver for latest HW/FW combinations
- MediaTek (mt76):
- preparation for mt7996 Multi-Link Operation (MLO) support
- Qualcomm/Atheros (ath12k):
- continued work on MLO
- Silabs (wfx):
- Wake-on-WLAN support
- Bluetooth:
- add support for skb TX SND/COMPLETION timestamping
- hci_core: enable buffer flow control for SCO/eSCO
- coredump: log devcd dumps into the monitor
- Bluetooth drivers:
- intel: add support to configure TX power
- nxp: handle bootloader error during cmd5 and cmd7"
* tag 'net-next-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1681 commits)
unix: fix up for "apparmor: add fine grained af_unix mediation"
mctp: Fix incorrect tx flow invalidation condition in mctp-i2c
net: usb: asix: ax88772: Increase phy_name size
net: phy: Introduce PHY_ID_SIZE — minimum size for PHY ID string
net: libwx: fix Tx L4 checksum
net: libwx: fix Tx descriptor content for some tunnel packets
atm: Fix NULL pointer dereference
net: tn40xx: add pci-id of the aqr105-based Tehuti TN4010 cards
net: tn40xx: prepare tn40xx driver to find phy of the TN9510 card
net: tn40xx: create swnode for mdio and aqr105 phy and add to mdiobus
net: phy: aquantia: add essential functions to aqr105 driver
net: phy: aquantia: search for firmware-name in fwnode
net: phy: aquantia: add probe function to aqr105 for firmware loading
net: phy: Add swnode support to mdiobus_scan
gve: add XDP DROP and PASS support for DQ
gve: update XDP allocation path support RX buffer posting
gve: merge packet buffer size fields
gve: update GQ RX to use buf_size
gve: introduce config-based allocation for XDP
gve: remove xdp_xsk_done and xdp_xsk_wakeup statistics
...
This commit is contained in:
@@ -8526,6 +8526,7 @@ static int bpf_prog_type_to_kfunc_hook(enum bpf_prog_type prog_type)
|
||||
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
|
||||
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
|
||||
case BPF_PROG_TYPE_CGROUP_SYSCTL:
|
||||
case BPF_PROG_TYPE_SOCK_OPS:
|
||||
return BTF_KFUNC_HOOK_CGROUP;
|
||||
case BPF_PROG_TYPE_SCHED_ACT:
|
||||
return BTF_KFUNC_HOOK_SCHED_ACT;
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
#include <trace/events/xdp.h>
|
||||
#include <linux/btf_ids.h>
|
||||
|
||||
#include <linux/netdevice.h> /* netif_receive_skb_list */
|
||||
#include <linux/etherdevice.h> /* eth_type_trans */
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/gro.h>
|
||||
|
||||
/* General idea: XDP packets getting XDP redirected to another CPU,
|
||||
* will maximum be stored/queued for one driver ->poll() call. It is
|
||||
@@ -68,6 +68,7 @@ struct bpf_cpu_map_entry {
|
||||
|
||||
struct bpf_cpumap_val value;
|
||||
struct bpf_prog *prog;
|
||||
struct gro_node gro;
|
||||
|
||||
struct completion kthread_running;
|
||||
struct rcu_work free_work;
|
||||
@@ -133,22 +134,23 @@ static void __cpu_map_ring_cleanup(struct ptr_ring *ring)
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu,
|
||||
struct list_head *listp,
|
||||
struct xdp_cpumap_stats *stats)
|
||||
static u32 cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu,
|
||||
void **skbs, u32 skb_n,
|
||||
struct xdp_cpumap_stats *stats)
|
||||
{
|
||||
struct sk_buff *skb, *tmp;
|
||||
struct xdp_buff xdp;
|
||||
u32 act;
|
||||
u32 act, pass = 0;
|
||||
int err;
|
||||
|
||||
list_for_each_entry_safe(skb, tmp, listp, list) {
|
||||
for (u32 i = 0; i < skb_n; i++) {
|
||||
struct sk_buff *skb = skbs[i];
|
||||
|
||||
act = bpf_prog_run_generic_xdp(skb, &xdp, rcpu->prog);
|
||||
switch (act) {
|
||||
case XDP_PASS:
|
||||
skbs[pass++] = skb;
|
||||
break;
|
||||
case XDP_REDIRECT:
|
||||
skb_list_del_init(skb);
|
||||
err = xdp_do_generic_redirect(skb->dev, skb, &xdp,
|
||||
rcpu->prog);
|
||||
if (unlikely(err)) {
|
||||
@@ -157,7 +159,7 @@ static void cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu,
|
||||
} else {
|
||||
stats->redirect++;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
bpf_warn_invalid_xdp_action(NULL, rcpu->prog, act);
|
||||
fallthrough;
|
||||
@@ -165,12 +167,15 @@ static void cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu,
|
||||
trace_xdp_exception(skb->dev, rcpu->prog, act);
|
||||
fallthrough;
|
||||
case XDP_DROP:
|
||||
skb_list_del_init(skb);
|
||||
kfree_skb(skb);
|
||||
napi_consume_skb(skb, true);
|
||||
stats->drop++;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stats->pass += pass;
|
||||
|
||||
return pass;
|
||||
}
|
||||
|
||||
static int cpu_map_bpf_prog_run_xdp(struct bpf_cpu_map_entry *rcpu,
|
||||
@@ -204,7 +209,6 @@ static int cpu_map_bpf_prog_run_xdp(struct bpf_cpu_map_entry *rcpu,
|
||||
stats->drop++;
|
||||
} else {
|
||||
frames[nframes++] = xdpf;
|
||||
stats->pass++;
|
||||
}
|
||||
break;
|
||||
case XDP_REDIRECT:
|
||||
@@ -228,43 +232,65 @@ static int cpu_map_bpf_prog_run_xdp(struct bpf_cpu_map_entry *rcpu,
|
||||
}
|
||||
|
||||
xdp_clear_return_frame_no_direct();
|
||||
stats->pass += nframes;
|
||||
|
||||
return nframes;
|
||||
}
|
||||
|
||||
#define CPUMAP_BATCH 8
|
||||
|
||||
static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,
|
||||
int xdp_n, struct xdp_cpumap_stats *stats,
|
||||
struct list_head *list)
|
||||
struct cpu_map_ret {
|
||||
u32 xdp_n;
|
||||
u32 skb_n;
|
||||
};
|
||||
|
||||
static void cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,
|
||||
void **skbs, struct cpu_map_ret *ret,
|
||||
struct xdp_cpumap_stats *stats)
|
||||
{
|
||||
struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
|
||||
int nframes;
|
||||
|
||||
if (!rcpu->prog)
|
||||
return xdp_n;
|
||||
goto out;
|
||||
|
||||
rcu_read_lock_bh();
|
||||
rcu_read_lock();
|
||||
bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
|
||||
|
||||
nframes = cpu_map_bpf_prog_run_xdp(rcpu, frames, xdp_n, stats);
|
||||
ret->xdp_n = cpu_map_bpf_prog_run_xdp(rcpu, frames, ret->xdp_n, stats);
|
||||
if (unlikely(ret->skb_n))
|
||||
ret->skb_n = cpu_map_bpf_prog_run_skb(rcpu, skbs, ret->skb_n,
|
||||
stats);
|
||||
|
||||
if (stats->redirect)
|
||||
xdp_do_flush();
|
||||
|
||||
if (unlikely(!list_empty(list)))
|
||||
cpu_map_bpf_prog_run_skb(rcpu, list, stats);
|
||||
|
||||
bpf_net_ctx_clear(bpf_net_ctx);
|
||||
rcu_read_unlock_bh(); /* resched point, may call do_softirq() */
|
||||
rcu_read_unlock();
|
||||
|
||||
return nframes;
|
||||
out:
|
||||
if (unlikely(ret->skb_n) && ret->xdp_n)
|
||||
memmove(&skbs[ret->xdp_n], skbs, ret->skb_n * sizeof(*skbs));
|
||||
}
|
||||
|
||||
static void cpu_map_gro_flush(struct bpf_cpu_map_entry *rcpu, bool empty)
|
||||
{
|
||||
/*
|
||||
* If the ring is not empty, there'll be a new iteration soon, and we
|
||||
* only need to do a full flush if a tick is long (> 1 ms).
|
||||
* If the ring is empty, to not hold GRO packets in the stack for too
|
||||
* long, do a full flush.
|
||||
* This is equivalent to how NAPI decides whether to perform a full
|
||||
* flush.
|
||||
*/
|
||||
gro_flush(&rcpu->gro, !empty && HZ >= 1000);
|
||||
gro_normal_list(&rcpu->gro);
|
||||
}
|
||||
|
||||
static int cpu_map_kthread_run(void *data)
|
||||
{
|
||||
struct bpf_cpu_map_entry *rcpu = data;
|
||||
unsigned long last_qs = jiffies;
|
||||
u32 packets = 0;
|
||||
|
||||
complete(&rcpu->kthread_running);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
@@ -277,11 +303,11 @@ static int cpu_map_kthread_run(void *data)
|
||||
while (!kthread_should_stop() || !__ptr_ring_empty(rcpu->queue)) {
|
||||
struct xdp_cpumap_stats stats = {}; /* zero stats */
|
||||
unsigned int kmem_alloc_drops = 0, sched = 0;
|
||||
gfp_t gfp = __GFP_ZERO | GFP_ATOMIC;
|
||||
int i, n, m, nframes, xdp_n;
|
||||
struct cpu_map_ret ret = { };
|
||||
void *frames[CPUMAP_BATCH];
|
||||
void *skbs[CPUMAP_BATCH];
|
||||
LIST_HEAD(list);
|
||||
u32 i, n, m;
|
||||
bool empty;
|
||||
|
||||
/* Release CPU reschedule checks */
|
||||
if (__ptr_ring_empty(rcpu->queue)) {
|
||||
@@ -306,7 +332,7 @@ static int cpu_map_kthread_run(void *data)
|
||||
*/
|
||||
n = __ptr_ring_consume_batched(rcpu->queue, frames,
|
||||
CPUMAP_BATCH);
|
||||
for (i = 0, xdp_n = 0; i < n; i++) {
|
||||
for (i = 0; i < n; i++) {
|
||||
void *f = frames[i];
|
||||
struct page *page;
|
||||
|
||||
@@ -314,11 +340,11 @@ static int cpu_map_kthread_run(void *data)
|
||||
struct sk_buff *skb = f;
|
||||
|
||||
__ptr_clear_bit(0, &skb);
|
||||
list_add_tail(&skb->list, &list);
|
||||
skbs[ret.skb_n++] = skb;
|
||||
continue;
|
||||
}
|
||||
|
||||
frames[xdp_n++] = f;
|
||||
frames[ret.xdp_n++] = f;
|
||||
page = virt_to_page(f);
|
||||
|
||||
/* Bring struct page memory area to curr CPU. Read by
|
||||
@@ -328,40 +354,51 @@ static int cpu_map_kthread_run(void *data)
|
||||
prefetchw(page);
|
||||
}
|
||||
|
||||
/* Support running another XDP prog on this CPU */
|
||||
nframes = cpu_map_bpf_prog_run(rcpu, frames, xdp_n, &stats, &list);
|
||||
if (nframes) {
|
||||
m = kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
|
||||
gfp, nframes, skbs);
|
||||
if (unlikely(m == 0)) {
|
||||
for (i = 0; i < nframes; i++)
|
||||
skbs[i] = NULL; /* effect: xdp_return_frame */
|
||||
kmem_alloc_drops += nframes;
|
||||
}
|
||||
}
|
||||
|
||||
local_bh_disable();
|
||||
for (i = 0; i < nframes; i++) {
|
||||
struct xdp_frame *xdpf = frames[i];
|
||||
struct sk_buff *skb = skbs[i];
|
||||
|
||||
skb = __xdp_build_skb_from_frame(xdpf, skb,
|
||||
xdpf->dev_rx);
|
||||
if (!skb) {
|
||||
xdp_return_frame(xdpf);
|
||||
continue;
|
||||
}
|
||||
/* Support running another XDP prog on this CPU */
|
||||
cpu_map_bpf_prog_run(rcpu, frames, skbs, &ret, &stats);
|
||||
if (!ret.xdp_n)
|
||||
goto stats;
|
||||
|
||||
list_add_tail(&skb->list, &list);
|
||||
m = napi_skb_cache_get_bulk(skbs, ret.xdp_n);
|
||||
if (unlikely(m < ret.xdp_n)) {
|
||||
for (i = m; i < ret.xdp_n; i++)
|
||||
xdp_return_frame(frames[i]);
|
||||
|
||||
if (ret.skb_n)
|
||||
memmove(&skbs[m], &skbs[ret.xdp_n],
|
||||
ret.skb_n * sizeof(*skbs));
|
||||
|
||||
kmem_alloc_drops += ret.xdp_n - m;
|
||||
ret.xdp_n = m;
|
||||
}
|
||||
|
||||
for (i = 0; i < ret.xdp_n; i++) {
|
||||
struct xdp_frame *xdpf = frames[i];
|
||||
|
||||
/* Can fail only when !skb -- already handled above */
|
||||
__xdp_build_skb_from_frame(xdpf, skbs[i], xdpf->dev_rx);
|
||||
}
|
||||
|
||||
stats:
|
||||
/* Feedback loop via tracepoint.
|
||||
* NB: keep before recv to allow measuring enqueue/dequeue latency.
|
||||
*/
|
||||
trace_xdp_cpumap_kthread(rcpu->map_id, n, kmem_alloc_drops,
|
||||
sched, &stats);
|
||||
|
||||
netif_receive_skb_list(&list);
|
||||
for (i = 0; i < ret.xdp_n + ret.skb_n; i++)
|
||||
gro_receive_skb(&rcpu->gro, skbs[i]);
|
||||
|
||||
/* Flush either every 64 packets or in case of empty ring */
|
||||
packets += n;
|
||||
empty = __ptr_ring_empty(rcpu->queue);
|
||||
if (packets >= NAPI_POLL_WEIGHT || empty) {
|
||||
cpu_map_gro_flush(rcpu, empty);
|
||||
packets = 0;
|
||||
}
|
||||
|
||||
local_bh_enable(); /* resched point, may call do_softirq() */
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
@@ -430,6 +467,7 @@ __cpu_map_entry_alloc(struct bpf_map *map, struct bpf_cpumap_val *value,
|
||||
rcpu->cpu = cpu;
|
||||
rcpu->map_id = map->id;
|
||||
rcpu->value.qsize = value->qsize;
|
||||
gro_init(&rcpu->gro);
|
||||
|
||||
if (fd > 0 && __cpu_map_load_bpf_program(rcpu, map, fd))
|
||||
goto free_ptr_ring;
|
||||
@@ -458,6 +496,7 @@ __cpu_map_entry_alloc(struct bpf_map *map, struct bpf_cpumap_val *value,
|
||||
if (rcpu->prog)
|
||||
bpf_prog_put(rcpu->prog);
|
||||
free_ptr_ring:
|
||||
gro_cleanup(&rcpu->gro);
|
||||
ptr_ring_cleanup(rcpu->queue, NULL);
|
||||
free_queue:
|
||||
kfree(rcpu->queue);
|
||||
@@ -487,6 +526,7 @@ static void __cpu_map_entry_free(struct work_struct *work)
|
||||
|
||||
if (rcpu->prog)
|
||||
bpf_prog_put(rcpu->prog);
|
||||
gro_cleanup(&rcpu->gro);
|
||||
/* The queue should be empty at this point */
|
||||
__cpu_map_ring_cleanup(rcpu->queue);
|
||||
ptr_ring_cleanup(rcpu->queue, NULL);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <net/netdev_lock.h>
|
||||
#include <net/xdp.h>
|
||||
|
||||
/* Protects offdevs, members of bpf_offload_netdev and offload members
|
||||
@@ -528,13 +529,14 @@ struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
bpf_map_init_from_attr(&offmap->map, attr);
|
||||
|
||||
rtnl_lock();
|
||||
down_write(&bpf_devs_lock);
|
||||
offmap->netdev = __dev_get_by_index(net, attr->map_ifindex);
|
||||
err = bpf_dev_offload_check(offmap->netdev);
|
||||
if (err)
|
||||
goto err_unlock;
|
||||
goto err_unlock_rtnl;
|
||||
|
||||
netdev_lock_ops(offmap->netdev);
|
||||
down_write(&bpf_devs_lock);
|
||||
|
||||
ondev = bpf_offload_find_netdev(offmap->netdev);
|
||||
if (!ondev) {
|
||||
@@ -548,12 +550,15 @@ struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
|
||||
|
||||
list_add_tail(&offmap->offloads, &ondev->maps);
|
||||
up_write(&bpf_devs_lock);
|
||||
netdev_unlock_ops(offmap->netdev);
|
||||
rtnl_unlock();
|
||||
|
||||
return &offmap->map;
|
||||
|
||||
err_unlock:
|
||||
up_write(&bpf_devs_lock);
|
||||
netdev_unlock_ops(offmap->netdev);
|
||||
err_unlock_rtnl:
|
||||
rtnl_unlock();
|
||||
bpf_map_area_free(offmap);
|
||||
return ERR_PTR(err);
|
||||
|
||||
@@ -109,6 +109,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
|
||||
goto out;
|
||||
}
|
||||
pccontext->clk = clk;
|
||||
pccontext->fp = fp;
|
||||
if (clk->ops.open) {
|
||||
err = clk->ops.open(pccontext, fp->f_mode);
|
||||
if (err) {
|
||||
@@ -229,7 +230,7 @@ static int pc_clock_adjtime(clockid_t id, struct __kernel_timex *tx)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((cd.fp->f_mode & FMODE_WRITE) == 0) {
|
||||
if (tx->modes && (cd.fp->f_mode & FMODE_WRITE) == 0) {
|
||||
err = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user