Skip to content

Commit 6026894

Browse files
committed
Merge tag 'ceph-for-5.6-rc8' of git://github.com/ceph/ceph-client
Pull ceph fixes from Ilya Dryomov: "A patch for a rather old regression in fullness handling and two memory leak fixes, marked for stable" * tag 'ceph-for-5.6-rc8' of git://github.com/ceph/ceph-client: ceph: fix memory leak in ceph_cleanup_snapid_map() libceph: fix alloc_msg_with_page_vector() memory leaks ceph: check POOL_FLAG_FULL/NEARFULL in addition to OSDMAP_FULL/NEARFULL
2 parents a53071b + c8d6ee0 commit 6026894

File tree

8 files changed

+43
-21
lines changed

8 files changed

+43
-21
lines changed

fs/ceph/file.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,10 +1415,13 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
14151415
struct inode *inode = file_inode(file);
14161416
struct ceph_inode_info *ci = ceph_inode(inode);
14171417
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
1418+
struct ceph_osd_client *osdc = &fsc->client->osdc;
14181419
struct ceph_cap_flush *prealloc_cf;
14191420
ssize_t count, written = 0;
14201421
int err, want, got;
14211422
bool direct_lock = false;
1423+
u32 map_flags;
1424+
u64 pool_flags;
14221425
loff_t pos;
14231426
loff_t limit = max(i_size_read(inode), fsc->max_file_size);
14241427

@@ -1481,8 +1484,12 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
14811484
goto out;
14821485
}
14831486

1484-
/* FIXME: not complete since it doesn't account for being at quota */
1485-
if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_FULL)) {
1487+
down_read(&osdc->lock);
1488+
map_flags = osdc->osdmap->flags;
1489+
pool_flags = ceph_pg_pool_flags(osdc->osdmap, ci->i_layout.pool_id);
1490+
up_read(&osdc->lock);
1491+
if ((map_flags & CEPH_OSDMAP_FULL) ||
1492+
(pool_flags & CEPH_POOL_FLAG_FULL)) {
14861493
err = -ENOSPC;
14871494
goto out;
14881495
}
@@ -1575,7 +1582,8 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
15751582
}
15761583

15771584
if (written >= 0) {
1578-
if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_NEARFULL))
1585+
if ((map_flags & CEPH_OSDMAP_NEARFULL) ||
1586+
(pool_flags & CEPH_POOL_FLAG_NEARFULL))
15791587
iocb->ki_flags |= IOCB_DSYNC;
15801588
written = generic_write_sync(iocb, written);
15811589
}

fs/ceph/snap.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,5 +1155,6 @@ void ceph_cleanup_snapid_map(struct ceph_mds_client *mdsc)
11551155
pr_err("snapid map %llx -> %x still in use\n",
11561156
sm->snap, sm->dev);
11571157
}
1158+
kfree(sm);
11581159
}
11591160
}

include/linux/ceph/messenger.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,10 @@ struct ceph_msg_data {
175175
#endif /* CONFIG_BLOCK */
176176
struct ceph_bvec_iter bvec_pos;
177177
struct {
178-
struct page **pages; /* NOT OWNER. */
178+
struct page **pages;
179179
size_t length; /* total # bytes */
180180
unsigned int alignment; /* first page */
181+
bool own_pages;
181182
};
182183
struct ceph_pagelist *pagelist;
183184
};
@@ -356,8 +357,8 @@ extern void ceph_con_keepalive(struct ceph_connection *con);
356357
extern bool ceph_con_keepalive_expired(struct ceph_connection *con,
357358
unsigned long interval);
358359

359-
extern void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages,
360-
size_t length, size_t alignment);
360+
void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages,
361+
size_t length, size_t alignment, bool own_pages);
361362
extern void ceph_msg_data_add_pagelist(struct ceph_msg *msg,
362363
struct ceph_pagelist *pagelist);
363364
#ifdef CONFIG_BLOCK

include/linux/ceph/osdmap.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ int ceph_spg_compare(const struct ceph_spg *lhs, const struct ceph_spg *rhs);
3737
#define CEPH_POOL_FLAG_HASHPSPOOL (1ULL << 0) /* hash pg seed and pool id
3838
together */
3939
#define CEPH_POOL_FLAG_FULL (1ULL << 1) /* pool is full */
40+
#define CEPH_POOL_FLAG_FULL_QUOTA (1ULL << 10) /* pool ran out of quota,
41+
will set FULL too */
42+
#define CEPH_POOL_FLAG_NEARFULL (1ULL << 11) /* pool is nearfull */
4043

