@@ -32,6 +32,12 @@
#define CEPH_OPT_DEFAULT (0)
+/* osd full behavior */
+enum {
+ CEPH_OSD_FULL_ERROR,
+ CEPH_OSD_FULL_BLOCK,
+};
+
#define ceph_set_opt(client, opt) \
(client)->options->flags |= CEPH_OPT_##opt;
#define ceph_test_opt(client, opt) \
@@ -44,6 +50,7 @@ struct ceph_options {
int mount_timeout;
int osd_idle_ttl;
int osd_keepalive_timeout;
+ int osd_full_behavior;
/*
* any type that can't be simply compared or doesn't need need
@@ -217,6 +217,7 @@ enum {
Opt_secret,
Opt_key,
Opt_ip,
+ Opt_osd_full_behavior,
Opt_last_string,
/* string args above */
Opt_share,
@@ -236,6 +237,7 @@ static match_table_t opt_tokens = {
{Opt_secret, "secret=%s"},
{Opt_key, "key=%s"},
{Opt_ip, "ip=%s"},
+ {Opt_osd_full_behavior, "osd_full_behavior=%s"},
/* string args above */
{Opt_share, "share"},
{Opt_noshare, "noshare"},
@@ -329,6 +331,7 @@ ceph_parse_options(char *options, const char *dev_name,
opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */
opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; /* seconds */
+ opt->osd_full_behavior = CEPH_OSD_FULL_BLOCK;
/* get mon ip(s) */
/* ip1[:port1][,ip2[:port2]...] */
@@ -408,6 +411,16 @@ ceph_parse_options(char *options, const char *dev_name,
if (err < 0)
goto out;
break;
+ case Opt_osd_full_behavior:
+ if (!strcmp(argstr[0].from, "error")) {
+ opt->osd_full_behavior = CEPH_OSD_FULL_ERROR;
+ } else if (!strcmp(argstr[0].from, "block")) {
+ opt->osd_full_behavior = CEPH_OSD_FULL_BLOCK;
+ } else {
+ err = -EINVAL;
+ goto out;
+ }
+ break;
/* misc */
case Opt_osdtimeout:
@@ -1240,9 +1240,12 @@ EXPORT_SYMBOL(ceph_osdc_set_request_linger);
static bool __req_should_be_paused(struct ceph_osd_client *osdc,
struct ceph_osd_request *req)
{
+ bool block_on_full =
+ osdc->client->options->osd_full_behavior & CEPH_OSD_FULL_BLOCK;
bool pauserd = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSERD);
bool pausewr = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSEWR) ||
- ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL);
+ (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL) &&
+ block_on_full);
return (req->r_flags & CEPH_OSD_FLAG_READ && pauserd) ||
(req->r_flags & CEPH_OSD_FLAG_WRITE && pausewr);
}
Default to blocking requests to be consistent with userspace. Some applications may prefer the previous behavior of returning an error instead, so make that an option. CephFS implements returning -ENOSPC at a higher level, so only rbd is really affected by this. Signed-off-by: Josh Durgin <josh.durgin@inktank.com> --- include/linux/ceph/libceph.h | 7 +++++++ net/ceph/ceph_common.c | 13 +++++++++++++ net/ceph/osd_client.c | 5 ++++- 3 files changed, 24 insertions(+), 1 deletion(-)