* (unknown),
From: mari.kayhko @ 2017-06-02 6:04 UTC (permalink / raw)
To: netdev
[-- Attachment #1: 083544262110.zip --]
[-- Type: application/zip, Size: 3182 bytes --]
^ permalink raw reply
* Re: [PATCH net] ip6_tunnel: fix traffic class routing for tunnels
From: Peter Dawson @ 2017-06-02 6:03 UTC (permalink / raw)
To: Liam McBirnie
Cc: David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, netdev, peter.a.dawson
In-Reply-To: <91e31c60-5994-6784-cfe8-6a18016c6524@gmail.com>
On Fri, 2 Jun 2017 15:12:26 +1000
Liam McBirnie <mcbirnie.l@gmail.com> wrote:
> The traffic class is added here because only route lookup needs the
> flowlabel to contain the traffic class.
>
> Fixes: 0e9a709560db ("ip6_tunnel, ip6_gre: fix setting of DSCP on encapsulated packets")
> Signed-off-by: Liam McBirnie <liam.mcbirnie@boeing.com>
Concur with this patch. Testing that I performed on Commit: 0e9a709560db ("ip6_tunnel, ip6_gre: fix setting of DSCP on encapsulated packets") did not cover the case were DSCP-based routing policy is applied to the tunneled packets.
Acked-by: Peter Dawson <peter.a.dawson@boeing.com>
^ permalink raw reply
* [PATCH net-next 3/4] qed: Support NVM-image reading API
From: Yuval Mintz @ 2017-06-02 5:58 UTC (permalink / raw)
To: netdev, davem
Cc: linux-scsi, nilesh.javali, chad.dupuis, saurav.kashyap,
Yuval Mintz
In-Reply-To: <20170602055833.21814-1-Yuval.Mintz@cavium.com>
Storage drivers require images from the nvram in boot-from-SAN
scenarios. This provides the necessary API between qed and the
protocol drivers to perform such reads.
Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_main.c | 16 ++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 89 ++++++++++++++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 21 +++++++
include/linux/qed/qed_if.h | 18 ++++++
4 files changed, 144 insertions(+)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index baebd59..6ac10ce 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -1535,6 +1535,21 @@ static int qed_drain(struct qed_dev *cdev)
return 0;
}
+static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type,
+ u8 *buf, u16 len)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *ptt = qed_ptt_acquire(hwfn);
+ int rc;
+
+ if (!ptt)
+ return -EAGAIN;
+
+ rc = qed_mcp_get_nvm_image(hwfn, ptt, type, buf, len);
+ qed_ptt_release(hwfn, ptt);
+ return rc;
+}
+
static void qed_get_coalesce(struct qed_dev *cdev, u16 *rx_coal, u16 *tx_coal)
{
*rx_coal = cdev->rx_coalesce_usecs;
@@ -1712,6 +1727,7 @@ const struct qed_common_ops qed_common_ops_pass = {
.dbg_all_data_size = &qed_dbg_all_data_size,
.chain_alloc = &qed_chain_alloc,
.chain_free = &qed_chain_free,
+ .nvm_get_image = &qed_nvm_get_image,
.get_coalesce = &qed_get_coalesce,
.set_coalesce = &qed_set_coalesce,
.set_led = &qed_set_led,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index e82f329..9da9104 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -2310,6 +2310,95 @@ int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
return rc;
}
+static int
+qed_mcp_get_nvm_image_att(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_nvm_images image_id,
+ struct qed_nvm_image_att *p_image_att)
+{
+ struct bist_nvm_image_att mfw_image_att;
+ enum nvm_image_type type;
+ u32 num_images, i;
+ int rc;
+
+ /* Translate image_id into MFW definitions */
+ switch (image_id) {
+ case QED_NVM_IMAGE_ISCSI_CFG:
+ type = NVM_TYPE_ISCSI_CFG;
+ break;
+ case QED_NVM_IMAGE_FCOE_CFG:
+ type = NVM_TYPE_FCOE_CFG;
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "Unknown request of image_id %08x\n",
+ image_id);
+ return -EINVAL;
+ }
+
+ /* Learn number of images, then traverse and see if one fits */
+ rc = qed_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
+ if (rc || !num_images)
+ return -EINVAL;
+
+ for (i = 0; i < num_images; i++) {
+ rc = qed_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
+ &mfw_image_att, i);
+ if (rc)
+ return rc;
+
+ if (type == mfw_image_att.image_type)
+ break;
+ }
+ if (i == num_images) {
+ DP_VERBOSE(p_hwfn, QED_MSG_STORAGE,
+ "Failed to find nvram image of type %08x\n",
+ image_id);
+ return -EINVAL;
+ }
+
+ p_image_att->start_addr = mfw_image_att.nvm_start_addr;
+ p_image_att->length = mfw_image_att.len;
+
+ return 0;
+}
+
+int qed_mcp_get_nvm_image(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_nvm_images image_id,
+ u8 *p_buffer, u32 buffer_len)
+{
+ struct qed_nvm_image_att image_att;
+ int rc;
+
+ memset(p_buffer, 0, buffer_len);
+
+ rc = qed_mcp_get_nvm_image_att(p_hwfn, p_ptt, image_id, &image_att);
+ if (rc)
+ return rc;
+
+ /* Validate sizes - both the image's and the supplied buffer's */
+ if (image_att.length <= 4) {
+ DP_VERBOSE(p_hwfn, QED_MSG_STORAGE,
+ "Image [%d] is too small - only %d bytes\n",
+ image_id, image_att.length);
+ return -EINVAL;
+ }
+
+ /* Each NVM image is suffixed by CRC; Upper-layer has no need for it */
+ image_att.length -= 4;
+
+ if (image_att.length > buffer_len) {
+ DP_VERBOSE(p_hwfn,
+ QED_MSG_STORAGE,
+ "Image [%d] is too big - %08x bytes where only %08x are available\n",
+ image_id, image_att.length, buffer_len);
+ return -ENOMEM;
+ }
+
+ return qed_mcp_nvm_read(p_hwfn->cdev, image_att.start_addr,
+ p_buffer, image_att.length);
+}
+
static enum resource_id_enum qed_mcp_get_mfw_res_id(enum qed_resources res_id)
{
enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index 4024759..af03b36 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -430,6 +430,27 @@ int qed_mcp_set_led(struct qed_hwfn *p_hwfn,
*/
int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len);
+struct qed_nvm_image_att {
+ u32 start_addr;
+ u32 length;
+};
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param image_id - image requested for reading
+ * @param p_buffer - allocated buffer into which to fill data
+ * @param buffer_len - length of the allocated buffer.
+ *
+ * @return 0 iff p_buffer now contains the nvram image.
+ */
+int qed_mcp_get_nvm_image(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_nvm_images image_id,
+ u8 *p_buffer, u32 buffer_len);
+
/**
* @brief Bist register test
*
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index e29c6f7..567ea3e 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -156,6 +156,11 @@ struct qed_dcbx_get {
struct qed_dcbx_admin_params local;
};
+enum qed_nvm_images {
+ QED_NVM_IMAGE_ISCSI_CFG,
+ QED_NVM_IMAGE_FCOE_CFG,
+};
+
enum qed_led_mode {
QED_LED_MODE_OFF,
QED_LED_MODE_ON,
@@ -631,6 +636,19 @@ struct qed_common_ops {
struct qed_chain *p_chain);
/**
+ * @brief nvm_get_image - reads an entire image from nvram
+ *
+ * @param cdev
+ * @param type - type of the request nvram image
+ * @param buf - preallocated buffer to fill with the image
+ * @param len - length of the allocated buffer
+ *
+ * @return 0 on success, error otherwise
+ */
+ int (*nvm_get_image)(struct qed_dev *cdev,
+ enum qed_nvm_images type, u8 *buf, u16 len);
+
+/**
* @brief get_coalesce - Get coalesce parameters in usec
*
* @param cdev
--
2.9.4
^ permalink raw reply related
* [PATCH net-next 4/4] qed: Add support for changing iSCSI mac
From: Yuval Mintz @ 2017-06-02 5:58 UTC (permalink / raw)
To: netdev, davem
Cc: linux-scsi, nilesh.javali, chad.dupuis, saurav.kashyap,
Yuval Mintz
In-Reply-To: <20170602055833.21814-1-Yuval.Mintz@cavium.com>
Enhance API between qedi and qed, allowing qedi to inform device's
firmware when the iSCSI mac is to be changed.
Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_iscsi.c | 66 +++++++++++++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_sp.h | 1 +
include/linux/qed/qed_iscsi_if.h | 7 +++
3 files changed, 74 insertions(+)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
index bc8ce09..787f66e 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
@@ -488,6 +488,54 @@ static int qed_sp_iscsi_conn_update(struct qed_hwfn *p_hwfn,
return qed_spq_post(p_hwfn, p_ent, NULL);
}
+static int
+qed_sp_iscsi_mac_update(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_conn *p_conn,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_addr)
+{
+ struct iscsi_spe_conn_mac_update *p_ramrod = NULL;
+ struct qed_spq_entry *p_ent = NULL;
+ struct qed_sp_init_data init_data;
+ int rc = -EINVAL;
+ u8 ucval;
+
+ /* Get SPQ entry */
+ memset(&init_data, 0, sizeof(init_data));
+ init_data.cid = p_conn->icid;
+ init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
+ init_data.comp_mode = comp_mode;
+ init_data.p_comp_data = p_comp_addr;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ ISCSI_RAMROD_CMD_ID_MAC_UPDATE,
+ PROTOCOLID_ISCSI, &init_data);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.iscsi_conn_mac_update;
+ p_ramrod->hdr.op_code = ISCSI_RAMROD_CMD_ID_MAC_UPDATE;
+ SET_FIELD(p_ramrod->hdr.flags,
+ ISCSI_SLOW_PATH_HDR_LAYER_CODE, p_conn->layer_code);
+
+ p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id);
+ p_ramrod->fw_cid = cpu_to_le32(p_conn->icid);
+ ucval = p_conn->remote_mac[1];
+ ((u8 *)(&p_ramrod->remote_mac_addr_hi))[0] = ucval;
+ ucval = p_conn->remote_mac[0];
+ ((u8 *)(&p_ramrod->remote_mac_addr_hi))[1] = ucval;
+ ucval = p_conn->remote_mac[3];
+ ((u8 *)(&p_ramrod->remote_mac_addr_mid))[0] = ucval;
+ ucval = p_conn->remote_mac[2];
+ ((u8 *)(&p_ramrod->remote_mac_addr_mid))[1] = ucval;
+ ucval = p_conn->remote_mac[5];
+ ((u8 *)(&p_ramrod->remote_mac_addr_lo))[0] = ucval;
+ ucval = p_conn->remote_mac[4];
+ ((u8 *)(&p_ramrod->remote_mac_addr_lo))[1] = ucval;
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
static int qed_sp_iscsi_conn_terminate(struct qed_hwfn *p_hwfn,
struct qed_iscsi_conn *p_conn,
enum spq_mode comp_mode,
@@ -1324,6 +1372,23 @@ static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats)
return qed_iscsi_get_stats(QED_LEADING_HWFN(cdev), stats);
}
+static int qed_iscsi_change_mac(struct qed_dev *cdev,
+ u32 handle, const u8 *mac)
+{
+ struct qed_hash_iscsi_con *hash_con;
+
+ hash_con = qed_iscsi_get_hash(cdev, handle);
+ if (!hash_con) {
+ DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
+ handle);
+ return -EINVAL;
+ }
+
+ return qed_sp_iscsi_mac_update(QED_LEADING_HWFN(cdev),
+ hash_con->con,
+ QED_SPQ_MODE_EBLOCK, NULL);
+}
+
void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
struct qed_mcp_iscsi_stats *stats)
{
@@ -1358,6 +1423,7 @@ static const struct qed_iscsi_ops qed_iscsi_ops_pass = {
.destroy_conn = &qed_iscsi_destroy_conn,
.clear_sq = &qed_iscsi_clear_conn_sq,
.get_stats = &qed_iscsi_stats,
+ .change_mac = &qed_iscsi_change_mac,
};
const struct qed_iscsi_ops *qed_get_iscsi_ops(void)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h
index b9464f3..00dd50f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h
@@ -120,6 +120,7 @@ union ramrod_data {
struct iscsi_spe_func_dstry iscsi_destroy;
struct iscsi_spe_conn_offload iscsi_conn_offload;
struct iscsi_conn_update_ramrod_params iscsi_conn_update;
+ struct iscsi_spe_conn_mac_update iscsi_conn_mac_update;
struct iscsi_spe_conn_termination iscsi_conn_terminate;
struct vf_start_ramrod_data vf_start;
diff --git a/include/linux/qed/qed_iscsi_if.h b/include/linux/qed/qed_iscsi_if.h
index 3414649..111e606 100644
--- a/include/linux/qed/qed_iscsi_if.h
+++ b/include/linux/qed/qed_iscsi_if.h
@@ -210,6 +210,11 @@ struct qed_iscsi_cb_ops {
* @param stats - pointer to struck that would be filled
* we stats
* @return 0 on success, error otherwise.
+ * @change_mac Change MAC of interface
+ * @param cdev
+ * @param handle - the connection handle.
+ * @param mac - new MAC to configure.
+ * @return 0 on success, otherwise error value.
*/
struct qed_iscsi_ops {
const struct qed_common_ops *common;
@@ -248,6 +253,8 @@ struct qed_iscsi_ops {
int (*get_stats)(struct qed_dev *cdev,
struct qed_iscsi_stats *stats);
+
+ int (*change_mac)(struct qed_dev *cdev, u32 handle, const u8 *mac);
};
const struct qed_iscsi_ops *qed_get_iscsi_ops(void);
--
2.9.4
^ permalink raw reply related
* [PATCH net-next 2/4] qed: Share additional information with qedf
From: Yuval Mintz @ 2017-06-02 5:58 UTC (permalink / raw)
To: netdev, davem
Cc: linux-scsi, nilesh.javali, chad.dupuis, saurav.kashyap,
Yuval Mintz
In-Reply-To: <20170602055833.21814-1-Yuval.Mintz@cavium.com>
Share several new tidbits with qedf:
- wwpn & wwnn
- Absolute pf-id [this one is actually meant for qedi as well]
- Number of available CQs
While we're at it, now that qedf will be aware of the available CQs
we can add some validation on the inputs it provides.
Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_dev.c | 8 +++++++-
drivers/net/ethernet/qlogic/qed/qed_fcoe.c | 14 ++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_main.c | 2 ++
include/linux/qed/qed_fcoe_if.h | 5 +++++
include/linux/qed/qed_if.h | 2 ++
5 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 7649f35..2d88d48 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -2071,16 +2071,22 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
QED_VF_L2_QUE));
}
+ if (p_hwfn->hw_info.personality == QED_PCI_FCOE)
+ feat_num[QED_FCOE_CQ] = min_t(u32, sb_cnt.cnt,
+ RESC_NUM(p_hwfn,
+ QED_CMDQS_CQS));
+
if (p_hwfn->hw_info.personality == QED_PCI_ISCSI)
feat_num[QED_ISCSI_CQ] = min_t(u32, sb_cnt.cnt,
RESC_NUM(p_hwfn,
QED_CMDQS_CQS));
DP_VERBOSE(p_hwfn,
NETIF_MSG_PROBE,
- "#PF_L2_QUEUES=%d VF_L2_QUEUES=%d #ROCE_CNQ=%d ISCSI_CQ=%d #SBS=%d\n",
+ "#PF_L2_QUEUES=%d VF_L2_QUEUES=%d #ROCE_CNQ=%d FCOE_CQ=%d ISCSI_CQ=%d #SBS=%d\n",
(int)FEAT_NUM(p_hwfn, QED_PF_L2_QUE),
(int)FEAT_NUM(p_hwfn, QED_VF_L2_QUE),
(int)FEAT_NUM(p_hwfn, QED_RDMA_CNQ),
+ (int)FEAT_NUM(p_hwfn, QED_FCOE_CQ),
(int)FEAT_NUM(p_hwfn, QED_ISCSI_CQ),
(int)sb_cnt.cnt);
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_fcoe.c b/drivers/net/ethernet/qlogic/qed/qed_fcoe.c
index 3fc4ff2..df195c0 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_fcoe.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_fcoe.c
@@ -141,6 +141,15 @@ qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn,
p_data = &p_ramrod->init_ramrod_data;
fcoe_pf_params = &p_hwfn->pf_params.fcoe_pf_params;
+ /* Sanity */
+ if (fcoe_pf_params->num_cqs > p_hwfn->hw_info.feat_num[QED_FCOE_CQ]) {
+ DP_ERR(p_hwfn,
+ "Cannot satisfy CQ amount. CQs requested %d, CQs available %d. Aborting function start\n",
+ fcoe_pf_params->num_cqs,
+ p_hwfn->hw_info.feat_num[QED_FCOE_CQ]);
+ return -EINVAL;
+ }
+
p_data->mtu = cpu_to_le16(fcoe_pf_params->mtu);
tmp = cpu_to_le16(fcoe_pf_params->sq_num_pbl_pages);
p_data->sq_num_pages_in_pbl = tmp;
@@ -739,6 +748,11 @@ static int qed_fill_fcoe_dev_info(struct qed_dev *cdev,
info->secondary_bdq_rq_addr =
qed_fcoe_get_secondary_bdq_prod(hwfn, BDQ_ID_RQ);
+ info->wwpn = hwfn->mcp_info->func_info.wwn_port;
+ info->wwnn = hwfn->mcp_info->func_info.wwn_node;
+
+ info->num_cqs = FEAT_NUM(hwfn, QED_FCOE_CQ);
+
return rc;
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index ac3bdcd..baebd59 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -269,6 +269,8 @@ int qed_fill_dev_info(struct qed_dev *cdev,
if (QED_LEADING_HWFN(cdev)->hw_info.b_wol_support ==
QED_WOL_SUPPORT_PME)
dev_info->wol_support = true;
+
+ dev_info->abs_pf_id = QED_LEADING_HWFN(cdev)->abs_pf_id;
} else {
qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major,
&dev_info->fw_minor, &dev_info->fw_rev,
diff --git a/include/linux/qed/qed_fcoe_if.h b/include/linux/qed/qed_fcoe_if.h
index bd6bcb8..1e015c5 100644
--- a/include/linux/qed/qed_fcoe_if.h
+++ b/include/linux/qed/qed_fcoe_if.h
@@ -24,6 +24,11 @@ struct qed_dev_fcoe_info {
void __iomem *primary_dbq_rq_addr;
void __iomem *secondary_bdq_rq_addr;
+
+ u64 wwpn;
+ u64 wwnn;
+
+ u8 num_cqs;
};
struct qed_fcoe_params_offload {
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index 607e1c5..e29c6f7 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -360,6 +360,8 @@ struct qed_dev_info {
bool vxlan_enable;
bool gre_enable;
bool geneve_enable;
+
+ u8 abs_pf_id;
};
enum qed_sb_type {
--
2.9.4
^ permalink raw reply related
* [PATCH net-next 1/4] qed: Correct order of wwnn and wwpn
From: Yuval Mintz @ 2017-06-02 5:58 UTC (permalink / raw)
To: netdev, davem
Cc: linux-scsi, nilesh.javali, chad.dupuis, saurav.kashyap,
Yuval Mintz
In-Reply-To: <20170602055833.21814-1-Yuval.Mintz@cavium.com>
Driver reads values via HSI splitting this 8-byte into 2 32-bit
values and builds a single u64 field - but it does so by shifting
the lower field instead of the higher.
Luckily, we still don't use these fields for anything - but we're about
to start.
Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 31c88e1..e82f329 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1736,10 +1736,10 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,
DP_NOTICE(p_hwfn, "MAC is 0 in shmem\n");
}
- info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_upper |
- (((u64)shmem_info.fcoe_wwn_port_name_lower) << 32);
- info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_upper |
- (((u64)shmem_info.fcoe_wwn_node_name_lower) << 32);
+ info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_lower |
+ (((u64)shmem_info.fcoe_wwn_port_name_upper) << 32);
+ info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_lower |
+ (((u64)shmem_info.fcoe_wwn_node_name_upper) << 32);
info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK);
--
2.9.4
^ permalink raw reply related
* [PATCH net-next 0/4] qed: Enhance storage APIs
From: Yuval Mintz @ 2017-06-02 5:58 UTC (permalink / raw)
To: netdev, davem
Cc: linux-scsi, nilesh.javali, chad.dupuis, saurav.kashyap,
Yuval Mintz
This series is intended to add additional information and features
to the API between qed and its storage protocol drivers [qedi, qedf].
Patch #2 adds some information stored on device such as wwpn & wwnn
to allow qedf utilize it; #1 fixes an issue with the reading of those
values [which were unused until now].
Patch #3 would allow the protocol drivers access to images on persistent
storage which is a prerequirement for adding boot from SAN support.
Patch #4 adds infrastrucutre to a future feature for qedi.
Dave,
Please consider applying this series to 'net-next'.
Thanks,
Yuval
Yuval Mintz (4):
qed: Correct order of wwnn and wwpn
qed: Share additional information with qedf
qed: Support NVM-image reading API
qed: Add support for changing iSCSI mac
drivers/net/ethernet/qlogic/qed/qed_dev.c | 8 ++-
drivers/net/ethernet/qlogic/qed/qed_fcoe.c | 14 +++++
drivers/net/ethernet/qlogic/qed/qed_iscsi.c | 66 ++++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_main.c | 18 ++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 97 +++++++++++++++++++++++++++--
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 21 +++++++
drivers/net/ethernet/qlogic/qed/qed_sp.h | 1 +
include/linux/qed/qed_fcoe_if.h | 5 ++
include/linux/qed/qed_if.h | 20 ++++++
include/linux/qed/qed_iscsi_if.h | 7 +++
10 files changed, 252 insertions(+), 5 deletions(-)
--
2.9.4
^ permalink raw reply
* Ciao サ
From: hi @ 2017-06-02 5:16 UTC (permalink / raw)
To: stock
Ciao
Benvenuto al nostro negozio
24.88 euro per gli occhiali da sole di Ray Ban, trasporto libero direttamente alla vostra casa
web: rbewpt .com
放飞心情,释放真情,愿我们的心灵像湖水般的晶莹清澈,友情像山泉一样源远流长!
^ permalink raw reply
* [PATCH net] ip6_tunnel: fix traffic class routing for tunnels
From: Liam McBirnie @ 2017-06-02 5:12 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, netdev
Cc: peter.a.dawson
From: Liam McBirnie <mcbirnie.l@gmail.com>
Date: Thu, 1 Jun 2017 15:36:01 +1000
Subject: [PATCH net] ip6_tunnel: fix traffic class routing for tunnels
ip6_route_output() requires that the flowlabel contains the traffic
class for policy routing.
Commit 0e9a709560db ("ip6_tunnel, ip6_gre: fix setting of DSCP on
encapsulated packets") removed the code which previously added the
traffic class to the flowlabel.
The traffic class is added here because only route lookup needs the
flowlabel to contain the traffic class.
Fixes: 0e9a709560db ("ip6_tunnel, ip6_gre: fix setting of DSCP on encapsulated packets")
Signed-off-by: Liam McBirnie <liam.mcbirnie@boeing.com>
---
net/ipv6/ip6_tunnel.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 7ae6c50..9b37f97 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1095,6 +1095,9 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
if (!dst) {
route_lookup:
+ /* add dsfield to flowlabel for route lookup */
+ fl6->flowlabel = ip6_make_flowinfo(dsfield, fl6->flowlabel);
+
dst = ip6_route_output(net, NULL, fl6);
if (dst->error)
--
2.9.3
^ permalink raw reply related
* Re: [PATCH iproute2] iproute: extend route get to return matching fib route
From: David Ahern @ 2017-06-02 4:57 UTC (permalink / raw)
To: Roopa Prabhu, stephen; +Cc: netdev, nikolay
In-Reply-To: <1496379208-30573-1-git-send-email-roopa@cumulusnetworks.com>
On 6/1/17 10:53 PM, Roopa Prabhu wrote:
> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>
> Uses newly introduced RTM_GETROUTE flag RTM_F_FIB_MATCH
> to return a matching fib route. Introduces 'fibmatch'
> keyword to ip route get.
...
>
> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
> ---
> include/linux/rtnetlink.h | 1 +
> ip/iproute.c | 9 ++++++++-
> man/man8/ip-route.8.in | 12 ++++++++++++
> 3 files changed, 21 insertions(+), 1 deletion(-)
LGTM
Acked-by: David Ahern <dsahern@gmail.com>
^ permalink raw reply
* [PATCH iproute2] iproute: extend route get to return matching fib route
From: Roopa Prabhu @ 2017-06-02 4:53 UTC (permalink / raw)
To: stephen; +Cc: netdev, dsahern, nikolay
From: Roopa Prabhu <roopa@cumulusnetworks.com>
Uses newly introduced RTM_GETROUTE flag RTM_F_FIB_MATCH
to return a matching fib route. Introduces 'fibmatch'
keyword to ip route get.
ipv4:
----
$ip route show
default via 192.168.0.2 dev eth0
10.0.14.0/24
nexthop via 172.16.0.3 dev dummy0 weight 1
nexthop via 172.16.1.3 dev dummy1 weight 1
$ip route get 10.0.14.2
10.0.14.2 via 172.16.1.3 dev dummy1 src 172.16.1.1
cache
$ip route get fibmatch 10.0.14.2
10.0.14.0/24
nexthop via 172.16.0.3 dev dummy0 weight 1
nexthop via 172.16.1.3 dev dummy1 weight 1
ipv6:
----
$ip -6 route show
2001:db9:100::/120 metric 1024
nexthop via 2001:db8:2::2 dev dummy0 weight 1
nexthop via 2001:db8:12::2 dev dummy1 weight 1
$ip -6 route get 2001:db9:100::1
2001:db9:100::1 from :: via 2001:db8:12::2 dev dummy1 \
src 2001:db8:12::1 metric 1024 pref medium
$ip -6 route get fibmatch 2001:db9:100::1
2001:db9:100::/120 metric 1024
nexthop via 2001:db8:12::2 dev dummy1 weight 1
nexthop via 2001:db8:2::2 dev dummy0 weight 1
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
include/linux/rtnetlink.h | 1 +
ip/iproute.c | 9 ++++++++-
man/man8/ip-route.8.in | 12 ++++++++++++
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index a96db83..3035741 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -278,6 +278,7 @@ enum rt_scope_t {
#define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */
#define RTM_F_PREFIX 0x800 /* Prefix addresses */
#define RTM_F_LOOKUP_TABLE 0x1000 /* set rtm_table to FIB lookup result */
+#define RTM_F_FIB_MATCH 0x2000 /* get fib match support */
/* Reserved table identifiers */
diff --git a/ip/iproute.c b/ip/iproute.c
index b4ca291..1b9c903 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -65,7 +65,8 @@ static void usage(void)
fprintf(stderr, " ip route save SELECTOR\n");
fprintf(stderr, " ip route restore\n");
fprintf(stderr, " ip route showdump\n");
- fprintf(stderr, " ip route get ADDRESS [ from ADDRESS iif STRING ]\n");
+ fprintf(stderr, " ip route get [ ROUTE_GET_FLAGS ] ADDRESS\n");
+ fprintf(stderr, " [ from ADDRESS iif STRING ]\n");
fprintf(stderr, " [ oif STRING ] [ tos TOS ]\n");
fprintf(stderr, " [ mark NUMBER ] [ vrf NAME ]\n");
fprintf(stderr, " [ uid NUMBER ]\n");
@@ -103,6 +104,7 @@ static void usage(void)
fprintf(stderr, "ENCAPHDR := [ MPLSLABEL | SEG6HDR ]\n");
fprintf(stderr, "SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]\n");
fprintf(stderr, "SEGMODE := [ encap | inline ]\n");
+ fprintf(stderr, "ROUTE_GET_FLAGS := [ fibmatch ]\n");
exit(-1);
}
@@ -1674,6 +1676,7 @@ static int iproute_get(int argc, char **argv)
char *idev = NULL;
char *odev = NULL;
int connected = 0;
+ int fib_match = 0;
int from_ok = 0;
unsigned int mark = 0;
@@ -1728,6 +1731,8 @@ static int iproute_get(int argc, char **argv)
if (get_unsigned(&uid, *argv, 0))
invarg("invalid UID\n", *argv);
addattr32(&req.n, sizeof(req), RTA_UID, uid);
+ } else if (matches(*argv, "fibmatch") == 0) {
+ fib_match = 1;
} else {
inet_prefix addr;
@@ -1776,6 +1781,8 @@ static int iproute_get(int argc, char **argv)
req.r.rtm_family = AF_INET;
req.r.rtm_flags |= RTM_F_LOOKUP_TABLE;
+ if (fib_match)
+ req.r.rtm_flags |= RTM_F_FIB_MATCH;
if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
return -2;
diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in
index c8eb38a..de8d360 100644
--- a/man/man8/ip-route.8.in
+++ b/man/man8/ip-route.8.in
@@ -28,6 +28,7 @@ ip-route \- routing table management
.ti -8
.B ip route get
+.I ROUTE_GET_FLAGS
.IR ADDRESS " [ "
.BI from " ADDRESS " iif " STRING"
.RB " ] [ " oif
@@ -219,6 +220,12 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
.B hmac
.IR KEYID " ]"
+.ti -8
+.IR ROUTE_GET_FLAGS " := "
+.BR " [ "
+.BR fibmatch
+.BR " ] "
+
.SH DESCRIPTION
.B ip route
is used to manipulate entries in the kernel routing tables.
@@ -930,6 +937,11 @@ this command gets a single route to a destination and prints its
contents exactly as the kernel sees it.
.TP
+.BI fibmatch
+Return full fib lookup matched route. Default is to return the resolved
+dst entry
+
+.TP
.BI to " ADDRESS " (default)
the destination address.
--
2.1.4
^ permalink raw reply related
* Re: [net,V2] vxlan: fix use-after-free on deletion
From: Roopa Prabhu @ 2017-06-02 3:31 UTC (permalink / raw)
To: Mark Bloch; +Cc: jbenc, roid, netdev
In-Reply-To: <1496363048-21138-1-git-send-email-markb@mellanox.com>
On 6/1/17, 5:24 PM, Mark Bloch wrote:
> Adding a vxlan interface to a socket isn't symmetrical, while adding
> is done in vxlan_open() the deletion is done in vxlan_dellink().
> This can cause a use-after-free error when we close the vxlan
> interface before deleting it.
>
> We add vxlan_vs_del_dev() to match vxlan_vs_add_dev() and call
> it from vxlan_stop() to match the call from vxlan_open().
>
> Fixes: 56ef9c909b40 ("vxlan: Move socket initialization to within rtnl scope")
> Acked-by: Jiri Benc <jbenc@redhat.com>
> Tested-by: Roi Dayan <roid@mellanox.com>
> Signed-off-by: Mark Bloch <markb@mellanox.com>
Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>
^ permalink raw reply
* [PATCH net] net: dsa: Move dsa_switch_{suspend,resume} out of legacy.c
From: Florian Fainelli @ 2017-06-02 2:53 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Andrew Lunn, Vivien Didelot, David S. Miller,
open list
dsa_switch_suspend() and dsa_switch_resume() are functions that belong in
net/dsa/dsa.c and are not part of the legacy platform support code.
Fixes: a6a71f19fe5e ("net: dsa: isolate legacy code")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/dsa/dsa.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
net/dsa/legacy.c | 47 -----------------------------------------------
2 files changed, 47 insertions(+), 47 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 26130ae438da..90038d45a547 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -223,6 +223,53 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+int dsa_switch_suspend(struct dsa_switch *ds)
+{
+ int i, ret = 0;
+
+ /* Suspend slave network devices */
+ for (i = 0; i < ds->num_ports; i++) {
+ if (!dsa_is_port_initialized(ds, i))
+ continue;
+
+ ret = dsa_slave_suspend(ds->ports[i].netdev);
+ if (ret)
+ return ret;
+ }
+
+ if (ds->ops->suspend)
+ ret = ds->ops->suspend(ds);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dsa_switch_suspend);
+
+int dsa_switch_resume(struct dsa_switch *ds)
+{
+ int i, ret = 0;
+
+ if (ds->ops->resume)
+ ret = ds->ops->resume(ds);
+
+ if (ret)
+ return ret;
+
+ /* Resume slave network devices */
+ for (i = 0; i < ds->num_ports; i++) {
+ if (!dsa_is_port_initialized(ds, i))
+ continue;
+
+ ret = dsa_slave_resume(ds->ports[i].netdev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dsa_switch_resume);
+#endif
+
static struct packet_type dsa_pack_type __read_mostly = {
.type = cpu_to_be16(ETH_P_XDSA),
.func = dsa_switch_rcv,
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index ad345c8b0b06..7281098df04e 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -289,53 +289,6 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
dsa_switch_unregister_notifier(ds);
}
-#ifdef CONFIG_PM_SLEEP
-int dsa_switch_suspend(struct dsa_switch *ds)
-{
- int i, ret = 0;
-
- /* Suspend slave network devices */
- for (i = 0; i < ds->num_ports; i++) {
- if (!dsa_is_port_initialized(ds, i))
- continue;
-
- ret = dsa_slave_suspend(ds->ports[i].netdev);
- if (ret)
- return ret;
- }
-
- if (ds->ops->suspend)
- ret = ds->ops->suspend(ds);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(dsa_switch_suspend);
-
-int dsa_switch_resume(struct dsa_switch *ds)
-{
- int i, ret = 0;
-
- if (ds->ops->resume)
- ret = ds->ops->resume(ds);
-
- if (ret)
- return ret;
-
- /* Resume slave network devices */
- for (i = 0; i < ds->num_ports; i++) {
- if (!dsa_is_port_initialized(ds, i))
- continue;
-
- ret = dsa_slave_resume(ds->ports[i].netdev);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(dsa_switch_resume);
-#endif
-
/* platform driver init and cleanup *****************************************/
static int dev_is_class(struct device *dev, void *class)
{
--
2.11.0
^ permalink raw reply related
* Re: [PATCH 04/12] fs: ceph: CURRENT_TIME with ktime_get_real_ts()
From: Yan, Zheng @ 2017-06-02 2:09 UTC (permalink / raw)
To: Deepa Dinamani
Cc: John Stultz, Arnd Bergmann, Linux Kernel Mailing List,
Andrew Morton, Thomas Gleixner, Al Viro, gregkh, Dilger, Andreas,
J. Bruce Fields, Chris Mason, David Miller, David Sterba,
Evgeniy Dushistov, Eric Paris, Jaegeuk Kim, Josef Bacik,
Jeff Layton, James Simmons, Ingo Molnar, Drokin, Oleg, Paul
In-Reply-To: <CABeXuvqvLr6sSGF+rZEXXxpCBDKTOeLX1ObSjbPPY4aFBuwvMg@mail.gmail.com>
On Fri, Jun 2, 2017 at 8:57 AM, Deepa Dinamani <deepa.kernel@gmail.com> wrote:
> On Thu, Jun 1, 2017 at 5:36 PM, John Stultz <john.stultz@linaro.org> wrote:
>> On Thu, Jun 1, 2017 at 5:26 PM, Yan, Zheng <ukernel@gmail.com> wrote:
>>> On Thu, Jun 1, 2017 at 6:22 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>>>> On Thu, Jun 1, 2017 at 11:56 AM, Yan, Zheng <ukernel@gmail.com> wrote:
>>>>> On Sat, Apr 8, 2017 at 8:57 AM, Deepa Dinamani <deepa.kernel@gmail.com> wrote:
>>>>
>>>>>> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
>>>>>> index 517838b..77204da 100644
>>>>>> --- a/drivers/block/rbd.c
>>>>>> +++ b/drivers/block/rbd.c
>>>>>> @@ -1922,7 +1922,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
>>>>>> {
>>>>>> struct ceph_osd_request *osd_req = obj_request->osd_req;
>>>>>>
>>>>>> - osd_req->r_mtime = CURRENT_TIME;
>>>>>> + ktime_get_real_ts(&osd_req->r_mtime);
>>>>>> osd_req->r_data_offset = obj_request->offset;
>>>>>> }
>>>>>>
>>>>>> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
>>>>>> index c681762..1d3fa90 100644
>>>>>> --- a/fs/ceph/mds_client.c
>>>>>> +++ b/fs/ceph/mds_client.c
>>>>>> @@ -1666,6 +1666,7 @@ struct ceph_mds_request *
>>>>>> ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>>>>>> {
>>>>>> struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
>>>>>> + struct timespec ts;
>>>>>>
>>>>>> if (!req)
>>>>>> return ERR_PTR(-ENOMEM);
>>>>>> @@ -1684,7 +1685,8 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>>>>>> init_completion(&req->r_safe_completion);
>>>>>> INIT_LIST_HEAD(&req->r_unsafe_item);
>>>>>>
>>>>>> - req->r_stamp = current_fs_time(mdsc->fsc->sb);
>>>>>> + ktime_get_real_ts(&ts);
>>>>>> + req->r_stamp = timespec_trunc(ts, mdsc->fsc->sb->s_time_gran);
>>>>>
>>>>> This change causes our kernel_untar_tar test case to fail (inode's
>>>>> ctime goes back). The reason is that there is time drift between the
>>>>> time stamps got by ktime_get_real_ts() and current_time(). We need to
>>>>> revert this change until current_time() uses ktime_get_real_ts()
>>>>> internally.
>>>>
>>>> Hmm, the change was not supposed to have a user-visible effect, so
>>>> something has gone wrong, but I don't immediately see how it
>>>> relates to what you observe.
>>>>
>>>> ktime_get_real_ts() and current_time() use the same time base, there
>>>> is no drift, but there is a difference in resolution, as the latter uses
>>>> the time stamp of the last jiffies update, which may be up to one jiffy
>>>> (10ms) behind the exact time we put in the request stamps here.
>>>>
>>>> Do you still see problems if you use current_kernel_time() instead of
>>>> ktime_get_real_ts()?
>>>
>>> The problem disappears after using current_kernel_time().
>>>
>>> https://github.com/ceph/ceph-client/commit/2e0f648da23167034a3cf1500bc90ec60aef2417
>>
>> From the commit above:
>> "It seems there is time drift between ktime_get_real_ts() and
>> current_kernel_time()"
>>
>> Its more of a granularity difference. current_kernel_time() returns
>> the cached time at the last tick, where as ktime_get_real_ts() reads
>> the clocksource hardware and returns the immediate time.
>>
>> Filesystems usually use the cached time (similar to
>> CLOCK_REALTIME_COARSE), for performance reasons, as touching the
>> clocksource takes time.
>
> Alternatively, it would be best for this code also to use current_time().
> I had suggested this in one of the previous versions of the patch.
> The implementation of current_time() will change when we switch vfs to
> use 64 bit time. This will prevent such errors from happening again.
> But, this also means there is more code reordering for these modules
> to get a reference to inode.
>
I took a look. it's quite inconvenience to use current_time(). I
prefer to temporarily use current_kernel_time().
Regards
Yan, Zheng
> -Deepa
^ permalink raw reply
* [PATCH v3 net-next 3/3] bpf: update perf event helper functions documentation
From: Alexei Starovoitov @ 2017-06-02 2:03 UTC (permalink / raw)
To: David S . Miller
Cc: Peter Zijlstra, Brendan Gregg, Daniel Borkmann, Teng Qin, netdev,
linux-kernel, kernel-team
In-Reply-To: <20170602020336.1062853-1-ast@fb.com>
From: Teng Qin <qinteng@fb.com>
This commit updates documentation of the bpf_perf_event_output and
bpf_perf_event_read helpers to match their implementation.
Signed-off-by: Teng Qin <qinteng@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
include/uapi/linux/bpf.h | 11 +++++++----
tools/include/uapi/linux/bpf.h | 11 +++++++----
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 94dfa9def355..e78aece03628 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -313,8 +313,11 @@ union bpf_attr {
* @flags: room for future extensions
* Return: 0 on success or negative error
*
- * u64 bpf_perf_event_read(&map, index)
- * Return: Number events read or error code
+ * u64 bpf_perf_event_read(map, flags)
+ * read perf event counter value
+ * @map: pointer to perf_event_array map
+ * @flags: index of event in the map or bitmask flags
+ * Return: value of perf event counter read or error code
*
* int bpf_redirect(ifindex, flags)
* redirect to another netdev
@@ -328,11 +331,11 @@ union bpf_attr {
* @skb: pointer to skb
* Return: realm if != 0
*
- * int bpf_perf_event_output(ctx, map, index, data, size)
+ * int bpf_perf_event_output(ctx, map, flags, data, size)
* output perf raw sample
* @ctx: struct pt_regs*
* @map: pointer to perf_event_array map
- * @index: index of event in the map
+ * @flags: index of event in the map or bitmask flags
* @data: data on stack to be output as raw data
* @size: size of data
* Return: 0 on success or negative error
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 94dfa9def355..e78aece03628 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -313,8 +313,11 @@ union bpf_attr {
* @flags: room for future extensions
* Return: 0 on success or negative error
*
- * u64 bpf_perf_event_read(&map, index)
- * Return: Number events read or error code
+ * u64 bpf_perf_event_read(map, flags)
+ * read perf event counter value
+ * @map: pointer to perf_event_array map
+ * @flags: index of event in the map or bitmask flags
+ * Return: value of perf event counter read or error code
*
* int bpf_redirect(ifindex, flags)
* redirect to another netdev
@@ -328,11 +331,11 @@ union bpf_attr {
* @skb: pointer to skb
* Return: realm if != 0
*
- * int bpf_perf_event_output(ctx, map, index, data, size)
+ * int bpf_perf_event_output(ctx, map, flags, data, size)
* output perf raw sample
* @ctx: struct pt_regs*
* @map: pointer to perf_event_array map
- * @index: index of event in the map
+ * @flags: index of event in the map or bitmask flags
* @data: data on stack to be output as raw data
* @size: size of data
* Return: 0 on success or negative error
--
2.9.3
^ permalink raw reply related
* [PATCH v3 net-next 0/3] bpf: Add BPF support to all perf_event
From: Alexei Starovoitov @ 2017-06-02 2:03 UTC (permalink / raw)
To: David S . Miller
Cc: Peter Zijlstra, Brendan Gregg, Daniel Borkmann, Teng Qin, netdev,
linux-kernel, kernel-team
v2->v3: more refactoring to address Peter's feedback.
Now all perf_events are attachable and readable
v1->v2: address Peter's feedback. Refactor patch 1 to allow attaching
bpf programs to all event types and reading counters from all of them as well
patch 2 - more tests
patch 3 - address Dave's feedback and document bpf_perf_event_read()
and bpf_perf_event_output() properly
Alexei Starovoitov (1):
perf, bpf: Add BPF support to all perf_event types
Teng Qin (2):
samples/bpf: add tests for more perf event types
bpf: update perf event helper functions documentation
include/linux/perf_event.h | 7 +-
include/uapi/linux/bpf.h | 11 ++-
kernel/bpf/arraymap.c | 29 +------
kernel/events/core.c | 47 ++++++-----
kernel/trace/bpf_trace.c | 21 ++---
samples/bpf/bpf_helpers.h | 3 +-
samples/bpf/trace_event_user.c | 73 ++++++++++++++---
samples/bpf/tracex6_kern.c | 28 +++++--
samples/bpf/tracex6_user.c | 180 ++++++++++++++++++++++++++++++++---------
tools/include/uapi/linux/bpf.h | 11 ++-
10 files changed, 287 insertions(+), 123 deletions(-)
--
2.9.3
^ permalink raw reply
* [PATCH v3 net-next 2/3] samples/bpf: add tests for more perf event types
From: Alexei Starovoitov @ 2017-06-02 2:03 UTC (permalink / raw)
To: David S . Miller
Cc: Peter Zijlstra, Brendan Gregg, Daniel Borkmann, Teng Qin, netdev,
linux-kernel, kernel-team
In-Reply-To: <20170602020336.1062853-1-ast@fb.com>
From: Teng Qin <qinteng@fb.com>
$ trace_event
tests attaching BPF program to HW_CPU_CYCLES, SW_CPU_CLOCK, HW_CACHE_L1D and other events.
It runs 'dd' in the background while bpf program collects user and kernel
stack trace on counter overflow.
User space expects to see sys_read and sys_write in the kernel stack.
$ tracex6
tests reading of various perf counters from BPF program.
Both tests were refactored to increase coverage and be more accurate.
Signed-off-by: Teng Qin <qinteng@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
samples/bpf/bpf_helpers.h | 3 +-
samples/bpf/trace_event_user.c | 73 ++++++++++++++---
samples/bpf/tracex6_kern.c | 28 +++++--
samples/bpf/tracex6_user.c | 180 ++++++++++++++++++++++++++++++++---------
4 files changed, 228 insertions(+), 56 deletions(-)
diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h
index 9a9c95f2c9fb..51e567bc70fc 100644
--- a/samples/bpf/bpf_helpers.h
+++ b/samples/bpf/bpf_helpers.h
@@ -31,7 +31,8 @@ static unsigned long long (*bpf_get_current_uid_gid)(void) =
(void *) BPF_FUNC_get_current_uid_gid;
static int (*bpf_get_current_comm)(void *buf, int buf_size) =
(void *) BPF_FUNC_get_current_comm;
-static int (*bpf_perf_event_read)(void *map, int index) =
+static unsigned long long (*bpf_perf_event_read)(void *map,
+ unsigned long long flags) =
(void *) BPF_FUNC_perf_event_read;
static int (*bpf_clone_redirect)(void *ctx, int ifindex, int flags) =
(void *) BPF_FUNC_clone_redirect;
diff --git a/samples/bpf/trace_event_user.c b/samples/bpf/trace_event_user.c
index fa4336423da5..7bd827b84a67 100644
--- a/samples/bpf/trace_event_user.c
+++ b/samples/bpf/trace_event_user.c
@@ -75,7 +75,10 @@ static void print_stack(struct key_t *key, __u64 count)
for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--)
print_addr(ip[i]);
}
- printf("\n");
+ if (count < 6)
+ printf("\r");
+ else
+ printf("\n");
if (key->kernstack == -EEXIST && !warned) {
printf("stackmap collisions seen. Consider increasing size\n");
@@ -105,7 +108,7 @@ static void print_stacks(void)
bpf_map_delete_elem(fd, &next_key);
key = next_key;
}
-
+ printf("\n");
if (!sys_read_seen || !sys_write_seen) {
printf("BUG kernel stack doesn't contain sys_read() and sys_write()\n");
int_exit(0);
@@ -122,24 +125,29 @@ static void test_perf_event_all_cpu(struct perf_event_attr *attr)
{
int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
int *pmu_fd = malloc(nr_cpus * sizeof(int));
- int i;
+ int i, error = 0;
/* open perf_event on all cpus */
for (i = 0; i < nr_cpus; i++) {
pmu_fd[i] = sys_perf_event_open(attr, -1, i, -1, 0);
if (pmu_fd[i] < 0) {
printf("sys_perf_event_open failed\n");
+ error = 1;
goto all_cpu_err;
}
assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0);
- assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0) == 0);
+ assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE) == 0);
}
- system("dd if=/dev/zero of=/dev/null count=5000k");
+ system("dd if=/dev/zero of=/dev/null count=5000k status=none");
print_stacks();
all_cpu_err:
- for (i--; i >= 0; i--)
+ for (i--; i >= 0; i--) {
+ ioctl(pmu_fd[i], PERF_EVENT_IOC_DISABLE);
close(pmu_fd[i]);
+ }
free(pmu_fd);
+ if (error)
+ int_exit(0);
}
static void test_perf_event_task(struct perf_event_attr *attr)
@@ -150,12 +158,13 @@ static void test_perf_event_task(struct perf_event_attr *attr)
pmu_fd = sys_perf_event_open(attr, 0, -1, -1, 0);
if (pmu_fd < 0) {
printf("sys_perf_event_open failed\n");
- return;
+ int_exit(0);
}
assert(ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0);
- assert(ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0) == 0);
- system("dd if=/dev/zero of=/dev/null count=5000k");
+ assert(ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE) == 0);
+ system("dd if=/dev/zero of=/dev/null count=5000k status=none");
print_stacks();
+ ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
close(pmu_fd);
}
@@ -175,11 +184,56 @@ static void test_bpf_perf_event(void)
.config = PERF_COUNT_SW_CPU_CLOCK,
.inherit = 1,
};
+ struct perf_event_attr attr_hw_cache_l1d = {
+ .sample_freq = SAMPLE_FREQ,
+ .freq = 1,
+ .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_L1D |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
+ .inherit = 1,
+ };
+ struct perf_event_attr attr_hw_cache_branch_miss = {
+ .sample_freq = SAMPLE_FREQ,
+ .freq = 1,
+ .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_BPU |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
+ .inherit = 1,
+ };
+ struct perf_event_attr attr_type_raw = {
+ .sample_freq = SAMPLE_FREQ,
+ .freq = 1,
+ .type = PERF_TYPE_RAW,
+ /* Intel Instruction Retired */
+ .config = 0xc0,
+ .inherit = 1,
+ };
+ printf("Test HW_CPU_CYCLES\n");
test_perf_event_all_cpu(&attr_type_hw);
test_perf_event_task(&attr_type_hw);
+
+ printf("Test SW_CPU_CLOCK\n");
test_perf_event_all_cpu(&attr_type_sw);
test_perf_event_task(&attr_type_sw);
+
+ printf("Test HW_CACHE_L1D\n");
+ test_perf_event_all_cpu(&attr_hw_cache_l1d);
+ test_perf_event_task(&attr_hw_cache_l1d);
+
+ printf("Test HW_CACHE_BPU\n");
+ test_perf_event_all_cpu(&attr_hw_cache_branch_miss);
+ test_perf_event_task(&attr_hw_cache_branch_miss);
+
+ printf("Test Instruction Retired\n");
+ test_perf_event_all_cpu(&attr_type_raw);
+ test_perf_event_task(&attr_type_raw);
+
+ printf("*** PASS ***\n");
}
@@ -209,7 +263,6 @@ int main(int argc, char **argv)
return 0;
}
test_bpf_perf_event();
-
int_exit(0);
return 0;
}
diff --git a/samples/bpf/tracex6_kern.c b/samples/bpf/tracex6_kern.c
index be479c4af9e2..8a7d0f977625 100644
--- a/samples/bpf/tracex6_kern.c
+++ b/samples/bpf/tracex6_kern.c
@@ -3,22 +3,36 @@
#include <uapi/linux/bpf.h>
#include "bpf_helpers.h"
-struct bpf_map_def SEC("maps") my_map = {
+struct bpf_map_def SEC("maps") counters = {
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(u32),
- .max_entries = 32,
+ .max_entries = 64,
+};
+struct bpf_map_def SEC("maps") values = {
+ .type = BPF_MAP_TYPE_HASH,
+ .key_size = sizeof(int),
+ .value_size = sizeof(u64),
+ .max_entries = 64,
};
-SEC("kprobe/sys_write")
+SEC("kprobe/htab_map_get_next_key")
int bpf_prog1(struct pt_regs *ctx)
{
- u64 count;
u32 key = bpf_get_smp_processor_id();
- char fmt[] = "CPU-%d %llu\n";
+ u64 count, *val;
+ s64 error;
+
+ count = bpf_perf_event_read(&counters, key);
+ error = (s64)count;
+ if (error <= -2 && error >= -95)
+ return 0;
- count = bpf_perf_event_read(&my_map, key);
- bpf_trace_printk(fmt, sizeof(fmt), key, count);
+ val = bpf_map_lookup_elem(&values, &key);
+ if (val)
+ *val = count;
+ else
+ bpf_map_update_elem(&values, &key, &count, BPF_NOEXIST);
return 0;
}
diff --git a/samples/bpf/tracex6_user.c b/samples/bpf/tracex6_user.c
index ca7874ed77f4..a05a99a0752f 100644
--- a/samples/bpf/tracex6_user.c
+++ b/samples/bpf/tracex6_user.c
@@ -1,73 +1,177 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
+#define _GNU_SOURCE
+
+#include <assert.h>
#include <fcntl.h>
-#include <poll.h>
-#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <linux/bpf.h>
-#include "libbpf.h"
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
#include "bpf_load.h"
+#include "libbpf.h"
#include "perf-sys.h"
#define SAMPLE_PERIOD 0x7fffffffffffffffULL
-static void test_bpf_perf_event(void)
+static void check_on_cpu(int cpu, struct perf_event_attr *attr)
{
- int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
- int *pmu_fd = malloc(nr_cpus * sizeof(int));
- int status, i;
+ int pmu_fd, error = 0;
+ cpu_set_t set;
+ __u64 value;
- struct perf_event_attr attr_insn_pmu = {
+ /* Move to target CPU */
+ CPU_ZERO(&set);
+ CPU_SET(cpu, &set);
+ assert(sched_setaffinity(0, sizeof(set), &set) == 0);
+ /* Open perf event and attach to the perf_event_array */
+ pmu_fd = sys_perf_event_open(attr, -1/*pid*/, cpu/*cpu*/, -1/*group_fd*/, 0);
+ if (pmu_fd < 0) {
+ fprintf(stderr, "sys_perf_event_open failed on CPU %d\n", cpu);
+ error = 1;
+ goto on_exit;
+ }
+ assert(bpf_map_update_elem(map_fd[0], &cpu, &pmu_fd, BPF_ANY) == 0);
+ assert(ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0) == 0);
+ /* Trigger the kprobe */
+ bpf_map_get_next_key(map_fd[1], &cpu, NULL);
+ /* Check the value */
+ if (bpf_map_lookup_elem(map_fd[1], &cpu, &value)) {
+ fprintf(stderr, "Value missing for CPU %d\n", cpu);
+ error = 1;
+ goto on_exit;
+ }
+ fprintf(stderr, "CPU %d: %llu\n", cpu, value);
+
+on_exit:
+ assert(bpf_map_delete_elem(map_fd[0], &cpu) == 0 || error);
+ assert(ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE, 0) == 0 || error);
+ assert(close(pmu_fd) == 0 || error);
+ assert(bpf_map_delete_elem(map_fd[1], &cpu) == 0 || error);
+ exit(error);
+}
+
+static void test_perf_event_array(struct perf_event_attr *attr,
+ const char *name)
+{
+ int i, status, nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ pid_t pid[nr_cpus];
+ int err = 0;
+
+ printf("Test reading %s counters\n", name);
+
+ for (i = 0; i < nr_cpus; i++) {
+ pid[i] = fork();
+ assert(pid[i] >= 0);
+ if (pid[i] == 0) {
+ check_on_cpu(i, attr);
+ exit(1);
+ }
+ }
+
+ for (i = 0; i < nr_cpus; i++) {
+ assert(waitpid(pid[i], &status, 0) == pid[i]);
+ err |= status;
+ }
+
+ if (err)
+ printf("Test: %s FAILED\n", name);
+}
+
+static void test_bpf_perf_event(void)
+{
+ struct perf_event_attr attr_cycles = {
.freq = 0,
.sample_period = SAMPLE_PERIOD,
.inherit = 0,
.type = PERF_TYPE_HARDWARE,
.read_format = 0,
.sample_type = 0,
- .config = 0,/* PMU: cycles */
+ .config = PERF_COUNT_HW_CPU_CYCLES,
+ };
+ struct perf_event_attr attr_clock = {
+ .freq = 0,
+ .sample_period = SAMPLE_PERIOD,
+ .inherit = 0,
+ .type = PERF_TYPE_SOFTWARE,
+ .read_format = 0,
+ .sample_type = 0,
+ .config = PERF_COUNT_SW_CPU_CLOCK,
+ };
+ struct perf_event_attr attr_raw = {
+ .freq = 0,
+ .sample_period = SAMPLE_PERIOD,
+ .inherit = 0,
+ .type = PERF_TYPE_RAW,
+ .read_format = 0,
+ .sample_type = 0,
+ /* Intel Instruction Retired */
+ .config = 0xc0,
+ };
+ struct perf_event_attr attr_l1d_load = {
+ .freq = 0,
+ .sample_period = SAMPLE_PERIOD,
+ .inherit = 0,
+ .type = PERF_TYPE_HW_CACHE,
+ .read_format = 0,
+ .sample_type = 0,
+ .config =
+ PERF_COUNT_HW_CACHE_L1D |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
+ };
+ struct perf_event_attr attr_llc_miss = {
+ .freq = 0,
+ .sample_period = SAMPLE_PERIOD,
+ .inherit = 0,
+ .type = PERF_TYPE_HW_CACHE,
+ .read_format = 0,
+ .sample_type = 0,
+ .config =
+ PERF_COUNT_HW_CACHE_LL |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
+ };
+ struct perf_event_attr attr_msr_tsc = {
+ .freq = 0,
+ .sample_period = 0,
+ .inherit = 0,
+ /* From /sys/bus/event_source/devices/msr/ */
+ .type = 7,
+ .read_format = 0,
+ .sample_type = 0,
+ .config = 0,
};
- for (i = 0; i < nr_cpus; i++) {
- pmu_fd[i] = sys_perf_event_open(&attr_insn_pmu, -1/*pid*/, i/*cpu*/, -1/*group_fd*/, 0);
- if (pmu_fd[i] < 0) {
- printf("event syscall failed\n");
- goto exit;
- }
-
- bpf_map_update_elem(map_fd[0], &i, &pmu_fd[i], BPF_ANY);
- ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0);
- }
+ test_perf_event_array(&attr_cycles, "HARDWARE-cycles");
+ test_perf_event_array(&attr_clock, "SOFTWARE-clock");
+ test_perf_event_array(&attr_raw, "RAW-instruction-retired");
+ test_perf_event_array(&attr_l1d_load, "HW_CACHE-L1D-load");
- status = system("ls > /dev/null");
- if (status)
- goto exit;
- status = system("sleep 2");
- if (status)
- goto exit;
-
-exit:
- for (i = 0; i < nr_cpus; i++)
- close(pmu_fd[i]);
- close(map_fd[0]);
- free(pmu_fd);
+ /* below tests may fail in qemu */
+ test_perf_event_array(&attr_llc_miss, "HW_CACHE-LLC-miss");
+ test_perf_event_array(&attr_msr_tsc, "Dynamic-msr-tsc");
}
int main(int argc, char **argv)
{
+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
char filename[256];
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+ setrlimit(RLIMIT_MEMLOCK, &r);
if (load_bpf_file(filename)) {
printf("%s", bpf_log_buf);
return 1;
}
test_bpf_perf_event();
- read_trace_pipe();
-
return 0;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v3 net-next 1/3] perf, bpf: Add BPF support to all perf_event types
From: Alexei Starovoitov @ 2017-06-02 2:03 UTC (permalink / raw)
To: David S . Miller
Cc: Peter Zijlstra, Brendan Gregg, Daniel Borkmann, Teng Qin, netdev,
linux-kernel, kernel-team
In-Reply-To: <20170602020336.1062853-1-ast@fb.com>
Allow BPF_PROG_TYPE_PERF_EVENT program types to attach to all
perf_event types, including HW_CACHE, RAW, and dynamic pmu events.
Only tracepoint/kprobe events are treated differently which require
BPF_PROG_TYPE_TRACEPOINT/BPF_PROG_TYPE_KPROBE program types accordingly.
Also add support for reading all event counters using
bpf_perf_event_read() helper.
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
include/linux/perf_event.h | 7 +++++--
kernel/bpf/arraymap.c | 29 ++++------------------------
kernel/events/core.c | 47 +++++++++++++++++++++++++++-------------------
kernel/trace/bpf_trace.c | 21 ++++++++-------------
4 files changed, 45 insertions(+), 59 deletions(-)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 24a635887f28..8fc5f0fada5e 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -896,7 +896,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr,
void *context);
extern void perf_pmu_migrate_context(struct pmu *pmu,
int src_cpu, int dst_cpu);
-extern u64 perf_event_read_local(struct perf_event *event);
+int perf_event_read_local(struct perf_event *event, u64 *value);
extern u64 perf_event_read_value(struct perf_event *event,
u64 *enabled, u64 *running);
@@ -1301,7 +1301,10 @@ static inline const struct perf_event_attr *perf_event_attrs(struct perf_event *
{
return ERR_PTR(-EINVAL);
}
-static inline u64 perf_event_read_local(struct perf_event *event) { return -EINVAL; }
+static inline int perf_event_read_local(struct perf_event *event, u64 *value)
+{
+ return -EINVAL;
+}
static inline void perf_event_print_debug(void) { }
static inline int perf_event_task_disable(void) { return -EINVAL; }
static inline int perf_event_task_enable(void) { return -EINVAL; }
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 172dc8ee0e3b..ab93490d1a00 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -452,39 +452,18 @@ static void bpf_event_entry_free_rcu(struct bpf_event_entry *ee)
static void *perf_event_fd_array_get_ptr(struct bpf_map *map,
struct file *map_file, int fd)
{
- const struct perf_event_attr *attr;
struct bpf_event_entry *ee;
- struct perf_event *event;
struct file *perf_file;
perf_file = perf_event_get(fd);
if (IS_ERR(perf_file))
return perf_file;
- event = perf_file->private_data;
- ee = ERR_PTR(-EINVAL);
-
- attr = perf_event_attrs(event);
- if (IS_ERR(attr) || attr->inherit)
- goto err_out;
-
- switch (attr->type) {
- case PERF_TYPE_SOFTWARE:
- if (attr->config != PERF_COUNT_SW_BPF_OUTPUT)
- goto err_out;
- /* fall-through */
- case PERF_TYPE_RAW:
- case PERF_TYPE_HARDWARE:
- ee = bpf_event_entry_gen(perf_file, map_file);
- if (ee)
- return ee;
- ee = ERR_PTR(-ENOMEM);
- /* fall-through */
- default:
- break;
- }
+ ee = bpf_event_entry_gen(perf_file, map_file);
+ if (ee)
+ return ee;
-err_out:
+ ee = ERR_PTR(-ENOMEM);
fput(perf_file);
return ee;
}
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6e75a5c9412d..51e40e4876c0 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3636,10 +3636,10 @@ static inline u64 perf_event_count(struct perf_event *event)
* will not be local and we cannot read them atomically
* - must not have a pmu::count method
*/
-u64 perf_event_read_local(struct perf_event *event)
+int perf_event_read_local(struct perf_event *event, u64 *value)
{
unsigned long flags;
- u64 val;
+ int ret = 0;
/*
* Disabling interrupts avoids all counter scheduling (context
@@ -3647,25 +3647,37 @@ u64 perf_event_read_local(struct perf_event *event)
*/
local_irq_save(flags);
- /* If this is a per-task event, it must be for current */
- WARN_ON_ONCE((event->attach_state & PERF_ATTACH_TASK) &&
- event->hw.target != current);
-
- /* If this is a per-CPU event, it must be for this CPU */
- WARN_ON_ONCE(!(event->attach_state & PERF_ATTACH_TASK) &&
- event->cpu != smp_processor_id());
-
/*
* It must not be an event with inherit set, we cannot read
* all child counters from atomic context.
*/
- WARN_ON_ONCE(event->attr.inherit);
+ if (event->attr.inherit) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
/*
* It must not have a pmu::count method, those are not
* NMI safe.
*/
- WARN_ON_ONCE(event->pmu->count);
+ if (event->pmu->count) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* If this is a per-task event, it must be for current */
+ if ((event->attach_state & PERF_ATTACH_TASK) &&
+ event->hw.target != current) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* If this is a per-CPU event, it must be for this CPU */
+ if (!(event->attach_state & PERF_ATTACH_TASK) &&
+ event->cpu != smp_processor_id()) {
+ ret = -EINVAL;
+ goto out;
+ }
/*
* If the event is currently on this CPU, its either a per-task event,
@@ -3675,10 +3687,11 @@ u64 perf_event_read_local(struct perf_event *event)
if (event->oncpu == smp_processor_id())
event->pmu->read(event);
- val = local64_read(&event->count);
+ *value = local64_read(&event->count);
+out:
local_irq_restore(flags);
- return val;
+ return ret;
}
static int perf_event_read(struct perf_event *event, bool group)
@@ -8037,12 +8050,8 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
bool is_kprobe, is_tracepoint;
struct bpf_prog *prog;
- if (event->attr.type == PERF_TYPE_HARDWARE ||
- event->attr.type == PERF_TYPE_SOFTWARE)
- return perf_event_set_bpf_handler(event, prog_fd);
-
if (event->attr.type != PERF_TYPE_TRACEPOINT)
- return -EINVAL;
+ return perf_event_set_bpf_handler(event, prog_fd);
if (event->tp_event->prog)
return -EEXIST;
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 460a031c77e5..957ab2d35d7b 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -235,6 +235,8 @@ BPF_CALL_2(bpf_perf_event_read, struct bpf_map *, map, u64, flags)
u64 index = flags & BPF_F_INDEX_MASK;
struct bpf_event_entry *ee;
struct perf_event *event;
+ u64 value = 0;
+ int err;
if (unlikely(flags & ~(BPF_F_INDEX_MASK)))
return -EINVAL;
@@ -247,21 +249,14 @@ BPF_CALL_2(bpf_perf_event_read, struct bpf_map *, map, u64, flags)
if (!ee)
return -ENOENT;
- event = ee->event;
- if (unlikely(event->attr.type != PERF_TYPE_HARDWARE &&
- event->attr.type != PERF_TYPE_RAW))
- return -EINVAL;
-
- /* make sure event is local and doesn't have pmu::count */
- if (unlikely(event->oncpu != cpu || event->pmu->count))
- return -EINVAL;
-
+ err = perf_event_read_local(ee->event, &value);
/*
- * we don't know if the function is run successfully by the
- * return value. It can be judged in other places, such as
- * eBPF programs.
+ * this api is ugly since we miss [-95..-2] range of valid
+ * counter values, but that's uapi
*/
- return perf_event_read_local(event);
+ if (err)
+ return err;
+ return value;
}
static const struct bpf_func_proto bpf_perf_event_read_proto = {
--
2.9.3
^ permalink raw reply related
* Re: [PATCH net-next v2 2/2] bpf: Remove the capability check for cgroup skb eBPF program
From: Alexei Starovoitov @ 2017-06-02 1:58 UTC (permalink / raw)
To: Chenbo Feng; +Cc: Chenbo Feng, netdev, David Miller, Lorenzo Colitti
In-Reply-To: <CAMOXUJkHsj8c6Yc8FSvJsFt3vPcf-UKV0PPVWY8ewcZuA2vUwA@mail.gmail.com>
On Thu, Jun 01, 2017 at 06:55:09PM -0700, Chenbo Feng wrote:
> On Thu, Jun 1, 2017 at 4:42 PM, Alexei Starovoitov <
> alexei.starovoitov@gmail.com> wrote:
>
> > On Wed, May 31, 2017 at 06:16:00PM -0700, Chenbo Feng wrote:
> > > From: Chenbo Feng <fengc@google.com>
> > >
> > > Currently loading a cgroup skb eBPF program require a CAP_SYS_ADMIN
> > > capability while attaching the program to a cgroup only requires the
> > > user have CAP_NET_ADMIN privilege. We can escape the capability
> > > check when load the program just like socket filter program to make
> > > the capability requirement consistent.
> > >
> > > Change since v1:
> > > Change the code style in order to be compliant with checkpatch.pl
> > > preference
> > >
> > > Signed-off-by: Chenbo Feng <fengc@google.com>
> >
> > as far as I can see they're indeed the same as socket filters, so
> > Acked-by: Alexei Starovoitov <ast@kernel.org>
> >
> > but I don't quite understand how it helps, since as you said
> > attaching such unpriv fd to cgroup still requires root.
> > Do you have more patches to follow?
> >
> > Actually not, the purpose of this patch is only to make sure if a program
> have
> CAP_NET_ADMIN but not CAP_SYS_ADMIN it can still load and attach eBPF
> programs to cgroup.
got it. Thanks
^ permalink raw reply
* Re: [PATCH] virtio_net: lower limit on buffer size
From: J. Bruce Fields @ 2017-06-02 1:57 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: linux-kernel, Mikulas Patocka, Jason Wang, virtualization, netdev
In-Reply-To: <1496361148-4603-1-git-send-email-mst@redhat.com>
On Fri, Jun 02, 2017 at 02:56:04AM +0300, Michael S. Tsirkin wrote:
> commit d85b758f72b0 "virtio_net: fix support for small rings"
> was supposed to increase the buffer size for small rings
> but had an unintentional side effect of decreasing
> it for large rings. This seems to break some setups -
> it's not yet clear why, but increasing buffer size
> back to what it was before helps.
>
> Fixes: d85b758f72b0 "virtio_net: fix support for small rings"
> Reported-by: Mikulas Patocka <mpatocka@redhat.com>
> Reported-by: "J. Bruce Fields" <bfields@fieldses.org>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>
> Can reporters please confirm whether the following helps?
Works for me.
--b.
> If it does I think we should queue it even though I expect I'll need to
> investigate the exact reasons for the failure down the road - probably
> a hypervisor bug.
>
> drivers/net/virtio_net.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 87b5c20..60abb5d 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -842,7 +842,7 @@ static unsigned int get_mergeable_buf_len(struct receive_queue *rq,
> unsigned int len;
>
> len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len),
> - rq->min_buf_len - hdr_len, PAGE_SIZE - hdr_len);
> + rq->min_buf_len, PAGE_SIZE - hdr_len);
> return ALIGN(len, L1_CACHE_BYTES);
> }
>
> @@ -2039,7 +2039,8 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
> unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len;
> unsigned int min_buf_len = DIV_ROUND_UP(buf_len, rq_size);
>
> - return max(min_buf_len, hdr_len);
> + return max(max(min_buf_len, hdr_len) - hdr_len,
> + (unsigned int)GOOD_PACKET_LEN);
> }
>
> static int virtnet_find_vqs(struct virtnet_info *vi)
> --
> MST
^ permalink raw reply
* Re: [PATCH] b43legacy: Fix a sleep-in-atomic bug in b43legacy_attr_interfmode_store
From: Jia-Ju Bai @ 2017-06-02 1:18 UTC (permalink / raw)
To: Jonathan Corbet
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
b43-dev-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
kvalo-sgV2jX0FEOL9JmXXK+q4OQ, Larry Finger
In-Reply-To: <20170601101113.6dd30d6d-T1hC0tSOHrs@public.gmane.org>
On 06/02/2017 12:11 AM, Jonathan Corbet wrote:
> On Thu, 01 Jun 2017 09:05:07 +0800
> Jia-Ju Bai<baijiaju1990-9Onoh4P/yGk@public.gmane.org> wrote:
>
>> I admit my patches are not well tested, and they may not well fix the bugs.
>> I am looking forward to opinions and suggestions :)
> May I politely suggest that sending out untested locking changes is a
> dangerous thing to do? You really should not be changing the locking in a
> piece of kernel code without understanding very well what the lock is
> protecting and being able to say why your changes are safe. Without that,
> the risk of introducing subtle bugs is very high.
>
> It looks like you have written a useful tool that could help us to make
> the kernel more robust. If you are interested in my suggestion, I would
> recommend that you post the sleep-in-atomic scenarios that you are
> finding, but refrain from "fixing" them in any case where you cannot offer
> a strong explanation of why your fix is correct.
>
> Thanks for working to find bugs in the kernel!
>
> jon
Hi,
Thanks for your good and helpful advice. I am sorry for my improper patches.
I will only report bugs instead of sending improper patches when I have
no good solution of fixing the bugs.
Thanks,
Jia-Ju Bai
^ permalink raw reply
* [PATCH net] net: systemport: Fix missing Wake-on-LAN interrupt for SYSTEMPORT Lite
From: Florian Fainelli @ 2017-06-02 1:02 UTC (permalink / raw)
To: netdev; +Cc: davem, Florian Fainelli
On SYSTEMPORT Lite, since we have the main interrupt source in the first
cell, the second cell is the Wake-on-LAN interrupt, yet the code was not
properly updated to fetch the second cell, and instead looked at the
third and non-existing cell for Wake-on-LAN.
Fixes: 44a4524c54af ("net: systemport: Add support for SYSTEMPORT Lite")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/bcmsysport.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 099b374c1b17..5274501428e4 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -2026,9 +2026,12 @@ static int bcm_sysport_probe(struct platform_device *pdev)
priv->num_rx_desc_words = params->num_rx_desc_words;
priv->irq0 = platform_get_irq(pdev, 0);
- if (!priv->is_lite)
+ if (!priv->is_lite) {
priv->irq1 = platform_get_irq(pdev, 1);
- priv->wol_irq = platform_get_irq(pdev, 2);
+ priv->wol_irq = platform_get_irq(pdev, 2);
+ } else {
+ priv->wol_irq = platform_get_irq(pdev, 1);
+ }
if (priv->irq0 <= 0 || (priv->irq1 <= 0 && !priv->is_lite)) {
dev_err(&pdev->dev, "invalid interrupts\n");
ret = -EINVAL;
--
2.9.3
^ permalink raw reply related
* Re: [PATCH 04/12] fs: ceph: CURRENT_TIME with ktime_get_real_ts()
From: Deepa Dinamani @ 2017-06-02 0:57 UTC (permalink / raw)
To: John Stultz
Cc: yuchao0-hv44wF8Li93QT0dZR+AlfA, J. Bruce Fields, Chris Mason,
linux-mtd, Evgeniy Dushistov, Jeff Layton, ceph-devel,
devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
linux-cifs-u79uwXL29TY76Z2rM5mHXA, Paul Moore, y2038 Mailman List,
Ingo Molnar, Arnd Bergmann, Yan, Zheng, Steven Rostedt,
Drokin, Oleg, Al Viro, David Sterba, Jaegeuk Kim, Thomas Gleixner,
Josef Bacik, gregkh, samba-technical-w/Ol4Ecudpl8XjKLYN78aQ,
Linux Kernel Mailing List, Eric Paris
In-Reply-To: <CALAqxLV-yVKWM5es7fAFiDzhSQmtZFiZDPQwBRUYbWUtqhoWVg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Thu, Jun 1, 2017 at 5:36 PM, John Stultz <john.stultz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> On Thu, Jun 1, 2017 at 5:26 PM, Yan, Zheng <ukernel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On Thu, Jun 1, 2017 at 6:22 PM, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
>>> On Thu, Jun 1, 2017 at 11:56 AM, Yan, Zheng <ukernel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>>> On Sat, Apr 8, 2017 at 8:57 AM, Deepa Dinamani <deepa.kernel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>>
>>>>> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
>>>>> index 517838b..77204da 100644
>>>>> --- a/drivers/block/rbd.c
>>>>> +++ b/drivers/block/rbd.c
>>>>> @@ -1922,7 +1922,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
>>>>> {
>>>>> struct ceph_osd_request *osd_req = obj_request->osd_req;
>>>>>
>>>>> - osd_req->r_mtime = CURRENT_TIME;
>>>>> + ktime_get_real_ts(&osd_req->r_mtime);
>>>>> osd_req->r_data_offset = obj_request->offset;
>>>>> }
>>>>>
>>>>> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
>>>>> index c681762..1d3fa90 100644
>>>>> --- a/fs/ceph/mds_client.c
>>>>> +++ b/fs/ceph/mds_client.c
>>>>> @@ -1666,6 +1666,7 @@ struct ceph_mds_request *
>>>>> ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>>>>> {
>>>>> struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
>>>>> + struct timespec ts;
>>>>>
>>>>> if (!req)
>>>>> return ERR_PTR(-ENOMEM);
>>>>> @@ -1684,7 +1685,8 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>>>>> init_completion(&req->r_safe_completion);
>>>>> INIT_LIST_HEAD(&req->r_unsafe_item);
>>>>>
>>>>> - req->r_stamp = current_fs_time(mdsc->fsc->sb);
>>>>> + ktime_get_real_ts(&ts);
>>>>> + req->r_stamp = timespec_trunc(ts, mdsc->fsc->sb->s_time_gran);
>>>>
>>>> This change causes our kernel_untar_tar test case to fail (inode's
>>>> ctime goes back). The reason is that there is time drift between the
>>>> time stamps got by ktime_get_real_ts() and current_time(). We need to
>>>> revert this change until current_time() uses ktime_get_real_ts()
>>>> internally.
>>>
>>> Hmm, the change was not supposed to have a user-visible effect, so
>>> something has gone wrong, but I don't immediately see how it
>>> relates to what you observe.
>>>
>>> ktime_get_real_ts() and current_time() use the same time base, there
>>> is no drift, but there is a difference in resolution, as the latter uses
>>> the time stamp of the last jiffies update, which may be up to one jiffy
>>> (10ms) behind the exact time we put in the request stamps here.
>>>
>>> Do you still see problems if you use current_kernel_time() instead of
>>> ktime_get_real_ts()?
>>
>> The problem disappears after using current_kernel_time().
>>
>> https://github.com/ceph/ceph-client/commit/2e0f648da23167034a3cf1500bc90ec60aef2417
>
> From the commit above:
> "It seems there is time drift between ktime_get_real_ts() and
> current_kernel_time()"
>
> Its more of a granularity difference. current_kernel_time() returns
> the cached time at the last tick, where as ktime_get_real_ts() reads
> the clocksource hardware and returns the immediate time.
>
> Filesystems usually use the cached time (similar to
> CLOCK_REALTIME_COARSE), for performance reasons, as touching the
> clocksource takes time.
Alternatively, it would be best for this code also to use current_time().
I had suggested this in one of the previous versions of the patch.
The implementation of current_time() will change when we switch vfs to
use 64 bit time. This will prevent such errors from happening again.
But, this also means there is more code reordering for these modules
to get a reference to inode.
-Deepa
^ permalink raw reply
* Re: [PATCH 04/12] fs: ceph: CURRENT_TIME with ktime_get_real_ts()
From: John Stultz @ 2017-06-02 0:36 UTC (permalink / raw)
To: Yan, Zheng
Cc: Arnd Bergmann, Deepa Dinamani, Linux Kernel Mailing List,
Andrew Morton, Thomas Gleixner, Al Viro, gregkh, Dilger, Andreas,
J. Bruce Fields, Chris Mason, David Miller, David Sterba,
Evgeniy Dushistov, Eric Paris, Jaegeuk Kim, Josef Bacik,
Jeff Layton, James Simmons, Ingo Molnar, Drokin, Oleg, P
In-Reply-To: <CAAM7YAnWLUXMOCVbgfdKGfvK04EtAQcz-ETm7xFO=8Y=_fCvOQ@mail.gmail.com>
On Thu, Jun 1, 2017 at 5:26 PM, Yan, Zheng <ukernel@gmail.com> wrote:
> On Thu, Jun 1, 2017 at 6:22 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Thu, Jun 1, 2017 at 11:56 AM, Yan, Zheng <ukernel@gmail.com> wrote:
>>> On Sat, Apr 8, 2017 at 8:57 AM, Deepa Dinamani <deepa.kernel@gmail.com> wrote:
>>
>>>> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
>>>> index 517838b..77204da 100644
>>>> --- a/drivers/block/rbd.c
>>>> +++ b/drivers/block/rbd.c
>>>> @@ -1922,7 +1922,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
>>>> {
>>>> struct ceph_osd_request *osd_req = obj_request->osd_req;
>>>>
>>>> - osd_req->r_mtime = CURRENT_TIME;
>>>> + ktime_get_real_ts(&osd_req->r_mtime);
>>>> osd_req->r_data_offset = obj_request->offset;
>>>> }
>>>>
>>>> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
>>>> index c681762..1d3fa90 100644
>>>> --- a/fs/ceph/mds_client.c
>>>> +++ b/fs/ceph/mds_client.c
>>>> @@ -1666,6 +1666,7 @@ struct ceph_mds_request *
>>>> ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>>>> {
>>>> struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
>>>> + struct timespec ts;
>>>>
>>>> if (!req)
>>>> return ERR_PTR(-ENOMEM);
>>>> @@ -1684,7 +1685,8 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>>>> init_completion(&req->r_safe_completion);
>>>> INIT_LIST_HEAD(&req->r_unsafe_item);
>>>>
>>>> - req->r_stamp = current_fs_time(mdsc->fsc->sb);
>>>> + ktime_get_real_ts(&ts);
>>>> + req->r_stamp = timespec_trunc(ts, mdsc->fsc->sb->s_time_gran);
>>>
>>> This change causes our kernel_untar_tar test case to fail (inode's
>>> ctime goes back). The reason is that there is time drift between the
>>> time stamps got by ktime_get_real_ts() and current_time(). We need to
>>> revert this change until current_time() uses ktime_get_real_ts()
>>> internally.
>>
>> Hmm, the change was not supposed to have a user-visible effect, so
>> something has gone wrong, but I don't immediately see how it
>> relates to what you observe.
>>
>> ktime_get_real_ts() and current_time() use the same time base, there
>> is no drift, but there is a difference in resolution, as the latter uses
>> the time stamp of the last jiffies update, which may be up to one jiffy
>> (10ms) behind the exact time we put in the request stamps here.
>>
>> Do you still see problems if you use current_kernel_time() instead of
>> ktime_get_real_ts()?
>
> The problem disappears after using current_kernel_time().
>
> https://github.com/ceph/ceph-client/commit/2e0f648da23167034a3cf1500bc90ec60aef2417
>From the commit above:
"It seems there is time drift between ktime_get_real_ts() and
current_kernel_time()"
Its more of a granularity difference. current_kernel_time() returns
the cached time at the last tick, where as ktime_get_real_ts() reads
the clocksource hardware and returns the immediate time.
Filesystems usually use the cached time (similar to
CLOCK_REALTIME_COARSE), for performance reasons, as touching the
clocksource takes time.
thanks
-john
^ permalink raw reply
* Re: [PATCH 04/12] fs: ceph: CURRENT_TIME with ktime_get_real_ts()
From: Yan, Zheng @ 2017-06-02 0:35 UTC (permalink / raw)
To: Arnd Bergmann
Cc: yuchao0, J. Bruce Fields, Chris Mason, linux-mtd, Deepa Dinamani,
Evgeniy Dushistov, Jeff Layton, ceph-devel, devel, linux-cifs,
Paul Moore, y2038 Mailman List, Ingo Molnar, Steven Rostedt,
Drokin, Oleg, John Stultz, Al Viro, David Sterba, Jaegeuk Kim,
Thomas Gleixner, Dilger, Andreas, Josef Bacik, gregkh,
samba-technical, Linux
In-Reply-To: <CAK8P3a1pCw1Oo-Wg70kH5L12pbtEzGDfaPZ8g6ErERJjvY8znQ@mail.gmail.com>
On Thu, Jun 1, 2017 at 6:22 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thu, Jun 1, 2017 at 11:56 AM, Yan, Zheng <ukernel@gmail.com> wrote:
>> On Sat, Apr 8, 2017 at 8:57 AM, Deepa Dinamani <deepa.kernel@gmail.com> wrote:
>
>>> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
>>> index 517838b..77204da 100644
>>> --- a/drivers/block/rbd.c
>>> +++ b/drivers/block/rbd.c
>>> @@ -1922,7 +1922,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
>>> {
>>> struct ceph_osd_request *osd_req = obj_request->osd_req;
>>>
>>> - osd_req->r_mtime = CURRENT_TIME;
>>> + ktime_get_real_ts(&osd_req->r_mtime);
>>> osd_req->r_data_offset = obj_request->offset;
>>> }
>>>
>>> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
>>> index c681762..1d3fa90 100644
>>> --- a/fs/ceph/mds_client.c
>>> +++ b/fs/ceph/mds_client.c
>>> @@ -1666,6 +1666,7 @@ struct ceph_mds_request *
>>> ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>>> {
>>> struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
>>> + struct timespec ts;
>>>
>>> if (!req)
>>> return ERR_PTR(-ENOMEM);
>>> @@ -1684,7 +1685,8 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>>> init_completion(&req->r_safe_completion);
>>> INIT_LIST_HEAD(&req->r_unsafe_item);
>>>
>>> - req->r_stamp = current_fs_time(mdsc->fsc->sb);
>>> + ktime_get_real_ts(&ts);
>>> + req->r_stamp = timespec_trunc(ts, mdsc->fsc->sb->s_time_gran);
>>
>> This change causes our kernel_untar_tar test case to fail (inode's
>> ctime goes back). The reason is that there is time drift between the
>> time stamps got by ktime_get_real_ts() and current_time(). We need to
>> revert this change until current_time() uses ktime_get_real_ts()
>> internally.
>
> Hmm, the change was not supposed to have a user-visible effect, so
> something has gone wrong, but I don't immediately see how it
> relates to what you observe.
>
> ktime_get_real_ts() and current_time() use the same time base, there
> is no drift, but there is a difference in resolution, as the latter uses
> the time stamp of the last jiffies update, which may be up to one jiffy
> (10ms) behind the exact time we put in the request stamps here.
>
It happens in following sequence of events
1. create a new file, the inode's ctime is set to ktime_get_real_ts()
2. chmod the new file, the inode's ctime is set to current_time().
Inode's ctime goes back when current_time() is behind ktime_get_real_ts().
Regards
Yan, Zheng
> Do you still see problems if you use current_kernel_time() instead of
> ktime_get_real_ts()?
>
> Arnd
^ 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