Commit 14c06b91 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'ceph-for-6.6-rc4' of https://github.com/ceph/ceph-client

Pull ceph fixes from Ilya Dryomov:
 "A series that fixes an involved 'double watch error' deadlock in RBD
  marked for stable and two cleanups"

* tag 'ceph-for-6.6-rc4' of https://github.com/ceph/ceph-client:
  rbd: take header_rwsem in rbd_dev_refresh() only when updating
  rbd: decouple parent info read-in from updating rbd_dev
  rbd: decouple header read-in from updating rbd_dev->header
  rbd: move rbd_dev_refresh() definition
  Revert "ceph: make members in struct ceph_mds_request_args_ext a union"
  ceph: remove unnecessary check for NULL in parse_longname()
parents 10c0b6ba 0b207d02
Loading
Loading
Loading
Loading
+225 −187
Original line number Diff line number Diff line
@@ -632,9 +632,8 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...)
static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);

static int rbd_dev_refresh(struct rbd_device *rbd_dev);
static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev);
static int rbd_dev_header_info(struct rbd_device *rbd_dev);
static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev);
static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev,
				     struct rbd_image_header *header);
static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev,
					u64 snap_id);
static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
@@ -995,15 +994,24 @@ static void rbd_init_layout(struct rbd_device *rbd_dev)
	RCU_INIT_POINTER(rbd_dev->layout.pool_ns, NULL);
}

static void rbd_image_header_cleanup(struct rbd_image_header *header)
{
	kfree(header->object_prefix);
	ceph_put_snap_context(header->snapc);
	kfree(header->snap_sizes);
	kfree(header->snap_names);

	memset(header, 0, sizeof(*header));
}

/*
 * Fill an rbd image header with information from the given format 1
 * on-disk header.
 */
static int rbd_header_from_disk(struct rbd_device *rbd_dev,
				 struct rbd_image_header_ondisk *ondisk)
static int rbd_header_from_disk(struct rbd_image_header *header,
				struct rbd_image_header_ondisk *ondisk,
				bool first_time)
{
	struct rbd_image_header *header = &rbd_dev->header;
	bool first_time = header->object_prefix == NULL;
	struct ceph_snap_context *snapc;
	char *object_prefix = NULL;
	char *snap_names = NULL;
@@ -1070,11 +1078,6 @@ static int rbd_header_from_disk(struct rbd_device *rbd_dev,
	if (first_time) {
		header->object_prefix = object_prefix;
		header->obj_order = ondisk->options.order;
		rbd_init_layout(rbd_dev);
	} else {
		ceph_put_snap_context(header->snapc);
		kfree(header->snap_names);
		kfree(header->snap_sizes);
	}

	/* The remaining fields always get updated (when we refresh) */
@@ -4859,7 +4862,9 @@ static int rbd_obj_read_sync(struct rbd_device *rbd_dev,
 * return, the rbd_dev->header field will contain up-to-date
 * information about the image.
 */
static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev)
static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev,
				  struct rbd_image_header *header,
				  bool first_time)
{
	struct rbd_image_header_ondisk *ondisk = NULL;
	u32 snap_count = 0;
@@ -4907,7 +4912,7 @@ static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev)
		snap_count = le32_to_cpu(ondisk->snap_count);
	} while (snap_count != want_count);

	ret = rbd_header_from_disk(rbd_dev, ondisk);
	ret = rbd_header_from_disk(header, ondisk, first_time);
out:
	kfree(ondisk);

@@ -4931,39 +4936,6 @@ static void rbd_dev_update_size(struct rbd_device *rbd_dev)
	}
}

