aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2019-03-20 04:46:58 -0400
committerIlya Dryomov <idryomov@gmail.com>2019-03-20 11:27:40 -0400
commitbb229bbb3bf63d23128e851a1f3b85c083178fa1 (patch)
tree5b6b57fc2acdb4c09fd034e23c4930eb2ec2043a
parent16d80c54ad42c573a897ae7bcf5a9816be54e6fe (diff)
libceph: wait for latest osdmap in ceph_monc_blacklist_add()
Because map updates are distributed lazily, an OSD may not know about the new blacklist for quite some time after "osd blacklist add" command is completed. This makes it possible for a blacklisted but still alive client to overwrite a post-blacklist update, resulting in data corruption. Waiting for latest osdmap in ceph_monc_blacklist_add() and thus using the post-blacklist epoch for all post-blacklist requests ensures that all such requests "wait" for the blacklist to come into force on their respective OSDs. Cc: stable@vger.kernel.org Fixes: 6305a3b41515 ("libceph: support for blacklisting clients") Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Reviewed-by: Jason Dillaman <dillaman@redhat.com>
-rw-r--r--include/linux/ceph/libceph.h2
-rw-r--r--net/ceph/ceph_common.c18
-rw-r--r--net/ceph/mon_client.c9
3 files changed, 28 insertions, 1 deletions
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
index a420c07904bc..337d5049ff93 100644
--- a/include/linux/ceph/libceph.h
+++ b/include/linux/ceph/libceph.h
@@ -294,6 +294,8 @@ extern void ceph_destroy_client(struct ceph_client *client);
294extern int __ceph_open_session(struct ceph_client *client, 294extern int __ceph_open_session(struct ceph_client *client,
295 unsigned long started); 295 unsigned long started);
296extern int ceph_open_session(struct ceph_client *client); 296extern int ceph_open_session(struct ceph_client *client);
297int ceph_wait_for_latest_osdmap(struct ceph_client *client,
298 unsigned long timeout);
297 299
298/* pagevec.c */ 300/* pagevec.c */
299extern void ceph_release_page_vector(struct page **pages, int num_pages); 301extern void ceph_release_page_vector(struct page **pages, int num_pages);
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
index 9cab80207ced..79eac465ec65 100644
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -738,7 +738,6 @@ int __ceph_open_session(struct ceph_client *client, unsigned long started)
738} 738}
739EXPORT_SYMBOL(__ceph_open_session); 739EXPORT_SYMBOL(__ceph_open_session);
740 740
741
742int ceph_open_session(struct ceph_client *client) 741int ceph_open_session(struct ceph_client *client)
743{ 742{
744 int ret; 743 int ret;
@@ -754,6 +753,23 @@ int ceph_open_session(struct ceph_client *client)
754} 753}
755EXPORT_SYMBOL(ceph_open_session); 754EXPORT_SYMBOL(ceph_open_session);
756 755
756int ceph_wait_for_latest_osdmap(struct ceph_client *client,
757 unsigned long timeout)
758{
759 u64 newest_epoch;
760 int ret;
761
762 ret = ceph_monc_get_version(&client->monc, "osdmap", &newest_epoch);
763 if (ret)
764 return ret;
765
766 if (client->osdc.osdmap->epoch >= newest_epoch)
767 return 0;
768
769 ceph_osdc_maybe_request_map(&client->osdc);
770 return ceph_monc_wait_osdmap(&client->monc, newest_epoch, timeout);
771}
772EXPORT_SYMBOL(ceph_wait_for_latest_osdmap);
757 773
758static int __init init_ceph_lib(void) 774static int __init init_ceph_lib(void)
759{ 775{
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
index 18deb3d889c4..a53e4fbb6319 100644
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -922,6 +922,15 @@ int ceph_monc_blacklist_add(struct ceph_mon_client *monc,
922 mutex_unlock(&monc->mutex); 922 mutex_unlock(&monc->mutex);
923 923
924 ret = wait_generic_request(req); 924 ret = wait_generic_request(req);
925 if (!ret)
926 /*
927 * Make sure we have the osdmap that includes the blacklist
928 * entry. This is needed to ensure that the OSDs pick up the
929 * new blacklist before processing any future requests from
930 * this client.
931 */
932 ret = ceph_wait_for_latest_osdmap(monc->client, 0);
933
925out: 934out:
926 put_generic_request(req); 935 put_generic_request(req);
927 return ret; 936 return ret;