Skip to content

Commit 89d43d0

Browse files
lxbszidryomov
authored andcommitted
ceph: put the requests/sessions when it fails to alloc memory
When failing to allocate the sessions memory we should make sure the req1 and req2 and the sessions get put. And also in case the max_sessions decreased so when kreallocate the new memory some sessions maybe missed being put. And if the max_sessions is 0 krealloc will return ZERO_SIZE_PTR, which will lead to a distinct access fault. URL: https://tracker.ceph.com/issues/53819 Fixes: e1a4541 ("ceph: flush the mdlog before waiting on unsafe reqs") Signed-off-by: Xiubo Li <[email protected]> Reviewed-by: Venky Shankar <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent e783362 commit 89d43d0

File tree

1 file changed

+37
-18
lines changed

1 file changed

+37
-18
lines changed

fs/ceph/caps.c

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2218,6 +2218,7 @@ static int unsafe_request_wait(struct inode *inode)
22182218
struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
22192219
struct ceph_inode_info *ci = ceph_inode(inode);
22202220
struct ceph_mds_request *req1 = NULL, *req2 = NULL;
2221+
unsigned int max_sessions;
22212222
int ret, err = 0;
22222223

22232224
spin_lock(&ci->i_unsafe_lock);
@@ -2235,37 +2236,45 @@ static int unsafe_request_wait(struct inode *inode)
22352236
}
22362237
spin_unlock(&ci->i_unsafe_lock);
22372238

2239+
/*
2240+
* The mdsc->max_sessions is unlikely to be changed
2241+
* mostly, here we will retry it by reallocating the
2242+
* sessions array memory to get rid of the mdsc->mutex
2243+
* lock.
2244+
*/
2245+
retry:
2246+
max_sessions = mdsc->max_sessions;
2247+
22382248
/*
22392249
* Trigger to flush the journal logs in all the relevant MDSes
22402250
* manually, or in the worst case we must wait at most 5 seconds
22412251
* to wait the journal logs to be flushed by the MDSes periodically.
22422252
*/
2243-
if (req1 || req2) {
2253+
if ((req1 || req2) && likely(max_sessions)) {
22442254
struct ceph_mds_session **sessions = NULL;
22452255
struct ceph_mds_session *s;
22462256
struct ceph_mds_request *req;
2247-
unsigned int max;
22482257
int i;
22492258

2250-
/*
2251-
* The mdsc->max_sessions is unlikely to be changed
2252-
* mostly, here we will retry it by reallocating the
2253-
* sessions arrary memory to get rid of the mdsc->mutex
2254-
* lock.
2255-
*/
2256-
retry:
2257-
max = mdsc->max_sessions;
2258-
sessions = krealloc(sessions, max * sizeof(s), __GFP_ZERO);
2259-
if (!sessions)
2260-
return -ENOMEM;
2259+
sessions = kzalloc(max_sessions * sizeof(s), GFP_KERNEL);
2260+
if (!sessions) {
2261+
err = -ENOMEM;
2262+
goto out;
2263+
}
22612264

22622265
spin_lock(&ci->i_unsafe_lock);
22632266
if (req1) {
22642267
list_for_each_entry(req, &ci->i_unsafe_dirops,
22652268
r_unsafe_dir_item) {
22662269
s = req->r_session;
2267-
if (unlikely(s->s_mds >= max)) {
2270+
if (unlikely(s->s_mds >= max_sessions)) {
22682271
spin_unlock(&ci->i_unsafe_lock);
2272+
for (i = 0; i < max_sessions; i++) {
2273+
s = sessions[i];
2274+
if (s)
2275+
ceph_put_mds_session(s);
2276+
}
2277+
kfree(sessions);
22692278
goto retry;
22702279
}
22712280
if (!sessions[s->s_mds]) {
@@ -2278,8 +2287,14 @@ static int unsafe_request_wait(struct inode *inode)
22782287
list_for_each_entry(req, &ci->i_unsafe_iops,
22792288
r_unsafe_target_item) {
22802289
s = req->r_session;
2281-
if (unlikely(s->s_mds >= max)) {
2290+
if (unlikely(s->s_mds >= max_sessions)) {
22822291
spin_unlock(&ci->i_unsafe_lock);
2292+
for (i = 0; i < max_sessions; i++) {
2293+
s = sessions[i];
2294+
if (s)
2295+
ceph_put_mds_session(s);
2296+
}
2297+
kfree(sessions);
22832298
goto retry;
22842299
}
22852300
if (!sessions[s->s_mds]) {
@@ -2300,7 +2315,7 @@ static int unsafe_request_wait(struct inode *inode)
23002315
spin_unlock(&ci->i_ceph_lock);
23012316

23022317
/* send flush mdlog request to MDSes */
2303-
for (i = 0; i < max; i++) {
2318+
for (i = 0; i < max_sessions; i++) {
23042319
s = sessions[i];
23052320
if (s) {
23062321
send_flush_mdlog(s);
@@ -2317,15 +2332,19 @@ static int unsafe_request_wait(struct inode *inode)
23172332
ceph_timeout_jiffies(req1->r_timeout));
23182333
if (ret)
23192334
err = -EIO;
2320-
ceph_mdsc_put_request(req1);
23212335
}
23222336
if (req2) {
23232337
ret = !wait_for_completion_timeout(&req2->r_safe_completion,
23242338
ceph_timeout_jiffies(req2->r_timeout));
23252339
if (ret)
23262340
err = -EIO;
2327-
ceph_mdsc_put_request(req2);
23282341
}
2342+
2343+
out:
2344+
if (req1)
2345+
ceph_mdsc_put_request(req1);
2346+
if (req2)
2347+
ceph_mdsc_put_request(req2);
23292348
return err;
23302349
}
23312350

0 commit comments

Comments
 (0)