Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e884479 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull Ceph fixes from Sage Weil:
 "There are two critical regression fixes for CephFS from Zheng, and an
  RBD completion fix for layered images from Ilya"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
  rbd: fix copyup completion race
  ceph: always re-send cap flushes when MDS recovers
  ceph: fix ceph_encode_locks_to_buffer()
parents 665aadc1 2761713d
Loading
Loading
Loading
Loading
+17 −5
Original line number Original line Diff line number Diff line
@@ -523,6 +523,7 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...)
#  define rbd_assert(expr)	((void) 0)
#  define rbd_assert(expr)	((void) 0)
#endif /* !RBD_DEBUG */
#endif /* !RBD_DEBUG */


static void rbd_osd_copyup_callback(struct rbd_obj_request *obj_request);
static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request);
static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request);
static void rbd_img_parent_read(struct rbd_obj_request *obj_request);
static void rbd_img_parent_read(struct rbd_obj_request *obj_request);
static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
@@ -1818,6 +1819,16 @@ static void rbd_osd_stat_callback(struct rbd_obj_request *obj_request)
	obj_request_done_set(obj_request);
	obj_request_done_set(obj_request);
}
}


static void rbd_osd_call_callback(struct rbd_obj_request *obj_request)
{
	dout("%s: obj %p\n", __func__, obj_request);

	if (obj_request_img_data_test(obj_request))
		rbd_osd_copyup_callback(obj_request);
	else
		obj_request_done_set(obj_request);
}

static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
				struct ceph_msg *msg)
				struct ceph_msg *msg)
{
{
@@ -1866,6 +1877,8 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
		rbd_osd_discard_callback(obj_request);
		rbd_osd_discard_callback(obj_request);
		break;
		break;
	case CEPH_OSD_OP_CALL:
	case CEPH_OSD_OP_CALL:
		rbd_osd_call_callback(obj_request);
		break;
	case CEPH_OSD_OP_NOTIFY_ACK:
	case CEPH_OSD_OP_NOTIFY_ACK:
	case CEPH_OSD_OP_WATCH:
	case CEPH_OSD_OP_WATCH:
		rbd_osd_trivial_callback(obj_request);
		rbd_osd_trivial_callback(obj_request);
@@ -2530,13 +2543,15 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
}
}


static void
static void
rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request)
rbd_osd_copyup_callback(struct rbd_obj_request *obj_request)
{
{
	struct rbd_img_request *img_request;
	struct rbd_img_request *img_request;
	struct rbd_device *rbd_dev;
	struct rbd_device *rbd_dev;
	struct page **pages;
	struct page **pages;
	u32 page_count;
	u32 page_count;


	dout("%s: obj %p\n", __func__, obj_request);

	rbd_assert(obj_request->type == OBJ_REQUEST_BIO ||
	rbd_assert(obj_request->type == OBJ_REQUEST_BIO ||
		obj_request->type == OBJ_REQUEST_NODATA);
		obj_request->type == OBJ_REQUEST_NODATA);
	rbd_assert(obj_request_img_data_test(obj_request));
	rbd_assert(obj_request_img_data_test(obj_request));
@@ -2563,9 +2578,7 @@ rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request)
	if (!obj_request->result)
	if (!obj_request->result)
		obj_request->xferred = obj_request->length;
		obj_request->xferred = obj_request->length;


	/* Finish up with the normal image object callback */
	obj_request_done_set(obj_request);

	rbd_img_obj_callback(obj_request);
}
}


static void
static void
@@ -2650,7 +2663,6 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)


	/* All set, send it off. */
	/* All set, send it off. */


	orig_request->callback = rbd_img_obj_copyup_callback;
	osdc = &rbd_dev->rbd_client->client->osdc;
	osdc = &rbd_dev->rbd_client->client->osdc;
	img_result = rbd_obj_request_submit(osdc, orig_request);
	img_result = rbd_obj_request_submit(osdc, orig_request);
	if (!img_result)
	if (!img_result)