static int rbd_dev_refresh(struct rbd_device *rbd_dev)
{
	u64 mapping_size;
	int ret;

	down_write(&rbd_dev->header_rwsem);
	mapping_size = rbd_dev->mapping.size;

	ret = rbd_dev_header_info(rbd_dev);
	if (ret)
		goto out;

	/*
	 * If there is a parent, see if it has disappeared due to the
	 * mapped image getting flattened.
	 */
	if (rbd_dev->parent) {
		ret = rbd_dev_v2_parent_info(rbd_dev);
		if (ret)
			goto out;
	}

	rbd_assert(!rbd_is_snap(rbd_dev));
	rbd_dev->mapping.size = rbd_dev->header.image_size;

out:
	up_write(&rbd_dev->header_rwsem);
	if (!ret && mapping_size != rbd_dev->mapping.size)
		rbd_dev_update_size(rbd_dev);

	return ret;
}

static const struct blk_mq_ops rbd_mq_ops = {
	.queue_rq	= rbd_queue_rq,
};
@@ -5503,17 +5475,12 @@ static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
	return 0;
}

static int rbd_dev_v2_image_size(struct rbd_device *rbd_dev)
{
	return _rbd_dev_v2_snap_size(rbd_dev, CEPH_NOSNAP,
					&rbd_dev->header.obj_order,
					&rbd_dev->header.image_size);
}

static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev)
static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev,
				    char **pobject_prefix)
{
	size_t size;
	void *reply_buf;
	char *object_prefix;
	int ret;
	void *p;

@@ -5531,16 +5498,16 @@ static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev)
		goto out;

	p = reply_buf;
	rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p,
						p + ret, NULL, GFP_NOIO);
	object_prefix = ceph_extract_encoded_string(&p, p + ret, NULL,
						    GFP_NOIO);
	if (IS_ERR(object_prefix)) {
		ret = PTR_ERR(object_prefix);
		goto out;
	}
	ret = 0;

	if (IS_ERR(rbd_dev->header.object_prefix)) {
		ret = PTR_ERR(rbd_dev->header.object_prefix);
		rbd_dev->header.object_prefix = NULL;
	} else {
		dout("  object_prefix = %s\n", rbd_dev->header.object_prefix);
	}
	*pobject_prefix = object_prefix;
	dout("  object_prefix = %s\n", object_prefix);
out:
	kfree(reply_buf);

@@ -5591,13 +5558,6 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
	return 0;
}

static int rbd_dev_v2_features(struct rbd_device *rbd_dev)
{
	return _rbd_dev_v2_snap_features(rbd_dev, CEPH_NOSNAP,
					 rbd_is_ro(rbd_dev),
					 &rbd_dev->header.features);
}

/*
 * These are generic image flags, but since they are used only for
 * object map, store them in rbd_dev->object_map_flags.
@@ -5634,6 +5594,14 @@ struct parent_image_info {
	u64		overlap;
};

static void rbd_parent_info_cleanup(struct parent_image_info *pii)
{
	kfree(pii->pool_ns);
	kfree(pii->image_id);

	memset(pii, 0, sizeof(*pii));
}

/*
 * The caller is responsible for @pii.
 */
@@ -5703,6 +5671,9 @@ static int __get_parent_info(struct rbd_device *rbd_dev,
	if (pii->has_overlap)
		ceph_decode_64_safe(&p, end, pii->overlap, e_inval);

	dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n",
	     __func__, pii->pool_id, pii->pool_ns, pii->image_id, pii->snap_id,
	     pii->has_overlap, pii->overlap);
	return 0;

e_inval:
@@ -5741,13 +5712,16 @@ static int __get_parent_info_legacy(struct rbd_device *rbd_dev,
	pii->has_overlap = true;
	ceph_decode_64_safe(&p, end, pii->overlap, e_inval);

	dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n",
	     __func__, pii->pool_id, pii->pool_ns, pii->image_id, pii->snap_id,
	     pii->has_overlap, pii->overlap);
	return 0;

e_inval:
	return -EINVAL;
}

static int get_parent_info(struct rbd_device *rbd_dev,
static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev,
				  struct parent_image_info *pii)
{
	struct page *req_page, *reply_page;
@@ -5776,7 +5750,7 @@ static int get_parent_info(struct rbd_device *rbd_dev,
	return ret;
}

static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
static int rbd_dev_setup_parent(struct rbd_device *rbd_dev)
{
	struct rbd_spec *parent_spec;
	struct parent_image_info pii = { 0 };
@@ -5786,37 +5760,12 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
	if (!parent_spec)
		return -ENOMEM;

	ret = get_parent_info(rbd_dev, &pii);
	ret = rbd_dev_v2_parent_info(rbd_dev, &pii);
	if (ret)
		goto out_err;

	dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n",
	     __func__, pii.pool_id, pii.pool_ns, pii.image_id, pii.snap_id,
	     pii.has_overlap, pii.overlap);

	if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap) {
		/*
		 * Either the parent never existed, or we have
		 * record of it but the image got flattened so it no
		 * longer has a parent.  When the parent of a
		 * layered image disappears we immediately set the
		 * overlap to 0.  The effect of this is that all new
		 * requests will be treated as if the image had no
		 * parent.
		 *
		 * If !pii.has_overlap, the parent image spec is not
		 * applicable.  It's there to avoid duplication in each
		 * snapshot record.
		 */
		if (rbd_dev->parent_overlap) {
			rbd_dev->parent_overlap = 0;
			rbd_dev_parent_put(rbd_dev);
			pr_info("%s: clone image has been flattened\n",
				rbd_dev->disk->disk_name);
		}

	if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap)
		goto out;	/* No parent?  No problem. */
	}

	/* The ceph file layout needs to fit pool id in 32 bits */

@@ -5828,11 +5777,9 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
	}

	/*
	 * The parent won't change (except when the clone is
	 * flattened, already handled that).  So we only need to
	 * record the parent spec we have not already done so.
	 * The parent won't change except when the clone is flattened,
	 * so we only need to record the parent image spec once.
	 */
	if (!rbd_dev->parent_spec) {
	parent_spec->pool_id = pii.pool_id;
	if (pii.pool_ns && *pii.pool_ns) {
		parent_spec->pool_ns = pii.pool_ns;
@@ -5842,44 +5789,34 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
	pii.image_id = NULL;
	parent_spec->snap_id = pii.snap_id;

	rbd_assert(!rbd_dev->parent_spec);
	rbd_dev->parent_spec = parent_spec;
	parent_spec = NULL;	/* rbd_dev now owns this */
	}

	/*
	 * We always update the parent overlap.  If it's zero we issue
	 * a warning, as we will proceed as if there was no parent.
	 * Record the parent overlap.  If it's zero, issue a warning as
	 * we will proceed as if there is no parent.
	 */
	if (!pii.overlap) {
		if (parent_spec) {
			/* refresh, careful to warn just once */
			if (rbd_dev->parent_overlap)
				rbd_warn(rbd_dev,
				    "clone now standalone (overlap became 0)");
		} else {
			/* initial probe */
	if (!pii.overlap)
		rbd_warn(rbd_dev, "clone is standalone (overlap 0)");
		}
	}
	rbd_dev->parent_overlap = pii.overlap;

out:
	ret = 0;
out_err:
	kfree(pii.pool_ns);
	kfree(pii.image_id);
	rbd_parent_info_cleanup(&pii);
	rbd_spec_put(parent_spec);
	return ret;
}

static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev)
static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev,
				    u64 *stripe_unit, u64 *stripe_count)
{
	struct {
		__le64 stripe_unit;
		__le64 stripe_count;
	} __attribute__ ((packed)) striping_info_buf = { 0 };
	size_t size = sizeof (striping_info_buf);
	void *p;
	int ret;

	ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid,
@@ -5891,27 +5828,33 @@ static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev)
	if (ret < size)
		return -ERANGE;

	p = &striping_info_buf;
	rbd_dev->header.stripe_unit = ceph_decode_64(&p);
	rbd_dev->header.stripe_count = ceph_decode_64(&p);
	*stripe_unit = le64_to_cpu(striping_info_buf.stripe_unit);
	*stripe_count = le64_to_cpu(striping_info_buf.stripe_count);
	dout("  stripe_unit = %llu stripe_count = %llu\n", *stripe_unit,
	     *stripe_count);

	return 0;
}

static int rbd_dev_v2_data_pool(struct rbd_device *rbd_dev)
static int rbd_dev_v2_data_pool(struct rbd_device *rbd_dev, s64 *data_pool_id)
{
	__le64 data_pool_id;
	__le64 data_pool_buf;
	int ret;

	ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid,
				  &rbd_dev->header_oloc, "get_data_pool",
				  NULL, 0, &data_pool_id, sizeof(data_pool_id));
				  NULL, 0, &data_pool_buf,
				  sizeof(data_pool_buf));
	dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
	if (ret < 0)
		return ret;
	if (ret < sizeof(data_pool_id))
	if (ret < sizeof(data_pool_buf))
		return -EBADMSG;

	rbd_dev->header.data_pool_id = le64_to_cpu(data_pool_id);
	WARN_ON(rbd_dev->header.data_pool_id == CEPH_NOPOOL);
	*data_pool_id = le64_to_cpu(data_pool_buf);
	dout("  data_pool_id = %lld\n", *data_pool_id);
	WARN_ON(*data_pool_id == CEPH_NOPOOL);

	return 0;
}

@@ -6103,7 +6046,8 @@ static int rbd_spec_fill_names(struct rbd_device *rbd_dev)
	return ret;
}

static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev)
static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev,
				   struct ceph_snap_context **psnapc)
{
	size_t size;
	int ret;
@@ -6164,9 +6108,7 @@ static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev)
	for (i = 0; i < snap_count; i++)
		snapc->snaps[i] = ceph_decode_64(&p);

	ceph_put_snap_context(rbd_dev->header.snapc);
	rbd_dev->header.snapc = snapc;

	*psnapc = snapc;
	dout("  snap context seq = %llu, snap_count = %u\n",
		(unsigned long long)seq, (unsigned int)snap_count);
out:
@@ -6215,38 +6157,42 @@ static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev,
	return snap_name;
}

static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev)
static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev,
				  struct rbd_image_header *header,
				  bool first_time)
{
	bool first_time = rbd_dev->header.object_prefix == NULL;
	int ret;

	ret = rbd_dev_v2_image_size(rbd_dev);
	ret = _rbd_dev_v2_snap_size(rbd_dev, CEPH_NOSNAP,
				    first_time ? &header->obj_order : NULL,
				    &header->image_size);
	if (ret)
		return ret;

	if (first_time) {
		ret = rbd_dev_v2_header_onetime(rbd_dev);
		ret = rbd_dev_v2_header_onetime(rbd_dev, header);
		if (ret)
			return ret;
	}

	ret = rbd_dev_v2_snap_context(rbd_dev);
	if (ret && first_time) {
		kfree(rbd_dev->header.object_prefix);
		rbd_dev->header.object_prefix = NULL;
	}

	ret = rbd_dev_v2_snap_context(rbd_dev, &header->snapc);
	if (ret)
		return ret;

	return 0;
}

static int rbd_dev_header_info(struct rbd_device *rbd_dev)
static int rbd_dev_header_info(struct rbd_device *rbd_dev,
			       struct rbd_image_header *header,
			       bool first_time)
{
	rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
	rbd_assert(!header->object_prefix && !header->snapc);

	if (rbd_dev->image_format == 1)
		return rbd_dev_v1_header_info(rbd_dev);
		return rbd_dev_v1_header_info(rbd_dev, header, first_time);

	return rbd_dev_v2_header_info(rbd_dev);
	return rbd_dev_v2_header_info(rbd_dev, header, first_time);
}

/*
@@ -6734,60 +6680,49 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev)
 */
static void rbd_dev_unprobe(struct rbd_device *rbd_dev)
{
	struct rbd_image_header	*header;

	rbd_dev_parent_put(rbd_dev);
	rbd_object_map_free(rbd_dev);
	rbd_dev_mapping_clear(rbd_dev);

	/* Free dynamic fields from the header, then zero it out */

	header = &rbd_dev->header;
	ceph_put_snap_context(header->snapc);
	kfree(header->snap_sizes);
	kfree(header->snap_names);
	kfree(header->object_prefix);
	memset(header, 0, sizeof (*header));
	rbd_image_header_cleanup(&rbd_dev->header);
}

static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev)
static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev,
				     struct rbd_image_header *header)
{
	int ret;

	ret = rbd_dev_v2_object_prefix(rbd_dev);
	ret = rbd_dev_v2_object_prefix(rbd_dev, &header->object_prefix);
	if (ret)
		goto out_err;
		return ret;

	/*
	 * Get the and check features for the image.  Currently the
	 * features are assumed to never change.
	 */
	ret = rbd_dev_v2_features(rbd_dev);
	ret = _rbd_dev_v2_snap_features(rbd_dev, CEPH_NOSNAP,
					rbd_is_ro(rbd_dev), &header->features);
	if (ret)
		goto out_err;
		return ret;

	/* If the image supports fancy striping, get its parameters */

