Skip to content

Commit 952c48b

Browse files
committed
rbd: call rbd_dev_unprobe() after unwatching and flushing notifies
rbd_dev_unprobe() is supposed to undo most of rbd_dev_image_probe(), including rbd_dev_header_info(), which means that rbd_dev_header_info() isn't supposed to be called after rbd_dev_unprobe(). However, rbd_dev_image_release() calls rbd_dev_unprobe() before rbd_unregister_watch(). This is racy because a header update notify can sneak in: "rbd unmap" thread ceph-watch-notify worker rbd_dev_image_release() rbd_dev_unprobe() free and zero out header rbd_watch_cb() rbd_dev_refresh() rbd_dev_header_info() read in header The same goes for "rbd map" because rbd_dev_image_probe() calls rbd_dev_unprobe() on errors. In both cases this results in a memory leak. Fixes: fd22aef ("rbd: move rbd_unregister_watch() call into rbd_dev_image_release()") Signed-off-by: Ilya Dryomov <[email protected]> Reviewed-by: Jason Dillaman <[email protected]>
1 parent 0e4e1de commit 952c48b

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

drivers/block/rbd.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6898,9 +6898,10 @@ static void rbd_print_dne(struct rbd_device *rbd_dev, bool is_snap)
68986898

68996899
static void rbd_dev_image_release(struct rbd_device *rbd_dev)
69006900
{
6901-
rbd_dev_unprobe(rbd_dev);
69026901
if (rbd_dev->opts)
69036902
rbd_unregister_watch(rbd_dev);
6903+
6904+
rbd_dev_unprobe(rbd_dev);
69046905
rbd_dev->image_format = 0;
69056906
kfree(rbd_dev->spec->image_id);
69066907
rbd_dev->spec->image_id = NULL;
@@ -6950,7 +6951,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
69506951
if (ret) {
69516952
if (ret == -ENOENT && !need_watch)
69526953
rbd_print_dne(rbd_dev, false);
6953-
goto err_out_watch;
6954+
goto err_out_probe;
69546955
}
69556956

69566957
/*
@@ -6995,12 +6996,11 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
69956996
return 0;
69966997

69976998
err_out_probe:
6998-
rbd_dev_unprobe(rbd_dev);
6999-
err_out_watch:
70006999
if (!depth)
70017000
up_write(&rbd_dev->header_rwsem);
70027001
if (need_watch)
70037002
rbd_unregister_watch(rbd_dev);
7003+
rbd_dev_unprobe(rbd_dev);
70047004
err_out_format:
70057005
rbd_dev->image_format = 0;
70067006
kfree(rbd_dev->spec->image_id);

0 commit comments

Comments
 (0)