Skip to content

Commit 011af61

Browse files
committed
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()
2 parents c4f414b + ce8ded2 commit 011af61

4 files changed

Lines changed: 70 additions & 52 deletions

File tree

include/linux/wait.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,21 @@ extern int do_wait_intr_irq(wait_queue_head_t *, wait_queue_entry_t *);
937937
__ret; \
938938
})
939939

940+
#define __io_wait_event_killable(wq, condition) \
941+
___wait_event(wq, condition, TASK_KILLABLE, 0, 0, io_schedule())
942+
943+
/*
944+
* wait_event_killable() - link wait_event_killable but with io_schedule()
945+
*/
946+
#define io_wait_event_killable(wq_head, condition) \
947+
({ \
948+
int __ret = 0; \
949+
might_sleep(); \
950+
if (!(condition)) \
951+
__ret = __io_wait_event_killable(wq_head, condition); \
952+
__ret; \
953+
})
954+
940955
#define __wait_event_state(wq, condition, state) \
941956
___wait_event(wq, condition, state, 0, 0, schedule())
942957

net/9p/client.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -590,8 +590,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
590590
}
591591
again:
592592
/* Wait for the response */
593-
err = wait_event_killable(req->wq,
594-
READ_ONCE(req->status) >= REQ_STATUS_RCVD);
593+
err = io_wait_event_killable(req->wq,
594+
READ_ONCE(req->status) >= REQ_STATUS_RCVD);
595595

596596
/* Make sure our req is coherent with regard to updates in other
597597
* threads - echoes to wmb() in the callback

net/9p/trans_virtio.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,8 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
284284
if (err == -ENOSPC) {
285285
chan->ring_bufs_avail = 0;
286286
spin_unlock_irqrestore(&chan->lock, flags);
287-
err = wait_event_killable(*chan->vc_wq,
288-
chan->ring_bufs_avail);
287+
err = io_wait_event_killable(*chan->vc_wq,
288+
chan->ring_bufs_avail);
289289
if (err == -ERESTARTSYS)
290290
return err;
291291

@@ -325,7 +325,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
325325
* Other zc request to finish here
326326
*/
327327
if (atomic_read(&vp_pinned) >= chan->p9_max_pages) {
328-
err = wait_event_killable(vp_wq,
328+
err = io_wait_event_killable(vp_wq,
329329
(atomic_read(&vp_pinned) < chan->p9_max_pages));
330330
if (err == -ERESTARTSYS)
331331
return err;
@@ -512,8 +512,8 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
512512
if (err == -ENOSPC) {
513513
chan->ring_bufs_avail = 0;
514514
spin_unlock_irqrestore(&chan->lock, flags);
515-
err = wait_event_killable(*chan->vc_wq,
516-
chan->ring_bufs_avail);
515+
err = io_wait_event_killable(*chan->vc_wq,
516+
chan->ring_bufs_avail);
517517
if (err == -ERESTARTSYS)
518518
goto err_out;
519519

@@ -531,8 +531,8 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
531531
spin_unlock_irqrestore(&chan->lock, flags);
532532
kicked = 1;
533533
p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n");
534-
err = wait_event_killable(req->wq,
535-
READ_ONCE(req->status) >= REQ_STATUS_RCVD);
534+
err = io_wait_event_killable(req->wq,
535+
READ_ONCE(req->status) >= REQ_STATUS_RCVD);
536536
// RERROR needs reply (== error string) in static data
537537
if (READ_ONCE(req->status) == REQ_STATUS_RCVD &&
538538
unlikely(req->rc.sdata[4] == P9_RERROR))

net/9p/trans_xen.c

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
136136
ring = &priv->rings[num];
137137

138138
again:
139-
while (wait_event_killable(ring->wq,
140-
p9_xen_write_todo(ring, size)) != 0)
139+
while (io_wait_event_killable(ring->wq,
140+
p9_xen_write_todo(ring, size)) != 0)
141141
;
142142

143143
spin_lock_irqsave(&ring->lock, flags);
@@ -277,45 +277,52 @@ static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
277277
{
278278
int i, j;
279279

280-
write_lock(&xen_9pfs_lock);
281-
list_del(&priv->list);
282-
write_unlock(&xen_9pfs_lock);
283-
284-
for (i = 0; i < XEN_9PFS_NUM_RINGS; i++) {
285-
struct xen_9pfs_dataring *ring = &priv->rings[i];
286-
287-
cancel_work_sync(&ring->work);
288-
289-
if (!priv->rings[i].intf)
290-
break;
291-
if (priv->rings[i].irq > 0)
292-
unbind_from_irqhandler(priv->rings[i].irq, ring);
293-
if (priv->rings[i].data.in) {
294-
for (j = 0;
295-
j < (1 << priv->rings[i].intf->ring_order);
296-
j++) {
297-
grant_ref_t ref;
298-
299-
ref = priv->rings[i].intf->ref[j];
300-
gnttab_end_foreign_access(ref, NULL);
301-
}
302-
free_pages_exact(priv->rings[i].data.in,
280+
if (priv->rings) {
281+
for (i = 0; i < XEN_9PFS_NUM_RINGS; i++) {
282+
struct xen_9pfs_dataring *ring = &priv->rings[i];
283+
284+
cancel_work_sync(&ring->work);
285+
286+
if (!priv->rings[i].intf)
287+
break;
288+
if (priv->rings[i].irq > 0)
289+
unbind_from_irqhandler(priv->rings[i].irq, ring);
290+
if (priv->rings[i].data.in) {
291+
for (j = 0;
292+
j < (1 << priv->rings[i].intf->ring_order);
293+
j++) {
294+
grant_ref_t ref;
295+
296+
ref = priv->rings[i].intf->ref[j];
297+
gnttab_end_foreign_access(ref, NULL);
298+
}
299+
free_pages_exact(priv->rings[i].data.in,
303300
1UL << (priv->rings[i].intf->ring_order +
304301
XEN_PAGE_SHIFT));
302+
}
303+
gnttab_end_foreign_access(priv->rings[i].ref, NULL);
304+
free_page((unsigned long)priv->rings[i].intf);
305305
}
306-
gnttab_end_foreign_access(priv->rings[i].ref, NULL);
307-
free_page((unsigned long)priv->rings[i].intf);
306+
kfree(priv->rings);
308307
}
309-
kfree(priv->rings);
310308
kfree(priv->tag);
311309
kfree(priv);
312310
}
313311

314312
static void xen_9pfs_front_remove(struct xenbus_device *dev)
315313
{
316-
struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev);
314+
struct xen_9pfs_front_priv *priv;
317315

316+
write_lock(&xen_9pfs_lock);
317+
priv = dev_get_drvdata(&dev->dev);
318+
if (priv == NULL) {
319+
write_unlock(&xen_9pfs_lock);
320+
return;
321+
}
318322
dev_set_drvdata(&dev->dev, NULL);
323+
list_del(&priv->list);
324+
write_unlock(&xen_9pfs_lock);
325+
319326
xen_9pfs_front_free(priv);
320327
}
321328

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

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

420+
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
421+
if (!priv)
422+
return -ENOMEM;
423+
priv->dev = dev;
413424
priv->rings = kcalloc(XEN_9PFS_NUM_RINGS, sizeof(*priv->rings),
414425
GFP_KERNEL);
415426
if (!priv->rings) {
@@ -468,6 +479,11 @@ static int xen_9pfs_front_init(struct xenbus_device *dev)
468479
goto error;
469480
}
470481

482+
write_lock(&xen_9pfs_lock);
483+
dev_set_drvdata(&dev->dev, priv);
484+
list_add_tail(&priv->list, &xen_9pfs_devs);
485+
write_unlock(&xen_9pfs_lock);
486+
471487
xenbus_switch_state(dev, XenbusStateInitialised);
472488
return 0;
473489

@@ -482,19 +498,6 @@ static int xen_9pfs_front_init(struct xenbus_device *dev)
482498
static int xen_9pfs_front_probe(struct xenbus_device *dev,
483499
const struct xenbus_device_id *id)
484500
{
485-
struct xen_9pfs_front_priv *priv = NULL;
486-
487-
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
488-
if (!priv)
489-
return -ENOMEM;
490-
491-
priv->dev = dev;
492-
dev_set_drvdata(&dev->dev, priv);
493-
494-
write_lock(&xen_9pfs_lock);
495-
list_add_tail(&priv->list, &xen_9pfs_devs);
496-
write_unlock(&xen_9pfs_lock);
497-
498501
return 0;
499502
}
500503

0 commit comments

Comments
 (0)