Skip to content

Commit 7614209

Browse files
committed
ceph: check POOL_FLAG_FULL/NEARFULL in addition to OSDMAP_FULL/NEARFULL
CEPH_OSDMAP_FULL/NEARFULL aren't set since mimic, so we need to consult per-pool flags as well. Unfortunately the backwards compatibility here is lacking: - the change that deprecated OSDMAP_FULL/NEARFULL went into mimic, but was guarded by require_osd_release >= RELEASE_LUMINOUS - it was subsequently backported to luminous in v12.2.2, but that makes no difference to clients that only check OSDMAP_FULL/NEARFULL because require_osd_release is not client-facing -- it is for OSDs Since all kernels are affected, the best we can do here is just start checking both map flags and pool flags and send that to stable. These checks are best effort, so take osdc->lock and look up pool flags just once. Remove the FIXME, since filesystem quotas are checked above and RADOS quotas are reflected in POOL_FLAG_FULL: when the pool reaches its quota, both POOL_FLAG_FULL and POOL_FLAG_FULL_QUOTA are set. Cc: [email protected] Reported-by: Yanhu Cao <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Acked-by: Sage Weil <[email protected]>
1 parent 16fbf79 commit 7614209

File tree

4 files changed

+28
-5
lines changed

4 files changed

+28
-5
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
}

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/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)