Skip to contentSkip to conversation

RDMA fixes for-4.13

GIT PULL New Leon Romanovsky 2 participants 7 messages Aug 1, 2017 – Aug 6, 2017 2 messages not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

Changelog:
v0 -> v1:
* Added Reviewed-by tags
* Moved 10 patches to -next

Thanks
----------------------------------------------------------------

The following changes since commit 5dc78ad1904db597bdb4427f3ead437aae86f54c:

IB/ipoib: Notify on modify QP failure only when relevant (2017-07-23 10:52:00 +0300)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/leon/linux-rdma.git tags/rdma-rc-2017-08-01

for you to fetch changes up to 0626c5a5dec2e601f06a2c03b295fb7d7288e29c:

RDMA/mlx5: Fix existence check for extended address vector (2017-07-31 20:43:06 +0300)

----------------------------------------------------------------
RDMA fixes for 4.13

This patchset contains four patches:
* Two kernel panic fixes from Yishai and Parav.
* The bugfix to mlx5 wrong usage of big-endian variable.
* Preventing leak of reserved field.

----------------------------------------------------------------
Leon Romanovsky (2):
RDMA/uverbs: Prevent leak of reserved field RDMA/mlx5: Fix existence check for extended address vector

Parav Pandit (1):
IB/core: Fix race condition in resolving IP to MAC

Yishai Hadas (1):
IB/uverbs: Fix device cleanup

 drivers/infiniband/core/addr.c        | 62 +++++++++++++++++++++++++++--------
 drivers/infiniband/core/uverbs_cmd.c  |  2 +-
 drivers/infiniband/core/uverbs_main.c |  3 +-
 drivers/infiniband/hw/mlx5/odp.c      |  2 +-
 include/linux/mlx5/qp.h               |  1 -
 5 files changed, 51 insertions(+), 19 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): 20170801064137.8360-1-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org

#2 lore raw

PATCH 1/4 IB/core: Fix race condition in resolving IP to MAC

From: Parav Pandit <parav-VPRAkNaXOzVWk0Htik3J/[email protected]>

Currently while resolving IP address to MAC address single delayed work is used for resolving multiple such resolve requests. This singled work is essentially performs two tasks.
(a) any retry needed to resolve and
(b) it executes the callback function for all completed requests

