Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fd60ae40 authored by Jack Morgenstein's avatar Jack Morgenstein Committed by Roland Dreier
Browse files

IB/uverbs: Avoid a crash on device hot remove



Wait until all users have closed their device context before allowing
device unregistration to complete.  This prevents a crash caused by
referring to stale data structures.

A better solution would be to have a way to revoke contexts rather
than waiting for userspace to close the context, but that's a much
bigger change that will have to wait.  For now let's at least avoid
the crash.

Signed-off-by: default avatarJack Morgenstein <jackm@mellanox.co.il>
Signed-off-by: default avatarMichael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 8ddc7c53
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -42,6 +42,7 @@
#include <linux/kref.h>
#include <linux/kref.h>
#include <linux/idr.h>
#include <linux/idr.h>
#include <linux/mutex.h>
#include <linux/mutex.h>
#include <linux/completion.h>


#include <rdma/ib_verbs.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_user_verbs.h>
#include <rdma/ib_user_verbs.h>
@@ -69,6 +70,7 @@


struct ib_uverbs_device {
struct ib_uverbs_device {
	struct kref				ref;
	struct kref				ref;
	struct completion			comp;
	int					devnum;
	int					devnum;
	struct cdev			       *dev;
	struct cdev			       *dev;
	struct class_device		       *class_dev;
	struct class_device		       *class_dev;
+7 −1
Original line number Original line Diff line number Diff line
@@ -122,7 +122,7 @@ static void ib_uverbs_release_dev(struct kref *ref)
	struct ib_uverbs_device *dev =
	struct ib_uverbs_device *dev =
		container_of(ref, struct ib_uverbs_device, ref);
		container_of(ref, struct ib_uverbs_device, ref);


	kfree(dev);
	complete(&dev->comp);
}
}


void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
@@ -740,6 +740,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
		return;
		return;


	kref_init(&uverbs_dev->ref);
	kref_init(&uverbs_dev->ref);
	init_completion(&uverbs_dev->comp);


	spin_lock(&map_lock);
	spin_lock(&map_lock);
	uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
	uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -793,6 +794,8 @@ err_cdev:


err:
err:
	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
	wait_for_completion(&uverbs_dev->comp);
	kfree(uverbs_dev);
	return;
	return;
}
}


@@ -812,7 +815,10 @@ static void ib_uverbs_remove_one(struct ib_device *device)
	spin_unlock(&map_lock);
	spin_unlock(&map_lock);


	clear_bit(uverbs_dev->devnum, dev_map);
	clear_bit(uverbs_dev->devnum, dev_map);

	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
	wait_for_completion(&uverbs_dev->comp);
	kfree(uverbs_dev);
}
}


static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags,