Skip to content

Commit 3fa84bf

Browse files
committed
Merge tag 'ceph-for-5.7-rc2' of git://github.com/ceph/ceph-client
Pull ceph fixes from Ilya Dryomov: - a set of patches for a deadlock on "rbd map" error path - a fix for invalid pointer dereference and uninitialized variable use on asynchronous create and unlink error paths. * tag 'ceph-for-5.7-rc2' of git://github.com/ceph/ceph-client: ceph: fix potential bad pointer deref in async dirops cb's rbd: don't mess with a page vector in rbd_notify_op_lock() rbd: don't test rbd_dev->opts in rbd_dev_image_release() rbd: call rbd_dev_unprobe() after unwatching and flushing notifies rbd: avoid a deadlock on header_rwsem when flushing notifies
2 parents 4ede125 + 2a575f1 commit 3fa84bf

File tree

4 files changed

+24
-19
lines changed

4 files changed

+24
-19
lines changed

drivers/block/rbd.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3754,11 +3754,7 @@ static int __rbd_notify_op_lock(struct rbd_device *rbd_dev,
37543754
static void rbd_notify_op_lock(struct rbd_device *rbd_dev,
37553755
enum rbd_notify_op notify_op)
37563756
{
3757-
struct page **reply_pages;
3758-
size_t reply_len;
3759-
3760-
__rbd_notify_op_lock(rbd_dev, notify_op, &reply_pages, &reply_len);
3761-
ceph_release_page_vector(reply_pages, calc_pages_for(0, reply_len));
3757+
__rbd_notify_op_lock(rbd_dev, notify_op, NULL, NULL);
37623758
}
37633759

37643760
static void rbd_notify_acquired_lock(struct work_struct *work)
@@ -4527,6 +4523,10 @@ static void cancel_tasks_sync(struct rbd_device *rbd_dev)
45274523
cancel_work_sync(&rbd_dev->unlock_work);
45284524
}
45294525

4526+
/*
4527+
* header_rwsem must not be held to avoid a deadlock with
4528+
* rbd_dev_refresh() when flushing notifies.
4529+
*/
45304530
static void rbd_unregister_watch(struct rbd_device *rbd_dev)
45314531
{
45324532
cancel_tasks_sync(rbd_dev);
@@ -6894,9 +6894,10 @@ static void rbd_print_dne(struct rbd_device *rbd_dev, bool is_snap)
68946894

68956895
static void rbd_dev_image_release(struct rbd_device *rbd_dev)
68966896
{
6897-
rbd_dev_unprobe(rbd_dev);
6898-
if (rbd_dev->opts)
6897+
if (!rbd_is_ro(rbd_dev))
68996898
rbd_unregister_watch(rbd_dev);
6899+
6900+
rbd_dev_unprobe(rbd_dev);
69006901
rbd_dev->image_format = 0;
69016902
kfree(rbd_dev->spec->image_id);
69026903
rbd_dev->spec->image_id = NULL;
@@ -6907,6 +6908,9 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev)
69076908
* device. If this image is the one being mapped (i.e., not a
69086909
* parent), initiate a watch on its header object before using that
69096910
* object to get detailed information about the rbd image.
6911+
*
6912+
* On success, returns with header_rwsem held for write if called
6913+
* with @depth == 0.
69106914
*/
69116915
static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
69126916
{
@@ -6936,11 +6940,14 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
69366940
}
69376941
}
69386942

6943+
if (!depth)
6944+
down_write(&rbd_dev->header_rwsem);
6945+
69396946
ret = rbd_dev_header_info(rbd_dev);
69406947
if (ret) {
69416948
if (ret == -ENOENT && !need_watch)
69426949
rbd_print_dne(rbd_dev, false);
6943-
goto err_out_watch;
6950+
goto err_out_probe;
69446951
}
69456952

69466953
/*
@@ -6985,10 +6992,11 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
69856992
return 0;
69866993

69876994
err_out_probe:
6988-
rbd_dev_unprobe(rbd_dev);
6989-
err_out_watch:
6995+
if (!depth)
6996+
up_write(&rbd_dev->header_rwsem);
69906997
if (need_watch)
69916998
rbd_unregister_watch(rbd_dev);
6999+
rbd_dev_unprobe(rbd_dev);
69927000
err_out_format:
69937001
rbd_dev->image_format = 0;
69947002
kfree(rbd_dev->spec->image_id);
@@ -7050,12 +7058,9 @@ static ssize_t do_rbd_add(struct bus_type *bus,
70507058
goto err_out_rbd_dev;
70517059
}
70527060

7053-
down_write(&rbd_dev->header_rwsem);
70547061
rc = rbd_dev_image_probe(rbd_dev, 0);
7055-
if (rc < 0) {
7056-
up_write(&rbd_dev->header_rwsem);
7062+
if (rc < 0)
70577063
goto err_out_rbd_dev;
7058-
}
70597064

70607065
if (rbd_dev->opts->alloc_size > rbd_dev->layout.object_size) {
70617066
rbd_warn(rbd_dev, "alloc_size adjusted to %u",

fs/ceph/dir.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,8 +1051,8 @@ static void ceph_async_unlink_cb(struct ceph_mds_client *mdsc,
10511051

10521052
/* If op failed, mark everyone involved for errors */
10531053
if (result) {
1054-
int pathlen;
1055-
u64 base;
1054+
int pathlen = 0;
1055+
u64 base = 0;
10561056
char *path = ceph_mdsc_build_path(req->r_dentry, &pathlen,
10571057
&base, 0);
10581058

fs/ceph/file.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,8 @@ static void ceph_async_create_cb(struct ceph_mds_client *mdsc,
527527

528528
if (result) {
529529
struct dentry *dentry = req->r_dentry;
530-
int pathlen;
531-
u64 base;
530+
int pathlen = 0;
531+
u64 base = 0;
532532
char *path = ceph_mdsc_build_path(req->r_dentry, &pathlen,
533533
&base, 0);
534534

fs/ceph/mds_client.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc);
521521

522522
static inline void ceph_mdsc_free_path(char *path, int len)
523523
{
524-
if (path)
524+
if (!IS_ERR_OR_NULL(path))
525525
__putname(path - (PATH_MAX - 1 - len));
526526
}
527527

0 commit comments

Comments
 (0)