mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:24:47 +01:00
- 9p/xen racy double-free fix
- track 9p RPC waiting time as IO -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE/IPbcYBuWt0zoYhOq06b7GqY5nAFAmmRjJcACgkQq06b7GqY 5nCUMA//WDifZs5ug0Zf/6pKJ3PIr/NmQf0XXPmn0YlR53Uz11X9CoXV0ZjQJsz6 Dsp5DMgHpTBizBb+iS/0wTuNqB1Imx+r5opEi/+vgVdl53XxcurmmqfJBULLdOhj a02PKH3VBzpTel93mYpvJvxil6dpN/fqfpKm2dGOcz8U6d5KFYpjkMZoYBVQWhQx 4Afyp71XHbuHamg68sw4UOmCTeWNGOxYPDrL/pVCl3usKC+6zX4vTADtS6ckjYtb 7s45hJmYuRQ8IyZnXEJeUefm3OoxwSxXUERP3lotMEiImMLE6g/IK5hiQaLYkPwb aEyNGP2ReISXUdXy0jJA3ILUcYs1+fbq89Rs93LC/+EzjQm5b23yfsEB5DyIAZnw giOXAcBjm/3cC7czw8Rw6Aa6dGjjWDg//5hOzDbvdVH54j3MnKzLiwQylgsszBKX dY58SMDGPdn/Bcf+TDyu5Ahr4GDARX0vVSLFot3xEULt9x90Sdd89GQffujIKx3v bIcGj0Ql/BRMnPVB5gZD2c8K+HeIIYrv/l4tlVLpOeKIepBw0yNnFMBDp+yQxbSf gkJxajkcjd9hEjaK1U4znJeX3cQzhgj0cpPRJq7b9SSC1+4c6PThL8PSDrmzCPJV DGBSFMHQR6g+zFy4xpbc5ErBReNZVXN1FqvCGo6TM0fTPvTNcV0= =ew5K -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
011af61b9f
4 changed files with 67 additions and 49 deletions
|
|
@ -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())
|
||||
|
||||
|
|
|
|||
|
|
@ -590,8 +590,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
|
|||
}
|
||||
again:
|
||||
/* Wait for the response */
|
||||
err = wait_event_killable(req->wq,
|
||||
READ_ONCE(req->status) >= REQ_STATUS_RCVD);
|
||||
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
|
||||
* threads - echoes to wmb() in the callback
|
||||
|
|
|
|||
|
|
@ -284,8 +284,8 @@ req_retry:
|
|||
if (err == -ENOSPC) {
|
||||
chan->ring_bufs_avail = 0;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
err = wait_event_killable(*chan->vc_wq,
|
||||
chan->ring_bufs_avail);
|
||||
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,8 +512,8 @@ req_retry_pinned:
|
|||
if (err == -ENOSPC) {
|
||||
chan->ring_bufs_avail = 0;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
err = wait_event_killable(*chan->vc_wq,
|
||||
chan->ring_bufs_avail);
|
||||
err = io_wait_event_killable(*chan->vc_wq,
|
||||
chan->ring_bufs_avail);
|
||||
if (err == -ERESTARTSYS)
|
||||
goto err_out;
|
||||
|
||||
|
|
@ -531,8 +531,8 @@ req_retry_pinned:
|
|||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
kicked = 1;
|
||||
p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n");
|
||||
err = wait_event_killable(req->wq,
|
||||
READ_ONCE(req->status) >= REQ_STATUS_RCVD);
|
||||
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 &&
|
||||
unlikely(req->rc.sdata[4] == P9_RERROR))
|
||||
|
|
|
|||
|
|
@ -136,8 +136,8 @@ 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,
|
||||
p9_xen_write_todo(ring, size)) != 0)
|
||||
while (io_wait_event_killable(ring->wq,
|
||||
p9_xen_write_todo(ring, size)) != 0)
|
||||
;
|
||||
|
||||
spin_lock_irqsave(&ring->lock, flags);
|
||||
|
|
@ -277,45 +277,52 @@ 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];
|
||||
|
||||
for (i = 0; i < XEN_9PFS_NUM_RINGS; i++) {
|
||||
struct xen_9pfs_dataring *ring = &priv->rings[i];
|
||||
cancel_work_sync(&ring->work);
|
||||
|
||||
cancel_work_sync(&ring->work);
|
||||
if (!priv->rings[i].intf)
|
||||
break;
|
||||
if (priv->rings[i].irq > 0)
|
||||
unbind_from_irqhandler(priv->rings[i].irq, ring);
|
||||
if (priv->rings[i].data.in) {
|
||||
for (j = 0;
|
||||
j < (1 << priv->rings[i].intf->ring_order);
|
||||
j++) {
|
||||
grant_ref_t ref;
|
||||
|
||||
if (!priv->rings[i].intf)
|
||||
break;
|
||||
if (priv->rings[i].irq > 0)
|
||||
unbind_from_irqhandler(priv->rings[i].irq, ring);
|
||||
if (priv->rings[i].data.in) {
|
||||
for (j = 0;
|
||||
j < (1 << priv->rings[i].intf->ring_order);
|
||||
j++) {
|
||||
grant_ref_t ref;
|
||||
|
||||
ref = priv->rings[i].intf->ref[j];
|
||||
gnttab_end_foreign_access(ref, NULL);
|
||||
}
|
||||
free_pages_exact(priv->rings[i].data.in,
|
||||
ref = priv->rings[i].intf->ref[j];
|
||||
gnttab_end_foreign_access(ref, NULL);
|
||||
}
|
||||
free_pages_exact(priv->rings[i].data.in,
|
||||
1UL << (priv->rings[i].intf->ring_order +
|
||||
XEN_PAGE_SHIFT));
|
||||
}
|
||||
gnttab_end_foreign_access(priv->rings[i].ref, NULL);
|
||||
free_page((unsigned long)priv->rings[i].intf);
|
||||
}
|
||||
gnttab_end_foreign_access(priv->rings[i].ref, NULL);
|
||||
free_page((unsigned long)priv->rings[i].intf);
|
||||
kfree(priv->rings);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue