* [PATCH net-next v3 5/8] rocker: Check Handle PORT_PRE_BRIDGE_FLAGS
From: Florian Fainelli @ 2019-02-21 0:58 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, David S. Miller, Ido Schimmel, open list,
open list:STAGING SUBSYSTEM, moderated list:ETHERNET BRIDGE, jiri,
andrew, vivien.didelot
In-Reply-To: <20190221005826.26317-1-f.fainelli@gmail.com>
In preparation for getting rid of switchdev_port_attr_get(), have rocker
check for the bridge flags being set through switchdev_port_attr_set()
with the SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS attribute identifier.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/rocker/rocker_main.c | 55 +++++++++++++++++------
1 file changed, 41 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 5ce8d5aba603..25129f7b5583 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1566,34 +1566,57 @@ static int rocker_world_port_attr_stp_state_set(struct rocker_port *rocker_port,
}
static int
-rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port,
- unsigned long brport_flags,
- struct switchdev_trans *trans)
+rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port *
+ rocker_port,
+ unsigned long *
+ p_brport_flags_support)
{
struct rocker_world_ops *wops = rocker_port->rocker->wops;
+ if (!wops->port_attr_bridge_flags_support_get)
+ return -EOPNOTSUPP;
+ return wops->port_attr_bridge_flags_support_get(rocker_port,
+ p_brport_flags_support);
+}
+
+static int
+rocker_world_port_attr_pre_bridge_flags_set(struct rocker_port *rocker_port,
+ unsigned long brport_flags,
+ struct switchdev_trans *trans)
+{
+ struct rocker_world_ops *wops = rocker_port->rocker->wops;
+ unsigned long brport_flags_s;
+ int err;
+
if (!wops->port_attr_bridge_flags_set)
return -EOPNOTSUPP;
- if (switchdev_trans_ph_prepare(trans))
- return 0;
+ err = rocker_world_port_attr_bridge_flags_support_get(rocker_port,
+ &brport_flags_s);
+ if (err)
+ return err;
- return wops->port_attr_bridge_flags_set(rocker_port, brport_flags,
- trans);
+ if (brport_flags & ~brport_flags_s)
+ return -EINVAL;
+
+ return 0;
}
static int
-rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port *
- rocker_port,
- unsigned long *
- p_brport_flags_support)
+rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port,
+ unsigned long brport_flags,
+ struct switchdev_trans *trans)
{
struct rocker_world_ops *wops = rocker_port->rocker->wops;
- if (!wops->port_attr_bridge_flags_support_get)
+ if (!wops->port_attr_bridge_flags_set)
return -EOPNOTSUPP;
- return wops->port_attr_bridge_flags_support_get(rocker_port,
- p_brport_flags_support);
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ return wops->port_attr_bridge_flags_set(rocker_port, brport_flags,
+ trans);
}
static int
@@ -2074,6 +2097,10 @@ static int rocker_port_attr_set(struct net_device *dev,
attr->u.stp_state,
trans);
break;
+ case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
+ err = rocker_world_port_attr_pre_bridge_flags_set(rocker_port,
+ attr->u.brport_flags,
+ trans);
case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
err = rocker_world_port_attr_bridge_flags_set(rocker_port,
attr->u.brport_flags,
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v3 6/8] net: bridge: Stop calling switchdev_port_attr_get()
From: Florian Fainelli @ 2019-02-21 0:58 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, David S. Miller, Ido Schimmel, open list,
open list:STAGING SUBSYSTEM, moderated list:ETHERNET BRIDGE, jiri,
andrew, vivien.didelot
In-Reply-To: <20190221005826.26317-1-f.fainelli@gmail.com>
Now that all switchdev drivers have been converted to check the
SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS flags and report flags that they
do not support accordingly, we can migrate the bridge code to try to set
that attribute first, check the results and then do the actual setting.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/bridge/br_switchdev.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index db9e8ab96d48..af57c4a2b78a 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -64,21 +64,19 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
{
struct switchdev_attr attr = {
.orig_dev = p->dev,
- .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
+ .id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS,
+ .u.brport_flags = mask,
};
int err;
if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD)
return 0;
- err = switchdev_port_attr_get(p->dev, &attr);
+ err = switchdev_port_attr_set(p->dev, &attr);
if (err == -EOPNOTSUPP)
return 0;
- if (err)
- return err;
- /* Check if specific bridge flag attribute offload is supported */
- if (!(attr.u.brport_flags_support & mask)) {
+ if (err) {
br_warn(p->br, "bridge flag offload is not supported %u(%s)\n",
(unsigned int)p->port_no, p->dev->name);
return -EOPNOTSUPP;
@@ -87,6 +85,7 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS;
attr.flags = SWITCHDEV_F_DEFER;
attr.u.brport_flags = flags;
+
err = switchdev_port_attr_set(p->dev, &attr);
if (err) {
br_warn(p->br, "error setting offload flag on port %u(%s)\n",
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v3 7/8] net: Remove SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT
From: Florian Fainelli @ 2019-02-21 0:58 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, David S. Miller, Ido Schimmel, open list,
open list:STAGING SUBSYSTEM, moderated list:ETHERNET BRIDGE, jiri,
andrew, vivien.didelot
In-Reply-To: <20190221005826.26317-1-f.fainelli@gmail.com>
Now that we have converted the bridge code and the drivers to check for
bridge port(s) flags at the time we try to set them, there is no need
for a get() -> set() sequence anymore and
SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT therefore becomes unused.
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
Documentation/networking/switchdev.txt | 6 ++----
.../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 11 +----------
drivers/net/ethernet/rocker/rocker_main.c | 14 +-------------
drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 10 +---------
include/net/switchdev.h | 2 --
net/dsa/slave.c | 16 +---------------
6 files changed, 6 insertions(+), 53 deletions(-)
diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt
index f3244d87512a..79c8b0f16aee 100644
--- a/Documentation/networking/switchdev.txt
+++ b/Documentation/networking/switchdev.txt
@@ -232,10 +232,8 @@ Learning_sync attribute enables syncing of the learned/forgotten FDB entry to
the bridge's FDB. It's possible, but not optimal, to enable learning on the
device port and on the bridge port, and disable learning_sync.
-To support learning and learning_sync port attributes, the driver implements
-switchdev op switchdev_port_attr_get/set for
-SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS. The driver should initialize the attributes
-to the hardware defaults.
+To support learning, the driver implements switchdev op
+switchdev_port_attr_get/set for SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS.
FDB Ageing
^^^^^^^^^^
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 9a8798f74d2b..bbb5a406232e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -434,16 +434,7 @@ static void mlxsw_sp_bridge_vlan_put(struct mlxsw_sp_bridge_vlan *bridge_vlan)
static int mlxsw_sp_port_attr_get(struct net_device *dev,
struct switchdev_attr *attr)
{
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
- attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD |
- BR_MCAST_FLOOD;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
+ return -EOPNOTSUPP;
}
static int
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 25129f7b5583..6b8273e2057d 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2069,19 +2069,7 @@ static const struct net_device_ops rocker_port_netdev_ops = {
static int rocker_port_attr_get(struct net_device *dev,
struct switchdev_attr *attr)
{
- const struct rocker_port *rocker_port = netdev_priv(dev);
- int err = 0;
-
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
- err = rocker_world_port_attr_bridge_flags_support_get(rocker_port,
- &attr->u.brport_flags_support);
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return err;
+ return -EOPNOTSUPP;
}
static int rocker_port_attr_set(struct net_device *dev,
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index 331625137717..de4dcabbc29a 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -643,15 +643,7 @@ static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev)
static int swdev_port_attr_get(struct net_device *netdev,
struct switchdev_attr *attr)
{
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
- attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
+ return -EOPNOTSUPP;
}
static int port_attr_stp_state_set(struct net_device *netdev,
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index de72b0a3867f..0f352019ef99 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -45,7 +45,6 @@ enum switchdev_attr_id {
SWITCHDEV_ATTR_ID_UNDEFINED,
SWITCHDEV_ATTR_ID_PORT_STP_STATE,
SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
- SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS,
SWITCHDEV_ATTR_ID_PORT_MROUTER,
SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
@@ -63,7 +62,6 @@ struct switchdev_attr {
union {
u8 stp_state; /* PORT_STP_STATE */
unsigned long brport_flags; /* PORT_{PRE}_BRIDGE_FLAGS */
- unsigned long brport_flags_support; /* PORT_BRIDGE_FLAGS_SUPPORT */
bool mrouter; /* PORT_MROUTER */
clock_t ageing_time; /* BRIDGE_AGEING_TIME */
bool vlan_filtering; /* BRIDGE_VLAN_FILTERING */
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 44cc4e50dd5a..db0a2651070f 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -388,21 +388,7 @@ static int dsa_slave_get_port_parent_id(struct net_device *dev,
static int dsa_slave_port_attr_get(struct net_device *dev,
struct switchdev_attr *attr)
{
- struct dsa_port *dp = dsa_slave_to_port(dev);
- struct dsa_switch *ds = dp->ds;
-
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
- attr->u.brport_flags_support = 0;
- if (ds->ops->port_egress_floods)
- attr->u.brport_flags_support |= BR_FLOOD |
- BR_MCAST_FLOOD;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
+ return -EOPNOTSUPP;
}
static inline netdev_tx_t dsa_slave_netpoll_send_skb(struct net_device *dev,
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v3 8/8] net: Get rid of switchdev_port_attr_get()
From: Florian Fainelli @ 2019-02-21 0:58 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, David S. Miller, Ido Schimmel, open list,
open list:STAGING SUBSYSTEM, moderated list:ETHERNET BRIDGE, jiri,
andrew, vivien.didelot
In-Reply-To: <20190221005826.26317-1-f.fainelli@gmail.com>
With the bridge no longer calling switchdev_port_attr_get() to obtain
the supported bridge port flags from a driver but instead trying to set
the bridge port flags directly and relying on driver to reject
unsupported configurations, we can effectively get rid of
switchdev_port_attr_get() entirely since this was the only place where
it was called.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
Documentation/networking/switchdev.txt | 2 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 7 -------
drivers/net/ethernet/rocker/rocker_main.c | 7 -------
drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 7 -------
include/net/switchdev.h | 8 --------
net/dsa/slave.c | 7 -------
6 files changed, 1 insertion(+), 37 deletions(-)
diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt
index 79c8b0f16aee..413abbae952f 100644
--- a/Documentation/networking/switchdev.txt
+++ b/Documentation/networking/switchdev.txt
@@ -233,7 +233,7 @@ the bridge's FDB. It's possible, but not optimal, to enable learning on the
device port and on the bridge port, and disable learning_sync.
To support learning, the driver implements switchdev op
-switchdev_port_attr_get/set for SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS.
+switchdev_port_attr_set for SWITCHDEV_ATTR_PORT_ID_{PRE}_BRIDGE_FLAGS.
FDB Ageing
^^^^^^^^^^
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index bbb5a406232e..766f5b5f1cf5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -431,12 +431,6 @@ static void mlxsw_sp_bridge_vlan_put(struct mlxsw_sp_bridge_vlan *bridge_vlan)
mlxsw_sp_bridge_vlan_destroy(bridge_vlan);
}
-static int mlxsw_sp_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
-{
- return -EOPNOTSUPP;
-}
-
static int
mlxsw_sp_port_bridge_vlan_stp_set(struct mlxsw_sp_port *mlxsw_sp_port,
struct mlxsw_sp_bridge_vlan *bridge_vlan,
@@ -1945,7 +1939,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp,
}
static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = {
- .switchdev_port_attr_get = mlxsw_sp_port_attr_get,
.switchdev_port_attr_set = mlxsw_sp_port_attr_set,
};
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 6b8273e2057d..8200fbf91306 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2066,12 +2066,6 @@ static const struct net_device_ops rocker_port_netdev_ops = {
* swdev interface
********************/
-static int rocker_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
-{
- return -EOPNOTSUPP;
-}
-
static int rocker_port_attr_set(struct net_device *dev,
const struct switchdev_attr *attr,
struct switchdev_trans *trans)
@@ -2148,7 +2142,6 @@ static int rocker_port_obj_del(struct net_device *dev,
}
static const struct switchdev_ops rocker_port_switchdev_ops = {
- .switchdev_port_attr_get = rocker_port_attr_get,
.switchdev_port_attr_set = rocker_port_attr_set,
};
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index de4dcabbc29a..018399ee8731 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -640,12 +640,6 @@ static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev)
fsl_mc_free_irqs(sw_dev);
}
-static int swdev_port_attr_get(struct net_device *netdev,
- struct switchdev_attr *attr)
-{
- return -EOPNOTSUPP;
-}
-
static int port_attr_stp_state_set(struct net_device *netdev,
struct switchdev_trans *trans,
u8 state)
@@ -932,7 +926,6 @@ static int swdev_port_obj_del(struct net_device *netdev,
}
static const struct switchdev_ops ethsw_port_switchdev_ops = {
- .switchdev_port_attr_get = swdev_port_attr_get,
.switchdev_port_attr_set = swdev_port_attr_set,
};
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 0f352019ef99..45310ddf2d7e 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -179,8 +179,6 @@ switchdev_notifier_info_to_extack(const struct switchdev_notifier_info *info)
#ifdef CONFIG_NET_SWITCHDEV
void switchdev_deferred_process(void);
-int switchdev_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr);
int switchdev_port_attr_set(struct net_device *dev,
const struct switchdev_attr *attr);
int switchdev_port_obj_add(struct net_device *dev,
@@ -225,12 +223,6 @@ static inline void switchdev_deferred_process(void)
{
}
-static inline int switchdev_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
-{
- return -EOPNOTSUPP;
-}
-
static inline int switchdev_port_attr_set(struct net_device *dev,
const struct switchdev_attr *attr)
{
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index db0a2651070f..a78b2bba0332 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -385,12 +385,6 @@ static int dsa_slave_get_port_parent_id(struct net_device *dev,
return 0;
}
-static int dsa_slave_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
-{
- return -EOPNOTSUPP;
-}
-
static inline netdev_tx_t dsa_slave_netpoll_send_skb(struct net_device *dev,
struct sk_buff *skb)
{
@@ -1057,7 +1051,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
};
static const struct switchdev_ops dsa_slave_switchdev_ops = {
- .switchdev_port_attr_get = dsa_slave_port_attr_get,
.switchdev_port_attr_set = dsa_slave_port_attr_set,
};
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v3 4/8] net: dsa: Add setter for SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS
From: Florian Fainelli @ 2019-02-21 0:58 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, David S. Miller, Ido Schimmel, open list,
open list:STAGING SUBSYSTEM, moderated list:ETHERNET BRIDGE, jiri,
andrew, vivien.didelot
In-Reply-To: <20190221005826.26317-1-f.fainelli@gmail.com>
In preparation for removing SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
add support for a function that processes the
SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS and
SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS attributes and returns not
supported for any flag set, since DSA does not currently support
toggling those bridge port attributes (yet).
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/dsa/dsa_priv.h | 2 ++
net/dsa/port.c | 12 ++++++++++++
net/dsa/slave.c | 4 ++++
3 files changed, 18 insertions(+)
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index f4f99ec29f5d..47a1d1379d15 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -160,6 +160,8 @@ int dsa_port_mdb_add(const struct dsa_port *dp,
struct switchdev_trans *trans);
int dsa_port_mdb_del(const struct dsa_port *dp,
const struct switchdev_obj_port_mdb *mdb);
+int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags,
+ struct switchdev_trans *trans);
int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags,
struct switchdev_trans *trans);
int dsa_port_vlan_add(struct dsa_port *dp,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 7bc2a5ad95c6..e9b5b50f8cf1 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -187,6 +187,18 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
return dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info);
}
+int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags,
+ struct switchdev_trans *trans)
+{
+ struct dsa_switch *ds = dp->ds;
+
+ if (!ds->ops->port_egress_floods ||
+ (flags & ~(BR_FLOOD | BR_MCAST_FLOOD)))
+ return -EINVAL;
+
+ return 0;
+}
+
int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags,
struct switchdev_trans *trans)
{
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 85dc68611002..44cc4e50dd5a 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -295,6 +295,10 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
ret = dsa_port_ageing_time(dp, attr->u.ageing_time, trans);
break;
+ case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
+ ret = dsa_port_pre_bridge_flags(dp, attr->u.brport_flags,
+ trans);
+ break;
case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
ret = dsa_port_bridge_flags(dp, attr->u.brport_flags, trans);
break;
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v3 1/8] net: switchdev: Add PORT_PRE_BRIDGE_FLAGS
From: Florian Fainelli @ 2019-02-21 0:58 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, David S. Miller, Ido Schimmel, open list,
open list:STAGING SUBSYSTEM, moderated list:ETHERNET BRIDGE, jiri,
andrew, vivien.didelot
In-Reply-To: <20190221005826.26317-1-f.fainelli@gmail.com>
In preparation for removing switchdev_port_attr_get(), introduce
PORT_PRE_BRIDGE_FLAGS which will be called through
switchdev_port_attr_set(), in the caller's context (possibly atomic) and
which must be checked by the switchdev driver in order to return whether
the operation is supported or not.
This is entirely analoguous to how the BRIDGE_FLAGS_SUPPORT works,
except it goes through a set() instead of get().
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
include/net/switchdev.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 5e87b54c5dc5..de72b0a3867f 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -46,6 +46,7 @@ enum switchdev_attr_id {
SWITCHDEV_ATTR_ID_PORT_STP_STATE,
SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
+ SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS,
SWITCHDEV_ATTR_ID_PORT_MROUTER,
SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING,
@@ -61,7 +62,7 @@ struct switchdev_attr {
void (*complete)(struct net_device *dev, int err, void *priv);
union {
u8 stp_state; /* PORT_STP_STATE */
- unsigned long brport_flags; /* PORT_BRIDGE_FLAGS */
+ unsigned long brport_flags; /* PORT_{PRE}_BRIDGE_FLAGS */
unsigned long brport_flags_support; /* PORT_BRIDGE_FLAGS_SUPPORT */
bool mrouter; /* PORT_MROUTER */
clock_t ageing_time; /* BRIDGE_AGEING_TIME */
--
2.17.1
^ permalink raw reply related
* Re: [PATCH iproute2] ss: Render buffer to output every time a number of chunks are allocated
From: Stephen Hemminger @ 2019-02-21 1:49 UTC (permalink / raw)
To: Stefano Brivio
Cc: Eric Dumazet, Phil Sutter, David Ahern, Sabrina Dubroca, netdev
In-Reply-To: <20190220175808.4b22b59f@redhat.com>
On Wed, 20 Feb 2019 17:58:08 +0100
Stefano Brivio <sbrivio@redhat.com> wrote:
> Hi Stephen,
>
> I think this patch is reasonably tested now. Eric, who reported the
> original issue, is also satisfied with it. Is there any issue with it?
>
In general, I let non critical patches sit at least if not longer for review.
People are not always glued to their email
^ permalink raw reply
* Re: Handling an Extra Signal at PHY Reset
From: Andrew Lunn @ 2019-02-21 1:49 UTC (permalink / raw)
To: Paul Kocialkowski
Cc: Florian Fainelli, Heiner Kallweit, netdev, Thomas Petazzoni,
Mylène Josserand
In-Reply-To: <e647050a0fbadb8445cf6a7a5a2ccfbfd0865592.camel@bootlin.com>
On Tue, Feb 19, 2019 at 10:14:20AM +0100, Paul Kocialkowski wrote:
> Hi,
>
> We are dealing with an Ethernet PHY (Marvell 88E1512) that comes with a
> CONFIG pin that must be connected to one of the other pins of the PHY
> to configure the LSB of the PHY address as well as I/O voltages (see
> section 2.18.1 Hardware Configuration of the datasheet). It must be
> connected "soon after reset" for the PHY to be correctly configured.
Hi Paul
Turns out the datasheet is publicly available.
So you can at run-time configure the voltage. Page 2, register 24, bit
13.
So back to my last question. Can you address the PHY without using the
switch? Even if it has the wrong voltage?
If you can, you could set the correct voltage in the probe() function.
Andrew
^ permalink raw reply
* Re: [PATCH iproute2] ss: fix compilation under glibc < 2.18
From: Stephen Hemminger @ 2019-02-21 1:53 UTC (permalink / raw)
To: Thomas De Schampheleire; +Cc: netdev, Thomas De Schampheleire
In-Reply-To: <20190220144151.17943-1-patrickdepinguin@gmail.com>
On Wed, 20 Feb 2019 15:41:51 +0100
Thomas De Schampheleire <patrickdepinguin@gmail.com> wrote:
> From: Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>
>
> Commit c759116a0b2b6da8df9687b0a40ac69050132c77 introduced support for
> AF_VSOCK. This define is only provided since glibc version 2.18, so
> compilation fails when using older toolchains.
>
> Provide the necessary definitions if needed.
>
> Signed-off-by: Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>
Not sure why you would want new iproute2 with a 5 year old version of glibc?
Yes that means update your tool chain.
^ permalink raw reply
* Re: [patch iproute2] devlink: relax dpipe table show dependency on resources
From: Stephen Hemminger @ 2019-02-21 2:01 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, dsahern, mlxsw
In-Reply-To: <20190220092109.4496-1-jiri@resnulli.us>
On Wed, 20 Feb 2019 10:21:09 +0100
Jiri Pirko <jiri@resnulli.us> wrote:
> - resource_valid = !!nla_table[DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID];
> + resource_valid = !!nla_table[DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID] &&
> + ctx->resources;
When you add a logical AND operator the !! is no longer needed. The !! convention
is used to turn a value of not zero (ie not NULL) into a boolean. When you add the
additional operator the result is already boolean.
^ permalink raw reply
* RE: [RFC v1 01/19] net/i40e: Add peer register/unregister to struct i40e_netdev_priv
From: Saleem, Shiraz @ 2019-02-21 2:19 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: dledford@redhat.com, davem@davemloft.net,
linux-rdma@vger.kernel.org, netdev@vger.kernel.org,
Ismail, Mustafa, Kirsher, Jeffrey T, Patil, Kiran,
Ertman, David M
In-Reply-To: <20190215172233.GC30706@ziepe.ca>
>Subject: Re: [RFC v1 01/19] net/i40e: Add peer register/unregister to struct
>i40e_netdev_priv
>
>On Fri, Feb 15, 2019 at 11:10:48AM -0600, Shiraz Saleem wrote:
>> Expose the register/unregister function pointers in the struct
>> i40e_netdev_priv which is accesible via the netdev_priv() interface in
>> the RDMA driver. On a netdev notification in the RDMA driver, the
>> appropriate LAN driver register/unregister functions are invoked from
>> the struct i40e_netdev_priv structure,
>
>Why? In later patches we get an entire device_add() based thing. Why do you
>need two things?
>
>The RDMA driver should bind to the thing that device_add created and from there
>reliably get the netdev. It should not listen to netdev notifiers for attachment.
In the new IDC mechanism between ice<->irdma, the LAN driver setups up the
device for us and attaches it to a software bus via device_add() based mechanism.
However, RDMA driver binds to the device only when the LAN 'register' function is
called in irdma. In order to do a unified RDMA driver, this register function is exposed
in the private netdev struct of each LAN driver, so we need a matching LAN driver
netdev (ice or i40e) in irdma to call the 'register' function in the first place.
.
Once the binding is done, the bus infrastructure triggers the probe() for the device
into the 'ice' driver and it in turn calls the irdma probe() where we can get also get
the netdev like your referring to. But there is no software bus object or device the
RDMA driver can bind to without a matching LAN driver being loaded and calling its
register.
There is no ordering guarantee in which irdma, i40e and ice modules load.
The netdev notifier is for the case where the irdma loads before i40e or ice.
The irdma driver listen to the notifiers so that when a supporting LAN drivers netdev
appears (on load), it can register with it.
Shiraz
^ permalink raw reply
* Re: [PATCH net-next 3/3] nfp: devlink: allow flashing the device via devlink
From: Florian Fainelli @ 2019-02-21 2:59 UTC (permalink / raw)
To: Jakub Kicinski, Jiri Pirko; +Cc: davem, netdev, oss-drivers, mkubecek, andrew
In-Reply-To: <20190219164926.23981359@cakuba.netronome.com>
On 2/19/2019 4:49 PM, Jakub Kicinski wrote:
> On Tue, 19 Feb 2019 10:19:42 +0100, Jiri Pirko wrote:
>> Fri, Feb 15, 2019 at 04:44:29PM CET, jakub.kicinski@netronome.com wrote:
>>> On Fri, 15 Feb 2019 11:15:14 +0100, Jiri Pirko wrote:
>>>>> static const struct ethtool_ops nfp_net_ethtool_ops = {
>>>>
>>>> Why don't you use the compat fallback? I think you should.
>>>
>>> You and Michal both asked the same so let me answer the first to ask :)
>>> - if devlink is built as a module the fallback is not reachable.
>>
>> So the fallback is not really good as you can't use it for real drivers
>> anyway. Odd. Maybe we should compile devlink in without possibility to
>> have it as module.
>
> Ack, I'll make devlink a bool.
Meh how about those poor and memory constrained embedded systems?
Ideally ethtool should/could have been modular as well, but that ship
has now sailed.
>
> I need a little extra time, I forgot that nfp's flower offload still
> doesn't register all ports (using your port flavour infrastructure).
>
We have had similar issues with PHYLIB before where we wanted
net/core/ethtool.c to be able to call into generic PHYLIB functions to
obtain PHY statistics, an inline helper that de-references the PHY
device's driver function pointers solved that (look for
phy_ethtool_get_{strings,sset,stats}) while letting PHYLIB remain modular.
devlink_compat_flash_update() is a bit big to be inlined, but why not?
If we make sure we always provide a devlink_mutex and devlink_list that
symbols such that this builds wheter CONFIG_DEVLINK=y|m then everything
else can be determined at runtime whether devlink.ko is loaded or not.
Does that make sense?
--
Florian
^ permalink raw reply
* Re: [RESEND PATCH 3/7] mm/gup: Change GUP fast to use flags rather than a write 'bool'
From: Souptick Joarder @ 2019-02-21 3:18 UTC (permalink / raw)
To: ira.weiny
Cc: John Hubbard, Andrew Morton, Michal Hocko, Kirill A. Shutemov,
Peter Zijlstra, Jason Gunthorpe, Benjamin Herrenschmidt,
Paul Mackerras, David S. Miller, Martin Schwidefsky,
Heiko Carstens, Rich Felker, Yoshinori Sato, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Ralf Baechle, Paul Burton,
James Hogan, linux-kernel, Linux-MM, linux-mips, linuxppc-dev,
linux-s390, linux-sh, sparclinux, kvm-ppc, kvm, linux-fpga,
dri-devel, linux-rdma, linux-media, linux-scsi,
open list:ANDROID DRIVERS, virtualization, netdev, linux-fbdev,
xen-devel, devel, ceph-devel, rds-devel
In-Reply-To: <20190220053040.10831-4-ira.weiny@intel.com>
Hi Ira,
On Wed, Feb 20, 2019 at 11:01 AM <ira.weiny@intel.com> wrote:
>
> From: Ira Weiny <ira.weiny@intel.com>
>
> To facilitate additional options to get_user_pages_fast() change the
> singular write parameter to be gup_flags.
>
> This patch does not change any functionality. New functionality will
> follow in subsequent patches.
>
> Some of the get_user_pages_fast() call sites were unchanged because they
> already passed FOLL_WRITE or 0 for the write parameter.
>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> ---
> arch/mips/mm/gup.c | 11 ++++++-----
> arch/powerpc/kvm/book3s_64_mmu_hv.c | 4 ++--
> arch/powerpc/kvm/e500_mmu.c | 2 +-
> arch/powerpc/mm/mmu_context_iommu.c | 4 ++--
> arch/s390/kvm/interrupt.c | 2 +-
> arch/s390/mm/gup.c | 12 ++++++------
> arch/sh/mm/gup.c | 11 ++++++-----
> arch/sparc/mm/gup.c | 9 +++++----
> arch/x86/kvm/paging_tmpl.h | 2 +-
> arch/x86/kvm/svm.c | 2 +-
> drivers/fpga/dfl-afu-dma-region.c | 2 +-
> drivers/gpu/drm/via/via_dmablit.c | 3 ++-
> drivers/infiniband/hw/hfi1/user_pages.c | 3 ++-
> drivers/misc/genwqe/card_utils.c | 2 +-
> drivers/misc/vmw_vmci/vmci_host.c | 2 +-
> drivers/misc/vmw_vmci/vmci_queue_pair.c | 6 ++++--
> drivers/platform/goldfish/goldfish_pipe.c | 3 ++-
> drivers/rapidio/devices/rio_mport_cdev.c | 4 +++-
> drivers/sbus/char/oradax.c | 2 +-
> drivers/scsi/st.c | 3 ++-
> drivers/staging/gasket/gasket_page_table.c | 4 ++--
> drivers/tee/tee_shm.c | 2 +-
> drivers/vfio/vfio_iommu_spapr_tce.c | 3 ++-
> drivers/vhost/vhost.c | 2 +-
> drivers/video/fbdev/pvr2fb.c | 2 +-
> drivers/virt/fsl_hypervisor.c | 2 +-
> drivers/xen/gntdev.c | 2 +-
> fs/orangefs/orangefs-bufmap.c | 2 +-
> include/linux/mm.h | 4 ++--
> kernel/futex.c | 2 +-
> lib/iov_iter.c | 7 +++++--
> mm/gup.c | 10 +++++-----
> mm/util.c | 8 ++++----
> net/ceph/pagevec.c | 2 +-
> net/rds/info.c | 2 +-
> net/rds/rdma.c | 3 ++-
> 36 files changed, 81 insertions(+), 65 deletions(-)
>
> diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c
> index 0d14e0d8eacf..4c2b4483683c 100644
> --- a/arch/mips/mm/gup.c
> +++ b/arch/mips/mm/gup.c
> @@ -235,7 +235,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> * get_user_pages_fast() - pin user pages in memory
> * @start: starting user address
> * @nr_pages: number of pages from start to pin
> - * @write: whether pages will be written to
> + * @gup_flags: flags modifying pin behaviour
> * @pages: array that receives pointers to the pages pinned.
> * Should be at least nr_pages long.
> *
> @@ -247,8 +247,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> * requested. If nr_pages is 0 or negative, returns 0. If no pages
> * were pinned, returns -errno.
> */
> -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> - struct page **pages)
> +int get_user_pages_fast(unsigned long start, int nr_pages,
> + unsigned int gup_flags, struct page **pages)
> {
> struct mm_struct *mm = current->mm;
> unsigned long addr, len, end;
> @@ -273,7 +273,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> next = pgd_addr_end(addr, end);
> if (pgd_none(pgd))
> goto slow;
> - if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
> + if (!gup_pud_range(pgd, addr, next, gup_flags & FOLL_WRITE,
> + pages, &nr))
> goto slow;
> } while (pgdp++, addr = next, addr != end);
> local_irq_enable();
> @@ -289,7 +290,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> pages += nr;
>
> ret = get_user_pages_unlocked(start, (end - start) >> PAGE_SHIFT,
> - pages, write ? FOLL_WRITE : 0);
> + pages, gup_flags);
>
> /* Have to be a bit careful with return values */
> if (nr > 0) {
> diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> index bd2dcfbf00cd..8fcb0a921e46 100644
> --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
> +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> @@ -582,7 +582,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
> /* If writing != 0, then the HPTE must allow writing, if we get here */
> write_ok = writing;
> hva = gfn_to_hva_memslot(memslot, gfn);
> - npages = get_user_pages_fast(hva, 1, writing, pages);
> + npages = get_user_pages_fast(hva, 1, writing ? FOLL_WRITE : 0, pages);
Just requesting for opinion,
* writing ? FOLL_WRITE : 0 * is used in many places. How about placing it in a
macro/ inline ?
> if (npages < 1) {
> /* Check if it's an I/O mapping */
> down_read(¤t->mm->mmap_sem);
> @@ -1175,7 +1175,7 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
> if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
> goto err;
> hva = gfn_to_hva_memslot(memslot, gfn);
> - npages = get_user_pages_fast(hva, 1, 1, pages);
> + npages = get_user_pages_fast(hva, 1, FOLL_WRITE, pages);
> if (npages < 1)
> goto err;
> page = pages[0];
> diff --git a/arch/powerpc/kvm/e500_mmu.c b/arch/powerpc/kvm/e500_mmu.c
> index 24296f4cadc6..e0af53fd78c5 100644
> --- a/arch/powerpc/kvm/e500_mmu.c
> +++ b/arch/powerpc/kvm/e500_mmu.c
> @@ -783,7 +783,7 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
> if (!pages)
> return -ENOMEM;
>
> - ret = get_user_pages_fast(cfg->array, num_pages, 1, pages);
> + ret = get_user_pages_fast(cfg->array, num_pages, FOLL_WRITE, pages);
> if (ret < 0)
> goto free_pages;
>
> diff --git a/arch/powerpc/mm/mmu_context_iommu.c b/arch/powerpc/mm/mmu_context_iommu.c
> index a712a650a8b6..acb0990c8364 100644
> --- a/arch/powerpc/mm/mmu_context_iommu.c
> +++ b/arch/powerpc/mm/mmu_context_iommu.c
> @@ -190,7 +190,7 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
> for (i = 0; i < entries; ++i) {
> cur_ua = ua + (i << PAGE_SHIFT);
> if (1 != get_user_pages_fast(cur_ua,
> - 1/* pages */, 1/* iswrite */, &page)) {
> + 1/* pages */, FOLL_WRITE, &page)) {
> ret = -EFAULT;
> for (j = 0; j < i; ++j)
> put_page(pfn_to_page(mem->hpas[j] >>
> @@ -209,7 +209,7 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
> if (mm_iommu_move_page_from_cma(page))
> goto populate;
> if (1 != get_user_pages_fast(cur_ua,
> - 1/* pages */, 1/* iswrite */,
> + 1/* pages */, FOLL_WRITE,
> &page)) {
> ret = -EFAULT;
> for (j = 0; j < i; ++j)
> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> index fcb55b02990e..69d9366b966c 100644
> --- a/arch/s390/kvm/interrupt.c
> +++ b/arch/s390/kvm/interrupt.c
> @@ -2278,7 +2278,7 @@ static int kvm_s390_adapter_map(struct kvm *kvm, unsigned int id, __u64 addr)
> ret = -EFAULT;
> goto out;
> }
> - ret = get_user_pages_fast(map->addr, 1, 1, &map->page);
> + ret = get_user_pages_fast(map->addr, 1, FOLL_WRITE, &map->page);
> if (ret < 0)
> goto out;
> BUG_ON(ret != 1);
> diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
> index 2809d11c7a28..0a6faf3d9960 100644
> --- a/arch/s390/mm/gup.c
> +++ b/arch/s390/mm/gup.c
> @@ -265,7 +265,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> * get_user_pages_fast() - pin user pages in memory
> * @start: starting user address
> * @nr_pages: number of pages from start to pin
> - * @write: whether pages will be written to
> + * @gup_flags: flags modifying pin behaviour
> * @pages: array that receives pointers to the pages pinned.
> * Should be at least nr_pages long.
> *
> @@ -277,22 +277,22 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> * requested. If nr_pages is 0 or negative, returns 0. If no pages
> * were pinned, returns -errno.
> */
> -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> - struct page **pages)
> +int get_user_pages_fast(unsigned long start, int nr_pages,
> + unsigned int gup_flags, struct page **pages)
> {
> int nr, ret;
>
> might_sleep();
> start &= PAGE_MASK;
> - nr = __get_user_pages_fast(start, nr_pages, write, pages);
> + nr = __get_user_pages_fast(start, nr_pages, gup_flags & FOLL_WRITE,
> + pages);
> if (nr == nr_pages)
> return nr;
>
> /* Try to get the remaining pages with get_user_pages */
> start += nr << PAGE_SHIFT;
> pages += nr;
> - ret = get_user_pages_unlocked(start, nr_pages - nr, pages,
> - write ? FOLL_WRITE : 0);
> + ret = get_user_pages_unlocked(start, nr_pages - nr, pages, gup_flags);
> /* Have to be a bit careful with return values */
> if (nr > 0)
> ret = (ret < 0) ? nr : ret + nr;
> diff --git a/arch/sh/mm/gup.c b/arch/sh/mm/gup.c
> index 3e27f6d1f1ec..277c882f7489 100644
> --- a/arch/sh/mm/gup.c
> +++ b/arch/sh/mm/gup.c
> @@ -204,7 +204,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> * get_user_pages_fast() - pin user pages in memory
> * @start: starting user address
> * @nr_pages: number of pages from start to pin
> - * @write: whether pages will be written to
> + * @gup_flags: flags modifying pin behaviour
> * @pages: array that receives pointers to the pages pinned.
> * Should be at least nr_pages long.
> *
> @@ -216,8 +216,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> * requested. If nr_pages is 0 or negative, returns 0. If no pages
> * were pinned, returns -errno.
> */
> -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> - struct page **pages)
> +int get_user_pages_fast(unsigned long start, int nr_pages,
> + unsigned int gup_flags, struct page **pages)
> {
> struct mm_struct *mm = current->mm;
> unsigned long addr, len, end;
> @@ -241,7 +241,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> next = pgd_addr_end(addr, end);
> if (pgd_none(pgd))
> goto slow;
> - if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
> + if (!gup_pud_range(pgd, addr, next, gup_flags & FOLL_WRITE,
> + pages, &nr))
> goto slow;
> } while (pgdp++, addr = next, addr != end);
> local_irq_enable();
> @@ -261,7 +262,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
>
> ret = get_user_pages_unlocked(start,
> (end - start) >> PAGE_SHIFT, pages,
> - write ? FOLL_WRITE : 0);
> + gup_flags);
>
> /* Have to be a bit careful with return values */
> if (nr > 0) {
> diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
> index aee6dba83d0e..1e770a517d4a 100644
> --- a/arch/sparc/mm/gup.c
> +++ b/arch/sparc/mm/gup.c
> @@ -245,8 +245,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> return nr;
> }
>
> -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> - struct page **pages)
> +int get_user_pages_fast(unsigned long start, int nr_pages,
> + unsigned int gup_flags, struct page **pages)
> {
> struct mm_struct *mm = current->mm;
> unsigned long addr, len, end;
> @@ -303,7 +303,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> next = pgd_addr_end(addr, end);
> if (pgd_none(pgd))
> goto slow;
> - if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
> + if (!gup_pud_range(pgd, addr, next, gup_flags & FOLL_WRITE,
> + pages, &nr))
> goto slow;
> } while (pgdp++, addr = next, addr != end);
>
> @@ -324,7 +325,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
>
> ret = get_user_pages_unlocked(start,
> (end - start) >> PAGE_SHIFT, pages,
> - write ? FOLL_WRITE : 0);
> + gup_flags);
>
> /* Have to be a bit careful with return values */
> if (nr > 0) {
> diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
> index 6bdca39829bc..08715034e315 100644
> --- a/arch/x86/kvm/paging_tmpl.h
> +++ b/arch/x86/kvm/paging_tmpl.h
> @@ -140,7 +140,7 @@ static int FNAME(cmpxchg_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
> pt_element_t *table;
> struct page *page;
>
> - npages = get_user_pages_fast((unsigned long)ptep_user, 1, 1, &page);
> + npages = get_user_pages_fast((unsigned long)ptep_user, 1, FOLL_WRITE, &page);
> /* Check if the user is doing something meaningless. */
> if (unlikely(npages != 1))
> return -EFAULT;
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index f13a3a24d360..173596a020cb 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -1803,7 +1803,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,
> return NULL;
>
> /* Pin the user virtual address. */
> - npinned = get_user_pages_fast(uaddr, npages, write ? FOLL_WRITE : 0, pages);
> + npinned = get_user_pages_fast(uaddr, npages, FOLL_WRITE, pages);
> if (npinned != npages) {
> pr_err("SEV: Failure locking %lu pages.\n", npages);
> goto err;
> diff --git a/drivers/fpga/dfl-afu-dma-region.c b/drivers/fpga/dfl-afu-dma-region.c
> index e18a786fc943..c438722bf4e1 100644
> --- a/drivers/fpga/dfl-afu-dma-region.c
> +++ b/drivers/fpga/dfl-afu-dma-region.c
> @@ -102,7 +102,7 @@ static int afu_dma_pin_pages(struct dfl_feature_platform_data *pdata,
> goto unlock_vm;
> }
>
> - pinned = get_user_pages_fast(region->user_addr, npages, 1,
> + pinned = get_user_pages_fast(region->user_addr, npages, FOLL_WRITE,
> region->pages);
> if (pinned < 0) {
> ret = pinned;
> diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c
> index 345bda4494e1..0c8b09602910 100644
> --- a/drivers/gpu/drm/via/via_dmablit.c
> +++ b/drivers/gpu/drm/via/via_dmablit.c
> @@ -239,7 +239,8 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
> if (NULL == vsg->pages)
> return -ENOMEM;
> ret = get_user_pages_fast((unsigned long)xfer->mem_addr,
> - vsg->num_pages, vsg->direction == DMA_FROM_DEVICE,
> + vsg->num_pages,
> + vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
> vsg->pages);
> if (ret != vsg->num_pages) {
> if (ret < 0)
> diff --git a/drivers/infiniband/hw/hfi1/user_pages.c b/drivers/infiniband/hw/hfi1/user_pages.c
> index 24b592c6522e..78ccacaf97d0 100644
> --- a/drivers/infiniband/hw/hfi1/user_pages.c
> +++ b/drivers/infiniband/hw/hfi1/user_pages.c
> @@ -105,7 +105,8 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t np
> {
> int ret;
>
> - ret = get_user_pages_fast(vaddr, npages, writable, pages);
> + ret = get_user_pages_fast(vaddr, npages, writable ? FOLL_WRITE : 0,
> + pages);
> if (ret < 0)
> return ret;
>
> diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
> index 25265fd0fd6e..89cff9d1012b 100644
> --- a/drivers/misc/genwqe/card_utils.c
> +++ b/drivers/misc/genwqe/card_utils.c
> @@ -603,7 +603,7 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr,
> /* pin user pages in memory */
> rc = get_user_pages_fast(data & PAGE_MASK, /* page aligned addr */
> m->nr_pages,
> - m->write, /* readable/writable */
> + m->write ? FOLL_WRITE : 0, /* readable/writable */
> m->page_list); /* ptrs to pages */
> if (rc < 0)
> goto fail_get_user_pages;
> diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c
> index 997f92543dd4..422d08da3244 100644
> --- a/drivers/misc/vmw_vmci/vmci_host.c
> +++ b/drivers/misc/vmw_vmci/vmci_host.c
> @@ -242,7 +242,7 @@ static int vmci_host_setup_notify(struct vmci_ctx *context,
> /*
> * Lock physical page backing a given user VA.
> */
> - retval = get_user_pages_fast(uva, 1, 1, &context->notify_page);
> + retval = get_user_pages_fast(uva, 1, FOLL_WRITE, &context->notify_page);
> if (retval != 1) {
> context->notify_page = NULL;
> return VMCI_ERROR_GENERIC;
> diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c
> index 264f4ed8eef2..c5396ee32e51 100644
> --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c
> +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c
> @@ -666,7 +666,8 @@ static int qp_host_get_user_memory(u64 produce_uva,
> int err = VMCI_SUCCESS;
>
> retval = get_user_pages_fast((uintptr_t) produce_uva,
> - produce_q->kernel_if->num_pages, 1,
> + produce_q->kernel_if->num_pages,
> + FOLL_WRITE,
> produce_q->kernel_if->u.h.header_page);
> if (retval < (int)produce_q->kernel_if->num_pages) {
> pr_debug("get_user_pages_fast(produce) failed (retval=%d)",
> @@ -678,7 +679,8 @@ static int qp_host_get_user_memory(u64 produce_uva,
> }
>
> retval = get_user_pages_fast((uintptr_t) consume_uva,
> - consume_q->kernel_if->num_pages, 1,
> + consume_q->kernel_if->num_pages,
> + FOLL_WRITE,
> consume_q->kernel_if->u.h.header_page);
> if (retval < (int)consume_q->kernel_if->num_pages) {
> pr_debug("get_user_pages_fast(consume) failed (retval=%d)",
> diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c
> index 321bc673c417..cef0133aa47a 100644
> --- a/drivers/platform/goldfish/goldfish_pipe.c
> +++ b/drivers/platform/goldfish/goldfish_pipe.c
> @@ -274,7 +274,8 @@ static int pin_user_pages(unsigned long first_page,
> *iter_last_page_size = last_page_size;
> }
>
> - ret = get_user_pages_fast(first_page, requested_pages, !is_write,
> + ret = get_user_pages_fast(first_page, requested_pages,
> + !is_write ? FOLL_WRITE : 0,
> pages);
> if (ret <= 0)
> return -EFAULT;
> diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c
> index cbe467ff1aba..f681b3e9e970 100644
> --- a/drivers/rapidio/devices/rio_mport_cdev.c
> +++ b/drivers/rapidio/devices/rio_mport_cdev.c
> @@ -868,7 +868,9 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
>
> pinned = get_user_pages_fast(
> (unsigned long)xfer->loc_addr & PAGE_MASK,
> - nr_pages, dir == DMA_FROM_DEVICE, page_list);
> + nr_pages,
> + dir == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
> + page_list);
>
> if (pinned != nr_pages) {
> if (pinned < 0) {
> diff --git a/drivers/sbus/char/oradax.c b/drivers/sbus/char/oradax.c
> index 6516bc3cb58b..790aa148670d 100644
> --- a/drivers/sbus/char/oradax.c
> +++ b/drivers/sbus/char/oradax.c
> @@ -437,7 +437,7 @@ static int dax_lock_page(void *va, struct page **p)
>
> dax_dbg("uva %p", va);
>
> - ret = get_user_pages_fast((unsigned long)va, 1, 1, p);
> + ret = get_user_pages_fast((unsigned long)va, 1, FOLL_WRITE, p);
> if (ret == 1) {
> dax_dbg("locked page %p, for VA %p", *p, va);
> return 0;
> diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
> index 7ff22d3f03e3..871b25914c07 100644
> --- a/drivers/scsi/st.c
> +++ b/drivers/scsi/st.c
> @@ -4918,7 +4918,8 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
>
> /* Try to fault in all of the necessary pages */
> /* rw==READ means read from drive, write into memory area */
> - res = get_user_pages_fast(uaddr, nr_pages, rw == READ, pages);
> + res = get_user_pages_fast(uaddr, nr_pages, rw == READ ? FOLL_WRITE : 0,
> + pages);
>
> /* Errors and no page mapped should return here */
> if (res < nr_pages)
> diff --git a/drivers/staging/gasket/gasket_page_table.c b/drivers/staging/gasket/gasket_page_table.c
> index 26755d9ca41d..f67fdf1d3817 100644
> --- a/drivers/staging/gasket/gasket_page_table.c
> +++ b/drivers/staging/gasket/gasket_page_table.c
> @@ -486,8 +486,8 @@ static int gasket_perform_mapping(struct gasket_page_table *pg_tbl,
> ptes[i].dma_addr = pg_tbl->coherent_pages[0].paddr +
> off + i * PAGE_SIZE;
> } else {
> - ret = get_user_pages_fast(page_addr - offset, 1, 1,
> - &page);
> + ret = get_user_pages_fast(page_addr - offset, 1,
> + FOLL_WRITE, &page);
>
> if (ret <= 0) {
> dev_err(pg_tbl->device,
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index 0b9ab1d0dd45..49fd7312e2aa 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -273,7 +273,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> goto err;
> }
>
> - rc = get_user_pages_fast(start, num_pages, 1, shm->pages);
> + rc = get_user_pages_fast(start, num_pages, FOLL_WRITE, shm->pages);
> if (rc > 0)
> shm->num_pages = rc;
> if (rc != num_pages) {
> diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
> index c424913324e3..a4b10bb4086b 100644
> --- a/drivers/vfio/vfio_iommu_spapr_tce.c
> +++ b/drivers/vfio/vfio_iommu_spapr_tce.c
> @@ -532,7 +532,8 @@ static int tce_iommu_use_page(unsigned long tce, unsigned long *hpa)
> enum dma_data_direction direction = iommu_tce_direction(tce);
>
> if (get_user_pages_fast(tce & PAGE_MASK, 1,
> - direction != DMA_TO_DEVICE, &page) != 1)
> + direction != DMA_TO_DEVICE ? FOLL_WRITE : 0,
> + &page) != 1)
> return -EFAULT;
>
> *hpa = __pa((unsigned long) page_address(page));
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 24a129fcdd61..72685b1659ff 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -1700,7 +1700,7 @@ static int set_bit_to_user(int nr, void __user *addr)
> int bit = nr + (log % PAGE_SIZE) * 8;
> int r;
>
> - r = get_user_pages_fast(log, 1, 1, &page);
> + r = get_user_pages_fast(log, 1, FOLL_WRITE, &page);
> if (r < 0)
> return r;
> BUG_ON(r != 1);
> diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
> index 8a53d1de611d..41390c8e0f67 100644
> --- a/drivers/video/fbdev/pvr2fb.c
> +++ b/drivers/video/fbdev/pvr2fb.c
> @@ -686,7 +686,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
> if (!pages)
> return -ENOMEM;
>
> - ret = get_user_pages_fast((unsigned long)buf, nr_pages, true, pages);
> + ret = get_user_pages_fast((unsigned long)buf, nr_pages, FOLL_WRITE, pages);
> if (ret < nr_pages) {
> nr_pages = ret;
> ret = -EINVAL;
> diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c
> index 8ba726e600e9..6446bcab4185 100644
> --- a/drivers/virt/fsl_hypervisor.c
> +++ b/drivers/virt/fsl_hypervisor.c
> @@ -244,7 +244,7 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
>
> /* Get the physical addresses of the source buffer */
> num_pinned = get_user_pages_fast(param.local_vaddr - lb_offset,
> - num_pages, param.source != -1, pages);
> + num_pages, param.source != -1 ? FOLL_WRITE : 0, pages);
>
> if (num_pinned != num_pages) {
> /* get_user_pages() failed */
> diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
> index 5efc5eee9544..7b47f1e6aab4 100644
> --- a/drivers/xen/gntdev.c
> +++ b/drivers/xen/gntdev.c
> @@ -852,7 +852,7 @@ static int gntdev_get_page(struct gntdev_copy_batch *batch, void __user *virt,
> unsigned long xen_pfn;
> int ret;
>
> - ret = get_user_pages_fast(addr, 1, writeable, &page);
> + ret = get_user_pages_fast(addr, 1, writeable ? FOLL_WRITE : 0, &page);
> if (ret < 0)
> return ret;
>
> diff --git a/fs/orangefs/orangefs-bufmap.c b/fs/orangefs/orangefs-bufmap.c
> index 443bcd8c3c19..5a7c4fda682f 100644
> --- a/fs/orangefs/orangefs-bufmap.c
> +++ b/fs/orangefs/orangefs-bufmap.c
> @@ -269,7 +269,7 @@ orangefs_bufmap_map(struct orangefs_bufmap *bufmap,
>
> /* map the pages */
> ret = get_user_pages_fast((unsigned long)user_desc->ptr,
> - bufmap->page_count, 1, bufmap->page_array);
> + bufmap->page_count, FOLL_WRITE, bufmap->page_array);
>
> if (ret < 0)
> return ret;
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 05a105d9d4c3..8e1f3cd7482a 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1537,8 +1537,8 @@ long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
> long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
> struct page **pages, unsigned int gup_flags);
>
> -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> - struct page **pages);
> +int get_user_pages_fast(unsigned long start, int nr_pages,
> + unsigned int gup_flags, struct page **pages);
>
> /* Container for pinned pfns / pages */
> struct frame_vector {
> diff --git a/kernel/futex.c b/kernel/futex.c
> index fdd312da0992..e10209946f8b 100644
> --- a/kernel/futex.c
> +++ b/kernel/futex.c
> @@ -546,7 +546,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, enum futex_a
> if (unlikely(should_fail_futex(fshared)))
> return -EFAULT;
>
> - err = get_user_pages_fast(address, 1, 1, &page);
> + err = get_user_pages_fast(address, 1, FOLL_WRITE, &page);
> /*
> * If write access is not required (eg. FUTEX_WAIT), try
> * and get read-only access.
> diff --git a/lib/iov_iter.c b/lib/iov_iter.c
> index be4bd627caf0..6dbae0692719 100644
> --- a/lib/iov_iter.c
> +++ b/lib/iov_iter.c
> @@ -1280,7 +1280,9 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
> len = maxpages * PAGE_SIZE;
> addr &= ~(PAGE_SIZE - 1);
> n = DIV_ROUND_UP(len, PAGE_SIZE);
> - res = get_user_pages_fast(addr, n, iov_iter_rw(i) != WRITE, pages);
> + res = get_user_pages_fast(addr, n,
> + iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0,
> + pages);
> if (unlikely(res < 0))
> return res;
> return (res == n ? len : res * PAGE_SIZE) - *start;
> @@ -1361,7 +1363,8 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
> p = get_pages_array(n);
> if (!p)
> return -ENOMEM;
> - res = get_user_pages_fast(addr, n, iov_iter_rw(i) != WRITE, p);
> + res = get_user_pages_fast(addr, n,
> + iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, p);
> if (unlikely(res < 0)) {
> kvfree(p);
> return res;
> diff --git a/mm/gup.c b/mm/gup.c
> index 681388236106..6f32d36b3c5b 100644
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -1863,7 +1863,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> * get_user_pages_fast() - pin user pages in memory
> * @start: starting user address
> * @nr_pages: number of pages from start to pin
> - * @write: whether pages will be written to
> + * @gup_flags: flags modifying pin behaviour
> * @pages: array that receives pointers to the pages pinned.
> * Should be at least nr_pages long.
> *
> @@ -1875,8 +1875,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> * requested. If nr_pages is 0 or negative, returns 0. If no pages
> * were pinned, returns -errno.
> */
> -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> - struct page **pages)
> +int get_user_pages_fast(unsigned long start, int nr_pages,
> + unsigned int gup_flags, struct page **pages)
> {
> unsigned long addr, len, end;
> int nr = 0, ret = 0;
> @@ -1894,7 +1894,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
>
> if (gup_fast_permitted(start, nr_pages)) {
> local_irq_disable();
> - gup_pgd_range(addr, end, write ? FOLL_WRITE : 0, pages, &nr);
> + gup_pgd_range(addr, end, gup_flags, pages, &nr);
> local_irq_enable();
> ret = nr;
> }
> @@ -1905,7 +1905,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> pages += nr;
>
> ret = get_user_pages_unlocked(start, nr_pages - nr, pages,
> - write ? FOLL_WRITE : 0);
> + gup_flags);
>
> /* Have to be a bit careful with return values */
> if (nr > 0) {
> diff --git a/mm/util.c b/mm/util.c
> index 1ea055138043..01ffe145c62b 100644
> --- a/mm/util.c
> +++ b/mm/util.c
> @@ -306,7 +306,7 @@ EXPORT_SYMBOL_GPL(__get_user_pages_fast);
> * get_user_pages_fast() - pin user pages in memory
> * @start: starting user address
> * @nr_pages: number of pages from start to pin
> - * @write: whether pages will be written to
> + * @gup_flags: flags modifying pin behaviour
> * @pages: array that receives pointers to the pages pinned.
> * Should be at least nr_pages long.
> *
> @@ -327,10 +327,10 @@ EXPORT_SYMBOL_GPL(__get_user_pages_fast);
> * get_user_pages_fast simply falls back to get_user_pages.
> */
> int __weak get_user_pages_fast(unsigned long start,
> - int nr_pages, int write, struct page **pages)
> + int nr_pages, unsigned int gup_flags,
> + struct page **pages)
> {
> - return get_user_pages_unlocked(start, nr_pages, pages,
> - write ? FOLL_WRITE : 0);
> + return get_user_pages_unlocked(start, nr_pages, pages, gup_flags);
> }
> EXPORT_SYMBOL_GPL(get_user_pages_fast);
>
> diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c
> index d3736f5bffec..74cafc0142ea 100644
> --- a/net/ceph/pagevec.c
> +++ b/net/ceph/pagevec.c
> @@ -27,7 +27,7 @@ struct page **ceph_get_direct_page_vector(const void __user *data,
> while (got < num_pages) {
> rc = get_user_pages_fast(
> (unsigned long)data + ((unsigned long)got * PAGE_SIZE),
> - num_pages - got, write_page, pages + got);
> + num_pages - got, write_page ? FOLL_WRITE : 0, pages + got);
> if (rc < 0)
> break;
> BUG_ON(rc == 0);
> diff --git a/net/rds/info.c b/net/rds/info.c
> index e367a97a18c8..03f6fd56d237 100644
> --- a/net/rds/info.c
> +++ b/net/rds/info.c
> @@ -193,7 +193,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,
> ret = -ENOMEM;
> goto out;
> }
> - ret = get_user_pages_fast(start, nr_pages, 1, pages);
> + ret = get_user_pages_fast(start, nr_pages, FOLL_WRITE, pages);
> if (ret != nr_pages) {
> if (ret > 0)
> nr_pages = ret;
> diff --git a/net/rds/rdma.c b/net/rds/rdma.c
> index 182ab8430594..b340ed4fc43a 100644
> --- a/net/rds/rdma.c
> +++ b/net/rds/rdma.c
> @@ -158,7 +158,8 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages,
> {
> int ret;
>
> - ret = get_user_pages_fast(user_addr, nr_pages, write, pages);
> + ret = get_user_pages_fast(user_addr, nr_pages, write ? FOLL_WRITE : 0,
> + pages);
>
> if (ret >= 0 && ret < nr_pages) {
> while (ret--)
> --
> 2.20.1
>
^ permalink raw reply
* Re: [RFC PATCH net-next v3 15/21] ethtool: provide link settings and link modes in GET_SETTINGS request
From: Florian Fainelli @ 2019-02-21 3:14 UTC (permalink / raw)
To: Michal Kubecek, netdev
Cc: David Miller, Andrew Lunn, Jakub Kicinski, Jiri Pirko,
linux-kernel
In-Reply-To: <00e931c1ecd29bf302a190c7d7a3f2cbd0388542.1550513384.git.mkubecek@suse.cz>
On 2/18/2019 10:22 AM, Michal Kubecek wrote:
> Implement GET_SETTINGS netlink request to get link settings and link mode
> information provided by ETHTOOL_GLINKSETTINGS ioctl command.
>
> The information is divided into two parts: supported, advertised and peer
> advertised link modes when ETH_SETTINGS_IM_LINKMODES flag is set in the
> request and other settings when ETH_SETTINGS_IM_LINKINFO is set.
>
> Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
> ---
[snip]
> +#define ETH_SETTINGS_IM_LINKINFO 0x01
> +#define ETH_SETTINGS_IM_LINKMODES 0x02
> +
> +#define ETH_SETTINGS_IM_ALL 0x03
You could define ETH_SETTINGS_IM_ALL as:
#define ETH_SETTING_IM_ALL \
(ETH_SETTINGS_IM_LINKINFO |
ETH_SETTINGS_IM_LINMODES)
that would scale better IMHO, especially given that you have to keep
bumping that mask with new bits in subsequent patches.
[snip]
> + if (tb[ETHA_SETTINGS_INFOMASK])
> + req_info->req_mask = nla_get_u32(tb[ETHA_SETTINGS_INFOMASK]);
> + if (tb[ETHA_SETTINGS_COMPACT])
> + req_info->compact = true;
> + if (req_info->req_mask == 0)
> + req_info->req_mask = ETH_SETTINGS_IM_ALL;
What if userland is newer than the kernel and specifies a req_mask with
bits set that you don't support? Should not you always do an &
ETH_SETTINGS_IM_ALL here?
[snip]
--
Florian
^ permalink raw reply
* Re: [PATCH bpf-next 1/9] bpf: Add bpf helper bpf_tcp_enter_cwr
From: Lawrence Brakmo @ 2019-02-21 3:18 UTC (permalink / raw)
To: Eric Dumazet, netdev; +Cc: Martin Lau, Alexei Starovoitov, Daniel Borkmann
In-Reply-To: <67c8aaa3-81a5-b1c2-5be4-938a139f3013@gmail.com>
On 2/19/19, 10:30 AM, "Eric Dumazet" <eric.dumazet@gmail.com> wrote:
On 02/18/2019 09:38 PM, brakmo wrote:
> This patch adds a new bpf helper BPF_FUNC_tcp_enter_cwr
> "int bpf_tcp_enter_cwr(struct bpf_tcp_sock *tp)".
> It is added to BPF_PROG_TYPE_CGROUP_SKB typed bpf_prog
> which currently can be attached to the ingress and egress
> path.
>
Do we have the guarantee socket is a tcp one, and that the caller
owns the socket lock ?
Yes. The BPF verifier insures that a pointer to bpf_tcp_sock points to a non-NULL full tcp socket.
Please describe the exact context for this helper being used.
From cgroup skb egress bpf program. When the BPF program determines that a flow needs to slow down, it will call bpf_tcp_enter_cwr(tp).
^ permalink raw reply
* Re: [PATCH net-next 3/3] nfp: devlink: allow flashing the device via devlink
From: Jakub Kicinski @ 2019-02-21 3:20 UTC (permalink / raw)
To: Florian Fainelli; +Cc: Jiri Pirko, davem, netdev, oss-drivers, mkubecek, andrew
In-Reply-To: <befeae18-f80e-6f2f-3e97-28629200cf92@gmail.com>
On Wed, 20 Feb 2019 18:59:05 -0800, Florian Fainelli wrote:
> On 2/19/2019 4:49 PM, Jakub Kicinski wrote:
> > On Tue, 19 Feb 2019 10:19:42 +0100, Jiri Pirko wrote:
> >> Fri, Feb 15, 2019 at 04:44:29PM CET, jakub.kicinski@netronome.com wrote:
> >>> On Fri, 15 Feb 2019 11:15:14 +0100, Jiri Pirko wrote:
> >>>>> static const struct ethtool_ops nfp_net_ethtool_ops = {
> >>>>
> >>>> Why don't you use the compat fallback? I think you should.
> >>>
> >>> You and Michal both asked the same so let me answer the first to ask :)
> >>> - if devlink is built as a module the fallback is not reachable.
> >>
> >> So the fallback is not really good as you can't use it for real drivers
> >> anyway. Odd. Maybe we should compile devlink in without possibility to
> >> have it as module.
> >
> > Ack, I'll make devlink a bool.
>
> Meh how about those poor and memory constrained embedded systems?
> Ideally ethtool should/could have been modular as well, but that ship
> has now sailed.
To be clear - I'm not going to add a dependency. You'll still be able
to use ethtool without devlink (granted, you won't be able to flash the
device).
It's not immediately clear to me how devlink being modular saves memory.
The way I see it you either:
(a) not have networking or need any devlink related functionality, and
therefore do DEVLINK=n;
or:
(b) have a networking device driver built and loaded which will depend
on devlink, so devlink will practically speaking always be loaded,
even if its =m.
> > I need a little extra time, I forgot that nfp's flower offload still
> > doesn't register all ports (using your port flavour infrastructure).
>
> We have had similar issues with PHYLIB before where we wanted
> net/core/ethtool.c to be able to call into generic PHYLIB functions to
> obtain PHY statistics, an inline helper that de-references the PHY
> device's driver function pointers solved that (look for
> phy_ethtool_get_{strings,sset,stats}) while letting PHYLIB remain modular.
>
> devlink_compat_flash_update() is a bit big to be inlined, but why not?
>
> If we make sure we always provide a devlink_mutex and devlink_list that
> symbols such that this builds wheter CONFIG_DEVLINK=y|m then everything
> else can be determined at runtime whether devlink.ko is loaded or not.
>
> Does that make sense?
I think so, we'd have to have a little object that would always be
built-in when DEVLINK=m, and therefore accessible?
^ permalink raw reply
* Re: [RFC PATCH net-next v3 00/21] ethtool netlink interface, part 1
From: Florian Fainelli @ 2019-02-21 3:21 UTC (permalink / raw)
To: Michal Kubecek, netdev
Cc: David Miller, Andrew Lunn, Jakub Kicinski, Jiri Pirko,
linux-kernel
In-Reply-To: <cover.1550513384.git.mkubecek@suse.cz>
Hi Michal,
Let me start with a big thank you for tackling this humongous amount of
work!
On 2/18/2019 10:21 AM, Michal Kubecek wrote:
> Note: this is marked as RFC because it's rather late in the cycle; the plan
> is to make a regular submission (with changes based on review) once
> net-next reopens after the 5.1 merge window. The full (work in progress)
> series, together with the (userspace) ethtool counterpart can be found at
> https://github.com/mkubecek/ethnl
>
> This is first part of alternative userspace interface for ethtool. The aim
> is to address some long known issues with the ioctl interface, mainly lack
> of extensibility, raciness, limited error reporting and absence of
> notifications.
>
> The interface uses generic netlink family "ethtool"; it provides multicast
> group "monitor" which is used for notifications. Documentation for the
> interface is in Documentation/networking/ethtool-netlink.txt
>
> Basic concepts:
>
> - the goal is to provide all features of ioctl interface but allow
> easier future extensions; at some point, it should be possible to have
> full ethtool functionality without using the ioctl interface
+1
> - inextensibility of ioctl interface resulted in way too many commands,
> many of them obsoleted by newer ones; reduce the number by ignoring the
> obsolete commands and grouping some together
> - for "set" type commands, allows passing only the attributes to be
> changed; therefore we don't need a get-modify-set cycle (which is
> inherently racy), userspace can simply say what it wants to change
> - provide notifications to multicast group "monitor" like rtnetlink does,
> i.e. in the form of messages close to replies to "get" requests
+1
> - allow dump requests to get some information about all network devices
> providing it
And it seems like you have also added some filtering capability with at
least the settings dump, right? That is also highly welcome.
> - be less dependent on ethtool and kernel being in sync; allow e.g. saying
> "ethtool -s eth0 advertise foo off" without ethtool knowing what "foo"
> means; it's kernel's job to know what mode "xyz" is and if it exists and
> is supported
>
> Main changes between RFC v2 and RFC v3:
>
> - do not allow building as a module (no netdev notifiers needed)
I would very much prefer that we could build this as a module. Some
systems might be memory constrained or opt to disable ethtool entirely
(security?). If this is not too much trouble, can we try to maintain that?
> - drop some obsolete fields
> - add permanent hw address, timestamping and private flags support
> - rework bitset handling to get rid of variable length arrays
> - notify monitor on device renames
> - restructure GET_SETTINGS/SET_SETTINGS messages
> - split too long patches and submit only first part of the series
>
> Main changes between RFC v1 and RFC v2:
>
> - support dumps for all "get" requests
> - provide notifications for changes related to supported request types
> - support getting string sets (both global and per device)
> - support getting/setting device features
> - get rid of family specific header, everything passed as attributes
> - split netlink code into multiple files in net/ethtool/ directory
>
> ToDo / open questions:
>
> - some features provided by ethtool would rather belong to devlink (and
> some are already superseded by devlink); however, only few drivers
> provide devlink interface at the moment and as recent discussion on
> flashing revealed, we cannot rely on devlink's presence
Should we just move everything under devlink given that ethtool over
netlink or devlink are essentially manipulating the same (or close to)
objects? It seems to me that at least now is the right time to make
decisions about what should stay in ethtool and be offered via netlink,
what should be migrated to something else (e.g.: Jiri mentioned
rtnetlink), and what is a devlink candidate.
How do we proceed to easily triage which of these netlink facilities
should things be routed to/from?
>
> - while the netlink interface allows easy future extensions, ethtool_ops
> interface does not; some settings could be implemented using tunables and
> accessed via relevant netlink messages (as well as tunables) from
> userspace but in the long term, something better will be needed
Right, so as a driver writer, one thing I kind of hate is having to fill
a netlink skb myself because that's a lot of work, and it makes it
fairly hard to do mass conversion of internal APIs due to the increased
complexity in auditing what drivers do.
>
> - currently, all communication with drivers via ethtool_ops is done
> under RTNL as this is what ioctl interface does and likely many
> ethtool_ops handlers rely on that; if we are going to rework ethtool_ops
> in the future ("phase two"), it would be nice to get rid of it
>
> - ethtool_ops should pass extack pointer to allow drivers more meaningful
> error reporting; it's not clear, however, how to pass information about
> offending attribute
>
> - notifications are sent whenever a change is done via netlink API or
> ioctl API and for netdev features also whenever they are updated using
> netdev_change_features(); it would be desirable to notify also about
> link state and negotiation result (speed/duplex and partner link
> modes) but it would be more tricky
Historically you listen for a link event and you determine the link
parameters from there, I don't know if there is much value in giving the
full link parameter list, especially given those could theoretically
change depending on your medium (e.g.: wireless), or there could be a
lot to query at that time...
>
> Michal Kubecek (21):
> netlink: introduce nla_put_bitfield32()
> ethtool: move to its own directory
> ethtool: introduce ethtool netlink interface
> ethtool: helper functions for netlink interface
> ethtool: netlink bitset handling
> ethtool: support for netlink notifications
> ethtool: implement EVENT notifications
> ethtool: generic handlers for GET requests
> ethtool: move string arrays into common file
> ethtool: provide string sets with GET_STRSET request
> ethtool: provide driver/device information in GET_INFO request
> ethtool: provide permanent hardware address in GET_INFO request
> ethtool: provide timestamping information in GET_INFO request
> ethtool: provide link mode names as a string set
> ethtool: provide link settings and link modes in GET_SETTINGS request
> ethtool: provide WoL information in GET_SETTINGS request
> ethtool: provide message level in GET_SETTINGS request
> ethtool: provide link state in GET_SETTINGS request
> ethtool: provide device features in GET_SETTINGS request
> ethtool: provide private flags in GET_SETTINGS request
> ethtool: send netlink notifications about setting changes
>
> Documentation/networking/ethtool-netlink.txt | 441 +++++++++++++
> include/linux/ethtool_netlink.h | 17 +
> include/linux/netdevice.h | 14 +
> include/net/netlink.h | 15 +
> include/uapi/linux/ethtool.h | 10 +
> include/uapi/linux/ethtool_netlink.h | 265 ++++++++
> include/uapi/linux/net_tstamp.h | 13 +
> net/Kconfig | 8 +
> net/Makefile | 2 +-
> net/core/Makefile | 2 +-
> net/ethtool/Makefile | 7 +
> net/ethtool/bitset.c | 572 +++++++++++++++++
> net/ethtool/bitset.h | 40 ++
> net/ethtool/common.c | 227 +++++++
> net/ethtool/common.h | 29 +
> net/ethtool/info.c | 332 ++++++++++
> net/{core/ethtool.c => ethtool/ioctl.c} | 244 ++-----
> net/ethtool/netlink.c | 634 +++++++++++++++++++
> net/ethtool/netlink.h | 252 ++++++++
> net/ethtool/settings.c | 559 ++++++++++++++++
> net/ethtool/strset.c | 461 ++++++++++++++
> 21 files changed, 3937 insertions(+), 207 deletions(-)
> create mode 100644 Documentation/networking/ethtool-netlink.txt
> create mode 100644 include/linux/ethtool_netlink.h
> create mode 100644 include/uapi/linux/ethtool_netlink.h
> create mode 100644 net/ethtool/Makefile
> create mode 100644 net/ethtool/bitset.c
> create mode 100644 net/ethtool/bitset.h
> create mode 100644 net/ethtool/common.c
> create mode 100644 net/ethtool/common.h
> create mode 100644 net/ethtool/info.c
> rename net/{core/ethtool.c => ethtool/ioctl.c} (91%)
> create mode 100644 net/ethtool/netlink.c
> create mode 100644 net/ethtool/netlink.h
> create mode 100644 net/ethtool/settings.c
> create mode 100644 net/ethtool/strset.c
>
--
Florian
^ permalink raw reply
* Re: [RFC PATCH net-next v3 14/21] ethtool: provide link mode names as a string set
From: Florian Fainelli @ 2019-02-21 3:21 UTC (permalink / raw)
To: Michal Kubecek, netdev
Cc: David Miller, Andrew Lunn, Jakub Kicinski, Jiri Pirko,
linux-kernel
In-Reply-To: <e969567a4630812230efa4fd4c7f0233564822d6.1550513384.git.mkubecek@suse.cz>
On 2/18/2019 10:22 AM, Michal Kubecek wrote:
> Add table of ethernet link mode names and make it available as a string set
> to userspace GET_STRSET requests.
>
> Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
> ---
[snip]
>
> +const char *const link_mode_names[] = {
Maybe you can define a macro (totally untested) to build the table an
avoid some of the repetition, something like:
#define ETHTOOL_LINK_NAME(speed, duplex) \
[ETHTOOL_LINK_MODE_##speed_##duplex_BIT] = stringify(speed ## "/" ##
duplex)
--
Florian
^ permalink raw reply
* [tipc-discussion][net v2 1/1] tipc: fix race condition causing hung sendto
From: Tung Nguyen @ 2019-02-21 3:31 UTC (permalink / raw)
To: davem, netdev; +Cc: tipc-discussion
In-Reply-To: <20190219070310.23888-2-tung.q.nguyen@dektech.com.au>
When sending multicast messages via blocking socket,
if sending link is congested (tsk->cong_link_cnt is set to 1),
the sending thread will be put into sleeping state. However,
tipc_sk_filter_rcv() is called under socket spin lock but
tipc_wait_for_cond() is not. So, there is no guarantee that
the setting of tsk->cong_link_cnt to 0 in tipc_sk_proto_rcv() in
CPU-1 will be perceived by CPU-0. If that is the case, the sending
thread in CPU-0 after being waken up, will continue to see
tsk->cong_link_cnt as 1 and put the sending thread into sleeping
state again. The sending thread will sleep forever.
CPU-0 | CPU-1
tipc_wait_for_cond() |
{ |
// condition_ = !tsk->cong_link_cnt |
while ((rc_ = !(condition_))) { |
... |
release_sock(sk_); |
wait_woken(); |
| if (!sock_owned_by_user(sk))
| tipc_sk_filter_rcv()
| {
| ...
| tipc_sk_proto_rcv()
| {
| ...
| tsk->cong_link_cnt--;
| ...
| sk->sk_write_space(sk);
| ...
| }
| ...
| }
sched_annotate_sleep(); |
lock_sock(sk_); |
remove_wait_queue(); |
} |
} |
This commit fixes it by adding memory barrier to tipc_sk_proto_rcv()
and tipc_wait_for_cond().
Acked-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: Tung Nguyen <tung.q.nguyen@dektech.com.au>
---
net/tipc/socket.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 1217c90a363b..7cfa0c8ccc2a 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -379,16 +379,18 @@ static int tipc_sk_sock_err(struct socket *sock, long *timeout)
#define tipc_wait_for_cond(sock_, timeo_, condition_) \
({ \
+ DEFINE_WAIT_FUNC(wait_, woken_wake_function); \
struct sock *sk_; \
int rc_; \
\
while ((rc_ = !(condition_))) { \
- DEFINE_WAIT_FUNC(wait_, woken_wake_function); \
+ /* coupled with smp_wmb() in tipc_sk_proto_rcv() */ \
+ smp_rmb(); \
sk_ = (sock_)->sk; \
rc_ = tipc_sk_sock_err((sock_), timeo_); \
if (rc_) \
break; \
- prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE); \
+ add_wait_queue(sk_sleep(sk_), &wait_); \
release_sock(sk_); \
*(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \
sched_annotate_sleep(); \
@@ -1982,6 +1984,8 @@ static void tipc_sk_proto_rcv(struct sock *sk,
return;
case SOCK_WAKEUP:
tipc_dest_del(&tsk->cong_links, msg_orignode(hdr), 0);
+ /* coupled with smp_rmb() in tipc_wait_for_cond() */
+ smp_wmb();
tsk->cong_link_cnt--;
wakeup = true;
break;
--
2.17.1
^ permalink raw reply related
* Re: [PATCH bpf-next 3/9] bpf: add bpf helper bpf_skb_set_ecn
From: Lawrence Brakmo @ 2019-02-21 3:43 UTC (permalink / raw)
To: Eric Dumazet, netdev; +Cc: Martin Lau, Alexei Starovoitov, Daniel Borkmann
In-Reply-To: <318b6330-555f-224c-f4f5-5c635a78c99e@gmail.com>
On 2/19/19, 10:30 AM, "Eric Dumazet" <eric.dumazet@gmail.com> wrote:
On 02/18/2019 09:38 PM, brakmo wrote:
> This patch adds a new bpf helper BPF_FUNC_skb_set_ecn
> "int bpf_skb_set_Ecn(struct sk_buff *skb)". It is added to
> BPF_PROG_TYPE_CGROUP_SKB typed bpf_prog which currently can
> be attached to the ingress and egress path. This type of
> bpf_prog cannot modify the skb directly.
>
> This helper is used to set the ECN bits (2) of the IPv6 or IPv4
> header in skb. It can be used by a bpf_prog to manage egress
> network bandwdith limit per cgroupv2 by inducing an ECN
> response in the TCP sender (when the packet is ECN enabled).
> This works best when using DCTCP.
> +
> +BPF_CALL_2(bpf_skb_set_ecn, struct sk_buff *, skb, u32, val)
> +{
> + struct ipv6hdr *ip6h = ipv6_hdr(skb);
> +
> + if ((val & ~0x3) != 0)
> + return -EINVAL;
> +
> + if (ip6h->version == 6) {
> + ip6h->flow_lbl[0] = (ip6h->flow_lbl[0] & ~0x30) | (val << 4);
> + return 0;
> + } else if (ip6h->version == 4) {
> + struct iphdr *ip4h = (struct iphdr *)ip6h;
> +
> + ip4h->tos = (ip4h->tos & ~0x3) | val;
Why is not the IPv4 checksum recomputed here ?
If you leave this task to the caller, this should be documented.
These hard coded constants are not really nice.
Why not simply using INET_ECN_set_ce() which is IPv4/IPv6 ready ?
Do you really need to set anything else than CE ?
Good point, thank you. I will use it.
^ permalink raw reply
* Re: [tipc-discussion][net v2 1/1] tipc: fix race condition causing hung sendto
From: David Miller @ 2019-02-21 3:51 UTC (permalink / raw)
To: tung.q.nguyen; +Cc: netdev, tipc-discussion
In-Reply-To: <20190221033121.4220-1-tung.q.nguyen@dektech.com.au>
So if the previous version didn't even compile, I have to ask.
How did you test this?
^ permalink raw reply
* Re: [PATCH] net: marvell: mvneta: fix DMA debug warning
From: David Miller @ 2019-02-21 3:57 UTC (permalink / raw)
To: rmk+kernel; +Cc: thomas.petazzoni, netdev
In-Reply-To: <E1gudxz-0001T0-0K@rmk-PC.armlinux.org.uk>
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Fri, 15 Feb 2019 13:55:47 +0000
> Booting 4.20 on SolidRun Clearfog issues this warning with DMA API
> debug enabled:
...
> This appears to be caused by mvneta_rx_hwbm() calling
> dma_sync_single_range_for_cpu() with the wrong struct device pointer,
> as the buffer manager device pointer is used to map and unmap the
> buffer. Fix this.
>
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> ---
> Please check that this is the correct fix.
This makes it consistent with the other DMA calls in the hwbm
code paths, so on that basis I'm applying this and queueing it
up for -stable.
Thanks.
^ permalink raw reply
* Re: [PATCH bpf-next v2] bpf, seccomp: fix false positive preemption splat for cbpf->ebpf progs
From: Alexei Starovoitov @ 2019-02-21 4:02 UTC (permalink / raw)
To: Daniel Borkmann, Jann Horn, Andy Lutomirski
Cc: Alexei Starovoitov, Kees Cook, Network Development
In-Reply-To: <20190220235952.uzrsjypoqkha7ya6@ast-mbp.dhcp.thefacebook.com>
On Wed, Feb 20, 2019 at 3:59 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Thu, Feb 21, 2019 at 12:01:35AM +0100, Daniel Borkmann wrote:
> > In 568f196756ad ("bpf: check that BPF programs run with preemption disabled")
> > a check was added for BPF_PROG_RUN() that for every invocation preemption is
> > disabled to not break eBPF assumptions (e.g. per-cpu map). Of course this does
> > not count for seccomp because only cBPF -> eBPF is loaded here and it does
> > not make use of any functionality that would require this assertion. Fix this
> > false positive by adding and using SECCOMP_RUN() variant that does not have
> > the cant_sleep(); check.
> >
> > Fixes: 568f196756ad ("bpf: check that BPF programs run with preemption disabled")
> > Reported-by: syzbot+8bf19ee2aa580de7a2a7@syzkaller.appspotmail.com
> > Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> > Acked-by: Kees Cook <keescook@chromium.org>
>
> Applied, Thanks
Actually I think it's a wrong approach to go long term.
I'm thinking to revert it.
I think it's better to disable preemption for duration of
seccomp cbpf prog.
It's short and there is really no reason for it to be preemptible.
When seccomp switches to ebpf we'll have this weird inconsistency.
Let's just disable preemption for seccomp as well.
^ permalink raw reply
* RE: [tipc-discussion][net v2 1/1] tipc: fix race condition causing hung sendto
From: tung quang nguyen @ 2019-02-21 4:04 UTC (permalink / raw)
To: 'David Miller'; +Cc: netdev, tipc-discussion
In-Reply-To: <20190220.195104.1394349830331192977.davem@davemloft.net>
Hi David,
I compiled previous version and tested it. But I forgot to observe kernel
warning.
For the way to reproduce the issue: calling sendto() and printf() right
after that to print out a log to see if sendto() was successful. On some
occasions, the log was never printed and stack trace showed sendto() was not
returned.
By applying the patch, the issue disappeared.
Thanks.
Best regards,
Tung Nguyen
-----Original Message-----
From: David Miller <davem@davemloft.net>
Sent: Thursday, February 21, 2019 10:51 AM
To: tung.q.nguyen@dektech.com.au
Cc: netdev@vger.kernel.org; tipc-discussion@lists.sourceforge.net
Subject: Re: [tipc-discussion][net v2 1/1] tipc: fix race condition causing
hung sendto
So if the previous version didn't even compile, I have to ask.
How did you test this?
^ permalink raw reply
* Re: [PATCH][unix] missing barriers in some of unix_sock ->addr and ->path accesses
From: David Miller @ 2019-02-21 4:07 UTC (permalink / raw)
To: viro; +Cc: netdev
In-Reply-To: <20190215200934.GM2217@ZenIV.linux.org.uk>
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Fri, 15 Feb 2019 20:09:35 +0000
> Several u->addr and u->path users are not holding any locks in
> common with unix_bind(). unix_state_lock() is useless for those
> purposes.
>
> u->addr is assign-once and *(u->addr) is fully set up by the time
> we set u->addr (all under unix_table_lock). u->path is also
> set in the same critical area, also before setting u->addr, and
> any unix_sock with ->path filled will have non-NULL ->addr.
>
> So setting ->addr with smp_store_release() is all we need for those
> "lockless" users - just have them fetch ->addr with smp_load_acquire()
> and don't even bother looking at ->path if they see NULL ->addr.
>
> Users of ->addr and ->path fall into several classes now:
> 1) ones that do smp_load_acquire(u->addr) and access *(u->addr)
> and u->path only if smp_load_acquire() has returned non-NULL.
> 2) places holding unix_table_lock. These are guaranteed that
> *(u->addr) is seen fully initialized. If unix_sock is in one of the
> "bound" chains, so's ->path.
> 3) unix_sock_destructor() using ->addr is safe. All places
> that set u->addr are guaranteed to have seen all stores *(u->addr)
> while holding a reference to u and unix_sock_destructor() is called
> when (atomic) refcount hits zero.
> 4) unix_release_sock() using ->path is safe. unix_bind()
> is serialized wrt unix_release() (normally - by struct file
> refcount), and for the instances that had ->path set by unix_bind()
> unix_release_sock() comes from unix_release(), so they are fine.
> Instances that had it set in unix_stream_connect() either end up
> attached to a socket (in unix_accept()), in which case the call
> chain to unix_release_sock() and serialization are the same as in
> the previous case, or they never get accept'ed and unix_release_sock()
> is called when the listener is shut down and its queue gets purged.
> In that case the listener's queue lock provides the barriers needed -
> unix_stream_connect() shoves our unix_sock into listener's queue
> under that lock right after having set ->path and eventual
> unix_release_sock() caller picks them from that queue under the
> same lock right before calling unix_release_sock().
> 5) unix_find_other() use of ->path is pointless, but safe -
> it happens with successful lookup by (abstract) name, so ->path.dentry
> is guaranteed to be NULL there.
>
> earlier-variant-reviewed-by: "Paul E. McKenney" <paulmck@linux.ibm.com>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Applied and queued up for -stable, thanks Al.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox