Skip to content

Commit 002b758

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
Pull Ceph fixes from Sage Weil: "There are a couple of fixes from Yan for bad pointer dereferences in the messenger code and when fiddling with page->private after page migration, a fix from Alex for a use-after-free in the osd client code, and a couple fixes for the message refcounting and shutdown ordering." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: libceph: flush msgr queue during mon_client shutdown rbd: Clear ceph_msg->bio_iter for retransmitted message libceph: use con get/put ops from osd_client libceph: osd_client: don't drop reply reference too early ceph: check PG_Private flag before accessing page->private
2 parents 369c4f5 + 642c0db commit 002b758

File tree

5 files changed

+30
-22
lines changed

5 files changed

+30
-22
lines changed

fs/ceph/addr.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,12 @@
5454
(CONGESTION_ON_THRESH(congestion_kb) - \
5555
(CONGESTION_ON_THRESH(congestion_kb) >> 2))
5656

57-
57+
static inline struct ceph_snap_context *page_snap_context(struct page *page)
58+
{
59+
if (PagePrivate(page))
60+
return (void *)page->private;
61+
return NULL;
62+
}
5863

5964
/*
6065
* Dirty a page. Optimistically adjust accounting, on the assumption
@@ -142,10 +147,9 @@ static void ceph_invalidatepage(struct page *page, unsigned long offset)
142147
{
143148
struct inode *inode;
144149
struct ceph_inode_info *ci;
145-
struct ceph_snap_context *snapc = (void *)page->private;
150+
struct ceph_snap_context *snapc = page_snap_context(page);
146151

147152
BUG_ON(!PageLocked(page));
148-
BUG_ON(!page->private);
149153
BUG_ON(!PagePrivate(page));
150154
BUG_ON(!page->mapping);
151155

@@ -182,7 +186,6 @@ static int ceph_releasepage(struct page *page, gfp_t g)
182186
struct inode *inode = page->mapping ? page->mapping->host : NULL;
183187
dout("%p releasepage %p idx %lu\n", inode, page, page->index);
184188
WARN_ON(PageDirty(page));
185-
WARN_ON(page->private);
186189
WARN_ON(PagePrivate(page));
187190
return 0;
188191
}
@@ -443,15 +446,15 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
443446
osdc = &fsc->client->osdc;
444447

445448
/* verify this is a writeable snap context */
446-
snapc = (void *)page->private;
449+
snapc = page_snap_context(page);
447450
if (snapc == NULL) {
448451
dout("writepage %p page %p not dirty?\n", inode, page);
449452
goto out;
450453
}
451454
oldest = get_oldest_context(inode, &snap_size);
452455
if (snapc->seq > oldest->seq) {
453456
dout("writepage %p page %p snapc %p not writeable - noop\n",
454-
inode, page, (void *)page->private);
457+
inode, page, snapc);
455458
/* we should only noop if called by kswapd */
456459
WARN_ON((current->flags & PF_MEMALLOC) == 0);
457460
ceph_put_snap_context(oldest);
@@ -591,7 +594,7 @@ static void writepages_finish(struct ceph_osd_request *req,
591594
clear_bdi_congested(&fsc->backing_dev_info,
592595
BLK_RW_ASYNC);
593596

594-
ceph_put_snap_context((void *)page->private);
597+
ceph_put_snap_context(page_snap_context(page));
595598
page->private = 0;
596599
ClearPagePrivate(page);
597600
dout("unlocking %d %p\n", i, page);
@@ -795,7 +798,7 @@ static int ceph_writepages_start(struct address_space *mapping,
795798
}
796799

797800
/* only if matching snap context */
798-
pgsnapc = (void *)page->private;
801+
pgsnapc = page_snap_context(page);
799802
if (pgsnapc->seq > snapc->seq) {
800803
dout("page snapc %p %lld > oldest %p %lld\n",
801804
pgsnapc, pgsnapc->seq, snapc, snapc->seq);
@@ -984,7 +987,7 @@ static int ceph_update_writeable_page(struct file *file,
984987
BUG_ON(!ci->i_snap_realm);
985988
down_read(&mdsc->snap_rwsem);
986989
BUG_ON(!ci->i_snap_realm->cached_context);
987-
snapc = (void *)page->private;
990+
snapc = page_snap_context(page);
988991
if (snapc && snapc != ci->i_head_snapc) {
989992
/*
990993
* this page is already dirty in another (older) snap

net/ceph/ceph_common.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -504,13 +504,6 @@ void ceph_destroy_client(struct ceph_client *client)
504504
/* unmount */
505505
ceph_osdc_stop(&client->osdc);
506506

507-
/*
508-
* make sure osd connections close out before destroying the
509-
* auth module, which is needed to free those connections'
510-
* ceph_authorizers.
511-
*/
512-
ceph_msgr_flush();
513-
514507
ceph_monc_stop(&client->monc);
515508

516509
ceph_debugfs_client_cleanup(client);

net/ceph/messenger.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,10 @@ static void prepare_write_message(struct ceph_connection *con)
563563
m->hdr.seq = cpu_to_le64(++con->out_seq);
564564
m->needs_out_seq = false;
565565
}
566+
#ifdef CONFIG_BLOCK
567+
else
568+
m->bio_iter = NULL;
569+
#endif
566570

567571
dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n",
568572
m, con->out_seq, le16_to_cpu(m->hdr.type),

net/ceph/mon_client.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,14 @@ void ceph_monc_stop(struct ceph_mon_client *monc)
847847

848848
mutex_unlock(&monc->mutex);
849849

850+
/*
851+
* flush msgr queue before we destroy ourselves to ensure that:
852+
* - any work that references our embedded con is finished.
853+
* - any osd_client or other work that may reference an authorizer
854+
* finishes before we shut down the auth subsystem.
855+
*/
856+
ceph_msgr_flush();
857+
850858
ceph_auth_destroy(monc->auth);
851859

852860
ceph_msg_put(monc->m_auth);

net/ceph/osd_client.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,15 +139,15 @@ void ceph_osdc_release_request(struct kref *kref)
139139

140140
if (req->r_request)
141141
ceph_msg_put(req->r_request);
142-
if (req->r_reply)
143-
ceph_msg_put(req->r_reply);
144142
if (req->r_con_filling_msg) {
145143
dout("release_request revoking pages %p from con %p\n",
146144
req->r_pages, req->r_con_filling_msg);
147145
ceph_con_revoke_message(req->r_con_filling_msg,
148146
req->r_reply);
149-
ceph_con_put(req->r_con_filling_msg);
147+
req->r_con_filling_msg->ops->put(req->r_con_filling_msg);
150148
}
149+
if (req->r_reply)
150+
ceph_msg_put(req->r_reply);
151151
if (req->r_own_pages)
152152
ceph_release_page_vector(req->r_pages,
153153
req->r_num_pages);
@@ -1216,7 +1216,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
12161216
if (req->r_con_filling_msg == con && req->r_reply == msg) {
12171217
dout(" dropping con_filling_msg ref %p\n", con);
12181218
req->r_con_filling_msg = NULL;
1219-
ceph_con_put(con);
1219+
con->ops->put(con);
12201220
}
12211221

12221222
if (!req->r_got_reply) {
@@ -2028,7 +2028,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
20282028
dout("get_reply revoking msg %p from old con %p\n",
20292029
req->r_reply, req->r_con_filling_msg);
20302030
ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply);
2031-
ceph_con_put(req->r_con_filling_msg);
2031+
req->r_con_filling_msg->ops->put(req->r_con_filling_msg);
20322032
req->r_con_filling_msg = NULL;
20332033
}
20342034

@@ -2063,7 +2063,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
20632063
#endif
20642064
}
20652065
*skip = 0;
2066-
req->r_con_filling_msg = ceph_con_get(con);
2066+
req->r_con_filling_msg = con->ops->get(con);
20672067
dout("get_reply tid %lld %p\n", tid, m);
20682068

20692069
out:

0 commit comments

Comments
 (0)