+5 −17
Original line number Original line Diff line number Diff line
@@ -1506,7 +1506,6 @@ static int __mark_caps_flushing(struct inode *inode,


	swap(cf, ci->i_prealloc_cap_flush);
	swap(cf, ci->i_prealloc_cap_flush);
	cf->caps = flushing;
	cf->caps = flushing;
	cf->kick = false;


	spin_lock(&mdsc->cap_dirty_lock);
	spin_lock(&mdsc->cap_dirty_lock);
	list_del_init(&ci->i_dirty_item);
	list_del_init(&ci->i_dirty_item);
@@ -2123,8 +2122,7 @@ static void kick_flushing_capsnaps(struct ceph_mds_client *mdsc,


static int __kick_flushing_caps(struct ceph_mds_client *mdsc,
static int __kick_flushing_caps(struct ceph_mds_client *mdsc,
				struct ceph_mds_session *session,
				struct ceph_mds_session *session,
				struct ceph_inode_info *ci,
				struct ceph_inode_info *ci)
				bool kick_all)
{
{
	struct inode *inode = &ci->vfs_inode;
	struct inode *inode = &ci->vfs_inode;
	struct ceph_cap *cap;
	struct ceph_cap *cap;
@@ -2150,9 +2148,7 @@ static int __kick_flushing_caps(struct ceph_mds_client *mdsc,


		for (n = rb_first(&ci->i_cap_flush_tree); n; n = rb_next(n)) {
		for (n = rb_first(&ci->i_cap_flush_tree); n; n = rb_next(n)) {
			cf = rb_entry(n, struct ceph_cap_flush, i_node);
			cf = rb_entry(n, struct ceph_cap_flush, i_node);
			if (cf->tid < first_tid)
			if (cf->tid >= first_tid)
				continue;
			if (kick_all || cf->kick)
				break;
				break;
		}
		}
		if (!n) {
		if (!n) {
@@ -2161,7 +2157,6 @@ static int __kick_flushing_caps(struct ceph_mds_client *mdsc,
		}
		}


		cf = rb_entry(n, struct ceph_cap_flush, i_node);
		cf = rb_entry(n, struct ceph_cap_flush, i_node);
		cf->kick = false;


		first_tid = cf->tid + 1;
		first_tid = cf->tid + 1;


@@ -2181,8 +2176,6 @@ void ceph_early_kick_flushing_caps(struct ceph_mds_client *mdsc,
{
{
	struct ceph_inode_info *ci;
	struct ceph_inode_info *ci;
	struct ceph_cap *cap;
	struct ceph_cap *cap;
	struct ceph_cap_flush *cf;
	struct rb_node *n;


	dout("early_kick_flushing_caps mds%d\n", session->s_mds);
	dout("early_kick_flushing_caps mds%d\n", session->s_mds);
	list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) {
	list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) {
@@ -2205,16 +2198,11 @@ void ceph_early_kick_flushing_caps(struct ceph_mds_client *mdsc,
		if ((cap->issued & ci->i_flushing_caps) !=
		if ((cap->issued & ci->i_flushing_caps) !=
		    ci->i_flushing_caps) {
		    ci->i_flushing_caps) {
			spin_unlock(&ci->i_ceph_lock);
			spin_unlock(&ci->i_ceph_lock);
			if (!__kick_flushing_caps(mdsc, session, ci, true))
			if (!__kick_flushing_caps(mdsc, session, ci))
				continue;
				continue;
			spin_lock(&ci->i_ceph_lock);
			spin_lock(&ci->i_ceph_lock);
		}
		}


		for (n = rb_first(&ci->i_cap_flush_tree); n; n = rb_next(n)) {
			cf = rb_entry(n, struct ceph_cap_flush, i_node);
			cf->kick = true;
		}

		spin_unlock(&ci->i_ceph_lock);
		spin_unlock(&ci->i_ceph_lock);
	}
	}
}
}
@@ -2228,7 +2216,7 @@ void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc,


	dout("kick_flushing_caps mds%d\n", session->s_mds);
	dout("kick_flushing_caps mds%d\n", session->s_mds);
	list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) {
	list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) {
		int delayed = __kick_flushing_caps(mdsc, session, ci, false);
		int delayed = __kick_flushing_caps(mdsc, session, ci);
		if (delayed) {
		if (delayed) {
			spin_lock(&ci->i_ceph_lock);
			spin_lock(&ci->i_ceph_lock);
			__cap_delay_requeue(mdsc, ci);
			__cap_delay_requeue(mdsc, ci);
@@ -2261,7 +2249,7 @@ static void kick_flushing_inode_caps(struct ceph_mds_client *mdsc,


		spin_unlock(&ci->i_ceph_lock);
		spin_unlock(&ci->i_ceph_lock);


		delayed = __kick_flushing_caps(mdsc, session, ci, true);
		delayed = __kick_flushing_caps(mdsc, session, ci);
		if (delayed) {
		if (delayed) {
			spin_lock(&ci->i_ceph_lock);
			spin_lock(&ci->i_ceph_lock);
			__cap_delay_requeue(mdsc, ci);
			__cap_delay_requeue(mdsc, ci);
+1 −1
Original line number Original line Diff line number Diff line
@@ -287,7 +287,7 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
		return 0;
		return 0;


	spin_lock(&ctx->flc_lock);
	spin_lock(&ctx->flc_lock);
	list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
	list_for_each_entry(lock, &ctx->flc_posix, fl_list) {
		++seen_fcntl;
		++seen_fcntl;
		if (seen_fcntl > num_fcntl_locks) {
		if (seen_fcntl > num_fcntl_locks) {
			err = -ENOSPC;
			err = -ENOSPC;
+0 −1
Original line number Original line Diff line number Diff line
@@ -189,7 +189,6 @@ static inline void ceph_put_cap_snap(struct ceph_cap_snap *capsnap)
struct ceph_cap_flush {
struct ceph_cap_flush {
	u64 tid;
	u64 tid;
	int caps;
	int caps;
	bool kick;
	struct rb_node g_node; // global
	struct rb_node g_node; // global
	union {
	union {
		struct rb_node i_node; // inode
		struct rb_node i_node; // inode