4144
struct ceph_pg_pool_info {
4245
struct rb_node node;
@@ -304,5 +307,6 @@ extern struct ceph_pg_pool_info *ceph_pg_pool_by_id(struct ceph_osdmap *map,
304307

305308
extern const char *ceph_pg_pool_name_by_id(struct ceph_osdmap *map, u64 id);
306309
extern int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name);
310+
u64 ceph_pg_pool_flags(struct ceph_osdmap *map, u64 id);
307311

308312
#endif

include/linux/ceph/rados.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,10 @@ extern const char *ceph_osd_state_name(int s);
143143
/*
144144
* osd map flag bits
145145
*/
146-
#define CEPH_OSDMAP_NEARFULL (1<<0) /* sync writes (near ENOSPC) */
147-
#define CEPH_OSDMAP_FULL (1<<1) /* no data writes (ENOSPC) */
146+
#define CEPH_OSDMAP_NEARFULL (1<<0) /* sync writes (near ENOSPC),
147+
not set since ~luminous */
148+
#define CEPH_OSDMAP_FULL (1<<1) /* no data writes (ENOSPC),
149+
not set since ~luminous */
148150
#define CEPH_OSDMAP_PAUSERD (1<<2) /* pause all reads */
149151
#define CEPH_OSDMAP_PAUSEWR (1<<3) /* pause all writes */
150152
#define CEPH_OSDMAP_PAUSEREC (1<<4) /* pause recovery */

net/ceph/messenger.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3248,12 +3248,16 @@ static struct ceph_msg_data *ceph_msg_data_add(struct ceph_msg *msg)
32483248

32493249
static void ceph_msg_data_destroy(struct ceph_msg_data *data)
32503250
{
3251-
if (data->type == CEPH_MSG_DATA_PAGELIST)
3251+
if (data->type == CEPH_MSG_DATA_PAGES && data->own_pages) {
3252+
int num_pages = calc_pages_for(data->alignment, data->length);
3253+
ceph_release_page_vector(data->pages, num_pages);
3254+
} else if (data->type == CEPH_MSG_DATA_PAGELIST) {
32523255
ceph_pagelist_release(data->pagelist);
3256+
}
32533257
}
32543258

32553259
void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages,
3256-
size_t length, size_t alignment)
3260+
size_t length, size_t alignment, bool own_pages)
32573261
{
32583262
struct ceph_msg_data *data;
32593263

@@ -3265,6 +3269,7 @@ void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages,
32653269
data->pages = pages;
32663270
data->length = length;
32673271
data->alignment = alignment & ~PAGE_MASK;
3272+
data->own_pages = own_pages;
32683273

32693274
msg->data_length += length;
32703275
}

net/ceph/osd_client.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,7 @@ static void ceph_osdc_msg_data_add(struct ceph_msg *msg,
962962
BUG_ON(length > (u64) SIZE_MAX);
963963
if (length)
964964
ceph_msg_data_add_pages(msg, osd_data->pages,
965-
length, osd_data->alignment);
965+
length, osd_data->alignment, false);
966966
} else if (osd_data->type == CEPH_OSD_DATA_TYPE_PAGELIST) {
967967
BUG_ON(!length);
968968
ceph_msg_data_add_pagelist(msg, osd_data->pagelist);
@@ -4436,9 +4436,7 @@ static void handle_watch_notify(struct ceph_osd_client *osdc,
44364436
CEPH_MSG_DATA_PAGES);
44374437
*lreq->preply_pages = data->pages;
44384438
*lreq->preply_len = data->length;
4439-
} else {
4440-
ceph_release_page_vector(data->pages,
4441-
calc_pages_for(0, data->length));
4439+
data->own_pages = false;
44424440
}
44434441
}
44444442
lreq->notify_finish_error = return_code;
@@ -5506,9 +5504,6 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
55065504
return m;
55075505
}
55085506

5509-
/*
5510-
* TODO: switch to a msg-owned pagelist
5511-
*/
55125507
static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr)
55135508
{
55145509
struct ceph_msg *m;
@@ -5522,7 +5517,6 @@ static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr)
55225517

55235518
if (data_len) {
55245519
struct page **pages;
5525-
struct ceph_osd_data osd_data;
55265520

55275521
pages = ceph_alloc_page_vector(calc_pages_for(0, data_len),
55285522
GFP_NOIO);
@@ -5531,9 +5525,7 @@ static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr)
55315525
return NULL;
55325526
}
55335527

5534-
ceph_osd_data_pages_init(&osd_data, pages, data_len, 0, false,
5535-
false);
5536-
ceph_osdc_msg_data_add(m, &osd_data);
5528+
ceph_msg_data_add_pages(m, pages, data_len, 0, true);
55375529
}
55385530

55395531
return m;

net/ceph/osdmap.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,15 @@ int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name)
710710
}
711711
EXPORT_SYMBOL(ceph_pg_poolid_by_name);
712712

713+
u64 ceph_pg_pool_flags(struct ceph_osdmap *map, u64 id)
714+
{
715+
struct ceph_pg_pool_info *pi;
716+
717+
pi = __lookup_pg_pool(&map->pg_pools, id);
718+
return pi ? pi->flags : 0;
719+
}
720+
EXPORT_SYMBOL(ceph_pg_pool_flags);
721+
713722
static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi)
714723
{
715724
rb_erase(&pi->node, root);

0 commit comments

Comments
 (0)