While work is executing callbacks, any new work scheduled on for this workqueue is lost because workqueue has completed looking at all pending requests and now looking at callbacks, but work is still under execution. Any further retry to look at pending requests in process_req() after executing callbacks would lead to similar race condition (may be reduce the probably further but doesn't eliminate it). Retrying to enqueue work that from queue_req() context is not something rest of the kernel modules have followed.

Therefore fix in this patch utilizes kernel facility to enqueue multiple work items to a workqueue. This ensures that no such requests gets lost in synchronization. Request list is still maintained so that rdma_cancel_addr() can unlink the request and get the completion with error sooner. Neighbour update event handling continues to be handled in same way as before.
Additionally process_req() work entry cancels any pending work for a request that gets completed while processing those requests.

Originally ib_addr was ST workqueue, but it became MT work queue with patch of [1]. This patch again makes it similar to ST so that neighbour update events handler work item doesn't race with other work items.

In one such below trace, (though on 4.5 based kernel) it can be seen that process_req() never executed the callback, which is likely for an event that was schedule by queue_req() when previous callback was getting executed by workqueue.

 [<ffffffff816b0dde>] schedule+0x3e/0x90
 [<ffffffff816b3c45>] schedule_timeout+0x1b5/0x210
 [<ffffffff81618c37>] ? ip_route_output_flow+0x27/0x70
 [<ffffffffa027f9c9>] ? addr_resolve+0x149/0x1b0 [ib_addr]
 [<ffffffff816b228f>] wait_for_completion+0x10f/0x170
 [<ffffffff810b6140>] ? try_to_wake_up+0x210/0x210
 [<ffffffffa027f220>] ? rdma_copy_addr+0xa0/0xa0 [ib_addr]
 [<ffffffffa0280120>] rdma_addr_find_l2_eth_by_grh+0x1d0/0x278 [ib_addr]
 [<ffffffff81321297>] ? sub_alloc+0x77/0x1c0
 [<ffffffffa02943b7>] ib_init_ah_from_wc+0x3a7/0x5a0 [ib_core]
 [<ffffffffa0457aba>] cm_req_handler+0xea/0x580 [ib_cm]
 [<ffffffff81015982>] ? __switch_to+0x212/0x5e0
 [<ffffffffa04582fd>] cm_work_handler+0x6d/0x150 [ib_cm]
 [<ffffffff810a14c1>] process_one_work+0x151/0x4b0
 [<ffffffff810a1940>] worker_thread+0x120/0x480
 [<ffffffff816b074b>] ? __schedule+0x30b/0x890
 [<ffffffff810a1820>] ? process_one_work+0x4b0/0x4b0
 [<ffffffff810a1820>] ? process_one_work+0x4b0/0x4b0
 [<ffffffff810a6b1e>] kthread+0xce/0xf0
 [<ffffffff810a6a50>] ? kthread_freezable_should_stop+0x70/0x70
 [<ffffffff816b53a2>] ret_from_fork+0x42/0x70
 [<ffffffff810a6a50>] ? kthread_freezable_should_stop+0x70/0x70
INFO: task kworker/u144:1:156520 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this
message.
kworker/u144:1  D ffff883ffe1d7600     0 156520      2 0x00000080
Workqueue: ib_addr process_req [ib_addr]
 ffff883f446fbbd8 0000000000000046 ffff881f95280000 ffff881ff24de200
 ffff883f66120000 ffff883f446f8008 ffff881f95280000 ffff883f6f9208c4
 ffff883f6f9208c8 00000000ffffffff ffff883f446fbbf8 ffffffff816b0dde

[1] http://lkml.iu.edu/hypermail/linux/kernel/1608.1/05834.html

---
 drivers/infiniband/core/addr.c | 62 ++++++++++++++++++++++++++++++++----------
 1 file changed, 48 insertions(+), 14 deletions(-)
drivers/infiniband/core/addr.c +48 -14
index 01236cef7bfb..437522ca97b4 100644
@@ -61,6 +61,7 @@ struct addr_req {
 	void (*callback)(int status, struct sockaddr *src_addr,
 			 struct rdma_dev_addr *addr, void *context);
 	unsigned long timeout;
+	struct delayed_work work;
 	int status;
 	u32 seq;
 };
@@ -295,7 +296,7 @@ int rdma_translate_ip(const struct sockaddr *addr,
 }
 EXPORT_SYMBOL(rdma_translate_ip);
 
-static void set_timeout(unsigned long time)
+static void set_timeout(struct delayed_work *delayed_work, unsigned long time)
 {
 	unsigned long delay;
 
@@ -303,7 +304,7 @@ static void set_timeout(unsigned long time)
 	if ((long)delay < 0)
 		delay = 0;
 
-	mod_delayed_work(addr_wq, &work, delay);
+	mod_delayed_work(addr_wq, delayed_work, delay);
 }
 
 static void queue_req(struct addr_req *req)
@@ -318,8 +319,7 @@ static void queue_req(struct addr_req *req)
 
 	list_add(&req->list, &temp_req->list);
 
-	if (req_list.next == &req->list)
-		set_timeout(req->timeout);
+	set_timeout(&req->work, req->timeout);
 	mutex_unlock(&lock);
 }
 
@@ -574,6 +574,37 @@ static int addr_resolve(struct sockaddr *src_in,
 	return ret;
 }
 
+static void process_one_req(struct work_struct *_work)
+{
+	struct addr_req *req;
+	struct sockaddr *src_in, *dst_in;
+
+	mutex_lock(&lock);
+	req = container_of(_work, struct addr_req, work.work);
+
+	if (req->status == -ENODATA) {
+		src_in = (struct sockaddr *)&req->src_addr;
+		dst_in = (struct sockaddr *)&req->dst_addr;
+		req->status = addr_resolve(src_in, dst_in, req->addr,
+					   true, req->seq);
+		if (req->status && time_after_eq(jiffies, req->timeout)) {
+			req->status = -ETIMEDOUT;
+		} else if (req->status == -ENODATA) {
+			/* requeue the work for retrying again */
+			set_timeout(&req->work, req->timeout);
+			mutex_unlock(&lock);
+			return;
+		}
+	}
+	list_del(&req->list);
+	mutex_unlock(&lock);
+
+	req->callback(req->status, (struct sockaddr *)&req->src_addr,
+		req->addr, req->context);
+	put_client(req->client);
+	kfree(req);
+}
+
 static void process_req(struct work_struct *work)
 {
 	struct addr_req *req, *temp_req;
@@ -591,20 +622,23 @@ static void process_req(struct work_struct *work)
 						   true, req->seq);
 			if (req->status && time_after_eq(jiffies, req->timeout))
 				req->status = -ETIMEDOUT;