	if (rbd_dev->header.features & RBD_FEATURE_STRIPINGV2) {
		ret = rbd_dev_v2_striping_info(rbd_dev);
		if (ret < 0)
			goto out_err;
	if (header->features & RBD_FEATURE_STRIPINGV2) {
		ret = rbd_dev_v2_striping_info(rbd_dev, &header->stripe_unit,
					       &header->stripe_count);
		if (ret)
			return ret;
	}

	if (rbd_dev->header.features & RBD_FEATURE_DATA_POOL) {
		ret = rbd_dev_v2_data_pool(rbd_dev);
	if (header->features & RBD_FEATURE_DATA_POOL) {
		ret = rbd_dev_v2_data_pool(rbd_dev, &header->data_pool_id);
		if (ret)
			goto out_err;
			return ret;
	}

	rbd_init_layout(rbd_dev);
	return 0;

out_err:
	rbd_dev->header.features = 0;
	kfree(rbd_dev->header.object_prefix);
	rbd_dev->header.object_prefix = NULL;
	return ret;
}

/*
@@ -6982,13 +6917,15 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
	if (!depth)
		down_write(&rbd_dev->header_rwsem);

	ret = rbd_dev_header_info(rbd_dev);
	ret = rbd_dev_header_info(rbd_dev, &rbd_dev->header, true);
	if (ret) {
		if (ret == -ENOENT && !need_watch)
			rbd_print_dne(rbd_dev, false);
		goto err_out_probe;
	}

	rbd_init_layout(rbd_dev);

	/*
	 * If this image is the one being mapped, we have pool name and
	 * id, image name and id, and snap name - need to fill snap id.
@@ -7017,7 +6954,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
	}

	if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
		ret = rbd_dev_v2_parent_info(rbd_dev);
		ret = rbd_dev_setup_parent(rbd_dev);
		if (ret)
			goto err_out_probe;
	}
@@ -7043,6 +6980,107 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
	return ret;
}

static void rbd_dev_update_header(struct rbd_device *rbd_dev,
				  struct rbd_image_header *header)
{
	rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
	rbd_assert(rbd_dev->header.object_prefix); /* !first_time */

	if (rbd_dev->header.image_size != header->image_size) {
		rbd_dev->header.image_size = header->image_size;

		if (!rbd_is_snap(rbd_dev)) {
			rbd_dev->mapping.size = header->image_size;
			rbd_dev_update_size(rbd_dev);
		}
	}

	ceph_put_snap_context(rbd_dev->header.snapc);
	rbd_dev->header.snapc = header->snapc;
	header->snapc = NULL;

	if (rbd_dev->image_format == 1) {
		kfree(rbd_dev->header.snap_names);
		rbd_dev->header.snap_names = header->snap_names;
		header->snap_names = NULL;

		kfree(rbd_dev->header.snap_sizes);
		rbd_dev->header.snap_sizes = header->snap_sizes;
		header->snap_sizes = NULL;
	}
}

static void rbd_dev_update_parent(struct rbd_device *rbd_dev,
				  struct parent_image_info *pii)
{
	if (pii->pool_id == CEPH_NOPOOL || !pii->has_overlap) {
		/*
		 * Either the parent never existed, or we have
		 * record of it but the image got flattened so it no
		 * longer has a parent.  When the parent of a
		 * layered image disappears we immediately set the
		 * overlap to 0.  The effect of this is that all new
		 * requests will be treated as if the image had no
		 * parent.
		 *
		 * If !pii.has_overlap, the parent image spec is not
		 * applicable.  It's there to avoid duplication in each
		 * snapshot record.
		 */
		if (rbd_dev->parent_overlap) {
			rbd_dev->parent_overlap = 0;
			rbd_dev_parent_put(rbd_dev);
			pr_info("%s: clone has been flattened\n",
				rbd_dev->disk->disk_name);
		}
	} else {
		rbd_assert(rbd_dev->parent_spec);

		/*
		 * Update the parent overlap.  If it became zero, issue
		 * a warning as we will proceed as if there is no parent.
		 */
		if (!pii->overlap && rbd_dev->parent_overlap)
			rbd_warn(rbd_dev,
				 "clone has become standalone (overlap 0)");
		rbd_dev->parent_overlap = pii->overlap;
	}
}

static int rbd_dev_refresh(struct rbd_device *rbd_dev)
{
	struct rbd_image_header	header = { 0 };
	struct parent_image_info pii = { 0 };
	int ret;

	dout("%s rbd_dev %p\n", __func__, rbd_dev);

	ret = rbd_dev_header_info(rbd_dev, &header, false);
	if (ret)
		goto out;

	/*
	 * If there is a parent, see if it has disappeared due to the
	 * mapped image getting flattened.
	 */
	if (rbd_dev->parent) {
		ret = rbd_dev_v2_parent_info(rbd_dev, &pii);
		if (ret)
			goto out;
	}

	down_write(&rbd_dev->header_rwsem);
	rbd_dev_update_header(rbd_dev, &header);
	if (rbd_dev->parent)
		rbd_dev_update_parent(rbd_dev, &pii);
	up_write(&rbd_dev->header_rwsem);

out:
	rbd_parent_info_cleanup(&pii);
	rbd_image_header_cleanup(&header);
	return ret;
}

static ssize_t do_rbd_add(const char *buf, size_t count)
{
	struct rbd_device *rbd_dev = NULL;
+2 −4
Original line number Diff line number Diff line
@@ -249,11 +249,9 @@ static struct inode *parse_longname(const struct inode *parent,
	if (!dir) {
		/* This can happen if we're not mounting cephfs on the root */
		dir = ceph_get_inode(parent->i_sb, vino, NULL);
		if (!dir)
			dir = ERR_PTR(-ENOENT);
	}
		if (IS_ERR(dir))
			dout("Can't find inode %s (%s)\n", inode_number, name);
	}

out:
	kfree(inode_number);
+11 −13
Original line number Diff line number Diff line
@@ -467,7 +467,6 @@ union ceph_mds_request_args {
} __attribute__ ((packed));

union ceph_mds_request_args_ext {
	union {
	union ceph_mds_request_args old;
	struct {
		__le32 mode;
@@ -480,7 +479,6 @@ union ceph_mds_request_args_ext {
		struct ceph_timespec btime;
	} __attribute__ ((packed)) setattr_ext;
};
};

#define CEPH_MDS_FLAG_REPLAY		1 /* this is a replayed op */
#define CEPH_MDS_FLAG_WANT_DENTRY	2 /* want dentry in reply */