Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+24 -19
+19 -14
drivers/block/rbd.c
··· 3754 3754 static void rbd_notify_op_lock(struct rbd_device *rbd_dev, 3755 3755 enum rbd_notify_op notify_op) 3756 3756 { 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); 3762 3758 } 3763 3759 3764 3760 static void rbd_notify_acquired_lock(struct work_struct *work) ··· 4523 4527 cancel_work_sync(&rbd_dev->unlock_work); 4524 4528 } 4525 4529 4530 + /* 4531 + * header_rwsem must not be held to avoid a deadlock with 4532 + * rbd_dev_refresh() when flushing notifies. 4533 + */ 4526 4534 static void rbd_unregister_watch(struct rbd_device *rbd_dev) 4527 4535 { 4528 4536 cancel_tasks_sync(rbd_dev); ··· 6894 6894 6895 6895 static void rbd_dev_image_release(struct rbd_device *rbd_dev) 6896 6896 { 6897 - rbd_dev_unprobe(rbd_dev); 6898 - if (rbd_dev->opts) 6897 + if (!rbd_is_ro(rbd_dev)) 6899 6898 rbd_unregister_watch(rbd_dev); 6899 + 6900 + rbd_dev_unprobe(rbd_dev); 6900 6901 rbd_dev->image_format = 0; 6901 6902 kfree(rbd_dev->spec->image_id); 6902 6903 rbd_dev->spec->image_id = NULL; ··· 6908 6907 * device. If this image is the one being mapped (i.e., not a 6909 6908 * parent), initiate a watch on its header object before using that 6910 6909 * object to get detailed information about the rbd image. 6910 + * 6911 + * On success, returns with header_rwsem held for write if called 6912 + * with @depth == 0. 6911 6913 */ 6912 6914 static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth) 6913 6915 { ··· 6940 6936 } 6941 6937 } 6942 6938 6939 + if (!depth) 6940 + down_write(&rbd_dev->header_rwsem); 6941 + 6943 6942 ret = rbd_dev_header_info(rbd_dev); 6944 6943 if (ret) { 6945 6944 if (ret == -ENOENT && !need_watch) 6946 6945 rbd_print_dne(rbd_dev, false); 6947 - goto err_out_watch; 6946 + goto err_out_probe; 6948 6947 } 6949 6948 6950 6949 /* ··· 6992 6985 return 0; 6993 6986 6994 6987 err_out_probe: 6995 - rbd_dev_unprobe(rbd_dev); 6996 - err_out_watch: 6988 + if (!depth) 6989 + up_write(&rbd_dev->header_rwsem); 6997 6990 if (need_watch) 6998 6991 rbd_unregister_watch(rbd_dev); 6992 + rbd_dev_unprobe(rbd_dev); 6999 6993 err_out_format: 7000 6994 rbd_dev->image_format = 0; 7001 6995 kfree(rbd_dev->spec->image_id); ··· 7058 7050 goto err_out_rbd_dev; 7059 7051 } 7060 7052 7061 - down_write(&rbd_dev->header_rwsem); 7062 7053 rc = rbd_dev_image_probe(rbd_dev, 0); 7063 - if (rc < 0) { 7064 - up_write(&rbd_dev->header_rwsem); 7054 + if (rc < 0) 7065 7055 goto err_out_rbd_dev; 7066 - } 7067 7056 7068 7057 if (rbd_dev->opts->alloc_size > rbd_dev->layout.object_size) { 7069 7058 rbd_warn(rbd_dev, "alloc_size adjusted to %u",
+2 -2
fs/ceph/dir.c
··· 1051 1051 1052 1052 /* If op failed, mark everyone involved for errors */ 1053 1053 if (result) { 1054 - int pathlen; 1055 - u64 base; 1054 + int pathlen = 0; 1055 + u64 base = 0; 1056 1056 char *path = ceph_mdsc_build_path(req->r_dentry, &pathlen, 1057 1057 &base, 0); 1058 1058
+2 -2
fs/ceph/file.c
··· 527 527 528 528 if (result) { 529 529 struct dentry *dentry = req->r_dentry; 530 - int pathlen; 531 - u64 base; 530 + int pathlen = 0; 531 + u64 base = 0; 532 532 char *path = ceph_mdsc_build_path(req->r_dentry, &pathlen, 533 533 &base, 0); 534 534
+1 -1
fs/ceph/mds_client.h
··· 521 521 522 522 static inline void ceph_mdsc_free_path(char *path, int len) 523 523 { 524 - if (path) 524 + if (!IS_ERR_OR_NULL(path)) 525 525 __putname(path - (PATH_MAX - 1 - len)); 526 526 } 527 527