-			else if (req->status == -ENODATA)
+			else if (req->status == -ENODATA) {
+				set_timeout(&req->work, req->timeout);
 				continue;
+			}
 		}
 		list_move_tail(&req->list, &done_list);
 	}
 
-	if (!list_empty(&req_list)) {
-		req = list_entry(req_list.next, struct addr_req, list);
-		set_timeout(req->timeout);
-	}
 	mutex_unlock(&lock);
 
 	list_for_each_entry_safe(req, temp_req, &done_list, list) {
 		list_del(&req->list);
+		/* It is safe to cancel other work items from this work item
+		 * because at a time there can be only one work item running
+		 * with this single threaded work queue.
+		 */
+		cancel_delayed_work(&req->work);
 		req->callback(req->status, (struct sockaddr *) &req->src_addr,
 			req->addr, req->context);
 		put_client(req->client);
@@ -647,6 +681,7 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
 	req->context = context;
 	req->client = client;
 	atomic_inc(&client->refcount);
+	INIT_DELAYED_WORK(&req->work, process_one_req);
 	req->seq = (u32)atomic_inc_return(&ib_nl_addr_request_seq);
 
 	req->status = addr_resolve(src_in, dst_in, addr, true, req->seq);
@@ -701,7 +736,7 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr)
 			req->status = -ECANCELED;
 			req->timeout = jiffies;
 			list_move(&req->list, &req_list);
-			set_timeout(req->timeout);
+			set_timeout(&req->work, req->timeout);
 			break;
 		}
 	}
@@ -807,9 +842,8 @@ static int netevent_callback(struct notifier_block *self, unsigned long event,
 	if (event == NETEVENT_NEIGH_UPDATE) {
 		struct neighbour *neigh = ctx;
 
-		if (neigh->nud_state & NUD_VALID) {
-			set_timeout(jiffies);
-		}
+		if (neigh->nud_state & NUD_VALID)
+			set_timeout(&work, jiffies);
 	}
 	return 0;
 }
@@ -820,7 +854,7 @@ static struct notifier_block nb = {
 
 int addr_init(void)
 {
-	addr_wq = alloc_workqueue("ib_addr", WQ_MEM_RECLAIM, 0);
+	addr_wq = alloc_ordered_workqueue("ib_addr", WQ_MEM_RECLAIM);
 	if (!addr_wq)
 		return -ENOMEM;
 

--
2.13.3

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#3 lore raw

PATCH 2/4 RDMA/uverbs: Prevent leak of reserved field

In reply to a message not in the archive

From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/[email protected]>

initialize to zero the response structure to prevent the leakage of "resp.reserved" field.

drivers/infiniband/core/uverbs_cmd.c:1178 ib_uverbs_resize_cq() warn:
check that 'resp.reserved' doesn't leak information

Fixes 33b9b3ee9709 ("IB: Add userspace support for resizing CQs")
---
 drivers/infiniband/core/uverbs_cmd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/core/uverbs_cmd.c +1 -1
index 2c98533a0203..c551d2b275fd 100644
@@ -1153,7 +1153,7 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
 			    int out_len)
 {
 	struct ib_uverbs_resize_cq	cmd;
-	struct ib_uverbs_resize_cq_resp	resp;
+	struct ib_uverbs_resize_cq_resp	resp = {};
 	struct ib_udata                 udata;
 	struct ib_cq			*cq;
 	int				ret = -EINVAL;

--
2.13.3

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#4 lore raw

PATCH 3/4 IB/uverbs: Fix device cleanup

In reply to a message not in the archive

From: Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/[email protected]>

Uverbs device should be cleaned up only when there is no potential usage of.

As part of ib_uverbs_remove_one which might be triggered upon reset flow the device reference count is decreased as expected and leave the final cleanup to the FDs that were opened.

Current code increases reference count upon opening a new command FD and decreases it upon closing the file. The event FD is opened internally and rely on the command FD by taking on it a reference count.

In case that the command FD was closed and just later the event FD we may ensure that the device resources as of srcu are still alive as they are still in use.

Fixing the above by moving the reference count decreasing to the place where the command FD is really freed instead of doing that when it was just closed.

---
 drivers/infiniband/core/uverbs_main.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/infiniband/core/uverbs_main.c +1 -2
index 3d2609608f58..c023e2c81b8f 100644
@@ -250,6 +250,7 @@ void ib_uverbs_release_file(struct kref *ref)
 	if (atomic_dec_and_test(&file->device->refcount))
 		ib_uverbs_comp_dev(file->device);
 
+	kobject_put(&file->device->kobj);
 	kfree(file);
 }
 
@@ -917,7 +918,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
 static int ib_uverbs_close(struct inode *inode, struct file *filp)
 {
 	struct ib_uverbs_file *file = filp->private_data;
-	struct ib_uverbs_device *dev = file->device;
 
 	mutex_lock(&file->cleanup_mutex);
 	if (file->ucontext) {
@@ -939,7 +939,6 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
 			 ib_uverbs_release_async_event_file);
 
 	kref_put(&file->ref, ib_uverbs_release_file);
-	kobject_put(&dev->kobj);
 
 	return 0;
 }

--
2.13.3

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#5 lore raw

PATCH 4/4 RDMA/mlx5: Fix existence check for extended address vector

In reply to a message not in the archive

From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/[email protected]>

The extended address vector is the highest bit in be32 variable, but it was compared with the lowest. This patch fixes the endianness of that check and removes already declared define.

---
 drivers/infiniband/hw/mlx5/odp.c | 2 +-
 include/linux/mlx5/qp.h          | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)
