diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/rbd.c | 125 |
1 files changed, 88 insertions, 37 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index d81c653b9bf6..7915f3b03736 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -181,6 +181,7 @@ struct rbd_image_header { struct rbd_spec { u64 pool_id; const char *pool_name; + const char *pool_ns; /* NULL if default, never "" */ const char *image_id; const char *image_name; @@ -735,6 +736,7 @@ enum { Opt_lock_timeout, Opt_last_int, /* int args above */ + Opt_pool_ns, Opt_last_string, /* string args above */ Opt_read_only, @@ -749,6 +751,7 @@ static match_table_t rbd_opts_tokens = { {Opt_queue_depth, "queue_depth=%d"}, {Opt_lock_timeout, "lock_timeout=%d"}, /* int args above */ + {Opt_pool_ns, "_pool_ns=%s"}, /* string args above */ {Opt_read_only, "read_only"}, {Opt_read_only, "ro"}, /* Alternate spelling */ @@ -776,9 +779,14 @@ struct rbd_options { #define RBD_EXCLUSIVE_DEFAULT false #define RBD_TRIM_DEFAULT true +struct parse_rbd_opts_ctx { + struct rbd_spec *spec; + struct rbd_options *opts; +}; + static int parse_rbd_opts_token(char *c, void *private) { - struct rbd_options *rbd_opts = private; + struct parse_rbd_opts_ctx *pctx = private; substring_t argstr[MAX_OPT_ARGS]; int token, intval, ret; @@ -786,7 +794,7 @@ static int parse_rbd_opts_token(char *c, void *private) if (token < Opt_last_int) { ret = match_int(&argstr[0], &intval); if (ret < 0) { - pr_err("bad mount option arg (not int) at '%s'\n", c); + pr_err("bad option arg (not int) at '%s'\n", c); return ret; } dout("got int token %d val %d\n", token, intval); @@ -802,7 +810,7 @@ static int parse_rbd_opts_token(char *c, void *private) pr_err("queue_depth out of range\n"); return -EINVAL; } - rbd_opts->queue_depth = intval; + pctx->opts->queue_depth = intval; break; case Opt_lock_timeout: /* 0 is "wait forever" (i.e. infinite timeout) */ @@ -810,22 +818,28 @@ static int parse_rbd_opts_token(char *c, void *private) pr_err("lock_timeout out of range\n"); return -EINVAL; } - rbd_opts->lock_timeout = msecs_to_jiffies(intval * 1000); + pctx->opts->lock_timeout = msecs_to_jiffies(intval * 1000); + break; + case Opt_pool_ns: + kfree(pctx->spec->pool_ns); + pctx->spec->pool_ns = match_strdup(argstr); + if (!pctx->spec->pool_ns) + return -ENOMEM; break; case Opt_read_only: - rbd_opts->read_only = true; + pctx->opts->read_only = true; break; case Opt_read_write: - rbd_opts->read_only = false; + pctx->opts->read_only = false; break; case Opt_lock_on_read: - rbd_opts->lock_on_read = true; + pctx->opts->lock_on_read = true; break; case Opt_exclusive: - rbd_opts->exclusive = true; + pctx->opts->exclusive = true; break; case Opt_notrim: - rbd_opts->trim = false; + pctx->opts->trim = false; break; default: /* libceph prints "bad option" msg */ @@ -1452,7 +1466,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request) struct ceph_osd_request *osd_req = obj_request->osd_req; osd_req->r_flags = CEPH_OSD_FLAG_WRITE; - ktime_get_real_ts(&osd_req->r_mtime); + ktime_get_real_ts64(&osd_req->r_mtime); osd_req->r_data_offset = obj_request->ex.oe_off; } @@ -1475,7 +1489,13 @@ rbd_osd_req_create(struct rbd_obj_request *obj_req, unsigned int num_ops) req->r_callback = rbd_osd_req_callback; req->r_priv = obj_req; + /* + * Data objects may be stored in a separate pool, but always in + * the same namespace in that pool as the header in its pool. + */ + ceph_oloc_copy(&req->r_base_oloc, &rbd_dev->header_oloc); req->r_base_oloc.pool = rbd_dev->layout.pool_id; + if (ceph_oid_aprintf(&req->r_base_oid, GFP_NOIO, name_format, rbd_dev->header.object_prefix, obj_req->ex.oe_objno)) goto err_req; @@ -4119,6 +4139,14 @@ static ssize_t rbd_pool_id_show(struct device *dev, (unsigned long long) rbd_dev->spec->pool_id); } +static ssize_t rbd_pool_ns_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); + + return sprintf(buf, "%s\n", rbd_dev->spec->pool_ns ?: ""); +} + static ssize_t rbd_name_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -4217,6 +4245,7 @@ static DEVICE_ATTR(cluster_fsid, 0444, rbd_cluster_fsid_show, NULL); static DEVICE_ATTR(config_info, 0400, rbd_config_info_show, NULL); static DEVICE_ATTR(pool, 0444, rbd_pool_show, NULL); static DEVICE_ATTR(pool_id, 0444, rbd_pool_id_show, NULL); +static DEVICE_ATTR(pool_ns, 0444, rbd_pool_ns_show, NULL); static DEVICE_ATTR(name, 0444, rbd_name_show, NULL); static DEVICE_ATTR(image_id, 0444, rbd_image_id_show, NULL); static DEVICE_ATTR(refresh, 0200, NULL, rbd_image_refresh); @@ -4235,6 +4264,7 @@ static struct attribute *rbd_attrs[] = { &dev_attr_config_info.attr, &dev_attr_pool.attr, &dev_attr_pool_id.attr, + &dev_attr_pool_ns.attr, &dev_attr_name.attr, &dev_attr_image_id.attr, &dev_attr_current_snap.attr, @@ -4295,6 +4325,7 @@ static void rbd_spec_free(struct kref *kref) struct rbd_spec *spec = container_of(kref, struct rbd_spec, kref); kfree(spec->pool_name); + kfree(spec->pool_ns); kfree(spec->image_id); kfree(spec->image_name); kfree(spec->snap_name); @@ -4353,6 +4384,12 @@ static struct rbd_device *__rbd_dev_create(struct rbd_client *rbdc, rbd_dev->header.data_pool_id = CEPH_NOPOOL; ceph_oid_init(&rbd_dev->header_oid); rbd_dev->header_oloc.pool = spec->pool_id; + if (spec->pool_ns) { + WARN_ON(!*spec->pool_ns); + rbd_dev->header_oloc.pool_ns = + ceph_find_or_create_string(spec->pool_ns, + strlen(spec->pool_ns)); + } mutex_init(&rbd_dev->watch_mutex); rbd_dev->watch_state = RBD_WATCH_STATE_UNREGISTERED; @@ -4633,6 +4670,17 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) parent_spec->pool_id = pool_id; parent_spec->image_id = image_id; parent_spec->snap_id = snap_id; + + /* TODO: support cloning across namespaces */ + if (rbd_dev->spec->pool_ns) { + parent_spec->pool_ns = kstrdup(rbd_dev->spec->pool_ns, + GFP_KERNEL); + if (!parent_spec->pool_ns) { + ret = -ENOMEM; + goto out_err; + } + } + rbd_dev->parent_spec = parent_spec; parent_spec = NULL; /* rbd_dev now owns this */ } else { @@ -5146,8 +5194,7 @@ static int rbd_add_parse_args(const char *buf, const char *mon_addrs; char *snap_name; size_t mon_addrs_size; - struct rbd_spec *spec = NULL; - struct rbd_options *rbd_opts = NULL; + struct parse_rbd_opts_ctx pctx = { 0 }; struct ceph_options *copts; int ret; @@ -5171,22 +5218,22 @@ static int rbd_add_parse_args(const char *buf, goto out_err; } - spec = rbd_spec_alloc(); - if (!spec) + pctx.spec = rbd_spec_alloc(); + if (!pctx.spec) goto out_mem; - spec->pool_name = dup_token(&buf, NULL); - if (!spec->pool_name) + pctx.spec->pool_name = dup_token(&buf, NULL); + if (!pctx.spec->pool_name) goto out_mem; - if (!*spec->pool_name) { + if (!*pctx.spec->pool_name) { rbd_warn(NULL, "no pool name provided"); goto out_err; } - spec->image_name = dup_token(&buf, NULL); - if (!spec->image_name) + pctx.spec->image_name = dup_token(&buf, NULL); + if (!pctx.spec->image_name) goto out_mem; - if (!*spec->image_name) { + if (!*pctx.spec->image_name) { rbd_warn(NULL, "no image name provided"); goto out_err; } @@ -5207,24 +5254,24 @@ static int rbd_add_parse_args(const char *buf, if (!snap_name) goto out_mem; *(snap_name + len) = '\0'; - spec->snap_name = snap_name; + pctx.spec->snap_name = snap_name; /* Initialize all rbd options to the defaults */ - rbd_opts = kzalloc(sizeof (*rbd_opts), GFP_KERNEL); - if (!rbd_opts) + pctx.opts = kzalloc(sizeof(*pctx.opts), GFP_KERNEL); + if (!pctx.opts) goto out_mem; - rbd_opts->read_only = RBD_READ_ONLY_DEFAULT; - rbd_opts->queue_depth = RBD_QUEUE_DEPTH_DEFAULT; - rbd_opts->lock_timeout = RBD_LOCK_TIMEOUT_DEFAULT; - rbd_opts->lock_on_read = RBD_LOCK_ON_READ_DEFAULT; - rbd_opts->exclusive = RBD_EXCLUSIVE_DEFAULT; - rbd_opts->trim = RBD_TRIM_DEFAULT; + pctx.opts->read_only = RBD_READ_ONLY_DEFAULT; + pctx.opts->queue_depth = RBD_QUEUE_DEPTH_DEFAULT; + pctx.opts->lock_timeout = RBD_LOCK_TIMEOUT_DEFAULT; + pctx.opts->lock_on_read = RBD_LOCK_ON_READ_DEFAULT; + pctx.opts->exclusive = RBD_EXCLUSIVE_DEFAULT; + pctx.opts->trim = RBD_TRIM_DEFAULT; copts = ceph_parse_options(options, mon_addrs, - mon_addrs + mon_addrs_size - 1, - parse_rbd_opts_token, rbd_opts); + mon_addrs + mon_addrs_size - 1, + parse_rbd_opts_token, &pctx); if (IS_ERR(copts)) { ret = PTR_ERR(copts); goto out_err; @@ -5232,15 +5279,15 @@ static int rbd_add_parse_args(const char *buf, kfree(options); *ceph_opts = copts; - *opts = rbd_opts; - *rbd_spec = spec; + *opts = pctx.opts; + *rbd_spec = pctx.spec; return 0; out_mem: ret = -ENOMEM; out_err: - kfree(rbd_opts); - rbd_spec_put(spec); + kfree(pctx.opts); + rbd_spec_put(pctx.spec); kfree(options); return ret; @@ -5586,8 +5633,10 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth) ret = rbd_register_watch(rbd_dev); if (ret) { if (ret == -ENOENT) - pr_info("image %s/%s does not exist\n", + pr_info("image %s/%s%s%s does not exist\n", rbd_dev->spec->pool_name, + rbd_dev->spec->pool_ns ?: "", + rbd_dev->spec->pool_ns ? "/" : "", rbd_dev->spec->image_name); goto err_out_format; } @@ -5609,8 +5658,10 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth) ret = rbd_spec_fill_names(rbd_dev); if (ret) { if (ret == -ENOENT) - pr_info("snap %s/%s@%s does not exist\n", + pr_info("snap %s/%s%s%s@%s does not exist\n", rbd_dev->spec->pool_name, + rbd_dev->spec->pool_ns ?: "", + rbd_dev->spec->pool_ns ? "/" : "", rbd_dev->spec->image_name, rbd_dev->spec->snap_name); goto err_out_probe; |