Commit 011af61b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '9p-for-7.0-rc1' of https://github.com/martinetd/linux

Pull 9p updates from Dominique Martinet:

 - 9p/xen racy double-free fix

 - track 9p RPC waiting time as IO

* tag '9p-for-7.0-rc1' of https://github.com/martinetd/linux:
  9p/xen: protect xen_9pfs_front_free against concurrent calls
  9p: Track 9P RPC waiting time as IO
  wait: Introduce io_wait_event_killable()
parents c4f414be ce8ded2e
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -937,6 +937,21 @@ extern int do_wait_intr_irq(wait_queue_head_t *, wait_queue_entry_t *);
	__ret;									\
})

#define __io_wait_event_killable(wq, condition)					\
	___wait_event(wq, condition, TASK_KILLABLE, 0, 0, io_schedule())

/*
 * wait_event_killable() - link wait_event_killable but with io_schedule()
 */
#define io_wait_event_killable(wq_head, condition)				\
({										\
	int __ret = 0;								\
	might_sleep();								\
	if (!(condition))							\
		__ret = __io_wait_event_killable(wq_head, condition);		\
	__ret;									\
})

#define __wait_event_state(wq, condition, state)				\
	___wait_event(wq, condition, state, 0, 0, schedule())

+2 −2
Original line number Diff line number Diff line
@@ -590,7 +590,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
	}
again:
	/* Wait for the response */
	err = wait_event_killable(req->wq,
	err = io_wait_event_killable(req->wq,
				     READ_ONCE(req->status) >= REQ_STATUS_RCVD);

	/* Make sure our req is coherent with regard to updates in other
+7 −7
Original line number Diff line number Diff line
@@ -284,7 +284,7 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
		if (err == -ENOSPC) {
			chan->ring_bufs_avail = 0;
			spin_unlock_irqrestore(&chan->lock, flags);
			err = wait_event_killable(*chan->vc_wq,
			err = io_wait_event_killable(*chan->vc_wq,
						     chan->ring_bufs_avail);
			if (err  == -ERESTARTSYS)
				return err;
@@ -325,7 +325,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
		 * Other zc request to finish here
		 */
		if (atomic_read(&vp_pinned) >= chan->p9_max_pages) {
			err = wait_event_killable(vp_wq,
			err = io_wait_event_killable(vp_wq,
			      (atomic_read(&vp_pinned) < chan->p9_max_pages));
			if (err == -ERESTARTSYS)
				return err;
@@ -512,7 +512,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
		if (err == -ENOSPC) {
			chan->ring_bufs_avail = 0;
			spin_unlock_irqrestore(&chan->lock, flags);
			err = wait_event_killable(*chan->vc_wq,
			err = io_wait_event_killable(*chan->vc_wq,
						     chan->ring_bufs_avail);
			if (err  == -ERESTARTSYS)
				goto err_out;
@@ -531,7 +531,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
	spin_unlock_irqrestore(&chan->lock, flags);
	kicked = 1;
	p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n");
	err = wait_event_killable(req->wq,
	err = io_wait_event_killable(req->wq,
				     READ_ONCE(req->status) >= REQ_STATUS_RCVD);
	// RERROR needs reply (== error string) in static data
	if (READ_ONCE(req->status) == REQ_STATUS_RCVD &&
+46 −43
Original line number Diff line number Diff line
@@ -136,7 +136,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
	ring = &priv->rings[num];

again:
	while (wait_event_killable(ring->wq,
	while (io_wait_event_killable(ring->wq,
				      p9_xen_write_todo(ring, size)) != 0)
		;

@@ -277,10 +277,7 @@ static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
{
	int i, j;

	write_lock(&xen_9pfs_lock);
	list_del(&priv->list);
	write_unlock(&xen_9pfs_lock);

	if (priv->rings) {
		for (i = 0; i < XEN_9PFS_NUM_RINGS; i++) {
			struct xen_9pfs_dataring *ring = &priv->rings[i];

@@ -307,15 +304,25 @@ static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
			free_page((unsigned long)priv->rings[i].intf);
		}
		kfree(priv->rings);
	}
	kfree(priv->tag);
	kfree(priv);
}

static void xen_9pfs_front_remove(struct xenbus_device *dev)
{
	struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev);
	struct xen_9pfs_front_priv *priv;

	write_lock(&xen_9pfs_lock);
	priv = dev_get_drvdata(&dev->dev);
	if (priv == NULL) {
		write_unlock(&xen_9pfs_lock);
		return;
	}
	dev_set_drvdata(&dev->dev, NULL);
	list_del(&priv->list);
	write_unlock(&xen_9pfs_lock);

	xen_9pfs_front_free(priv);
}

@@ -382,7 +389,7 @@ static int xen_9pfs_front_init(struct xenbus_device *dev)
{
	int ret, i;
	struct xenbus_transaction xbt;
	struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev);
	struct xen_9pfs_front_priv *priv;
	char *versions, *v;
	unsigned int max_rings, max_ring_order, len = 0;

@@ -410,6 +417,10 @@ static int xen_9pfs_front_init(struct xenbus_device *dev)
	if (p9_xen_trans.maxsize > XEN_FLEX_RING_SIZE(max_ring_order))
		p9_xen_trans.maxsize = XEN_FLEX_RING_SIZE(max_ring_order) / 2;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;
	priv->dev = dev;
	priv->rings = kcalloc(XEN_9PFS_NUM_RINGS, sizeof(*priv->rings),
			      GFP_KERNEL);
	if (!priv->rings) {
@@ -468,6 +479,11 @@ static int xen_9pfs_front_init(struct xenbus_device *dev)
		goto error;
	}

	write_lock(&xen_9pfs_lock);
	dev_set_drvdata(&dev->dev, priv);
	list_add_tail(&priv->list, &xen_9pfs_devs);
	write_unlock(&xen_9pfs_lock);

	xenbus_switch_state(dev, XenbusStateInitialised);
	return 0;

@@ -482,19 +498,6 @@ static int xen_9pfs_front_init(struct xenbus_device *dev)
static int xen_9pfs_front_probe(struct xenbus_device *dev,
				const struct xenbus_device_id *id)
{
	struct xen_9pfs_front_priv *priv = NULL;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->dev = dev;
	dev_set_drvdata(&dev->dev, priv);

	write_lock(&xen_9pfs_lock);
	list_add_tail(&priv->list, &xen_9pfs_devs);
	write_unlock(&xen_9pfs_lock);

	return 0;
}