drivers/infiniband/hw/mlx5/odp.c +1 -1
index ae0746754008..3d701c7a4c91 100644
@@ -939,7 +939,7 @@ static int mlx5_ib_mr_initiator_pfault_handler(
 
 	if (qp->ibqp.qp_type != IB_QPT_RC) {
 		av = *wqe;
-		if (av->dqp_dct & be32_to_cpu(MLX5_WQE_AV_EXT))
+		if (av->dqp_dct & cpu_to_be32(MLX5_EXTENDED_UD_AV))
 			*wqe += sizeof(struct mlx5_av);
 		else
 			*wqe += sizeof(struct mlx5_base_av);
include/linux/mlx5/qp.h +0 -1
index 6f41270d80c0..f378dc0e7eaf 100644
@@ -212,7 +212,6 @@ struct mlx5_wqe_ctrl_seg {
 #define MLX5_WQE_CTRL_OPCODE_MASK 0xff
 #define MLX5_WQE_CTRL_WQE_INDEX_MASK 0x00ffff00
 #define MLX5_WQE_CTRL_WQE_INDEX_SHIFT 8
-#define MLX5_WQE_AV_EXT 0x80000000
 
 enum {
 	MLX5_ETH_WQE_L3_INNER_CSUM      = 1 << 4,

--
2.13.3

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#6 lore raw
In reply to a message not in the archive
Quoted 33 lines · Leon Romanovsky

Changelog:
v0 -> v1:
* Added Reviewed-by tags
* Moved 10 patches to -next

Thanks
----------------------------------------------------------------

The following changes since commit
5dc78ad1904db597bdb4427f3ead437aae86f54c:

IB/ipoib: Notify on modify QP failure only when relevant (2017-07-
23 10:52:00 +0300)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/leon/linux-rdma.git
tags/rdma-rc-2017-08-01

for you to fetch changes up to
0626c5a5dec2e601f06a2c03b295fb7d7288e29c:

RDMA/mlx5: Fix existence check for extended address vector (2017-
07-31 20:43:06 +0300)

----------------------------------------------------------------
RDMA fixes for 4.13

This patchset contains four patches:
* Two kernel panic fixes from Yishai and Parav.
* The bugfix to mlx5 wrong usage of big-endian variable.
* Preventing leak of reserved field.

Quoted 7 lines

----------------------------------------------------------------
Leon Romanovsky (2):
RDMA/uverbs: Prevent leak of reserved field RDMA/mlx5: Fix existence check for extended address vector

Parav Pandit (1):
IB/core: Fix race condition in resolving IP to MAC

This patch, in particular, was very similar in description to another patch I already took for this -rc cycle. Both of these patches ended up using ordered workqueues to resolve the problem. Finding two different workqueues that needed to be made ordered in the same -rc cycle makes me wonder if we might not have some other issues lurking in the subsystem in regards to workqueues...

Quoted 11 lines

Yishai Hadas (1):
IB/uverbs: Fix device cleanup

 drivers/infiniband/core/addr.c        | 62
+++++++++++++++++++++++++++--------
 drivers/infiniband/core/uverbs_cmd.c  |  2 +-
 drivers/infiniband/core/uverbs_main.c |  3 +-
 drivers/infiniband/hw/mlx5/odp.c      |  2 +-
 include/linux/mlx5/qp.h               |  1 -
 5 files changed, 51 insertions(+), 19 deletions(-)

I didn't use a pull (mainly because I was going through patchworks and saw the patches and took them from there before I saw the cover letter here with the pull tag...that and I'm not used to the pull request model so hunting through patchworks for the relevant patches is second nature and pull requests aren't). I'll try to keep the pull option in mind next time. In any case, thanks, series applied.

Signature · 8 lines
Doug Ledford <[email protected]>
    GPG KeyID: B826A3330E572FDD
    Key fingerprint = AE6B 1BDA 122B 23B4 265B  1274 B826 A333 0E57 2FDD

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): [email protected]

#8 lore raw
Quoted 42 lines · Doug Ledford
Quoted 33 lines · Leon Romanovsky

Changelog:
v0 -> v1:
* Added Reviewed-by tags
* Moved 10 patches to -next

Thanks
----------------------------------------------------------------

The following changes since commit
5dc78ad1904db597bdb4427f3ead437aae86f54c:

IB/ipoib: Notify on modify QP failure only when relevant (2017-07-
23 10:52:00 +0300)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/leon/linux-rdma.git
tags/rdma-rc-2017-08-01

for you to fetch changes up to
0626c5a5dec2e601f06a2c03b295fb7d7288e29c:

RDMA/mlx5: Fix existence check for extended address vector (2017-
07-31 20:43:06 +0300)

----------------------------------------------------------------
RDMA fixes for 4.13

This patchset contains four patches:
* Two kernel panic fixes from Yishai and Parav.
* The bugfix to mlx5 wrong usage of big-endian variable.
* Preventing leak of reserved field.

Quoted 7 lines

----------------------------------------------------------------
Leon Romanovsky (2):
RDMA/uverbs: Prevent leak of reserved field RDMA/mlx5: Fix existence check for extended address vector

Parav Pandit (1):
IB/core: Fix race condition in resolving IP to MAC

Quoted 6 lines

This patch, in particular, was very similar in description to another patch I already took for this -rc cycle. Both of these patches ended up using ordered workqueues to resolve the problem. Finding two different workqueues that needed to be made ordered in the same -rc cycle makes me wonder if we might not have some other issues lurking in the subsystem in regards to workqueues...

I hope no, we don't have many workqueues (except hfi1).

➜ linux-rdma git:(topic/rdma-uapi-export) git grep 'alloc_workqueue(\|create_workqueue(' drivers/infiniband

drivers/infiniband/core/addr.c: addr_wq = alloc_workqueue("ib_addr", WQ_MEM_RECLAIM, 0);
drivers/infiniband/core/cm.c:   cm.wq = create_workqueue("ib_cm");
drivers/infiniband/core/device.c:       ib_wq = alloc_workqueue("infiniband", 0, 0);
drivers/infiniband/core/device.c:       ib_comp_wq = alloc_workqueue("ib-comp-wq",
drivers/infiniband/hw/hfi1/init.c:                              alloc_workqueue(
drivers/infiniband/hw/usnic/usnic_uiom.c:       usnic_uiom_wq = create_workqueue(drv_name);
drivers/infiniband/ulp/iser/iscsi_iser.c:       release_wq = alloc_workqueue("release workqueue", 0, 0);
drivers/infiniband/ulp/isert/ib_isert.c:        isert_comp_wq = alloc_workqueue("isert_comp_wq",
drivers/infiniband/ulp/isert/ib_isert.c:        isert_release_wq = alloc_workqueue("isert_release_wq", WQ_UNBOUND,

drivers/infiniband/ulp/srp/ib_srp.c: srp_remove_wq = create_workqueue("srp_remove");

Quoted 25 lines
Quoted 5 lines

Yishai Hadas (1):
IB/uverbs: Fix device cleanup

Quoted 7 lines
 drivers/infiniband/core/addr.c        | 62
+++++++++++++++++++++++++++--------
 drivers/infiniband/core/uverbs_cmd.c  |  2 +-
 drivers/infiniband/core/uverbs_main.c |  3 +-
 drivers/infiniband/hw/mlx5/odp.c      |  2 +-
 include/linux/mlx5/qp.h               |  1 -
 5 files changed, 51 insertions(+), 19 deletions(-)

I didn't use a pull (mainly because I was going through patchworks and saw the patches and took them from there before I saw the cover letter here with the pull tag...that and I'm not used to the pull request model so hunting through patchworks for the relevant patches is second nature and pull requests aren't). I'll try to keep the pull option in mind next time. In any case, thanks, series applied.

--
Doug Ledford <[email protected]>

    GPG KeyID: B826A3330E572FDD
    Key fingerprint = AE6B 1BDA 122B 23B4 265B  1274 B826 A333 0E57 2FDD